On Jan 23, 2012, at 10:22 PM, Eliot Miranda wrote:

> 
> 
> On Mon, Jan 23, 2012 at 12:57 PM, Stéphane Ducasse 
> <[email protected]> wrote:
> Hi elliot
> 
> What are these tryNamedPrimitive?
> 
> The methods in ProtoObject implement invoking primitives in the context of 
> the debugger.  The debugger used to use methods in Object, tryPrimitive0, 
> tryPrimitive1: tryPrimitive2:with: et al, to invoke normal primitives.  The 
> debugger would choose the tryPrimitive1: method with the right number of 
> arguments, modify its header to change its primitive number of the desired 
> primitive, and then call it to invoke the primitive.  This is not reentrant.  
> If one is trying to debug the debugger then the tryPrimitive: method can be 
> modified by the debugger that is debugging the debugger that is in the 
> process of editing the tryPrimitive: method.  To fix this, and eliminate the 
> tryPrimitiveN methods, someone introduced the tryPrimitive:withArgs: 
> primitive.  (Note that in VisualWorks we solved this by creating a method on 
> the fly to invoke a given primitive and evaluating it using a primitive that 
> did the same thing as withArgs:executeMethod:).

Thanks for the explanation.
I have another question 
        is this for invoking primitive directly? Or my question is why we 
cannot simply call the method that is flagged as a primitive?
I started to read the interpreter of camillo and I did not arrive yet at 
primitives :)
 
> Analogously, one needs a way of invoking named primitives in the debugger, 
> and using tryNamedPrimitive[:with:with:...] et al has exactly the same 
> weaknesses as tryPrimitiveN above.  So introducing a primitive to run named 
> primitives is in keeping with tryPrimitive:withArgs:.  Using the VisualWorks 
> approach is feasible but violates Occam's razor.

You lost me. You mean that you want to avoid to have a primitive to execute 
primitives?
> 
> Why do we need them in ProtoObject?
> 
> Once tryNamedPrimitiveIn:for:withArgs: is implemented in all relevant virtual 
> machines we don't need them.  You'll notice that there is no trace of the 
> tryPrimitiveN methods anymore, even though they're in Smalltalk-80.
>  
> Because I'm not sure that adding primitive to VM is always a good solution.
> 
> Agreed.  But it is in keeping with the primitive for invoking numbered 
> primitives,  tryPrimitive:withArgs:.

Yes I see. 
Thanks for the explanation. 
> 
> 
> HTH
> Eliot
> 
> 
> 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
> >
> 
> 
> 
> 
> 
> -- 
> best,
> Eliot
> 


Reply via email to