changeset 19149:183f7d3a93e5

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 05 Feb 2015 03:42:42 +0100
parents 276bc2752feb (diff) b8b8f0fcb8c3 (current diff)
children bb25b153433c
files
diffstat 12 files changed, 155 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Thu Feb 05 03:42:42 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	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Thu Feb 05 03:42:42 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	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Thu Feb 05 03:42:42 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/GraphBuilderConfiguration.java	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Thu Feb 05 03:42:42 2015 +0100
@@ -39,6 +39,7 @@
     private GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin;
     private GraphBuilderPlugins.ParameterPlugin parameterPlugin;
     private GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin;
+    private GraphBuilderPlugins.LoopExplosionPlugin loopExplosionPlugin;
 
     public static enum DebugInfoMode {
         SafePointsOnly,
@@ -167,4 +168,12 @@
     public void setInlineInvokePlugin(GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin) {
         this.inlineInvokePlugin = inlineInvokePlugin;
     }
+
+    public GraphBuilderPlugins.LoopExplosionPlugin getLoopExplosionPlugin() {
+        return loopExplosionPlugin;
+    }
+
+    public void setLoopExplosionPlugin(GraphBuilderPlugins.LoopExplosionPlugin loopExplosionPlugin) {
+        this.loopExplosionPlugin = loopExplosionPlugin;
+    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Feb 05 03:42:42 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	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Thu Feb 05 03:42:42 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 {
@@ -49,6 +57,10 @@
         boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth);
     }
 
+    public interface LoopExplosionPlugin extends GraphBuilderPlugin {
+        boolean shouldExplodeLoops(ResolvedJavaMethod method);
+    }
+
     /**
      * Plugin for handling a method invocation.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Thu Feb 05 03:42:42 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	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Feb 05 03:42:42 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/FrameWithoutBoxing.java	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java	Thu Feb 05 03:42:42 2015 +0100
@@ -49,7 +49,10 @@
         this.arguments = arguments;
         int size = descriptor.getSize();
         this.locals = new Object[size];
-        Arrays.fill(locals, descriptor.getDefaultValue());
+        Object defaultValue = descriptor.getDefaultValue();
+        if (defaultValue != null) {
+            Arrays.fill(locals, defaultValue);
+        }
         this.primitiveLocals = new long[size];
         this.tags = new byte[size];
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Feb 05 03:42:42 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -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 {
@@ -185,12 +192,21 @@
 
     }
 
+    private class LoopExplosionPlugin implements GraphBuilderPlugins.LoopExplosionPlugin {
+
+        public boolean shouldExplodeLoops(ResolvedJavaMethod method) {
+            return method.getAnnotation(ExplodeLoop.class) != null;
+        }
+
+    }
+
     @SuppressWarnings("unused")
     private void fastPartialEvaluation(OptimizedCallTarget callTarget, Assumptions assumptions, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) {
         GraphBuilderConfiguration newConfig = configForRoot.copy();
         newConfig.setLoadFieldPlugin(new InterceptLoadFieldPlugin());
         newConfig.setParameterPlugin(new InterceptReceiverPlugin(callTarget));
         newConfig.setInlineInvokePlugin(new InlineInvokePlugin());
+        newConfig.setLoopExplosionPlugin(new LoopExplosionPlugin());
         DefaultGraphBuilderPlugins plugins = new DefaultGraphBuilderPlugins();
         Iterable<GraphBuilderPluginsProvider> sl = Services.load(GraphBuilderPluginsProvider.class);
         for (GraphBuilderPluginsProvider p : sl) {
@@ -199,6 +215,14 @@
         new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), newConfig, plugins,
                         TruffleCompilerImpl.Optimizations).apply(graph);
         Debug.dump(graph, "After FastPE");
+
+        // Do single partial escape and canonicalization pass.
+        try (Scope pe = Debug.scope("TrufflePartialEscape", graph)) {
+            new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext);
+            new IncrementalCanonicalizerPhase<>(canonicalizer, new ConditionalEliminationPhase()).apply(graph, tierContext);
+        } catch (Throwable t) {
+            Debug.handle(t);
+        }
     }
 
     private void partialEvaluation(final OptimizedCallTarget callTarget, final Assumptions assumptions, final StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Thu Feb 05 03:42:42 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);
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java	Wed Feb 04 17:02:31 2015 -0800
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java	Thu Feb 05 03:42:42 2015 +0100
@@ -27,13 +27,16 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
+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.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.truffle.*;
 import com.oracle.graal.truffle.nodes.frame.*;
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
 
 /**
  * Provider of {@link GraphBuilderPlugin}s for Truffle classes.
@@ -41,6 +44,15 @@
 @ServiceProvider(GraphBuilderPluginsProvider.class)
 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;
+            }
+        });
+
         Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class);
         r.register0("inInterpreter", new InvocationPlugin() {
             public boolean apply(GraphBuilderContext builder) {