changeset 19147:609480dfa0d8

Create ExplodeLoop plugin prototype. Special sort for blocks from bci block map builder for explode loop methods. Graph builder plugin for customizing static field accesses. New Truffle option TruffleExcludeAssertions default true that excludes assertion code from being partial evaluated in the new partial evaluator.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 05 Feb 2015 03:25:21 +0100
parents df63505aa8e9
children 276bc2752feb
files graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java
diffstat 9 files changed, 109 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Thu Feb 05 03:25:21 2015 +0100
@@ -95,7 +95,7 @@
             BciBlockMapping blockMap;
             try (Scope ds = Debug.scope("BciBlockMapping")) {
                 // compute the block map, setup exception handlers and get the entrypoint(s)
-                blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis());
+                blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis(), false);
             } catch (Throwable e) {
                 throw Debug.handle(e);
             }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Thu Feb 05 03:25:21 2015 +0100
@@ -737,7 +737,10 @@
     private void genGetStatic(JavaField field) {
         Kind kind = field.getKind();
         if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
-            appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field));
+            GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin();
+            if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) {
+                appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field));
+            }
         } else {
             handleUnresolvedLoadField(field, null);
         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Feb 05 03:25:21 2015 +0100
@@ -81,6 +81,7 @@
         public int endBci;
         public boolean isExceptionEntry;
         public boolean isLoopHeader;
+        public boolean isLastLoopEnd;
         public int loopId;
 
         /**
@@ -358,14 +359,16 @@
     private final boolean doLivenessAnalysis;
     public LocalLiveness liveness;
     private int blocksNotYetAssignedId;
+    private final boolean consecutiveLoopBlocks;
 
     /**
      * Creates a new BlockMap instance from bytecode of the given method .
      *
      * @param method the compiler interface method containing the code
      */
-    private BciBlockMapping(ResolvedJavaMethod method, boolean doLivenessAnalysis) {
+    private BciBlockMapping(ResolvedJavaMethod method, boolean doLivenessAnalysis, boolean consecutiveLoopBlocks) {
         this.doLivenessAnalysis = doLivenessAnalysis;
+        this.consecutiveLoopBlocks = consecutiveLoopBlocks;
         this.method = method;
         this.exceptionHandlers = method.getExceptionHandlers();
         this.stream = new BytecodeStream(method.getCode());
@@ -737,6 +740,7 @@
     }
 
     private void computeBlockOrder() {
+        int maxBlocks = blocksNotYetAssignedId;
         this.blocks = new BciBlock[blocksNotYetAssignedId];
         long loop = computeBlockOrder(blockMap[0]);
 
@@ -747,23 +751,61 @@
             throw new BailoutException("Non-reducible loop");
         }
 
-        if (blocks[0] == null) {
-            purgeLeadingNullBlocks();
+        if (blocks[0] != null && this.nextLoop == 0) {
+            // No unreached blocks and no loops
+            for (int i = 0; i < blocks.length; ++i) {
+                blocks[i].setId(i);
+            }
+            return;
+        }
+
+        // Purge null entries for unreached blocks and sort blocks such that loop bodies are always
+        // consecutively in the array.
+        int blockCount = maxBlocks - blocksNotYetAssignedId;
+        BciBlock[] newBlocks = new BciBlock[blockCount];
+        int next = 0;
+        for (int i = 0; i < blocks.length; ++i) {
+            BciBlock b = blocks[i];
+            if (b != null) {
+                b.setId(next);
+                newBlocks[next++] = b;
+                if (consecutiveLoopBlocks && b.isLoopHeader) {
+                    next = handleLoopHeader(newBlocks, next, i, b);
+                }
+            }
+        }
+        blocks = newBlocks;
+
+        if (consecutiveLoopBlocks && this.nextLoop > 2) {
+            System.out.println();
+            for (int i = 0; i < blocks.length; ++i) {
+                String succ = "";
+                for (BciBlock succBlock : blocks[i].getSuccessors()) {
+                    succ += succBlock.getId() + " ";
+                }
+                System.out.printf("%3s %10s %s %s succ=[%s]\n", blocks[i].getId(), Long.toBinaryString(blocks[i].loops), blocks[i].isLoopHeader, blocks[i].isLastLoopEnd, succ);
+            }
+            System.out.println();
         }
     }
 
-    private void purgeLeadingNullBlocks() {
-        // Purge leading null values due to unreachable blocks.
-        int i = 0;
-        for (; i < blocks.length; ++i) {
-            if (blocks[i] != null) {
-                break;
+    private int handleLoopHeader(BciBlock[] newBlocks, int nextStart, int i, BciBlock loopHeader) {
+        int next = nextStart;
+        BciBlock last = loopHeader;
+        for (int j = i + 1; j < blocks.length; ++j) {
+            BciBlock other = blocks[j];
+            if (other != null && (other.loops & (1L << loopHeader.loopId)) != 0) {
+                other.setId(next);
+                newBlocks[next++] = other;
+                last = other;
+                blocks[j] = null;
+                if (other.isLoopHeader) {
+                    next = handleLoopHeader(newBlocks, next, j, other);
+                }
             }
         }
-        blocks = Arrays.copyOfRange(blocks, i, blocks.length);
-        for (i = 0; i < blocks.length; ++i) {
-            blocks[i].setId(i);
-        }
+        last.isLastLoopEnd = true;
+        return next;
     }
 
     public void log(String name) {
@@ -885,6 +927,7 @@
             if (successor.active) {
                 // Reached block via backward branch.
                 block.isLoopEnd = true;
+                loops |= (1L << successor.loopId);
             }
         }
 
@@ -898,7 +941,6 @@
         block.active = false;
         blocksNotYetAssignedId--;
         blocks[blocksNotYetAssignedId] = block;
-        block.setId(blocksNotYetAssignedId);
 
         return loops;
     }
@@ -1154,8 +1196,8 @@
         }
     }
 
-    public static BciBlockMapping create(ResolvedJavaMethod method, boolean doLivenessAnalysis) {
-        BciBlockMapping map = new BciBlockMapping(method, doLivenessAnalysis);
+    public static BciBlockMapping create(ResolvedJavaMethod method, boolean doLivenessAnalysis, boolean consecutiveLoopBlocks) {
+        BciBlockMapping map = new BciBlockMapping(method, doLivenessAnalysis, consecutiveLoopBlocks);
         map.build();
         if (Debug.isDumpEnabled()) {
             Debug.dump(map, method.format("After block building %f %R %H.%n(%P)"));
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Feb 05 03:25:21 2015 +0100
@@ -191,6 +191,7 @@
             private FixedWithNextNode beforeUnwindNode;
 
             private FixedWithNextNode lastInstr;                 // the last instruction added
+            private final boolean explodeLoops;
 
             public BytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, int entryBCI) {
                 super(metaAccess, method, graphBuilderConfig, optimisticOpts);
@@ -200,6 +201,13 @@
                     lnt = method.getLineNumberTable();
                     previousLineNumber = -1;
                 }
+
+                LoopExplosionPlugin loopExplosionPlugin = graphBuilderConfig.getLoopExplosionPlugin();
+                if (loopExplosionPlugin != null) {
+                    explodeLoops = loopExplosionPlugin.shouldExplodeLoops(method);
+                } else {
+                    explodeLoops = false;
+                }
             }
 
             public ValueNode getReturnValue() {
@@ -228,7 +236,7 @@
                 try (Indent indent = Debug.logAndIndent("build graph for %s", method)) {
 
                     // compute the block map, setup exception handlers and get the entrypoint(s)
-                    BciBlockMapping blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis());
+                    BciBlockMapping blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis(), explodeLoops);
                     loopHeaders = blockMap.getLoopHeaders();
                     liveness = blockMap.liveness;
 
@@ -571,7 +579,7 @@
 
             @Override
             protected ValueNode genIntegerEquals(ValueNode x, ValueNode y) {
-                return new IntegerEqualsNode(x, y);
+                return IntegerEqualsNode.create(x, y, constantReflectionProvider);
             }
 
             @Override
@@ -941,7 +949,7 @@
                 JsrScope scope = currentBlock.getJsrScope();
                 int retAddress = scope.nextReturnAddress();
                 ConstantNode returnBciNode = getJsrConstant(retAddress);
-                LogicNode guard = new IntegerEqualsNode(local, returnBciNode);
+                LogicNode guard = IntegerEqualsNode.create(local, returnBciNode, constantReflectionProvider);
                 guard = currentGraph.unique(guard);
                 append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile));
                 if (!successor.getJsrScope().equals(scope.pop())) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Thu Feb 05 03:25:21 2015 +0100
@@ -38,7 +38,15 @@
 public interface GraphBuilderPlugins {
 
     public interface LoadFieldPlugin extends GraphBuilderPlugin {
-        boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field);
+        @SuppressWarnings("unused")
+        default boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) {
+            return false;
+        }
+
+        @SuppressWarnings("unused")
+        default boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) {
+            return false;
+        }
     }
 
     public interface ParameterPlugin extends GraphBuilderPlugin {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Thu Feb 05 03:25:21 2015 +0100
@@ -32,7 +32,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
-public class IntegerEqualsNode extends CompareNode {
+public final class IntegerEqualsNode extends CompareNode {
 
     public IntegerEqualsNode(ValueNode x, ValueNode y) {
         super(Condition.EQ, false, x, y);
@@ -40,6 +40,15 @@
         assert !y.getKind().isNumericFloat() && y.getKind() != Kind.Object;
     }
 
+    public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
+        LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false);
+        if (result != null) {
+            return result;
+        } else {
+            return new IntegerEqualsNode(x, y);
+        }
+    }
+
     @Override
     protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         PrimitiveConstant primitive = (PrimitiveConstant) constant;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Feb 05 03:25:21 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "==")
-public class ObjectEqualsNode extends PointerEqualsNode implements Virtualizable {
+public final class ObjectEqualsNode extends PointerEqualsNode implements Virtualizable {
 
     public ObjectEqualsNode(ValueNode x, ValueNode y) {
         super(x, y);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Feb 05 03:25:21 2015 +0100
@@ -146,19 +146,26 @@
     private class InterceptLoadFieldPlugin implements GraphBuilderPlugins.LoadFieldPlugin {
 
         public boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) {
-            System.out.println("Load field plugin called for receiver: " + receiver + " and field " + field);
-
             if (receiver.isConstant()) {
                 JavaConstant asJavaConstant = receiver.asJavaConstant();
                 JavaConstant result = providers.getConstantReflection().readConstantFieldValue(field, asJavaConstant);
                 if (result != null) {
                     ConstantNode constantNode = builder.append(ConstantNode.forConstant(result, providers.getMetaAccess()));
-                    builder.push(constantNode.getKind(), constantNode);
+                    builder.push(constantNode.getKind().getStackKind(), constantNode);
                     return true;
                 }
             }
             return false;
         }
+
+        public boolean apply(GraphBuilderContext builder, ResolvedJavaField staticField) {
+            if (TruffleCompilerOptions.TruffleExcludeAssertions.getValue() && staticField.getName().equals("$assertionsDisabled")) {
+                ConstantNode trueNode = builder.append(ConstantNode.forBoolean(true));
+                builder.push(trueNode.getKind().getStackKind(), trueNode);
+                return true;
+            }
+            return false;
+        }
     }
 
     private class InterceptReceiverPlugin implements GraphBuilderPlugins.ParameterPlugin {
@@ -188,7 +195,7 @@
     private class LoopExplosionPlugin implements GraphBuilderPlugins.LoopExplosionPlugin {
 
         public boolean shouldExplodeLoops(ResolvedJavaMethod method) {
-            return method.getAnnotation(ExplodeLoop.class) == null;
+            return method.getAnnotation(ExplodeLoop.class) != null;
         }
 
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Thu Feb 05 03:22:35 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Thu Feb 05 03:25:21 2015 +0100
@@ -44,6 +44,9 @@
     @Option(help = "Restrict compilation to comma-separated list of includes (or excludes prefixed with tilde)", type = OptionType.Debug)
     public static final OptionValue<String> TruffleCompileOnly = new OptionValue<>(null);
 
+    @Option(help = "Exclude assertion code from Truffle compilations", type = OptionType.Debug)
+    public static final StableOptionValue<Boolean> TruffleExcludeAssertions = new StableOptionValue<>(true);
+
     @Option(help = "Compile call target when call count exceeds this threshold", type = OptionType.User)
     public static final OptionValue<Integer> TruffleCompilationThreshold = new OptionValue<>(1000);