changeset 414:c73fecb5e075

meth-lazy: add stronger typing to field accessor base pointers; constructor bug fix
author jrose
date Tue, 17 Jul 2012 17:03:38 -0700
parents 72d2a3526502
children b6a3c70ad80a
files meth-lazy-7023639.bmh.patch
diffstat 1 files changed, 62 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/meth-lazy-7023639.bmh.patch	Tue Jul 17 16:02:05 2012 -0700
+++ b/meth-lazy-7023639.bmh.patch	Tue Jul 17 17:03:38 2012 -0700
@@ -1048,7 +1048,7 @@
 diff --git a/src/share/classes/java/lang/invoke/DirectMethodHandle.java b/src/share/classes/java/lang/invoke/DirectMethodHandle.java
 --- a/src/share/classes/java/lang/invoke/DirectMethodHandle.java
 +++ b/src/share/classes/java/lang/invoke/DirectMethodHandle.java
-@@ -31,20 +31,25 @@
+@@ -31,20 +31,26 @@
  import sun.invoke.util.VerifyAccess;
  import static java.lang.invoke.MethodHandleNatives.Constants.*;
  import static java.lang.invoke.LambdaForm.*;
@@ -1056,6 +1056,7 @@
 +import static java.lang.invoke.MethodHandleStatics.*;
  import java.lang.ref.WeakReference;
 +import java.lang.reflect.Field;
++import java.util.Objects;
  import sun.invoke.util.ValueConversions;
 +import sun.invoke.util.VerifyType;
 +import sun.invoke.util.Wrapper;
@@ -1077,7 +1078,7 @@
          if (!member.isResolved())  throw new InternalError();
          this.member = member;
      }
-@@ -52,24 +57,52 @@
+@@ -52,24 +58,54 @@
      // Factory methods:
  
      static DirectMethodHandle make(Class<?> receiver, MemberName member) {
@@ -1124,7 +1125,9 @@
 +        assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
 +        MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
 +        LambdaForm lform = preparedLambdaForm(ctor);
-+        return new Constructor(mtype, lform, ctor, ctor.asSpecial(), instanceClass);
++        MemberName init = ctor.asSpecial();
++        assert(init.getMethodType().returnType() == void.class);
++        return new Constructor(mtype, lform, ctor, init, instanceClass);
 +    }
  
      @Override
@@ -1134,7 +1137,7 @@
      }
  
      @Override
-@@ -116,7 +149,7 @@
+@@ -116,7 +152,7 @@
                  MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial);
                  concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass);
                  if (concrete != null)
@@ -1143,7 +1146,7 @@
                  break;
              }
          }
-@@ -128,65 +161,115 @@
+@@ -128,65 +164,117 @@
       * Cache and share this structure among all methods with
       * the same basicType and refKind.
       */
@@ -1217,7 +1220,9 @@
          }
          MethodType mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
 +        if (doesAlloc)
-+            mtypeWithArg = mtypeWithArg.insertParameterTypes(0, Object.class);  // insert newly allocated obj
++            mtypeWithArg = mtypeWithArg
++                    .insertParameterTypes(0, Object.class)  // insert newly allocated obj
++                    .changeReturnType(void.class);          // <init> returns void
          MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
          try {
              linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
@@ -1286,7 +1291,7 @@
      }
  
      /*non-public*/ static
-@@ -213,26 +296,19 @@
+@@ -213,26 +301,19 @@
              VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
              // It is a system class.  It is probably in the process of
              // being initialized, but we will help it along just to be safe.
@@ -1318,7 +1323,7 @@
                  // If the previous call didn't block, this can happen.
                  // We are executing inside <clinit>.
                  return new WeakReference<>(Thread.currentThread());
-@@ -241,29 +317,16 @@
+@@ -241,29 +322,16 @@
          static final EnsureInitialized INSTANCE = new EnsureInitialized();
      }
  
@@ -1357,7 +1362,7 @@
          Class<?> defc = member.getDeclaringClass();
          WeakReference<Thread> ref = EnsureInitialized.INSTANCE.get(defc);
          if (ref == null) {
-@@ -273,65 +336,304 @@
+@@ -273,65 +341,321 @@
          // Somebody may still be running defc.<clinit>.
          if (clinitThread == Thread.currentThread()) {
              // If anybody is running defc.<clinit>, it is this thread.
@@ -1419,13 +1424,15 @@
 +
 +    /** This subclass handles non-static field references. */
 +    static class Accessor extends DirectMethodHandle {
-+        final private Class<?> fieldType;
-+        final private int objectOffset;
++        final Class<?> fieldType;
++        final Class<?> fieldHolder;
++        final int      fieldOffset;
 +        private Accessor(MethodType mtype, LambdaForm form, MemberName member,
-+                         int objectOffset) {
++                         int fieldOffset) {
 +            super(mtype, form, member);
-+            this.fieldType    = member.getFieldType();
-+            this.objectOffset = objectOffset;
++            this.fieldType   = member.getFieldType();
++            this.fieldHolder = member.getDeclaringClass();
++            this.fieldOffset = fieldOffset;
 +        }
 +
 +        @Override Object checkCast(Object obj) {
@@ -1434,10 +1441,21 @@
 +    }
 +
 +    @ForceInline
-+    /*non-public*/ static long objectOffset(Object accessorObj) {
++    /*non-public*/ static long fieldOffset(Object accessorObj) {
 +        // Note: We return a long because that is what Unsafe.getObject likes.
 +        // We store a plain int because it is more compact.
-+        return ((Accessor)accessorObj).objectOffset;
++        return ((Accessor)accessorObj).fieldOffset;
++    }
++
++    @ForceInline
++    /*non-public*/ static Object fieldHolder(Object accessorObj) {
++        return ((Accessor)accessorObj).fieldHolder;
++    }
++
++    @ForceInline
++    /*non-public*/ static Object checkBase(Object obj, Object fieldHolderObj) {
++        Objects.requireNonNull(obj);
++        return ((Class<?>)fieldHolderObj).cast(obj);
 +    }
 +
 +    /** This subclass handles static field references. */
@@ -1460,6 +1478,12 @@
 +    }
 +
 +    @ForceInline
++    /*non-public*/ static Object nullCheck(Object obj) {
++        obj.getClass();
++        return obj;
++    }
++
++    @ForceInline
 +    /*non-public*/ static Object staticBase(Object accessorObj) {
 +        return ((StaticAccessor)accessorObj).staticBase;
 +    }
@@ -1470,12 +1494,6 @@
 +    }
 +
 +    @ForceInline
-+    /*non-public*/ static Object nullCheck(Object obj) {
-+        obj.getClass();
-+        return obj;
-+    }
-+
-+    @ForceInline
 +    /*non-public*/ static Object checkCast(Object mh, Object obj) {
 +        return ((DirectMethodHandle) mh).checkCast(obj);
 +    }
@@ -1595,51 +1613,53 @@
 +        // if this is for write access, the value to be written is stored at this index:
 +        final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
 +        int nameCursor = ARG_LIMIT;
-+        final int NPE_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
++        final int F_HOLDER  = nameCursor++;  // Either static base or field holder.
++        final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
++        final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
 +        final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
-+        final int CAST_1    = (needsCast && !isGetter ? nameCursor++ : -1);
-+        final int F_OFFSET  = nameCursor++;
-+        final int ST_BASE   = (isStatic ?  nameCursor++ : -1);
++        final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
 +        final int LINKER_CALL = nameCursor++;
-+        final int CAST_2    = (needsCast && isGetter ? nameCursor++ : -1);
++        final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
 +        final int RESULT    = nameCursor-1;  // either the call or the cast
 +        Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
 +        if (needsInit)
 +            names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]);
 +        if (needsCast && !isGetter)
-+            names[CAST_1] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
++            names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
 +        Object[] outArgs = new Object[1 + linkerType.parameterCount()];
 +        assert(outArgs.length == (isGetter ? 3 : 4));
 +        outArgs[0] = UNSAFE;
 +        if (isStatic) {
-+            outArgs[1] = names[ST_BASE]   = new Name(NF_staticBase, names[DMH_THIS]);
++            outArgs[1] = names[F_HOLDER]  = new Name(NF_staticBase, names[DMH_THIS]);
 +            outArgs[2] = names[F_OFFSET]  = new Name(NF_staticOffset, names[DMH_THIS]);
 +        } else {
-+            outArgs[1] = names[NPE_CHECK] = new Name(NF_nullCheck, names[OBJ_BASE]);
-+            outArgs[2] = names[F_OFFSET]  = new Name(NF_objectOffset, names[DMH_THIS]);
++            names[F_HOLDER]               = new Name(NF_fieldHolder, names[DMH_THIS]);
++            outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE], names[F_HOLDER]);
++            outArgs[2] = names[F_OFFSET]  = new Name(NF_fieldOffset, names[DMH_THIS]);
 +        }
 +        if (!isGetter) {
-+            outArgs[3] = (needsCast ? names[CAST_1] : names[SET_VALUE]);
++            outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 +        }
 +        for (Object a : outArgs)  assert(a != null);
 +        names[LINKER_CALL] = new Name(linker, outArgs);
 +        if (needsCast && isGetter)
-+            names[CAST_2] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
++            names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
 +        for (Name n : names)  assert(n != null);
 +        String lambdaName = linkerName;  // significant only for debugging
 +        if (needsCast)  lambdaName += "Cast";
 +        if (needsInit)  lambdaName += "Init";
-+        return new LambdaForm(lambdaName, ARG_LIMIT, names);
++        return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT);
 +    }
 +
 +    private static final NamedFunction
 +            NF_internalMemberName,
 +            NF_internalMemberNameEnsureInit,
 +            NF_ensureInitialized,
++            NF_fieldHolder,
++            NF_fieldOffset,
++            NF_checkBase,
 +            NF_staticBase,
 +            NF_staticOffset,
-+            NF_nullCheck,
-+            NF_objectOffset,
 +            NF_checkCast,
 +            NF_allocateInstance,
 +            NF_constructorMethod;
@@ -1659,14 +1679,16 @@
 +                    .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
 +                NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
 +                    .getDeclaredMethod("ensureInitialized", Object.class)),
++                NF_fieldHolder = new NamedFunction(DirectMethodHandle.class
++                    .getDeclaredMethod("fieldHolder", Object.class)),
++                NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
++                    .getDeclaredMethod("fieldOffset", Object.class)),
++                NF_checkBase = new NamedFunction(DirectMethodHandle.class
++                    .getDeclaredMethod("checkBase", Object.class, Object.class)),
 +                NF_staticBase = new NamedFunction(DirectMethodHandle.class
 +                    .getDeclaredMethod("staticBase", Object.class)),
 +                NF_staticOffset = new NamedFunction(DirectMethodHandle.class
 +                    .getDeclaredMethod("staticOffset", Object.class)),
-+                NF_nullCheck = new NamedFunction(DirectMethodHandle.class
-+                    .getDeclaredMethod("nullCheck", Object.class)),
-+                NF_objectOffset = new NamedFunction(DirectMethodHandle.class
-+                    .getDeclaredMethod("objectOffset", Object.class)),
 +                NF_checkCast = new NamedFunction(DirectMethodHandle.class
 +                    .getDeclaredMethod("checkCast", Object.class, Object.class)),
 +                NF_allocateInstance = new NamedFunction(DirectMethodHandle.class