diff graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java @ 18314:3cc813ce3cea

MethodCallTargetNode: document the single implementor optimization.
author Josef Eisl <josef.eisl@jku.at>
date Mon, 10 Nov 2014 11:31:41 +0100
parents 6b8bceeecb30
children c7cd54360119
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Nov 06 12:40:28 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Mon Nov 10 11:31:41 2014 +0100
@@ -149,18 +149,31 @@
                     }
                 }
             }
+            // try to turn a interface call into a virtual call
             ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass();
             /*
-             * We need to check the invoke kind to avoid recursive simplification for default
-             * methods calls.
+             * We need to check the invoke kind to avoid recursive simplification for virtual
+             * interface methods calls.
              */
             if (declaredReceiverType.isInterface() && !invokeKind().equals(InvokeKind.Virtual)) {
                 ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor();
                 if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) {
                     ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType(), true);
                     if (singleImplementorMethod != null) {
+                        assert graph().getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal() : "Graph already fixed!";
+                        /**
+                         * We have an invoke on an interface with a single implementor. We can
+                         * replace this with an invoke virtual.
+                         *
+                         * To do so we need to ensure two properties: 1) the receiver must implement
+                         * the interface (declaredReceiverType). The verifier does not prove this so
+                         * we need a dynamic check. 2) we need to ensure that there is still only
+                         * one implementor of this interface, i.e. that we are calling the right
+                         * method. We could do this with an assumption but as we need an instanceof
+                         * check anyway we can verify both properties by checking of the receiver is
+                         * an instance of the single implementor.
+                         */
                         LogicNode condition = graph().unique(InstanceOfNode.create(singleImplementor, receiver, getProfile()));
-                        assert graph().getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal() : "Graph already fixed!";
                         GuardNode guard = graph().unique(
                                         GuardNode.create(condition, BeginNode.prevBegin(invoke().asNode()), DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile,
                                                         false, JavaConstant.NULL_OBJECT));