comparison 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
comparison
equal deleted inserted replaced
19766:29916dcee0b8 19767:e6a4ba0980dd
267 return replace(newNode, ""); 267 return replace(newNode, "");
268 } 268 }
269 269
270 final void replaceHelper(Node newNode, CharSequence reason) { 270 final void replaceHelper(Node newNode, CharSequence reason) {
271 CompilerAsserts.neverPartOfCompilation(); 271 CompilerAsserts.neverPartOfCompilation();
272 assert inAtomicBlock();
272 if (this.getParent() == null) { 273 if (this.getParent() == null) {
273 throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); 274 throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
274 } 275 }
275 if (sourceSection != null && newNode.getSourceSection() == null) { 276 if (sourceSection != null && newNode.getSourceSection() == null) {
276 // Pass on the source section to the new node. 277 // Pass on the source section to the new node.
571 } 572 }
572 573
573 public final void atomic(Runnable closure) { 574 public final void atomic(Runnable closure) {
574 RootNode rootNode = getRootNode(); 575 RootNode rootNode = getRootNode();
575 synchronized (rootNode != null ? rootNode : GIL) { 576 synchronized (rootNode != null ? rootNode : GIL) {
576 closure.run(); 577 assert enterAtomic();
578 try {
579 closure.run();
580 } finally {
581 assert exitAtomic();
582 }
577 } 583 }
578 } 584 }
579 585
580 public final <T> T atomic(Callable<T> closure) { 586 public final <T> T atomic(Callable<T> closure) {
581 try { 587 try {
582 RootNode rootNode = getRootNode(); 588 RootNode rootNode = getRootNode();
583 synchronized (rootNode != null ? rootNode : GIL) { 589 synchronized (rootNode != null ? rootNode : GIL) {
584 return closure.call(); 590 assert enterAtomic();
591 try {
592 return closure.call();
593 } finally {
594 assert exitAtomic();
595 }
585 } 596 }
586 } catch (RuntimeException | Error e) { 597 } catch (RuntimeException | Error e) {
587 throw e; 598 throw e;
588 } catch (Exception e) { 599 } catch (Exception e) {
589 throw new RuntimeException(e); 600 throw new RuntimeException(e);
616 } 627 }
617 return ""; 628 return "";
618 } 629 }
619 630
620 private static final Object GIL = new Object(); 631 private static final Object GIL = new Object();
632
633 private static final ThreadLocal<Integer> IN_ATOMIC_BLOCK = new ThreadLocal<>();
634
635 private static boolean inAtomicBlock() {
636 Integer value = IN_ATOMIC_BLOCK.get();
637 if (value == null) {
638 return false;
639 }
640 return value > 0;
641 }
642
643 private static boolean enterAtomic() {
644 Integer currentValue = IN_ATOMIC_BLOCK.get();
645 if (currentValue == null) {
646 currentValue = 0;
647 }
648 IN_ATOMIC_BLOCK.set(currentValue + 1);
649 return true;
650 }
651
652 private static boolean exitAtomic() {
653 IN_ATOMIC_BLOCK.set(IN_ATOMIC_BLOCK.get() - 1);
654 return true;
655 }
621 } 656 }