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,95 **** --- 81,112 ---- } 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,107 **** 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()); } onStack = name; // unless otherwise modified below MemberName member = name.function.member(); if (InvokerBytecodeGenerator.isStaticallyInvocable(member)) { emitStaticInvoke(member, name); --- 114,124 ---- 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), localsMap[onStack.index()]); } onStack = name; // unless otherwise modified below MemberName member = name.function.member(); if (InvokerBytecodeGenerator.isStaticallyInvocable(member)) { emitStaticInvoke(member, name);
*** 127,137 **** } 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); } emitImplicitConversion(rtype, rclass, rn); // generate actual return statement --- 144,154 ---- } 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(localsMap[lambdaForm.result]); } emitImplicitConversion(rtype, rclass, rn); // generate actual return statement
*** 177,187 **** 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()))) return; // this cast was already performed if (lambdaForm.useCount(n) > 1) { // This guy gets used more than once. writeBack = n; } --- 194,204 ---- 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(localsMap[n.index()]))) return; // this cast was already performed if (lambdaForm.useCount(n) > 1) { // This guy gets used more than once. writeBack = n; }
*** 197,207 **** builder.checkcast(Object[].class); else if (PROFILE_LEVEL > 0) builder.checkcast(Object.class); } if (writeBack != null) { ! builder.dup().astore(writeBack.index()); } } /** * Emit an invoke for the given name, using the MemberName directly. --- 214,224 ---- builder.checkcast(Object[].class); else if (PROFILE_LEVEL > 0) builder.checkcast(Object.class); } if (writeBack != null) { ! builder.dup().astore(localsMap[writeBack.index()]); } } /** * Emit an invoke for the given name, using the MemberName directly.
*** 278,288 **** 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()); 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) { --- 295,305 ---- private void emitPushArgument(Class<?> ptype, Object arg) { BasicType bptype = basicType(ptype); if (arg instanceof Name) { Name n = (Name) arg; ! 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) {