Hi Tom,<div><br></div><div>I think you&#39;d still need an explicit subtype check. See the example in Parse::catch_inline_exceptions():</div><div><br></div><div><div><font face="courier new, monospace">    // Check the type of the exception against the catch type</font></div>
<div><font face="courier new, monospace">    const TypeKlassPtr *tk = TypeKlassPtr::make(klass);</font></div><div><font face="courier new, monospace">    Node* con = _gvn.makecon(tk);</font></div><div><font face="courier new, monospace">    Node* not_subtype_ctrl = gen_subtype_check(ex_klass_node, con);</font></div>
<div><font face="courier new, monospace">    if (!stopped()) {</font></div><div><font face="courier new, monospace">      PreserveJVMState pjvms(this);</font></div><div><font face="courier new, monospace">      const TypeInstPtr* tinst = TypeOopPtr::make_from_klass_unique(klass)-&gt;cast_to_ptr_type(TypePtr::NotNull)-&gt;is_instptr();</font></div>
<div><font face="courier new, monospace">      assert(klass-&gt;has_subklass() || tinst-&gt;klass_is_exact(), &quot;lost exactness&quot;);</font></div><div><font face="courier new, monospace">      Node* ex_oop = _gvn.transform(new (C, 2) CheckCastPPNode(control(), ex_node, tinst));</font></div>
<div><font face="courier new, monospace">      push_ex_oop(ex_oop);      // Push exception oop for handler</font></div><br><div class="gmail_quote">The CheckCastPP node is only meant to tell later parts of the graph that &quot;we&#39;re sure we&#39;re getting the expected type on this path&quot;, instead of the actually checking logic.</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">- Kris</div><div class="gmail_quote"><br></div><div class="gmail_quote">On Fri, Jul 6, 2012 at 6:50 AM, Deneau, Tom <span dir="ltr">&lt;<a href="mailto:tom.deneau@amd.com" target="_blank">tom.deneau@amd.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Vladimir --<br>
<br>
Limiting here to your reponse to my second question...<br>
The code you show for casting, I assume I can safely eliminate the instanceOf check<br>
(the lines commented out below)<br>
because we already checked for this in the predicated code path. so we<br>
would not have gotten to this intrinsic setup code if the runtime object were the wrong type.<br>
<br>
-- Tom<br>
<div class="im"><br>
<br>
   const TypeKlassPtr* aklass = TypeKlassPtr::make(klass_AESCrypt);<br>
</div>//   _sp += nargs;          // gen_instanceof might do an uncommon trap<br>
//   Node* instof = gen_instanceof(embeddedCipherObj, makecon(aklass));<br>
//   _sp -= nargs;<br>
//   Node* cmp_instof  = _gvn.transform(new (C, 3) CmpINode(instof, intcon(1)));<br>
//   Node* bool_instof  = _gvn.transform(new (C, 2) BoolNode(cmp_instof, BoolTest::ne));<br>
<br>
//   Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);<br>
<div class="im HOEnZb">   // fall through if the instance exactly matches the desired type<br>
   const TypeOopPtr* xtype = aklass-&gt;as_instance_type();<br>
   Node* cast = new(C, 2) CheckCastPPNode(control(), embeddedCipherObj, xtype);<br>
   cast = _gvn.transform(cast);<br>
   _gvn.replace_in_map(embeddedCipherObj, cast);<br>
   Node* k_len = get_key_len_from_aescrypt_object(cast);<br>
<br>
<br>
</div><div class="im HOEnZb">-----Original Message-----<br>
From: Vladimir Kozlov [mailto:<a href="mailto:vladimir.kozlov@oracle.com">vladimir.kozlov@oracle.com</a>]<br>
</div><div class="HOEnZb"><div class="h5">Sent: Thursday, July 05, 2012 4:55 PM<br>
To: Deneau, Tom<br>
Cc: <a href="mailto:hotspot-compiler-dev@openjdk.java.net">hotspot-compiler-dev@openjdk.java.net</a><br>
Subject: Re: intrinsic that makes runtime choice whether to revert to java<br>
<br>
Deneau, Tom wrote:<br>
&gt; Vladimir --<br>
&gt;<br>
&gt; The code you provided helps a lot, thank you.<br>
&gt; I am still testing it, but it seems to work for the basic cases.<br>
&gt;<br>
&gt; A couple of questions based on my not having done much with GraphKit:<br>
&gt;<br>
&gt;    1) I want to do a test at compile time (or maybe even earlier at<br>
&gt;       stub generation time) as to whether a certain library class is a<br>
&gt;       version that has a certain field.  This would fail if are<br>
&gt;       mistakenly using the old library with a new JVM, which would<br>
&gt;       indicate we cannot use the intrinsics.  I suspect this is done<br>
&gt;       using the class from the systemDictionary but I&#39;m not sure.<br>
<br>
Look on usage of find_local_field() method in thread.cpp and other places.<br>
<br>
&gt;<br>
&gt;    2) At compile time, when generating the code for the fast path, I<br>
&gt;       want to generate a Node* to load a certain field from the<br>
&gt;       embeddedCipher object (since we have made it past the predicate,<br>
&gt;       we know that the embeddedCipher object is an instance of the<br>
&gt;       class we expect).  I need to do this so that I can pass the<br>
&gt;       field to the stub.  But at compile time, the particular instance<br>
&gt;       that triggered compilation might not have an embeddedCipher<br>
&gt;       object of the proper type.  Still I want to generate a Node*<br>
&gt;       that will load a field from the embeddedCipher object as if it<br>
&gt;       were the proper type.  And I am not sure how to do that.  (My<br>
&gt;       current code failes to generate the intrinsic unless the<br>
&gt;       particular instance that triggered compilation is the correct<br>
&gt;       type).  I hope this question makes sense.<br>
<br>
I assume by the &quot;fast path&quot; you mean the intrinsic for whole encrypt() method.<br>
Right? You need to cast field object&#39;s type to AESCrypt if I understand your<br>
question correctly:<br>
<br>
   const TypeKlassPtr* aklass = TypeKlassPtr::make(klass_AESCrypt);<br>
   _sp += nargs;          // gen_instanceof might do an uncommon trap<br>
   Node* instof = gen_instanceof(embeddedCipherObj, makecon(aklass));<br>
   _sp -= nargs;<br>
   Node* cmp_instof  = _gvn.transform(new (C, 3) CmpINode(instof, intcon(1)));<br>
   Node* bool_instof  = _gvn.transform(new (C, 2) BoolNode(cmp_instof,<br>
BoolTest::ne));<br>
<br>
   Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);<br>
   // fall through if the instance exactly matches the desired type<br>
   const TypeOopPtr* xtype = aklass-&gt;as_instance_type();<br>
   Node* cast = new(C, 2) CheckCastPPNode(control(), embeddedCipherObj, xtype);<br>
   cast = _gvn.transform(cast);<br>
   _gvn.replace_in_map(embeddedCipherObj, cast);<br>
   Node* k_len = get_key_len_from_aescrypt_object(cast);<br>
<br>
&gt;<br>
&gt;    3) If I want my predicate to be based on two Boolean tests,<br>
&gt;       similar to the following java code<br>
&gt;<br>
&gt;       if ((obj instanceof XXXClass) &amp;&amp; ((XXXClass)(obj).field == SomeConstant))<br>
&gt;<br>
&gt;       and I want to of course skip the second test if the first test fails.<br>
&gt;       Is it something like the following?<br>
<br>
You need Region node to merge 2 false paths:<br>
<br>
   RegionNode* region = new(C, 3) RegionNode(3);<br>
...<br>
   region-&gt;init_req(1, instof_false);<br>
...<br>
   region-&gt;init_req(2, klen_false);<br>
   record_for_igvn(region);<br>
   return _gvn.transform(region);<br>
<br>
&gt;<br>
&gt;   _sp += nargs;          // gen_instanceof might do an uncommon trap<br>
&gt;   Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(klass_AESCrypt)));<br>
&gt;   _sp -= nargs;<br>
&gt;   Node* cmp_instof  = _gvn.transform(new (C, 3) CmpINode(instof, intcon(1)));<br>
&gt;   Node* bool_instof  = _gvn.transform(new (C, 2) BoolNode(cmp_instof, BoolTest::ne));<br>
&gt;<br>
&gt;   Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);<br>
&gt;   //instanceOf == true, fallthrough<br>
&gt;<br>
&gt;   Node* k_len = get_key_len_from_aescrypt_object(embeddedCipherObj);<br>
&gt;   Node* cmp_klen  = _gvn.transform(new (C, 3) CmpINode(k_len, intcon(44)));   // corresponds to keys we can handle<br>
&gt;   Node* bool_klen  = _gvn.transform(new (C, 2) BoolNode(cmp_klen, BoolTest::ne));<br>
<br>
Why exact 44 and not &lt;= ?<br>
<br>
Vladimir<br>
<br>
&gt;   Node* klen_false = generate_guard(bool_klen, NULL, PROB_MIN);<br>
&gt;   return klen_false;<br>
&gt;<br>
&gt; -- Tom<br>
&gt;<br>
&gt; -----Original Message-----<br>
&gt; From: Vladimir Kozlov [mailto:<a href="mailto:vladimir.kozlov@oracle.com">vladimir.kozlov@oracle.com</a>]<br>
&gt; Sent: Monday, July 02, 2012 9:57 PM<br>
&gt; To: Deneau, Tom<br>
&gt; Cc: <a href="mailto:hotspot-compiler-dev@openjdk.java.net">hotspot-compiler-dev@openjdk.java.net</a><br>
&gt; Subject: Re: intrinsic that makes runtime choice whether to revert to java<br>
&gt;<br>
&gt; I finally had time today to look on this. Here is code:<br>
&gt;<br>
&gt; <a href="http://cr.openjdk.java.net/~kvn/pred_intr/webrev" target="_blank">http://cr.openjdk.java.net/~kvn/pred_intr/webrev</a><br>
&gt;<br>
&gt; But I did not test or optimize it (part of new code in callGenerator.cpp should<br>
&gt; be shared with PredictedCallGenerator from which it was cloned).<br>
&gt;<br>
&gt; Vladimir<br>
&gt;<br>
&gt; Deneau, Tom wrote:<br>
&gt;&gt; Hi all --<br>
&gt;&gt;<br>
&gt;&gt; I am writing a hotspot intrinsic but I want it to make a runtime<br>
&gt;&gt; choice whether to execute the intrinsic code or to execute the regular<br>
&gt;&gt; java code.<br>
&gt;&gt;<br>
&gt;&gt; I got the suggestion below from Vladimir but I am not experienced<br>
&gt;&gt; enough with the graphkit functionality to see how to do this.  Would<br>
&gt;&gt; someone be able to provide the code skeleton for this?  I can generate<br>
&gt;&gt; the region to actually do my intrinsic and I believe I can generate the<br>
&gt;&gt; BoolNode which determines which path to take.<br>
&gt;&gt;<br>
&gt;&gt; The other choice would be to modify the actual JDK library routine to<br>
&gt;&gt; do the runtime tests and call a new routine which the intrinsic would<br>
&gt;&gt; hook into.  I have done this for testing but I am assuming this is more<br>
&gt;&gt; intrusive since on some architectures the intrinsic will not even be generated.<br>
&gt;&gt;<br>
&gt;&gt; -- Tom Deneau<br>
&gt;&gt;<br>
&gt;&gt;&gt; We don&#39;t have such mechanism currently. But it is not difficult to implement.<br>
&gt;&gt;&gt; Look on the code in doCall.cpp and callGenerator files. Instead of calling<br>
&gt;&gt;&gt; find_intrinsic() you need to do something special for your case. Like code for<br>
&gt;&gt;&gt; CallGenerator::for_method_handle_call() where you will generate class check and<br>
&gt;&gt;&gt; on one path you will get intrinsic (by calling find_intrinsic()) and on other<br>
&gt;&gt;&gt; path is regular CallGenerator::for_inline().<br>
&gt;&gt;<br>
&gt;<br>
&gt;<br>
<br>
<br>
</div></div></blockquote></div><br></div>