Mercurial > hg > truffle
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 } |