[llvm-dev] llvm.experimental.gc.statepoint genarates wrong Stack Map (or does it?)
Sanjoy Das via llvm-dev
llvm-dev at lists.llvm.org
Tue Nov 17 12:07:10 PST 2015
Vladislav Ivanishin wrote:
> Hmm. Do you think it would be a good change to push upstream given we
> might not be able to do it in all cases (say, always fall back to
> rsp-based if the frame is aligned)?
I'm not sure -- I'd say write up a patch and send it in for review;
and see what people think.
>
>>>> Can I ask what you're using the deopt information for? Do you have a
>>>> language runtime which supports deoptimization? Or are you using it
>>>> for something different? If so, what? I'm curious to know how others
>>>> are using the infrastructure.
>>>
>>> Sure.
>>> I am working on LLV8, which is an attempt to use LLVM MCJIT as a
backend
>>> for Google V8. So yes, we have a language runtime which supports
>>> deoptimization.
>>> Deoptimization support wasn't hard. We use the stackmap intrinsic for
>>> that. (And we've encountered each type of Location except Direct so
>>> far).
>>> Now I am implementing the safepoint functionality which is why I
use the
>>> gc.statepoint intrinsic. The two utility passes have been extremely
>>> helpful. The use-cases they support are much more general than my needs
>>> though. So I use a modified version of RewriteStatepointsForGC, which
>>> only appends the pointer values live across the statepoint to <deopt
>>> args>.
>>
>> If I understand you correctly, that will work only if your GC isn't a
>> relocating GC. Is that the case?
>
> V8's GC is a relocating GC. When it moves an object which is live at a
> safe point it knows where the pointer is located (typically it's a stack
> slot) from info stored in the associated safepoint table so it can
> change it right there. As far as I can see, we are getting the
> relocations right.
I don't know your system well enough to say anything definitive, but
the deopt state only gives you spill semantics, not reload semantics.
So it is legal to lower
%v = gc.statepoint(@callee | %gcptr) ;; %gcptr is in the deopt section
load_from(%gcptr)
as
;; %gcptr is in %r12
[%rsp + 40] = %r12
call @callee [[ stackmaps contains [%rsp + 40] ]]
load_from(%rcx)
You'll only update [%rsp + 40] at the safepoint at "call @callee", and
will dereference a stale pointer at "load_from(%rcx)".
To get around this, you need to use the gc_args section of
gc.statepoint. The good news is that RewriteStatepointsForGC should
do all the heavy lifting for you.
We gave a talk about this in last year's dev meeting [1], and please
feel free to ask any questions here.
[1]: http://llvm.org/devmtg/2014-10/#talk4
-- Sanjoy
>
> [if you are interested in more detail on my use-case, read the next ..
> paragraph]
>
> Let's go a little into how Lithium works. After register allocation
> phase it emits safepoint tables i.e. locations of live pointers for each
> safe point. To define the live pointers it simply looks which live
> ranges cover the safe point (and which of them hold pointers).
> I want to emit safepoint tables for LLVM-generated code as well, but I
> lack the info which becomes available only after register allocation. So
> I use the mighty Stack Maps to get it after codegen. And to emit Stack
> Maps in this case I use the <deopt args> of gc.statepoint (liveness
> analysis is done on the CFG in terms of SSA values in this case). I
> don't use <transition args> and <gc params> at all.
>
More information about the llvm-dev
mailing list