Re: JavaMemoryModel: Implementing KeepAlive

From: Jerry Schwarz (jerry.schwarz@oracle.com)
Date: Thu Apr 22 2004 - 12:16:22 EDT


At 07:40 PM 4/21/2004, Bill Pugh wrote:

>On Apr 21, 2004, at 8:30 PM, Jerry Schwarz wrote:
>
>> At 12:02 PM 4/21/2004, Bill Pugh wrote:
>>
>>OK, here is a class that implements keepAlive:
>>
>> public class FinalizerHelp {
>> static volatile Object v;
>> public static void keepAlive(Object o) {
>> v = o;
>> v = null;
>> }
>> public static void getReadyToFinalize() {
>> Object o = v;
>> }
>> }
>>
>>
>> Take Hans'es example and add a call to keepAlive.
>> for (i = 0; i < 10; ++i) {
>> sum += x.a[i];
>> }
>> FinalizerHelp.keepAlive(a)
>> ===
>>
>> I don't think this has the desired effect. The compiler first moves the
>> reference to x outside the loop and inlines keepAlive to
>>
>> v = o;
>> v = null;
>>
>> Then it eliminates v=o.
>
>Nope. This isn't allowed.
>
>The semantics we introduced to make finalizer guardians work ensures that
>if a reachable variable contains a reference to an object, that object is
>also reachable,
>even if that field is never read.

I had missed this on previous readings. I assume you're referring to the
following paragraphs:
------------------------------------------------------------
Optimizing transformations of a program can be designed that reduce the
number of
objects that are reachable to be less than those which would na¨ývely be
considered reachable.
For example, a compiler or code generator may choose to set a variable or
parameter that will
no longer be used to null to cause the storage for such an object to be
potentially reclaimable
sooner.
Another example of this occurs if the values in an object’s fields are
stored in registers.
The program then may access the registers instead of the object, and never
access the object
again. This would imply that the object is garbage.
Note that this sort of optimization is only allowed if references are on
the stack, not
stored in the heap.
---------------------------------------

The phrase "this sort of optimization" isn't clear. I guess the intention
is that any store to the heap of a reference serves as a "keep alive" for
the referent. But is that really what it says?

In this case I would like to interpret it as saying the compiler can
eliminate the redundant store as long as it honors the naive reachability
semantics.

Consider the following case

    public class R {
       public X x;
    }
    ...
    R r = new R();
    r.x = ...;
    for (i = 0; i < 10; ++i) {
      sum += r.x.a[i];
    }
    // r is dead at this point

The compiler ought to be able to notice that r does not escape this method
and allocate it on the stack rather than the heap. Stack allocation such
is potentially a significant optimization.

Under my interpretation the compiler is allowed to do the stack allocation
provided it ensure the reachability of r.x conformed to naive expectations.

>Now it occurs to me that perhaps this is too strong a requirement, and it
>will prevent some useful optimizations.
>I don't see a problem with keeping compilers from eliminating stores to
>volatile fields, but eliminating overwritten
>stores to non-volatile fields is something we might want to allow.

If we're concerned about reachability we need to force the compiler to
maintain reachability relations, we shouldn't constrain it at all with
regards to what loads and stores it does.

>Bill
>
>-------------------------------
>JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel

-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel



This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:01:05 EDT