<br><br><div class="gmail_quote">On Mon, Jan 23, 2012 at 8:52 AM, Mariano Martinez Peck <span dir="ltr">&lt;<a href="mailto:marianopeck@gmail.com">marianopeck@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi guys. I usually like to take a look to ProtoObject and see what is really needed for the minimal object. But having 30% of the methods being  #tryNamedPrimitive:with: *  is not fun. <br>So...I wonder, do you think there could be another way so that to avoid having all those methods in ProtoObject ?<br>
</blockquote><div><br></div><div>Yes there is.  I implemented primitive 218 in Cog, primitiveDoNamedPrimitiveWithArgs, which is accessed via </div><div><br></div><div><div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>| selector theMethod spec receiverClass |</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>&lt;primitive: 218 error: ec&gt;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>ec ifNotNil:</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>[&quot;If ec is an integer other than -1 there was a problem with primitive 218,</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>  not with the external primitive itself.  -1 indicates a generic failure (where</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>  ec should be nil) but ec = nil means primitive 218 is not implemented.  So</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>  interpret -1 to mean the external primitive failed with a nil error code.&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> ec isInteger ifTrue:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>[ec = -1</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>ifTrue: [ec := nil]</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>ifFalse: [self primitiveFailed]].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>^{PrimitiveFailToken. ec}].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;Assume a nil error code implies the primitive is not implemented and fall back on the old code.&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;Hack. Attempt to execute the named primitive from the given compiled method&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>arguments size &gt; 8 ifTrue:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>[^{PrimitiveFailToken. nil}].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>selector := #(</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive </div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive: </div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive:with: </div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive:with:with: </div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive:with:with:with:</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive:with:with:with:with:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive:with:with:with:with:with:</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive:with:with:with:with:with:with:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>receiverClass := self objectClass: aReceiver.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>theMethod := receiverClass lookupSelector: selector.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>theMethod == nil ifTrue:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>[^{PrimitiveFailToken. nil}].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>spec := theMethod literalAt: 1.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>Smalltalk unbindExternalPrimitives.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass</div>
</div></div><div><br></div><div><span class="Apple-style-span">(cf tryPrimitive:</span> withArgs<span class="Apple-style-span">:) and used in</span></div><div><br></div><div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments </div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;Simulate a primitive method whose index is primitiveIndex.  The simulated receiver</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span> and arguments are given as arguments to this message. Any primitive which provokes</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span> execution needs to be intercepted and simulated to avoid execution running away.&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>| value |</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;If successful, push result and return resuming context, else ^ { PrimitiveFailToken. errorCode }&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>(primitiveIndex = 19) ifTrue:</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>[ToolSet </div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>debugContext: self</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>label:&#39;Code simulation error&#39;</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>contents: nil].</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;ContextPart&gt;&gt;blockCopy:; simulated to get startpc right&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart]) </div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [^self push: ((BlockContext newForMethod: receiver method)</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>home: receiver home</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>startpc: pc + 2</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>nargs: (arguments at: 1))].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) &quot;BlockContext&gt;&gt;value[:value:...]&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [^receiver pushArgs: arguments from: self].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) &quot;BlockContext&gt;&gt;valueWithArguments:&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [^receiver pushArgs: arguments first from: self].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>primitiveIndex = 83 &quot;afr 9/11/1998 19:50&quot; &quot;Object&gt;&gt;perform:[with:...]&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [^self send: arguments first</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>to: receiver</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>with: arguments allButFirst</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>super: false].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>primitiveIndex = 84 &quot;afr 9/11/1998 19:50 &amp; eem 8/18/2009 17:04&quot; &quot;Object&gt;&gt;perform:withArguments:&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [^self send: arguments first</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>to: receiver</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>with: (arguments at: 2)</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>startClass: nil].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>primitiveIndex = 100 &quot;eem 8/18/2009 16:57&quot; &quot;Object&gt;&gt;perform:withArguments:inSuperclass:&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [^self send: arguments first</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>to: receiver</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>with: (arguments at: 2)</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>startClass: (arguments at: 3)].</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;Mutex&gt;&gt;primitiveEnterCriticalSection</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span> Mutex&gt;&gt;primitiveTestAndSetOwnershipOfCriticalSection&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>[| active effective |</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> active := Processor activeProcess.</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> effective := active effectiveProcess.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span> &quot;active == effective&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> value := primitiveIndex = 186</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective]</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective].</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> ^(value isArray</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>    and: [value size = 2</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>    and: [value first == PrimitiveFailToken]])</div><div>
<span class="Apple-tab-span" style="white-space:pre">                                        </span>ifTrue: [value]</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>ifFalse: [self push: value]].</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>primitiveIndex = 188 ifTrue: &quot;eem 5/27/2008 11:10 Object&gt;&gt;withArgs:executeMethod:&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>[^MethodContext</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>sender: self</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>receiver: receiver</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>method: (arguments at: 2)</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>arguments: (arguments at: 1)].</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;Closure primitives&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>(primitiveIndex = 200 and: [self == receiver]) ifTrue:</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>&quot;ContextPart&gt;&gt;closureCopy:copiedValues:; simulated to get startpc right&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>[^self push: (BlockClosure</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>outerContext: receiver</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>startpc: pc + 2</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>numArgs: arguments first</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>copiedValues: arguments last)].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>((primitiveIndex between: 201 and: 205)<span class="Apple-tab-span" style="white-space:pre">                        </span> &quot;BlockClosure&gt;&gt;value[:value:...]&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>or: [primitiveIndex between: 221 and: 222]) ifTrue: &quot;BlockClosure&gt;&gt;valueNoContextSwitch[:]&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>[^receiver simulateValueWithArguments: arguments caller: self].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>primitiveIndex = 206 ifTrue:<span class="Apple-tab-span" style="white-space:pre">                                                </span>&quot;BlockClosure&gt;&gt;valueWithArguments:&quot;</div><div>
<span class="Apple-tab-span" style="white-space:pre">                                </span>[^receiver simulateValueWithArguments: arguments first caller: self].</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>primitiveIndex = 118 ifTrue: &quot;tryPrimitive:withArgs:; avoid recursing in the VM&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>[(arguments size = 2</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> and: [arguments first isInteger</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> and: [arguments last class == Array]]) ifFalse:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>[^ContextPart primitiveFailTokenFor: nil].</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>value := primitiveIndex = 120 &quot;FFI method&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments]</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                </span>ifFalse:</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>[primitiveIndex = 117 &quot;named primitives&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments]</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                                </span>ifFalse:</div><div><span class="Apple-tab-span" style="white-space:pre">                                                                        </span>[receiver tryPrimitive: primitiveIndex withArgs: arguments]].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>^(value isArray</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>    and: [value size = 2</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>    and: [value first == PrimitiveFailToken]])</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [value]</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifFalse: [self push: value]</div></div><div><br></div><div>(find attached).  But these need implementing in the standard VM before they can be used in Pharo, Squeak, etc.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>Thanks<br clear="all"><font color="#888888"><br>-- <br>Mariano<br><a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br><br>
</font></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>