< prev index next >

src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java

Print this page
rev 59151 : imported patch viewAs

@@ -49,13 +49,14 @@
  * to a class member.
  * @author jrose
  */
 class DirectMethodHandle extends MethodHandle {
     final MemberName member;
+    final boolean crackable;
 
     // Constructors and factory methods in this class *must* be package scoped or private.
-    private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
+    private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member, boolean crackable) {
         super(mtype, form);
         if (!member.isResolved())  throw new InternalError();
 
         if (member.getDeclaringClass().isInterface() &&
             member.getReferenceKind() == REF_invokeInterface &&

@@ -68,10 +69,11 @@
                 member = m;
             }
         }
 
         this.member = member;
+        this.crackable = crackable;
     }
 
     // Factory methods:
     static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
         MethodType mtype = member.getMethodOrFieldType();

@@ -90,34 +92,34 @@
                     // receiver check inserted
                     if (callerClass == null) {
                         throw new InternalError("callerClass must not be null for REF_invokeSpecial");
                     }
                     LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
-                    return new Special(mtype, lform, member, callerClass);
+                    return new Special(mtype, lform, member, true, callerClass);
                 }
                 case REF_invokeInterface: {
                     // for interfaces we always need the receiver typecheck,
                     // so we always pass 'true' to ensure we adapt if needed
                     // to include the REF_invokeSpecial case
                     LambdaForm lform = preparedLambdaForm(member, true);
-                    return new Interface(mtype, lform, member, refc);
+                    return new Interface(mtype, lform, member, true, refc);
                 }
                 default: {
                     LambdaForm lform = preparedLambdaForm(member);
-                    return new DirectMethodHandle(mtype, lform, member);
+                    return new DirectMethodHandle(mtype, lform, member, true);
                 }
             }
         } else {
             LambdaForm lform = preparedFieldLambdaForm(member);
             if (member.isStatic()) {
                 long offset = MethodHandleNatives.staticFieldOffset(member);
                 Object base = MethodHandleNatives.staticFieldBase(member);
-                return new StaticAccessor(mtype, lform, member, base, offset);
+                return new StaticAccessor(mtype, lform, member, true, base, offset);
             } else {
                 long offset = MethodHandleNatives.objectFieldOffset(member);
                 assert(offset == (int)offset);
-                return new Accessor(mtype, lform, member, (int)offset);
+                return new Accessor(mtype, lform, member, true, (int)offset);
             }
         }
     }
     static DirectMethodHandle make(Class<?> refc, MemberName member) {
         byte refKind = member.getReferenceKind();

@@ -137,24 +139,40 @@
         assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
         MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
         LambdaForm lform = preparedLambdaForm(ctor);
         MemberName init = ctor.asSpecial();
         assert(init.getMethodType().returnType() == void.class);
-        return new Constructor(mtype, lform, ctor, init, instanceClass);
+        return new Constructor(mtype, lform, ctor, true, init, instanceClass);
     }
 
     @Override
     BoundMethodHandle rebind() {
         return BoundMethodHandle.makeReinvoker(this);
     }
 
     @Override
     MethodHandle copyWith(MethodType mt, LambdaForm lf) {
         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
-        return new DirectMethodHandle(mt, lf, member);
+        return new DirectMethodHandle(mt, lf, member, crackable);
+    }
+    /*non-public*/
+    @Override
+    MethodHandle viewAsType(MethodType newType, boolean strict) {
+        // No actual conversions, just a new view of the same method.
+        // However, we must not expose a DMH that is crackable into a
+        // MethodHandleInfo, so we return a cloned, uncrackable DMH
+        assert viewAsTypeChecks(newType, strict);
+        assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
+        return new DirectMethodHandle(newType, form, member, false);
+    }
+    /*non-public*/
+    @Override
+    boolean isCrackable() {
+        return crackable;
     }
 
+
     @Override
     String internalProperties() {
         return "\n& DMH.MN="+internalMemberName();
     }
 

@@ -404,21 +422,26 @@
     }
 
     /** This subclass represents invokespecial instructions. */
     static class Special extends DirectMethodHandle {
         private final Class<?> caller;
-        private Special(MethodType mtype, LambdaForm form, MemberName member, Class<?> caller) {
-            super(mtype, form, member);
+        private Special(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> caller) {
+            super(mtype, form, member, crackable);
             this.caller = caller;
         }
         @Override
         boolean isInvokeSpecial() {
             return true;
         }
         @Override
         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
-            return new Special(mt, lf, member, caller);
+            return new Special(mt, lf, member, crackable, caller);
+        }
+        @Override
+        MethodHandle viewAsType(MethodType newType, boolean strict) {
+            assert viewAsTypeChecks(newType, strict);
+            return new Special(newType, form, member, false, caller);
         }
         Object checkReceiver(Object recv) {
             if (!caller.isInstance(recv)) {
                 String msg = String.format("Receiver class %s is not a subclass of caller class %s",
                                            recv.getClass().getName(), caller.getName());

@@ -429,18 +452,23 @@
     }
 
     /** This subclass represents invokeinterface instructions. */
     static class Interface extends DirectMethodHandle {
         private final Class<?> refc;
-        private Interface(MethodType mtype, LambdaForm form, MemberName member, Class<?> refc) {
-            super(mtype, form, member);
+        private Interface(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> refc) {
+            super(mtype, form, member, crackable);
             assert refc.isInterface() : refc;
             this.refc = refc;
         }
         @Override
         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
-            return new Interface(mt, lf, member, refc);
+            return new Interface(mt, lf, member, crackable, refc);
+        }
+        @Override
+        MethodHandle viewAsType(MethodType newType, boolean strict) {
+            assert viewAsTypeChecks(newType, strict);
+            return new Interface(newType, form, member, false, refc);
         }
         @Override
         Object checkReceiver(Object recv) {
             if (!refc.isInstance(recv)) {
                 String msg = String.format("Receiver class %s does not implement the requested interface %s",

@@ -461,19 +489,24 @@
     static class Constructor extends DirectMethodHandle {
         final MemberName initMethod;
         final Class<?>   instanceClass;
 
         private Constructor(MethodType mtype, LambdaForm form, MemberName constructor,
-                            MemberName initMethod, Class<?> instanceClass) {
-            super(mtype, form, constructor);
+                            boolean crackable, MemberName initMethod, Class<?> instanceClass) {
+            super(mtype, form, constructor, crackable);
             this.initMethod = initMethod;
             this.instanceClass = instanceClass;
             assert(initMethod.isResolved());
         }
         @Override
         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
-            return new Constructor(mt, lf, member, initMethod, instanceClass);
+            return new Constructor(mt, lf, member, crackable, initMethod, instanceClass);
+        }
+        @Override
+        MethodHandle viewAsType(MethodType newType, boolean strict) {
+            assert viewAsTypeChecks(newType, strict);
+            return new Constructor(newType, form, member, false, initMethod, instanceClass);
         }
     }
 
     /*non-public*/
     static Object constructorMethod(Object mh) {

@@ -490,22 +523,27 @@
     /** This subclass handles non-static field references. */
     static class Accessor extends DirectMethodHandle {
         final Class<?> fieldType;
         final int      fieldOffset;
         private Accessor(MethodType mtype, LambdaForm form, MemberName member,
-                         int fieldOffset) {
-            super(mtype, form, member);
+                         boolean crackable, int fieldOffset) {
+            super(mtype, form, member, crackable);
             this.fieldType   = member.getFieldType();
             this.fieldOffset = fieldOffset;
         }
 
         @Override Object checkCast(Object obj) {
             return fieldType.cast(obj);
         }
         @Override
         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
-            return new Accessor(mt, lf, member, fieldOffset);
+            return new Accessor(mt, lf, member, crackable, fieldOffset);
+        }
+        @Override
+        MethodHandle viewAsType(MethodType newType, boolean strict) {
+            assert viewAsTypeChecks(newType, strict);
+            return new Accessor(newType, form, member, false, fieldOffset);
         }
     }
 
     @ForceInline
     /*non-public*/

@@ -533,23 +571,28 @@
         private final Class<?> fieldType;
         private final Object   staticBase;
         private final long     staticOffset;
 
         private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
-                               Object staticBase, long staticOffset) {
-            super(mtype, form, member);
+                               boolean crackable, Object staticBase, long staticOffset) {
+            super(mtype, form, member, crackable);
             this.fieldType    = member.getFieldType();
             this.staticBase   = staticBase;
             this.staticOffset = staticOffset;
         }
 
         @Override Object checkCast(Object obj) {
             return fieldType.cast(obj);
         }
         @Override
         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
-            return new StaticAccessor(mt, lf, member, staticBase, staticOffset);
+            return new StaticAccessor(mt, lf, member, crackable, staticBase, staticOffset);
+        }
+        @Override
+        MethodHandle viewAsType(MethodType newType, boolean strict) {
+            assert viewAsTypeChecks(newType, strict);
+            return new StaticAccessor(newType, form, member, false, staticBase, staticOffset);
         }
     }
 
     @ForceInline
     /*non-public*/
< prev index next >