It is fixed in latest vm (which you can get from the zeroconf script
http://get.pharo.org/vmLatest) :).

Guille


On Fri, May 31, 2013 at 1:25 PM, Igor Stasenko <[email protected]> wrote:

> On 31 May 2013 09:20, Guillermo Polito <[email protected]> wrote:
> > Ahh, that's why the code in CoInterpreter I was looking didn't match the
> C
> > code :D. Was looking at the wrong place, hehe.
> >
> > Igor, why do you say that this method should be reached only with vanilla
> > compiled methods? From the comment I understand
> >
> >       "For interpreter performance and to ease the objectAsMethod
> > implementation eagerly
> >          evaluate the primtiive, i.e. if the method is cogged and has a
> > primitive /do not/ evaluate
> >          the machine code primitive, just evaluate
> primitiveFunctionPointer
> > directly."
> >
>
> Yes, my bad..
> It is hard to see that in code: the logic to handle objects-as-method.
> So, yes, please fix executNewMethod and internalExecuteNewMethod with
> this additional check.
>
> > And in #addNewMethodToCache: there is as a first statement:
> >
> > [...]
> > (objectMemory isOopCompiledMethod: newMethod)
> > ifTrue:
> > [primitiveIndex := self primitiveIndexOf: newMethod.
> > primitiveFunctionPointer := self functionPointerFor: primitiveIndex
> inClass:
> > class]
> > ifFalse:
> > [primitiveFunctionPointer := #primitiveInvokeObjectAsMethod].
> > [...]
> >
> > So I'd say that both objects as methods and primitives are kind of
> handled
> > in the same way after?
> >
> >
> >
> > On Fri, May 31, 2013 at 2:27 AM, Igor Stasenko <[email protected]>
> wrote:
> >>
> >> On 30 May 2013 20:06, Guillermo Polito <[email protected]>
> wrote:
> >> > Ok, I was playing with flushing caches and stuff... Its still a bit
> >> > obsure
> >> > to me why the example in the workspace works and the code coverage
> >> > doesnot.
> >> >
> >> > However, I managed to hack the VM to make it work :).
> >> >
> >> > It looks like the VM is treating the objects as methods, as cog
> methods.
> >> > So
> >> > I added the following validation in the commonSend:
> >> >
> >> > methodHeader2 = longAt((GIV(newMethod) + BaseHeaderSize) +
> (HeaderIndex
> >> > <<
> >> > ShiftForWord));
> >> >
> >> > if (isCogMethodReference(methodHeader2) &&
> >> > isCompiledMethodHeader(methodHeader2)) {
> >> >
> >> > /* begin externalizeIPandSP */
> >> >
> >> > assert((((usqInt)localIP)) != (ceReturnToInterpreterPC()));
> >> >
> >> > GIV(instructionPointer) = oopForPointer(localIP);
> >> >
> >> > GIV(stackPointer) = localSP;
> >> >
> >> > GIV(framePointer) = localFP;
> >> >
> >> > executeCoggedNewMethodmethodHeader(1, methodHeader2);
> >> >
> >> > }
> >> >
> >> >
> >> > And it works :).
> >> >
> >> > I cc Eliot, so maybe he has an idea...
> >> >
> >> I touched this code.
> >>
> >> Original:
> >>
> >> CoInterpreter>>internalExecuteNewMethod
> >>         <inline: true>
> >>         "For interpreter performance and to ease the objectAsMethod
> >> implementation eagerly
> >>          evaluate the primtiive, i.e. if the method is cogged and has a
> >> primitive /do not/ evaluate
> >>          the machine code primitive, just evaluate
> >> primitiveFunctionPointer directly."
> >>         primitiveFunctionPointer ~= 0 ifTrue:
> >>                 [| succeeded |
> >>                  self isPrimitiveFunctionPointerAnIndex ifTrue:
> >>                         [^self internalQuickPrimitiveResponse].
> >>                  "slowPrimitiveResponse may of course context-switch.
>  If
> >> so we must
> >> reenter the
> >>                   new process appropriately, returning only if we've
> found
> >> an
> >> interpreter frame."
> >>                  self externalizeIPandSP.
> >>                  succeeded := self slowPrimitiveResponse.
> >>                  instructionPointer = cogit ceReturnToInterpreterPC
> >> ifTrue:
> >>                         [instructionPointer := self iframeSavedIP:
> >> framePointer].
> >>                  self internalizeIPandSP.
> >>                  succeeded ifTrue:
> >>                         [self return: self popStack toExecutive: true.
> >>                          self browserPluginReturnIfNeeded.
> >>                         ^nil]].
> >>         "if not primitive, or primitive failed, activate the method"
> >>         (self methodHasCogMethod: newMethod)
> >>                 ifTrue: [self iframeSavedIP: localFP put: localIP
> >> asInteger.
> >>                                 instructionPointer := cogit
> >> ceReturnToInterpreterPC.
> >>                                 self externalizeFPandSP.
> >>                                 self activateCoggedNewMethod: true.
> >>                                 self internalizeIPandSP]
> >>                 ifFalse: [self internalActivateNewMethod]
> >>
> >> Now in subclass (NBCoInterpreter)
> >> i made this:
> >>
> >> internalExecuteNewMethod
> >>         <inline: true>
> >>         "For interpreter performance and to ease the objectAsMethod
> >> implementation eagerly
> >>          evaluate the primtiive, i.e. if the method is cogged and has a
> >> primitive /do not/ evaluate
> >>          the machine code primitive, just evaluate
> >> primitiveFunctionPointer directly."
> >>
> >>         | methodHeader |
> >>
> >>         methodHeader := self rawHeaderOf: newMethod.
> >>
> >>         (self isCogMethodReference: methodHeader) ifTrue: [
> >>                 self externalizeIPandSP.
> >>                 self executeCoggedNewMethod: true methodHeader:
> >> methodHeader.
> >>                 "we never reach here"
> >>                 ].
> >>
> >>         primitiveFunctionPointer ~= 0 ifTrue:
> >>                 [| succeeded |
> >>                  self isPrimitiveFunctionPointerAnIndex ifTrue:
> >>                         [^self internalQuickPrimitiveResponse].
> >>                  "slowPrimitiveResponse may of course context-switch.
>  If
> >> so we must
> >> reenter the
> >>                   new process appropriately, returning only if we've
> found
> >> an
> >> interpreter frame."
> >>                  self externalizeIPandSP.
> >>                  succeeded := self slowPrimitiveResponse.
> >>                  instructionPointer = cogit ceReturnToInterpreterPC
> >> ifTrue:
> >>                         [instructionPointer := self iframeSavedIP:
> >> framePointer].
> >>                  self internalizeIPandSP.
> >>                  succeeded ifTrue:
> >>                         [self return: self popStack toExecutive: true.
> >>                          self browserPluginReturnIfNeeded.
> >>                         ^nil]].
> >>         "if not primitive, or primitive failed, activate the method"
> >>         (self methodHasCogMethod: newMethod)
> >>                 ifTrue: [self iframeSavedIP: localFP put: localIP
> >> asInteger.
> >>                                 instructionPointer := cogit
> >> ceReturnToInterpreterPC.
> >>                                 self externalizeFPandSP.
> >>                                 self activateCoggedNewMethod: true.
> >>                                 self internalizeIPandSP]
> >>                 ifFalse: [self internalActivateNewMethod]
> >>
> >> ===
> >> The intent of change was:
> >>  - if method is cog method, execute it (the jited code takes care to
> >> call primitive, if it there)
> >>
> >> The old code logic was:
> >>  - run primitive if it there
> >>  - and only then, if no prim/or prim failed, try to run a jited code
> >> (but entry point is to the first bytecode of method,
> >> not to its start)
> >>
> >> This (old) logic prevents from using primitive 220 properly, because
> >> it is a "meta-primitive" - a marker
> >> that says that given method should:
> >>  - always be jited
> >>  - actual primitive is taken by copying machine code from compiled
> >> method trailer into CogMethod's primitive section.
> >> Therefore executing prim 220 (a C function) ~~ invoking method's
> >> primitive (a machine code generated by image).
> >>
> >> Still i cannot understand why code reaching this point, when a result
> >> of lookup is not a compiled method, but arbitrary object, because
> >> everything even in original code says: VM enters this method only if
> >> it found 100% vanilla guaranteed CompiledMethod, and not something
> >> which pretends to be it.
> >> As i understand , the logic to handle object-as-method is in method
> >> lookup.. but not in internalExecuteNewMethod, because VM can "execute"
> >> the only thing it knows, and it is CompiledMethod.
> >>
> >> Your test says, that Cog does something extra (some magic, which i
> >> failed to grasp) with object-as-method,
> >> like generating special kind of CogMethod which sends #run:as:in:
> message
> >> to it.
> >>
> >> I would like to hear Eliot's comments on this.
> >>
> >>
> >>
> >> --
> >> Best regards,
> >> Igor Stasenko.
> >>
> >
>
>
>
> --
> Best regards,
> Igor Stasenko.
>
>

Reply via email to