Mercurial > hg > graal-compiler
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. |