Mercurial > hg > graal-compiler
comparison graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java @ 18504:c2b23f6e4603
Try to bind method after guarded interface invoke
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Tue, 25 Nov 2014 12:25:51 -0800 |
parents | ca81508f2a19 |
children | 2885aafd812f |
comparison
equal
deleted
inserted
replaced
18503:290eb3f3d643 | 18504:c2b23f6e4603 |
---|---|
110 setInvokeKind(InvokeKind.Special); | 110 setInvokeKind(InvokeKind.Special); |
111 return; | 111 return; |
112 } | 112 } |
113 | 113 |
114 // check if the type of the receiver can narrow the result | 114 // check if the type of the receiver can narrow the result |
115 if (tryToResolveMethod(tool)) { | |
116 return; | |
117 } | |
118 | |
115 ValueNode receiver = receiver(); | 119 ValueNode receiver = receiver(); |
116 ResolvedJavaType type = StampTool.typeOrNull(receiver); | 120 |
117 if (type == null && invokeKind == InvokeKind.Virtual) { | 121 // try to turn an interface call into a virtual call |
118 // For virtual calls, we are guaranteed to receive a correct receiver type. | |
119 type = targetMethod.getDeclaringClass(); | |
120 } | |
121 if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) { | |
122 /* | |
123 * either the holder class is exact, or the receiver object has an exact type, or | |
124 * it's an array type | |
125 */ | |
126 ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(targetMethod(), invoke().getContextType()); | |
127 if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) { | |
128 setInvokeKind(InvokeKind.Special); | |
129 setTargetMethod(resolvedMethod); | |
130 return; | |
131 } | |
132 if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { | |
133 ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); | |
134 if (uniqueConcreteType != null) { | |
135 ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod(), invoke().getContextType()); | |
136 if (methodFromUniqueType != null) { | |
137 tool.assumptions().recordConcreteSubtype(type, uniqueConcreteType); | |
138 setInvokeKind(InvokeKind.Special); | |
139 setTargetMethod(methodFromUniqueType); | |
140 return; | |
141 } | |
142 } | |
143 | |
144 ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod()); | |
145 if (uniqueConcreteMethod != null) { | |
146 tool.assumptions().recordConcreteMethod(targetMethod(), type, uniqueConcreteMethod); | |
147 setInvokeKind(InvokeKind.Special); | |
148 setTargetMethod(uniqueConcreteMethod); | |
149 return; | |
150 } | |
151 } | |
152 } | |
153 // try to turn a interface call into a virtual call | |
154 ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass(); | 122 ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass(); |
155 /* | 123 /* |
156 * We need to check the invoke kind to avoid recursive simplification for virtual | 124 * We need to check the invoke kind to avoid recursive simplification for virtual |
157 * interface methods calls. | 125 * interface methods calls. |
158 */ | 126 */ |
159 if (declaredReceiverType.isInterface() && !invokeKind().equals(InvokeKind.Virtual)) { | 127 if (declaredReceiverType.isInterface() && !invokeKind().equals(InvokeKind.Virtual)) { |
160 tryCheckCastSingleImplementor(receiver, declaredReceiverType); | 128 tryCheckCastSingleImplementor(tool, receiver, declaredReceiverType); |
161 } | 129 } |
162 | 130 |
163 if (invokeKind().equals(InvokeKind.Interface) && receiver instanceof UncheckedInterfaceProvider) { | 131 if (invokeKind().equals(InvokeKind.Interface) && receiver instanceof UncheckedInterfaceProvider) { |
164 UncheckedInterfaceProvider uncheckedInterfaceProvider = (UncheckedInterfaceProvider) receiver; | 132 UncheckedInterfaceProvider uncheckedInterfaceProvider = (UncheckedInterfaceProvider) receiver; |
165 Stamp uncheckedStamp = uncheckedInterfaceProvider.uncheckedStamp(); | 133 Stamp uncheckedStamp = uncheckedInterfaceProvider.uncheckedStamp(); |
166 if (uncheckedStamp != null) { | 134 if (uncheckedStamp != null) { |
167 ResolvedJavaType uncheckedReceiverType = StampTool.typeOrNull(uncheckedStamp); | 135 ResolvedJavaType uncheckedReceiverType = StampTool.typeOrNull(uncheckedStamp); |
168 if (uncheckedReceiverType.isInterface()) { | 136 if (uncheckedReceiverType.isInterface()) { |
169 tryCheckCastSingleImplementor(receiver, uncheckedReceiverType); | 137 tryCheckCastSingleImplementor(tool, receiver, uncheckedReceiverType); |
170 } | 138 } |
171 } | 139 } |
172 } | 140 } |
173 } | 141 } |
174 } | 142 } |
175 | 143 |
176 private void tryCheckCastSingleImplementor(ValueNode receiver, ResolvedJavaType declaredReceiverType) { | 144 /** |
145 * Try to use receiver type information to statically bind the method. | |
146 * | |
147 * @param tool | |
148 * @return true if successfully converted to InvokeKind.Special | |
149 */ | |
150 private boolean tryToResolveMethod(SimplifierTool tool) { | |
151 ValueNode receiver = receiver(); | |
152 ResolvedJavaType type = StampTool.typeOrNull(receiver); | |
153 if (type == null && invokeKind == InvokeKind.Virtual) { | |
154 // For virtual calls, we are guaranteed to receive a correct receiver type. | |
155 type = targetMethod.getDeclaringClass(); | |
156 } | |
157 if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) { | |
158 /* | |
159 * either the holder class is exact, or the receiver object has an exact type, or it's | |
160 * an array type | |
161 */ | |
162 ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(targetMethod(), invoke().getContextType()); | |
163 if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) { | |
164 setInvokeKind(InvokeKind.Special); | |
165 setTargetMethod(resolvedMethod); | |
166 return true; | |
167 } | |
168 if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { | |
169 ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); | |
170 if (uniqueConcreteType != null) { | |
171 ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod(), invoke().getContextType()); | |
172 if (methodFromUniqueType != null) { | |
173 tool.assumptions().recordConcreteSubtype(type, uniqueConcreteType); | |
174 setInvokeKind(InvokeKind.Special); | |
175 setTargetMethod(methodFromUniqueType); | |
176 return true; | |
177 } | |
178 } | |
179 | |
180 ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod()); | |
181 if (uniqueConcreteMethod != null) { | |
182 tool.assumptions().recordConcreteMethod(targetMethod(), type, uniqueConcreteMethod); | |
183 setInvokeKind(InvokeKind.Special); | |
184 setTargetMethod(uniqueConcreteMethod); | |
185 return true; | |
186 } | |
187 } | |
188 } | |
189 return false; | |
190 } | |
191 | |
192 private void tryCheckCastSingleImplementor(SimplifierTool tool, ValueNode receiver, ResolvedJavaType declaredReceiverType) { | |
177 ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor(); | 193 ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor(); |
178 if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) { | 194 if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) { |
179 ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType(), true); | 195 ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveMethod(targetMethod(), invoke().getContextType(), true); |
180 if (singleImplementorMethod != null) { | 196 if (singleImplementorMethod != null) { |
181 assert graph().getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal() : "Graph already fixed!"; | 197 assert graph().getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal() : "Graph already fixed!"; |
196 JavaConstant.NULL_POINTER)); | 212 JavaConstant.NULL_POINTER)); |
197 PiNode piNode = graph().unique(PiNode.create(receiver, StampFactory.declaredNonNull(singleImplementor), guard)); | 213 PiNode piNode = graph().unique(PiNode.create(receiver, StampFactory.declaredNonNull(singleImplementor), guard)); |
198 arguments().set(0, piNode); | 214 arguments().set(0, piNode); |
199 setInvokeKind(InvokeKind.Virtual); | 215 setInvokeKind(InvokeKind.Virtual); |
200 setTargetMethod(singleImplementorMethod); | 216 setTargetMethod(singleImplementorMethod); |
217 // Now try to bind the method exactly. | |
218 tryToResolveMethod(tool); | |
201 } | 219 } |
202 } | 220 } |
203 } | 221 } |
204 | 222 |
205 private JavaTypeProfile getProfile() { | 223 private JavaTypeProfile getProfile() { |