changeset 22925:7e4d254d6ff6

Truffle: lazily clone uninitialized root node
author Andreas Woess <andreas.woess@oracle.com>
date Mon, 02 Nov 2015 19:10:39 +0100
parents 8adfe7597660
children 321ae5145865
files graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java
diffstat 1 files changed, 18 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Nov 02 14:31:27 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Nov 02 19:10:39 2015 +0100
@@ -75,6 +75,7 @@
  * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
  */
 public class OptimizedCallTarget extends InstalledCode implements RootCallTarget, LoopCountReceiver, ReplaceObserver {
+    private static final RootNode UNINITIALIZED = RootNode.createConstantNode(null);
 
     protected final GraalTruffleRuntime runtime;
     private SpeculationLog speculationLog;
@@ -89,8 +90,8 @@
     @CompilationFinal private Class<?> profiledReturnType;
     @CompilationFinal private Assumption profiledReturnTypeAssumption;
 
-    private final RootNode uninitializedRootNode;
     private final RootNode rootNode;
+    private volatile RootNode uninitializedRootNode = UNINITIALIZED;
 
     /* Experimental fields for new splitting. */
     private final Map<TruffleStamp, OptimizedCallTarget> splitVersions = new HashMap<>();
@@ -99,6 +100,7 @@
     private TruffleInlining inlining;
     private int cachedNonTrivialNodeCount = -1;
     private boolean compiling;
+    private int cloneIndex;
 
     /**
      * When this call target is inlined, the inlining {@link InstalledCode} registers this
@@ -120,7 +122,6 @@
         this.compilationPolicy = compilationPolicy;
         this.rootNode.adoptChildren();
         this.rootNode.applyInstrumentation();
-        this.uninitializedRootNode = sourceCallTarget == null ? cloneRootNode(rootNode) : sourceCallTarget.uninitializedRootNode;
         if (TruffleCallTargetProfiling.getValue()) {
             this.compilationProfile = new TraceCompilationProfile();
         } else {
@@ -156,13 +157,12 @@
         return argumentStamp;
     }
 
-    private int cloneIndex;
-
     public int getCloneIndex() {
         return cloneIndex;
     }
 
     public OptimizedCallTarget cloneUninitialized() {
+        ensureCloned();
         RootNode copiedRoot = cloneRootNode(uninitializedRootNode);
         if (copiedRoot == null) {
             return null;
@@ -172,6 +172,16 @@
         return splitTarget;
     }
 
+    private void ensureCloned() {
+        if (uninitializedRootNode == UNINITIALIZED) {
+            synchronized (this) {
+                if (uninitializedRootNode == UNINITIALIZED) {
+                    this.uninitializedRootNode = sourceCallTarget == null ? cloneRootNode(rootNode) : sourceCallTarget.uninitializedRootNode;
+                }
+            }
+        }
+    }
+
     public Map<TruffleStamp, OptimizedCallTarget> getSplitVersions() {
         return splitVersions;
     }
@@ -358,6 +368,9 @@
             // Stubs were deoptimized => reinstall.
             this.runtime.reinstallStubs();
         } else {
+            if (uninitializedRootNode == UNINITIALIZED) {
+                ensureCloned();
+            }
             compilationProfile.reportInterpreterCall();
             if (!isCompiling() && compilationPolicy.shouldCompile(compilationProfile, getCompilerOptions())) {
                 compile();
@@ -368,6 +381,7 @@
     public final void compile() {
         if (!isCompiling()) {
             compiling = true;
+            ensureCloned();
             runtime.compile(this, TruffleBackgroundCompilation.getValue() && !TruffleCompilationExceptionsAreThrown.getValue());
         }
     }