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

Mariano Martinez Peck marianopeck at gmail.com
Wed Jan 25 18:36:26 UTC 2012


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20120125/59fab9ba/attachment-0001.htm


More information about the Vm-dev mailing list