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() {