changeset 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 a7d9b88ecd68
children 0eb70f622d01
files graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java
diffstat 2 files changed, 84 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java	Tue Jul 22 15:06:15 2014 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java	Tue Jul 22 16:32:43 2014 +0200
@@ -95,4 +95,50 @@
             return 21;
         }
     }
+
+    @Test
+    public void testMultipleChildrenFields() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildNode firstChild = new TestChildNode();
+        TestChildNode secondChild = new TestChildNode();
+        TestChildNode thirdChild = new TestChildNode();
+        TestChildNode forthChild = new TestChildNode();
+        TestRootNode rootNode = new TestRoot2Node(new TestChildNode[]{firstChild, secondChild}, new TestChildNode[]{thirdChild, forthChild});
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Assert.assertEquals(rootNode, firstChild.getParent());
+        Assert.assertEquals(rootNode, secondChild.getParent());
+        Assert.assertEquals(rootNode, thirdChild.getParent());
+        Assert.assertEquals(rootNode, forthChild.getParent());
+        Iterator<Node> iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(firstChild, iterator.next());
+        Assert.assertEquals(secondChild, iterator.next());
+        Assert.assertEquals(thirdChild, iterator.next());
+        Assert.assertEquals(forthChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Object result = target.call();
+        Assert.assertEquals(2 * 42, result);
+    }
+
+    class TestRoot2Node extends TestRootNode {
+        @Children private final TestChildNode[] children1;
+        @Children private final TestChildNode[] children2;
+
+        public TestRoot2Node(TestChildNode[] children1, TestChildNode[] children2) {
+            super(new TestChildNode[0]);
+            this.children1 = children1;
+            this.children2 = children2;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children1.length; ++i) {
+                sum += children1[i].execute();
+            }
+            for (int i = 0; i < children2.length; ++i) {
+                sum += children2[i].execute();
+            }
+            return sum;
+        }
+    }
 }
--- 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() {