changeset 55381:abb07ff1dbe3 records-and-sealed

folding all bootstraps at ObjectMethodBuilders into one
author vromero
date Sat, 23 Mar 2019 20:59:47 -0400
parents ee1dea3bfa8f
children e752ba81c19d
files src/java.base/share/classes/java/lang/invoke/ObjectMethodBuilders.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
diffstat 4 files changed, 84 insertions(+), 139 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/invoke/ObjectMethodBuilders.java	Thu Mar 14 12:18:50 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/ObjectMethodBuilders.java	Sat Mar 23 20:59:47 2019 -0400
@@ -235,48 +235,43 @@
     }
 
     /**
-     * Bootstrap method to generate the {@code equals} method for a given data class
-     * @param lookup    the lookup
-     * @param invName   the name
-     * @param invType   the method type
-     * @param dataClass the data class
-     * @param getters   the list of getters
-     * @return a call site
+     * Bootstrap method to generate the {@code equals}, {@code hashCode}, and {@code toString} methods for a given data class
+     * @param lookup       the lookup
+     * @param methodName   the method name
+     * @param type         the method type
+     * @param theClass     the data class
+     * @param names        the list of field names joined into a string, separated by ";"
+     * @param getters      the list of getters
+     * @return a call site if invoked by and indy or a method handle if invoked by a condy
      * @throws Throwable if any exception is thrown during call site construction
      */
-    public static CallSite makeEquals(MethodHandles.Lookup lookup, String invName, MethodType invType,
-                                      Class<?> dataClass, MethodHandle... getters) throws Throwable {
-        return new ConstantCallSite(makeEquals(dataClass, List.of(getters)));
-    }
-
-    /**
-     * Bootstrap method to generate the {@code hashCode} method for a given data class
-     * @param lookup    the lookup
-     * @param invName   the name
-     * @param invType   the method type
-     * @param dataClass the data class
-     * @param getters   the list of getters
-     * @return a call site
-     * @throws Throwable if any exception is thrown during call site construction
-     */
-    public static CallSite makeHashCode(MethodHandles.Lookup lookup, String invName, MethodType invType,
-                                        Class<?> dataClass, MethodHandle... getters) throws Throwable {
-        return new ConstantCallSite(makeHashCode(dataClass, List.of(getters)));
-    }
-
-    /**
-     * Bootstrap method to generate the {@code toString} method for a given data class
-     * @param lookup    the lookup
-     * @param invName   the name
-     * @param invType   the method type
-     * @param dataClass the data class
-     * @param names     the list of field names joined into a string, separated by ";"
-     * @param getters   the list of getters
-     * @return a call site
-     * @throws Throwable if any exception is thrown during call site construction
-     */
-    public static CallSite makeToString(MethodHandles.Lookup lookup, String invName, MethodType invType,
-                                        Class<?> dataClass, String names, MethodHandle... getters) throws Throwable {
-        return new ConstantCallSite(makeToString(dataClass, List.of(getters), List.of(names.split(";"))));
+    public static Object bootstrap(MethodHandles.Lookup lookup, String methodName, TypeDescriptor type,
+                                   Class<?> theClass, String names, MethodHandle... getters) throws Throwable {
+        MethodType methodType;
+        if (type instanceof MethodType)
+            methodType = (MethodType) type;
+        else {
+            methodType = null;
+            if (!MethodHandle.class.equals(type))
+                throw new IllegalArgumentException(type.toString());
+        }
+        List<MethodHandle> getterList = List.of(getters);
+        MethodHandle handle;
+        switch (methodName) {
+            case "equals":
+                // validate method type
+                handle = makeEquals(theClass, getterList);
+                return methodType != null ? new ConstantCallSite(handle) : handle;
+            case "hashCode":
+                // validate method type
+                handle = makeHashCode(theClass, getterList);
+                return methodType != null ? new ConstantCallSite(handle) : handle;
+            case "toString":
+                // validate method type
+                handle = makeToString(theClass, getterList, List.of(names.split(";")));
+                return methodType != null ? new ConstantCallSite(handle) : handle;
+            default:
+                throw new IllegalArgumentException(methodName);
+        }
     }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Mar 14 12:18:50 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Sat Mar 23 20:59:47 2019 -0400
@@ -217,6 +217,7 @@
     public final Type elementTypeType;
     public final Type functionalInterfaceType;
     public final Type extractorType;
+    public final Type typeDescriptorType;
 
     /** The symbol representing the length field of an array.
      */
@@ -575,6 +576,7 @@
         stringConcatFactory = enterClass("java.lang.invoke.StringConcatFactory");
         functionalInterfaceType = enterClass("java.lang.FunctionalInterface");
         extractorType = enterClass("java.lang.compiler.Extractor");
+        typeDescriptorType = enterClass("java.lang.invoke.TypeDescriptor");
 
         synthesizeEmptyInterfaceIfMissing(autoCloseableType);
         synthesizeEmptyInterfaceIfMissing(cloneableType);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Mar 14 12:18:50 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Sat Mar 23 20:59:47 2019 -0400
@@ -2481,23 +2481,23 @@
 
         tree.defs = tree.defs.appendList(accessors(tree));
         tree.defs = tree.defs.appendList(List.of(
-                recordEquals(tree, getterMethHandles),
-                recordToString(tree, vars, getterMethHandles),
-                recordHashCode(tree, getterMethHandles),
+                generateRecordMethod(tree, names.toString, vars, getterMethHandles),
+                generateRecordMethod(tree, names.hashCode, vars, getterMethHandles),
+                generateRecordMethod(tree, names.equals, vars, getterMethHandles),
                 recordExtractor(tree, getterMethHandles),
                 recordReadResolve(tree)
         ));
     }
 
-    JCTree recordToString(JCClassDecl tree, List<VarSymbol> vars, Pool.MethodHandle[] getterMethHandles) {
+    JCTree generateRecordMethod(JCClassDecl tree, Name name, List<VarSymbol> vars, Pool.MethodHandle[] getterMethHandles) {
         make_at(tree.pos());
-
+        boolean isEquals = name == names.equals;
         MethodSymbol msym = lookupMethod(tree.pos(),
-                         names.toString,
-                         tree.sym.type,
-                         List.nil());
+                name,
+                tree.sym.type,
+                isEquals ? List.of(syms.objectType) : List.nil());
         if ((msym.flags() & RECORD) != 0) {
-            Name bootstrapName = names.makeToString;
+            Name bootstrapName = names.bootstrap;
             Object[] staticArgsValues = new Object[2 + getterMethHandles.length];
             staticArgsValues[0] = tree.sym;
             String concatNames = vars.stream()
@@ -2514,46 +2514,22 @@
                     syms.stringType,
                     new ArrayType(syms.methodHandleType, syms.arrayClass));
 
-            JCFieldAccess qualifier = makeIndyQualifier(syms.objectMethodBuildersType,
-                    tree, msym, staticArgTypes, staticArgsValues, bootstrapName, false);
+            JCFieldAccess qualifier = makeIndyQualifier(syms.objectMethodBuildersType, tree, msym,
+                    List.of(syms.methodHandleLookupType,
+                            syms.stringType,
+                            syms.typeDescriptorType).appendList(staticArgTypes),
+                    staticArgsValues, bootstrapName, name, false);
 
             VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
 
-            JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this)));
-            proxyCall.type = qualifier.type;
-            return make.MethodDef(msym, make.Block(0, List.of(make.Return(proxyCall))));
-        } else {
-            return make.Block(SYNTHETIC, List.nil());
-        }
-    }
-
-    JCTree recordHashCode(JCClassDecl tree, Pool.MethodHandle[] getterMethHandles) {
-        make_at(tree.pos());
-        MethodSymbol msym = lookupMethod(tree.pos(),
-                         names.hashCode,
-                         tree.sym.type,
-                         List.nil());
-        if ((msym.flags() & RECORD) != 0) {
-            Name bootstrapName = names.makeHashCode;
-            Object[] staticArgsValues = new Object[1 + getterMethHandles.length];
-            staticArgsValues[0] = tree.sym;
-            int index = 1;
-            for (Object mho : getterMethHandles) {
-                staticArgsValues[index] = mho;
-                index++;
+            JCMethodInvocation proxyCall;
+            if (!isEquals) {
+                proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this)));
+            } else {
+                VarSymbol o = msym.params.head;
+                o.adr = 0;
+                proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this), make.Ident(o)));
             }
-
-            List<Type> staticArgTypes = List.of(syms.classType,
-                    new ArrayType(syms.methodHandleType, syms.arrayClass));
-
-            JCFieldAccess qualifier = makeIndyQualifier(
-                    syms.objectMethodBuildersType, tree, msym,
-                    staticArgTypes, staticArgsValues, bootstrapName,
-                    false);
-
-            VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
-
-            JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this)));
             proxyCall.type = qualifier.type;
             return make.MethodDef(msym, make.Block(0, List.of(make.Return(proxyCall))));
         } else {
@@ -2589,9 +2565,11 @@
 
         List<Type> staticArgTypes = List.of(syms.methodTypeType,
                 new ArrayType(syms.methodHandleType, syms.arrayClass));
-        JCFieldAccess qualifier = makeIndyQualifier(
-                syms.extractorType, tree, extractorSym, staticArgTypes,
-                staticArgsValues, bootstrapName, true);
+        JCFieldAccess qualifier = makeIndyQualifier(syms.extractorType, tree, extractorSym,
+                List.of(syms.methodHandleLookupType,
+                        syms.stringType,
+                        syms.methodTypeType).appendList(staticArgTypes),
+                staticArgsValues, bootstrapName, bootstrapName, true);
 
         JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.nil());
         proxyCall.type = qualifier.type;
@@ -2656,42 +2634,19 @@
         }
     }
 
-    JCTree recordEquals(JCClassDecl tree, Pool.MethodHandle[] getterMethHandles) {
-        make_at(tree.pos());
-        MethodSymbol msym = lookupMethod(tree.pos(),
-                         names.equals,
-                         tree.sym.type,
-                         List.of(syms.objectType));
-
-        if ((msym.flags() & RECORD) != 0) {
-            Name bootstrapName = names.makeEquals;
-            Object[] staticArgsValues = new Object[1 + getterMethHandles.length];
-            staticArgsValues[0] = tree.sym;
-            int index = 1;
-            for (Object mho : getterMethHandles) {
-                staticArgsValues[index] = mho;
-                index++;
-            }
-
-            List<Type> staticArgTypes = List.of(syms.classType,
-                    new ArrayType(syms.methodHandleType, syms.arrayClass));
-
-            JCFieldAccess qualifier = makeIndyQualifier(
-                    syms.objectMethodBuildersType, tree, msym,
-                    staticArgTypes, staticArgsValues, bootstrapName, false);
-
-            VarSymbol o = msym.params.head;
-            o.adr = 0;
-            VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
-
-            JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this), make.Ident(o)));
-            proxyCall.type = qualifier.type;
-            return make.MethodDef(msym, make.Block(0, List.of(make.Return(proxyCall))));
-        } else {
-            return make.Block(SYNTHETIC, List.nil());
-        }
-    }
-
+    /**
+     * Creates an indy qualifier, helpful to be part of an indy invocation
+     * @param site                the site
+     * @param tree                a class declaration tree
+     * @param msym                the method symbol
+     * @param staticArgTypes      the static argument types
+     * @param staticArgValues     the static argument values
+     * @param bootstrapName       the bootstrap name to look for
+     * @param argName             normally bootstraps receives a method name as second argument, if you want that name
+     *                            to be different to that of the bootstrap name pass a different name here
+     * @param isStatic            is it static or not
+     * @return                    a field access tree
+     */
     JCFieldAccess makeIndyQualifier(
             Type site,
             JCClassDecl tree,
@@ -2699,13 +2654,10 @@
             List<Type> staticArgTypes,
             Object[] staticArgValues,
             Name bootstrapName,
+            Name argName,
             boolean isStatic) {
-        List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
-                syms.stringType,
-                syms.methodTypeType).appendList(staticArgTypes);
-
         Symbol bsm = rs.resolveInternalMethod(tree.pos(), attrEnv, site,
-                bootstrapName, bsm_staticArgs, List.nil());
+                bootstrapName, staticArgTypes, List.nil());
 
         MethodType indyType = msym.type.asMethodType();
         indyType = new MethodType(
@@ -2714,13 +2666,13 @@
                 indyType.thrown,
                 syms.methodClass
         );
-        DynamicMethodSymbol dynSym = new DynamicMethodSymbol(bootstrapName,
+        DynamicMethodSymbol dynSym = new DynamicMethodSymbol(argName,
                 syms.noSymbol,
                 ClassFile.REF_invokeStatic,
                 (MethodSymbol)bsm,
                 indyType,
                 staticArgValues);
-        JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bootstrapName);
+        JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), argName);
         qualifier.sym = dynSym;
         qualifier.type = msym.type.asMethodType().restype;
         return qualifier;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Thu Mar 14 12:18:50 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Sat Mar 23 20:59:47 2019 -0400
@@ -212,12 +212,10 @@
     public final Name makeConcat;
     public final Name makeConcatWithConstants;
 
+    // record related
     // members of java.lang.invoke.ObjectMethodBuilders
-    public final Name makeEquals;
-    public final Name makeHashCode;
-    public final Name makeToString;
+    public final Name bootstrap;
 
-    // record related
     public final Name record;
     public final Name where;
     public final Name non;
@@ -398,9 +396,7 @@
         makeConcat = fromString("makeConcat");
         makeConcatWithConstants = fromString("makeConcatWithConstants");
 
-        makeEquals = fromString("makeEquals");
-        makeHashCode = fromString("makeHashCode");
-        makeToString = fromString("makeToString");
+        bootstrap = fromString("bootstrap");
         record = fromString("record");
         where = fromString("where");
         non = fromString("non");