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

Eliot Miranda eliot.miranda at gmail.com
Wed Jan 25 21:44:28 UTC 2012


On Wed, Jan 25, 2012 at 1:32 PM, stephane ducasse <
stephane.ducasse at gmail.com> wrote:

>
> for the record mariano, VW implementation of method wrapper had a template
> of method one for each number of possible args
> and they reserved space in the compiled method to be able to binding the
> class name (from memory) so installing one was copy of the right template +
> homeClass + selector (not sure anymore) so it was quite fast and simple to
> read.
>

and the same thing is in my port to 4.2, MethodWrappers4.2 on squeaksource.
 See MwMethodWrapper's class instance variable protoMethods.


>
> Stef
>
> On Jan 25, 2012, at 7:36 PM, Mariano Martinez Peck wrote:
>
> >
> >
> > Ok. I will try to give it a try to this approach as well.
> > But what happened with the version I attached in the previous email that
> uses a template method and just change the arguments number?
> >
> > That would be fine.  I didn't look.
> >
> >
> > Since I am quite newbie here and the change can be quite important, I
> would really appreciate if someone can take a look to the .cs so that I
> feel confident to commit it :)
> >
> >
> > but I get lost to get this working...the previous solution seems easier.
> >
> > Do you want to build Trabants or BMWs?
> >
> > I didn't understand. Which solution which be each car?
> >
> > Compiling from source each time = trabant.  Synthesizing directly = vw.
>   Using a template method = bmw.
> >
> > (vw = VisualWorks ;) )
> >
> >
> > :):):):)
> >
> > Nice because it means that we found a fast solution yet quite
> understandable :)
> >
> >
> >
> > Documentation helps.
> >
> >
> > I didn't understand either. If you refer to the fact I didn't put
> comments in the .cs I attached, I explicitly said in my previous email "If
> you agree, I can put a nice comment and commit.". It already took me the
> whole morning (yes, I am completly noob here) to do the version of changing
> the argument count, so I was waiting the confirmation in the solution
> before documenting it and make it better.
> >
> > I mean in general if one builds good quality code that is "clever" then
> that code needs to be documented.  Sometimes simple doesn't cut it (look at
> the complexity involved in making a VM fast).  So if simple doesn't cut it
> one must document.
> >
> > Agree. Once someone gives me the OK for my .cs, I will add comments and
> commit.
> >
> > Thanks Eliot.
> >
> >
> >
> >
> >
> > Thanks!
> >
> >
> >
> >
> > On Tue, Jan 24, 2012 at 11:01 PM, Mariano Martinez Peck <
> 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> 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
> >
> >
> >
> >
> >
> > --
> > Mariano
> > http://marianopeck.wordpress.com
> >
> >
> >
> >
> >
> > --
> > best,
> > Eliot
> >
> >
> >
> >
> >
> > --
> > Mariano
> > http://marianopeck.wordpress.com
> >
> >
> >
> >
> >
> > --
> > best,
> > Eliot
> >
> >
> >
> >
> >
> > --
> > Mariano
> > http://marianopeck.wordpress.com
> >
>
>


-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20120125/226a033d/attachment-0001.htm


More information about the Vm-dev mailing list