Dynamic type in method substitution

Tom Rodriguez tom.rodriguez at oracle.com
Fri Jan 18 01:08:19 UTC 2019

Halimi, Jean-Philippe wrote on 1/17/19 4:05 PM:
> Dear all,
> Happy new year! :)
> I am spending time implementing DigestBase::shaImplCompressMultiBlock stub for Graal as it provides hashing performance improvement. The method is implemented in DigestBase base class, but the stub depends on which derived class the actual instance is of.
> Quick diagram:
>     DigestBase
>       - Implements shaImplCompressMB
>     |        \          \
> SHA1  SHA2   SHA5
> state state   state
> Each SHA class has its own state object, but DigestBase implements the shaImplCompressMultiBlock intrinsified method. This stub needs to figure out which SHA class it is an instance of.

C2 does this using a complicated PredicatedCallGenerator that appears to 
forcibly load the SHA1/SHA256/SHA512 during code generation so I think 
this is a reasonable Grall interpretation of this pattern.

> I have the following code:
>      @MethodSubstitution(isStatic = false)
>      static int shaImplCompressMB(Object receiver, byte[] buf, int ofs, int limit) {
>          ResolvedJavaType type = INJECTED_INTRINSIC_CONTEXT.getIntrinsicMethod().getDeclaringClass();
>          ResolvedJavaType sha1 = HotSpotReplacementsUtil.getType(INJECTED_INTRINSIC_CONTEXT, "sun/security/provider/SHA");
>          ResolvedJavaType sha256 = HotSpotReplacementsUtil.getType(INJECTED_INTRINSIC_CONTEXT, "sun/security/provider/SHA2");
>          ResolvedJavaType sha512 = HotSpotReplacementsUtil.getType(INJECTED_INTRINSIC_CONTEXT, "sun/security/provider/SHA5");
>          if (type == sha1) {
>              Object realReceiver = getRealReceiver(receiver);
>              Object state = getState(realReceiver, "sun/security/provider/SHA");
>              return HotSpotBackend.shaImplCompressMBStub(getBufAddr(buf, ofs), getStateAddr(state), ofs, limit);
>          } else if (type == sha256) {
>              Object realReceiver = getRealReceiver(receiver);
>              Object state = getState(realReceiver, "sun/security/provider/SHA2");
>              return HotSpotBackend.sha2ImplCompressMBStub(getBufAddr(buf, ofs), getStateAddr(state), ofs, limit);
>          } else if (type == sha512) {
>              Object realReceiver = getRealReceiver(receiver);
>              Object state = getState(realReceiver, "sun/security/provider/SHA5");
>              return HotSpotBackend.sha5ImplCompressMBStub(getBufAddr(buf, ofs), getStateAddr(state), ofs, limit);
>          } else {
>              return -1;
>          }
>      }
> I would like to know if this is the correct way to proceed, especially lines 3 4 5 6, to respectively get the type of the object instance and the types of each derived class.

Your type test is wrong though.  You can't use 
INJECTED_INTRINSIC_CONTEXT like this.  It's a placeholder value for an 
@Fold method and can't simply be used directly.  It's also not the value 
you want since it would be DigestBase I think.  You need to be type 
checking the receiver.  I think it should be:

if (doInstanceof(sha1, realReceiver)) {

See CipherBlockChainingSubstitutions for an example of this.

I think those are ok but make sure that HotSpotReplacementsUtil.getType 
has an @Fold annotation on it.  Otherwise it will try to inline the 
whole thing instead of appearing as a constant.  I thought this had 
already appeared in another PR but don't see it right now.  It should 
look like this:

     static ResolvedJavaType getType(@InjectedParameter IntrinsicContext 
context, String typeName) {

Shouldn't the final return -1 case be a dispatch to the real method in 
case there are other subclasses?  As in:

} else {
     return shaImplCompressMB(receiver, ofs, buf limit);

This should result in a normal invoke site being emitted.

I think that should get you close to the a working result.


> Thank you for your help.
> -Jp

More information about the graal-dev mailing list