diff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java @ 10742:99789440ce28

Truffle: Added assertions to replaceChild.
author Christian Humer <christian.humer@gmail.com>
date Sat, 13 Jul 2013 17:14:23 +0200
parents 84b944726df2
children b221e31d7b0b
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Sat Jul 13 17:13:08 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Sat Jul 13 17:14:23 2013 +0200
@@ -352,17 +352,26 @@
     public static void replaceChild(Node parent, Node oldChild, Node newChild) {
         NodeClass nodeClass = NodeClass.get(parent.getClass());
 
-        for (long fieldOffset : nodeClass.childOffsets) {
+        long[] fieldOffsets = nodeClass.childOffsets;
+        for (int i = 0; i < fieldOffsets.length; i++) {
+            long fieldOffset = fieldOffsets[i];
             if (unsafe.getObject(parent, fieldOffset) == oldChild) {
+                assert assertAssignable(nodeClass, parent, oldChild, newChild);
                 unsafe.putObject(parent, fieldOffset, newChild);
             }
         }
-        for (long fieldOffset : nodeClass.childrenOffsets) {
-            Node[] array = (Node[]) unsafe.getObject(parent, fieldOffset);
-            if (array != null) {
-                for (int i = 0; i < array.length; i++) {
-                    if (array[i] == oldChild) {
-                        array[i] = newChild;
+
+        long[] childrenOffsets = nodeClass.childrenOffsets;
+        for (int i = 0; i < childrenOffsets.length; i++) {
+            long fieldOffset = childrenOffsets[i];
+            Object arrayObject = unsafe.getObject(parent, fieldOffset);
+            if (arrayObject != null) {
+                assert arrayObject instanceof Node[] : "Children must be instanceof Node[] ";
+                Node[] array = (Node[]) arrayObject;
+                for (int j = 0; j < array.length; j++) {
+                    if (array[j] == oldChild) {
+                        assert newChild != null && array.getClass().getComponentType().isAssignableFrom(newChild.getClass()) : "Array type does not match";
+                        array[j] = newChild;
                         return;
                     }
                 }
@@ -370,6 +379,26 @@
         }
     }
 
+    private static boolean assertAssignable(NodeClass clazz, Node parent, Object oldValue, Object newValue) {
+        if (newValue == null) {
+            return true;
+        }
+        for (NodeField field : clazz.fields) {
+            if (field.kind != NodeFieldKind.CHILD) {
+                continue;
+            }
+            if (unsafe.getObject(parent, field.offset) == oldValue) {
+                if (!field.type.isAssignableFrom(newValue.getClass())) {
+                    assert false : "Child class " + newValue.getClass() + " is not assignable to field " + field.type.getName() + " at " + field.name + " in ";
+                    return false;
+                } else {
+                    break;
+                }
+            }
+        }
+        return true;
+    }
+
     /** Returns all declared fields in the class hierarchy. */
     private static Field[] getAllFields(Class<? extends Object> clazz) {
         Field[] declaredFields = clazz.getDeclaredFields();
@@ -660,4 +689,5 @@
             p.print("    ");
         }
     }
+
 }