jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
changeset 29020 9f6d43586ccb
parent 29019 a859b806c8bd
child 30343 bf75edd66df0
child 29986 97167d851fc4
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Jan 29 10:27:30 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Jan 29 10:27:30 2015 -0800
@@ -56,9 +56,11 @@
     private static final String OBJ     = "java/lang/Object";
     private static final String OBJARY  = "[Ljava/lang/Object;";
 
+    private static final String MH_SIG  = "L" + MH + ";";
     private static final String LF_SIG  = "L" + LF + ";";
     private static final String LFN_SIG = "L" + LFN + ";";
     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 CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";";
 
     /** Name of its super class*/
@@ -616,6 +618,15 @@
         return g.loadMethod(g.generateCustomizedCodeBytes());
     }
 
+    /** 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
+        mv.visitInsn(Opcodes.DUP);
+        mv.visitVarInsn(Opcodes.ALOAD, localsMap[0]);
+        mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "assertSame", LLV_SIG, false);
+        return true;
+    }
+
     /**
      * Generate an invoker method for the passed {@link LambdaForm}.
      */
@@ -635,6 +646,17 @@
             mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
         }
 
+        if (lambdaForm.customized != null) {
+            // 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.
+            mv.visitLdcInsn(constantPlaceholder(lambdaForm.customized));
+            mv.visitTypeInsn(Opcodes.CHECKCAST, MH);
+            assert(checkActualReceiver()); // expects MethodHandle on top of the stack
+            mv.visitVarInsn(Opcodes.ASTORE, localsMap[0]);
+        }
+
         // iterate over the form's names, generating bytecode instructions for each
         // start iterating at the first name following the arguments
         Name onStack = null;