< prev index next >

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

Print this page

        

@@ -385,10 +385,18 @@
     }
     private BoundMethodHandle.SpeciesData newSpeciesData(BasicType type) {
         return oldSpeciesData().extendWith(type);
     }
 
+    BoundMethodHandle bindArgumentQ(BoundMethodHandle mh, int pos, Object value, MethodHandle unbox) {
+        assert(mh.speciesData() == oldSpeciesData());
+        BasicType bt = Q_TYPE;
+        MethodType type2 = bindArgumentType(mh, pos, bt);
+        LambdaForm form2 = bindArgumentForm(1+pos);
+        return mh.copyWithExtendL(type2, form2, value)
+                 .copyWithExtendL(type2, form2, unbox);
+    }
     BoundMethodHandle bindArgumentL(BoundMethodHandle mh, int pos, Object value) {
         assert(mh.speciesData() == oldSpeciesData());
         BasicType bt = L_TYPE;
         MethodType type2 = bindArgumentType(mh, pos, bt);
         LambdaForm form2 = bindArgumentForm(1+pos);

@@ -445,22 +453,39 @@
         }
         LambdaFormBuffer buf = buffer();
         buf.startEdit();
 
         BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
-        BoundMethodHandle.SpeciesData newData = newSpeciesData(lambdaForm.parameterType(pos));
+        BasicType ptype = lambdaForm.parameterType(pos);
+        BoundMethodHandle.SpeciesData newData = (ptype != Q_TYPE) ? newSpeciesData(ptype)
+                                                                  : oldData.extendWith(L_TYPE).extendWith(L_TYPE); // value + unbox MH
         Name oldBaseAddress = lambdaForm.parameter(0);  // BMH holding the values
         Name newBaseAddress;
         NamedFunction getter = newData.getterFunction(oldData.fieldCount());
 
         if (pos != 0) {
             // The newly created LF will run with a different BMH.
             // Switch over any pre-existing BMH field references to the new BMH class.
             buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
             newBaseAddress = oldBaseAddress.withConstraint(newData);
             buf.renameParameter(0, newBaseAddress);
+            if (ptype == Q_TYPE) {
+                // Q-types are stored in boxed form. Unboxing step is required.
+                int exprPos = lambdaForm.arity();
+                int UNBOX_MH      = exprPos++;
+                int BOXED_VALUE   = exprPos++;
+                int UNBOXED_VALUE = exprPos++;
+                NamedFunction unboxGetter = newData.getterFunction(oldData.fieldCount()+1);
+                buf.insertExpression(UNBOX_MH, new Name(unboxGetter, newBaseAddress));
+                buf.insertExpression(BOXED_VALUE, new Name(getter, newBaseAddress));
+                MethodType unboxInvokerType = MethodType.methodType(Q_TYPE.basicTypeClass(), L_TYPE.basicTypeClass());
+                Name unbox = new Name(unboxInvokerType, buf.name(UNBOX_MH), buf.name(BOXED_VALUE));
+                buf.insertExpression(UNBOXED_VALUE, unbox);
+                buf.replaceParameterByCopy(pos, UNBOXED_VALUE);
+            } else {
             buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress));
+            }
         } else {
             // cannot bind the MH arg itself, unless oldData is empty
             assert(oldData == BoundMethodHandle.SpeciesData.EMPTY);
             newBaseAddress = new Name(L_TYPE).withConstraint(newData);
             buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress));
< prev index next >