diff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java @ 16468:9fa5872291c1

Truffle: improve NodeIterator
author Andreas Woess <andreas.woess@jku.at>
date Thu, 10 Jul 2014 18:15:29 +0200
parents 17f7331dcc4f
children d86f948268da
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Jul 10 18:08:29 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Jul 10 18:15:29 2014 +0200
@@ -252,58 +252,53 @@
 
         private final class NodeIterator implements Iterator<Node> {
             private final Node node;
-            private final int childrenCount;
-            private int index;
+            private int fieldIndex;
+            private int arrayIndex;
 
             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 (index < childrenCount) {
-                    index++;
+                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);
+                    }
                 }
             }
 
             public boolean hasNext() {
-                return index < childrenCount;
+                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;
             }
 
             public Node next() {
-                try {
-                    return nodeAt(index);
-                } finally {
-                    forward();
+                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();
                 }
+                forward();
+                return next;
             }
 
             public void remove() {