<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On 2007-09-12, at 14:26, Chris Lattner wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">On Sep 12, 2007, at 11:14 AM, Gordon Henriksen wrote:</div></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> <blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Hm. Are you sure this is wise? I realize my patch didn't provide <span class="Apple-converted-space"><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">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.</span></span></div> </blockquote><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">I think it is fine.<span class="Apple-converted-space">  </span>trivially, any front-end that produced a call to <span class="Apple-converted-space"><span class="Apple-style-span" style="-webkit-text-stroke-width: -1; ">the gcroot intrinsic could emit that intrinsic and a store of null, so there is no power lost here.</span></span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">The reason it is useful is for things like this (C syntax):</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">void foo(object *P) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span class="Apple-converted-space">   </span>gcroot(&P, 0);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span class="Apple-converted-space">   </span>... use P ...</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">when converted to LLVM, this turns into the equivalent of:</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">void foo(object *P) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span class="Apple-converted-space">   </span>P_addr = alloca object*</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span class="Apple-converted-space">   </span>store P -> P_addr</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span class="Apple-converted-space">   </span>gcroot(P_addr, 0);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span class="Apple-converted-space">   </span>... use *P_addr...</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">With the null'ing property of gcroot, it would clobber the live in <span class="Apple-converted-space"> </span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">value.</div></blockquote><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">Well, this would also fix that:</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font class="Apple-style-span" face="Courier">   P_addr = alloca object*</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#999999">-  store P -> P_addr</font></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font class="Apple-style-span" face="Courier">   gcroot(P_addr, 0);</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#0000FF">+  store P -> P_addr</font></font></div><font class="Apple-style-span" face="Courier"><br class="webkit-block-placeholder"></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">But I'd be more concerned about more complex codes:</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">  void f(object[] ar) {</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    g();</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    foreach (object o : ar)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">      h(o);</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">  }</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">becomes</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">  void @f({ i32, [0 x %object*] }* %ar) {</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">  entry:</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    %ar_addr = alloca { i32, [0 x %object*] }*</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    @llvm.gcroot(%ar_addr, 0)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    store %ar -> %ar_addr</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    </font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    %o_addr = alloca %object*</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    @llvm.gcroot(%o_addr, 0)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    </font><font class="Apple-style-span" color="#FF0000"><font class="Apple-style-span" face="Courier">store null -> %o_addr   ; ****</font></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier"><br class="webkit-block-placeholder"></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    @g()</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    </font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    tmp.0 = load %ar_addr</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    tmp.1 = gep %tmp.0, 0, 0</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    index.0 = load tmp.1</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">  loop:</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">    ...</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><font class="Apple-style-span" face="Courier">  }</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">Here, the FE must emit the highlighted null initializer separate from the use, declaration, and scope of <font class="Apple-style-span" face="Courier">o</font>; otherwise, a GC at a safepoint corresponding to <font class="Apple-style-span" face="Courier">call @g</font> will likely segfault the collector. Of more concern, the FE must do so before <i>any</i> gc points, which are implementation-defined. It's that last property which makes this potentially error-prone.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">But upon further musings, I'm actually convinced your new spec is best. <font class="Apple-style-span" face="Courier">llvm.gcroot</font> should be purely an annotation, with no runtime component.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">• In the case of a liveness-accurate collector:</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">The initializers are not necessary, so the collector is free to omit them. The <font class="Apple-style-span" face="Courier">alloca</font> has the same value as if <font class="Apple-style-span" face="Courier">llvm.gcroot</font> were not present.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">• In the case of a collector without liveness:</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">The null initializers are necessary, but the initializer should immediately follow <font class="Apple-style-span" face="Courier">alloca</font> rather than replacing <font class="Apple-style-span" face="Courier">call @llvm.gcroot</font>. Effectively, the initial value of the <font class="Apple-style-span" face="Courier">alloca</font> becomes <font class="Apple-style-span" face="Courier">null</font> if and only if required by the collector. This change enables your <font class="Apple-style-span" face="Courier">alloca<font class="Apple-style-span" face="'Trebuchet MS'">-</font>store<font class="Apple-style-span" face="'Trebuchet MS'">-</font>gcroot</font> sequence to behave as desired.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">Regardless of the collector, the FE should not rely on the contents of an uninitialized <font class="Apple-style-span" face="Courier">alloca</font>; 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.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">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:</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "> 1. The semantics of <font class="Apple-style-span" face="Courier">alloca</font> are entirely preserved by the <font class="Apple-style-span" face="Courier">llvm.gcroot</font> annotation.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "> 2. The user program's interaction with the collector is even more robust than before.</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; ">— Gordon</div></div> <br></body></html>