Mercurial > hg > graal-compiler
changeset 22610:0d282ecc09ab
c.o.g.microbenchmarks: add graal jmh benchmarks.
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/ArrayDuplicationBenchmark.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,76 @@ +package com.oracle.graal.microbenchmarks.graal; + +import java.util.*; + +import org.openjdk.jmh.annotations.*; + +@State(Scope.Thread) +public class ArrayDuplicationBenchmark { + + /** How large should the test-arrays be. */ + private static final int TESTSIZE = 300; + + private Object[][] testObjectArray; + + private Object[] dummy; + + @Setup + public void setup() { + testObjectArray = new Object[TESTSIZE][]; + for (int i = 0; i < TESTSIZE; i++) { + testObjectArray[i] = new Object[20]; + } + } + + @Setup(Level.Iteration) + public void iterationSetup() { + dummy = new Object[TESTSIZE * 3]; + } + + @TearDown(Level.Iteration) + public void iterationTearDown() { + dummy = null; + } + + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public Object[] normalArraycopy() { + for (int i = 0, j = 0; i < TESTSIZE; i++) { + dummy[j++] = normalArraycopy(testObjectArray[i]); + } + return dummy; + } + + public Object[] normalArraycopy(Object[] cache) { + Object[] result = new Object[cache.length]; + System.arraycopy(cache, 0, result, 0, result.length); + return result; + } + + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public Object[] arraysCopyOf() { + for (int i = 0, j = 0; i < TESTSIZE; i++) { + dummy[j++] = arraysCopyOf(testObjectArray[i]); + } + return dummy; + } + + public Object[] arraysCopyOf(Object[] cache) { + return Arrays.copyOf(cache, cache.length); + } + + @Benchmark + @OperationsPerInvocation(TESTSIZE) + public Object[] cloneObjectArray() { + for (int i = 0, j = 0; i < TESTSIZE; i++) { + dummy[j++] = arraysClone(testObjectArray[i]); + } + return dummy; + } + + public Object[] arraysClone(Object[] cache) { + return (Object[]) cache.clone(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/ConditionalEliminationBenchmark.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,103 @@ +package com.oracle.graal.microbenchmarks.graal; + +import org.openjdk.jmh.annotations.*; + +import com.oracle.graal.microbenchmarks.graal.util.*; +import com.oracle.graal.phases.common.*; + +public class ConditionalEliminationBenchmark extends GraalBenchmark { + + @MethodSpec(declaringClass = ConditionalEliminationBenchmark.class, name = "nullnessSnippet") + public static class Nullness extends GraphState { + } + + @SuppressWarnings("unused") + public static int nullnessSnippet(Object a, Object b) { + if (a == null) { + if (a == b) { + if (b == null) { + return 1; + } else { + return -2; + } + } else { + if (b == null) { + return -3; + } else { + return 4; + } + } + } else { + if (a == b) { + if (b == null) { + return -5; + } else { + return 6; + } + } else { + if (b == null) { + return 7; + } else { + return 8; + } + } + } + } + + @Benchmark + @Warmup(iterations = 20) + public void nullness(Nullness s, GraalState g) { + new ConditionalEliminationPhase().apply(s.graph); + } + + @MethodSpec(declaringClass = ConditionalEliminationBenchmark.class, name = "searchSnippet") + public static class Search extends GraphState { + } + + static class Entry { + final String name; + + public Entry(String name) { + this.name = name; + } + } + + static class EntryWithNext extends Entry { + public EntryWithNext(String name, Entry next) { + super(name); + this.next = next; + } + + final Entry next; + } + + public static Entry searchSnippet(Entry start, String name, Entry alternative) { + Entry current = start; + do { + while (current instanceof EntryWithNext) { + if (name != null && current.name == name) { + current = null; + } else { + Entry next = ((EntryWithNext) current).next; + current = next; + } + } + + if (current != null) { + if (current.name.equals(name)) { + return current; + } + } + if (current == alternative) { + return null; + } + current = alternative; + + } while (true); + } + + @Benchmark + public void search(Search s, GraalState g) { + new ConditionalEliminationPhase().apply(s.graph); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/FrameStateAssigmentPhaseBenchmark.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,20 @@ +package com.oracle.graal.microbenchmarks.graal; + +import java.util.*; + +import org.openjdk.jmh.annotations.*; + +import com.oracle.graal.microbenchmarks.graal.util.*; + +@Warmup(iterations = 15) +public class FrameStateAssigmentPhaseBenchmark extends GraalBenchmark { + + @MethodSpec(declaringClass = StringTokenizer.class, name = "nextToken", parameters = {String.class}) + public static class StringTokenizedNextToken extends FrameStateAssignmentState { + } + + @Benchmark + public void nextToken(StringTokenizedNextToken s) { + s.phase.apply(s.graph); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/GraalBenchmark.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,22 @@ +package com.oracle.graal.microbenchmarks.graal; + +import static com.oracle.graal.microbenchmarks.graal.GraalBenchmark.Defaults.*; + +import org.openjdk.jmh.annotations.*; + +/** + * All classes defining Graal benchmarks must subclass this class as it defines the default value + * for each benchmark option. Individual options can be overridden in the subclasses or by an + * individual benchmark. + */ +@Warmup(iterations = WARMUP_ITERATIONS) +@Measurement(iterations = MEASUREMENT_ITERATIONS) +@Fork(FORKS) +public class GraalBenchmark { + + public static class Defaults { + public static final int MEASUREMENT_ITERATIONS = 10; + public static final int WARMUP_ITERATIONS = 10; + public static final int FORKS = 1; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/GraphCopyBenchmark.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,108 @@ +package com.oracle.graal.microbenchmarks.graal; + +import org.openjdk.jmh.annotations.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.microbenchmarks.graal.util.*; +import com.oracle.graal.nodes.*; + +/** + * Benchmarks the performance of {@link Graph#copy()}. + */ +public class GraphCopyBenchmark extends GraalBenchmark { + + @MethodSpec(declaringClass = ConditionalEliminationBenchmark.class, name = "nullnessSnippet") + public static class Nullness extends GraphState { + } + + @SuppressWarnings("unused") + public static int nullnessSnippet(Object a, Object b) { + if (a == null) { + if (a == b) { + if (b == null) { + return 1; + } else { + return -2; + } + } else { + if (b == null) { + return -3; + } else { + return 4; + } + } + } else { + if (a == b) { + if (b == null) { + return -5; + } else { + return 6; + } + } else { + if (b == null) { + return 7; + } else { + return 8; + } + } + } + } + + @Benchmark + @Warmup(iterations = 20) + public StructuredGraph nullness(Nullness s, GraalState g) { + return (StructuredGraph) s.graph.copy(); + } + + @MethodSpec(declaringClass = GraphCopyBenchmark.class, name = "searchSnippet") + public static class Search extends GraphState { + } + + static class Entry { + final String name; + + public Entry(String name) { + this.name = name; + } + } + + static class EntryWithNext extends Entry { + public EntryWithNext(String name, Entry next) { + super(name); + this.next = next; + } + + final Entry next; + } + + public static Entry searchSnippet(Entry start, String name, Entry alternative) { + Entry current = start; + do { + while (current instanceof EntryWithNext) { + if (name != null && current.name == name) { + current = null; + } else { + Entry next = ((EntryWithNext) current).next; + current = next; + } + } + + if (current != null) { + if (current.name.equals(name)) { + return current; + } + } + if (current == alternative) { + return null; + } + current = alternative; + + } while (true); + } + + @Benchmark + @Warmup(iterations = 20) + public StructuredGraph search(Search s, GraalState g) { + return (StructuredGraph) s.graph.copy(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/NodeBenchmark.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,107 @@ +package com.oracle.graal.microbenchmarks.graal; + +import java.util.*; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import com.oracle.graal.graph.*; +import com.oracle.graal.microbenchmarks.graal.util.*; +import com.oracle.graal.microbenchmarks.graal.util.NodesState.NodePair; + +public class NodeBenchmark extends GraalBenchmark { + + @MethodSpec(declaringClass = String.class, name = "equals") + public static class StringEquals extends NodesState { + } + + @Benchmark + @Warmup(iterations = 20) + public int getNodeClass(StringEquals s) { + int sum = 0; + for (Node n : s.nodes) { + sum += n.getNodeClass().iterableId(); + } + return sum; + } + + @Benchmark + public void inputs(StringEquals s, Blackhole bh) { + for (Node n : s.nodes) { + for (Node input : n.inputs()) { + bh.consume(input); + } + } + } + + @Benchmark + public void usages(StringEquals s, Blackhole bh) { + for (Node n : s.nodes) { + for (Node input : n.usages()) { + bh.consume(input); + } + } + } + + @MethodSpec(declaringClass = HashMap.class, name = "computeIfAbsent") + public static class HashMapComputeIfAbsent extends NodesState { + } + + @Benchmark + @Warmup(iterations = 20) + public void nonNullInputs(HashMapComputeIfAbsent s, Blackhole bh) { + for (Node n : s.nodes) { + for (Node input : n.inputs().nonNull()) { + bh.consume(input); + } + } + } + + @Benchmark + @Warmup(iterations = 20) + public int valueEquals_STRING_EQUALS(StringEquals s) { + int result = 0; + for (NodePair np : s.valueEqualsNodePairs) { + if (np.n1.valueEquals(np.n2)) { + result += 27; + } else { + result += 31; + } + } + return result; + } + + @Benchmark + @Warmup(iterations = 20) + public int valueEquals_HASHMAP_COMPUTE_IF_ABSENT(HashMapComputeIfAbsent s) { + int result = 0; + for (NodePair np : s.valueEqualsNodePairs) { + if (np.n1.valueEquals(np.n2)) { + result += 27; + } else { + result += 31; + } + } + return result; + } + + @Benchmark + @Warmup(iterations = 20) + public int valueNumberLeaf_HASHMAP_COMPUTE_IF_ABSENT(HashMapComputeIfAbsent s) { + int result = 0; + for (Node n : s.valueNumberableLeafNodes) { + result += (n.getNodeClass().isLeafNode() ? 1 : 0); + } + return result; + } + + @Benchmark + @Warmup(iterations = 20) + public int valueNumberLeaf_STRING_EQUALS(StringEquals s) { + int result = 0; + for (Node n : s.valueNumberableLeafNodes) { + result += (n.getNodeClass().isLeafNode() ? 1 : 0); + } + return result; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/SchedulePhaseBenchmark.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,74 @@ +package com.oracle.graal.microbenchmarks.graal; + +import java.util.*; + +import org.openjdk.jmh.annotations.*; + +import com.oracle.graal.microbenchmarks.graal.util.*; +import com.oracle.graal.phases.schedule.SchedulePhase.SchedulingStrategy; + +@Warmup(iterations = 15) +public class SchedulePhaseBenchmark extends GraalBenchmark { + + @MethodSpec(declaringClass = String.class, name = "equals") + public static class StringEquals extends ScheduleState { + } + + @Benchmark + public void stringEquals(StringEquals s) { + s.schedule.apply(s.graph); + } + + public static int[] intersectionSnippet(int[] in1, int[] in2) { + int[] result = new int[Math.min(in1.length, in2.length)]; + int next = 0; + for (int i1 : in1) { + for (int i2 : in2) { + if (i2 == i1) { + result[next++] = i1; + break; + } + } + } + if (next < result.length) { + result = Arrays.copyOf(result, next); + } + return result; + } + + @MethodSpec(declaringClass = SchedulePhaseBenchmark.class, name = "intersectionSnippet") + public static class IntersectionState_LATEST_OPTIMAL extends ScheduleState { + public IntersectionState_LATEST_OPTIMAL() { + super(SchedulingStrategy.LATEST); + } + } + + @Benchmark + public void intersection_LATEST_OPTIMAL(IntersectionState_LATEST_OPTIMAL s) { + s.schedule.apply(s.graph); + } + + @MethodSpec(declaringClass = SchedulePhaseBenchmark.class, name = "intersectionSnippet") + public static class IntersectionState_LATEST_OUT_OF_LOOPS_OPTIMAL extends ScheduleState { + public IntersectionState_LATEST_OUT_OF_LOOPS_OPTIMAL() { + super(SchedulingStrategy.LATEST_OUT_OF_LOOPS); + } + } + + @Benchmark + public void intersection_LATEST_OUT_OF_LOOPS_OPTIMAL(IntersectionState_LATEST_OUT_OF_LOOPS_OPTIMAL s) { + s.schedule.apply(s.graph); + } + + @MethodSpec(declaringClass = SchedulePhaseBenchmark.class, name = "intersectionSnippet") + public static class IntersectionState_EARLIEST_OPTIMAL extends ScheduleState { + public IntersectionState_EARLIEST_OPTIMAL() { + super(SchedulingStrategy.EARLIEST); + } + } + + @Benchmark + public void intersection_EARLIEST_OPTIMAL(IntersectionState_EARLIEST_OPTIMAL s) { + s.schedule.apply(s.graph); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/FrameStateAssignmentState.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,21 @@ +package com.oracle.graal.microbenchmarks.graal.util; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.common.*; + +public class FrameStateAssignmentState extends GraphState { + + public FrameStateAssignmentPhase phase; + + @Override + protected StructuredGraph preprocessOriginal(StructuredGraph graph) { + new GuardLoweringPhase().apply(graph, null); + return graph; + } + + @Override + public void beforeInvocation() { + phase = new FrameStateAssignmentPhase(); + super.beforeInvocation(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/GraalState.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,27 @@ +package com.oracle.graal.microbenchmarks.graal.util; + +import jdk.internal.jvmci.meta.*; + +import org.openjdk.jmh.annotations.*; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.runtime.*; + +/** + * Read-only, benchmark-wide state providing Graal runtime context. + */ +@State(Scope.Benchmark) +public class GraalState { + + public final Backend backend; + public final Providers providers; + public final MetaAccessProvider metaAccess; + + public GraalState() { + backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); + providers = backend.getProviders(); + metaAccess = providers.getMetaAccess(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/GraalUtil.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,117 @@ +package com.oracle.graal.microbenchmarks.graal.util; + +import java.lang.reflect.*; +import java.util.*; + +import jdk.internal.jvmci.meta.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +public class GraalUtil { + + public static Method getMethod(Class<?> declaringClass, String name, Class<?>... parameterTypes) { + try { + if (parameterTypes == null) { + Method found = null; + for (Method m : declaringClass.getDeclaredMethods()) { + if (m.getName().equals(name)) { + if (found != null) { + throw new RuntimeException("more than one method named " + name + " in " + declaringClass); + } + found = m; + } + } + if (found == null) { + throw new NoSuchMethodException(declaringClass.getName() + "." + name); + } + return found; + } else { + return declaringClass.getDeclaredMethod(name, parameterTypes); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Gets the first {@link MethodSpec} annotation encountered in the class hierarchy terminated by + * {@code startClass}. + */ + public static MethodSpec getMethodSpec(Class<?> startClass) { + Class<?> c = startClass; + while (c != null) { + MethodSpec methodSpec = c.getAnnotation(MethodSpec.class); + if (methodSpec != null) { + return methodSpec; + } + c = c.getSuperclass(); + } + throw new RuntimeException("Could not find class annotated with " + MethodSpec.class.getSimpleName() + " in hierarchy of " + startClass); + } + + /** + * Gets the method specified by the first {@link MethodSpec} annotation encountered in the class + * hierarchy terminated by {@code startClass}. + */ + public static Method getMethodFromMethodSpec(Class<?> startClass) { + MethodSpec methodSpec = getMethodSpec(startClass); + Class<?> declaringClass = methodSpec.declaringClass(); + if (declaringClass == MethodSpec.class) { + declaringClass = startClass; + } + String name = methodSpec.name(); + Class<?>[] parameters = methodSpec.parameters(); + if (parameters.length == 1 && parameters[0] == void.class) { + parameters = null; + } + return getMethod(declaringClass, name, parameters); + } + + /** + * Gets the graph for the method specified by the first {@link MethodSpec} annotation + * encountered in the class hierarchy terminated by {@code startClass}. + */ + public static StructuredGraph getGraphFromMethodSpec(Class<?> startClass) { + MethodSpec methodSpec = getMethodSpec(startClass); + Class<?> declaringClass = methodSpec.declaringClass(); + if (declaringClass == MethodSpec.class) { + declaringClass = startClass; + } + String name = methodSpec.name(); + Class<?>[] parameters = methodSpec.parameters(); + if (parameters.length == 1 && parameters[0] == void.class) { + parameters = null; + } + return getGraph(declaringClass, name, parameters); + } + + public static StructuredGraph getGraph(Class<?> declaringClass, String name, Class<?>... parameterTypes) { + return getGraph(getMethod(declaringClass, name, parameterTypes)); + } + + public static StructuredGraph getGraph(Method method) { + GraalState graal = new GraalState(); + ResolvedJavaMethod javaMethod = graal.metaAccess.lookupJavaMethod(method); + return getGraph(graal, javaMethod); + } + + public static StructuredGraph getGraph(GraalState graal, ResolvedJavaMethod javaMethod) { + StructuredGraph graph = new StructuredGraph(javaMethod, StructuredGraph.AllowAssumptions.YES); + PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>(); + MetaAccessProvider metaAccess = graal.providers.getMetaAccess(); + graphBuilderSuite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault(new Plugins(new InvocationPlugins(metaAccess))))); + graphBuilderSuite.apply(graph, new HighTierContext(graal.providers, graphBuilderSuite, OptimisticOptimizations.ALL)); + return graph; + } + + public static Node[] getNodes(StructuredGraph graph) { + List<Node> nodeList = graph.getNodes().snapshot(); + return nodeList.toArray(new Node[nodeList.size()]); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/GraphState.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,55 @@ +package com.oracle.graal.microbenchmarks.graal.util; + +import static com.oracle.graal.microbenchmarks.graal.util.GraalUtil.*; +import jdk.internal.jvmci.meta.*; + +import org.openjdk.jmh.annotations.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; +import com.oracle.graal.nodes.*; + +/** + * State providing a new copy of a graph for each invocation of a benchmark. Subclasses of this + * class are annotated with {@link MethodSpec} to specify the Java method that will be parsed to + * obtain the original graph. + */ +@State(Scope.Thread) +public abstract class GraphState { + + public GraphState() { + // Ensure a debug configuration for this thread is initialized + if (Debug.isEnabled() && DebugScope.getConfig() == null) { + DebugEnvironment.initialize(System.out); + } + + GraalState graal = new GraalState(); + ResolvedJavaMethod method = graal.metaAccess.lookupJavaMethod(getMethodFromMethodSpec(getClass())); + StructuredGraph graph = null; + try (Debug.Scope s = Debug.scope("GraphState", method)) { + graph = preprocessOriginal(getGraph(graal, method)); + } catch (Throwable t) { + Debug.handle(t); + } + this.originalGraph = graph; + } + + protected StructuredGraph preprocessOriginal(StructuredGraph graph) { + return graph; + } + + /** + * Original graph from which the per-benchmark invocation {@link #graph} is cloned. + */ + private final StructuredGraph originalGraph; + + /** + * The graph processed by the benchmark. + */ + public StructuredGraph graph; + + @Setup(Level.Invocation) + public void beforeInvocation() { + graph = (StructuredGraph) originalGraph.copy(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/MethodSpec.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,27 @@ +package com.oracle.graal.microbenchmarks.graal.util; + +import java.lang.annotation.*; + +/** + * Annotation for specifying a method based on a declaring class, a name and parameter types. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MethodSpec { + /** + * The class in which the method is declared. If not specified, the annotated class is used as + * the declaring class. + */ + Class<?> declaringClass() default MethodSpec.class; + + /** + * The name of the method. + */ + String name(); + + /** + * The types of the method's parameters. If not specified, then the {@linkplain #name() name} is + * expected to be unique within the declaring class. + */ + Class<?>[] parameters() default {void.class}; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/NodesState.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,77 @@ +package com.oracle.graal.microbenchmarks.graal.util; + +import static com.oracle.graal.microbenchmarks.graal.util.GraalUtil.*; + +import java.util.*; + +import org.openjdk.jmh.annotations.*; + +import com.oracle.graal.graph.*; + +/** + * State providing the nodes in a graph. Subclasses of this class are annotated with + * {@link MethodSpec} to specify the Java method that will be parsed to obtain the original graph. + */ +@State(Scope.Benchmark) +public abstract class NodesState { + + public NodesState() { + this.nodes = getNodes(getGraphFromMethodSpec(getClass())); + this.originalNodes = nodes.clone(); + List<Node> vnln = new ArrayList<>(nodes.length); + List<NodePair> list2 = new ArrayList<>(nodes.length); + for (int i = 0; i < nodes.length; i++) { + Node n = nodes[i]; + NodeClass<?> nc = n.getNodeClass(); + if (nc.valueNumberable() && nc.isLeafNode()) { + vnln.add(n); + } + for (int j = i + i; j < nodes.length; j++) { + Node o = nodes[j]; + if (o.getClass() == n.getClass()) { + list2.add(new NodePair(n, o)); + } + } + } + valueNumberableLeafNodes = vnln.toArray(new Node[vnln.size()]); + valueEqualsNodePairs = list2.toArray(new NodePair[list2.size()]); + } + + /** + * Used to check that benchmark does not mutate {@link #nodes}. + */ + private final Node[] originalNodes; + + /** + * The nodes processed by the benchmark. These arrays must be treated as read-only within the + * benchmark method. + */ + public final Node[] nodes; + public final Node[] valueNumberableLeafNodes; + public final NodePair[] valueEqualsNodePairs; + + public final class NodePair { + public final Node n1; + public final Node n2; + + public NodePair(Node n1, Node n2) { + this.n1 = n1; + this.n2 = n2; + } + } + + private int invocation; + + @TearDown(Level.Invocation) + public void afterInvocation() { + if (invocation == 0) { + // Only need to check the first invocation + invocation++; + for (int i = 0; i < nodes.length; i++) { + if (nodes[i] != originalNodes[i]) { + throw new InternalError(String.format("Benchmark method mutated node %d: original=%s, current=%s", i, originalNodes[i], nodes[i])); + } + } + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/ScheduleState.java Wed Sep 09 12:54:12 2015 +0200 @@ -0,0 +1,25 @@ +package com.oracle.graal.microbenchmarks.graal.util; + +import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.schedule.SchedulePhase.SchedulingStrategy; + +public class ScheduleState extends GraphState { + + public SchedulePhase schedule; + + private final SchedulingStrategy selectedStrategy; + + public ScheduleState(SchedulingStrategy selectedStrategy) { + this.selectedStrategy = selectedStrategy; + } + + public ScheduleState() { + this(SchedulingStrategy.LATEST_OUT_OF_LOOPS); + } + + @Override + public void beforeInvocation() { + schedule = new SchedulePhase(selectedStrategy); + super.beforeInvocation(); + } +}
--- a/mx.graal/suite.py Wed Sep 09 13:29:51 2015 +0200 +++ b/mx.graal/suite.py Wed Sep 09 12:54:12 2015 +0200 @@ -604,6 +604,20 @@ "workingSets" : "Graal,Bench", }, + "com.oracle.graal.microbenchmarks" : { + "subDir" : "graal", + "sourceDirs" : ["src"], + "dependencies" : [ + "JMH", + "com.oracle.graal.java", + "com.oracle.graal.runtime", + ], + "checkstyle" : "com.oracle.graal.graph", + "javaCompliance" : "1.8", + "annotationProcessors" : ["JMH"], + "workingSets" : "Graal,Bench", + }, + "com.oracle.graal.loop" : { "subDir" : "graal", "sourceDirs" : ["src"],