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

Print this page
rev 17253 : imported patch 8183131.patch
rev 17240 : Dump classes from LambdaFormBuilder is triggered using
MethodHandleStatics.DUMP_CLASS_FILES. Class names are
extended by the LF invoker name (which should be unique)
when debugging (dumping triggers debugging).
rev 17235 : Add support for Q-types to lambda forms
Note: support is optional, and can be enabled using the flag:
-Dvalhalla.enableValueLambdaForms=true

@@ -81,15 +81,32 @@
     }
 
     LambdaFormCodeBuilder builder;
     LambdaForm lambdaForm;
     MethodType invokerType;
+    int maxLocals;
+    int[] localsMap;
 
     LambdaFormBuilder(LambdaFormCodeBuilder builder, LambdaForm lambdaForm, MethodType invokerType) {
         this.builder = builder;
         this.lambdaForm = lambdaForm;
         this.invokerType = invokerType;
+        this.maxLocals = lambdaForm.names.length;
+        this.localsMap = computeLocalsMap(lambdaForm);
+    }
+
+    static int[] computeLocalsMap(LambdaForm lform) {
+        int localsMapSize = lform.names.length;
+        int[] localsMap = new int[localsMapSize+1]; // last entry of localsMap is count of allocated local slots
+        for (int i = 0, index = 0; i < localsMap.length; i++) {
+            localsMap[i] = index;
+            if (i < lform.names.length) {
+                BasicType type = lform.names[i].type();
+                index += type.basicTypeSlots();
+            }
+        }
+        return localsMap;
     }
 
     void generateLambdaFormBody() {
         // iterate over the form's names, generating bytecode instructions for each
         // start iterating at the first name following the arguments

@@ -97,11 +114,11 @@
         for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
             Name name = lambdaForm.names[i];
 
             if (onStack != null && onStack.type != V_TYPE) {
                 // non-void: actually assign
-                builder.store(fromBasicType(onStack.type), onStack.index());
+                builder.store(fromBasicType(onStack.type), localsMap[onStack.index()]);
             }
             onStack = name;  // unless otherwise modified below
             MemberName member = name.function.member();
             if (InvokerBytecodeGenerator.isStaticallyInvocable(member)) {
                 emitStaticInvoke(member, name);

@@ -127,11 +144,11 @@
         } else {
             LambdaForm.Name rn = lambdaForm.names[lambdaForm.result];
 
             // put return value on the stack if it is not already there
             if (rn != onStack) {
-                builder.load(lambdaForm.result);
+                builder.load(localsMap[lambdaForm.result]);
             }
 
             emitImplicitConversion(rtype, rclass, rn);
 
             // generate actual return statement

@@ -177,11 +194,11 @@
 
     private void emitReferenceCast(Class<?> cls, Object arg) {
         Name writeBack = null;  // local to write back result
         if (arg instanceof Name) {
             Name n = (Name) arg;
-            if (cls.isAssignableFrom(builder.typeOfLocal(n.index())))
+            if (cls.isAssignableFrom(builder.typeOfLocal(localsMap[n.index()])))
                 return;  // this cast was already performed
             if (lambdaForm.useCount(n) > 1) {
                 // This guy gets used more than once.
                 writeBack = n;
             }

@@ -197,11 +214,11 @@
                 builder.checkcast(Object[].class);
             else if (PROFILE_LEVEL > 0)
                 builder.checkcast(Object.class);
         }
         if (writeBack != null) {
-            builder.dup().astore(writeBack.index());
+            builder.dup().astore(localsMap[writeBack.index()]);
         }
     }
 
     /**
      * Emit an invoke for the given name, using the MemberName directly.

@@ -278,11 +295,11 @@
 
     private void emitPushArgument(Class<?> ptype, Object arg) {
         BasicType bptype = basicType(ptype);
         if (arg instanceof Name) {
             Name n = (Name) arg;
-            builder.load(fromBasicType(n.type), n.index());
+            builder.load(fromBasicType(n.type), localsMap[n.index()]);
             emitImplicitConversion(n.type, ptype, n);
         } else if ((arg == null || arg instanceof String) && bptype == L_TYPE) {
             builder.ldc(arg);
         } else {
             if (Wrapper.isWrapperType(arg.getClass()) && bptype != L_TYPE) {