intrinsic that makes runtime choice whether to revert to java

Vladimir Kozlov vladimir.kozlov at oracle.com
Thu Jul 5 14:54:49 PDT 2012


Deneau, Tom wrote:
> Vladimir --
> 
> The code you provided helps a lot, thank you.
> I am still testing it, but it seems to work for the basic cases.
> 
> A couple of questions based on my not having done much with GraphKit:
> 
>    1) I want to do a test at compile time (or maybe even earlier at
>       stub generation time) as to whether a certain library class is a
>       version that has a certain field.  This would fail if are
>       mistakenly using the old library with a new JVM, which would
>       indicate we cannot use the intrinsics.  I suspect this is done
>       using the class from the systemDictionary but I'm not sure.

Look on usage of find_local_field() method in thread.cpp and other places.

> 
>    2) At compile time, when generating the code for the fast path, I
>       want to generate a Node* to load a certain field from the
>       embeddedCipher object (since we have made it past the predicate,
>       we know that the embeddedCipher object is an instance of the
>       class we expect).  I need to do this so that I can pass the
>       field to the stub.  But at compile time, the particular instance
>       that triggered compilation might not have an embeddedCipher
>       object of the proper type.  Still I want to generate a Node*
>       that will load a field from the embeddedCipher object as if it
>       were the proper type.  And I am not sure how to do that.  (My
>       current code failes to generate the intrinsic unless the
>       particular instance that triggered compilation is the correct
>       type).  I hope this question makes sense.

I assume by the "fast path" you mean the intrinsic for whole encrypt() method. 
Right? You need to cast field object's type to AESCrypt if I understand your 
question correctly:

   const TypeKlassPtr* aklass = TypeKlassPtr::make(klass_AESCrypt);
   _sp += nargs;          // gen_instanceof might do an uncommon trap
   Node* instof = gen_instanceof(embeddedCipherObj, makecon(aklass));
   _sp -= nargs;
   Node* cmp_instof  = _gvn.transform(new (C, 3) CmpINode(instof, intcon(1)));
   Node* bool_instof  = _gvn.transform(new (C, 2) BoolNode(cmp_instof, 
BoolTest::ne));

   Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);
   // fall through if the instance exactly matches the desired type
   const TypeOopPtr* xtype = aklass->as_instance_type();
   Node* cast = new(C, 2) CheckCastPPNode(control(), embeddedCipherObj, xtype);
   cast = _gvn.transform(cast);
   _gvn.replace_in_map(embeddedCipherObj, cast);
   Node* k_len = get_key_len_from_aescrypt_object(cast);

> 
>    3) If I want my predicate to be based on two Boolean tests,
>       similar to the following java code
> 
> 	if ((obj instanceof XXXClass) && ((XXXClass)(obj).field == SomeConstant))
> 
>       and I want to of course skip the second test if the first test fails.
>       Is it something like the following?

You need Region node to merge 2 false paths:

   RegionNode* region = new(C, 3) RegionNode(3);
...
   region->init_req(1, instof_false);
...
   region->init_req(2, klen_false);
   record_for_igvn(region);
   return _gvn.transform(region);

> 
>   _sp += nargs;          // gen_instanceof might do an uncommon trap
>   Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(klass_AESCrypt)));
>   _sp -= nargs;
>   Node* cmp_instof  = _gvn.transform(new (C, 3) CmpINode(instof, intcon(1)));
>   Node* bool_instof  = _gvn.transform(new (C, 2) BoolNode(cmp_instof, BoolTest::ne));
> 
>   Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);
>   //instanceOf == true, fallthrough
> 
>   Node* k_len = get_key_len_from_aescrypt_object(embeddedCipherObj);
>   Node* cmp_klen  = _gvn.transform(new (C, 3) CmpINode(k_len, intcon(44)));   // corresponds to keys we can handle
>   Node* bool_klen  = _gvn.transform(new (C, 2) BoolNode(cmp_klen, BoolTest::ne));

Why exact 44 and not <= ?

Vladimir

>   Node* klen_false = generate_guard(bool_klen, NULL, PROB_MIN);
>   return klen_false;
> 
> -- Tom      
> 
> -----Original Message-----
> From: Vladimir Kozlov [mailto:vladimir.kozlov at oracle.com] 
> Sent: Monday, July 02, 2012 9:57 PM
> To: Deneau, Tom
> Cc: hotspot-compiler-dev at openjdk.java.net
> Subject: Re: intrinsic that makes runtime choice whether to revert to java
> 
> I finally had time today to look on this. Here is code:
> 
> http://cr.openjdk.java.net/~kvn/pred_intr/webrev
> 
> But I did not test or optimize it (part of new code in callGenerator.cpp should 
> be shared with PredictedCallGenerator from which it was cloned).
> 
> Vladimir
> 
> Deneau, Tom wrote:
>> Hi all --
>>
>> I am writing a hotspot intrinsic but I want it to make a runtime
>> choice whether to execute the intrinsic code or to execute the regular
>> java code.
>>
>> I got the suggestion below from Vladimir but I am not experienced
>> enough with the graphkit functionality to see how to do this.  Would
>> someone be able to provide the code skeleton for this?  I can generate
>> the region to actually do my intrinsic and I believe I can generate the
>> BoolNode which determines which path to take.
>>
>> The other choice would be to modify the actual JDK library routine to
>> do the runtime tests and call a new routine which the intrinsic would
>> hook into.  I have done this for testing but I am assuming this is more
>> intrusive since on some architectures the intrinsic will not even be generated.
>>
>> -- Tom Deneau
>>
>>> We don't have such mechanism currently. But it is not difficult to implement. 
>>> Look on the code in doCall.cpp and callGenerator files. Instead of calling 
>>> find_intrinsic() you need to do something special for your case. Like code for 
>>> CallGenerator::for_method_handle_call() where you will generate class check and 
>>> on one path you will get intrinsic (by calling find_intrinsic()) and on other 
>>> path is regular CallGenerator::for_inline().
>>
> 
> 


More information about the hotspot-compiler-dev mailing list