diff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java @ 16581:8be5c68a779d

Truffle: revert to previous iterator implementation, add test case
author Andreas Woess <andreas.woess@jku.at>
date Tue, 22 Jul 2014 16:32:43 +0200
parents a3b0a2d61e62
children 70f47dbbcabd
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Tue Jul 22 15:06:15 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Tue Jul 22 16:32:43 2014 +0200
@@ -252,53 +252,58 @@
 
         private final class NodeIterator implements Iterator<Node> {
             private final Node node;
-            private int fieldIndex;
-            private int arrayIndex;
+            private final int childrenCount;
+            private int index;
 
             protected NodeIterator(Node node) {
                 this.node = node;
+                this.index = 0;
+                this.childrenCount = childrenCount();
+            }
+
+            private int childrenCount() {
+                int nodeCount = childOffsets.length;
+                for (long fieldOffset : childrenOffsets) {
+                    Node[] children = ((Node[]) unsafe.getObject(node, fieldOffset));
+                    if (children != null) {
+                        nodeCount += children.length;
+                    }
+                }
+                return nodeCount;
+            }
+
+            private Node nodeAt(int idx) {
+                int nodeCount = childOffsets.length;
+                if (idx < nodeCount) {
+                    return (Node) unsafe.getObject(node, childOffsets[idx]);
+                } else {
+                    for (long fieldOffset : childrenOffsets) {
+                        Node[] nodeArray = (Node[]) unsafe.getObject(node, fieldOffset);
+                        if (idx < nodeCount + nodeArray.length) {
+                            return nodeArray[idx - nodeCount];
+                        }
+                        nodeCount += nodeArray.length;
+                    }
+                }
+                return null;
             }
 
             private void forward() {
-                if (fieldIndex < childOffsets.length) {
-                    fieldIndex++;
-                } else if (fieldIndex < childOffsets.length + childrenOffsets.length) {
-                    if (arrayIndex + 1 < currentChildrenArrayLength()) {
-                        arrayIndex++;
-                    } else {
-                        arrayIndex = 0;
-                        do {
-                            fieldIndex++;
-                        } while (fieldIndex < childOffsets.length + childrenOffsets.length && currentChildrenArrayLength() == 0);
-                    }
+                if (index < childrenCount) {
+                    index++;
                 }
             }
 
             public boolean hasNext() {
-                return fieldIndex < childOffsets.length || (fieldIndex < childOffsets.length + childrenOffsets.length && arrayIndex < currentChildrenArrayLength());
-            }
-
-            private Node[] currentChildrenArray() {
-                assert fieldIndex >= childOffsets.length && fieldIndex < childOffsets.length + childrenOffsets.length;
-                return (Node[]) unsafe.getObject(node, childrenOffsets[fieldIndex - childOffsets.length]);
-            }
-
-            private int currentChildrenArrayLength() {
-                Node[] childrenArray = currentChildrenArray();
-                return childrenArray != null ? childrenArray.length : 0;
+                return index < childrenCount;
             }
 
             public Node next() {
-                Node next;
-                if (fieldIndex < childOffsets.length) {
-                    next = (Node) unsafe.getObject(node, childOffsets[fieldIndex]);
-                } else if (fieldIndex < childOffsets.length + childrenOffsets.length) {
-                    next = currentChildrenArray()[arrayIndex];
-                } else {
-                    throw new NoSuchElementException();
+                try {
+                    return nodeAt(index);
+                } finally {
+                    forward();
                 }
-                forward();
-                return next;
             }
 
             public void remove() {