intrinsic that makes runtime choice whether to revert to java

Krystal Mok rednaxelafx at gmail.com
Thu Jul 5 16:03:48 PDT 2012


Hi Tom,

I think you'd still need an explicit subtype check. See the example
in Parse::catch_inline_exceptions():

    // Check the type of the exception against the catch type
    const TypeKlassPtr *tk = TypeKlassPtr::make(klass);
    Node* con = _gvn.makecon(tk);
    Node* not_subtype_ctrl = gen_subtype_check(ex_klass_node, con);
    if (!stopped()) {
      PreserveJVMState pjvms(this);
      const TypeInstPtr* tinst =
TypeOopPtr::make_from_klass_unique(klass)->cast_to_ptr_type(TypePtr::NotNull)->is_instptr();
      assert(klass->has_subklass() || tinst->klass_is_exact(), "lost
exactness");
      Node* ex_oop = _gvn.transform(new (C, 2) CheckCastPPNode(control(),
ex_node, tinst));
      push_ex_oop(ex_oop);      // Push exception oop for handler

The CheckCastPP node is only meant to tell later parts of the graph that
"we're sure we're getting the expected type on this path", instead of the
actually checking logic.

- Kris

On Fri, Jul 6, 2012 at 6:50 AM, Deneau, Tom <tom.deneau at amd.com> wrote:

> Vladimir --
>
> Limiting here to your reponse to my second question...
> The code you show for casting, I assume I can safely eliminate the
> instanceOf check
> (the lines commented out below)
> because we already checked for this in the predicated code path. so we
> would not have gotten to this intrinsic setup code if the runtime object
> were the wrong type.
>
> -- Tom
>
>
>    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);
>
>
> -----Original Message-----
> From: Vladimir Kozlov [mailto:vladimir.kozlov at oracle.com]
> Sent: Thursday, July 05, 2012 4:55 PM
> To: Deneau, Tom
> Cc: hotspot-compiler-dev at openjdk.java.net
> Subject: Re: intrinsic that makes runtime choice whether to revert to java
>
> 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().
> >>
> >
> >
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20120706/6a271786/attachment.html 


More information about the hotspot-compiler-dev mailing list