# HG changeset patch # User Christian Humer # Date 1426018272 -3600 # Node ID e6a4ba0980dd7e9038396e7e0c579334af371efb # Parent 29916dcee0b84eac8bf1195532c0e443240396ce Truffle: add assertion to always be in atomic blocks for replaces as it now may be violated by NodeUtil#nonAtomicReplace. diff -r 29916dcee0b8 -r e6a4ba0980dd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- 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 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; + } }