# HG changeset patch # User Doug Simon # Date 1381521521 -7200 # Node ID ec57cc36371e0aa0d5e125336ac9c53482aeeb23 # Parent cfba4fd3d616d458c80b04a79f4e3eceb5e2f66f introduced @InjectedNodeParameter annotation to make injection of arguments during node intrinsification more extensible diff -r cfba4fd3d616 -r ec57cc36371e graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Oct 11 21:05:41 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Oct 11 21:58:41 2013 +0200 @@ -86,10 +86,22 @@ } /** + * Denotes an injected parameter in a {@linkplain NodeIntrinsic node intrinsic} constructor. If + * the constructor is called as part of node intrinsification, the node intrinsifier will inject + * an argument for the annotated parameter. Injected parameters must precede all non-injected + * parameters in a constructor. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.PARAMETER) + public static @interface InjectedNodeParameter { + } + + /** * Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the * annotated method can be replaced with an instance of the node class denoted by * {@link #value()}. For this reason, the signature of the annotated method must match the - * signature of a constructor in the node class. + * signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a + * constructor in the node class. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) diff -r cfba4fd3d616 -r ec57cc36371e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Fri Oct 11 21:05:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Fri Oct 11 21:58:41 2013 +0200 @@ -43,7 +43,7 @@ public static final ForeignCallDescriptor NEW_MULTI_ARRAY = new ForeignCallDescriptor("new_multi_array", Object.class, Word.class, int.class, Word.class); - public NewMultiArrayStubCall(MetaAccessProvider metaAccess, ValueNode hub, int rank, ValueNode dims) { + public NewMultiArrayStubCall(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub, int rank, ValueNode dims) { super(metaAccess, NEW_MULTI_ARRAY, defaultStamp); this.hub = hub; this.rank = rank; diff -r cfba4fd3d616 -r ec57cc36371e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Fri Oct 11 21:05:41 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Fri Oct 11 21:58:41 2013 +0200 @@ -41,7 +41,7 @@ private final ForeignCallDescriptor descriptor; - public StubForeignCallNode(MetaAccessProvider metaAccess, ForeignCallDescriptor descriptor, ValueNode... arguments) { + public StubForeignCallNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ForeignCallDescriptor descriptor, ValueNode... arguments) { super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; diff -r cfba4fd3d616 -r ec57cc36371e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Fri Oct 11 21:05:41 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Fri Oct 11 21:58:41 2013 +0200 @@ -41,14 +41,14 @@ private final ForeignCallDescriptor descriptor; - public ForeignCallNode(MetaAccessProvider metaAccess, ForeignCallDescriptor descriptor, ValueNode... arguments) { + public ForeignCallNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ForeignCallDescriptor descriptor, ValueNode... arguments) { super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType()))); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.metaAccess = metaAccess; } - protected ForeignCallNode(MetaAccessProvider metaAccess, ForeignCallDescriptor descriptor, Stamp stamp) { + protected ForeignCallNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ForeignCallDescriptor descriptor, Stamp stamp) { super(stamp); this.arguments = new NodeInputList<>(this); this.descriptor = descriptor; diff -r cfba4fd3d616 -r ec57cc36371e graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Oct 11 21:05:41 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Oct 11 21:58:41 2013 +0200 @@ -31,8 +31,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.ConstantNodeParameter; -import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.graph.Node.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; @@ -75,7 +74,7 @@ assert target.getAnnotation(Fold.class) == null; assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target; - ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass); + ResolvedJavaType[] parameterTypes = resolveJavaTypes(signatureToTypes(target), declaringClass); // Prepare the arguments for the reflective constructor call on the node class. Constant[] nodeConstructorArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false); @@ -94,7 +93,7 @@ // Clean up checkcast instructions inserted by javac if the return type is generic. cleanUpReturnList.add(newInstance); } else if (isFoldable(target)) { - ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass); + ResolvedJavaType[] parameterTypes = resolveJavaTypes(signatureToTypes(target), declaringClass); // Prepare the arguments for the reflective method call Constant[] arguments = prepareArguments(methodCallTargetNode, parameterTypes, target, true); @@ -150,7 +149,7 @@ parameterIndex--; } ValueNode argument = arguments.get(i); - if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) { + if (folding || getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) { if (!(argument instanceof ConstantNode)) { return null; } @@ -205,12 +204,12 @@ constructor = c; arguments = match; } else { - throw new GraalInternalError("Found multiple constructors in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes) + ": " + constructor + ", " + c); + throw new GraalInternalError("Found multiple constructors in %s compatible with signature %s: %s, %s", toJavaName(nodeClass), sigString(parameterTypes), constructor, c); } } } if (constructor == null) { - throw new GraalInternalError("Could not find constructor in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes)); + throw new GraalInternalError("Could not find constructor in %s compatible with signature %s", toJavaName(nodeClass), sigString(parameterTypes)); } try { @@ -225,15 +224,47 @@ } } + private static String sigString(ResolvedJavaType[] types) { + StringBuilder sb = new StringBuilder("("); + for (int i = 0; i < types.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(toJavaName(types[i])); + } + return sb.append(")").toString(); + } + + private static boolean containsInjected(ResolvedJavaMethod c, int start, int end) { + for (int i = start; i < end; i++) { + if (getParameterAnnotation(InjectedNodeParameter.class, i, c) != null) { + return true; + } + } + return false; + } + private Constant[] match(ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Constant[] nodeConstructorArguments) { Constant[] arguments = null; - boolean needsMetaAccessProviderArgument = false; + Constant[] injected = null; - ResolvedJavaType[] signature = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(c.getSignature(), null), c.getDeclaringClass()); - if (signature.length != 0 && signature[0].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) { - // Chop off the MetaAccessProvider first parameter - signature = Arrays.copyOfRange(signature, 1, signature.length); - needsMetaAccessProviderArgument = true; + ResolvedJavaType[] signature = resolveJavaTypes(signatureToTypes(c.getSignature(), null), c.getDeclaringClass()); + for (int i = 0; i < signature.length; i++) { + if (getParameterAnnotation(InjectedNodeParameter.class, i, c) != null) { + injected = injected == null ? new Constant[1] : Arrays.copyOf(injected, injected.length + 1); + if (signature[i].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) { + injected[injected.length - 1] = Constant.forObject(metaAccess); + } else { + throw new GraalInternalError("Cannot handle injected argument of type %s in %s", toJavaName(signature[i]), format("%H.%n(%p)", c)); + } + } else { + if (i > 0) { + // Chop injected arguments from signature + signature = Arrays.copyOfRange(signature, i, signature.length); + } + assert !containsInjected(c, i, signature.length); + break; + } } if (Arrays.equals(parameterTypes, signature)) { @@ -270,10 +301,10 @@ return null; } - if (needsMetaAccessProviderArgument) { - Constant[] copy = new Constant[arguments.length + 1]; - System.arraycopy(arguments, 0, copy, 1, arguments.length); - copy[0] = Constant.forObject(metaAccess); + if (injected != null) { + Constant[] copy = new Constant[injected.length + arguments.length]; + System.arraycopy(injected, 0, copy, 0, injected.length); + System.arraycopy(arguments, 0, copy, injected.length, arguments.length); arguments = copy; } return arguments;