Mercurial > hg > graal-compiler
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()) { |