comparison graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java @ 19134:0b05bd821399

Factor the findSpecialCallTarget logic when canonicalizing MethodCallTarget nodes into a static method.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 04 Feb 2015 21:04:41 +0100
parents ec0733b5a90a
children 8ab925a6f724
comparison
equal deleted inserted replaced
19133:ce6f3cfbc7e0 19134:0b05bd821399
20 * or visit www.oracle.com if you need additional information or have any 20 * or visit www.oracle.com if you need additional information or have any
21 * questions. 21 * questions.
22 */ 22 */
23 package com.oracle.graal.nodes.java; 23 package com.oracle.graal.nodes.java;
24 24
25 import com.oracle.graal.api.code.*;
25 import com.oracle.graal.api.meta.*; 26 import com.oracle.graal.api.meta.*;
26 import com.oracle.graal.compiler.common.type.*; 27 import com.oracle.graal.compiler.common.type.*;
27 import com.oracle.graal.graph.*; 28 import com.oracle.graal.graph.*;
28 import com.oracle.graal.graph.spi.*; 29 import com.oracle.graal.graph.spi.*;
29 import com.oracle.graal.nodeinfo.*; 30 import com.oracle.graal.nodeinfo.*;
91 } else { 92 } else {
92 return super.toString(verbosity); 93 return super.toString(verbosity);
93 } 94 }
94 } 95 }
95 96
97 public static ResolvedJavaMethod findSpecialCallTarget(InvokeKind invokeKind, ValueNode receiver, ResolvedJavaMethod targetMethod, Assumptions assumptions, ResolvedJavaType contextType) {
98 if (invokeKind.isDirect()) {
99 return null;
100 }
101
102 // check for trivial cases (e.g. final methods, nonvirtual methods)
103 if (targetMethod.canBeStaticallyBound()) {
104 return targetMethod;
105 }
106
107 ResolvedJavaType type = StampTool.typeOrNull(receiver);
108 if (type == null && invokeKind == InvokeKind.Virtual) {
109 // For virtual calls, we are guaranteed to receive a correct receiver type.
110 type = targetMethod.getDeclaringClass();
111 }
112
113 if (type != null) {
114 /*
115 * either the holder class is exact, or the receiver object has an exact type, or it's
116 * an array type
117 */
118 ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(targetMethod, contextType);
119 if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) {
120 return resolvedMethod;
121 }
122 if (assumptions != null && assumptions.useOptimisticAssumptions()) {
123 ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype();
124 if (uniqueConcreteType != null) {
125 ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod, contextType);
126 if (methodFromUniqueType != null) {
127 assumptions.recordConcreteSubtype(type, uniqueConcreteType);
128 return methodFromUniqueType;
129 }
130 }
131
132 ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod);
133 if (uniqueConcreteMethod != null) {
134 assumptions.recordConcreteMethod(targetMethod, type, uniqueConcreteMethod);
135 return uniqueConcreteMethod;
136 }
137 }
138 }
139
140 return null;
141 }
142
96 @Override 143 @Override
97 public void simplify(SimplifierTool tool) { 144 public void simplify(SimplifierTool tool) {
98 if (invokeKind().isIndirect()) { 145 // attempt to devirtualize the call
99 // attempt to devirtualize the call 146 ResolvedJavaType contextType = (invoke().stateAfter() == null && invoke().stateDuring() == null) ? null : invoke().getContextType();
100 147 ResolvedJavaMethod specialCallTarget = findSpecialCallTarget(invokeKind, receiver(), targetMethod, tool.assumptions(), contextType);
101 // check for trivial cases (e.g. final methods, nonvirtual methods) 148 if (specialCallTarget != null) {
102 if (targetMethod().canBeStaticallyBound()) { 149 this.setTargetMethod(specialCallTarget);
103 setInvokeKind(InvokeKind.Special); 150 setInvokeKind(InvokeKind.Special);
104 return; 151 return;
105 } 152 }
153
154 if (invokeKind().isIndirect() && invokeKind().isInterface()) {
106 155
107 // check if the type of the receiver can narrow the result 156 // check if the type of the receiver can narrow the result
108 ValueNode receiver = receiver(); 157 ValueNode receiver = receiver();
109 ResolvedJavaType type = StampTool.typeOrNull(receiver); 158
110 if (type == null && invokeKind == InvokeKind.Virtual) {
111 // For virtual calls, we are guaranteed to receive a correct receiver type.
112 type = targetMethod.getDeclaringClass();
113 }
114 if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) {
115 /*
116 * either the holder class is exact, or the receiver object has an exact type, or
117 * it's an array type
118 */
119 ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(targetMethod(), invoke().getContextType());
120 if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) {
121 setInvokeKind(InvokeKind.Special);
122 setTargetMethod(resolvedMethod);
123 return;
124 }
125 if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) {
126 ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype();
127 if (uniqueConcreteType != null) {
128 ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod(), invoke().getContextType());
129 if (methodFromUniqueType != null) {
130 tool.assumptions().recordConcreteSubtype(type, uniqueConcreteType);
131 setInvokeKind(InvokeKind.Special);
132 setTargetMethod(methodFromUniqueType);
133 return;
134 }
135 }
136
137 ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod());
138 if (uniqueConcreteMethod != null) {
139 tool.assumptions().recordConcreteMethod(targetMethod(), type, uniqueConcreteMethod);
140 setInvokeKind(InvokeKind.Special);
141 setTargetMethod(uniqueConcreteMethod);
142 return;
143 }
144 }
145 }
146 // try to turn a interface call into a virtual call 159 // try to turn a interface call into a virtual call
147 ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass(); 160 ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass();
148 /* 161 /*
149 * We need to check the invoke kind to avoid recursive simplification for virtual 162 * We need to check the invoke kind to avoid recursive simplification for virtual
150 * interface methods calls. 163 * interface methods calls.
151 */ 164 */
152 if (declaredReceiverType.isInterface() && !invokeKind().equals(InvokeKind.Virtual)) { 165 if (declaredReceiverType.isInterface()) {
153 tryCheckCastSingleImplementor(receiver, declaredReceiverType); 166 tryCheckCastSingleImplementor(receiver, declaredReceiverType);
154 } 167 }
155 168
156 if (invokeKind().equals(InvokeKind.Interface) && receiver instanceof UncheckedInterfaceProvider) { 169 if (receiver instanceof UncheckedInterfaceProvider) {
157 UncheckedInterfaceProvider uncheckedInterfaceProvider = (UncheckedInterfaceProvider) receiver; 170 UncheckedInterfaceProvider uncheckedInterfaceProvider = (UncheckedInterfaceProvider) receiver;
158 Stamp uncheckedStamp = uncheckedInterfaceProvider.uncheckedStamp(); 171 Stamp uncheckedStamp = uncheckedInterfaceProvider.uncheckedStamp();
159 if (uncheckedStamp != null) { 172 if (uncheckedStamp != null) {
160 ResolvedJavaType uncheckedReceiverType = StampTool.typeOrNull(uncheckedStamp); 173 ResolvedJavaType uncheckedReceiverType = StampTool.typeOrNull(uncheckedStamp);
161 if (uncheckedReceiverType.isInterface()) { 174 if (uncheckedReceiverType.isInterface()) {