<br><br><div class="gmail_quote">On Mon, Jan 23, 2012 at 8:52 AM, Mariano Martinez Peck <span dir="ltr"><<a href="mailto:marianopeck@gmail.com">marianopeck@gmail.com</a>></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><primitive: 218 error: ec></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>["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."</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>"Assume a nil error code implies the primitive is not implemented and fall back on the old code."</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>"Hack. Attempt to execute the named primitive from the given compiled method"</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>arguments size > 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>"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."</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>"If successful, push result and return resuming context, else ^ { PrimitiveFailToken. errorCode }"</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:'Code simulation error'</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>"ContextPart>>blockCopy:; simulated to get startpc right"</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]) "BlockContext>>value[:value:...]"</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]) "BlockContext>>valueWithArguments:"</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 "afr 9/11/1998 19:50" "Object>>perform:[with:...]"</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 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:"</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 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:"</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>"Mutex>>primitiveEnterCriticalSection</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span> Mutex>>primitiveTestAndSetOwnershipOfCriticalSection"</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> "active == effective"</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: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:"</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>"Closure primitives"</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>"ContextPart>>closureCopy:copiedValues:; simulated to get startpc right"</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> "BlockClosure>>value[:value:...]"</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]"</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>"BlockClosure>>valueWithArguments:"</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: "tryPrimitive:withArgs:; avoid recursing in the VM"</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 "FFI method"</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 "named primitives"</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>