comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java @ 14628:a08b8694f556

Truffle: Node API changes deprecate adoptChild, no longer needed in constructor add Node#insert for inserting new nodes into the tree (previously adoptChild) add Node#adoptChildren() helper method that adopts all (direct and indirect) children of a node, automatically called in TruffleRuntime#createCallTarget
author Andreas Woess <andreas.woess@jku.at>
date Wed, 19 Mar 2014 23:11:46 +0100
parents 6189c1983cd3
children ba52fbec5b6c
comparison
equal deleted inserted replaced
14627:46c020971d9c 14628:a08b8694f556
131 * node. 131 * node.
132 * 132 *
133 * @param newChildren the array of new children whose parent should be updated 133 * @param newChildren the array of new children whose parent should be updated
134 * @return the array of new children 134 * @return the array of new children
135 */ 135 */
136 protected final <T extends Node> T[] adoptChildren(T[] newChildren) { 136 @SuppressWarnings("static-method")
137 if (newChildren != null) { 137 @Deprecated
138 for (T n : newChildren) { 138 protected final <T extends Node> T[] adoptChildren(final T[] newChildren) {
139 adoptChild(n);
140 }
141 }
142 return newChildren; 139 return newChildren;
143 } 140 }
144 141
145 /** 142 /**
146 * Method that updates the link to the parent in the specified new child node to this node. 143 * Method that updates the link to the parent in the specified new child node to this node.
147 * 144 *
148 * @param newChild the new child whose parent should be updated 145 * @param newChild the new child whose parent should be updated
149 * @return the new child 146 * @return the new child
150 */ 147 */
151 protected final <T extends Node> T adoptChild(T newChild) { 148 @SuppressWarnings("static-method")
152 if (newChild != null) { 149 @Deprecated
153 if (newChild == this) { 150 protected final <T extends Node> T adoptChild(final T newChild) {
154 throw new IllegalStateException("The parent of a node can never be the node itself.");
155 }
156 ((Node) newChild).parent = this;
157 }
158 return newChild; 151 return newChild;
152 }
153
154 /**
155 * Method that updates the link to the parent in the array of specified new child nodes to this
156 * node.
157 *
158 * @param newChildren the array of new children whose parent should be updated
159 * @return the array of new children
160 */
161 protected final <T extends Node> T[] insert(final T[] newChildren) {
162 CompilerDirectives.transferToInterpreterAndInvalidate();
163 assert newChildren != null;
164 for (Node newChild : newChildren) {
165 adoptHelper(newChild);
166 }
167 return newChildren;
168 }
169
170 /**
171 * Method that updates the link to the parent in the specified new child node to this node.
172 *
173 * @param newChild the new child whose parent should be updated
174 * @return the new child
175 */
176 protected final <T extends Node> T insert(final T newChild) {
177 CompilerDirectives.transferToInterpreterAndInvalidate();
178 assert newChild != null;
179 adoptHelper(newChild);
180 return newChild;
181 }
182
183 public final void adoptChildren() {
184 CompilerDirectives.transferToInterpreterAndInvalidate();
185 adoptHelper();
186 }
187
188 private void adoptHelper(final Node newChild) {
189 assert newChild != null;
190 if (newChild == this) {
191 throw new IllegalStateException("The parent of a node can never be the node itself.");
192 }
193 newChild.parent = this;
194 newChild.adoptHelper();
195 }
196
197 private void adoptHelper() {
198 Iterable<Node> children = this.getChildren();
199 for (Node child : children) {
200 if (child != null && child.getParent() != this) {
201 this.adoptHelper(child);
202 }
203 }
204 }
205
206 private void adoptUnadoptedHelper(final Node newChild) {
207 assert newChild != null;
208 if (newChild == this) {
209 throw new IllegalStateException("The parent of a node can never be the node itself.");
210 }
211 newChild.parent = this;
212 newChild.adoptUnadoptedHelper();
213 }
214
215 private void adoptUnadoptedHelper() {
216 Iterable<Node> children = this.getChildren();
217 for (Node child : children) {
218 if (child != null && child.getParent() == null) {
219 this.adoptUnadoptedHelper(child);
220 }
221 }
159 } 222 }
160 223
161 /** 224 /**
162 * Returns properties of this node interesting for debugging and can be overwritten by 225 * Returns properties of this node interesting for debugging and can be overwritten by
163 * subclasses to add their own custom properties. 226 * subclasses to add their own custom properties.
184 * 247 *
185 * @param newNode the new node that is the replacement 248 * @param newNode the new node that is the replacement
186 * @param reason a description of the reason for the replacement 249 * @param reason a description of the reason for the replacement
187 * @return the new node 250 * @return the new node
188 */ 251 */
189 public final <T extends Node> T replace(T newNode, CharSequence reason) { 252 public final <T extends Node> T replace(final T newNode, final CharSequence reason) {
190 CompilerDirectives.transferToInterpreterAndInvalidate(); 253 CompilerDirectives.transferToInterpreterAndInvalidate();
254 replaceHelper(newNode, reason);
255 return newNode;
256 }
257
258 /**
259 * Replaces this node with another node. If there is a source section (see
260 * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
261 *
262 * @param newNode the new node that is the replacement
263 * @return the new node
264 */
265 public final <T extends Node> T replace(T newNode) {
266 return replace(newNode, "");
267 }
268
269 private void replaceHelper(Node newNode, CharSequence reason) {
270 CompilerAsserts.neverPartOfCompilation();
191 if (this.getParent() == null) { 271 if (this.getParent() == null) {
192 throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); 272 throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
193 } 273 }
194 if (sourceSection != null && newNode.getSourceSection() == null) { 274 if (sourceSection != null && newNode.getSourceSection() == null) {
195 // Pass on the source section to the new node. 275 // Pass on the source section to the new node.
196 newNode.assignSourceSection(sourceSection); 276 newNode.assignSourceSection(sourceSection);
197 } 277 }
278 // (aw) need to set parent *before* replace, so that (unsynchronized) getRootNode()
279 // will always find the root node
280 newNode.parent = this.parent;
281 if (NodeUtil.replaceChild(this.parent, this, newNode)) {
282 this.parent.adoptHelper(newNode);
283 } else {
284 this.parent.adoptUnadoptedHelper(newNode);
285 }
286 reportReplace(this, newNode, reason);
198 onReplace(newNode, reason); 287 onReplace(newNode, reason);
199 ((Node) newNode).parent = this.parent;
200 if (!NodeUtil.replaceChild(this.parent, this, newNode)) {
201 fixupTree();
202 }
203 reportReplace(this, newNode, reason);
204 return newNode;
205 }
206
207 /**
208 * Rewrite has failed; the tree is likely inconsistent, so fix any stale parent references.
209 *
210 * This is a rather expensive operation but rare to occur.
211 */
212 private void fixupTree() {
213 Node rootNode = getRootNode();
214 if (rootNode == null) {
215 throw new UnsupportedOperationException("Tree does not have a root node.");
216 }
217 int fixCount = rootNode.fixupChildren();
218 assert fixCount != 0 : "sanity check failed: missing @Child[ren] or adoptChild?";
219 // if nothing had to be fixed, rewrite failed due to node not being a proper child.
220 }
221
222 private int fixupChildren() {
223 int fixCount = 0;
224 for (Node child : getChildren()) {
225 if (child != null) {
226 if (child.parent != this) {
227 child.parent = this;
228 fixCount++;
229 }
230 fixCount += child.fixupChildren();
231 }
232 }
233 return fixCount;
234 }
235
236 /**
237 * Replaces this node with another node. If there is a source section (see
238 * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
239 *
240 * @param newNode the new node that is the replacement
241 * @return the new node
242 */
243 public final <T extends Node> T replace(T newNode) {
244 return replace(newNode, "");
245 } 288 }
246 289
247 /** 290 /**
248 * Checks if this node is properly adopted by a parent and can be replaced. 291 * Checks if this node is properly adopted by a parent and can be replaced.
249 * 292 *