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) {