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

Eliot Miranda eliot.miranda at gmail.com
Fri Jan 27 18:40:23 UTC 2012


On Fri, Jan 27, 2012 at 9:56 AM, Eliot Miranda <eliot.miranda at gmail.com>wrote:

>
>
> On Fri, Jan 27, 2012 at 5:55 AM, Igor Stasenko <siguctua at gmail.com> wrote:
>
>>
>> On 26 January 2012 19:25, Eliot Miranda <eliot.miranda at gmail.com> wrote:
>> >
>> >
>> >
>> > On Thu, Jan 26, 2012 at 6:00 AM, Igor Stasenko <siguctua at gmail.com>
>> wrote:
>> >>
>> >>
>> >> On 26 January 2012 14:42, Mariano Martinez Peck <marianopeck at gmail.com>
>> wrote:
>> >> >
>> >> >
>> >> >
>> >> > On Thu, Jan 26, 2012 at 11:38 AM, Igor Stasenko <siguctua at gmail.com>
>> wrote:
>> >> >>
>> >> >>
>> >> >> On 26 January 2012 11:25, stephane ducasse <
>> stephane.ducasse at gmail.com> wrote:
>> >> >> >
>> >> >> >> phew... done reading through overquoting :)
>> >> >> >>
>> >> >> >> +1000 to removing tryXYZprimitive:
>> >> >> >>
>> >> >> >> I was always wondering what those methods for, until i met a
>> need to
>> >> >> >> support debugging when invoking nativeboost-prim methods,
>> >> >> >> because it needs special handing when invoking methods with
>> native
>> >> >> >> code via debugger.
>> >> >> >>
>> >> >> >> Then i understood that this mechanism is necessary.. yet a bit
>> awkward..
>> >> >> >>
>> >> >> >> Funny. Even after implementing the fix, I still do not
>> understand why all these is needed. Can someone explain to a newbie why
>> invoking primitives (whether they are normal primitives, named primitives
>> or NB primitives) from the debugger is different than invoking them
>> normally (as when they are invoked by normal code)
>> >> >> >
>> >> >> > Yes I want to understand too.
>> >> >> >
>> >> >>
>> >> >> Here the hint for you:
>> >> >>  - what should happen when you doing 'step in' on method, which has
>> a primitive?
>> >> >>
>> >> >> Apparently, it should invoke that primitive , otherwise you will
>> have
>> >> >> difference between running and debugging modes,
>> >> >> and will have different results, which makes debugger useless.
>> >> >> So debugger should detect "somehow" if primitive was failed, and
>> then
>> >> >> step in into given method,
>> >> >> or if its not, then step in = step over.
>> >> >>
>> >> >> And these 'tryXYZ ... ' is exactly for solving this dilemma.
>> >> >
>> >> >
>> >> > Thanks Igor. So I wrote what I understood. Problem is that I always
>> write for newbies (like me) so if it is too obvios or too long to put it as
>> comment, let me know.
>> >> > I would appreaciate if someone can validate what I wrote.
>> >> > Today I will create a slice with mentioned solution + comments +
>> removal of all those tryNamedPrimitive*.
>> >> >
>> >> > ----
>> >> >
>> >> > "When using the debugger we want to run a method step by step. But
>> what happens when we do a step into a CompiledMethod which has a primitive?
>> If such a method is executed form outside the Debugger (normal scenario)
>> the VM knows that such CompiledMethod has a primitive declaration and hence
>> executes it. If it fails, then it continues executing all the bytecodes of
>> the method. Otherwise, it just returns.
>> >> >
>> >> > Now, what is the problem with the Debugger? The problem is that if
>> the primitive fail, we don't want that the VM directly executes all the
>> remaining bytecodes of the method. Instead, we would like to go step by
>> step with he Debugger, just as happens with normal methods.
>> >> >
>> >> > To solve the mentioned problem, we use the following trick: We have
>> the original compiled method (the one that has a primitive invocation), the
>> receiver and the arguments. So the idea is to use a template compiled
>> method that ONLY contains the primitive declaration (it doesn't include all
>> the original smalltalk code after the primitive).
>> #tryNamedPrimitiveTemplateMethod answers such a template method which looks
>> like:
>> >> >
>> >> > tryNamedPrimitive
>> >> >     <primitive:'to be set later' module:'to be ser later'>
>> >> >     ^ ContextPart primitiveFailToken'
>> >> >
>> >> >  Since this method does not change its bytecodes for every
>> invocation, we can reuse it for all methods with primitives. There are only
>> 2 things we have to change in the template: the number of arguments and the
>> primitive declaration (to use the correct primitive name and module name).
>> >> >
>> >> > Then what we do is to run that compiled method with the receiver and
>> arguments we have. The result is that we will be invoking almost the same
>> original method but a slightly different version that does not have the
>> smalltalk part after the primitive and that in contrast is sends
>> #primitiveFailToken (which tells the Debugger what to do after). If this
>> method invocation does not fail, then the Debugger continues debugging the
>> sender of the primitive method. In this case, the step in is the same as
>> step over. If the primitive fails, then the debugger continues executing
>> the smalltalk part after the primitive method. In this case, step in is a
>> real step in.  "
>> >> >
>> >> >
>> >> There's another problem with using "tryXYZ" when primitive doing
>> >> something weird with contexts (like block's #value)
>> >> because then debugger cannot intercept switching contexts so easily,
>> >> when primitive doing manipulation with contexts,
>> >> because debugger have no idea where to put his next "break point" to
>> >> do step-by-step evaluation.
>> >>
>> >> I thinking that there should be special primitive which:
>> >>  - takes a context, a receiver, a method and arguments (or just a
>> >> context, if debugger ensures to pass it in prepared state i.e.
>> >> receiver and args already on stack)
>> >>  - invokes method's primitive
>> >>  - answers a nil if primitive failed or a new context object, which
>> >> holds an updated context state after primitive possibly manipulated
>> >> with context(s)
>> >
>> >
>> > No, not needed.  Manipulation of contexts does not require primitives
>> since contexts are first-class, and the effect of these primitives can be
>> simulated in Smalltalk (just as the effect of executing bytecodes can be
>> simulated).  Look at the caller of tryPrimitive:withArgs: and
>> tryNamedPrimitiveIn:for:withArgs:, namely
>> ContextPart>doPrimitive:method:receiver:args:.  It handles all these
>> primitives such as perform:[*], value[:value:*], withArgs:executeMethod:.
>>
>> Looks like you don't read carefully. Exactly because of looking to
>> ContextPart>doPrimitive:method:receiver:args: i proposed another way.
>> And besides it is much simpler.
>> If tomorrow we introduce new primitive which manipulates context, you
>> will need to fix this method,
>> because it duplicating knowledge of what VM does.
>>
>
> I disagree.  ContextPart already duplicates the VM.  The direction you
> propose ends up putting all context functionality in the VM, which makes
> the system harder to understand (the SMalltalk code is more readable),
> harder to experiment with (one can no longer implement experiments in the
> image, for example as I did in implementing the closure compiler), and
> harder to implement (implementing and testing tricky do-lots-of-things
> primitives in the VM is harder than implementing and testing their
> equivalents in the image).  So I think this primitive is a really bad idea.
>  Its going to be much more complex than doPrimitive:method:receiver:args:.
>

And of course experience shows it is much quicker and easier to distribute
Smalltalk improvements than new virtual machines, so pushing important
functionality down into the VM is a retrograde step.  It seems out of
keeping with NativeBoost and ideas such as moving the linking machinery for
named primitives and the FFI up into the image, decomposing them into a
more general set of smaller simpler primitives.


>
>>
>> --
>> Best regards,
>> Igor Stasenko.
>>
>
>
>
> --
> best,
> Eliot
>
>


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


More information about the Vm-dev mailing list