< prev index next >
src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java
Print this page
@@ -63,10 +63,11 @@
private static final String OBJ = "java/lang/Object";
private static final String CLASS_PREFIX = "java/lang/invoke/LambdaForm$Value$";
private static final String DEFAULT_CLASS = "MH";
private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";";
+ private static final String LLV_SIG = "(L" + OBJ + ";L" + OBJ + ";)V";
private static final String MH = "java/lang/invoke/MethodHandle";
private static final String MHARY2 = "[[L" + MH + ";";
static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
@@ -92,11 +93,29 @@
LambdaFormBuilder(LambdaFormCodeBuilder builder, LambdaForm lambdaForm) {
this.builder = builder;
this.lambdaForm = lambdaForm;
}
+ /** Generates code to check that actual receiver and LambdaForm matches */
+ private boolean checkActualReceiver() {
+ // Expects MethodHandle on the stack and actual receiver MethodHandle in slot #0
+ builder.dup().load(0).invokestatic(MethodHandleImpl.class, "assertSame", LLV_SIG, false);
+ return true;
+ }
+
void generateLambdaFormBody() {
+ if (lambdaForm.customized != null && MethodHandleBuilder.ENABLE_POOL_PATCHES) {
+ // Since LambdaForm is customized for a particular MethodHandle, it's safe to substitute
+ // receiver MethodHandle (at slot #0) with an embedded constant and use it instead.
+ // It enables more efficient code generation in some situations, since embedded constants
+ // are compile-time constants for JIT compiler.
+ builder.ldc(lambdaForm.customized)
+ .checkcast(MethodHandle.class);
+ assert(checkActualReceiver()); // generates runtime check
+ builder.store(0);
+ }
+
// iterate over the form's names, generating bytecode instructions for each
// start iterating at the first name following the arguments
Name onStack = null;
for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
Name name = lambdaForm.names[i];
< prev index next >