[llvm-commits] [llvm] r41879 - in /llvm/trunk: docs/GarbageCollection.html lib/Transforms/Scalar/LowerGC.cpp
Gordon Henriksen
ghenriksen at carbonite.com
Wed Sep 12 13:14:04 PDT 2007
On 2007-09-12, at 14:26, Chris Lattner wrote:
> On Sep 12, 2007, at 11:14 AM, Gordon Henriksen wrote:
>
>> Hm. Are you sure this is wise? I realize my patch didn't provide
>> root initialization, but I have that fixed locally. Without
>> liveness analysis, leaving stack roots uninitialized seems unwise,
>> since gc points are not entirely predictable from the IR.
>
> I think it is fine. trivially, any front-end that produced a call
> to the gcroot intrinsic could emit that intrinsic and a store of
> null, so there is no power lost here.
>
> The reason it is useful is for things like this (C syntax):
>
> void foo(object *P) {
> gcroot(&P, 0);
>
> ... use P ...
> }
>
> when converted to LLVM, this turns into the equivalent of:
>
> void foo(object *P) {
> P_addr = alloca object*
> store P -> P_addr
> gcroot(P_addr, 0);
>
> ... use *P_addr...
> }
>
> With the null'ing property of gcroot, it would clobber the live in
> value.
Well, this would also fix that:
P_addr = alloca object*
- store P -> P_addr
gcroot(P_addr, 0);
+ store P -> P_addr
But I'd be more concerned about more complex codes:
void f(object[] ar) {
g();
foreach (object o : ar)
h(o);
}
becomes
void @f({ i32, [0 x %object*] }* %ar) {
entry:
%ar_addr = alloca { i32, [0 x %object*] }*
@llvm.gcroot(%ar_addr, 0)
store %ar -> %ar_addr
%o_addr = alloca %object*
@llvm.gcroot(%o_addr, 0)
store null -> %o_addr ; ****
@g()
tmp.0 = load %ar_addr
tmp.1 = gep %tmp.0, 0, 0
index.0 = load tmp.1
loop:
...
}
Here, the FE must emit the highlighted null initializer separate from
the use, declaration, and scope of o; otherwise, a GC at a safepoint
corresponding to call @g will likely segfault the collector. Of more
concern, the FE must do so before any gc points, which are
implementation-defined. It's that last property which makes this
potentially error-prone.
But upon further musings, I'm actually convinced your new spec is
best. llvm.gcroot should be purely an annotation, with no runtime
component.
• In the case of a liveness-accurate collector:
The initializers are not necessary, so the collector is free to omit
them. The alloca has the same value as if llvm.gcroot were not present.
• In the case of a collector without liveness:
The null initializers are necessary, but the initializer should
immediately follow alloca rather than replacing call @llvm.gcroot.
Effectively, the initial value of the alloca becomes null if and only
if required by the collector. This change enables your alloca-store-
gcroot sequence to behave as desired.
Regardless of the collector, the FE should not rely on the contents
of an uninitialized alloca; it FE should emit initializers if that is
necessary for the source language. The collector should perform a
trivial DSE of the initial basic block to avoid obviously redundant
initializers; the difference is that it can do this reliably, since
it has knowledge of where safe points might occur.
I need to tweak the collector infrastructure slightly, but that's
okay; it's definitely a stronger spec if I comply with it in this
manner, since:
1. The semantics of alloca are entirely preserved by the
llvm.gcroot annotation.
2. The user program's interaction with the collector is even more
robust than before.
— Gordon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20070912/52e7d864/attachment.html>
More information about the llvm-commits
mailing list