# HG changeset patch # User Doug Simon # Date 1423241964 -3600 # Node ID c8091ec0fdc073020d78aad359474b2dea71b70a # Parent 1a7b33c96c0d8fcdcca2204d5b1fd3c249d0ebdf added graph builder plugins for FrameWithoutBoxing diff -r 1a7b33c96c0d -r c8091ec0fdc0 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Fri Feb 06 17:59:24 2015 +0100 @@ -47,6 +47,8 @@ Assumptions getAssumptions(); + ConstantReflectionProvider getConstantReflection(); + void push(Kind kind, ValueNode value); /** diff -r 1a7b33c96c0d -r c8091ec0fdc0 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Feb 06 17:59:24 2015 +0100 @@ -37,8 +37,8 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; @@ -1659,6 +1659,7 @@ } public void push(Kind kind, ValueNode value) { + assert kind == kind.getStackKind(); frameState.push(kind, value); } @@ -1669,6 +1670,11 @@ return this.explodeLoopsContext.peek().peelIteration; } } + + public ConstantReflectionProvider getConstantReflection() { + return constantReflectionProvider; + } + } } } diff -r 1a7b33c96c0d -r c8091ec0fdc0 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Fri Feb 06 17:59:24 2015 +0100 @@ -94,6 +94,13 @@ } /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { + throw invalidHandler(builder, arg1, arg2, arg3, arg4); + } + + /** * Executes a given plugin against a set of invocation arguments by dispatching to the * plugin's {@code apply(...)} method that matches the number of arguments. * @@ -111,6 +118,8 @@ return plugin.apply(builder, args[0], args[1]); } else if (args.length == 3) { return plugin.apply(builder, args[0], args[1], args[2]); + } else if (args.length == 4) { + return plugin.apply(builder, args[0], args[1], args[2], args[3]); } else { throw plugin.invalidHandler(builder, args); } @@ -200,6 +209,17 @@ } /** + * Registers a plugin for a method with 4 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register4(String name, Class arg1, Class arg2, Class arg3, Class arg4, InvocationPlugin plugin) { + ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4); + plugins.register(method, plugin); + } + + /** * Resolves a method given a declaring class, name and parameter types. */ public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class declaringClass, String name, Class... parameterTypes) { @@ -212,11 +232,27 @@ } public static class InvocationPluginChecker { - static final Class[] APPLY0 = {GraphBuilderContext.class}; - static final Class[] APPLY1 = {GraphBuilderContext.class, ValueNode.class}; - static final Class[] APPLY2 = {GraphBuilderContext.class, ValueNode.class, ValueNode.class}; - static final Class[] APPLY3 = {GraphBuilderContext.class, ValueNode.class, ValueNode.class, ValueNode.class}; - static final Class[][] SIGS = {APPLY0, APPLY1, APPLY2, APPLY3}; + /** + * The set of all {@link InvocationPlugin#apply} method signatures. + */ + static final Class[][] SIGS; + static { + ArrayList[]> sigs = new ArrayList<>(5); + for (Method method : InvocationPlugin.class.getDeclaredMethods()) { + if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) { + Class[] sig = method.getParameterTypes(); + assert sig[0] == GraphBuilderContext.class; + assert Arrays.asList(Arrays.copyOfRange(sig, 1, sig.length)).stream().allMatch(c -> c == ValueNode.class); + while (sigs.size() < sig.length) { + sigs.add(null); + } + sigs.set(sig.length - 1, sig); + } + } + assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null), + ValueNode.class.getSimpleName()); + SIGS = sigs.toArray(new Class[sigs.size()][]); + } public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) { int arguments = method.getSignature().getParameterCount(!method.isStatic()); diff -r 1a7b33c96c0d -r c8091ec0fdc0 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java Fri Feb 06 17:59:24 2015 +0100 @@ -22,17 +22,23 @@ */ package com.oracle.graal.truffle.substitutions; +import static java.lang.Character.*; + import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; import com.oracle.graal.java.GraphBuilderPlugins.Registration; +import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; import com.oracle.graal.truffle.nodes.frame.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; @@ -43,14 +49,7 @@ public class TruffleGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - Registration r2 = new Registration(plugins, metaAccess, OptimizedCallTarget.class); - r2.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { - builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(FrameWithoutBoxing.class)), arg1, arg2))); - return true; - } - }); - + // CompilerDirectives.class Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class); r.register0("inInterpreter", new InvocationPlugin() { public boolean apply(GraphBuilderContext builder) { @@ -115,5 +114,102 @@ return true; } }); + + // OptimizedCallTarget.class + r = new Registration(plugins, metaAccess, OptimizedCallTarget.class); + r.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { + builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(FrameWithoutBoxing.class)), arg1, arg2))); + return true; + } + }); + + // FrameWithoutBoxing.class + r = new Registration(plugins, metaAccess, FrameWithoutBoxing.class); + r.register1("materialize", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode frame) { + builder.append(new MaterializeFrameNode(frame)); + return true; + } + }); + r.register4("unsafeCast", Object.class, Class.class, boolean.class, boolean.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull) { + if (clazz.isConstant() && nonNull.isConstant()) { + ConstantReflectionProvider constantReflection = builder.getConstantReflection(); + ResolvedJavaType javaType = constantReflection.asJavaType(clazz.asConstant()); + if (javaType == null) { + builder.push(Kind.Object, object); + } else { + Stamp piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0); + ConditionAnchorNode valueAnchorNode = builder.append(new ConditionAnchorNode(CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, + ConstantNode.forBoolean(true, object.graph())))); + PiNode piCast = builder.append(new PiNode(object, piStamp, valueAnchorNode)); + builder.push(Kind.Object, piCast); + } + return true; + } + // TODO: should we throw GraalInternalError.shouldNotReachHere() here? + return false; + } + }); + for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}) { + String kindName = kind.getJavaName(); + kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); + String getName = "unsafeGet" + kindName; + String putName = "unsafePut" + kindName; + r.register4(getName, Object.class, long.class, boolean.class, Object.class, new CustomizedUnsafeLoadPlugin(kind)); + r.register4(putName, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), Object.class, new CustomizedUnsafeStorePlugin(kind)); + } + } + + static class CustomizedUnsafeLoadPlugin implements InvocationPlugin { + + private final Kind returnKind; + + public CustomizedUnsafeLoadPlugin(Kind returnKind) { + this.returnKind = returnKind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode offset, ValueNode condition, ValueNode location) { + if (location.isConstant()) { + LocationIdentity locationIdentity; + if (location.isNullConstant()) { + locationIdentity = LocationIdentity.ANY_LOCATION; + } else { + locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); + } + CompareNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()))); + builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); + return true; + } + // TODO: should we throw GraalInternalError.shouldNotReachHere() here? + return false; + } + } + + static class CustomizedUnsafeStorePlugin implements InvocationPlugin { + + private final Kind kind; + + public CustomizedUnsafeStorePlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode offset, ValueNode value, ValueNode location) { + ValueNode locationArgument = location; + if (locationArgument.isConstant()) { + LocationIdentity locationIdentity; + if (locationArgument.isNullConstant()) { + locationIdentity = LocationIdentity.ANY_LOCATION; + } else { + locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); + } + + builder.append(new UnsafeStoreNode(object, offset, value, kind, locationIdentity, null)); + return true; + } + // TODO: should we throw GraalInternalError.shouldNotReachHere() here? + return false; + } } }