# HG changeset patch # User Tom Rodriguez # Date 1403634480 25200 # Node ID b1be2a46cc5c94e7fb67aee32e2974bf063beec3 # Parent 0a7e9347f8d09e47652d8a0812607d5a588a626b canonicalize LoadMethodNodes diff -r 0a7e9347f8d0 -r b1be2a46cc5c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Tue Jun 24 13:23:58 2014 -0400 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Tue Jun 24 11:28:00 2014 -0700 @@ -229,6 +229,12 @@ return runtime.getHostProviders().getMetaAccess().lookupJavaType((Class) obj); } } + if (constant instanceof HotSpotMetaspaceConstant) { + Object obj = HotSpotMetaspaceConstant.getMetaspaceObject(constant); + if (obj instanceof HotSpotResolvedObjectType) { + return (ResolvedJavaType) obj; + } + } return null; } } diff -r 0a7e9347f8d0 -r b1be2a46cc5c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Tue Jun 24 13:23:58 2014 -0400 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Tue Jun 24 11:28:00 2014 -0700 @@ -24,13 +24,16 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; /** * Loads a method from the virtual method table of a given hub. */ -public final class LoadMethodNode extends FixedWithNextNode implements Lowerable { +public final class LoadMethodNode extends FixedWithNextNode implements Lowerable, Canonicalizable { @Input private ValueNode hub; private final ResolvedJavaMethod method; @@ -55,6 +58,50 @@ tool.getLowerer().lower(this, tool); } + @Override + public Node canonical(CanonicalizerTool tool) { + if (hub instanceof LoadHubNode) { + ValueNode object = ((LoadHubNode) hub).object(); + ResolvedJavaType type = StampTool.typeOrNull(object); + if (StampTool.isExactType(object)) { + return resolveExactMethod(tool, type); + } + if (type != null && tool.assumptions().useOptimisticAssumptions()) { + ResolvedJavaMethod resolvedMethod = type.findUniqueConcreteMethod(method); + if (resolvedMethod != null && !type.isInterface() && method.getDeclaringClass().isAssignableFrom(type)) { + tool.assumptions().recordConcreteMethod(method, type, resolvedMethod); + return ConstantNode.forConstant(resolvedMethod.getEncoding(), tool.getMetaAccess(), graph()); + } + } + } + if (hub.isConstant()) { + return resolveExactMethod(tool, tool.getConstantReflection().asJavaType(hub.asConstant())); + } + + return this; + } + + /** + * Find the method which would be loaded. + * + * @param tool + * @param type the exact type of object being loaded from + * @return the method which would be invoked for {@code type} or null if it doesn't implement + * the method + */ + private Node resolveExactMethod(CanonicalizerTool tool, ResolvedJavaType type) { + ResolvedJavaMethod newMethod = type.resolveMethod(method, type); + if (newMethod == null) { + /* + * This really represent a misuse of LoadMethod since we're loading from a class which + * isn't known to implement the original method but for now at least fold it away. + */ + return ConstantNode.forConstant(Constant.NULL_OBJECT, null, graph()); + } else { + return ConstantNode.forConstant(newMethod.getEncoding(), tool.getMetaAccess(), graph()); + } + } + public ResolvedJavaMethod getMethod() { return method; }