JDK-8205549: unsafe and LW1: needed for MethodHandles, VarHandles and Reflection

Remi Forax forax at univ-mlv.fr
Wed Jun 27 22:28:47 UTC 2018


Hi Karen,
at least MethodHandles.zero also doesn't work with a value type.

and there are method handles to access arrays, see below.

Rémi

----- Mail original -----
> De: "Karen Kinnear" <karen.kinnear at oracle.com>
> À: "valhalla-dev" <valhalla-dev at openjdk.java.net>
> Envoyé: Mercredi 27 Juin 2018 23:36:44
> Objet: JDK-8205549: unsafe and LW1: needed for MethodHandles, VarHandles and Reflection

> I’ve appended a summary of Unsafe object accessors used in MethodHandles,
> VarHandles and Reflection.
> 
> Thanks to Remi’s hashCode that Mandy was trying, we identified a hole in our
> current implementation.
> Turns out our tests for MethodHandles, VarHandles and Reflection did not include
> testing for field accessors
> to flattened value type fields, which all use unsafe.
> 
> Model of usage (see e.g. test/hotspot/jtreg/runtime/Unsafe/GetPutObject.java)
>  1. use reflection to return a j.l.reflect.Field:
>  Test.class.getField("fieldname")
>  2. unsafe.objectFieldOffset(j.l.reflect.Field)
>  3. unsafe.getObject(jobject t, offset)
> 
> sample array usage:
>  Object arrayObject[]
>  1. int scale = unsafe.arrayIndexScale(arrayObject.getClass())
>  2. long offset = unsafe.arrayBaseOffset(arrayObject.getClass())
>  3. iterate, starting with offset, += scale and pass to
>  unsafe.getObject(arrayObject, offset)
> 
> Issues:
> 1. getObject on a flattened value field today will return the first 64 bits of
> the flattened contents
> 2. putObject on a flattened value field today will overwrite the first 64 bits
> with an object address
> 3. put$Type$ to a field in a value class will NOT prevent writing
>    note: I recognize this is unsafe. I highly recommend we prevent writing when
>    given a clazz and offset so
>    we can identify a value type field.
> 4. getObject/putObject not only accept a clazz + offset, they also accept a null
> base pointer + arbitrary address
>     - there is no way to determine the start of the object
> 5. performance
>     - basic unsafe calls are going to be very slow when applied to flattened fields
> 6. C2 intrinsics
>     - today we count on intrinsics to make these fast. If C2 scalarizes fields from
>     a value type, there may not be any value type to return
> 
> Status:
> 1. Frederic has been working rapidly on an initial prototype for changing
> unsafe, and sent a webrev
> for unsafe changes.
> http://cr.openjdk.java.net/~fparain/Unsafe/webrev.02/index.html
> <http://cr.openjdk.java.net/~fparain/Unsafe/webrev.02/index.html>
>   Note - this will not handle passing a null base pointer to a value type
> 
> 2. Paul has started prototyping one possible form of optimization -
>   - add some internal APIs to determine if you have a flattened field or array
>   - call a different unsafe API to access a flattened field or array element
>   - use this for VarHandles
> 
> 3. Mandy is prototyping optimizations for MethodHandles and Reflection to use
> these new APIs
> 
> Next Steps:
> 
> Roland:
>    Please do look at C2 intrinsics for the unsafe Object accessors and see what it
>    would take to make these intrinsics work
> for value types
>    If you think there is significant benefit in adding new APIs, please help us
>    understand what APIs might be most helpful.
> 
> Mandy, Paul - could you possibly send your webrevs when you are ready?
> 
> Then we can have a better conversation of alternatives with our C2 folks.
> 
> We will need a more complete set of tests specifically for MethodHandles,
> VarHandles and Reflection as well as for
> unsafe.
>    
> 
> thanks,
> Karen
> 
> p.s. Here is the usage of unsafe for MethodHandles, VarHandles, Reflection and
> java.util.Concurrent.
> I did not include explicit internal uses on JDK existing classes or on
> ByteBuffers.
> I did not do a complete search of the JDK.
> 
> MethodHandles:
> 
> DirectMethodHandles create LambdaForms with NamedFunctions in unsafe to access
> fields. Underneath they use unsafe:
>  getObject, getObjectVolatile, putObject, putObjectVolatile as well as
>  equivalents for primitive types.
> 
>    sources in DirectMethodHandles.java: see makePreparedFieldLambdaForm,
>    getFieldKind: Kind is an enum in LambdaForm.java
>    note: uses MethodHandleNatives.objectFieldOffset, staticFieldBase,
>    staticFieldOffset to set up base & offset, base is always
>     either the mirror for statics or the class for instances. offset is obtained
>     from fieldDescriptor returned by LinkResolver::resolve_field,
>     i.e. instanceKlass.find_field(). MemberName stores offset in vmindex, is_static,
>     is_setter are stored in flags.
> 
>     I do not see any array element accessors via MethodHandles


MethodHandles.arrayElementGetter() and MethodHandles.arrayElementSetter.


> 
> VarHandles:
>    Creates Forms which use unsafe.get$Type$ use:
>    getObject, putObject and decorations such as Volatile, Opaque,Acquire, … as well
>    as equivalents for primitive types
> 
>    VarHandles ALSO access array elements using unsafe.
>     arrayBaseOffset, arrayIndexScale (returns ascale)
>     shift = 31 - Integer.numberOfLeadingZeros(ascale) and then e.g.
>     UNSAFE.get$Type$Volatile, etc.
> 
>    (sources in VarHandle.s.java, X-VarHandle.java.template). Acquire base and
>    offset from MethodHandleNatives calls.
>     For the non-volatile case, appears to directly get/set from the array[index]
> 
> Reflection:
>    Reflection creates UnsafeFieldAccessorImpl (or Qualified for Volatile, same 2
>    for static) and they use unsafe:
>    getObject, putObject, getObjectVolatile, putObjectVolatile
> 
>    sources in jdk/internal/reflect/UnsafeFieldAccessorImpl.java uses
>    unsafe.staticFieldOffset or unsafe.objectFieldOffset
> 
>    I do not see any array element accessors in Reflection.
> 
> java.util.Concurrent: Atomics - uses various decorated versions of
> Get/putObjectVolatile/Release/compareAndSet etc.
> I think clarifying that LW1 does not support java.util.Concurrent atomics is the
> way to handle this one.



More information about the valhalla-dev mailing list