changeset 21087:056f90577ed1

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 22 Apr 2015 15:36:53 +0200
parents 0a3bc68fc3a7 (current diff) 8f67ddf0dd3b (diff)
children 355ebfa2ba95
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassQueryNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java
diffstat 38 files changed, 1134 insertions(+), 1080 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Wed Apr 22 15:36:53 2015 +0200
@@ -132,10 +132,31 @@
     public static final int INVALID_FRAMESTATE_BCI = -6;
 
     /**
-     * Determines if a given BCI matches one of the synthetic BCI contants defined in this class.
+     * Determines if a given BCI matches one of the placeholder BCI constants defined in this class.
+     */
+    public static boolean isPlaceholderBci(int bci) {
+        return bci < 0;
+    }
+
+    /**
+     * Gets the name of a given placeholder BCI.
      */
-    public static boolean isSyntheticBci(int bci) {
-        return bci < 0;
+    public static String getPlaceholderBciName(int bci) {
+        assert isPlaceholderBci(bci);
+        if (bci == BytecodeFrame.AFTER_BCI) {
+            return "AFTER_BCI";
+        } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
+            return "AFTER_EXCEPTION_BCI";
+        } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+            return "INVALID_FRAMESTATE_BCI";
+        } else if (bci == BytecodeFrame.BEFORE_BCI) {
+            return "BEFORE_BCI";
+        } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
+            return "UNKNOWN_BCI";
+        } else {
+            assert bci == BytecodeFrame.UNWIND_BCI;
+            return "UNWIND_BCI";
+        }
     }
 
     /**
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java	Wed Apr 22 15:36:53 2015 +0200
@@ -41,9 +41,22 @@
 public final class MethodSubstitutionPlugin implements InvocationPlugin {
 
     private ResolvedJavaMethod cachedSubstitute;
+
+    /**
+     * The class in which the substitute method is declared.
+     */
     private final Class<?> declaringClass;
+
+    /**
+     * The name of the original and substitute method.
+     */
     private final String name;
+
+    /**
+     * The parameter types of the substitute method.
+     */
     private final Class<?>[] parameters;
+
     private final boolean originalIsStatic;
 
     /**
@@ -62,6 +75,20 @@
         this.originalIsStatic = parameters.length == 0 || parameters[0] != Receiver.class;
     }
 
+    /**
+     * Creates a method substitution plugin.
+     *
+     * @param declaringClass the class in which the substitute method is declared
+     * @param name the name of the substitute method
+     * @param parameters the parameter types of the substitute method
+     */
+    public MethodSubstitutionPlugin(boolean originalIsStatic, Class<?> declaringClass, String name, Class<?>... parameters) {
+        this.declaringClass = declaringClass;
+        this.name = name;
+        this.parameters = parameters;
+        this.originalIsStatic = originalIsStatic;
+    }
+
     public boolean inlineOnly() {
         // Conservatively assume MacroNodes may be used in a substitution
         return true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Wed Apr 22 15:36:53 2015 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.api.code.BytecodeFrame.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
@@ -60,7 +62,7 @@
 
     @Override
     protected BytecodeFrame computeFrameForState(FrameState state) {
-        assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI : state.bci;
+        assert !isPlaceholderBci(state.bci) || state.bci == BytecodeFrame.BEFORE_BCI : state.bci;
         return super.computeFrameForState(state);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Wed Apr 22 15:36:53 2015 +0200
@@ -38,7 +38,6 @@
 import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.nodes.ClassQueryNode.Query;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.hotspot.replacements.arraycopy.*;
 import com.oracle.graal.hotspot.word.*;
@@ -79,7 +78,7 @@
         plugins.setGenericInvocationPlugin(new DefaultGenericInvocationPlugin(metaAccess, nodeIntrinsification, wordOperationPlugin));
 
         registerObjectPlugins(invocationPlugins);
-        registerClassPlugins(invocationPlugins);
+        registerClassPlugins(plugins);
         registerSystemPlugins(invocationPlugins, foreignCalls);
         registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config);
         registerCallSitePlugins(invocationPlugins);
@@ -107,27 +106,16 @@
         r.registerMethodSubstitution(ObjectSubstitutions.class, "hashCode", Receiver.class);
     }
 
-    private static void registerClassPlugins(InvocationPlugins plugins) {
-        Registration r = new Registration(plugins, Class.class);
+    private static void registerClassPlugins(Plugins plugins) {
+        Registration r = new Registration(plugins.getInvocationPlugins(), Class.class);
 
-        for (Query query : Query.values()) {
-            r.register1(query.name(), Receiver.class, new InvocationPlugin() {
-                public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
-                    ValueNode javaClass = receiver.get();
-                    ValueNode folded = ClassQueryNode.tryFold(GraphUtil.originalValue(javaClass), query, b.getMetaAccess(), b.getConstantReflection());
-                    if (folded != null) {
-                        b.addPush(query.returnKind, folded);
-                    } else {
-                        b.addPush(query.returnKind, new ClassQueryNode(b.getInvokeKind(), targetMethod, query, b.bci(), b.getInvokeReturnType(), javaClass));
-                    }
-                    return true;
-                }
+        r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "getModifiers", Receiver.class);
+        r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "isInterface", Receiver.class);
+        r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "isArray", Receiver.class);
+        r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "isPrimitive", Receiver.class);
+        r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "getSuperclass", Receiver.class);
+        r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "getComponentType", Receiver.class);
 
-                public boolean inlineOnly() {
-                    return true;
-                }
-            });
-        }
         r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() {
             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
                 ValueNode javaClass = receiver.get();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java	Wed Apr 22 15:36:53 2015 +0200
@@ -39,6 +39,7 @@
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.StandardGraphBuilderPlugins.BoxPlugin;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -149,12 +150,21 @@
             for (Node node : newNodes) {
                 if (node.hasUsages() && node instanceof ConstantNode) {
                     ConstantNode c = (ConstantNode) node;
-                    if (c.getKind() == Kind.Object && !AheadOfTimeVerificationPhase.isLegalObjectConstant(c)) {
-                        throw new AssertionError("illegal constant node in AOT: " + node);
+                    if (c.getKind() == Kind.Object && AheadOfTimeVerificationPhase.isIllegalObjectConstant(c)) {
+                        if (isClass(c)) {
+                            // This will be handled later by LoadJavaMirrorWithKlassPhase
+                        } else {
+                            throw new AssertionError("illegal constant node in AOT: " + node);
+                        }
                     }
                 }
             }
         }
         super.checkNewNodes(b, plugin, newNodes);
     }
+
+    private static boolean isClass(ConstantNode node) {
+        ResolvedJavaType typeOrNull = StampTool.typeOrNull(node);
+        return typeOrNull != null && "Ljava/lang/Class;".equals(typeOrNull.getName());
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassQueryNode.java	Wed Apr 22 15:36:38 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +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.compiler.common.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.replacements.nodes.*;
-
-/**
- * {@link MacroNode Macro node} for some basic query methods in {@link Class}.
- */
-@NodeInfo
-public final class ClassQueryNode extends MacroStateSplitNode implements Canonicalizable {
-
-    /**
-     * The query methods in {@link Class} supported by {@link ClassQueryNode}.
-     */
-    public enum Query {
-        getClassLoader0(Kind.Object),
-        getComponentType(Kind.Object),
-        getSuperclass(Kind.Object),
-        getModifiers(Kind.Int),
-        isArray(Kind.Boolean),
-        isInterface(Kind.Boolean),
-        isPrimitive(Kind.Boolean);
-
-        private Query(Kind returnKind) {
-            this.returnKind = returnKind;
-        }
-
-        public final Kind returnKind;
-    }
-
-    public static final NodeClass<ClassQueryNode> TYPE = NodeClass.create(ClassQueryNode.class);
-
-    protected final Query query;
-
-    public ClassQueryNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, Query query, int bci, JavaType returnType, ValueNode receiver) {
-        super(TYPE, invokeKind, targetMethod, bci, returnType, receiver);
-        this.query = query;
-        assert query.returnKind == targetMethod.getSignature().getReturnKind();
-    }
-
-    private ValueNode getJavaClass() {
-        return arguments.get(0);
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        ValueNode value = tryFold(getJavaClass(), query, tool.getMetaAccess(), tool.getConstantReflection());
-        return value == null ? this : value;
-    }
-
-    public static ValueNode tryFold(ValueNode javaClass, Query query, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
-        if (javaClass != null && javaClass.isConstant()) {
-            if (query.returnKind == Kind.Object) {
-                if (GraalOptions.ImmutableCode.getValue()) {
-                    return null;
-                }
-                HotSpotObjectConstant c = (HotSpotObjectConstant) javaClass.asConstant();
-                JavaConstant answer;
-                switch (query) {
-                    case getClassLoader0:
-                        answer = c.getClassLoader();
-                        break;
-                    case getComponentType:
-                        answer = c.getComponentType();
-                        break;
-                    case getSuperclass:
-                        answer = c.getSuperclass();
-                        break;
-                    default:
-                        GraalInternalError.shouldNotReachHere();
-                        answer = null;
-                }
-                if (answer != null) {
-                    return ConstantNode.forConstant(answer, metaAccess);
-                }
-            } else {
-                ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant());
-                if (type != null) {
-                    switch (query) {
-                        case isArray:
-                            return ConstantNode.forBoolean(type.isArray());
-                        case isPrimitive:
-                            return ConstantNode.forBoolean(type.isPrimitive());
-                        case isInterface:
-                            return ConstantNode.forBoolean(type.isInterface());
-                        case getModifiers:
-                            return ConstantNode.forInt(type.getModifiers());
-                        default:
-                            GraalInternalError.shouldNotReachHere();
-                    }
-                }
-            }
-        }
-        return null;
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java	Wed Apr 22 15:36:53 2015 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo
-public class G1PostWriteBarrier extends WriteBarrier {
+public class G1PostWriteBarrier extends WriteBarrier implements MemoryCheckpoint.Single {
 
     public static final NodeClass<G1PostWriteBarrier> TYPE = NodeClass.create(G1PostWriteBarrier.class);
     protected final boolean alwaysNull;
@@ -45,4 +46,8 @@
     public boolean alwaysNull() {
         return alwaysNull;
     }
+
+    public LocationIdentity getLocationIdentity() {
+        return LocationIdentity.any();
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java	Wed Apr 22 15:36:53 2015 +0200
@@ -32,7 +32,7 @@
 import com.oracle.graal.phases.tiers.*;
 
 /**
- * Checks for {@link #isLegalObjectConstant(ConstantNode) illegal} object constants in a graph
+ * Checks for {@link #isIllegalObjectConstant(ConstantNode) illegal} object constants in a graph
  * processed for AOT compilation.
  *
  * @see LoadJavaMirrorWithKlassPhase
@@ -42,14 +42,14 @@
     @Override
     protected boolean verify(StructuredGraph graph, PhaseContext context) {
         for (ConstantNode node : getConstantNodes(graph)) {
-            if (isLegalObjectConstant(node)) {
+            if (isIllegalObjectConstant(node)) {
                 throw new VerificationError("illegal object constant: " + node);
             }
         }
         return true;
     }
 
-    public static boolean isLegalObjectConstant(ConstantNode node) {
+    public static boolean isIllegalObjectConstant(ConstantNode node) {
         return isObject(node) && !isNullReference(node) && !isInternedString(node) && !isDirectMethodHandle(node) && !isBoundMethodHandle(node);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java	Wed Apr 22 15:36:53 2015 +0200
@@ -26,7 +26,6 @@
 
 import java.lang.reflect.*;
 
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.word.*;
@@ -34,10 +33,8 @@
 /**
  * Substitutions for {@link java.lang.Class} methods.
  */
-@ClassSubstitution(java.lang.Class.class)
 public class HotSpotClassSubstitutions {
 
-    @MethodSubstitution(isStatic = false, forced = true)
     public static int getModifiers(final Class<?> thisObj) {
         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
         if (klass.isNull()) {
@@ -48,7 +45,6 @@
         }
     }
 
-    @MethodSubstitution(isStatic = false, forced = true)
     public static boolean isInterface(final Class<?> thisObj) {
         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
         if (klass.isNull()) {
@@ -59,7 +55,6 @@
         }
     }
 
-    @MethodSubstitution(isStatic = false, forced = true)
     public static boolean isArray(final Class<?> thisObj) {
         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
         if (klass.isNull()) {
@@ -69,15 +64,11 @@
         }
     }
 
-    @MethodSubstitution(isStatic = false, forced = true)
     public static boolean isPrimitive(final Class<?> thisObj) {
         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
         return klass.isNull();
     }
 
-    public static native ClassLoader getClassLoader0(Class<?> thisObj);
-
-    @MethodSubstitution(isStatic = false)
     public static Class<?> getSuperclass(final Class<?> thisObj) {
         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
         if (!klass.isNull()) {
@@ -102,7 +93,6 @@
         return PiNode.asNonNullClass(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION));
     }
 
-    @MethodSubstitution(isStatic = false)
     public static Class<?> getComponentType(final Class<?> thisObj) {
         KlassPointer klass = ClassGetHubNode.readClass(thisObj);
         if (!klass.isNull()) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Wed Apr 22 15:36:53 2015 +0200
@@ -43,7 +43,6 @@
         replacements.registerSubstitutions(System.class, SystemSubstitutions.class);
         replacements.registerSubstitutions(Thread.class, ThreadSubstitutions.class);
         replacements.registerSubstitutions(Unsafe.class, UnsafeSubstitutions.class);
-        replacements.registerSubstitutions(Class.class, HotSpotClassSubstitutions.class);
         replacements.registerSubstitutions(CRC32.class, CRC32Substitutions.class);
         replacements.registerSubstitutions(Reflection.class, ReflectionSubstitutions.class);
         replacements.registerSubstitutions(CompilerToVMImpl.class, CompilerToVMImplSubstitutions.class);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Apr 22 15:36:53 2015 +0200
@@ -124,7 +124,7 @@
                 frameState.initializeForMethodStart(graphBuilderConfig.eagerResolving() || replacementContext != null, graphBuilderConfig.getPlugins().getParameterPlugin());
                 parser.build(graph.start(), frameState);
 
-                connectLoopEndToBegin(graph);
+                GraphUtil.normalizeLoops(graph);
 
                 // Remove dead parameters.
                 for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
@@ -2428,27 +2428,4 @@
         assert assertionsEnabled = true;
         return assertionsEnabled;
     }
-
-    /**
-     * Remove loop header without loop ends. This can happen with degenerated loops like this one:
-     *
-     * <pre>
-     * for (;;) {
-     *     try {
-     *         break;
-     *     } catch (UnresolvedException iioe) {
-     *     }
-     * }
-     * </pre>
-     */
-    public static void connectLoopEndToBegin(StructuredGraph graph) {
-        for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.TYPE)) {
-            if (begin.loopEnds().isEmpty()) {
-                assert begin.forwardEndCount() == 1;
-                graph.reduceDegenerateLoopBegin(begin);
-            } else {
-                GraphUtil.normalizeLoopBegin(begin);
-            }
-        }
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Wed Apr 22 15:36:53 2015 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import static com.oracle.graal.api.code.BytecodeFrame.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -293,7 +295,7 @@
      * is that a stateAfter is being transformed into a stateDuring, so the stack depth may change.
      */
     private boolean checkStackDepth(int oldBci, int oldStackSize, boolean oldDuringCall, boolean oldRethrowException, int newBci, int newStackSize, boolean newDuringCall, boolean newRethrowException) {
-        if (BytecodeFrame.isSyntheticBci(oldBci)) {
+        if (BytecodeFrame.isPlaceholderBci(oldBci)) {
             return true;
         }
         /*
@@ -449,18 +451,8 @@
                 properties.put("sourceLine", ste.getLineNumber());
             }
         }
-        if (bci == BytecodeFrame.AFTER_BCI) {
-            properties.put("bci", "AFTER_BCI");
-        } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
-            properties.put("bci", "AFTER_EXCEPTION_BCI");
-        } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
-            properties.put("bci", "INVALID_FRAMESTATE_BCI");
-        } else if (bci == BytecodeFrame.BEFORE_BCI) {
-            properties.put("bci", "BEFORE_BCI");
-        } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
-            properties.put("bci", "UNKNOWN_BCI");
-        } else if (bci == BytecodeFrame.UNWIND_BCI) {
-            properties.put("bci", "UNWIND_BCI");
+        if (isPlaceholderBci(bci)) {
+            properties.put("bci", getPlaceholderBciName(bci));
         }
         properties.put("locksSize", values.size() - stackSize - localsSize);
         return properties;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java	Wed Apr 22 15:36:53 2015 +0200
@@ -257,10 +257,14 @@
     }
 
     public final void decode(StructuredGraph graph, EncodedGraph encodedGraph) {
-        MethodScope methodScope = new MethodScope(graph, encodedGraph, LoopExplosionKind.NONE);
-        decode(methodScope, null);
-        cleanupGraph(methodScope, null);
-        methodScope.graph.verify();
+        try (Debug.Scope scope = Debug.scope("GraphDecoder", graph)) {
+            MethodScope methodScope = new MethodScope(graph, encodedGraph, LoopExplosionKind.NONE);
+            decode(methodScope, null);
+            cleanupGraph(methodScope, null);
+            methodScope.graph.verify();
+        } catch (Throwable ex) {
+            Debug.handle(ex);
+        }
     }
 
     protected final void decode(MethodScope methodScope, FixedWithNextNode startNode) {
@@ -287,6 +291,7 @@
                 assert loopScope.nextIterations.peekFirst().loopIteration == loopScope.loopIteration + 1;
                 loopScope = loopScope.nextIterations.removeFirst();
             } else {
+                propagateCreatedNodes(loopScope);
                 loopScope = loopScope.outer;
             }
         }
@@ -303,6 +308,19 @@
         }
     }
 
+    private static void propagateCreatedNodes(LoopScope loopScope) {
+        if (loopScope.outer == null) {
+            return;
+        }
+
+        /* Register nodes that were created while decoding the loop to the outside scope. */
+        for (int i = 0; i < loopScope.createdNodes.length; i++) {
+            if (loopScope.outer.createdNodes[i] == null) {
+                loopScope.outer.createdNodes[i] = loopScope.createdNodes[i];
+            }
+        }
+    }
+
     protected LoopScope processNextNode(MethodScope methodScope, LoopScope loopScope) {
         int nodeOrderId = loopScope.nodesToProcess.nextSetBit(0);
         loopScope.nodesToProcess.clear(nodeOrderId);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java	Wed Apr 22 15:36:53 2015 +0200
@@ -442,9 +442,6 @@
             }
         }
 
-        for (Node expectedNode : expectedGraph.getNodes()) {
-            assert nodeMapping.get(expectedNode) != null || (expectedNode.hasNoUsages() && !(expectedNode instanceof FixedNode)) : "expectedNode";
-        }
         return true;
     }
 
@@ -486,7 +483,19 @@
         assert !actualIter.hasNext();
     }
 
-    protected static void verifyNodeEqual(Node expectedNode, Node actualNode, NodeMap<Node> nodeMapping, Deque<Pair<Node, Node>> workList, boolean ignoreEndNode) {
+    protected static void verifyNodeEqual(Node e, Node actualNode, NodeMap<Node> nodeMapping, Deque<Pair<Node, Node>> workList, boolean ignoreEndNode) {
+        Node expectedNode = e;
+        if (expectedNode instanceof PhiNode) {
+            /*
+             * The input graph can contain unnecessary (eliminatable) phi functions. Such phis are
+             * not re-created during decoding, so we need to simplify the expected node too.
+             */
+            Node singleValue = ((PhiNode) expectedNode).singleValue();
+            if (singleValue != null && singleValue != PhiNode.MULTIPLE_VALUES) {
+                expectedNode = singleValue;
+            }
+        }
+
         assert expectedNode.getClass() == actualNode.getClass();
         if (ignoreEndNode && expectedNode instanceof EndNode) {
             return;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimplifyingGraphDecoder.java	Wed Apr 22 15:36:53 2015 +0200
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2015, 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;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
+
+/**
+ * Graph decoder that simplifies nodes during decoding. The standard
+ * {@link Canonicalizable#canonical node canonicalization} interface is used to canonicalize nodes
+ * during decoding. Additionally, {@link IfNode branches} and {@link IntegerSwitchNode switches}
+ * with constant conditions are simplified.
+ */
+public class SimplifyingGraphDecoder extends GraphDecoder {
+
+    protected final MetaAccessProvider metaAccess;
+    protected final ConstantReflectionProvider constantReflection;
+    protected final StampProvider stampProvider;
+    protected final boolean canonicalizeReads;
+
+    protected class PECanonicalizerTool implements CanonicalizerTool {
+        @Override
+        public MetaAccessProvider getMetaAccess() {
+            return metaAccess;
+        }
+
+        @Override
+        public ConstantReflectionProvider getConstantReflection() {
+            return constantReflection;
+        }
+
+        @Override
+        public boolean canonicalizeReads() {
+            return canonicalizeReads;
+        }
+
+        @Override
+        public boolean allUsagesAvailable() {
+            return false;
+        }
+    }
+
+    public SimplifyingGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, boolean canonicalizeReads, Architecture architecture) {
+        super(architecture);
+        this.metaAccess = metaAccess;
+        this.constantReflection = constantReflection;
+        this.stampProvider = stampProvider;
+        this.canonicalizeReads = canonicalizeReads;
+    }
+
+    @Override
+    protected void cleanupGraph(MethodScope methodScope, Graph.Mark start) {
+        GraphUtil.normalizeLoops(methodScope.graph);
+        super.cleanupGraph(methodScope, start);
+    }
+
+    @Override
+    protected void simplifyFixedNode(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node) {
+        if (node instanceof IfNode) {
+            IfNode ifNode = (IfNode) node;
+            if (ifNode.condition() instanceof LogicNegationNode) {
+                ifNode.eliminateNegation();
+            }
+            if (ifNode.condition() instanceof LogicConstantNode) {
+                boolean condition = ((LogicConstantNode) ifNode.condition()).getValue();
+                AbstractBeginNode survivingSuccessor = ifNode.getSuccessor(condition);
+                AbstractBeginNode deadSuccessor = ifNode.getSuccessor(!condition);
+
+                methodScope.graph.removeSplit(ifNode, survivingSuccessor);
+                assert deadSuccessor.next() == null : "must not be parsed yet";
+                deadSuccessor.safeDelete();
+            }
+
+        } else if (node instanceof IntegerSwitchNode && ((IntegerSwitchNode) node).value().isConstant()) {
+            IntegerSwitchNode switchNode = (IntegerSwitchNode) node;
+            int value = switchNode.value().asJavaConstant().asInt();
+            AbstractBeginNode survivingSuccessor = switchNode.successorAtKey(value);
+            List<Node> allSuccessors = switchNode.successors().snapshot();
+
+            methodScope.graph.removeSplit(switchNode, survivingSuccessor);
+            for (Node successor : allSuccessors) {
+                if (successor != survivingSuccessor) {
+                    assert ((AbstractBeginNode) successor).next() == null : "must not be parsed yet";
+                    successor.safeDelete();
+                }
+            }
+
+        } else if (node instanceof Canonicalizable) {
+            Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool());
+            if (canonical == null) {
+                /*
+                 * This is a possible return value of canonicalization. However, we might need to
+                 * add additional usages later on for which we need a node. Therefore, we just do
+                 * nothing and leave the node in place.
+                 */
+            } else if (canonical != node) {
+                if (!canonical.isAlive()) {
+                    assert !canonical.isDeleted();
+                    canonical = methodScope.graph.addOrUniqueWithInputs(canonical);
+                    if (canonical instanceof FixedWithNextNode) {
+                        methodScope.graph.addBeforeFixed(node, (FixedWithNextNode) canonical);
+                    } else if (canonical instanceof ControlSinkNode) {
+                        FixedWithNextNode predecessor = (FixedWithNextNode) node.predecessor();
+                        predecessor.setNext((ControlSinkNode) canonical);
+                        node.safeDelete();
+                        for (Node successor : node.successors()) {
+                            successor.safeDelete();
+                        }
+
+                    } else {
+                        assert !(canonical instanceof FixedNode);
+                    }
+                }
+                if (!node.isDeleted()) {
+                    GraphUtil.unlinkFixedNode((FixedWithNextNode) node);
+                    node.replaceAtUsages(canonical);
+                    node.safeDelete();
+                }
+                assert lookupNode(loopScope, nodeOrderId) == node;
+                registerNode(loopScope, nodeOrderId, canonical, true, false);
+            }
+        }
+    }
+
+    @Override
+    protected Node handleFloatingNodeBeforeAdd(MethodScope methodScope, LoopScope loopScope, Node node) {
+        if (node instanceof Canonicalizable) {
+            Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool());
+            if (canonical == null) {
+                /*
+                 * This is a possible return value of canonicalization. However, we might need to
+                 * add additional usages later on for which we need a node. Therefore, we just do
+                 * nothing and leave the node in place.
+                 */
+            } else if (canonical != node) {
+                if (!canonical.isAlive()) {
+                    assert !canonical.isDeleted();
+                    canonical = methodScope.graph.addOrUniqueWithInputs(canonical);
+                }
+                assert node.hasNoUsages();
+                // methodScope.graph.replaceFloating((FloatingNode) node, canonical);
+                return canonical;
+            }
+        }
+        return node;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Apr 22 15:36:53 2015 +0200
@@ -80,7 +80,7 @@
             ResolvedJavaType exactType = null;
             if (objectStamp.isExactType()) {
                 exactType = objectStamp.type();
-            } else if (objectStamp.type() != null && graph().getAssumptions() != null) {
+            } else if (objectStamp.type() != null && graph() != null && graph().getAssumptions() != null) {
                 AssumptionResult<ResolvedJavaType> leafConcreteSubtype = objectStamp.type().findLeafConcreteSubtype();
                 if (leafConcreteSubtype != null) {
                     exactType = leafConcreteSubtype.getResult();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java	Wed Apr 22 15:36:53 2015 +0200
@@ -79,7 +79,7 @@
             if (result != null) {
                 return result;
             }
-            Assumptions assumptions = graph().getAssumptions();
+            Assumptions assumptions = graph() == null ? null : graph().getAssumptions();
             if (assumptions != null) {
                 AssumptionResult<ResolvedJavaType> leafConcreteSubtype = stampType.findLeafConcreteSubtype();
                 if (leafConcreteSubtype != null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Apr 22 15:36:53 2015 +0200
@@ -225,7 +225,30 @@
         }
     }
 
-    public static void normalizeLoopBegin(LoopBeginNode begin) {
+    /**
+     * Remove loop header without loop ends. This can happen with degenerated loops like this one:
+     *
+     * <pre>
+     * for (;;) {
+     *     try {
+     *         break;
+     *     } catch (UnresolvedException iioe) {
+     *     }
+     * }
+     * </pre>
+     */
+    public static void normalizeLoops(StructuredGraph graph) {
+        for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.TYPE)) {
+            if (begin.loopEnds().isEmpty()) {
+                assert begin.forwardEndCount() == 1;
+                graph.reduceDegenerateLoopBegin(begin);
+            } else {
+                normalizeLoopBegin(begin);
+            }
+        }
+    }
+
+    private static void normalizeLoopBegin(LoopBeginNode begin) {
         // Delete unnecessary loop phi functions, i.e., phi functions where all inputs are either
         // the same or the phi itself.
         for (PhiNode phi : begin.phis().snapshot()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CachingPEGraphDecoder.java	Wed Apr 22 15:36:53 2015 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, 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 java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.phases.util.*;
+
+/**
+ * A graph decoder that provides all necessary encoded graphs on-the-fly (by parsing the methods and
+ * encoding the graphs).
+ */
+public class CachingPEGraphDecoder extends PEGraphDecoder {
+
+    private final Providers providers;
+    private final GraphBuilderConfiguration graphBuilderConfig;
+    private final OptimisticOptimizations optimisticOpts;
+    private final AllowAssumptions allowAssumptions;
+    private final Map<ResolvedJavaMethod, EncodedGraph> graphCache;
+
+    public CachingPEGraphDecoder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, AllowAssumptions allowAssumptions, Architecture architecture) {
+        super(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider(), architecture);
+
+        this.providers = providers;
+        this.graphBuilderConfig = graphBuilderConfig;
+        this.optimisticOpts = optimisticOpts;
+        this.allowAssumptions = allowAssumptions;
+        this.graphCache = new HashMap<>();
+    }
+
+    private EncodedGraph createGraph(ResolvedJavaMethod method) {
+        StructuredGraph graph = new StructuredGraph(method, allowAssumptions);
+        try (Debug.Scope scope = Debug.scope("createGraph", graph)) {
+
+            new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), graphBuilderConfig, optimisticOpts, null).apply(graph);
+
+            PhaseContext context = new PhaseContext(providers);
+            new CanonicalizerPhase().apply(graph, context);
+
+            EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, architecture);
+            graphCache.put(method, encodedGraph);
+            return encodedGraph;
+
+        } catch (Throwable ex) {
+            throw Debug.handle(ex);
+        }
+    }
+
+    @Override
+    protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method) {
+        EncodedGraph result = graphCache.get(method);
+        if (result == null && method.hasBytecodes()) {
+            result = createGraph(method);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Wed Apr 22 15:36:53 2015 +0200
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 2015, 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 static com.oracle.graal.compiler.common.GraalInternalError.*;
+import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.graphbuilderconf.InlineInvokePlugin.InlineInfo;
+import com.oracle.graal.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.common.inlining.*;
+
+/**
+ * A graph decoder that performs partial evaluation, i.e., that performs method inlining and
+ * canonicalization/simplification of nodes during decoding.
+ *
+ * Inlining and loop explosion are configured via the plugin mechanism also used by the
+ * {@link GraphBuilderPhase}. However, not all callback methods defined in
+ * {@link GraphBuilderContext} are available since decoding is more limited than graph building.
+ *
+ * The standard {@link Canonicalizable#canonical node canonicalization} interface is used to
+ * canonicalize nodes during decoding. Additionally, {@link IfNode branches} and
+ * {@link IntegerSwitchNode switches} with constant conditions are simplified.
+ */
+public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
+
+    protected class PEMethodScope extends MethodScope {
+        /** The state of the caller method. Only non-null during method inlining. */
+        protected final PEMethodScope caller;
+        protected final LoopScope callerLoopScope;
+        protected final ResolvedJavaMethod method;
+        protected final InvokeData invokeData;
+        protected final int inliningDepth;
+
+        protected final LoopExplosionPlugin loopExplosionPlugin;
+        protected final InvocationPlugins invocationPlugins;
+        protected final InlineInvokePlugin inlineInvokePlugin;
+        protected final ParameterPlugin parameterPlugin;
+        protected final ValueNode[] arguments;
+
+        protected FrameState outerState;
+        protected FrameState exceptionState;
+        protected ExceptionPlaceholderNode exceptionPlaceholderNode;
+        protected BytecodePosition bytecodePosition;
+
+        protected PEMethodScope(StructuredGraph targetGraph, PEMethodScope caller, LoopScope callerLoopScope, EncodedGraph encodedGraph, ResolvedJavaMethod method, InvokeData invokeData,
+                        int inliningDepth, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin inlineInvokePlugin, ParameterPlugin parameterPlugin,
+                        ValueNode[] arguments) {
+            super(targetGraph, encodedGraph, loopExplosionKind(method, loopExplosionPlugin));
+
+            this.caller = caller;
+            this.callerLoopScope = callerLoopScope;
+            this.method = method;
+            this.invokeData = invokeData;
+            this.inliningDepth = inliningDepth;
+            this.loopExplosionPlugin = loopExplosionPlugin;
+            this.invocationPlugins = invocationPlugins;
+            this.inlineInvokePlugin = inlineInvokePlugin;
+            this.parameterPlugin = parameterPlugin;
+            this.arguments = arguments;
+        }
+
+        public boolean isInlinedMethod() {
+            return caller != null;
+        }
+    }
+
+    protected class PENonAppendGraphBuilderContext implements GraphBuilderContext {
+        protected final PEMethodScope methodScope;
+        protected final Invoke invoke;
+
+        public PENonAppendGraphBuilderContext(PEMethodScope methodScope, Invoke invoke) {
+            this.methodScope = methodScope;
+            this.invoke = invoke;
+        }
+
+        @Override
+        public BailoutException bailout(String string) {
+            throw new BailoutException(string);
+        }
+
+        @Override
+        public StampProvider getStampProvider() {
+            return stampProvider;
+        }
+
+        @Override
+        public MetaAccessProvider getMetaAccess() {
+            return metaAccess;
+        }
+
+        @Override
+        public ConstantReflectionProvider getConstantReflection() {
+            return constantReflection;
+        }
+
+        @Override
+        public StructuredGraph getGraph() {
+            return methodScope.graph;
+        }
+
+        @Override
+        public int getDepth() {
+            return methodScope.inliningDepth;
+        }
+
+        @Override
+        public Replacement getReplacement() {
+            return null;
+        }
+
+        @Override
+        public <T extends ValueNode> T append(T value) {
+            throw unimplemented();
+        }
+
+        @Override
+        public <T extends ValueNode> T recursiveAppend(T value) {
+            throw unimplemented();
+        }
+
+        @Override
+        public void push(Kind kind, ValueNode value) {
+            throw unimplemented();
+        }
+
+        @Override
+        public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) {
+            throw unimplemented();
+        }
+
+        @Override
+        public void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args) {
+            throw unimplemented();
+        }
+
+        @Override
+        public FrameState createStateAfter() {
+            throw unimplemented();
+        }
+
+        @Override
+        public GraphBuilderContext getParent() {
+            throw unimplemented();
+        }
+
+        @Override
+        public ResolvedJavaMethod getMethod() {
+            throw unimplemented();
+        }
+
+        @Override
+        public int bci() {
+            return invoke.bci();
+        }
+
+        @Override
+        public InvokeKind getInvokeKind() {
+            throw unimplemented();
+        }
+
+        @Override
+        public JavaType getInvokeReturnType() {
+            throw unimplemented();
+        }
+    }
+
+    protected class PEAppendGraphBuilderContext extends PENonAppendGraphBuilderContext {
+        protected FixedWithNextNode lastInstr;
+        protected ValueNode pushedNode;
+
+        public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr) {
+            super(inlineScope, inlineScope.invokeData.invoke);
+            this.lastInstr = lastInstr;
+        }
+
+        @Override
+        public void push(Kind kind, ValueNode value) {
+            if (pushedNode != null) {
+                throw unimplemented("Only one push is supported");
+            }
+            pushedNode = value;
+        }
+
+        @Override
+        public FrameState createStateAfter() {
+            Node stateAfter = decodeFloatingNode(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId);
+            getGraph().add(stateAfter);
+            return (FrameState) handleFloatingNodeAfterAdd(methodScope.caller, methodScope.callerLoopScope, stateAfter);
+        }
+
+        @Override
+        public <T extends ValueNode> T append(T v) {
+            if (v.graph() != null) {
+                return v;
+            }
+            T added = getGraph().addOrUnique(v);
+            if (added == v) {
+                updateLastInstruction(v);
+            }
+            return added;
+        }
+
+        @Override
+        public <T extends ValueNode> T recursiveAppend(T v) {
+            if (v.graph() != null) {
+                return v;
+            }
+            T added = getGraph().addOrUniqueWithInputs(v);
+            if (added == v) {
+                updateLastInstruction(v);
+            }
+            return added;
+        }
+
+        private <T extends ValueNode> void updateLastInstruction(T v) {
+            if (v instanceof FixedNode) {
+                FixedNode fixedNode = (FixedNode) v;
+                lastInstr.setNext(fixedNode);
+                if (fixedNode instanceof FixedWithNextNode) {
+                    FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode;
+                    assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end";
+                    lastInstr = fixedWithNextNode;
+                } else {
+                    lastInstr = null;
+                }
+            }
+        }
+    }
+
+    @NodeInfo
+    static class ExceptionPlaceholderNode extends ValueNode {
+        public static final NodeClass<ExceptionPlaceholderNode> TYPE = NodeClass.create(ExceptionPlaceholderNode.class);
+
+        public ExceptionPlaceholderNode() {
+            super(TYPE, StampFactory.object());
+        }
+    }
+
+    public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, Architecture architecture) {
+        super(metaAccess, constantReflection, stampProvider, true, architecture);
+    }
+
+    protected static LoopExplosionKind loopExplosionKind(ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin) {
+        if (loopExplosionPlugin == null) {
+            return LoopExplosionKind.NONE;
+        } else if (loopExplosionPlugin.shouldMergeExplosions(method)) {
+            return LoopExplosionKind.MERGE_EXPLODE;
+        } else if (loopExplosionPlugin.shouldExplodeLoops(method)) {
+            return LoopExplosionKind.FULL_EXPLODE;
+        } else {
+            return LoopExplosionKind.NONE;
+        }
+    }
+
+    public void decode(StructuredGraph targetGraph, ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin inlineInvokePlugin,
+                    ParameterPlugin parameterPlugin) {
+        PEMethodScope methodScope = new PEMethodScope(targetGraph, null, null, lookupEncodedGraph(method), method, null, 0, loopExplosionPlugin, invocationPlugins, inlineInvokePlugin,
+                        parameterPlugin, null);
+        decode(methodScope, null);
+        cleanupGraph(methodScope, null);
+        methodScope.graph.verify();
+    }
+
+    @Override
+    protected void checkLoopExplosionIteration(MethodScope s, LoopScope loopScope) {
+        PEMethodScope methodScope = (PEMethodScope) s;
+
+        if (loopScope.loopIteration > MaximumLoopExplosionCount.getValue()) {
+            String message = "too many loop explosion iterations - does the explosion not terminate for method " + methodScope.method + "?";
+            if (FailedLoopExplosionIsFatal.getValue()) {
+                throw new RuntimeException(message);
+            } else {
+                throw new BailoutException(message);
+            }
+        }
+    }
+
+    @Override
+    protected void handleInvoke(MethodScope s, LoopScope loopScope, InvokeData invokeData) {
+        PEMethodScope methodScope = (PEMethodScope) s;
+
+        /*
+         * Decode the call target, but do not add it to the graph yet. This avoids adding usages for
+         * all the arguments, which are expensive to remove again when we can inline the method.
+         */
+        assert invokeData.invoke.callTarget() == null : "callTarget edge is ignored during decoding of Invoke";
+        CallTargetNode callTarget = (CallTargetNode) decodeFloatingNode(methodScope, loopScope, invokeData.callTargetOrderId);
+        if (!(callTarget instanceof MethodCallTargetNode) || !trySimplifyInvoke(methodScope, loopScope, invokeData, (MethodCallTargetNode) callTarget)) {
+
+            /* We know that we need an invoke, so now we can add the call target to the graph. */
+            methodScope.graph.add(callTarget);
+            registerNode(loopScope, invokeData.callTargetOrderId, callTarget, false, false);
+            super.handleInvoke(methodScope, loopScope, invokeData);
+        }
+    }
+
+    protected boolean trySimplifyInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) {
+        // attempt to devirtualize the call
+        ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(callTarget.invokeKind(), callTarget.receiver(), callTarget.targetMethod(), invokeData.contextType);
+        if (specialCallTarget != null) {
+            callTarget.setTargetMethod(specialCallTarget);
+            callTarget.setInvokeKind(InvokeKind.Special);
+        }
+
+        if (tryInvocationPlugin(methodScope, loopScope, invokeData, callTarget)) {
+            return true;
+        }
+        if (tryInline(methodScope, loopScope, invokeData, callTarget)) {
+            return true;
+        }
+
+        if (methodScope.inlineInvokePlugin != null) {
+            methodScope.inlineInvokePlugin.notifyOfNoninlinedInvoke(new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke), callTarget.targetMethod(), invokeData.invoke);
+        }
+        return false;
+    }
+
+    protected boolean tryInvocationPlugin(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) {
+        if (methodScope.invocationPlugins == null) {
+            return false;
+        }
+
+        Invoke invoke = invokeData.invoke;
+
+        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
+        InvocationPlugin invocationPlugin = methodScope.invocationPlugins.lookupInvocation(targetMethod);
+        if (invocationPlugin == null) {
+            return false;
+        }
+
+        ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]);
+        FixedWithNextNode invokePredecessor = (FixedWithNextNode) invoke.asNode().predecessor();
+
+        /* Remove invoke from graph so that invocation plugin can append nodes to the predecessor. */
+        invoke.asNode().replaceAtPredecessor(null);
+
+        PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, methodScope.loopExplosionPlugin,
+                        methodScope.invocationPlugins, methodScope.inlineInvokePlugin, null, arguments);
+        PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor);
+        InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext);
+
+        if (invocationPlugin.execute(graphBuilderContext, targetMethod, invocationPluginReceiver.init(targetMethod, arguments), arguments)) {
+
+            if (graphBuilderContext.lastInstr != null) {
+                registerNode(loopScope, invokeData.invokeOrderId, graphBuilderContext.pushedNode, true, true);
+                invoke.asNode().replaceAtUsages(graphBuilderContext.pushedNode);
+                graphBuilderContext.lastInstr.setNext(nodeAfterInvoke(methodScope, loopScope, invokeData));
+            } else {
+                assert graphBuilderContext.pushedNode == null : "Why push a node when the invoke does not return anyway?";
+                invoke.asNode().replaceAtUsages(null);
+            }
+
+            deleteInvoke(invoke);
+            return true;
+
+        } else {
+            /* Intrinsification failed, restore original state: invoke is in Graph. */
+            invokePredecessor.setNext(invoke.asNode());
+            return false;
+        }
+    }
+
+    protected boolean tryInline(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) {
+        if (methodScope.inlineInvokePlugin == null || !callTarget.invokeKind().isDirect()) {
+            return false;
+        }
+
+        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
+        if (!targetMethod.canBeInlined()) {
+            return false;
+        }
+
+        ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]);
+        GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke);
+        InlineInfo inlineInfo = methodScope.inlineInvokePlugin.getInlineInfo(graphBuilderContext, targetMethod, arguments, callTarget.returnType());
+        if (inlineInfo == null) {
+            return false;
+        }
+        assert !inlineInfo.isIntrinsic && !inlineInfo.isReplacement : "not supported";
+
+        ResolvedJavaMethod inlineMethod = inlineInfo.methodToInline;
+        EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod);
+        if (graphToInline == null) {
+            return false;
+        }
+
+        Invoke invoke = invokeData.invoke;
+        FixedNode invokeNode = invoke.asNode();
+        FixedWithNextNode predecessor = (FixedWithNextNode) invokeNode.predecessor();
+        invokeNode.replaceAtPredecessor(null);
+
+        PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, graphToInline, inlineMethod, invokeData, methodScope.inliningDepth + 1,
+                        methodScope.loopExplosionPlugin, methodScope.invocationPlugins, methodScope.inlineInvokePlugin, null, arguments);
+        /* Do the actual inlining by decoding the inlineMethod */
+        decode(inlineScope, predecessor);
+
+        ValueNode exceptionValue = null;
+        if (inlineScope.unwindNode != null) {
+            exceptionValue = inlineScope.unwindNode.exception();
+        }
+        UnwindNode unwindNode = inlineScope.unwindNode;
+
+        if (invoke instanceof InvokeWithExceptionNode) {
+            InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke);
+            assert invokeWithException.next() == null;
+            assert invokeWithException.exceptionEdge() == null;
+
+            if (unwindNode != null) {
+                assert unwindNode.predecessor() != null;
+                Node n = makeStubNode(methodScope, loopScope, invokeData.exceptionNextOrderId);
+                unwindNode.replaceAndDelete(n);
+            }
+
+        } else {
+            if (unwindNode != null && !unwindNode.isDeleted()) {
+                DeoptimizeNode deoptimizeNode = methodScope.graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
+                unwindNode.replaceAndDelete(deoptimizeNode);
+            }
+        }
+
+        assert invoke.next() == null;
+
+        ValueNode returnValue;
+        List<ReturnNode> returnNodes = inlineScope.returnNodes;
+        if (!returnNodes.isEmpty()) {
+            FixedNode n;
+            n = nodeAfterInvoke(methodScope, loopScope, invokeData);
+            if (returnNodes.size() == 1) {
+                ReturnNode returnNode = returnNodes.get(0);
+                returnValue = returnNode.result();
+                returnNode.replaceAndDelete(n);
+            } else {
+                AbstractMergeNode merge = methodScope.graph.add(new MergeNode());
+                merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId));
+                returnValue = InliningUtil.mergeReturns(merge, returnNodes, null);
+                merge.setNext(n);
+            }
+        } else {
+            returnValue = null;
+        }
+        invokeNode.replaceAtUsages(returnValue);
+
+        /*
+         * Usage the handles that we have on the return value and the exception to update the
+         * orderId->Node table.
+         */
+        registerNode(loopScope, invokeData.invokeOrderId, returnValue, true, true);
+        if (invoke instanceof InvokeWithExceptionNode) {
+            registerNode(loopScope, invokeData.exceptionOrderId, exceptionValue, true, true);
+        }
+        if (inlineScope.exceptionPlaceholderNode != null) {
+            inlineScope.exceptionPlaceholderNode.replaceAndDelete(exceptionValue);
+        }
+        deleteInvoke(invoke);
+
+        methodScope.inlineInvokePlugin.postInline(inlineMethod);
+        return true;
+    }
+
+    public FixedNode nodeAfterInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData) {
+        FixedNode n;
+        if (invokeData.invoke instanceof InvokeWithExceptionNode) {
+            n = makeStubNode(methodScope, loopScope, invokeData.nextNextOrderId);
+        } else {
+            n = makeStubNode(methodScope, loopScope, invokeData.nextOrderId);
+        }
+        return n;
+    }
+
+    private static void deleteInvoke(Invoke invoke) {
+        /*
+         * Clean up unused nodes. We cannot just call killCFG on the invoke node because that can
+         * kill too much: nodes that are decoded later can use values that appear unused by now.
+         */
+        FrameState frameState = invoke.stateAfter();
+        invoke.asNode().safeDelete();
+        assert invoke.callTarget() == null : "must not have been added to the graph yet";
+        if (frameState != null && frameState.hasNoUsages()) {
+            frameState.safeDelete();
+        }
+    }
+
+    protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method);
+
+    @Override
+    protected Node handleFloatingNodeBeforeAdd(MethodScope s, LoopScope loopScope, Node node) {
+        PEMethodScope methodScope = (PEMethodScope) s;
+
+        if (node instanceof ParameterNode) {
+            if (methodScope.arguments != null) {
+                Node result = methodScope.arguments[((ParameterNode) node).index()];
+                assert result != null;
+                return result;
+
+            } else if (methodScope.parameterPlugin != null) {
+                GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, null);
+                Node result = methodScope.parameterPlugin.interceptParameter(graphBuilderContext, ((ParameterNode) node).index(), ((ParameterNode) node).stamp());
+                if (result != null) {
+                    return result;
+                }
+            }
+
+        }
+
+        return super.handleFloatingNodeBeforeAdd(methodScope, loopScope, node);
+    }
+
+    protected void ensureOuterStateDecoded(PEMethodScope methodScope) {
+        if (methodScope.outerState == null && methodScope.caller != null) {
+            FrameState stateAtReturn = methodScope.invokeData.invoke.stateAfter();
+            if (stateAtReturn == null) {
+                stateAtReturn = (FrameState) decodeFloatingNode(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId);
+            }
+
+            Kind invokeReturnKind = methodScope.invokeData.invoke.asNode().getKind();
+            FrameState outerState = stateAtReturn.duplicateModified(methodScope.graph, methodScope.invokeData.invoke.bci(), stateAtReturn.rethrowException(), true, invokeReturnKind);
+
+            /*
+             * When the encoded graph has methods inlining, we can already have a proper caller
+             * state. If not, we set the caller state here.
+             */
+            if (outerState.outerFrameState() == null && methodScope.caller != null) {
+                ensureOuterStateDecoded(methodScope.caller);
+                outerState.setOuterFrameState(methodScope.caller.outerState);
+            }
+            methodScope.outerState = outerState;
+        }
+    }
+
+    protected void ensureStateAfterDecoded(PEMethodScope methodScope) {
+        if (methodScope.invokeData.invoke.stateAfter() == null) {
+            methodScope.invokeData.invoke.setStateAfter((FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId));
+        }
+    }
+
+    protected void ensureExceptionStateDecoded(PEMethodScope methodScope) {
+        if (methodScope.exceptionState == null && methodScope.caller != null && methodScope.invokeData.invoke instanceof InvokeWithExceptionNode) {
+            ensureStateAfterDecoded(methodScope);
+
+            assert methodScope.exceptionPlaceholderNode == null;
+            methodScope.exceptionPlaceholderNode = methodScope.graph.add(new ExceptionPlaceholderNode());
+            registerNode(methodScope.callerLoopScope, methodScope.invokeData.exceptionOrderId, methodScope.exceptionPlaceholderNode, false, false);
+            FrameState exceptionState = (FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.exceptionStateOrderId);
+
+            if (exceptionState.outerFrameState() == null && methodScope.caller != null) {
+                ensureOuterStateDecoded(methodScope.caller);
+                exceptionState.setOuterFrameState(methodScope.caller.outerState);
+            }
+            methodScope.exceptionState = exceptionState;
+        }
+    }
+
+    @Override
+    protected Node handleFloatingNodeAfterAdd(MethodScope s, LoopScope loopScope, Node node) {
+        PEMethodScope methodScope = (PEMethodScope) s;
+
+        if (methodScope.isInlinedMethod()) {
+            if (node instanceof SimpleInfopointNode) {
+                methodScope.bytecodePosition = InliningUtil.processSimpleInfopoint(methodScope.invokeData.invoke, (SimpleInfopointNode) node, methodScope.bytecodePosition);
+                return node;
+
+            } else if (node instanceof FrameState) {
+                FrameState frameState = (FrameState) node;
+
+                ensureOuterStateDecoded(methodScope);
+                if (frameState.bci < 0) {
+                    ensureExceptionStateDecoded(methodScope);
+                }
+                return InliningUtil.processFrameState(frameState, methodScope.invokeData.invoke, methodScope.method, methodScope.exceptionState, methodScope.outerState, true);
+
+            } else if (node instanceof MonitorIdNode) {
+                ensureOuterStateDecoded(methodScope);
+                InliningUtil.processMonitorId(methodScope.outerState, (MonitorIdNode) node);
+                return node;
+            }
+        }
+
+        return node;
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Wed Apr 22 15:36:53 2015 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.replacements.nodes;
 
+import static com.oracle.graal.api.code.BytecodeFrame.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
@@ -74,7 +76,7 @@
         this.targetMethod = targetMethod;
         this.returnType = returnType;
         this.invokeKind = invokeKind;
-        assert bci >= 0;
+        assert !isPlaceholderBci(bci);
     }
 
     public int getBci() {
@@ -171,8 +173,8 @@
             InliningUtil.inline(invoke, replacementGraph, false, null);
             Debug.dump(graph(), "After inlining replacement %s", replacementGraph);
         } else {
-            if (invoke.bci() < 0) {
-                throw new GraalInternalError("%s: cannot lower to invoke with invalid BCI: %s", graph(), this);
+            if (isPlaceholderBci(invoke.bci())) {
+                throw new GraalInternalError("%s: cannot lower to invoke with placeholder BCI: %s", graph(), this);
             }
 
             if (invoke.stateAfter() == null) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java	Wed Apr 22 15:36:38 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2015, 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;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graphbuilderconf.*;
-import com.oracle.graal.java.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.phases.util.*;
-
-/**
- * A graph decoder that provides all necessary encoded graphs on-the-fly (by parsing the methods and
- * encoding the graphs).
- */
-public class CachingPEGraphDecoder extends PEGraphDecoder {
-
-    private final Providers providers;
-    private final GraphBuilderConfiguration graphBuilderConfig;
-    private final AllowAssumptions allowAssumptions;
-    private final Map<ResolvedJavaMethod, EncodedGraph> graphCache;
-
-    public CachingPEGraphDecoder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, AllowAssumptions allowAssumptions, Architecture architecture) {
-        super(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider(), architecture);
-
-        this.providers = providers;
-        this.graphBuilderConfig = graphBuilderConfig;
-        this.allowAssumptions = allowAssumptions;
-        this.graphCache = new HashMap<>();
-    }
-
-    private EncodedGraph createGraph(ResolvedJavaMethod method) {
-        StructuredGraph graph = new StructuredGraph(method, allowAssumptions);
-        try (Debug.Scope scope = Debug.scope("createGraph", graph)) {
-
-            new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), graphBuilderConfig, TruffleCompilerImpl.Optimizations, null).apply(graph);
-
-            PhaseContext context = new PhaseContext(providers);
-            new CanonicalizerPhase().apply(graph, context);
-
-            EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, architecture);
-            graphCache.put(method, encodedGraph);
-            return encodedGraph;
-
-        } catch (Throwable ex) {
-            throw Debug.handle(ex);
-        }
-    }
-
-    @Override
-    protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method) {
-        EncodedGraph result = graphCache.get(method);
-        if (result == null && method.hasBytecodes()) {
-            result = createGraph(method);
-        }
-        return result;
-    }
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java	Wed Apr 22 15:36:38 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,725 +0,0 @@
-/*
- * Copyright (c) 2015, 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;
-
-import static com.oracle.graal.compiler.common.GraalInternalError.*;
-import static com.oracle.graal.java.AbstractBytecodeParser.Options.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.graphbuilderconf.*;
-import com.oracle.graal.graphbuilderconf.InlineInvokePlugin.InlineInfo;
-import com.oracle.graal.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
-import com.oracle.graal.java.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.common.inlining.*;
-
-/**
- * A graph decoder that performs partial evaluation, i.e., that performs method inlining and
- * canonicalization/simplification of nodes during decoding.
- *
- * Inlining and loop explosion are configured via the plugin mechanism also used by the
- * {@link GraphBuilderPhase}. However, not all callback methods defined in
- * {@link GraphBuilderContext} are available since decoding is more limited than graph building.
- *
- * The standard {@link Canonicalizable#canonical node canonicalization} interface is used to
- * canonicalize nodes during decoding. Additionally, {@link IfNode branches} and
- * {@link IntegerSwitchNode switches} with constant conditions are simplified.
- */
-public abstract class PEGraphDecoder extends GraphDecoder {
-
-    protected final MetaAccessProvider metaAccess;
-    protected final ConstantReflectionProvider constantReflection;
-    protected final StampProvider stampProvider;
-
-    protected class PEMethodScope extends MethodScope {
-        /** The state of the caller method. Only non-null during method inlining. */
-        protected final PEMethodScope caller;
-        protected final LoopScope callerLoopScope;
-        protected final ResolvedJavaMethod method;
-        protected final InvokeData invokeData;
-        protected final int inliningDepth;
-
-        protected final LoopExplosionPlugin loopExplosionPlugin;
-        protected final InvocationPlugins invocationPlugins;
-        protected final InlineInvokePlugin inlineInvokePlugin;
-        protected final ParameterPlugin parameterPlugin;
-        protected final ValueNode[] arguments;
-
-        protected FrameState outerState;
-        protected FrameState exceptionState;
-        protected ExceptionPlaceholderNode exceptionPlaceholderNode;
-        protected BytecodePosition bytecodePosition;
-
-        protected PEMethodScope(StructuredGraph targetGraph, PEMethodScope caller, LoopScope callerLoopScope, EncodedGraph encodedGraph, ResolvedJavaMethod method, InvokeData invokeData,
-                        int inliningDepth, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin inlineInvokePlugin, ParameterPlugin parameterPlugin,
-                        ValueNode[] arguments) {
-            super(targetGraph, encodedGraph, loopExplosionKind(method, loopExplosionPlugin));
-
-            this.caller = caller;
-            this.callerLoopScope = callerLoopScope;
-            this.method = method;
-            this.invokeData = invokeData;
-            this.inliningDepth = inliningDepth;
-            this.loopExplosionPlugin = loopExplosionPlugin;
-            this.invocationPlugins = invocationPlugins;
-            this.inlineInvokePlugin = inlineInvokePlugin;
-            this.parameterPlugin = parameterPlugin;
-            this.arguments = arguments;
-        }
-
-        public boolean isInlinedMethod() {
-            return caller != null;
-        }
-    }
-
-    protected class PECanonicalizerTool implements CanonicalizerTool {
-        @Override
-        public MetaAccessProvider getMetaAccess() {
-            return metaAccess;
-        }
-
-        @Override
-        public ConstantReflectionProvider getConstantReflection() {
-            return constantReflection;
-        }
-
-        @Override
-        public boolean canonicalizeReads() {
-            return true;
-        }
-
-        @Override
-        public boolean allUsagesAvailable() {
-            return false;
-        }
-    }
-
-    protected class PENonAppendGraphBuilderContext implements GraphBuilderContext {
-        protected final PEMethodScope methodScope;
-        protected final Invoke invoke;
-
-        public PENonAppendGraphBuilderContext(PEMethodScope methodScope, Invoke invoke) {
-            this.methodScope = methodScope;
-            this.invoke = invoke;
-        }
-
-        @Override
-        public BailoutException bailout(String string) {
-            throw new BailoutException(string);
-        }
-
-        @Override
-        public StampProvider getStampProvider() {
-            return stampProvider;
-        }
-
-        @Override
-        public MetaAccessProvider getMetaAccess() {
-            return metaAccess;
-        }
-
-        @Override
-        public ConstantReflectionProvider getConstantReflection() {
-            return constantReflection;
-        }
-
-        @Override
-        public StructuredGraph getGraph() {
-            return methodScope.graph;
-        }
-
-        @Override
-        public int getDepth() {
-            return methodScope.inliningDepth;
-        }
-
-        @Override
-        public Replacement getReplacement() {
-            return null;
-        }
-
-        @Override
-        public <T extends ValueNode> T append(T value) {
-            throw unimplemented();
-        }
-
-        @Override
-        public <T extends ValueNode> T recursiveAppend(T value) {
-            throw unimplemented();
-        }
-
-        @Override
-        public void push(Kind kind, ValueNode value) {
-            throw unimplemented();
-        }
-
-        @Override
-        public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) {
-            throw unimplemented();
-        }
-
-        @Override
-        public void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args) {
-            throw unimplemented();
-        }
-
-        @Override
-        public FrameState createStateAfter() {
-            throw unimplemented();
-        }
-
-        @Override
-        public GraphBuilderContext getParent() {
-            throw unimplemented();
-        }
-
-        @Override
-        public ResolvedJavaMethod getMethod() {
-            throw unimplemented();
-        }
-
-        @Override
-        public int bci() {
-            return invoke.bci();
-        }
-
-        @Override
-        public InvokeKind getInvokeKind() {
-            throw unimplemented();
-        }
-
-        @Override
-        public JavaType getInvokeReturnType() {
-            throw unimplemented();
-        }
-    }
-
-    protected class PEAppendGraphBuilderContext extends PENonAppendGraphBuilderContext {
-        protected FixedWithNextNode lastInstr;
-        protected ValueNode pushedNode;
-
-        public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr) {
-            super(inlineScope, inlineScope.invokeData.invoke);
-            this.lastInstr = lastInstr;
-        }
-
-        @Override
-        public void push(Kind kind, ValueNode value) {
-            if (pushedNode != null) {
-                throw unimplemented("Only one push is supported");
-            }
-            pushedNode = value;
-        }
-
-        @Override
-        public FrameState createStateAfter() {
-            Node stateAfter = decodeFloatingNode(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId);
-            getGraph().add(stateAfter);
-            return (FrameState) handleFloatingNodeAfterAdd(methodScope.caller, methodScope.callerLoopScope, stateAfter);
-        }
-
-        @Override
-        public <T extends ValueNode> T append(T v) {
-            if (v.graph() != null) {
-                return v;
-            }
-            T added = getGraph().addOrUnique(v);
-            if (added == v) {
-                updateLastInstruction(v);
-            }
-            return added;
-        }
-
-        @Override
-        public <T extends ValueNode> T recursiveAppend(T v) {
-            if (v.graph() != null) {
-                return v;
-            }
-            T added = getGraph().addOrUniqueWithInputs(v);
-            if (added == v) {
-                updateLastInstruction(v);
-            }
-            return added;
-        }
-
-        private <T extends ValueNode> void updateLastInstruction(T v) {
-            if (v instanceof FixedNode) {
-                FixedNode fixedNode = (FixedNode) v;
-                lastInstr.setNext(fixedNode);
-                if (fixedNode instanceof FixedWithNextNode) {
-                    FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode;
-                    assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end";
-                    lastInstr = fixedWithNextNode;
-                } else {
-                    lastInstr = null;
-                }
-            }
-        }
-    }
-
-    @NodeInfo
-    static class ExceptionPlaceholderNode extends ValueNode {
-        public static final NodeClass<ExceptionPlaceholderNode> TYPE = NodeClass.create(ExceptionPlaceholderNode.class);
-
-        public ExceptionPlaceholderNode() {
-            super(TYPE, StampFactory.object());
-        }
-    }
-
-    public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, Architecture architecture) {
-        super(architecture);
-        this.metaAccess = metaAccess;
-        this.constantReflection = constantReflection;
-        this.stampProvider = stampProvider;
-    }
-
-    protected static LoopExplosionKind loopExplosionKind(ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin) {
-        if (loopExplosionPlugin == null) {
-            return LoopExplosionKind.NONE;
-        } else if (loopExplosionPlugin.shouldMergeExplosions(method)) {
-            return LoopExplosionKind.MERGE_EXPLODE;
-        } else if (loopExplosionPlugin.shouldExplodeLoops(method)) {
-            return LoopExplosionKind.FULL_EXPLODE;
-        } else {
-            return LoopExplosionKind.NONE;
-        }
-    }
-
-    public void decode(StructuredGraph targetGraph, ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin inlineInvokePlugin,
-                    ParameterPlugin parameterPlugin) {
-        PEMethodScope methodScope = new PEMethodScope(targetGraph, null, null, lookupEncodedGraph(method), method, null, 0, loopExplosionPlugin, invocationPlugins, inlineInvokePlugin,
-                        parameterPlugin, null);
-        decode(methodScope, null);
-        cleanupGraph(methodScope, null);
-        methodScope.graph.verify();
-    }
-
-    @Override
-    protected void cleanupGraph(MethodScope methodScope, Graph.Mark start) {
-        GraphBuilderPhase.connectLoopEndToBegin(methodScope.graph);
-        super.cleanupGraph(methodScope, start);
-    }
-
-    @Override
-    protected void checkLoopExplosionIteration(MethodScope s, LoopScope loopScope) {
-        PEMethodScope methodScope = (PEMethodScope) s;
-
-        if (loopScope.loopIteration > MaximumLoopExplosionCount.getValue()) {
-            String message = "too many loop explosion iterations - does the explosion not terminate for method " + methodScope.method + "?";
-            if (FailedLoopExplosionIsFatal.getValue()) {
-                throw new RuntimeException(message);
-            } else {
-                throw new BailoutException(message);
-            }
-        }
-    }
-
-    @Override
-    protected void handleInvoke(MethodScope s, LoopScope loopScope, InvokeData invokeData) {
-        PEMethodScope methodScope = (PEMethodScope) s;
-
-        /*
-         * Decode the call target, but do not add it to the graph yet. This avoids adding usages for
-         * all the arguments, which are expensive to remove again when we can inline the method.
-         */
-        assert invokeData.invoke.callTarget() == null : "callTarget edge is ignored during decoding of Invoke";
-        CallTargetNode callTarget = (CallTargetNode) decodeFloatingNode(methodScope, loopScope, invokeData.callTargetOrderId);
-        if (!(callTarget instanceof MethodCallTargetNode) || !trySimplifyInvoke(methodScope, loopScope, invokeData, (MethodCallTargetNode) callTarget)) {
-
-            /* We know that we need an invoke, so now we can add the call target to the graph. */
-            methodScope.graph.add(callTarget);
-            registerNode(loopScope, invokeData.callTargetOrderId, callTarget, false, false);
-            super.handleInvoke(methodScope, loopScope, invokeData);
-        }
-    }
-
-    protected boolean trySimplifyInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) {
-        // attempt to devirtualize the call
-        ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(callTarget.invokeKind(), callTarget.receiver(), callTarget.targetMethod(), invokeData.contextType);
-        if (specialCallTarget != null) {
-            callTarget.setTargetMethod(specialCallTarget);
-            callTarget.setInvokeKind(InvokeKind.Special);
-        }
-
-        if (tryInvocationPlugin(methodScope, loopScope, invokeData, callTarget)) {
-            return true;
-        }
-        if (tryInline(methodScope, loopScope, invokeData, callTarget)) {
-            return true;
-        }
-
-        if (methodScope.inlineInvokePlugin != null) {
-            methodScope.inlineInvokePlugin.notifyOfNoninlinedInvoke(new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke), callTarget.targetMethod(), invokeData.invoke);
-        }
-        return false;
-    }
-
-    protected boolean tryInvocationPlugin(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) {
-        if (methodScope.invocationPlugins == null) {
-            return false;
-        }
-
-        Invoke invoke = invokeData.invoke;
-
-        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-        InvocationPlugin invocationPlugin = methodScope.invocationPlugins.lookupInvocation(targetMethod);
-        if (invocationPlugin == null) {
-            return false;
-        }
-
-        ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]);
-        FixedWithNextNode invokePredecessor = (FixedWithNextNode) invoke.asNode().predecessor();
-
-        /* Remove invoke from graph so that invocation plugin can append nodes to the predecessor. */
-        invoke.asNode().replaceAtPredecessor(null);
-
-        PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, methodScope.loopExplosionPlugin,
-                        methodScope.invocationPlugins, methodScope.inlineInvokePlugin, null, arguments);
-        PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor);
-        InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext);
-
-        if (invocationPlugin.execute(graphBuilderContext, targetMethod, invocationPluginReceiver.init(targetMethod, arguments), arguments)) {
-
-            if (graphBuilderContext.lastInstr != null) {
-                registerNode(loopScope, invokeData.invokeOrderId, graphBuilderContext.pushedNode, true, true);
-                invoke.asNode().replaceAtUsages(graphBuilderContext.pushedNode);
-                graphBuilderContext.lastInstr.setNext(nodeAfterInvoke(methodScope, loopScope, invokeData));
-            } else {
-                assert graphBuilderContext.pushedNode == null : "Why push a node when the invoke does not return anyway?";
-                invoke.asNode().replaceAtUsages(null);
-            }
-
-            deleteInvoke(invoke);
-            return true;
-
-        } else {
-            /* Intrinsification failed, restore original state: invoke is in Graph. */
-            invokePredecessor.setNext(invoke.asNode());
-            return false;
-        }
-    }
-
-    protected boolean tryInline(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) {
-        if (methodScope.inlineInvokePlugin == null || !callTarget.invokeKind().isDirect()) {
-            return false;
-        }
-
-        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-        if (!targetMethod.canBeInlined()) {
-            return false;
-        }
-
-        ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]);
-        GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke);
-        InlineInfo inlineInfo = methodScope.inlineInvokePlugin.getInlineInfo(graphBuilderContext, targetMethod, arguments, callTarget.returnType());
-        if (inlineInfo == null) {
-            return false;
-        }
-        assert !inlineInfo.isIntrinsic && !inlineInfo.isReplacement : "not supported";
-
-        ResolvedJavaMethod inlineMethod = inlineInfo.methodToInline;
-        EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod);
-        if (graphToInline == null) {
-            return false;
-        }
-
-        Invoke invoke = invokeData.invoke;
-        FixedNode invokeNode = invoke.asNode();
-        FixedWithNextNode predecessor = (FixedWithNextNode) invokeNode.predecessor();
-        invokeNode.replaceAtPredecessor(null);
-
-        PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, graphToInline, inlineMethod, invokeData, methodScope.inliningDepth + 1,
-                        methodScope.loopExplosionPlugin, methodScope.invocationPlugins, methodScope.inlineInvokePlugin, null, arguments);
-        /* Do the actual inlining by decoding the inlineMethod */
-        decode(inlineScope, predecessor);
-
-        ValueNode exceptionValue = null;
-        if (inlineScope.unwindNode != null) {
-            exceptionValue = inlineScope.unwindNode.exception();
-        }
-        UnwindNode unwindNode = inlineScope.unwindNode;
-
-        if (invoke instanceof InvokeWithExceptionNode) {
-            InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke);
-            assert invokeWithException.next() == null;
-            assert invokeWithException.exceptionEdge() == null;
-
-            if (unwindNode != null) {
-                assert unwindNode.predecessor() != null;
-                Node n = makeStubNode(methodScope, loopScope, invokeData.exceptionNextOrderId);
-                unwindNode.replaceAndDelete(n);
-            }
-
-        } else {
-            if (unwindNode != null && !unwindNode.isDeleted()) {
-                DeoptimizeNode deoptimizeNode = methodScope.graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
-                unwindNode.replaceAndDelete(deoptimizeNode);
-            }
-        }
-
-        assert invoke.next() == null;
-
-        ValueNode returnValue;
-        List<ReturnNode> returnNodes = inlineScope.returnNodes;
-        if (!returnNodes.isEmpty()) {
-            FixedNode n;
-            n = nodeAfterInvoke(methodScope, loopScope, invokeData);
-            if (returnNodes.size() == 1) {
-                ReturnNode returnNode = returnNodes.get(0);
-                returnValue = returnNode.result();
-                returnNode.replaceAndDelete(n);
-            } else {
-                AbstractMergeNode merge = methodScope.graph.add(new MergeNode());
-                merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId));
-                returnValue = InliningUtil.mergeReturns(merge, returnNodes, null);
-                merge.setNext(n);
-            }
-        } else {
-            returnValue = null;
-        }
-        invokeNode.replaceAtUsages(returnValue);
-
-        /*
-         * Usage the handles that we have on the return value and the exception to update the
-         * orderId->Node table.
-         */
-        registerNode(loopScope, invokeData.invokeOrderId, returnValue, true, true);
-        if (invoke instanceof InvokeWithExceptionNode) {
-            registerNode(loopScope, invokeData.exceptionOrderId, exceptionValue, true, true);
-        }
-        if (inlineScope.exceptionPlaceholderNode != null) {
-            inlineScope.exceptionPlaceholderNode.replaceAndDelete(exceptionValue);
-        }
-        deleteInvoke(invoke);
-
-        methodScope.inlineInvokePlugin.postInline(inlineMethod);
-        return true;
-    }
-
-    public FixedNode nodeAfterInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData) {
-        FixedNode n;
-        if (invokeData.invoke instanceof InvokeWithExceptionNode) {
-            n = makeStubNode(methodScope, loopScope, invokeData.nextNextOrderId);
-        } else {
-            n = makeStubNode(methodScope, loopScope, invokeData.nextOrderId);
-        }
-        return n;
-    }
-
-    private static void deleteInvoke(Invoke invoke) {
-        /*
-         * Clean up unused nodes. We cannot just call killCFG on the invoke node because that can
-         * kill too much: nodes that are decoded later can use values that appear unused by now.
-         */
-        FrameState frameState = invoke.stateAfter();
-        invoke.asNode().safeDelete();
-        assert invoke.callTarget() == null : "must not have been added to the graph yet";
-        if (frameState != null && frameState.hasNoUsages()) {
-            frameState.safeDelete();
-        }
-    }
-
-    protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method);
-
-    @Override
-    protected void simplifyFixedNode(MethodScope s, LoopScope loopScope, int nodeOrderId, FixedNode node) {
-        PEMethodScope methodScope = (PEMethodScope) s;
-
-        if (node instanceof IfNode) {
-            IfNode ifNode = (IfNode) node;
-            if (ifNode.condition() instanceof LogicNegationNode) {
-                ifNode.eliminateNegation();
-            }
-            if (ifNode.condition() instanceof LogicConstantNode) {
-                boolean condition = ((LogicConstantNode) ifNode.condition()).getValue();
-                AbstractBeginNode survivingSuccessor = ifNode.getSuccessor(condition);
-                AbstractBeginNode deadSuccessor = ifNode.getSuccessor(!condition);
-
-                methodScope.graph.removeSplit(ifNode, survivingSuccessor);
-                assert deadSuccessor.next() == null : "must not be parsed yet";
-                deadSuccessor.safeDelete();
-            }
-
-        } else if (node instanceof IntegerSwitchNode && ((IntegerSwitchNode) node).value().isConstant()) {
-            IntegerSwitchNode switchNode = (IntegerSwitchNode) node;
-            int value = switchNode.value().asJavaConstant().asInt();
-            AbstractBeginNode survivingSuccessor = switchNode.successorAtKey(value);
-            List<Node> allSuccessors = switchNode.successors().snapshot();
-
-            methodScope.graph.removeSplit(switchNode, survivingSuccessor);
-            for (Node successor : allSuccessors) {
-                if (successor != survivingSuccessor) {
-                    assert ((AbstractBeginNode) successor).next() == null : "must not be parsed yet";
-                    successor.safeDelete();
-                }
-            }
-
-        } else if (node instanceof Canonicalizable) {
-            Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool());
-            if (canonical == null) {
-                /*
-                 * This is a possible return value of canonicalization. However, we might need to
-                 * add additional usages later on for which we need a node. Therefore, we just do
-                 * nothing and leave the node in place.
-                 */
-            } else if (canonical != node) {
-                if (!canonical.isAlive()) {
-                    assert !canonical.isDeleted();
-                    canonical = methodScope.graph.addOrUniqueWithInputs(canonical);
-                    if (canonical instanceof FixedWithNextNode) {
-                        methodScope.graph.addBeforeFixed(node, (FixedWithNextNode) canonical);
-                    }
-                }
-                GraphUtil.unlinkFixedNode((FixedWithNextNode) node);
-                node.replaceAtUsages(canonical);
-                node.safeDelete();
-                assert lookupNode(loopScope, nodeOrderId) == node;
-                registerNode(loopScope, nodeOrderId, canonical, true, false);
-            }
-        }
-    }
-
-    @Override
-    protected Node handleFloatingNodeBeforeAdd(MethodScope s, LoopScope loopScope, Node node) {
-        PEMethodScope methodScope = (PEMethodScope) s;
-
-        if (node instanceof ParameterNode) {
-            if (methodScope.arguments != null) {
-                Node result = methodScope.arguments[((ParameterNode) node).index()];
-                assert result != null;
-                return result;
-
-            } else if (methodScope.parameterPlugin != null) {
-                GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, null);
-                Node result = methodScope.parameterPlugin.interceptParameter(graphBuilderContext, ((ParameterNode) node).index(), ((ParameterNode) node).stamp());
-                if (result != null) {
-                    return result;
-                }
-            }
-
-        } else if (node instanceof Canonicalizable) {
-            Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool());
-            if (canonical == null) {
-                /*
-                 * This is a possible return value of canonicalization. However, we might need to
-                 * add additional usages later on for which we need a node. Therefore, we just do
-                 * nothing and leave the node in place.
-                 */
-            } else if (canonical != node) {
-                if (!canonical.isAlive()) {
-                    assert !canonical.isDeleted();
-                    canonical = methodScope.graph.addOrUniqueWithInputs(canonical);
-                }
-                assert node.hasNoUsages();
-                // methodScope.graph.replaceFloating((FloatingNode) node, canonical);
-                return canonical;
-            }
-        }
-        return node;
-    }
-
-    protected void ensureOuterStateDecoded(PEMethodScope methodScope) {
-        if (methodScope.outerState == null && methodScope.caller != null) {
-            FrameState stateAtReturn = methodScope.invokeData.invoke.stateAfter();
-            if (stateAtReturn == null) {
-                stateAtReturn = (FrameState) decodeFloatingNode(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId);
-            }
-
-            Kind invokeReturnKind = methodScope.invokeData.invoke.asNode().getKind();
-            FrameState outerState = stateAtReturn.duplicateModified(methodScope.graph, methodScope.invokeData.invoke.bci(), stateAtReturn.rethrowException(), true, invokeReturnKind);
-
-            /*
-             * When the encoded graph has methods inlining, we can already have a proper caller
-             * state. If not, we set the caller state here.
-             */
-            if (outerState.outerFrameState() == null && methodScope.caller != null) {
-                ensureOuterStateDecoded(methodScope.caller);
-                outerState.setOuterFrameState(methodScope.caller.outerState);
-            }
-            methodScope.outerState = outerState;
-        }
-    }
-
-    protected void ensureStateAfterDecoded(PEMethodScope methodScope) {
-        if (methodScope.invokeData.invoke.stateAfter() == null) {
-            methodScope.invokeData.invoke.setStateAfter((FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId));
-        }
-    }
-
-    protected void ensureExceptionStateDecoded(PEMethodScope methodScope) {
-        if (methodScope.exceptionState == null && methodScope.caller != null && methodScope.invokeData.invoke instanceof InvokeWithExceptionNode) {
-            ensureStateAfterDecoded(methodScope);
-
-            assert methodScope.exceptionPlaceholderNode == null;
-            methodScope.exceptionPlaceholderNode = methodScope.graph.add(new ExceptionPlaceholderNode());
-            registerNode(methodScope.callerLoopScope, methodScope.invokeData.exceptionOrderId, methodScope.exceptionPlaceholderNode, false, false);
-            FrameState exceptionState = (FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.exceptionStateOrderId);
-
-            if (exceptionState.outerFrameState() == null && methodScope.caller != null) {
-                ensureOuterStateDecoded(methodScope.caller);
-                exceptionState.setOuterFrameState(methodScope.caller.outerState);
-            }
-            methodScope.exceptionState = exceptionState;
-        }
-    }
-
-    @Override
-    protected Node handleFloatingNodeAfterAdd(MethodScope s, LoopScope loopScope, Node node) {
-        PEMethodScope methodScope = (PEMethodScope) s;
-
-        if (methodScope.isInlinedMethod()) {
-            if (node instanceof SimpleInfopointNode) {
-                methodScope.bytecodePosition = InliningUtil.processSimpleInfopoint(methodScope.invokeData.invoke, (SimpleInfopointNode) node, methodScope.bytecodePosition);
-                return node;
-
-            } else if (node instanceof FrameState) {
-                FrameState frameState = (FrameState) node;
-
-                ensureOuterStateDecoded(methodScope);
-                if (frameState.bci < 0) {
-                    ensureExceptionStateDecoded(methodScope);
-                }
-                return InliningUtil.processFrameState(frameState, methodScope.invokeData.invoke, methodScope.method, methodScope.exceptionState, methodScope.outerState, true);
-
-            } else if (node instanceof MonitorIdNode) {
-                ensureOuterStateDecoded(methodScope);
-                InliningUtil.processMonitorId(methodScope.outerState, (MonitorIdNode) node);
-                return node;
-            }
-        }
-
-        return node;
-    }
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Apr 22 15:36:53 2015 +0200
@@ -340,7 +340,7 @@
         plugins.setInlineInvokePlugin(new ParsingInlineInvokePlugin((ReplacementsImpl) providers.getReplacements(), parsingInvocationPlugins, loopExplosionPlugin,
                         !PrintTruffleExpansionHistogram.getValue()));
 
-        CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(providers, newConfig, AllowAssumptions.from(graph.getAssumptions() != null), architecture);
+        CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(providers, newConfig, TruffleCompilerImpl.Optimizations, AllowAssumptions.from(graph.getAssumptions() != null), architecture);
 
         ParameterPlugin parameterPlugin = new InterceptReceiverPlugin(callTarget);
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Apr 22 15:36:53 2015 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.graph.*;
@@ -158,11 +159,11 @@
                 if (node instanceof LoopExitNode) {
                     LoopExitNode loopExit = (LoopExitNode) node;
                     for (ProxyNode proxy : loopExit.proxies()) {
-                        changed |= processNode(proxy, state, effects, lastFixedNode);
+                        changed |= processNode(proxy, state, effects, lastFixedNode) && isSignificantNode(node);
                     }
                     processLoopExit(loopExit, loopEntryStates.get(loopExit.loopBegin()), state, blockEffects.get(block));
                 }
-                changed |= processNode(node, state, effects, lastFixedNode);
+                changed |= processNode(node, state, effects, lastFixedNode) && isSignificantNode(node);
                 if (node instanceof FixedWithNextNode) {
                     lastFixedNode = (FixedWithNextNode) node;
                 }
@@ -175,6 +176,15 @@
         return state;
     }
 
+    private static boolean isSignificantNode(Node node) {
+        return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode || node instanceof BoxNode);
+    }
+
+    /**
+     * Collects the effects of virtualizing the given node.
+     * 
+     * @return {@code true} if the effects include removing the node, {@code false} otherwise.
+     */
     protected abstract boolean processNode(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode);
 
     @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Apr 22 15:36:53 2015 +0200
@@ -34,7 +34,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
 import com.oracle.graal.nodes.virtual.*;
@@ -134,32 +133,30 @@
 
     private boolean processNodeInternal(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
         FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next();
-        boolean significantChange = false;
         VirtualUtil.trace("%s", node);
 
         if (node instanceof VirtualizableAllocation) {
-            significantChange |= processVirtualizable((ValueNode) node, nextFixedNode, state, effects);
-            if (tool.isDeleted()) {
+            if (processVirtualizable((ValueNode) node, nextFixedNode, state, effects)) {
                 VirtualUtil.trace("deleted virtualizable allocation %s", node);
-                return significantChange;
+                return true;
             }
         }
-
         if (hasVirtualInputs.isMarked(node) && node instanceof ValueNode) {
             if (node instanceof Virtualizable) {
-                significantChange |= processVirtualizable((ValueNode) node, nextFixedNode, state, effects);
-                if (tool.isDeleted()) {
+                if (processVirtualizable((ValueNode) node, nextFixedNode, state, effects)) {
                     VirtualUtil.trace("deleted virtualizable node %s", node);
-                    return significantChange;
+                    return true;
                 }
             }
             processNodeInputs((ValueNode) node, nextFixedNode, state, effects);
         }
 
         if (hasScalarReplacedInputs(node) && node instanceof ValueNode) {
-            significantChange |= processNodeWithScalarReplacedInputs((ValueNode) node, nextFixedNode, state, effects);
+            if (processNodeWithScalarReplacedInputs((ValueNode) node, nextFixedNode, state, effects)) {
+                return true;
+            }
         }
-        return significantChange;
+        return false;
     }
 
     private boolean processNodeWithScalarReplacedInputs(ValueNode node, FixedNode insertBefore, BlockT state, GraphEffectList effects) {
@@ -268,10 +265,7 @@
     private boolean processVirtualizable(ValueNode node, FixedNode insertBefore, BlockT state, GraphEffectList effects) {
         tool.reset(state, node, insertBefore, effects);
         ((Virtualizable) node).virtualize(tool);
-        if (tool.isDeleted()) {
-            return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode || node instanceof BoxNode);
-        }
-        return false;
+        return tool.isDeleted();
     }
 
     private void processNodeWithState(NodeWithState nodeWithState, BlockT state, GraphEffectList effects) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Wed Apr 22 15:36:53 2015 +0200
@@ -63,7 +63,7 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (getUsageCount() == 0) {
+        if (tool.allUsagesAvailable() && hasNoUsages()) {
             /* If the cast is unused, it can be eliminated. */
             return input;
         }
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java	Wed Apr 22 15:36:53 2015 +0200
@@ -504,7 +504,15 @@
         if (merged == generated) {
             // new node
             if (start.count() == 2) {
-                insertAt(start, start.createPolymorphic(), "insert polymorphic");
+                SpecializationNode polymorphic = start.createPolymorphic();
+                /*
+                 * For nodes with all parameters evaluated in the execute method we do not need a
+                 * polymorphic node. the generated code returns null in createPolymorphic in this
+                 * case.
+                 */
+                if (polymorphic != null) {
+                    insertAt(start, polymorphic, "insert polymorphic");
+                }
             }
             SpecializationNode current = start;
             while (current != null && current.index < generated.index) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Wed Apr 22 15:36:53 2015 +0200
@@ -420,6 +420,17 @@
     }
 
     private boolean needsPolymorphic() {
+        int signatureSize = node.getSignatureSize();
+        boolean allEvaluated = true;
+        for (ExecutableTypeData type : usedTypes) {
+            if (type.getEvaluatedCount() != signatureSize) {
+                allEvaluated = false;
+            }
+        }
+        if (allEvaluated) {
+            return false;
+        }
+
         if (reachableSpecializations.size() != 1) {
             return true;
         }
@@ -2345,6 +2356,7 @@
             final CodeTreeBuilder polyChainBuilder = builder.create();
             final String profileField = polymorphicTypeProfileFieldName(execution);
             final String valueFieldName = "_value";
+            final String typeFieldName = "_type";
 
             builder.declaration(getType(Class.class), profileField, accessParent(profileField));
 
@@ -2367,6 +2379,8 @@
             polyChainBuilder.startElseIf().string(profileField).string(" == null").end();
             polyChainBuilder.startBlock();
             polyChainBuilder.tree(createTransferToInterpreterAndInvalidate());
+            polyChainBuilder.declaration(context.getType(Class.class), typeFieldName, polyChainBuilder.create().typeLiteral(genericType).build());
+            polyChainBuilder.startTryBlock();
             polyChainBuilder.declaration(genericExecutableType.getReturnType(), valueFieldName, executeGeneric);
 
             hasSpecializedTypes = false;
@@ -2375,14 +2389,17 @@
                 polyChainBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, executableType.getReturnType(), CodeTreeBuilder.singleString(valueFieldName)));
                 polyChainBuilder.end();
                 polyChainBuilder.startBlock();
-                polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(executableType.getReturnType()).end();
+                polyChainBuilder.startStatement().string(typeFieldName).string(" = ").typeLiteral(executableType.getReturnType()).end();
                 polyChainBuilder.end();
             }
-
             polyChainBuilder.startElseBlock();
-            polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end();
+            polyChainBuilder.startStatement().string(typeFieldName).string(" = ").typeLiteral(genericType).end();
             polyChainBuilder.end();
             polyChainBuilder.startReturn().string(valueFieldName).end();
+
+            polyChainBuilder.end().startFinallyBlock();
+            polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").string(typeFieldName).end();
+            polyChainBuilder.end();
             polyChainBuilder.end();
 
             // else -> execute generic
--- a/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/messages/MessageUtil.java	Wed Apr 22 15:36:38 2015 +0200
+++ b/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/messages/MessageUtil.java	Wed Apr 22 15:36:53 2015 +0200
@@ -34,6 +34,6 @@
         } else if (o1 instanceof Receiver && o2 instanceof Receiver) {
             return true;
         }
-        throw new IllegalStateException();
+        return false;
     }
 }
--- a/make/Makefile	Wed Apr 22 15:36:38 2015 +0200
+++ b/make/Makefile	Wed Apr 22 15:36:53 2015 +0200
@@ -632,6 +632,9 @@
 $(EXPORT_JRE_LIB_EXT_DIR)/%.jar: $(SHARED_DIR)/%.jar
 	$(install-file)
 
+$(EXPORT_JRE_LIB_GRAAL_DIR)/%.jar: $(SHARED_DIR)/%.jar
+	$(install-file)
+
 $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/code/%
 	$(install-file)
 
--- a/mx/mx_graal.py	Wed Apr 22 15:36:38 2015 +0200
+++ b/mx/mx_graal.py	Wed Apr 22 15:36:53 2015 +0200
@@ -594,6 +594,35 @@
         shutil.move(tmp, dstLib)
         os.chmod(dstLib, permissions)
 
+def _updateGraalServiceFiles(jdkDir):
+    jreGraalDir = join(jdkDir, 'jre', 'lib', 'graal')
+    graalJars = [join(jreGraalDir, e) for e in os.listdir(jreGraalDir) if e.startswith('graal') and e.endswith('.jar')]
+    jreGraalServicesDir = join(jreGraalDir, 'services')
+    if exists(jreGraalServicesDir):
+        shutil.rmtree(jreGraalServicesDir)
+    os.makedirs(jreGraalServicesDir)
+    for jar in graalJars:
+        if os.path.isfile(jar):
+            with zipfile.ZipFile(jar) as zf:
+                for member in zf.namelist():
+                    if not member.startswith('META-INF/services'):
+                        continue
+                    serviceName = basename(member)
+                    # we don't handle directories
+                    assert serviceName
+                    target = join(jreGraalServicesDir, serviceName)
+                    lines = []
+                    with zf.open(member) as serviceFile:
+                        lines.extend(serviceFile.readlines())
+                    if exists(target):
+                        with open(target) as targetFile:
+                            lines.extend(targetFile.readlines())
+                    with open(target, "w+") as targetFile:
+                        for line in lines:
+                            targetFile.write(line.rstrip() + os.linesep)
+
+
+
 def _installDistInJdks(deployableDist):
     """
     Installs the jar(s) for a given Distribution into all existing Graal JDKs
@@ -613,7 +642,8 @@
 
     if exists(jdks):
         for e in os.listdir(jdks):
-            jreLibDir = join(jdks, e, 'jre', 'lib')
+            jdkDir = join(jdks, e)
+            jreLibDir = join(jdkDir, 'jre', 'lib')
             if exists(jreLibDir):
                 if deployableDist.isExtension:
                     targetDir = join(jreLibDir, 'ext')
@@ -625,23 +655,10 @@
                     os.makedirs(targetDir)
                 _copyToJdk(dist.path, targetDir)
                 if dist.sourcesPath:
-                    _copyToJdk(dist.sourcesPath, join(jdks, e))
-                # deploy service files
+                    _copyToJdk(dist.sourcesPath, jdkDir)
                 if deployableDist.isGraalClassLoader:
-                    # deploy services files
-                    jreGraalServicesDir = join(jreLibDir, 'graal', 'services')
-                    if not exists(jreGraalServicesDir):
-                        os.makedirs(jreGraalServicesDir)
-                    with zipfile.ZipFile(dist.path) as zf:
-                        for member in zf.namelist():
-                            if not member.startswith('META-INF/services'):
-                                continue
-                            serviceName = basename(member)
-                            # we don't handle directories
-                            assert serviceName
-                            target = join(jreGraalServicesDir, serviceName)
-                            with zf.open(member) as serviceFile, open(target, "w+") as targetFile:
-                                shutil.copyfileobj(serviceFile, targetFile)
+                    # deploy service files
+                    _updateGraalServiceFiles(jdkDir)
 
 # run a command in the windows SDK Debug Shell
 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
--- a/mxtool/mx.py	Wed Apr 22 15:36:38 2015 +0200
+++ b/mxtool/mx.py	Wed Apr 22 15:36:53 2015 +0200
@@ -2798,7 +2798,7 @@
                 archive(['@' + dist.name])
             if args.check_distributions and not dist.isProcessorDistribution:
                 with zipfile.ZipFile(dist.path, 'r') as zf:
-                    files.extend([member for member in zf.namelist() if not member.startswith('META-INF/services')])
+                    files.extend([member for member in zf.namelist() if not member.startswith('META-INF')])
         dups = set([x for x in files if files.count(x) > 1])
         if len(dups) > 0:
             abort('Distributions overlap! duplicates: ' + str(dups))
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Apr 22 15:36:38 2015 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Apr 22 15:36:53 2015 +0200
@@ -186,9 +186,7 @@
   __ subptr(rsp, 256); // Save upper half of YMM registers
   if (save_vectors) {
     assert(UseAVX > 0, "256bit vectors are supported only with AVX");
-#ifdef COMPILER2
     assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
-#endif
     // Save upper half of YMM registers
     __ vextractf128h(Address(rsp, ymm_hi0_off * BytesPerInt),  xmm0);
     __ vextractf128h(Address(rsp, ymm_hi1_off * BytesPerInt),  xmm1);
@@ -327,9 +325,7 @@
   if (restore_vectors) {
     // Restore upper half of YMM registes.
     assert(UseAVX > 0, "256bit vectors are supported only with AVX");
-#if defined(COMPILER2)
     assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
-#endif
     __ vinsertf128h(xmm0,  Address(rsp, ymm_hi0_off * BytesPerInt));
     __ vinsertf128h(xmm1,  Address(rsp, ymm_hi1_off * BytesPerInt));
     __ vinsertf128h(xmm2,  Address(rsp, ymm_hi2_off * BytesPerInt));
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Wed Apr 22 15:36:38 2015 +0200
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Wed Apr 22 15:36:53 2015 +0200
@@ -667,6 +667,8 @@
       FLAG_SET_DEFAULT(UseFPUForSpilling, false);
     }
   }
+#endif
+#if defined(COMPILER2) || defined(GRAAL)
   if (MaxVectorSize > 0) {
     if (!is_power_of_2(MaxVectorSize)) {
       warning("MaxVectorSize must be a power of 2");
@@ -684,7 +686,7 @@
       FLAG_SET_DEFAULT(MaxVectorSize, 0);
     }
 #ifdef ASSERT
-    if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
+    if (supports_avx() && PrintMiscellaneous && Verbose) {
       tty->print_cr("State of YMM registers after signal handle:");
       int nreg = 2 LP64_ONLY(+2);
       const char* ymm_name[4] = {"0", "7", "8", "15"};
@@ -698,7 +700,9 @@
     }
 #endif
   }
+#endif
 
+#ifdef COMPILER2
 #ifdef _LP64
   if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
     UseMultiplyToLenIntrinsic = true;
--- a/src/share/vm/graal/graalEnv.cpp	Wed Apr 22 15:36:38 2015 +0200
+++ b/src/share/vm/graal/graalEnv.cpp	Wed Apr 22 15:36:53 2015 +0200
@@ -550,7 +550,7 @@
         // It might be preferable to set this only for methods which
         // use vector instructions but we currently don't track this
         // and it probably wouldn't make much difference.
-        nm->set_has_wide_vectors(UseAVX >= 2);
+        nm->set_has_wide_vectors(MaxVectorSize > 16);
 #endif
 
         // Record successful registration.
--- a/src/share/vm/graal/graalGlobals.hpp	Wed Apr 22 15:36:38 2015 +0200
+++ b/src/share/vm/graal/graalGlobals.hpp	Wed Apr 22 15:36:53 2015 +0200
@@ -67,6 +67,10 @@
   GRAAL_ONLY(product(bool, CodeInstallSafepointChecks, true,                \
           "Perform explicit safepoint checks while installing code"))       \
                                                                             \
+  NOT_COMPILER2(product(intx, MaxVectorSize, 32,                            \
+          "Max vector size in bytes, "                                      \
+          "actual size could be less depending on elements type"))          \
+                                                                            \
   product(intx, TraceGraal, 0,                                              \
           "Trace level for Graal")                                          \
                                                                             \
--- a/src/share/vm/runtime/sharedRuntime.cpp	Wed Apr 22 15:36:38 2015 +0200
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Apr 22 15:36:53 2015 +0200
@@ -113,11 +113,7 @@
 
 #if defined(COMPILER2) || defined(GRAAL)
   // Vectors are generated only by C2 and Graal.
-#ifdef COMPILER2
-  bool support_wide = is_wide_vector(MaxVectorSize) || IS_GRAAL_DEFINED;
-#else
-  bool support_wide = true;
-#endif
+  bool support_wide = is_wide_vector(MaxVectorSize);
   if (support_wide) {
     _polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP);
   }