changeset 19354:343e0e71031b

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 13 Feb 2015 12:54:34 +0100
parents 8d09a572da84 (current diff) dd7d436a7e19 (diff)
children 1c2e8a440bbd
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsAssignableFromNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java
diffstat 47 files changed, 743 insertions(+), 415 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Fri Feb 13 12:54:34 2015 +0100
@@ -532,7 +532,9 @@
     private Assumption[] assumptions;
 
     /**
-     * The list of the methods whose bytecodes were used as input to the compilation.
+     * The list of the methods whose bytecodes were used as input to the compilation. If
+     * {@code null}, then the compilation did not record method dependencies. Otherwise, the first
+     * element of this array is the root method of the compilation.
      */
     private ResolvedJavaMethod[] methods;
 
@@ -552,6 +554,9 @@
 
     @Override
     public String toString() {
+        if (methods != null) {
+            return getClass().getName() + "[" + methods[0].format("%H.%n(%p)%r") + "]";
+        }
         return identityHashCodeString(this);
     }
 
@@ -629,17 +634,45 @@
 
     /**
      * Sets the methods whose bytecodes were used as input to the compilation.
+     *
+     * @param rootMethod the root method of the compilation
+     * @param inlinedMethods the methods inlined during compilation
      */
-    public void setMethods(ResolvedJavaMethod[] methods) {
-        this.methods = methods;
+    public void setMethods(ResolvedJavaMethod rootMethod, Collection<ResolvedJavaMethod> inlinedMethods) {
+        assert rootMethod != null;
+        assert inlinedMethods != null;
+        if (inlinedMethods.contains(rootMethod)) {
+            methods = inlinedMethods.toArray(new ResolvedJavaMethod[inlinedMethods.size()]);
+            for (int i = 0; i < methods.length; i++) {
+                if (methods[i].equals(rootMethod)) {
+                    if (i != 0) {
+                        ResolvedJavaMethod tmp = methods[0];
+                        methods[0] = methods[i];
+                        methods[i] = tmp;
+                    }
+                    break;
+                }
+            }
+        } else {
+            methods = new ResolvedJavaMethod[1 + inlinedMethods.size()];
+            methods[0] = rootMethod;
+            int i = 1;
+            for (ResolvedJavaMethod m : inlinedMethods) {
+                methods[i++] = m;
+            }
+        }
     }
 
     /**
      * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the methods whose bytecodes
      * were used as input to the compilation.
+     *
+     * @return {@code null} if the compilation did not record method dependencies otherwise the
+     *         methods whose bytecodes were used as input to the compilation with the first element
+     *         being the root method of the compilation
      */
     public Collection<ResolvedJavaMethod> getMethods() {
-        return methods == null ? Collections.emptyList() : Arrays.asList(methods);
+        return methods == null ? null : Arrays.asList(methods);
     }
 
     public DataSection getDataSection() {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Feb 13 12:54:34 2015 +0100
@@ -280,7 +280,7 @@
             LIRGenerationResult lirGen = null;
             lirGen = emitLIR(backend, target, schedule, graph, stub, cc, registerConfig, lirSuites);
             try (Scope s = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) {
-                emitCode(backend, graph.getAssumptions(), graph.getMethods(), lirGen, compilationResult, installedCodeOwner, factory);
+                emitCode(backend, graph.getAssumptions(), graph.method(), graph.getInlinedMethods(), lirGen, compilationResult, installedCodeOwner, factory);
             } catch (Throwable e) {
                 throw Debug.handle(e);
             }
@@ -364,8 +364,8 @@
         return lirGenRes;
     }
 
-    public static void emitCode(Backend backend, Assumptions assumptions, Set<ResolvedJavaMethod> methods, LIRGenerationResult lirGenRes, CompilationResult compilationResult,
-                    ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) {
+    public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Set<ResolvedJavaMethod> inlinedMethods, LIRGenerationResult lirGenRes,
+                    CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) {
         FrameMap frameMap = lirGenRes.getFrameMap();
         CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
         backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
@@ -373,8 +373,8 @@
         if (assumptions != null && !assumptions.isEmpty()) {
             compilationResult.setAssumptions(assumptions.toArray());
         }
-        if (methods != null) {
-            compilationResult.setMethods(methods.toArray(new ResolvedJavaMethod[methods.size()]));
+        if (inlinedMethods != null) {
+            compilationResult.setMethods(rootMethod, inlinedMethods);
         }
 
         if (Debug.isMeterEnabled()) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java	Fri Feb 13 12:54:34 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,25 +33,20 @@
  */
 public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest {
 
-    /*
-     * We have to ignore this test for now because currently there is no way to read uncompressed
-     * pointers in a compressed world via JNI.
-     */
-    @Ignore
     @Test
     public void testObjectSubstitutions() {
+        TestClassA obj = new TestClassA();
+
         test("getClass0");
         test("objectHashCode");
 
-        Object obj = new Object();
-
-        assertDeepEquals("a string".getClass(), ObjectSubstitutions.getClass("a string"));
-        assertDeepEquals(obj.hashCode(), ObjectSubstitutions.hashCode(obj));
+        test("getClass0", "a string");
+        test("objectHashCode", obj);
     }
 
     @SuppressWarnings("all")
-    public static boolean getClass0(Object obj, Class<?> clazz) {
-        return obj.getClass() == clazz;
+    public static Class<?> getClass0(Object obj) {
+        return obj.getClass();
     }
 
     @SuppressWarnings("all")
@@ -59,15 +54,9 @@
         return obj.hashCode();
     }
 
-    /*
-     * We have to ignore this test for now because currently there is no way to read uncompressed
-     * pointers in a compressed world via JNI.
-     */
-    @Ignore
     @Test
     public void testClassSubstitutions() {
         test("getModifiers");
-        test("isInstance");
         test("isInterface");
         test("isArray");
         test("isPrimitive");
@@ -75,15 +64,12 @@
         test("getComponentType");
 
         for (Class<?> c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) {
-            assertDeepEquals(c.getModifiers(), ClassSubstitutions.getModifiers(c));
-            assertDeepEquals(c.isInterface(), ClassSubstitutions.isInterface(c));
-            assertDeepEquals(c.isArray(), ClassSubstitutions.isArray(c));
-            assertDeepEquals(c.isPrimitive(), ClassSubstitutions.isPrimitive(c));
-            assertDeepEquals(c.getSuperclass(), ClassSubstitutions.getSuperclass(c));
-            assertDeepEquals(c.getComponentType(), ClassSubstitutions.getComponentType(c));
-            for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
-                assertDeepEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o));
-            }
+            test("getModifiers", c);
+            test("isInterface", c);
+            test("isArray", c);
+            test("isPrimitive", c);
+            test("getSuperClass", c);
+            test("getComponentType", c);
         }
     }
 
@@ -93,11 +79,6 @@
     }
 
     @SuppressWarnings("all")
-    public static boolean isInstance(Class<?> clazz) {
-        return clazz.isInstance(Number.class);
-    }
-
-    @SuppressWarnings("all")
     public static boolean isInterface(Class<?> clazz) {
         return clazz.isInterface();
     }
@@ -122,11 +103,6 @@
         return clazz.getComponentType();
     }
 
-    /*
-     * We have to ignore this test for now because currently there is no way to read uncompressed
-     * pointers in a compressed world via JNI.
-     */
-    @Ignore
     @Test
     public void testThreadSubstitutions() {
         test("currentThread");
@@ -134,13 +110,13 @@
         test("threadInterrupted");
 
         Thread currentThread = Thread.currentThread();
-        assertDeepEquals(currentThread, ThreadSubstitutions.currentThread());
-        assertDeepEquals(currentThread.isInterrupted(), ThreadSubstitutions.isInterrupted(currentThread, false));
+        test("currentThread", currentThread);
+        test("threadIsInterrupted", currentThread);
     }
 
     @SuppressWarnings("all")
-    public static Thread currentThread() {
-        return Thread.currentThread();
+    public static boolean currentThread(Thread other) {
+        return Thread.currentThread() == other;
     }
 
     @SuppressWarnings("all")
@@ -161,7 +137,7 @@
         SystemSubstitutions.currentTimeMillis();
         SystemSubstitutions.nanoTime();
         for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
-            assertDeepEquals(System.identityHashCode(o), SystemSubstitutions.identityHashCode(o));
+            test("systemIdentityHashCode", o);
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Fri Feb 13 12:54:34 2015 +0100
@@ -208,7 +208,7 @@
                 if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) {
                     graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue()));
                     if (!recordEvolMethodDeps) {
-                        graph.disableMethodRecording();
+                        graph.disableInlinedMethodRecording();
                     }
                 } else {
                     // Compiling method substitution - must clone the graph
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Fri Feb 13 12:54:34 2015 +0100
@@ -56,7 +56,7 @@
         // Stubs cannot be recompiled so they cannot be compiled with
         // assumptions and there is no point in recording evol_method dependencies
         assert compResult.getAssumptions().isEmpty() : "stubs should not use assumptions: " + this;
-        assert compResult.getMethods().isEmpty() : "stubs should not record evol_method dependencies: " + this;
+        assert compResult.getMethods() == null : "stubs should not record evol_method dependencies: " + this;
 
         for (DataPatch data : compResult.getDataPatches()) {
             if (data.reference instanceof ConstantReference) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri Feb 13 12:54:34 2015 +0100
@@ -119,6 +119,10 @@
             if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
                 instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
             }
+        } else if (n instanceof ClassIsAssignableFromNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool);
+            }
         } else if (n instanceof NewInstanceNode) {
             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
                 newObjectSnippets.lower((NewInstanceNode) n, registers, tool);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -33,7 +33,7 @@
 /**
  * {@link MacroNode Macro node} for {@link Class#cast(Object)}.
  *
- * @see ClassSubstitutions#cast(Class, Object)
+ * @see HotSpotClassSubstitutions#cast(Class, Object)
  */
 @NodeInfo
 public final class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary<ValueNode> {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java	Fri Feb 13 12:54:34 2015 +0100
@@ -34,7 +34,7 @@
 /**
  * {@link MacroNode Macro node} for {@link Class#getClassLoader0()}.
  *
- * @see ClassSubstitutions#getClassLoader0(Class)
+ * @see HotSpotClassSubstitutions#getClassLoader0(Class)
  */
 @SuppressWarnings("javadoc")
 @NodeInfo
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -34,7 +34,7 @@
 /**
  * {@link MacroNode Macro node} for {@link Class#getComponentType()}.
  *
- * @see ClassSubstitutions#getComponentType(Class)
+ * @see HotSpotClassSubstitutions#getComponentType(Class)
  */
 @NodeInfo
 public final class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -33,7 +33,7 @@
 /**
  * {@link MacroNode Macro node} for {@link Class#getModifiers()}.
  *
- * @see ClassSubstitutions#getModifiers(Class)
+ * @see HotSpotClassSubstitutions#getModifiers(Class)
  */
 @NodeInfo
 public final class ClassGetModifiersNode extends MacroNode implements Canonicalizable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -34,7 +34,7 @@
 /**
  * {@link MacroNode Macro node} for {@link Class#getSuperclass()}.
  *
- * @see ClassSubstitutions#getSuperclass(Class)
+ * @see HotSpotClassSubstitutions#getSuperclass(Class)
  */
 @NodeInfo
 public final class ClassGetSuperclassNode extends MacroNode implements Canonicalizable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -33,7 +33,7 @@
 /**
  * {@link MacroNode Macro node} for {@link Class#isArray()}.
  *
- * @see ClassSubstitutions#isArray(Class)
+ * @see HotSpotClassSubstitutions#isArray(Class)
  */
 @NodeInfo
 public final class ClassIsArrayNode extends MacroNode implements Canonicalizable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsAssignableFromNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.nodes;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.nodes.*;
-
-/**
- * {@link MacroNode Macro node} for {@link Class#isAssignableFrom(Class)}.
- *
- * @see ClassSubstitutions#isAssignableFrom(Class, Class)
- */
-@NodeInfo
-public final class ClassIsAssignableFromNode extends MacroStateSplitNode implements Canonicalizable {
-    public ClassIsAssignableFromNode(Invoke invoke) {
-        super(invoke);
-    }
-
-    private ValueNode getJavaClass() {
-        return arguments.get(0);
-    }
-
-    private ValueNode getOtherClass() {
-        return arguments.get(1);
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        ValueNode javaClass = getJavaClass();
-        ValueNode otherClass = getOtherClass();
-        if (javaClass.isConstant() && otherClass.isConstant()) {
-            ConstantReflectionProvider constantReflection = tool.getConstantReflection();
-            ResolvedJavaType thisType = constantReflection.asJavaType(javaClass.asJavaConstant());
-            ResolvedJavaType otherType = constantReflection.asJavaType(otherClass.asJavaConstant());
-            if (thisType != null && otherType != null) {
-                return ConstantNode.forBoolean(thisType.isAssignableFrom(otherType));
-            }
-        }
-        return this;
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInstanceNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.nodes;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.hotspot.replacements.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.replacements.nodes.*;
-
-/**
- * {@link MacroNode Macro node} for {@link Class#isInstance(Object)}.
- *
- * @see ClassSubstitutions#isInstance(Class, Object)
- */
-@NodeInfo
-public final class ClassIsInstanceNode extends MacroNode implements Canonicalizable {
-
-    public ClassIsInstanceNode(Invoke invoke) {
-        super(invoke);
-    }
-
-    private ValueNode getJavaClass() {
-        return arguments.get(0);
-    }
-
-    private ValueNode getObject() {
-        return arguments.get(1);
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        ValueNode javaClass = getJavaClass();
-        if (javaClass.isConstant()) {
-            ValueNode object = getObject();
-            ConstantReflectionProvider constantReflection = tool.getConstantReflection();
-            ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant());
-            if (type != null) {
-                if (type.isPrimitive()) {
-                    return ConstantNode.forBoolean(false);
-                }
-                if (object.isConstant()) {
-                    JavaConstant c = object.asJavaConstant();
-                    return ConstantNode.forBoolean(c.isNonNull() && type.isInstance(c));
-                }
-                InstanceOfNode instanceOf = new InstanceOfNode(type, object, null);
-                return new ConditionalNode(instanceOf, ConstantNode.forBoolean(true), ConstantNode.forBoolean(false));
-            }
-        }
-        return this;
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -33,7 +33,7 @@
 /**
  * {@link MacroNode Macro node} for {@link Class#isInterface()}.
  *
- * @see ClassSubstitutions#isInterface(Class)
+ * @see HotSpotClassSubstitutions#isInterface(Class)
  */
 @NodeInfo
 public final class ClassIsInterfaceNode extends MacroNode implements Canonicalizable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -33,7 +33,7 @@
 /**
  * {@link MacroNode Macro node} for {@link Class#isPrimitive()}.
  *
- * @see ClassSubstitutions#isPrimitive(Class)
+ * @see HotSpotClassSubstitutions#isPrimitive(Class)
  */
 @NodeInfo
 public final class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Fri Feb 13 12:48:27 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.replacements;
-
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
-import static com.oracle.graal.nodes.PiNode.*;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.word.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.word.*;
-
-/**
- * Substitutions for {@link java.lang.Class} methods.
- */
-@ClassSubstitution(java.lang.Class.class)
-public class ClassSubstitutions {
-
-    @MacroSubstitution(macro = ClassGetModifiersNode.class, isStatic = false)
-    @MethodSubstitution(isStatic = false, forced = true)
-    public static int getModifiers(final Class<?> thisObj) {
-        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
-        if (klass.isNull()) {
-            // Class for primitive type
-            return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
-        } else {
-            return klass.readInt(klassModifierFlagsOffset(), KLASS_MODIFIER_FLAGS_LOCATION);
-        }
-    }
-
-    // This MacroSubstitution should be removed once non-null klass pointers can be optimized
-    @MacroSubstitution(macro = ClassIsInterfaceNode.class, isStatic = false)
-    @MethodSubstitution(isStatic = false, forced = true)
-    public static boolean isInterface(final Class<?> thisObj) {
-        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
-        if (klass.isNull()) {
-            return false;
-        } else {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION);
-            return (accessFlags & Modifier.INTERFACE) != 0;
-        }
-    }
-
-    // This MacroSubstitution should be removed once non-null klass pointers can be optimized
-    @MacroSubstitution(macro = ClassIsArrayNode.class, isStatic = false)
-    @MethodSubstitution(isStatic = false, forced = true)
-    public static boolean isArray(final Class<?> thisObj) {
-        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
-        if (klass.isNull()) {
-            return false;
-        } else {
-            return klassIsArray(klass);
-        }
-    }
-
-    // This MacroSubstitution should be removed once non-null klass pointers can be optimized
-    @MacroSubstitution(macro = ClassIsPrimitiveNode.class, isStatic = false)
-    @MethodSubstitution(isStatic = false, forced = true)
-    public static boolean isPrimitive(final Class<?> thisObj) {
-        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
-        return klass.isNull();
-    }
-
-    @MacroSubstitution(macro = ClassGetClassLoader0Node.class, isStatic = false)
-    public static native ClassLoader getClassLoader0(Class<?> thisObj);
-
-    @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false)
-    @MethodSubstitution(isStatic = false)
-    public static Class<?> getSuperclass(final Class<?> thisObj) {
-        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
-        if (!klass.isNull()) {
-            int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION);
-            if ((accessFlags & Modifier.INTERFACE) == 0) {
-                if (klassIsArray(klass)) {
-                    return Object.class;
-                } else {
-                    Word superKlass = klass.readWord(klassSuperKlassOffset(), KLASS_SUPER_KLASS_LOCATION);
-                    if (superKlass.equal(0)) {
-                        return null;
-                    } else {
-                        return readJavaMirror(superKlass);
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    public static Class<?> readJavaMirror(Word klass) {
-        return piCastExactNonNull(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION), Class.class);
-    }
-
-    @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false)
-    @MethodSubstitution(isStatic = false)
-    public static Class<?> getComponentType(final Class<?> thisObj) {
-        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
-        if (!klass.isNull()) {
-            if (klassIsArray(klass)) {
-                return piCastExactNonNull(klass.readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR), Class.class);
-            }
-        }
-        return null;
-    }
-
-    @MacroSubstitution(macro = ClassIsInstanceNode.class, isStatic = false)
-    @MethodSubstitution(isStatic = false)
-    public static boolean isInstance(Class<?> thisObj, Object obj) {
-        return ConditionalNode.materializeIsInstance(thisObj, obj);
-    }
-
-    @MacroSubstitution(macro = ClassIsAssignableFromNode.class, isStatic = false)
-    @MethodSubstitution(isStatic = false)
-    public static boolean isAssignableFrom(Class<?> thisClass, Class<?> otherClass) {
-        if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, otherClass == null)) {
-            DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
-            return false;
-        }
-        GuardingNode anchorNode = SnippetAnchorNode.anchor();
-        KlassPointer thisHub = ClassGetHubNode.readClass(thisClass, anchorNode);
-        KlassPointer otherHub = ClassGetHubNode.readClass(otherClass, anchorNode);
-        if (thisHub.isNull() || otherHub.isNull()) {
-            // primitive types, only true if equal.
-            return thisClass == otherClass;
-        }
-        if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub, otherHub)) {
-            return false;
-        }
-        return true;
-    }
-
-    @MacroSubstitution(macro = ClassCastNode.class, isStatic = false)
-    public static native Object cast(final Class<?> thisObj, Object obj);
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompilerToVMImplSubstitutions.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompilerToVMImplSubstitutions.java	Fri Feb 13 12:54:34 2015 +0100
@@ -34,6 +34,6 @@
 
     @MethodSubstitution(isStatic = false)
     public static Class<?> getJavaMirror(@SuppressWarnings("unused") CompilerToVMImpl impl, long metaspaceklass) {
-        return ClassSubstitutions.readJavaMirror(Word.unsigned(metaspaceklass));
+        return HotSpotClassSubstitutions.readJavaMirror(Word.unsigned(metaspaceklass));
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java	Fri Feb 13 12:54:34 2015 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.nodes.PiNode.*;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.word.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Substitutions for {@link java.lang.Class} methods.
+ */
+@ClassSubstitution(java.lang.Class.class)
+public class HotSpotClassSubstitutions {
+
+    @MacroSubstitution(macro = ClassGetModifiersNode.class, isStatic = false)
+    @MethodSubstitution(isStatic = false, forced = true)
+    public static int getModifiers(final Class<?> thisObj) {
+        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
+        if (klass.isNull()) {
+            // Class for primitive type
+            return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC;
+        } else {
+            return klass.readInt(klassModifierFlagsOffset(), KLASS_MODIFIER_FLAGS_LOCATION);
+        }
+    }
+
+    // This MacroSubstitution should be removed once non-null klass pointers can be optimized
+    @MacroSubstitution(macro = ClassIsInterfaceNode.class, isStatic = false)
+    @MethodSubstitution(isStatic = false, forced = true)
+    public static boolean isInterface(final Class<?> thisObj) {
+        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
+        if (klass.isNull()) {
+            return false;
+        } else {
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION);
+            return (accessFlags & Modifier.INTERFACE) != 0;
+        }
+    }
+
+    // This MacroSubstitution should be removed once non-null klass pointers can be optimized
+    @MacroSubstitution(macro = ClassIsArrayNode.class, isStatic = false)
+    @MethodSubstitution(isStatic = false, forced = true)
+    public static boolean isArray(final Class<?> thisObj) {
+        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
+        if (klass.isNull()) {
+            return false;
+        } else {
+            return klassIsArray(klass);
+        }
+    }
+
+    // This MacroSubstitution should be removed once non-null klass pointers can be optimized
+    @MacroSubstitution(macro = ClassIsPrimitiveNode.class, isStatic = false)
+    @MethodSubstitution(isStatic = false, forced = true)
+    public static boolean isPrimitive(final Class<?> thisObj) {
+        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
+        return klass.isNull();
+    }
+
+    @MacroSubstitution(macro = ClassGetClassLoader0Node.class, isStatic = false)
+    public static native ClassLoader getClassLoader0(Class<?> thisObj);
+
+    @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false)
+    @MethodSubstitution(isStatic = false)
+    public static Class<?> getSuperclass(final Class<?> thisObj) {
+        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
+        if (!klass.isNull()) {
+            int accessFlags = klass.readInt(klassAccessFlagsOffset(), KLASS_ACCESS_FLAGS_LOCATION);
+            if ((accessFlags & Modifier.INTERFACE) == 0) {
+                if (klassIsArray(klass)) {
+                    return Object.class;
+                } else {
+                    Word superKlass = klass.readWord(klassSuperKlassOffset(), KLASS_SUPER_KLASS_LOCATION);
+                    if (superKlass.equal(0)) {
+                        return null;
+                    } else {
+                        return readJavaMirror(superKlass);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    public static Class<?> readJavaMirror(Word klass) {
+        return piCastExactNonNull(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION), Class.class);
+    }
+
+    @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false)
+    @MethodSubstitution(isStatic = false)
+    public static Class<?> getComponentType(final Class<?> thisObj) {
+        KlassPointer klass = ClassGetHubNode.readClass(thisObj);
+        if (!klass.isNull()) {
+            if (klassIsArray(klass)) {
+                return piCastExactNonNull(klass.readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR), Class.class);
+            }
+        }
+        return null;
+    }
+
+    @MacroSubstitution(macro = ClassCastNode.class, isStatic = false)
+    public static native Object cast(final Class<?> thisObj, Object obj);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Fri Feb 13 12:54:34 2015 +0100
@@ -60,7 +60,7 @@
         replacements.registerSubstitutions(System.class, SystemSubstitutions.class);
         replacements.registerSubstitutions(Thread.class, ThreadSubstitutions.class);
         replacements.registerSubstitutions(Unsafe.class, UnsafeSubstitutions.class);
-        replacements.registerSubstitutions(Class.class, ClassSubstitutions.class);
+        replacements.registerSubstitutions(Class.class, HotSpotClassSubstitutions.class);
         replacements.registerSubstitutions(CRC32.class, CRC32Substitutions.class);
         replacements.registerSubstitutions(Reflection.class, ReflectionSubstitutions.class);
         replacements.registerSubstitutions(NodeClass.class, HotSpotNodeClassSubstitutions.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Feb 13 12:54:34 2015 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
@@ -194,6 +195,25 @@
         return trueValue;
     }
 
+    @Snippet
+    public static Object isAssignableFrom(Class<?> thisClass, Class<?> otherClass, Object trueValue, Object falseValue) {
+        if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, otherClass == null)) {
+            DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
+            return false;
+        }
+        GuardingNode anchorNode = SnippetAnchorNode.anchor();
+        KlassPointer thisHub = ClassGetHubNode.readClass(thisClass, anchorNode);
+        KlassPointer otherHub = ClassGetHubNode.readClass(otherClass, anchorNode);
+        if (thisHub.isNull() || otherHub.isNull()) {
+            // primitive types, only true if equal.
+            return thisClass == otherClass ? trueValue : falseValue;
+        }
+        if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub, otherHub)) {
+            return falseValue;
+        }
+        return trueValue;
+    }
+
     static class Options {
 
         // @formatter:off
@@ -214,6 +234,7 @@
         private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary");
         private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary");
         private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic");
+        private final SnippetInfo isAssignableFrom = snippet(InstanceOfSnippets.class, "isAssignableFrom");
         private final long compilationThreshold;
 
         public Templates(HotSpotProviders providers, TargetDescription target, long compilationThreshold) {
@@ -264,8 +285,7 @@
                 }
                 return args;
 
-            } else {
-                assert replacer.instanceOf instanceof InstanceOfDynamicNode;
+            } else if (replacer.instanceOf instanceof InstanceOfDynamicNode) {
                 InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf;
                 ValueNode object = instanceOf.object();
 
@@ -275,6 +295,16 @@
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
                 return args;
+            } else if (replacer.instanceOf instanceof ClassIsAssignableFromNode) {
+                ClassIsAssignableFromNode isAssignable = (ClassIsAssignableFromNode) replacer.instanceOf;
+                Arguments args = new Arguments(isAssignableFrom, isAssignable.graph().getGuardsStage(), tool.getLoweringStage());
+                args.add("thisClass", isAssignable.getThisClass());
+                args.add("otherClass", isAssignable.getOtherClass());
+                args.add("trueValue", replacer.trueValue);
+                args.add("falseValue", replacer.falseValue);
+                return args;
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Fri Feb 13 12:54:34 2015 +0100
@@ -192,7 +192,7 @@
         boolean isObjectResult = linkage.getOutgoingCallingConvention().getReturn().getKind() == Kind.Object;
 
         StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO);
-        graph.disableMethodRecording();
+        graph.disableInlinedMethodRecording();
 
         GraphKit kit = new HotSpotGraphKit(graph, providers);
         ParameterNode[] params = createParameters(kit, args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Feb 13 12:54:34 2015 +0100
@@ -161,7 +161,7 @@
                 // Stubs cannot be recompiled so they cannot be compiled with
                 // assumptions and there is no point in recording evol_method dependencies
                 assert graph.getAssumptions() == null;
-                assert !graph.isMethodRecordingEnabled() : graph;
+                assert !graph.isInlinedMethodRecordingEnabled() : graph;
 
                 if (!(graph.start() instanceof StubStartNode)) {
                     StubStartNode newStart = graph.add(new StubStartNode(Stub.this));
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Feb 13 12:54:34 2015 +0100
@@ -971,9 +971,9 @@
                     calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
                 }
 
-                // Record method dependency in the graph
-                if (currentGraph.isMethodRecordingEnabled()) {
-                    currentGraph.getMethods().add(targetMethod);
+                // Record inlined method dependency in the graph
+                if (currentGraph.isInlinedMethodRecordingEnabled()) {
+                    currentGraph.getInlinedMethods().add(targetMethod);
                 }
             }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Fri Feb 13 12:54:34 2015 +0100
@@ -112,9 +112,9 @@
     private final Assumptions assumptions;
 
     /**
-     * The methods whose bytecodes are used while constructing this graph.
+     * The methods that were inlined while constructing this graph.
      */
-    private Set<ResolvedJavaMethod> methods = new HashSet<>();
+    private Set<ResolvedJavaMethod> inlinedMethods = new HashSet<>();
 
     /**
      * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
@@ -220,16 +220,16 @@
     }
 
     public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod) {
-        return copy(newName, newMethod, AllowAssumptions.from(assumptions != null), isMethodRecordingEnabled());
+        return copy(newName, newMethod, AllowAssumptions.from(assumptions != null), isInlinedMethodRecordingEnabled());
     }
 
-    public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod, AllowAssumptions allowAssumptions, boolean enableMethodRecording) {
+    public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod, AllowAssumptions allowAssumptions, boolean enableInlinedMethodRecording) {
         StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI, allowAssumptions);
         if (allowAssumptions == AllowAssumptions.YES && assumptions != null) {
             copy.assumptions.record(assumptions);
         }
-        if (!enableMethodRecording) {
-            copy.disableMethodRecording();
+        if (!enableInlinedMethodRecording) {
+            copy.disableInlinedMethodRecording();
         }
         copy.setGuardsStage(getGuardsStage());
         copy.isAfterFloatingReadPhase = isAfterFloatingReadPhase;
@@ -512,26 +512,26 @@
     }
 
     /**
-     * Disables recording of method used while constructing this graph. This can be done at most
-     * once and must be done before any methods are recorded.
+     * Disables recording of methods inlined while constructing this graph. This can be done at most
+     * once and must be done before any inlined methods are recorded.
      */
-    public void disableMethodRecording() {
-        assert methods != null : "cannot disable method recording more than once";
-        assert methods.isEmpty() : "cannot disable method recording once methods have been recorded";
-        methods = null;
+    public void disableInlinedMethodRecording() {
+        assert inlinedMethods != null : "cannot disable inlined method recording more than once";
+        assert inlinedMethods.isEmpty() : "cannot disable inlined method recording once methods have been recorded";
+        inlinedMethods = null;
     }
 
-    public boolean isMethodRecordingEnabled() {
-        return methods != null;
+    public boolean isInlinedMethodRecordingEnabled() {
+        return inlinedMethods != null;
     }
 
     /**
-     * Gets the methods whose bytecodes are used while constructing this graph.
+     * Gets the methods that were inlined while constructing this graph.
      *
-     * @return {@code null} if method recording has been {@linkplain #disableMethodRecording()
-     *         disabled}
+     * @return {@code null} if inlined method recording has been
+     *         {@linkplain #disableInlinedMethodRecording() disabled}
      */
-    public Set<ResolvedJavaMethod> getMethods() {
-        return methods;
+    public Set<ResolvedJavaMethod> getInlinedMethods() {
+        return inlinedMethods;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -157,4 +157,24 @@
     public static boolean materializeIsInstance(Class<?> mirror, Object object) {
         return mirror.isInstance(object);
     }
+
+    /**
+     * @param thisClass
+     * @param otherClass
+     * @param dummy a marker to make this constructor unique for the
+     *            {@link #materializeIsAssignableFrom(Class, Class, int)} NodeIntrinsic
+     */
+    public ConditionalNode(ValueNode thisClass, ValueNode otherClass, int dummy) {
+        this(thisClass.graph().unique(new ClassIsAssignableFromNode(thisClass, otherClass)));
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    private static boolean materializeIsAssignableFrom(Class<?> thisClass, Class<?> otherClass, @ConstantNodeParameter int dummy) {
+        return thisClass.isAssignableFrom(otherClass);
+    }
+
+    public static boolean materializeIsAssignableFrom(Class<?> thisClass, Class<?> otherClass) {
+        return materializeIsAssignableFrom(thisClass, otherClass, 0);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -52,6 +52,6 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         Value addr = getLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(getObject()));
-        gen.setResult(this, addr);
+        gen.setResult(this, gen.getLIRGeneratorTool().asAllocatable(addr));
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ClassIsAssignableFromNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.java;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * The {@code ClassIsAssignableFromNode} represents a type check against {@link Class} instead of
+ * against instances. This is used, for instance, to intrinsify
+ * {@link Class#isAssignableFrom(Class)} .
+ */
+@NodeInfo
+public final class ClassIsAssignableFromNode extends LogicNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
+    @Input ValueNode thisClass;
+    @Input ValueNode otherClass;
+
+    public ClassIsAssignableFromNode(ValueNode thisClass, ValueNode otherClass) {
+        this.thisClass = thisClass;
+        this.otherClass = otherClass;
+    }
+
+    public Object getThisClass() {
+        return thisClass;
+    }
+
+    public Object getOtherClass() {
+        return otherClass;
+    }
+
+    @Override
+    public ValueNode getX() {
+        return thisClass;
+    }
+
+    @Override
+    public ValueNode getY() {
+        return otherClass;
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            ConstantReflectionProvider constantReflection = tool.getConstantReflection();
+            ResolvedJavaType thisType = constantReflection.asJavaType(forX.asJavaConstant());
+            ResolvedJavaType otherType = constantReflection.asJavaType(forY.asJavaConstant());
+            if (thisType != null && otherType != null) {
+                return LogicConstantNode.forBoolean(thisType.isAssignableFrom(otherType));
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Fri Feb 13 12:54:34 2015 +0100
@@ -373,9 +373,9 @@
             assert inlineGraph.getAssumptions() == null : "cannot inline graph which makes assumptions into a graph that doesn't: " + inlineGraph + " -> " + graph;
         }
 
-        // Copy method dependencies from inlinee to caller
-        if (inlineGraph.isMethodRecordingEnabled() && graph.isMethodRecordingEnabled()) {
-            graph.getMethods().addAll(inlineGraph.getMethods());
+        // Copy inlined methods from inlinee to caller
+        if (inlineGraph.isInlinedMethodRecordingEnabled() && graph.isInlinedMethodRecordingEnabled()) {
+            graph.getInlinedMethods().addAll(inlineGraph.getInlinedMethods());
         }
 
         return duplicates;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java	Fri Feb 13 12:54:34 2015 +0100
@@ -66,8 +66,8 @@
 
         InliningUtil.InlinedBytecodes.add(concrete.getCodeSize());
         StructuredGraph graph = invoke.asNode().graph();
-        if (graph.isMethodRecordingEnabled()) {
-            graph.getMethods().add(concrete);
+        if (graph.isInlinedMethodRecordingEnabled()) {
+            graph.getInlinedMethods().add(concrete);
         }
         return canonicalizeNodes;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java	Fri Feb 13 12:54:34 2015 +0100
@@ -201,12 +201,12 @@
     private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) {
         StructuredGraph newGraph = new StructuredGraph(method, AllowAssumptions.from(caller.getAssumptions() != null));
         try (Debug.Scope s = Debug.scope("InlineGraph", newGraph)) {
-            if (!caller.isMethodRecordingEnabled()) {
-                // Don't record method dependencies in the inlinee if
+            if (!caller.isInlinedMethodRecordingEnabled()) {
+                // Don't record inlined methods in the callee if
                 // the caller doesn't want them. This decision is
                 // preserved in the graph cache (if used) which is
                 // ok since the graph cache is compilation local.
-                newGraph.disableMethodRecording();
+                newGraph.disableInlinedMethodRecording();
             }
             if (context.getGraphBuilderSuite() != null) {
                 context.getGraphBuilderSuite().apply(newGraph, context);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java	Fri Feb 13 12:54:34 2015 +0100
@@ -177,4 +177,25 @@
     public static double longBitsToDouble(long value) {
         return Double.longBitsToDouble(value);
     }
+
+    @SuppressWarnings("all")
+    public static boolean isInstance(Class<?> clazz) {
+        return clazz.isInstance(Number.class);
+    }
+
+    @SuppressWarnings("all")
+    public static boolean isAssignableFrom(Class<?> clazz) {
+        return clazz.isInstance(Number.class);
+    }
+
+    @Test
+    public void testClassSubstitutions() {
+        test("isInstance");
+        for (Class<?> c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) {
+            for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) {
+                assertDeepEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o));
+                assertDeepEquals(c.isAssignableFrom(o.getClass()), ClassSubstitutions.isAssignableFrom(c, o.getClass()));
+            }
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ClassSubstitutions.java	Fri Feb 13 12:54:34 2015 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.calc.*;
+
+/**
+ * Substitutions for {@link java.lang.Class} methods.
+ */
+@ClassSubstitution(java.lang.Class.class)
+public class ClassSubstitutions {
+
+    @MethodSubstitution(isStatic = false)
+    public static boolean isInstance(Class<?> thisObj, Object obj) {
+        return ConditionalNode.materializeIsInstance(thisObj, obj);
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static boolean isAssignableFrom(Class<?> thisClass, Class<?> otherClass) {
+        return ConditionalNode.materializeIsAssignableFrom(thisClass, otherClass);
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Fri Feb 13 12:54:34 2015 +0100
@@ -62,6 +62,7 @@
             replacements.registerSubstitutions(Short.class, ShortSubstitutions.class);
             replacements.registerSubstitutions(UnsignedMath.class, UnsignedMathSubstitutions.class);
             replacements.registerSubstitutions(Edges.class, EdgesSubstitutions.class);
+            replacements.registerSubstitutions(Class.class, ClassSubstitutions.class);
         }
         if (Options.UseBlackholeSubstitution.getValue()) {
             replacements.registerSubstitutions(new Type() {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Fri Feb 13 12:54:34 2015 +0100
@@ -65,7 +65,7 @@
     protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool);
 
     public void lower(FloatingNode instanceOf, LoweringTool tool) {
-        assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode;
+        assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode || instanceOf instanceof ClassIsAssignableFromNode;
         List<Node> usages = instanceOf.usages().snapshot();
 
         Instantiation instantiation = new Instantiation();
@@ -176,7 +176,7 @@
         public final ValueNode falseValue;
 
         public InstanceOfUsageReplacer(Instantiation instantiation, FloatingNode instanceOf, ValueNode trueValue, ValueNode falseValue) {
-            assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode;
+            assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode || instanceOf instanceof ClassIsAssignableFromNode;
             this.instantiation = instantiation;
             this.instanceOf = instanceOf;
             this.trueValue = trueValue;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Feb 13 12:54:34 2015 +0100
@@ -612,7 +612,7 @@
             final StructuredGraph graph = new StructuredGraph(methodToParse, AllowAssumptions.NO);
 
             // They will also never be never be evolved or have breakpoints set in them
-            graph.disableMethodRecording();
+            graph.disableInlinedMethodRecording();
 
             try (Scope s = Debug.scope("buildInitialGraph", graph)) {
                 MetaAccessProvider metaAccess = replacements.providers.getMetaAccess();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Feb 13 12:54:34 2015 +0100
@@ -566,8 +566,8 @@
 
         // Copy snippet graph, replacing constant parameters with given arguments
         final StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method(), AllowAssumptions.NO);
-        if (!snippetGraph.isMethodRecordingEnabled()) {
-            snippetCopy.disableMethodRecording();
+        if (!snippetGraph.isInlinedMethodRecordingEnabled()) {
+            snippetCopy.disableInlinedMethodRecording();
         }
 
         Map<Node, Node> nodeReplacements = Node.newIdentityMap();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/InstrumentationPartialEvaluationTest.java	Fri Feb 13 12:54:34 2015 +0100
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test;
+
+import org.junit.*;
+
+import com.oracle.graal.truffle.test.nodes.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+
+/**
+ * Tests for a single simple PE test with various combinations of instrumentation attached. None of
+ * the instrumentation ultimate does anything, so should compile away.
+ */
+public class InstrumentationPartialEvaluationTest extends PartialEvaluationTest {
+
+    public static Object constant42() {
+        return 42;
+    }
+
+    @Test
+    public void constantValueUninstrumented() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(42);
+        RootTestNode root = new RootTestNode(fd, "constantValue", result);
+        root.adoptChildren();
+        assertPartialEvalEquals("constant42", root);
+    }
+
+    @Ignore
+    @Test
+    public void constantValueProbedNoInstruments() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(42);
+        RootTestNode root = new RootTestNode(fd, "constantValue", result);
+        root.adoptChildren();
+        result.probe();
+        assertPartialEvalEquals("constant42", root);
+    }
+
+    @Ignore
+    @Test
+    public void constantValueProbedNullInstrument() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(42);
+        RootTestNode root = new RootTestNode(fd, "constantValue", result);
+        root.adoptChildren();
+        Probe probe = result.probe();
+        Instrument instrument = Instrument.create(new DefaultEventListener(), "Null test Instrument");
+        probe.attach(instrument);
+        assertPartialEvalEquals("constant42", root);
+    }
+
+    @Ignore
+    @Test
+    public void constantValueProbedNullInstrumentDisposed() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(42);
+        RootTestNode root = new RootTestNode(fd, "constantValue", result);
+        root.adoptChildren();
+        Probe probe = result.probe();
+        Instrument instrument = Instrument.create(new DefaultEventListener(), "Null test Instrument");
+        probe.attach(instrument);
+        instrument.dispose();
+        assertPartialEvalEquals("constant42", root);
+    }
+
+    @Ignore
+    @Test
+    public void constantValueProbedTwoNullInstruments() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(42);
+        RootTestNode root = new RootTestNode(fd, "constantValue", result);
+        root.adoptChildren();
+        Probe probe = result.probe();
+        Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1");
+        probe.attach(instrument1);
+        Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2");
+        probe.attach(instrument2);
+        assertPartialEvalEquals("constant42", root);
+    }
+
+    @Ignore
+    @Test
+    public void constantValueProbedThreeNullInstruments() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(42);
+        RootTestNode root = new RootTestNode(fd, "constantValue", result);
+        root.adoptChildren();
+        Probe probe = result.probe();
+        Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1");
+        probe.attach(instrument1);
+        Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2");
+        probe.attach(instrument2);
+        Instrument instrument3 = Instrument.create(new DefaultEventListener(), "Null test Instrument 3");
+        probe.attach(instrument3);
+        assertPartialEvalEquals("constant42", root);
+    }
+
+    @Ignore
+    @Test
+    public void constantValueProbedThreeNullInstrumentsOneDisposed() {
+        FrameDescriptor fd = new FrameDescriptor();
+        AbstractTestNode result = new ConstantTestNode(42);
+        RootTestNode root = new RootTestNode(fd, "constantValue", result);
+        root.adoptChildren();
+        Probe probe = result.probe();
+        Instrument instrument1 = Instrument.create(new DefaultEventListener(), "Null test Instrument 1");
+        probe.attach(instrument1);
+        Instrument instrument2 = Instrument.create(new DefaultEventListener(), "Null test Instrument 2");
+        probe.attach(instrument2);
+        Instrument instrument3 = Instrument.create(new DefaultEventListener(), "Null test Instrument 3");
+        probe.attach(instrument3);
+        instrument2.dispose();
+        assertPartialEvalEquals("constant42", root);
+    }
+}
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
 package com.oracle.graal.truffle.test.nodes;
 
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
 import com.oracle.truffle.api.nodes.*;
 
 public abstract class AbstractTestNode extends Node {
@@ -31,5 +32,15 @@
         super(null);
     }
 
+    @Override
+    public boolean isInstrumentable() {
+        return true;
+    }
+
+    @Override
+    public WrapperNode createWrapperNode() {
+        return new WrapperTestNode(this);
+    }
+
     public abstract int execute(VirtualFrame frame);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/WrapperTestNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.test.nodes;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Support for PE testing instrumentation.
+ */
+public final class WrapperTestNode extends AbstractTestNode implements WrapperNode {
+
+    @Child private AbstractTestNode child;
+    @Child private ProbeNode probeNode;
+
+    public WrapperTestNode(AbstractTestNode child) {
+        this.child = child;
+    }
+
+    public String instrumentationInfo() {
+        return "Wrapper for PE test nodes";
+    }
+
+    @Override
+    public boolean isInstrumentable() {
+        return false;
+    }
+
+    public void insertProbe(ProbeNode newProbeNode) {
+        this.probeNode = newProbeNode;
+    }
+
+    public Probe getProbe() {
+        return probeNode.getProbe();
+    }
+
+    @Override
+    public Node getChild() {
+        return child;
+    }
+
+    @Override
+    public int execute(VirtualFrame frame) {
+        probeNode.enter(child, frame);
+        try {
+            final int result = child.execute(frame);
+            probeNode.returnValue(child, frame, result);
+            return result;
+        } catch (KillException e) {
+            throw (e);
+        } catch (Exception e) {
+            probeNode.returnExceptional(child, frame, e);
+            throw (e);
+        }
+
+    }
+
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Fri Feb 13 12:54:34 2015 +0100
@@ -166,9 +166,8 @@
 
         compilationNotify.notifyCompilationGraalTierFinished((OptimizedCallTarget) predefinedInstalledCode, graph);
 
-        if (graph.isMethodRecordingEnabled()) {
-            Set<ResolvedJavaMethod> methods = graph.getMethods();
-            result.setMethods(methods.toArray(new ResolvedJavaMethod[methods.size()]));
+        if (graph.isInlinedMethodRecordingEnabled()) {
+            result.setMethods(graph.method(), graph.getInlinedMethods());
         } else {
             assert result.getMethods() == null;
         }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Fri Feb 13 12:54:34 2015 +0100
@@ -65,6 +65,17 @@
             /* If the cast is unused, it can be eliminated. */
             return input;
         }
+
+        assert !stamp().isCompatible(input.stamp());
+        if (input.isConstant()) {
+            /* Null pointers are uncritical for GC, so they can be constant folded. */
+            if (input.asJavaConstant().isNull()) {
+                return ConstantNode.forIntegerStamp(stamp(), 0);
+            } else if (input.asJavaConstant().getKind().isNumericInteger() && input.asJavaConstant().asLong() == 0) {
+                return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, tool.getMetaAccess());
+            }
+        }
+
         return this;
     }
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Fri Feb 13 12:54:34 2015 +0100
@@ -113,6 +113,8 @@
     protected void rewriteNode(StructuredGraph graph, Node node) {
         if (node instanceof CheckCastNode) {
             rewriteCheckCast(graph, (CheckCastNode) node);
+        } else if (node instanceof PiNode) {
+            rewritePi(graph, (PiNode) node);
         } else if (node instanceof LoadFieldNode) {
             rewriteLoadField(graph, (LoadFieldNode) node);
         } else if (node instanceof AccessIndexedNode) {
@@ -133,6 +135,16 @@
     }
 
     /**
+     * Remove casts between word types (which by now no longer have kind Object).
+     */
+    protected void rewritePi(StructuredGraph graph, PiNode node) {
+        if (node.getKind() == wordKind) {
+            node.replaceAtUsages(node.object());
+            graph.removeFloating(node);
+        }
+    }
+
+    /**
      * Fold constant field reads, e.g. enum constants.
      */
     protected void rewriteLoadField(StructuredGraph graph, LoadFieldNode node) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java	Fri Feb 13 12:54:34 2015 +0100
@@ -23,6 +23,7 @@
 package com.oracle.truffle.dsl.processor.expression;
 
 import java.util.*;
+import java.util.concurrent.atomic.*;
 
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
@@ -68,6 +69,19 @@
         return variables;
     }
 
+    public boolean containsComparisons() {
+        final AtomicBoolean found = new AtomicBoolean();
+        this.accept(new AbstractDSLExpressionVisitor() {
+            @Override
+            public void visitBinary(Binary binary) {
+                if (binary.isComparison()) {
+                    found.set(true);
+                }
+            }
+        });
+        return found.get();
+    }
+
     public void setResolvedTargetType(TypeMirror resolvedTargetType) {
         this.resolvedTargetType = resolvedTargetType;
     }
@@ -131,6 +145,10 @@
             this.right = right;
         }
 
+        public boolean isComparison() {
+            return DSLExpressionResolver.COMPARABLE_OPERATORS.contains(operator) || DSLExpressionResolver.IDENTITY_OPERATORS.contains(operator);
+        }
+
         @Override
         public boolean equals(Object obj) {
             if (obj instanceof Binary) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java	Fri Feb 13 12:54:34 2015 +0100
@@ -41,8 +41,8 @@
 public class DSLExpressionResolver implements DSLExpressionVisitor {
 
     private static final List<String> LOGIC_OPERATORS = Arrays.asList("||");
-    private static final List<String> COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">=");
-    private static final List<String> IDENTITY_OPERATORS = Arrays.asList("==", "!=");
+    public static final List<String> COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">=");
+    public static final List<String> IDENTITY_OPERATORS = Arrays.asList("==", "!=");
     private static final String CONSTRUCTOR_KEYWORD = "new";
 
     private final List<VariableElement> variables = new ArrayList<>();
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Fri Feb 13 12:54:34 2015 +0100
@@ -213,6 +213,8 @@
         }
         clazz.add(createGetCostMethod());
 
+        avoidFindbugsProblems(clazz);
+
         if (singleSpecializable) {
             if (node.needsRewrites(context)) {
                 clazz.add(createUnsupportedMethod());
@@ -236,6 +238,28 @@
         return clazz;
     }
 
+    private void avoidFindbugsProblems(CodeTypeElement clazz) {
+        TypeElement type = context.getEnvironment().getElementUtils().getTypeElement("edu.umd.cs.findbugs.annotations.SuppressFBWarnings");
+        if (type == null) {
+            return;
+        }
+        boolean foundComparison = false;
+        outer: for (SpecializationData specialization : node.getSpecializations()) {
+            for (GuardExpression guard : specialization.getGuards()) {
+                if (guard.getExpression().containsComparisons()) {
+                    foundComparison = true;
+                    break outer;
+                }
+            }
+        }
+
+        if (foundComparison) {
+            CodeAnnotationMirror annotation = new CodeAnnotationMirror((DeclaredType) type.asType());
+            annotation.setElementValue(annotation.findExecutableElement("value"), new CodeAnnotationValue("SA_LOCAL_SELF_COMPARISON"));
+            clazz.addAnnotationMirror(annotation);
+        }
+    }
+
     private Element createUnsupportedMethod() {
         LocalContext locals = LocalContext.load(this);
         CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED), getType(UnsupportedSpecializationException.class), "unsupported");
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Fri Feb 13 12:48:27 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Fri Feb 13 12:54:34 2015 +0100
@@ -1126,10 +1126,6 @@
     }
 
     private void initializeGeneric(final NodeData node) {
-        if (!node.needsRewrites(context)) {
-            return;
-        }
-
         List<SpecializationData> generics = new ArrayList<>();
         for (SpecializationData spec : node.getSpecializations()) {
             if (spec.isFallback()) {