diff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java @ 19767:e6a4ba0980dd

Truffle: add assertion to always be in atomic blocks for replaces as it now may be violated by NodeUtil#nonAtomicReplace.
author Christian Humer <christian.humer@gmail.com>
date Tue, 10 Mar 2015 21:11:12 +0100
parents f682b9e6ca07
children 907128d02b31
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Mar 10 22:18:53 2015 -0700
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Tue Mar 10 21:11:12 2015 +0100
@@ -269,6 +269,7 @@
 
     final void replaceHelper(Node newNode, CharSequence reason) {
         CompilerAsserts.neverPartOfCompilation();
+        assert inAtomicBlock();
         if (this.getParent() == null) {
             throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
         }
@@ -573,7 +574,12 @@
     public final void atomic(Runnable closure) {
         RootNode rootNode = getRootNode();
         synchronized (rootNode != null ? rootNode : GIL) {
-            closure.run();
+            assert enterAtomic();
+            try {
+                closure.run();
+            } finally {
+                assert exitAtomic();
+            }
         }
     }
 
@@ -581,7 +587,12 @@
         try {
             RootNode rootNode = getRootNode();
             synchronized (rootNode != null ? rootNode : GIL) {
-                return closure.call();
+                assert enterAtomic();
+                try {
+                    return closure.call();
+                } finally {
+                    assert exitAtomic();
+                }
             }
         } catch (RuntimeException | Error e) {
             throw e;
@@ -618,4 +629,28 @@
     }
 
     private static final Object GIL = new Object();
+
+    private static final ThreadLocal<Integer> IN_ATOMIC_BLOCK = new ThreadLocal<>();
+
+    private static boolean inAtomicBlock() {
+        Integer value = IN_ATOMIC_BLOCK.get();
+        if (value == null) {
+            return false;
+        }
+        return value > 0;
+    }
+
+    private static boolean enterAtomic() {
+        Integer currentValue = IN_ATOMIC_BLOCK.get();
+        if (currentValue == null) {
+            currentValue = 0;
+        }
+        IN_ATOMIC_BLOCK.set(currentValue + 1);
+        return true;
+    }
+
+    private static boolean exitAtomic() {
+        IN_ATOMIC_BLOCK.set(IN_ATOMIC_BLOCK.get() - 1);
+        return true;
+    }
 }