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.