comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java @ 12494:57b8a41c0e18

Truffle: fix possible node rewrite failures after recursive calls.
author Andreas Woess <andreas.woess@jku.at>
date Sun, 20 Oct 2013 03:26:03 +0200
parents c0c616fe3588
children b7c8b843dc7b
comparison
equal deleted inserted replaced
12493:0276bea0f72f 12494:57b8a41c0e18
168 * 168 *
169 * @param newNode the new node that is the replacement 169 * @param newNode the new node that is the replacement
170 * @param reason a description of the reason for the replacement 170 * @param reason a description of the reason for the replacement
171 * @return the new node 171 * @return the new node
172 */ 172 */
173 @SuppressWarnings({"unchecked"})
174 public final <T extends Node> T replace(T newNode, String reason) { 173 public final <T extends Node> T replace(T newNode, String reason) {
175 if (this.getParent() == null) { 174 if (this.getParent() == null) {
176 throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); 175 throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
177 } 176 }
178 if (sourceSection != null && newNode.getSourceSection() == null) { 177 if (sourceSection != null && newNode.getSourceSection() == null) {
179 // Pass on the source section to the new node. 178 // Pass on the source section to the new node.
180 newNode.assignSourceSection(sourceSection); 179 newNode.assignSourceSection(sourceSection);
181 } 180 }
182 onReplace(newNode, reason); 181 onReplace(newNode, reason);
183 return (T) this.getParent().replaceChild(this, newNode); 182 ((Node) newNode).parent = this.parent;
184 } 183 if (!NodeUtil.replaceChild(this.parent, this, newNode)) {
185 184 fixupTree();
186 private <T extends Node> T replaceChild(T oldChild, T newChild) { 185 }
187 NodeUtil.replaceChild(this, oldChild, newChild); 186 return newNode;
188 adoptChild(newChild); 187 }
189 return newChild; 188
189 /**
190 * Rewrite has failed; the tree is likely inconsistent, so fix any stale parent references.
191 *
192 * This is a rather expensive operation but rare to occur.
193 */
194 private void fixupTree() {
195 Node rootNode = NodeUtil.findParent(this, RootNode.class);
196 if (rootNode == null) {
197 throw new UnsupportedOperationException("Tree does not have a root node.");
198 }
199 rootNode.fixupChildren();
200 }
201
202 private void fixupChildren() {
203 for (Node child : getChildren()) {
204 if (child != null) {
205 if (child.parent != this) {
206 child.parent = this;
207 }
208 child.fixupChildren();
209 }
210 }
190 } 211 }
191 212
192 /** 213 /**
193 * Replaces this node with another node. If there is a source section (see 214 * Replaces this node with another node. If there is a source section (see
194 * {@link #getSourceSection()}) associated with this node, it is transferred to the new node. 215 * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.