ARRGGGH! Ben: Are you whacking out-bound Reply-To headers somehow, or did I neglect to set the right config in mailman?
On Sun, Apr 10, 2011 at 10:21 PM, Jonathan S. Shapiro <[email protected]>wrote: > On Sun, Apr 10, 2011 at 8:36 PM, Ben Karel <[email protected]> wrote: > > In any case, it's an example of the kind of thing where an optimization >>> pass written by someone who is thinking in terms of non-managed source >>> languages will be written in such a way that you end up re-writing the pass >>> when you have to accommodate the new case. We are then presented with the >>> difficulty of designing test cases that will let us determine which passes >>> are currently "relocating GC safe" and which passes are not. >>> >> >> I don't fully understand the example, so I don't know what LLVM winds up >> doing. But I don't see anything an optimization pass must do for GC >> correctness beyond preserving the same semantics that needed to be preserved >> without GC primitives. >> > > Then indeed you don't understand the example. I think it's worth the time > to get this point clear, so let me work an example. First, let's start with > the source code. Suppose we have: > > struct S { ... }; // something size > 16 bytes > > ... > > void f(S *s_vec, int vecSize) { > for (int i = 0; i < vecSize; i++) > s_vec[i].i = 5 > } > > Note first that because sizeof(S) > 16, we cannot use scaled-index > addressing modes on hardware that provides it, and we don't want to multiply > /i/ by /sizeof(S)/ in each iteration (because multiply is expensive). In > consequence, the *standard* optimization for this will convert into > something that looks like: > > void f(S *s_vec, int vecSize) { > int i = 0; > while(i < vecSize) > s_vec->i = 5; > s_vec++; // that is: increment by sizeof(S) > } > > It will also unroll the loop, but that's not important to explain the issue > at hand. > > Note than when i>=1, s_vec does not point to the base of the vector, which > is the base of the object that we need to mark for GC. > > First problem: a typical GC runtime relies on using a negative offset from > the object base pointer in order to find the object header for mark > purposes, but there is no live object base pointer when i >= 1. And it is > altogether possible that the argument passed from above the call to f() is > dead on return from the call, and therefore does not appear in any GC > register map above this one. The simple solution in this case is to save a > base pointer and use that for mark purposes, but a conventional optimizer > will see no need to do this. > > Second problem: even if we save a base pointer for mark purposes, we still > need to ensure that s_vec gets updated by the proper delta whenever the > vector is relocated by GC. In order to do this, we need to know that s_vec > is an interior reference into the object named by s_vec_save. > > Either that, or we need to do interior pointer lookup, which is (a) * > extremely* expensive, and (b) based on heuristic assumptions about things > the optimizer will not do in the course of loop unrolling - when loop > unrolling is applied aggressively, it's very possible that s_vec will end up > pointing substantially *past* the body of the vector. > > > Is that expansion enough to see the problem? Also, do you see why an > unrolling algorithm written for an unmanaged language has no need to record > this information? > > > I'm not clear whether the IR needs to somehow distinguish between "anchor" > pointers and "derived" pointers or not - I haven't thought about it enough, > and there may be an easier way. But looking at how C# handles "foreign" > objects, there are clearly two low-level pointer types that need to be in > play at the IR level. Adding a second type isn't that hard, but it probably > touches a lot of code in LLVM. > > > It's also worth noting that there are neither required nor default >>>> optimization passes, at either the LLVM or MC levels. It's all opt-in... >>>> >>> >>> I agree, but ultimately that is a cop-out. The point of going to LLVM is >>> that we get to take advantage existing infrastructure. If we are forced to >>> turn the existing infrastructure off, then what's the point of using LLVM. I >>> do understand that it isn't that black and white, but you see my point. >>> >> >> More importantly, giving clients complete control over optimization passes >> helps diagnose whatever miscompilations might occur. >> > > Oh absolutely! I definitely agree that being in control of the passes is a > good thing. But what you seemed to be suggesting was that we could, in > effect, turn off the optimizer in order to avoid GC hazards in production. > Which we could, but if we are forced to do that, the value of LLVM starts to > decay quickly... > > Having said that, Chris is a very smart guy, so maybe he will find a way. >>> >> >> Out of curiosity, would you have predicted that they could build a full >> C++ compiler, from scratch, in less than 4 years? I certainly wouldn't >> have... >> > > I would definitely have predicted that. Both of my C++ compiler groups did > that, but I grant that C++ was a simpler language at the time. > > But the permanent vs. transitional distinction is quite real. >>> >> >> There's also the difference that you're building a specific compiler, >> while they're building a library for compiler writers. By building in C++ >> with C bindings, they maximize their potential client base. >> > > Not quite. They are building an infrastructure for compiler writers who > choose to implement their compilers in C/C++. It does not follow that this > maximizes the client base. It may or may not. What it *does* do is maximize > the immediate utility to Apple, which is important. > > > shap >
_______________________________________________ bitc-dev mailing list [email protected] http://www.coyotos.org/mailman/listinfo/bitc-dev
