changeset 22080:65e9fbb40e51

avoid publishing unadopted children in node replacement to fix potential race
author Andreas Woess <andreas.woess@oracle.com>
date Thu, 13 Aug 2015 18:22:22 +0200
parents 14ee5048c76e
children ff531952a91c
files truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java
diffstat 2 files changed, 12 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Aug 13 16:59:39 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Aug 13 18:22:22 2015 +0200
@@ -179,7 +179,7 @@
         adoptHelper();
     }
 
-    private void adoptHelper(final Node newChild) {
+    void adoptHelper(final Node newChild) {
         assert newChild != null;
         if (newChild == this) {
             throw new IllegalStateException("The parent of a node can never be the node itself.");
@@ -280,9 +280,7 @@
         // (aw) need to set parent *before* replace, so that (unsynchronized) getRootNode()
         // will always find the root node
         newNode.parent = this.parent;
-        if (NodeUtil.replaceChild(this.parent, this, newNode)) {
-            this.parent.adoptHelper(newNode);
-        } else {
+        if (!NodeUtil.replaceChild(this.parent, this, newNode, true)) {
             this.parent.adoptUnadoptedHelper(newNode);
         }
         reportReplace(this, newNode, reason);
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Aug 13 16:59:39 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Aug 13 18:22:22 2015 +0200
@@ -199,12 +199,19 @@
     }
 
     public static boolean replaceChild(Node parent, Node oldChild, Node newChild) {
+        return replaceChild(parent, oldChild, newChild, false);
+    }
+
+    static boolean replaceChild(Node parent, Node oldChild, Node newChild, boolean adopt) {
         CompilerAsserts.neverPartOfCompilation();
         NodeClass nodeClass = parent.getNodeClass();
 
         for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) {
             if (nodeField.getObject(parent) == oldChild) {
                 assert assertAssignable(nodeField, newChild);
+                if (adopt) {
+                    parent.adoptHelper(newChild);
+                }
                 nodeField.putObject(parent, newChild);
                 return true;
             }
@@ -217,6 +224,9 @@
                 for (int i = 0; i < array.length; i++) {
                     if (array[i] == oldChild) {
                         assert assertAssignable(nodeField, newChild);
+                        if (adopt) {
+                            parent.adoptHelper(newChild);
+                        }
                         array[i] = newChild;
                         return true;
                     }