JavaMemoryModel: Worries about JIT compilation and class loading on multiprocessors

From: Bill Pugh (pugh@cs.umd.edu)
Date: Wed Jul 14 1999 - 15:52:41 EDT


I am still seriously concerned about JIT compilation and class loading
on shared memory multiprocessors.

On the Alpha for example, consider the case where processor 1
  * loads a class Bar,
  * creates all of the internal data structures for Bar,
  * generates native code for some of the methods in Bar
  * runs the static initializer for Bar
  * creates an instance of Bar
  * does a memory barrier (possibly at other points above)
  * stores a reference to that instance in Foo.x

Processor 2
    (while not calling any synchronized methods, and thus
     not needing memory barriers, except to prohibit behavior
     I am about to describe)
  * reads the reference in Foo.x, happens to see the value
    written by processor 1
  * Invokes a virtual method on that reference
    * reads the vtbl pointer in the instance
    * reads the contents of the vtbl
    * jumps to native code generated by processor 1
    * does an instanceof on "this", reading C-level fields
        of the class data structure
    * reads instance and static fields of the instance

All of the stuff done on processor 2 after reading Foo.x
might see stale values. We've discussed way processor 2
could detect and recover from reading stale values for the
vtbl pointer from the object header. But in order to be sure that
all the class data structures and vtbl entries are valid, processor
2 must do a memory barrier instruction. To ensure that the
native code generated by processor 1 isn't stale,
processor 2 needs to do a CALL_PAL IMB (instruction
memory barrier).

Even without class loading, if a HotSpot compiler decided
to generate optimized native code for a method, it couldn't
just substitute the new, optimized code: other processors
might see stale, invalid versions.

The only reasonable way I see to fix this, is to not make
newly loaded classes or newly compiled code available
until the next garbage collection (at which time, everyone does
a global memory barrier).

If you wanted to reduce that latency, but were willing to endure
a higher per-invocation cost, here is one possibility:

  * In each class structure, have a field that says which thread
    is know to have a coherent view of that class. When a class is
    created, it is set to the creating thread.

  * At garbage collection time, this field is set to a special value
    indicating "ALL".

  * Whenever a thread references the class data structure, the thread must
    check to see if the field is either ANY or itself. If not, it must do
    a memory barrier, and optionally change the field to be itself.

You could do a similar thing for native code.

Do people agree that something like this is required?
        
        Bill Pugh
-------------------------------
This is the JavaMemoryModel mailing list, managed by Majordomo 1.94.4.

To send a message to the list, email JavaMemoryModel@cs.umd.edu
To send a request to the list, email majordomo@cs.umd.edu and put
your request in the body of the message (use the request "help" for help).
For more information, visit http://www.cs.umd.edu/~pugh/java/memoryModel



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