[Vm-dev] When Cog should deoptimize CM and when its not?

Eliot Miranda eliot.miranda at gmail.com
Mon Mar 11 22:23:11 UTC 2013


On Fri, Mar 8, 2013 at 2:34 PM, Igor Stasenko <siguctua at gmail.com> wrote:
>
> Hi, Eliot & all
>
> I was looking at #become: code
> and did not found the place where it deoptimizing compiled methods to
> throw away the jited version of it (if it has one),
> before even trying to do anything with it.
>
> i know it pricey, because it should:
>
>  - remove CogMethod from JIT zone
>  - walk the stack and look for all activations of it, and replace
> native code instruction pointer with bytecode instruction pointer
>  - fix the compiled method's header
> (another alternative, if method has activations, i would fail
> primitive actually, because this is too hard to do things right and
> very dangerous
> to play with, as well as it makes little sense )
>
> IMO, if we add that, then we could minimize the impact of JIT
> complexity on #become: and make things work
> in same way as in stack vm (which is stable ;).
> And since become scans part/whole heap.. deoptimizing the CM would not
> add too much on top :)
>
> I don't know if it is there, maybe it is.. then sorry for first part..
> but not the second one:
>
>
> objectAt: index put: value
>         "Primitive. Store the value argument into a literal in the receiver. An
>         index of 2 corresponds to the first literal. Fails if the index is less than 2
>         or greater than the number of literals. Answer the value as the result.
>         Normally only the compiler sends this message, because only the
>         compiler stores values in CompiledMethods. Essential. See Object
>         documentation whatIsAPrimitive."
>
>         <primitive: 69>
>         self primitiveFailed
>
> i was playing with metaprogramming , using
> #literalAt:put:
> to store/change some value directly in method's literal (yeah.. you
> can kill the messenger and stop reading further ;) .
>
> And i found that the change is not immediately visible..
>
> My idea is plain simple:
>  - you have a template method, like:
>
>  foo
>    ^ 'ssssss'
>
> and then i simply doing things like:
>
>  copy := foo copy literalAt:1 put: 'bar'.
>  methodDict at: #bar put: copy
>
> and when i wanna change the #bar value next time, i don't creating new
> method again, but just modifying
> its literal.
> Things worked perfectly on old interpreted VMs and i used this
> trickery to implement prototypes (where object's properties
> are held by correspoding CM )
>
> But with Cog, because of its aggressive caching, it no longer working:
>
> at: aName put: value
>         | method |
>
>         (getter methodDict includesKey: aName) ifTrue: [
>
>                 method := getter methodDict at: aName.
>                 method literalAt: 1 put: value.
>                 method flushCache.
>
>         ] ifFalse: [
>
>                 method := getter addReadAccessorFor: aName value: value.
>                 setter addWriteAccessorFor: aName readAccessor: method.
>         ].
>         aName flushCache.
>
>         ^ value
>
> here neither "method flushCache. " nor "aName flushCache." helps with it..
> my test still fails.
> But of course, when i click to debug , it magically passes when i
> evaluating very same expression in debugger :)
>
> Things working only when i always replacing things with new method(s)
> (as i doing under under ifFalse: clause).
>
> I strongly suggest that <primitive: 69> should always deoptimize CM
> (throw away Cogged method , even if it has high price to pay)
> as well as #flushCache (<primitive: 116>) should also do the same, because
>   - JITed code is a cache
>   - we should have a means to throw it away when asked so
>
> The #voidCogVMState flushes all machine code.. but is it possible to
> make more could we have one which flushing only particular one?

It's already there.  See primitive 215, primitiveVoidVMStateForMethod,
CompiledMethod>voidCogVMState.  Find attached.



>
> (...in alternative universe, i'd rather look for a way how to
> "deoptimize Jited method in smart way, so when you deoptimizing the
> CM,
> it won't require scanning stacks to patch instruction pointers, and
> instead mark/make jited code obsolete by:
>
> - patching the machine code at entry point to immediately switch back
> to interpreter mode of corresponding method (to prevent spawning new
> activations with native code)
>  - patching the machine code at every possible return address (call
> sites) to immediately switch to interpreter (to gracefully handle
> existing activations so, there is no need to fix instruction pointers)
>  - keep that obsolete CogMethod till next GC.
>  ;)
>
>
>
> --
> Best regards,
> Igor Stasenko.



-- 
best,
Eliot
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CompiledMethod-voidCogVMState.st
Type: application/octet-stream
Size: 726 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20130311/3cb78628/CompiledMethod-voidCogVMState.obj


More information about the Vm-dev mailing list