[Vm-dev] Re: [Pharo-project] is there a way to avoid all the #tryNamedPrimitive:with: * in ProtoObject

Andreas Raab andreas.raab at gmx.de
Wed Jan 25 13:21:08 UTC 2012


Hi Eliot -

On 1/25/2012 2:43, Eliot Miranda wrote:
> On Tue, Jan 24, 2012 at 2:02 PM, Mariano Martinez Peck 
> <marianopeck at gmail.com <mailto:marianopeck at gmail.com>> wrote:
>
>
>     sorry...here is the attached.
>
>
> OK. What you've done will work.

I actually quite like it. Getting rid of all those methods in class 
ProtoObject is definitely a good thing. Is there any downside other than 
some possible performance issues? I.e., the code should work everywhere, 
right?

> Some criticism: Since the method is new the flushCache should be 
> unneeded.  I think either copying a template method (e.g. stored in a 
> class variable) and  changing its argument count, or creating a method 
> directly (look at the generate: method) would be much faster.  Speed 
> can be important in the debugger.

More important in my view is the misuse of the term "temporal" in the 
method names. I find it quite confusing to read about "temporal" 
compiled methods :-)

Cheers,
   - Andreas

>
>
>     On Tue, Jan 24, 2012 at 11:01 PM, Mariano Martinez Peck
>     <marianopeck at gmail.com <mailto:marianopeck at gmail.com>> wrote:
>
>
>
>                     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.
>
>
>                 What what about temporally (to be removed in the
>                 future) just when we are using older VMs?
>
>
>             If temporary, then fine.  But its all work :)
>
>
>
>         Well...writing papers can be boring ;)
>         Please, could you take a look to the attached .cs?  I tried to
>         do what I had in mind. Since this part of the system is new
>         for me, I have not sure it is correct, nor how to test it. So
>         far what I did for testing it is to take the 
>         #tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs:
>         arguments
>         and (temporally) remove the <primitive: 218 error: ec> and
>         define 'ec' as a temporal variable. Since it will be nil, the
>         following code will be executed.
>         Then I put a halt in #open: fileName forWrite: writeMode  
>         from StandardFileStream and then I do it:
>         FileDirectory default forceNewFileNamed: 'xxxxx'.
>         Once in the debugger, I went to:
>
>         StandardFileStream retryWithGC:[self primOpen: f writable:
>         writeMode]
>                             until:[:id| id notNil]
>                             forFileNamed: fileName.
>
>         did a "through" in the close, and be sure I could do "into"
>         and "step" for #self primOpen: f writable: writeMode  (which
>         is a named primitive).
>
>         is this ok?
>
>         Thanks Eliot!
>
>
>
>                         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:.
>
>
>                     HTH
>                     Eliot
>
>
>                         Stef
>
>                         > On Mon, Jan 23, 2012 at 8:52 AM, Mariano
>                         Martinez Peck <marianopeck at gmail.com
>                         <mailto:marianopeck at gmail.com>> 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
>
>
>
>
>
>                 -- 
>                 Mariano
>                 http://marianopeck.wordpress.com
>
>
>
>
>
>             -- 
>             best,
>             Eliot
>
>
>
>
>
>         -- 
>         Mariano
>         http://marianopeck.wordpress.com
>
>
>
>
>     -- 
>     Mariano
>     http://marianopeck.wordpress.com
>
>
>
>
>
> -- 
> best,
> Eliot
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20120125/2169248b/attachment-0001.htm


More information about the Vm-dev mailing list