--- old/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java 2017-07-07 19:24:33.000000000 +0300 +++ new/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java 2017-07-07 19:24:33.000000000 +0300 @@ -387,6 +387,14 @@ 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; @@ -447,7 +455,9 @@ 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()); @@ -458,7 +468,22 @@ buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress); newBaseAddress = oldBaseAddress.withConstraint(newData); buf.renameParameter(0, newBaseAddress); - buf.replaceParameterByNewExpression(pos, new Name(getter, 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);