<p dir="ltr">> Yes, if you define "same pointer" as "pointers with the same bitwise<br>
representation".</p>
<p dir="ltr">Yes, this is the definition I was interested in, under the assumption that it's the definition LLVM uses. But it sounds like you've augmented LLVM so that bitwise-identical pointer values are not considered equal if they come from different allocations.</p>
<p dir="ltr">In that case, I don't see any problem, although if this isn't already explicit in the langref (possibly not specifically here, since I figure this applies to lots of other stuff as well) clarifying it somewhere might help!</p>
<p dir="ltr">-Justin<br></p>
<p dir="ltr">> Are you talking about cases like these:<br>
><br>
> void f(array_t* a) {<br>
> // Not sure if this is well-defined C++, but you get the picture<br>
> int l = a->length; // invariant<br>
> delete a;<br>
> new(a) array_t(other_length);<br>
> int l2 = a->length; // also invariant<br>
> }</p>
<p dir="ltr">Yes,</p>
<p dir="ltr">On Mon, Aug 29, 2016 at 1:21 PM, Sanjoy Das <<a href="mailto:sanjoy@playingwithpointers.com">sanjoy@playingwithpointers.com</a>> wrote:<br>
> Hi Justin,<br>
><br>
> Justin Lebar wrote:<br>
>> Sanjoy, can you clarify this bit about JVM array lengths?<br>
>><br>
>> Presumably the same pointer can point to two arrays of different lengths<br>
>> during a program's execution.<br>
><br>
> Yes, if you define "same pointer" as "pointers with the same bitwise<br>
> representation". However, we do not have placement new or free, and<br>
> we do not have to worry about pointers that are visible to the program<br>
> being re-used. That is, a pointer pointing to an array in the heap<br>
> will not be re-used for any other allocation while the program can<br>
> still reach it.<br>
><br>
>> Does this mean that you're relying on<br>
>> invariant.load having function scope? That is, correctness depends on<br>
>> the pointer not being reused for an array of a different length between<br>
>> the first invariant load of that array length in a function and the last<br>
>> (possibly not invariant) load in the function?<br>
><br>
> Are you talking about cases like these:<br>
><br>
> void f(array_t* a) {<br>
> // Not sure if this is well-defined C++, but you get the picture<br>
> int l = a->length; // invariant<br>
> delete a;<br>
> new(a) array_t(other_length);<br>
> int l2 = a->length; // also invariant<br>
> }<br>
><br>
> A case like above cannot happen for us since we don't have placement<br>
> new. An allocation always returns a logically new reference, which<br>
> goes away once the application can provably no longer look at that<br>
> reference (not just load from it, but also compare it to other<br>
> references etc.). An allocation can return a "logically new" location<br>
> that happens to be bitwise equal to something it returned before (in<br>
> fact, it has to, otherwise we'll need infinite memory :) ), but the GC<br>
> (this includes the stuff we've added to LLVM) makes sure that we<br>
> re-use only locations that are no longer visible to the application.<br>
><br>
> Another way to look at this is, the GC provides an illusion of an<br>
> infinitely large heap, where every "new" returns a new distinct<br>
> reference. For instance, in cases like:<br>
><br>
> void do_something(array_t* a);<br>
><br>
> void f(array_t* a) {<br>
> do_something(a);<br>
> array_t* b = gc_new_array(...);<br>
> boolean c = (a == b);<br>
> }<br>
><br>
> `c` is *always* false. Since we have a use of `a` when computing `c`,<br>
> it _cannot_ have gone away at the point of the comparison[0].<br>
><br>
>> This seems like a very weak form of invariance. For example, when you<br>
>> inline, you would have to transform invariant loads to the scoped<br>
>> invariant thing.<br>
><br>
> I don't think we have to, but if you have some specific examples, I'll<br>
> be more than happy to comment on those. And thanks for bringing this<br>
> up!<br>
><br>
> -- Sanjoy<br>
><br>
> [0]: Actually it can, since we can first fold `c` to `false`, after<br>
> which the GC can re-use the space for `a` when allocating `b`. But<br>
> that falls into "as-if" type optimization.<br>
</p>