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

Igor Stasenko siguctua at gmail.com
Fri Jan 27 13:55:23 UTC 2012


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.


-- 
Best regards,
Igor Stasenko.


More information about the Vm-dev mailing list