changeset 14773:d41609429f2e

8072844: Use more efficient LambdaForm type representation Reviewed-by: sundar, redestad
author mhaupt
date Thu, 03 Dec 2015 15:34:39 +0100
parents 7cc5e8fd62c9
children 4d010a9bd0d9
files src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java src/java.base/share/classes/java/lang/invoke/LambdaForm.java
diffstat 2 files changed, 34 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Wed Dec 02 19:46:46 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Dec 03 15:34:39 2015 +0100
@@ -1276,10 +1276,10 @@
     /**
      * Generate bytecode for a LambdaForm.vmentry which calls interpretWithArguments.
      */
-    static MemberName generateLambdaFormInterpreterEntryPoint(String sig) {
-        assert(isValidSignature(sig));
-        String name = "interpret_"+signatureReturn(sig).basicTypeChar();
-        MethodType type = signatureType(sig);  // sig includes leading argument
+    static MemberName generateLambdaFormInterpreterEntryPoint(MethodType mt) {
+        assert(isValidSignature(basicTypeSignature(mt)));
+        String name = "interpret_"+basicTypeChar(mt.returnType());
+        MethodType type = mt;  // includes leading argument
         type = type.changeParameterType(0, MethodHandle.class);
         InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", name, type);
         return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes());
--- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Wed Dec 02 19:46:46 2015 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java	Thu Dec 03 15:34:39 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -288,32 +288,28 @@
         return names;
     }
 
-    private LambdaForm(String sig) {
+    private LambdaForm(MethodType mt) {
         // Make a blank lambda form, which returns a constant zero or null.
         // It is used as a template for managing the invocation of similar forms that are non-empty.
         // Called only from getPreparedForm.
-        assert(isValidSignature(sig));
-        this.arity = signatureArity(sig);
-        this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity);
-        this.names = buildEmptyNames(arity, sig);
+        this.arity = mt.parameterCount();
+        this.result = (mt.returnType() == void.class || mt.returnType() == Void.class) ? -1 : arity;
+        this.names = buildEmptyNames(arity, mt, result == -1);
         this.debugName = "LF.zero";
         this.forceInline = true;
         this.customized = null;
         assert(nameRefsAreLegal());
         assert(isEmpty());
+        String sig = null;
+        assert(isValidSignature(sig = basicTypeSignature()));
         assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
     }
 
-    private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
-        assert(isValidSignature(basicTypeSignature));
-        int resultPos = arity + 1;  // skip '_'
-        if (arity < 0 || basicTypeSignature.length() != resultPos+1)
-            throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
-        int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1);
-        Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
-        for (int i = 0; i < numRes; i++) {
-            Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i))));
-            names[arity + i] = zero.newIndex(arity + i);
+    private static Name[] buildEmptyNames(int arity, MethodType mt, boolean isVoid) {
+        Name[] names = arguments(isVoid ? 0 : 1, mt);
+        if (!isVoid) {
+            Name zero = new Name(constantZero(basicType(mt.returnType())));
+            names[arity] = zero.newIndex(arity);
         }
         return names;
     }
@@ -520,8 +516,13 @@
 
     /** Return the method type corresponding to my basic type signature. */
     MethodType methodType() {
-        return signatureType(basicTypeSignature());
+        Class<?>[] ptypes = new Class<?>[arity];
+        for (int i = 0; i < arity; ++i) {
+            ptypes[i] = parameterType(i).btClass;
+        }
+        return MethodType.methodType(returnType().btClass, ptypes);
     }
+
     /** Return ABC_Z, where the ABC are parameter type characters, and Z is the return type character. */
     final String basicTypeSignature() {
         StringBuilder buf = new StringBuilder(arity() + 3);
@@ -633,7 +634,14 @@
             // already prepared (e.g., a primitive DMH invoker form)
             return;
         }
-        LambdaForm prep = getPreparedForm(basicTypeSignature());
+        MethodType mtype = methodType();
+        LambdaForm prep = mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET);
+        if (prep == null) {
+            assert (isValidSignature(basicTypeSignature()));
+            prep = new LambdaForm(mtype);
+            prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(mtype);
+            prep = mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep);
+        }
         this.vmentry = prep.vmentry;
         // TO DO: Maybe add invokeGeneric, invokeWithArguments
     }
@@ -664,9 +672,10 @@
             if (mt.parameterCount() > 0 &&
                 mt.parameterType(0) == MethodHandle.class &&
                 m.getName().startsWith("interpret_")) {
-                String sig = basicTypeSignature(mt);
-                assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
-                LambdaForm form = new LambdaForm(sig);
+                String sig = null;
+                assert((sig = basicTypeSignature(mt)) != null &&
+                        m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
+                LambdaForm form = new LambdaForm(mt);
                 form.vmentry = m;
                 form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
             }
@@ -702,15 +711,6 @@
         assert(returnTypesMatch(sig, av, res));
         return res;
     }
-    private static LambdaForm getPreparedForm(String sig) {
-        MethodType mtype = signatureType(sig);
-        LambdaForm prep =  mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET);
-        if (prep != null)  return prep;
-        assert(isValidSignature(sig));
-        prep = new LambdaForm(sig);
-        prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig);
-        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep);
-    }
 
     // The next few routines are called only from assert expressions
     // They verify that the built-in invokers process the correct raw data types.
@@ -1558,13 +1558,6 @@
         if (n.constraint != null)  return n;
         return argument(n.index, n.type);
     }
-    static Name[] arguments(int extra, String types) {
-        int length = types.length();
-        Name[] names = new Name[length + extra];
-        for (int i = 0; i < length; i++)
-            names[i] = argument(i, basicType(types.charAt(i)));
-        return names;
-    }
     static Name[] arguments(int extra, MethodType types) {
         int length = types.parameterCount();
         Name[] names = new Name[length + extra];