[9] RFR (S): 8153540: C2 intrinsic for Unsafe.allocateInstance doesn't properly filter out array classes

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Wed Apr 13 16:47:19 UTC 2016


Thanks for the feedback, John.

I see your point.

Actually, after looking at check_valid_for_instantiation more carefully, 
I found one more missing check in the intrinsic: Class instantiation is 
forbidden in InstanceKlass::check_valid_for_instantiation, but the 
intrinsic allows it.

So I agree it would be desirable to minimize duplication in the code.

Am I right that you are in favor of the following approach?

   http://cr.openjdk.java.net/~vlivanov/8153540/webrev.slow_path/

I'll experiment to see how does it shape out in both cases.

Best regards,
Vladimir Ivanov

On 4/12/16 11:09 PM, John Rose wrote:
> On Apr 12, 2016, at 9:55 AM, Vladimir Ivanov
> <vladimir.x.ivanov at oracle.com <mailto:vladimir.x.ivanov at oracle.com>> wrote:
>>
>> On 4/12/16 7:33 PM, Vladimir Kozlov wrote:
>>> You did not fix comment:
>>>
>>> + // public native Object Unsafe.allocateInstance(Class<?> cls);
>>>
>>> should be:
>>>
>>> + // private native Object allocateInstance0(Class<?> cls) throws
>>> InstantiationException;
>>
>> Ok, finally found where it is :-)
>> Incorporated (will update the webrev shortly).
>>
>>> An other question: does it really throw InstantiationException?
>>
>> Yes, it does throw IE from runtime call on slow path for abstract
>> classes & interfaces (they have slow bit set in layout_helper).
>>
>> I didn't move the check into Java, because I didn't want to add yet
>> another guard on fast path.
>
> A fix is necessary, but I'm not comfortable with the shape of the
> checking logic.
> The C-coded JNI function (not the intrinsic) just surfaces the function
> JNIEnv::AllocObject.
> This function calls some complicated C++ logic
> in Klass::check_valid_for_instantiation
> to check for various things, including arrays and abstracts.  (There's
> also a primitive check.)
>
> So the problem is that the JIT intrinsic doesn't mimic all these checks.
> And a good tactic is to lift such checks into Java code, since Java is
> maintainable.
> But, there is still a maintenance problem:  The checks in the proposed
> chance
> overlap with, but do not cover, the checks performed by JNIEnv::AllocObject.
> Thus, it is difficult to prove that they are correct.  Some additional
> checks are
> performed (in an ad hoc manner) by the JIT intrinsic.
>
> Thus, the checking for a valid class is now in three places:  1.
> JNIEnv::AllocObject
> (when the intrinsic is not used), 2. the new Java code (whether the
> intrinsic is used
> or not), and 3. the partial checks in the intrinsic code (library_call.cpp).
>
> The unit test will prevent regressions, but the code is still messy and
> hard to work with.
>
> Can we make it better at this point?  Maybe not; maybe this is the
> least-bad point fix.
> But it seems to me that a less-bad fix would put the required logic in
> two places
> rather than three.  Two ways to do that are 1. push the prim and array
> checks from
> Java down into the JIT intrinsic, next to the pre-existing checks, or 2.
> pull the
> pre-existing JIT intrinsic tests up into Java.  Option 2 seems to
> require a new
> intrinsic to capture the pre-existing intrinsic tests.
>
> On the whole, since this Unsafe API point simply exposes
> JNIEnv::AllocObject,
> I suggest doing the necessary work in library_call.cpp to make the intrinsic
> accurately reflect that JNI function.  That will make the checks easier
> to verify
> and maintain.  I don't think (AM I REALLY SAYING THIS?) the Java-based
> checks
> help much in this particular case.
>
> — John


More information about the hotspot-compiler-dev mailing list