changeset 49705:829d99f94b43 datum

hooking records to patterns
author vromero
date Fri, 06 Apr 2018 12:28:25 -0400
parents 43acbccddc7d
children 0547bb081005
files make/autoconf/spec.gmk.in src/java.base/share/classes/java/lang/compiler/Extractor.java src/java.base/share/classes/module-info.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.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 7 files changed, 119 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/make/autoconf/spec.gmk.in	Wed Apr 04 15:33:06 2018 -0400
+++ b/make/autoconf/spec.gmk.in	Fri Apr 06 12:28:25 2018 -0400
@@ -612,6 +612,7 @@
     --add-exports java.base/sun.reflect.annotation=jdk.compiler.interim \
     --add-exports java.base/jdk.internal.jmod=jdk.compiler.interim \
     --add-exports java.base/jdk.internal.misc=jdk.compiler.interim \
+    --add-exports java.base/sun.invoke.util=jdk.compiler.interim \
     #
 INTERIM_LANGTOOLS_MODULES_COMMA := $(strip $(subst $(SPACE),$(COMMA),$(strip \
     $(INTERIM_LANGTOOLS_MODULES))))
--- a/src/java.base/share/classes/java/lang/compiler/Extractor.java	Wed Apr 04 15:33:06 2018 -0400
+++ b/src/java.base/share/classes/java/lang/compiler/Extractor.java	Fri Apr 06 12:28:25 2018 -0400
@@ -267,6 +267,22 @@
      *
      * @param lookup ignored
      * @param constantName ignored
+     * @param constantType doc
+     * @param descriptor the descriptor method type
+     * @param components the {@code components} method handles
+     * @return a callsite
+     * @throws Throwable doc
+     */
+    public static CallSite makeLazyExtractor(MethodHandles.Lookup lookup, String constantName, MethodType constantType,
+                                             MethodType descriptor, MethodHandle... components) throws Throwable {
+        return new ConstantCallSite(MethodHandles.constant(Extractor.class, ofLazy(descriptor, components)));
+    }
+
+    /**
+     * Bootstrap for creating a lazy, partial, self-carrier {@linkplain Extractor} from components
+     *
+     * @param lookup ignored
+     * @param constantName ignored
      * @param constantType Must be {@code Extractor.class}
      * @param descriptor the descriptor method type
      * @param predicate predicate method handle, applied to target
@@ -348,23 +364,6 @@
     }
 
     /**
-     * Invokedynamic bootstrap for creating lazy extractors
-     *
-     * @param lookup ignored
-     * @param invocationName ignored
-     * @param invocationType ignored
-     * @param descriptor the extractor descriptor
-     * @param components the extractor components
-     * @return the extractor factory
-     * @throws Throwable if something went wrong
-     */
-
-    public static CallSite makeLazyExtractor(MethodHandles.Lookup lookup, String invocationName, MethodType invocationType,
-                                             MethodType descriptor, MethodHandle... components) throws Throwable {
-        return new ConstantCallSite(MethodHandles.constant(Extractor.class, ofLazy(descriptor, components)));
-    }
-
-    /**
      * Condy bootstrap for creating lazy extractors
      *
      * @param lookup ignored
--- a/src/java.base/share/classes/module-info.java	Wed Apr 04 15:33:06 2018 -0400
+++ b/src/java.base/share/classes/module-info.java	Fri Apr 06 12:28:25 2018 -0400
@@ -129,10 +129,11 @@
     exports javax.security.auth.x500;
     exports javax.security.cert;
 
-
     // additional qualified exports may be inserted at build time
     // see make/gensrc/GenModuleInfo.gmk
 
+    exports sun.invoke.util to
+        jdk.compiler;
     exports com.sun.security.ntlm to
         java.security.sasl;
     exports jdk.internal.jimage to
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Wed Apr 04 15:33:06 2018 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Apr 06 12:28:25 2018 -0400
@@ -214,6 +214,7 @@
     public final Type documentedType;
     public final Type elementTypeType;
     public final Type functionalInterfaceType;
+    public final Type extractorType;
 
     /** The symbol representing the length field of an array.
      */
@@ -550,6 +551,7 @@
         lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory");
         stringConcatFactory = enterClass("java.lang.invoke.StringConcatFactory");
         functionalInterfaceType = enterClass("java.lang.FunctionalInterface");
+        extractorType = enterClass("java.lang.compiler.Extractor");
 
         synthesizeEmptyInterfaceIfMissing(autoCloseableType);
         synthesizeEmptyInterfaceIfMissing(cloneableType);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Wed Apr 04 15:33:06 2018 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Fri Apr 06 12:28:25 2018 -0400
@@ -5156,7 +5156,7 @@
             append('>');
         }
 
-        private void assembleSig(List<Type> types) {
+        public void assembleSig(List<Type> types) {
             for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) {
                 assembleSig(ts.head);
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Apr 04 15:33:06 2018 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Apr 06 12:28:25 2018 -0400
@@ -25,6 +25,8 @@
 
 package com.sun.tools.javac.comp;
 
+import sun.invoke.util.BytecodeName;
+
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -2534,7 +2536,8 @@
                             recordToString(tree, vars, getterMethHandles),
                     generationSwitchSet.contains(GenerationSwitch.OLD_HASCODE) ?
                             recordOldHashCode(tree, vars):
-                            recordHashCode(tree, getterMethHandles)
+                            recordHashCode(tree, getterMethHandles),
+                    recordExtractor(tree, getterMethHandles)
             ));
         }
     }
@@ -2564,8 +2567,8 @@
                     syms.stringType,
                     new ArrayType(syms.methodHandleType, syms.arrayClass));
 
-            JCFieldAccess qualifier = makeIndyQualifier(
-                    tree, msym, staticArgTypes, staticArgsValues, bootstrapName);
+            JCFieldAccess qualifier = makeIndyQualifier(syms.objectMethodBuildersType,
+                    tree, msym, staticArgTypes, staticArgsValues, bootstrapName, false);
 
             VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
 
@@ -2597,7 +2600,9 @@
                     new ArrayType(syms.methodHandleType, syms.arrayClass));
 
             JCFieldAccess qualifier = makeIndyQualifier(
-                    tree, msym, staticArgTypes, staticArgsValues, bootstrapName);
+                    syms.objectMethodBuildersType, tree, msym,
+                    staticArgTypes, staticArgsValues, bootstrapName,
+                    false);
 
             VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
 
@@ -2609,6 +2614,84 @@
         }
     }
 
+    JCTree recordExtractor(JCClassDecl tree, Pool.MethodHandle[] getterMethHandles) {
+        make_at(tree.pos());
+        List<Type> fieldTypes = TreeInfo.types(TreeInfo.recordFields(tree));
+        String argsTypeSig = '(' + argsTypeSig(fieldTypes) + ')';
+        String extractorStr = BytecodeName.toBytecodeName("$pattern$" + tree.sym.name + "$" + argsTypeSig);
+        Name extractorName = names.fromString(extractorStr);
+        // public Extractor extractorName () { return ???; }
+        MethodType extractorMT = new MethodType(List.nil(), syms.extractorType, List.nil(), syms.methodClass);
+        MethodSymbol extractorSym = new MethodSymbol(
+                Flags.PUBLIC | Flags.RECORD | Flags.STATIC,
+                extractorName, extractorMT, tree.sym);
+        tree.sym.members().enter(extractorSym);
+
+        Name bootstrapName = names.makeLazyExtractor;
+        Object[] staticArgsValues = new Object[1 + getterMethHandles.length];
+        /** this method descriptor should have the same arguments as the record constructor and its
+         *  return type should be the same as the type of the record
+         */
+        MethodType mt = new MethodType(fieldTypes, tree.type, List.nil(), syms.methodClass);
+        staticArgsValues[0] = mt;
+        int index = 1;
+        for (Object mho : getterMethHandles) {
+            staticArgsValues[index] = mho;
+            index++;
+        }
+
+        List<Type> staticArgTypes = List.of(syms.methodTypeType,
+                new ArrayType(syms.methodHandleType, syms.arrayClass));
+        JCFieldAccess qualifier = makeIndyQualifier(
+                syms.extractorType, tree, extractorSym, staticArgTypes,
+                staticArgsValues, bootstrapName, true);
+
+        JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, List.nil());
+        proxyCall.type = qualifier.type;
+        return make.MethodDef(extractorSym, make.Block(0, List.of(make.Return(proxyCall))));
+    }
+
+    private String argsTypeSig(List<Type> typeList) {
+        LowerSignatureGenerator sg = new LowerSignatureGenerator();
+        sg.assembleSig(typeList);
+        return sg.toString();
+    }
+
+    /**
+     * Signature Generation
+     */
+    private class LowerSignatureGenerator extends Types.SignatureGenerator {
+
+        /**
+         * An output buffer for type signatures.
+         */
+        StringBuilder sb = new StringBuilder();
+
+        LowerSignatureGenerator() {
+            super(types);
+        }
+
+        @Override
+        protected void append(char ch) {
+            sb.append(ch);
+        }
+
+        @Override
+        protected void append(byte[] ba) {
+            sb.append(new String(ba));
+        }
+
+        @Override
+        protected void append(Name name) {
+            sb.append(name.toString());
+        }
+
+        @Override
+        public String toString() {
+            return sb.toString();
+        }
+    }
+
     JCTree recordEquals(JCClassDecl tree, Pool.MethodHandle[] getterMethHandles) {
         make_at(tree.pos());
         MethodSymbol msym = lookupMethod(tree.pos(),
@@ -2630,7 +2713,8 @@
                     new ArrayType(syms.methodHandleType, syms.arrayClass));
 
             JCFieldAccess qualifier = makeIndyQualifier(
-                    tree, msym, staticArgTypes, staticArgsValues, bootstrapName);
+                    syms.objectMethodBuildersType, tree, msym,
+                    staticArgTypes, staticArgsValues, bootstrapName, false);
 
             VarSymbol o = msym.params.head;
             o.adr = 0;
@@ -2645,21 +2729,23 @@
     }
 
     JCFieldAccess makeIndyQualifier(
+            Type site,
             JCClassDecl tree,
             MethodSymbol msym,
             List<Type> staticArgTypes,
             Object[] staticArgValues,
-            Name bootstrapName) {
+            Name bootstrapName,
+            boolean isStatic) {
         List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
                 syms.stringType,
                 syms.methodTypeType).appendList(staticArgTypes);
 
-        Symbol bsm = rs.resolveInternalMethod(tree.pos(), attrEnv, syms.objectMethodBuildersType,
+        Symbol bsm = rs.resolveInternalMethod(tree.pos(), attrEnv, site,
                 bootstrapName, bsm_staticArgs, List.nil());
 
         MethodType indyType = msym.type.asMethodType();
         indyType = new MethodType(
-                indyType.argtypes.prepend(tree.sym.type),
+                isStatic ? List.nil() : indyType.argtypes.prepend(tree.sym.type),
                 indyType.restype,
                 indyType.thrown,
                 syms.methodClass
@@ -2670,7 +2756,7 @@
                 (MethodSymbol)bsm,
                 indyType,
                 staticArgValues);
-        JCFieldAccess qualifier = make.Select(make.QualIdent(syms.objectMethodBuildersType.tsym), bootstrapName);
+        JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bootstrapName);
         qualifier.sym = dynSym;
         qualifier.type = msym.type.asMethodType().restype;
         return qualifier;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Wed Apr 04 15:33:06 2018 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Fri Apr 06 12:28:25 2018 -0400
@@ -216,6 +216,7 @@
     public final Name where;
     public final Name guard;
     public final Name non;
+    public final Name makeLazyExtractor;
 
     public final Name.Table table;
 
@@ -389,6 +390,7 @@
         where = fromString("where");
         guard = fromString("$guard");
         non = fromString("non");
+        makeLazyExtractor = fromString("makeLazyExtractor");
     }
 
     protected Name.Table createTable(Options options) {