changeset 19149:183f7d3a93e5

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 05 Feb 2015 03:42:42 +0100
parents 276bc2752feb (current diff) b8b8f0fcb8c3 (diff)
children bb25b153433c
files
diffstat 4 files changed, 28 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Thu Feb 05 03:42:23 2015 +0100
+++ b/CHANGELOG.md	Thu Feb 05 03:42:42 2015 +0100
@@ -12,6 +12,10 @@
 ### Truffle
 * Added Node#deepCopy as primary method to copy ASTs.
 * Disable inlining across Truffle boundary by default. New option TruffleInlineAcrossTruffleBoundary default false.
+* Node.replace(Node) now guards against non-assignable replacement, and Node.isReplacementSafe(Node) checks in advance.
+* Instrumentation:  AST "probing" is now safe and implemented by Node.probe(); language implementors need only implement Node.isInstrumentable() and Node.createWrapperNode().
+* Instrumentation:  A new framework defines a category of  simple "instrumentation tools" that can be created, configured, and installed, after which they autonomously collect execution data of some kind.
+* Instrumentation:  A new example "instrumentation tool" is a language-agnostic collector of code coverage information (CoverageTracker); there are two other examples.
 
 ### Truffle-DSL
 * All methods enclosed in a @TypeSystem must now be static. 
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/SafeReplaceTest.java	Thu Feb 05 03:42:23 2015 +0100
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/SafeReplaceTest.java	Thu Feb 05 03:42:42 2015 +0100
@@ -39,12 +39,11 @@
     public void testCorrectReplacement() {
         TestRootNode root = new TestRootNode();
         final TestNode oldChild = new TestNode();
+        final TestNode newChild = new TestNode();
         root.child = oldChild;
-        assertFalse(oldChild.isReplaceable());  // No parent node
+        assertFalse(oldChild.isSafelyReplaceableBy(newChild));  // No parent node
         root.adoptChildren();
-        assertTrue(oldChild.isReplaceable());   // Now adopted by parent
-        final TestNode newChild = new TestNode();
-        assertTrue(oldChild.isSafelyReplaceableBy(newChild));  // Parent field type is assignable by
+        assertTrue(oldChild.isSafelyReplaceableBy(newChild));   // Now adopted by parent
         // new node
         oldChild.replace(newChild);
         root.execute(null);
@@ -59,10 +58,11 @@
         final TestNode oldChild = new TestNode();
         root.child = oldChild;
         root.adoptChildren();
-        final WrongTestNode newChild = new WrongTestNode();
-        assertFalse(oldChild.isSafelyReplaceableBy(newChild));
-        // Can't test: oldChild.replace(newChild);
-        // Fails if assertions checked; else unsafe assignment will eventually crash the VM
+        final TestNode newChild = new TestNode();
+        final TestNode strayChild = new TestNode();
+        assertFalse(strayChild.isSafelyReplaceableBy(newChild)); // Stray not a child of parent
+        final WrongTestNode wrongTypeNewChild = new WrongTestNode();
+        assertFalse(oldChild.isSafelyReplaceableBy(wrongTypeNewChild));
     }
 
     private static class TestNode extends Node {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Feb 05 03:42:23 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Feb 05 03:42:42 2015 +0100
@@ -290,26 +290,10 @@
     }
 
     /**
-     * Checks if this node is properly adopted by its parent.
-     *
-     * @return {@code true} if it is structurally safe to replace this node.
-     */
-    public final boolean isReplaceable() {
-        if (getParent() != null) {
-            for (Node sibling : getParent().getChildren()) {
-                if (sibling == this) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Checks if this node can be replaced by another node, both structurally and with type safety.
+     * Checks if this node can be replaced by another node: tree structure & type.
      */
     public final boolean isSafelyReplaceableBy(Node newNode) {
-        return isReplaceable() && NodeUtil.isReplacementSafe(getParent(), this, newNode);
+        return NodeUtil.isReplacementSafe(getParent(), this, newNode);
     }
 
     private void reportReplace(Node oldNode, Node newNode, CharSequence reason) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Feb 05 03:42:23 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Feb 05 03:42:42 2015 +0100
@@ -676,26 +676,24 @@
     }
 
     /**
-     * Determines whether a proposed child replacement would be type safe.
-     *
-     * @param parent non-null node
-     * @param oldChild non-null existing child of parent
-     * @param newChild non-null proposed replacement for existing child
+     * Determines whether a proposed child replacement would be safe: structurally and type.
      */
     public static boolean isReplacementSafe(Node parent, Node oldChild, Node newChild) {
         assert newChild != null;
-        final NodeField field = findChildField(parent, oldChild);
-        if (field == null) {
-            throw new IllegalArgumentException();
+        if (parent != null) {
+            final NodeField field = findChildField(parent, oldChild);
+            if (field != null) {
+                switch (field.getKind()) {
+                    case CHILD:
+                        return field.getType().isAssignableFrom(newChild.getClass());
+                    case CHILDREN:
+                        return field.getType().getComponentType().isAssignableFrom(newChild.getClass());
+                    default:
+                        throw new IllegalStateException();
+                }
+            }
         }
-        switch (field.getKind()) {
-            case CHILD:
-                return field.getType().isAssignableFrom(newChild.getClass());
-            case CHILDREN:
-                return field.getType().getComponentType().isAssignableFrom(newChild.getClass());
-            default:
-                throw new IllegalArgumentException();
-        }
+        return false;
     }
 
     /** Returns all declared fields in the class hierarchy. */