Hi elliot What are these tryNamedPrimitive? Why do we need them in ProtoObject? Because I'm not sure that adding primitive to VM is always a good solution.
Stef > On Mon, Jan 23, 2012 at 8:52 AM, Mariano Martinez Peck > <[email protected]> wrote: > 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. > So...I wonder, do you think there could be another way so that to avoid > having all those methods in ProtoObject ? > > Yes there is. I implemented primitive 218 in Cog, > primitiveDoNamedPrimitiveWithArgs, which is accessed via > > > tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: > arguments > | selector theMethod spec receiverClass | > <primitive: 218 error: ec> > ec ifNotNil: > ["If ec is an integer other than -1 there was a > problem with primitive 218, > not with the external primitive itself. -1 > indicates a generic failure (where > ec should be nil) but ec = nil means > primitive 218 is not implemented. So > interpret -1 to mean the external primitive > failed with a nil error code." > ec isInteger ifTrue: > [ec = -1 > ifTrue: [ec := nil] > ifFalse: [self > primitiveFailed]]. > ^{PrimitiveFailToken. ec}]. > "Assume a nil error code implies the primitive is not > implemented and fall back on the old code." > "Hack. Attempt to execute the named primitive from the > given compiled method" > arguments size > 8 ifTrue: > [^{PrimitiveFailToken. nil}]. > selector := #( > tryNamedPrimitive > tryNamedPrimitive: > tryNamedPrimitive:with: > tryNamedPrimitive:with:with: > tryNamedPrimitive:with:with:with: > tryNamedPrimitive:with:with:with:with: > tryNamedPrimitive:with:with:with:with:with: > tryNamedPrimitive:with:with:with:with:with:with: > > tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1. > receiverClass := self objectClass: aReceiver. > theMethod := receiverClass lookupSelector: selector. > theMethod == nil ifTrue: > [^{PrimitiveFailToken. nil}]. > spec := theMethod literalAt: 1. > spec replaceFrom: 1 to: spec size with: > (aCompiledMethod literalAt: 1) startingAt: 1. > Smalltalk unbindExternalPrimitives. > ^self object: aReceiver perform: selector > withArguments: arguments inClass: receiverClass > > (cf tryPrimitive: withArgs:) and used in > > > doPrimitive: primitiveIndex method: meth receiver: receiver > args: arguments > "Simulate a primitive method whose index is > primitiveIndex. The simulated receiver > and arguments are given as arguments to this message. > Any primitive which provokes > execution needs to be intercepted and simulated to > avoid execution running away." > > | value | > "If successful, push result and return resuming > context, else ^ { PrimitiveFailToken. errorCode }" > (primitiveIndex = 19) ifTrue: > [ToolSet > debugContext: self > label:'Code simulation error' > contents: nil]. > > "ContextPart>>blockCopy:; simulated to get startpc > right" > (primitiveIndex = 80 and: [(self objectClass: receiver) > includesBehavior: ContextPart]) > ifTrue: [^self push: ((BlockContext > newForMethod: receiver method) > home: receiver > home > startpc: pc + 2 > nargs: > (arguments at: 1))]. > (primitiveIndex = 81 and: [(self objectClass: receiver) > == BlockContext]) "BlockContext>>value[:value:...]" > ifTrue: [^receiver pushArgs: arguments from: > self]. > (primitiveIndex = 82 and: [(self objectClass: receiver) > == BlockContext]) "BlockContext>>valueWithArguments:" > ifTrue: [^receiver pushArgs: arguments first > from: self]. > primitiveIndex = 83 "afr 9/11/1998 19:50" > "Object>>perform:[with:...]" > ifTrue: [^self send: arguments first > to: receiver > with: arguments > allButFirst > super: false]. > primitiveIndex = 84 "afr 9/11/1998 19:50 & eem > 8/18/2009 17:04" "Object>>perform:withArguments:" > ifTrue: [^self send: arguments first > to: receiver > with: (arguments at: 2) > startClass: nil]. > primitiveIndex = 100 "eem 8/18/2009 16:57" > "Object>>perform:withArguments:inSuperclass:" > ifTrue: [^self send: arguments first > to: receiver > with: (arguments at: 2) > startClass: (arguments > at: 3)]. > > "Mutex>>primitiveEnterCriticalSection > Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" > (primitiveIndex = 186 or: [primitiveIndex = 187]) > ifTrue: > [| active effective | > active := Processor activeProcess. > effective := active effectiveProcess. > "active == effective" > value := primitiveIndex = 186 > ifTrue: [receiver > primitiveEnterCriticalSectionOnBehalfOf: effective] > ifFalse: [receiver > primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. > ^(value isArray > and: [value size = 2 > and: [value first == PrimitiveFailToken]]) > ifTrue: [value] > ifFalse: [self push: value]]. > > primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 > Object>>withArgs:executeMethod:" > [^MethodContext > sender: self > receiver: receiver > method: (arguments at: 2) > arguments: (arguments at: 1)]. > > "Closure primitives" > (primitiveIndex = 200 and: [self == receiver]) ifTrue: > "ContextPart>>closureCopy:copiedValues:; > simulated to get startpc right" > [^self push: (BlockClosure > outerContext: > receiver > startpc: pc + 2 > numArgs: > arguments first > copiedValues: > arguments last)]. > ((primitiveIndex between: 201 and: 205) > "BlockClosure>>value[:value:...]" > or: [primitiveIndex between: 221 and: 222]) ifTrue: > "BlockClosure>>valueNoContextSwitch[:]" > [^receiver simulateValueWithArguments: > arguments caller: self]. > primitiveIndex = 206 ifTrue: > "BlockClosure>>valueWithArguments:" > [^receiver simulateValueWithArguments: > arguments first caller: self]. > > primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; > avoid recursing in the VM" > [(arguments size = 2 > and: [arguments first isInteger > and: [arguments last class == Array]]) ifFalse: > [^ContextPart primitiveFailTokenFor: > nil]. > ^self doPrimitive: arguments first method: > meth receiver: receiver args: arguments last]. > > value := primitiveIndex = 120 "FFI method" > ifTrue: [(meth literalAt: 1) > tryInvokeWithArguments: arguments] > ifFalse: > [primitiveIndex = 117 > "named primitives" > ifTrue: [self > tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] > ifFalse: > > [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. > ^(value isArray > and: [value size = 2 > and: [value first == PrimitiveFailToken]]) > ifTrue: [value] > ifFalse: [self push: value] > > (find attached). But these need implementing in the standard VM before they > can be used in Pharo, Squeak, etc. > > > Thanks > > -- > Mariano > http://marianopeck.wordpress.com > > > > > -- > best, > Eliot >
