comparison 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
comparison
equal deleted inserted replaced
18313:6b8bceeecb30 18314:3cc813ce3cea
147 setTargetMethod(uniqueConcreteMethod); 147 setTargetMethod(uniqueConcreteMethod);
148 return; 148 return;
149 } 149 }
150 } 150 }
151 } 151 }
152 // try to turn a interface call into a virtual call
152 ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass(); 153 ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass();
153 /* 154 /*
154 * We need to check the invoke kind to avoid recursive simplification for default 155 * We need to check the invoke kind to avoid recursive simplification for virtual
155 * methods calls. 156 * interface methods calls.
156 */ 157 */
157 if (declaredReceiverType.isInterface() && !invokeKind().equals(InvokeKind.Virtual)) { 158 if (declaredReceiverType.isInterface() && !invokeKind().equals(InvokeKind.Virtual)) {
158 ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor(); 159 ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor();
159 if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) { 160 if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) {
160 ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType(), true); 161 ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType(), true);
161 if (singleImplementorMethod != null) { 162 if (singleImplementorMethod != null) {
163 assert graph().getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal() : "Graph already fixed!";
164 /**
165 * We have an invoke on an interface with a single implementor. We can
166 * replace this with an invoke virtual.
167 *
168 * To do so we need to ensure two properties: 1) the receiver must implement
169 * the interface (declaredReceiverType). The verifier does not prove this so
170 * we need a dynamic check. 2) we need to ensure that there is still only
171 * one implementor of this interface, i.e. that we are calling the right
172 * method. We could do this with an assumption but as we need an instanceof
173 * check anyway we can verify both properties by checking of the receiver is
174 * an instance of the single implementor.
175 */
162 LogicNode condition = graph().unique(InstanceOfNode.create(singleImplementor, receiver, getProfile())); 176 LogicNode condition = graph().unique(InstanceOfNode.create(singleImplementor, receiver, getProfile()));
163 assert graph().getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal() : "Graph already fixed!";
164 GuardNode guard = graph().unique( 177 GuardNode guard = graph().unique(
165 GuardNode.create(condition, BeginNode.prevBegin(invoke().asNode()), DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, 178 GuardNode.create(condition, BeginNode.prevBegin(invoke().asNode()), DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile,
166 false, JavaConstant.NULL_OBJECT)); 179 false, JavaConstant.NULL_OBJECT));
167 PiNode piNode = graph().unique(PiNode.create(receiver, StampFactory.declared(singleImplementor), guard)); 180 PiNode piNode = graph().unique(PiNode.create(receiver, StampFactory.declared(singleImplementor), guard));
168 arguments().set(0, piNode); 181 arguments().set(0, piNode);