# HG changeset patch # User Christian Humer # Date 1373728463 -7200 # Node ID 99789440ce28a81ee28cffc6bf0785c441bcbad2 # Parent 00a9dbcbe431ef1be70bc3f131ee0f4a7c9299a0 Truffle: Added assertions to replaceChild. diff -r 00a9dbcbe431 -r 99789440ce28 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- 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 clazz) { Field[] declaredFields = clazz.getDeclaredFields(); @@ -660,4 +689,5 @@ p.print(" "); } } + }