changeset 16300:8da760bd1575

Merge.
author Doug Simon <doug.simon@oracle.com>
date Mon, 30 Jun 2014 17:28:53 +0200
parents 732a9e80e8dc (current diff) 81e4af185dd6 (diff)
children b741f44cb277 281c30cf1952
files
diffstat 39 files changed, 1216 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/DefaultCanonicalizerTool.java	Mon Jun 30 17:28:53 2014 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011, 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.graph.spi;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+public class DefaultCanonicalizerTool implements CanonicalizerTool {
+
+    private final Assumptions assumptions;
+    private final MetaAccessProvider metaAccess;
+    private final ConstantReflectionProvider constantReflection;
+    private final boolean canonicalizeReads;
+
+    public DefaultCanonicalizerTool(Assumptions assumptions, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean canonicalizeReads) {
+        this.assumptions = assumptions;
+        this.metaAccess = metaAccess;
+        this.constantReflection = constantReflection;
+        this.canonicalizeReads = canonicalizeReads;
+    }
+
+    public Assumptions assumptions() {
+        return assumptions;
+    }
+
+    public MetaAccessProvider getMetaAccess() {
+        return metaAccess;
+    }
+
+    public ConstantReflectionProvider getConstantReflection() {
+        return constantReflection;
+    }
+
+    public boolean canonicalizeReads() {
+        return canonicalizeReads;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Mon Jun 30 17:28:53 2014 +0200
@@ -140,8 +140,9 @@
         }
         lengths.add("PrintFlags".length());
 
-        out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS) {");
-        out.println("  if (value[0] == '+' || value[0] == '-') {");
+        out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS) {");
+        out.println("  bool check_only = hotSpotOptionsClass.is_null();");
+        out.println("  if (value != NULL && (value[0] == '+' || value[0] == '-')) {");
         out.println("    // boolean options");
         genMatchers(out, lengths, options, true);
         out.println("  } else {");
@@ -164,7 +165,11 @@
                 out.println("    case " + len + ":");
                 out.printf("      if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len);
                 out.println("        if (value[0] == '+') {");
-                out.println("          set_option_helper(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);");
+                out.println("          if (check_only) {");
+                out.println("            TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", THREAD);");
+                out.println("            hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));");
+                out.println("          }");
+                out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);");
                 out.println("        }");
                 out.println("        return true;");
                 out.println("      }");
@@ -178,17 +183,28 @@
                     }
                     out.printf("      if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len);
                     Class<?> declaringClass = desc.getDeclaringClass();
-                    out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
-                                    toInternalName(getFieldType(desc)));
                     if (isBoolean) {
-                        out.println("        set_option_helper(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);");
+                        out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
+                                        toInternalName(getFieldType(desc)));
+                        out.println("        if (!check_only) {");
+                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, value[0], Handle(), 0L);");
+                        out.println("        }");
                     } else if (desc.getType() == String.class) {
-                        out.println("        Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));");
-                        out.println("        set_option_helper(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);");
+                        out.println("        check_required_value(name, name_len, value, CHECK_(true));");
+                        out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
+                                        toInternalName(getFieldType(desc)));
+                        out.println("        if (!check_only) {");
+                        out.println("          Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));");
+                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);");
+                        out.println("        }");
                     } else {
                         char spec = getPrimitiveSpecChar(desc);
-                        out.println("        jlong primitiveValue = parse_primitive_option_value('" + spec + "', name_handle, value, CHECK_(true));");
-                        out.println("        set_option_helper(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);");
+                        out.println("        jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));");
+                        out.println("        if (!check_only) {");
+                        out.printf("          Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
+                                        toInternalName(getFieldType(desc)));
+                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);");
+                        out.println("        }");
                     }
                     out.println("        return true;");
                     out.println("      }");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Jun 30 17:28:53 2014 +0200
@@ -202,13 +202,22 @@
     }
 
     protected static void printNoMatchMessage(String optionName) {
-        System.err.println("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)");
-        List<OptionDescriptor> matches = fuzzyMatch(optionName);
-        if (!matches.isEmpty()) {
-            System.err.println("Did you mean one of the following?");
-            for (OptionDescriptor match : matches) {
-                boolean isBoolean = match.getType() == boolean.class;
-                System.err.println(String.format("    %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=<value>"));
+        OptionDescriptor desc = options.get(optionName);
+        if (desc != null) {
+            if (desc.getType() == Boolean.class) {
+                System.err.println("Boolean option " + optionName + " must be prefixed with '+' or '-'");
+            } else {
+                System.err.println(desc.getType().getSimpleName() + " option " + optionName + " must not be prefixed with '+' or '-'");
+            }
+        } else {
+            System.err.println("Could not find option " + optionName + " (use -G:+PrintFlags to see Graal options)");
+            List<OptionDescriptor> matches = fuzzyMatch(optionName);
+            if (!matches.isEmpty()) {
+                System.err.println("Did you mean one of the following?");
+                for (OptionDescriptor match : matches) {
+                    boolean isBoolean = match.getType() == Boolean.class;
+                    System.err.println(String.format("    %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=<value>"));
+                }
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -34,7 +34,7 @@
  *
  * @see ClassSubstitutions#cast(Class, Object)
  */
-public class ClassCastNode extends MacroNode implements Canonicalizable.Binary<ValueNode> {
+public class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary<ValueNode> {
 
     public ClassCastNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java	Mon Jun 30 17:28:53 2014 +0200
@@ -35,7 +35,7 @@
  * @see ClassSubstitutions#getClassLoader0(Class)
  */
 @SuppressWarnings("javadoc")
-public class ClassGetClassLoader0Node extends MacroNode implements Canonicalizable {
+public class ClassGetClassLoader0Node extends MacroStateSplitNode implements Canonicalizable {
 
     public ClassGetClassLoader0Node(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -38,7 +38,7 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class ArrayCopyNode extends MacroNode implements Virtualizable, Lowerable {
+public class ArrayCopyNode extends MacroStateSplitNode implements Virtualizable, Lowerable {
 
     public ArrayCopyNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class CallSiteTargetNode extends MacroNode implements Canonicalizable, Lowerable {
+public class CallSiteTargetNode extends MacroStateSplitNode implements Canonicalizable, Lowerable {
 
     public CallSiteTargetNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -44,7 +44,7 @@
 /**
  * Node for invocation methods defined on the class {@link MethodHandle}.
  */
-public class MethodHandleNode extends MacroNode implements Simplifiable {
+public class MethodHandleNode extends MacroStateSplitNode implements Simplifiable {
 
     /** The method that this node is representing. */
     private final IntrinsicMethod intrinsicMethod;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -39,7 +39,7 @@
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class ObjectCloneNode extends MacroNode implements VirtualizableAllocation, ArrayLengthProvider {
+public class ObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider {
 
     public ObjectCloneNode(Invoke invoke) {
         super(invoke);
@@ -107,7 +107,7 @@
     /*
      * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an
      * exact type) and if it is a cloneable type.
-     * 
+     *
      * If yes, then the exact type is returned, otherwise it returns null.
      */
     private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class ReflectionGetCallerClassNode extends MacroNode implements Canonicalizable, Lowerable {
+public class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable {
 
     public ReflectionGetCallerClassNode(Invoke invoke) {
         super(invoke);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java	Mon Jun 30 17:28:53 2014 +0200
@@ -0,0 +1,171 @@
+/*
+ * 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.lir.test;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
+import com.oracle.graal.lir.asm.*;
+
+public class ValuePositionTest1 {
+
+    private static class NestedCompositeValue extends CompositeValue {
+
+        private static final long serialVersionUID = -8804214200173503527L;
+        @Component({REG, OperandFlag.ILLEGAL}) protected Value value;
+
+        public NestedCompositeValue(Value value) {
+            super(LIRKind.Illegal);
+            this.value = value;
+        }
+
+    }
+
+    private static class DummyValue extends Value {
+
+        private static final long serialVersionUID = -645435039553382737L;
+        private final int id;
+        private static int counter = 1;
+
+        protected DummyValue() {
+            super(LIRKind.Illegal);
+            this.id = counter++;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + id;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!super.equals(obj)) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            DummyValue other = (DummyValue) obj;
+            if (id != other.id) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private static class TestOp extends LIRInstruction {
+
+        @Use({COMPOSITE}) protected NestedCompositeValue compValue;
+
+        public TestOp(NestedCompositeValue compValue) {
+            this.compValue = compValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb) {
+            fail("should not reach!");
+        }
+
+    }
+
+    private static LIRInstruction createNestedOp(Value value, int nestingLevel) {
+        NestedCompositeValue compValue = new NestedCompositeValue(value);
+        for (int i = 0; i < nestingLevel; i++) {
+            compValue = new NestedCompositeValue(compValue);
+        }
+        TestOp op = new TestOp(compValue);
+        return op;
+    }
+
+    @Test
+    public void nestedTest0() {
+        DummyValue dummyValue = new DummyValue();
+        LIRInstruction op = createNestedOp(dummyValue, 0);
+
+        List<ValuePosition> positions = new ArrayList<>();
+
+        op.forEachInput(new ValuePositionProcedure() {
+
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                positions.add(position);
+            }
+        });
+
+        assertEquals(1, positions.size());
+        assertEquals(dummyValue, positions.get(0).get(op));
+    }
+
+    @Test
+    public void nestedTest1() {
+        DummyValue dummyValue = new DummyValue();
+        LIRInstruction op = createNestedOp(dummyValue, 1);
+
+        List<ValuePosition> positions = new ArrayList<>();
+
+        op.forEachInput(new ValuePositionProcedure() {
+
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                positions.add(position);
+            }
+        });
+
+        assertEquals(1, positions.size());
+        assertEquals(dummyValue, positions.get(0).get(op));
+    }
+
+    @Test
+    public void nestedTest2() {
+        DummyValue dummyValue = new DummyValue();
+        LIRInstruction op = createNestedOp(dummyValue, 2);
+
+        List<ValuePosition> positions = new ArrayList<>();
+
+        op.forEachInput(new ValuePositionProcedure() {
+
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                positions.add(position);
+            }
+        });
+
+        assertEquals(1, positions.size());
+        assertEquals(dummyValue, positions.get(0).get(op));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java	Mon Jun 30 17:28:53 2014 +0200
@@ -0,0 +1,149 @@
+/*
+ * 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.lir.test;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
+import com.oracle.graal.lir.asm.*;
+
+public class ValuePositionTest2 {
+
+    private static class NestedCompositeValue extends CompositeValue {
+
+        private static final long serialVersionUID = -2243948303328857965L;
+        @Component({REG, OperandFlag.ILLEGAL}) protected Value value1;
+        @Component({REG, OperandFlag.ILLEGAL}) protected Value value2;
+
+        public NestedCompositeValue(Value value1, Value value2) {
+            super(LIRKind.Illegal);
+            this.value1 = value1;
+            this.value2 = value2;
+        }
+
+    }
+
+    private static class DummyValue extends Value {
+
+        private static final long serialVersionUID = 3620305384660607012L;
+        private final int id;
+        private static int counter = 0;
+
+        protected DummyValue() {
+            super(LIRKind.Illegal);
+            this.id = counter++;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + id;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!super.equals(obj)) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            DummyValue other = (DummyValue) obj;
+            if (id != other.id) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private static class TestOp extends LIRInstruction {
+
+        @Use({COMPOSITE}) protected NestedCompositeValue compValue;
+
+        public TestOp(NestedCompositeValue compValue) {
+            this.compValue = compValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb) {
+            fail("should not reach!");
+        }
+
+    }
+
+    @Test
+    public void testSetGet() {
+        DummyValue dummyValue0 = new DummyValue();
+        DummyValue dummyValue1 = new DummyValue();
+        DummyValue dummyValue2 = new DummyValue();
+        DummyValue dummyValue3 = new DummyValue();
+
+        NestedCompositeValue compValue0 = new NestedCompositeValue(dummyValue0, dummyValue1);
+        NestedCompositeValue compValue1 = new NestedCompositeValue(compValue0, dummyValue2);
+        NestedCompositeValue compValue2 = new NestedCompositeValue(dummyValue3, compValue1);
+
+        LIRInstruction op = new TestOp(compValue2);
+        List<ValuePosition> positions = new ArrayList<>();
+
+        op.forEachInput(new ValuePositionProcedure() {
+
+            @Override
+            public void doValue(LIRInstruction instruction, ValuePosition position) {
+                positions.add(position);
+            }
+        });
+
+        assertEquals(4, positions.size());
+
+        // replace values
+        List<Value> replValues = new ArrayList<>();
+        for (ValuePosition pos : positions) {
+            Value v = new DummyValue();
+            replValues.add(v);
+            pos.set(op, v);
+
+        }
+
+        // check replaced values
+        Iterator<Value> it = replValues.iterator();
+        for (ValuePosition pos : positions) {
+            Value v = pos.get(op);
+            assertEquals(it.next(), v);
+        }
+        assertFalse(it.hasNext());
+    }
+
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Mon Jun 30 17:28:53 2014 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 
 /**
  * Base class to represent values that need to be stored in more than one register.
@@ -58,6 +59,10 @@
         valueClass.forEachComponent(inst, this, mode, proc);
     }
 
+    public final void forEachComponent(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) {
+        valueClass.forEachComponent(inst, this, mode, proc, outerPosition);
+    }
+
     @Override
     public String toString() {
         return valueClass.toString(this);
@@ -76,4 +81,9 @@
         }
         return false;
     }
+
+    CompositeValueClass getValueClass() {
+        return valueClass;
+    }
+
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Jun 30 17:28:53 2014 +0200
@@ -25,11 +25,13 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.CompositeValue.Component;
 import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 
 /**
  * Lazily associated metadata for every {@link CompositeValue} type. The metadata includes:
@@ -143,6 +145,10 @@
         forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
     }
 
+    public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) {
+        forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc, outerPosition);
+    }
+
     public String toString(CompositeValue obj) {
         StringBuilder result = new StringBuilder();
 
@@ -154,4 +160,16 @@
 
         return result.toString();
     }
+
+    Value getValue(CompositeValue obj, ValuePosition pos) {
+        return getValueForPosition(obj, componentOffsets, directComponentCount, pos);
+    }
+
+    void setValue(CompositeValue obj, ValuePosition pos, Value value) {
+        setValueForPosition(obj, componentOffsets, directComponentCount, pos, value);
+    }
+
+    EnumSet<OperandFlag> getFlags(ValuePosition pos) {
+        return componentFlags[pos.getIndex()];
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Jun 30 17:28:53 2014 +0200
@@ -42,6 +42,22 @@
     public static final Value[] NO_OPERANDS = {};
 
     /**
+     * Iterator for iterating over a list of {@linkplain ValuePosition value positions}.
+     */
+    public abstract static class ValuePositionProcedure {
+
+        /**
+         * Iterator method to be overwritten. This version of the iterator does not take additional
+         * parameters to keep the signature short.
+         *
+         * @param instruction The current instruction.
+         * @param position The position of the value that is iterated.
+         */
+
+        public abstract void doValue(LIRInstruction instruction, ValuePosition position);
+    }
+
+    /**
      * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue
      * methods. Clients of the class must only call the doValue method that takes additional
      * parameters.
@@ -297,6 +313,22 @@
         return false;
     }
 
+    public final void forEachInput(ValuePositionProcedure proc) {
+        instructionClass.forEachUse(this, proc);
+    }
+
+    public final void forEachAlive(ValuePositionProcedure proc) {
+        instructionClass.forEachAlive(this, proc);
+    }
+
+    public final void forEachTemp(ValuePositionProcedure proc) {
+        instructionClass.forEachTemp(this, proc);
+    }
+
+    public final void forEachOutput(ValuePositionProcedure proc) {
+        instructionClass.forEachDef(this, proc);
+    }
+
     public final void forEachInput(InstructionValueProcedure proc) {
         instructionClass.forEachUse(this, proc);
     }
@@ -354,4 +386,8 @@
     public String toString() {
         return instructionClass.toString(this);
     }
+
+    public LIRInstructionClass getLIRInstructionClass() {
+        return instructionClass;
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Jun 30 17:28:53 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
+import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 
 public class LIRInstructionClass extends LIRIntrospection {
 
@@ -241,6 +242,73 @@
         return str.toString();
     }
 
+    Value getValue(LIRInstruction obj, ValuePosition pos) {
+        long[] offsets;
+        int directCount;
+        switch (pos.getMode()) {
+            case USE:
+                directCount = directUseCount;
+                offsets = useOffsets;
+                break;
+            case ALIVE:
+                directCount = directAliveCount;
+                offsets = aliveOffsets;
+                break;
+            case TEMP:
+                directCount = directTempCount;
+                offsets = tempOffsets;
+                break;
+            case DEF:
+                directCount = directDefCount;
+                offsets = defOffsets;
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("unkown OperandMode: " + pos.getMode());
+        }
+        return getValueForPosition(obj, offsets, directCount, pos);
+    }
+
+    void setValue(LIRInstruction obj, ValuePosition pos, Value value) {
+        long[] offsets;
+        int directCount;
+        switch (pos.getMode()) {
+            case USE:
+                directCount = directUseCount;
+                offsets = useOffsets;
+                break;
+            case ALIVE:
+                directCount = directAliveCount;
+                offsets = aliveOffsets;
+                break;
+            case TEMP:
+                directCount = directTempCount;
+                offsets = tempOffsets;
+                break;
+            case DEF:
+                directCount = directDefCount;
+                offsets = defOffsets;
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("unkown OperandMode: " + pos.getMode());
+        }
+        setValueForPosition(obj, offsets, directCount, pos, value);
+    }
+
+    EnumSet<OperandFlag> getFlags(ValuePosition pos) {
+        switch (pos.getMode()) {
+            case USE:
+                return useFlags[pos.getIndex()];
+            case ALIVE:
+                return aliveFlags[pos.getIndex()];
+            case TEMP:
+                return tempFlags[pos.getIndex()];
+            case DEF:
+                return defFlags[pos.getIndex()];
+            default:
+                throw GraalInternalError.shouldNotReachHere("unkown OperandMode: " + pos.getMode());
+        }
+    }
+
     public final String getOpcode(LIRInstruction obj) {
         if (opcodeConstant != null) {
             return opcodeConstant;
@@ -262,6 +330,22 @@
         return false;
     }
 
+    public final void forEachUse(LIRInstruction obj, ValuePositionProcedure proc) {
+        forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc, ValuePosition.ROOT_VALUE_POSITION);
+    }
+
+    public final void forEachAlive(LIRInstruction obj, ValuePositionProcedure proc) {
+        forEach(obj, obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc, ValuePosition.ROOT_VALUE_POSITION);
+    }
+
+    public final void forEachTemp(LIRInstruction obj, ValuePositionProcedure proc) {
+        forEach(obj, obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc, ValuePosition.ROOT_VALUE_POSITION);
+    }
+
+    public final void forEachDef(LIRInstruction obj, ValuePositionProcedure proc) {
+        forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc, ValuePosition.ROOT_VALUE_POSITION);
+    }
+
     public final void forEachUse(LIRInstruction obj, InstructionValueProcedure proc) {
         forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Jun 30 17:28:53 2014 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValuePositionProcedure;
 
 abstract class LIRIntrospection extends FieldIntrospection {
 
@@ -146,6 +147,49 @@
         }
     }
 
+    protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValuePositionProcedure proc,
+                    ValuePosition outerPosition) {
+        for (int i = 0; i < offsets.length; i++) {
+            assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
+
+            if (i < directCount) {
+                Value value = getValue(obj, offsets[i]);
+                doForValue(inst, mode, proc, outerPosition, i, ValuePosition.NO_SUBINDEX, value);
+            } else {
+                Value[] values = getValueArray(obj, offsets[i]);
+                for (int j = 0; j < values.length; j++) {
+                    Value value = values[j];
+                    doForValue(inst, mode, proc, outerPosition, i, j, value);
+                }
+            }
+        }
+    }
+
+    private static void doForValue(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition, int index, int subIndex, Value value) {
+        ValuePosition position = new ValuePosition(mode, index, subIndex, outerPosition);
+        if (value instanceof CompositeValue) {
+            CompositeValue composite = (CompositeValue) value;
+            composite.forEachComponent(inst, mode, proc, position);
+        } else {
+            proc.doValue(inst, position);
+        }
+    }
+
+    protected static Value getValueForPosition(Object obj, long[] offsets, int directCount, ValuePosition pos) {
+        if (pos.getIndex() < directCount) {
+            return getValue(obj, offsets[pos.getIndex()]);
+        }
+        return getValueArray(obj, offsets[pos.getIndex()])[pos.getSubIndex()];
+    }
+
+    protected static void setValueForPosition(Object obj, long[] offsets, int directCount, ValuePosition pos, Value value) {
+        if (pos.getIndex() < directCount) {
+            setValue(obj, offsets[pos.getIndex()], value);
+        } else {
+            getValueArray(obj, offsets[pos.getIndex()])[pos.getSubIndex()] = value;
+        }
+    }
+
     protected static Value getValue(Object obj, long offset) {
         return (Value) unsafe.getObject(obj, offset);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java	Mon Jun 30 17:28:53 2014 +0200
@@ -0,0 +1,145 @@
+/*
+ * 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.lir;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.LIRInstruction.*;
+
+/**
+ * Describes an operand slot for a {@link LIRInstructionClass}.
+ */
+public final class ValuePosition {
+
+    private final OperandMode mode;
+    private final int index;
+    private final int subIndex;
+    private final ValuePosition outerPosition;
+
+    public static final int NO_SUBINDEX = -1;
+    public static final ValuePosition ROOT_VALUE_POSITION = null;
+
+    public ValuePosition(OperandMode mode, int index, int subIndex, ValuePosition outerPosition) {
+        this.mode = mode;
+        this.index = index;
+        this.subIndex = subIndex;
+        this.outerPosition = outerPosition;
+    }
+
+    public boolean isCompositePosition() {
+        return outerPosition != ROOT_VALUE_POSITION;
+    }
+
+    public Value get(LIRInstruction inst) {
+        if (isCompositePosition()) {
+            CompositeValue compValue = (CompositeValue) outerPosition.get(inst);
+            return compValue.getValueClass().getValue(compValue, this);
+        }
+        return inst.getLIRInstructionClass().getValue(inst, this);
+    }
+
+    public EnumSet<OperandFlag> getFlags(LIRInstruction inst) {
+        if (isCompositePosition()) {
+            CompositeValue compValue = (CompositeValue) outerPosition.get(inst);
+            return compValue.getValueClass().getFlags(this);
+        }
+        return inst.getLIRInstructionClass().getFlags(this);
+    }
+
+    public void set(LIRInstruction inst, Value value) {
+        if (isCompositePosition()) {
+            CompositeValue compValue = (CompositeValue) outerPosition.get(inst);
+            compValue.getValueClass().setValue(compValue, this, value);
+        } else {
+            inst.getLIRInstructionClass().setValue(inst, this, value);
+        }
+    }
+
+    public int getSubIndex() {
+        return subIndex;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public OperandMode getMode() {
+        return mode;
+    }
+
+    public ValuePosition getSuperPosition() {
+        return outerPosition;
+    }
+
+    @Override
+    public String toString() {
+        if (outerPosition == ROOT_VALUE_POSITION) {
+            return mode.toString() + "(" + index + (subIndex < 0 ? "" : "/" + subIndex) + ")";
+        }
+        return outerPosition.toString() + "[" + mode.toString() + "(" + index + (subIndex < 0 ? "" : "/" + subIndex) + ")]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + index;
+        result = prime * result + ((mode == null) ? 0 : mode.hashCode());
+        result = prime * result + subIndex;
+        result = prime * result + ((outerPosition == null) ? 0 : outerPosition.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        ValuePosition other = (ValuePosition) obj;
+        if (index != other.index) {
+            return false;
+        }
+        if (mode != other.mode) {
+            return false;
+        }
+        if (subIndex != other.subIndex) {
+            return false;
+        }
+        if (outerPosition == null) {
+            if (other.outerPosition != null) {
+                return false;
+            }
+        } else if (!outerPosition.equals(other.outerPosition)) {
+            return false;
+        }
+        return true;
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -163,6 +163,9 @@
             int numEnds = this.forwardEndCount();
             for (int i = 0; i < numEnds - 1; i++) {
                 AbstractEndNode end = forwardEndAt(numEnds - 1 - i);
+                if (tool != null) {
+                    tool.addToWorkList(end);
+                }
                 AbstractEndNode newEnd;
                 if (merge instanceof LoopBeginNode) {
                     newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge));
@@ -207,6 +210,9 @@
             List<AbstractEndNode> endNodes = forwardEnds().snapshot();
             for (AbstractEndNode end : endNodes) {
                 ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
+                if (tool != null) {
+                    tool.addToWorkList(end.predecessor());
+                }
                 end.replaceAtPredecessor(newReturn);
             }
             GraphUtil.killCFG(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -34,7 +34,7 @@
 public class IntegerDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
     public IntegerDivNode(ValueNode x, ValueNode y) {
-        super(x.stamp().unrestricted(), x, y);
+        super(StampTool.div(x.stamp(), y.stamp()), x, y);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -34,7 +34,7 @@
 public class IntegerRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
     public IntegerRemNode(ValueNode x, ValueNode y) {
-        super(x.stamp().unrestricted(), x, y);
+        super(StampTool.rem(x.stamp(), y.stamp()), x, y);
     }
 
     @Override
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java	Mon Jun 30 17:28:53 2014 +0200
@@ -42,11 +42,13 @@
         this.option = option;
         this.declaringClass = declaringClass;
         this.fieldName = fieldName;
+        assert !type.isPrimitive() : "must used boxed type instead of " + type;
         option.setDescriptor(this);
     }
 
     /**
-     * Gets the type of values stored in the option.
+     * Gets the type of values stored in the option. This will be the boxed type for a primitive
+     * option.
      */
     public Class<?> getType() {
         return type;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Jun 30 17:28:53 2014 +0200
@@ -63,6 +63,10 @@
         this.customCanonicalizer = customCanonicalizer;
     }
 
+    public boolean getCanonicalizeReads() {
+        return canonicalizeReads;
+    }
+
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
         new Instance(context, canonicalizeReads, customCanonicalizer).run(graph);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Mon Jun 30 17:28:53 2014 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.AbstractNewObjectNode;
 import com.oracle.graal.nodes.java.MethodCallTargetNode;
+import com.oracle.graal.nodes.virtual.AllocatedObjectNode;
 import com.oracle.graal.nodes.virtual.VirtualObjectNode;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
@@ -117,7 +118,7 @@
     }
 
     public static boolean isFreshInstantiation(ValueNode arg) {
-        return (arg instanceof AbstractNewObjectNode) || (arg instanceof VirtualObjectNode);
+        return (arg instanceof AbstractNewObjectNode) || (arg instanceof AllocatedObjectNode) || (arg instanceof VirtualObjectNode);
     }
 
     private String checkTargetConditionsHelper(ResolvedJavaMethod method) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,13 +24,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
@@ -39,7 +39,22 @@
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.*;
 
-public class MacroNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+/**
+ * Macro nodes can be used to temporarily replace an invoke (usually by using the
+ * {@link MacroSubstitution} annotation). They can, for example, be used to implement constant
+ * folding for known JDK functions like {@link Class#isInterface()}.<br/>
+ * <br/>
+ * During lowering, multiple sources are queried in order to look for a replacement:
+ * <ul>
+ * <li>If {@link #getLoweredSnippetGraph(LoweringTool)} returns a non-null result, this graph is
+ * used as a replacement.</li>
+ * <li>If a {@link MethodSubstitution} for the target method is found, this substitution is used as
+ * a replacement.</li>
+ * <li>Otherwise, the macro node is replaced with an {@link InvokeNode}. Note that this is only
+ * possible if the macro node is a {@link MacroStateSplitNode}.</li>
+ * </ul>
+ */
+public class MacroNode extends FixedWithNextNode implements Lowerable {
 
     @Input protected final NodeInputList<ValueNode> arguments;
 
@@ -49,7 +64,7 @@
     private final InvokeKind invokeKind;
 
     protected MacroNode(Invoke invoke) {
-        super(invoke.asNode().stamp(), invoke.stateAfter());
+        super(StampFactory.forKind(((MethodCallTargetNode) invoke.callTarget()).targetMethod().getSignature().getReturnKind()));
         MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget();
         this.arguments = new NodeInputList<>(this, methodCallTarget.arguments());
         this.bci = invoke.bci();
@@ -70,6 +85,10 @@
         return returnType;
     }
 
+    protected FrameState stateAfter() {
+        return null;
+    }
+
     /**
      * Gets a snippet to be used for lowering this macro node. The returned graph (if non-null) must
      * have been {@linkplain #lowerReplacement(StructuredGraph, LoweringTool) lowered}.
@@ -145,6 +164,7 @@
             InliningUtil.inline(invoke, replacementGraph, false, null);
             Debug.dump(graph(), "After inlining replacement %s", replacementGraph);
         } else {
+            assert stateAfter() != null : "cannot lower to invoke without state: " + this;
             invoke.lower(tool);
         }
     }
@@ -166,23 +186,4 @@
         }
         return invoke;
     }
-
-    protected void replaceSnippetInvokes(StructuredGraph snippetGraph) {
-        for (MethodCallTargetNode call : snippetGraph.getNodes(MethodCallTargetNode.class)) {
-            Invoke invoke = call.invoke();
-            if (!call.targetMethod().equals(getTargetMethod())) {
-                throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName());
-            }
-            assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI;
-            // Here we need to fix the bci of the invoke
-            InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci()));
-            newInvoke.setStateAfter(invoke.stateAfter());
-            snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke);
-        }
-    }
-
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        return LocationIdentity.ANY_LOCATION;
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+
+/**
+ * This is an extension of {@link MacroNode} that is a {@link StateSplit} and a
+ * {@link MemoryCheckpoint}.
+ */
+public class MacroStateSplitNode extends MacroNode implements StateSplit, MemoryCheckpoint.Single {
+
+    @Input(InputType.State) private FrameState stateAfter;
+
+    protected MacroStateSplitNode(Invoke invoke) {
+        super(invoke);
+        this.stateAfter = invoke.stateAfter();
+    }
+
+    @Override
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    public void setStateAfter(FrameState x) {
+        assert x == null || x.isAlive() : "frame state must be in a graph";
+        updateUsages(stateAfter, x);
+        stateAfter = x;
+    }
+
+    public boolean hasSideEffect() {
+        return true;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return LocationIdentity.ANY_LOCATION;
+    }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
+
+    protected void replaceSnippetInvokes(StructuredGraph snippetGraph) {
+        for (MethodCallTargetNode call : snippetGraph.getNodes(MethodCallTargetNode.class)) {
+            Invoke invoke = call.invoke();
+            if (!call.targetMethod().equals(getTargetMethod())) {
+                throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName());
+            }
+            assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI;
+            // Here we need to fix the bci of the invoke
+            InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci()));
+            newInvoke.setStateAfter(invoke.stateAfter());
+            snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke);
+        }
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -31,7 +31,7 @@
  * This node class can be used to create {@link MacroNode}s for simple pure functions like
  * {@link System#identityHashCode(Object)}.
  */
-public abstract class PureFunctionMacroNode extends MacroNode implements Canonicalizable {
+public abstract class PureFunctionMacroNode extends MacroStateSplitNode implements Canonicalizable {
 
     public PureFunctionMacroNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java	Mon Jun 30 17:28:53 2014 +0200
@@ -64,7 +64,12 @@
     private final HashMap<List<Object>, StructuredGraph> cache = new HashMap<>();
     private final HashMap<List<Object>, Long> lastUsed = new HashMap<>();
     private final StructuredGraph markerGraph = new StructuredGraph();
+
     private final ResolvedJavaType stringBuilderClass;
+    private final ResolvedJavaType runtimeExceptionClass;
+    private final ResolvedJavaType assertionErrorClass;
+    private final ResolvedJavaType controlFlowExceptionClass;
+
     private final ResolvedJavaMethod callBoundaryMethod;
     private long counter;
 
@@ -73,7 +78,12 @@
         this.config = config;
         this.configForRootGraph = configForRootGraph;
         this.optimisticOptimizations = optimisticOptimizations;
+
         this.stringBuilderClass = providers.getMetaAccess().lookupJavaType(StringBuilder.class);
+        this.runtimeExceptionClass = providers.getMetaAccess().lookupJavaType(RuntimeException.class);
+        this.assertionErrorClass = providers.getMetaAccess().lookupJavaType(AssertionError.class);
+        this.controlFlowExceptionClass = providers.getMetaAccess().lookupJavaType(ControlFlowException.class);
+
         try {
             callBoundaryMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("callRoot", Object[].class));
         } catch (NoSuchMethodException ex) {
@@ -249,10 +259,12 @@
 
     private boolean tryCutOffRuntimeExceptions(MethodCallTargetNode methodCallTargetNode) {
         if (methodCallTargetNode.targetMethod().isConstructor()) {
-            ResolvedJavaType runtimeException = providers.getMetaAccess().lookupJavaType(RuntimeException.class);
-            ResolvedJavaType controlFlowException = providers.getMetaAccess().lookupJavaType(ControlFlowException.class);
+            ResolvedJavaType declaringClass = methodCallTargetNode.targetMethod().getDeclaringClass();
             ResolvedJavaType exceptionType = Objects.requireNonNull(StampTool.typeOrNull(methodCallTargetNode.receiver().stamp()));
-            if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass()) && !controlFlowException.isAssignableFrom(exceptionType)) {
+
+            boolean removeAllocation = runtimeExceptionClass.isAssignableFrom(declaringClass) || assertionErrorClass.isAssignableFrom(declaringClass);
+            boolean isCFGException = controlFlowExceptionClass.isAssignableFrom(exceptionType);
+            if (removeAllocation && !isCFGException) {
                 DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode));
                 FixedNode invokeNode = methodCallTargetNode.invoke().asNode();
                 invokeNode.replaceAtPredecessor(deoptNode);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,11 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.truffle.*;
 
@@ -50,6 +53,11 @@
     }
 
     @Override
+    public void lower(LoweringTool tool) {
+        throw new GraalInternalError(GraphUtil.approxSourceException(this, new RuntimeException("assumption could not be evaluated to a constant")));
+    }
+
+    @Override
     public void simplify(SimplifierTool tool) {
         ValueNode assumption = getAssumption();
         if (tool.assumptions() != null && assumption.isConstant()) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
 public class BailoutNode extends MacroNode implements Canonicalizable {
@@ -35,13 +36,20 @@
         assert arguments.size() == 1;
     }
 
+    public ValueNode getMessage() {
+        return arguments.get(0);
+    }
+
+    @Override
+    public void lower(LoweringTool tool) {
+        throw new BailoutException("bailout (message is not compile-time constant, so no additional information is available)");
+    }
+
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        ValueNode arg = arguments.get(0);
-        String message = "";
-        if (arg.isConstant()) {
-            message = arg.asConstant().toValueString();
+        if (getMessage().isConstant()) {
+            throw new BailoutException(getMessage().asConstant().toValueString());
         }
-        throw new BailoutException(message);
+        return this;
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class NeverInlineMacroNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType {
+public class NeverInlineMacroNode extends MacroStateSplitNode implements com.oracle.graal.graph.IterableNodeType {
 
     public NeverInlineMacroNode(Invoke invoke) {
         super(invoke);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.truffle.nodes.asserts;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.nodes.*;
 
-public class NeverPartOfCompilationNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType {
+public class NeverPartOfCompilationNode extends MacroNode implements IterableNodeType {
 
     private final String message;
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java	Mon Jun 30 17:28:53 2014 +0200
@@ -34,7 +34,9 @@
 /**
  * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class, boolean)}.
  */
-public class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable {
+public class CustomizedUnsafeStoreMacroNode extends NeverPartOfCompilationNode implements Canonicalizable, StateSplit {
+
+    @Input(InputType.State) private FrameState stateAfter;
 
     private static final int ARGUMENT_COUNT = 4;
     private static final int OBJECT_ARGUMENT_INDEX = 0;
@@ -45,6 +47,7 @@
     public CustomizedUnsafeStoreMacroNode(Invoke invoke) {
         super(invoke, "The location argument could not be resolved to a constant.");
         assert arguments.size() == ARGUMENT_COUNT;
+        this.stateAfter = invoke.stateAfter();
     }
 
     @Override
@@ -61,8 +64,21 @@
                 locationIdentity = ObjectLocationIdentity.create(locationArgument.asConstant());
             }
 
-            return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter());
+            return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter);
         }
         return this;
     }
+
+    @Override
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    public void setStateAfter(FrameState x) {
+        this.stateAfter = x;
+    }
+
+    public boolean hasSideEffect() {
+        return true;
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java	Mon Jun 30 17:27:40 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java	Mon Jun 30 17:28:53 2014 +0200
@@ -24,6 +24,8 @@
  */
 package com.oracle.truffle.api.utilities;
 
+import java.util.*;
+
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
 
@@ -119,4 +121,117 @@
     public static void restart() {
         AstJsonDumpBuilder = new StringBuilder();
     }
+
+    public static JsonObjectBuilder object() {
+        return new JsonObjectBuilder();
+    }
+
+    public static JsonArrayBuilder array() {
+        return new JsonArrayBuilder();
+    }
+
+    public static abstract class JsonStringBuilder {
+        @Override
+        public final String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendTo(sb);
+            return sb.toString();
+        }
+
+        protected abstract void appendTo(StringBuilder sb);
+
+        protected static void appendValue(StringBuilder sb, Object value) {
+            if (value instanceof JsonStringBuilder) {
+                ((JsonStringBuilder) value).appendTo(sb);
+            } else if (value instanceof Integer || value instanceof Boolean || value == null) {
+                sb.append(value);
+            } else {
+                sb.append(quote(String.valueOf(value)));
+            }
+        }
+    }
+
+    public static final class JsonObjectBuilder extends JsonStringBuilder {
+        private final Map<String, Object> contents = new LinkedHashMap<>();
+
+        private JsonObjectBuilder() {
+        }
+
+        public JsonObjectBuilder add(String key, String value) {
+            contents.put(key, value);
+            return this;
+        }
+
+        public JsonObjectBuilder add(String key, Number value) {
+            contents.put(key, value);
+            return this;
+        }
+
+        public JsonObjectBuilder add(String key, Boolean value) {
+            contents.put(key, value);
+            return this;
+        }
+
+        public JsonObjectBuilder add(String key, JsonStringBuilder value) {
+            contents.put(key, value);
+            return this;
+        }
+
+        @Override
+        protected void appendTo(StringBuilder sb) {
+            sb.append("{");
+            boolean comma = false;
+            for (Map.Entry<String, Object> entry : contents.entrySet()) {
+                if (comma) {
+                    sb.append(", ");
+                }
+                sb.append(quote(entry.getKey()));
+                sb.append(": ");
+                appendValue(sb, entry.getValue());
+                comma = true;
+            }
+            sb.append("}");
+        }
+    }
+
+    public static final class JsonArrayBuilder extends JsonStringBuilder {
+        private final List<Object> contents = new ArrayList<>();
+
+        private JsonArrayBuilder() {
+        }
+
+        public JsonArrayBuilder add(String value) {
+            contents.add(value);
+            return this;
+        }
+
+        public JsonArrayBuilder add(Number value) {
+            contents.add(value);
+            return this;
+        }
+
+        public JsonArrayBuilder add(Boolean value) {
+            contents.add(value);
+            return this;
+        }
+
+        public JsonArrayBuilder add(JsonStringBuilder value) {
+            contents.add(value);
+            return this;
+        }
+
+        @Override
+        protected void appendTo(StringBuilder sb) {
+            sb.append("[");
+            boolean comma = false;
+            for (Object value : contents) {
+                if (comma) {
+                    sb.append(", ");
+                }
+                appendValue(sb, value);
+                comma = true;
+            }
+            sb.append("]");
+        }
+    }
 }
--- a/mx/projects	Mon Jun 30 17:27:40 2014 +0200
+++ b/mx/projects	Mon Jun 30 17:28:53 2014 +0200
@@ -345,6 +345,14 @@
 project@com.oracle.graal.lir@javaCompliance=1.8
 project@com.oracle.graal.lir@workingSets=Graal,LIR
 
+# graal.lir.test
+project@com.oracle.graal.lir.test@subDir=graal
+project@com.oracle.graal.lir.test@sourceDirs=src
+project@com.oracle.graal.lir.test@dependencies=JUNIT,com.oracle.graal.lir
+project@com.oracle.graal.lir.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.lir.test@javaCompliance=1.8
+project@com.oracle.graal.lir.test@workingSets=Graal,LIR
+
 # graal.lir.amd64
 project@com.oracle.graal.lir.amd64@subDir=graal
 project@com.oracle.graal.lir.amd64@sourceDirs=src
--- a/mxtool/mx.py	Mon Jun 30 17:27:40 2014 +0200
+++ b/mxtool/mx.py	Mon Jun 30 17:28:53 2014 +0200
@@ -103,7 +103,7 @@
                 isOverwrite = False
                 if existingSource and existingSource != source:
                     if arcname[-1] != os.path.sep:
-                        log('warning: ' + self.path + ': avoid overwrite of ' + arcname + '\n  new: ' + source + '\n  old: ' + existingSource)
+                        logv('warning: ' + self.path + ': avoid overwrite of ' + arcname + '\n  new: ' + source + '\n  old: ' + existingSource)
                     isOverwrite = True
                 zf._provenance[arcname] = source
                 return isOverwrite
@@ -4163,9 +4163,8 @@
         projectDirs = [p.dir for p in suite.projects]
         for dirpath, dirnames, files in os.walk(suite.dir):
             if dirpath == suite.dir:
-                # no point in traversing .hg
-                if '.hg' in dirnames:
-                    dirnames.remove('.hg')
+                # no point in traversing .hg or lib/
+                dirnames[:] = [d for d in dirnames if d not in ['.hg', 'lib']]
             elif dirpath in projectDirs:
                 # don't traverse subdirs of an existing project in this suite
                 dirnames[:] = []
--- a/src/share/vm/graal/graalRuntime.cpp	Mon Jun 30 17:27:40 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Mon Jun 30 17:28:53 2014 +0200
@@ -701,6 +701,35 @@
 JVM_END
 #endif
 
+jint GraalRuntime::check_arguments(TRAPS) {
+  KlassHandle nullHandle;
+  parse_arguments(nullHandle, THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    // Errors in parsing Graal arguments cause exceptions.
+    // We now load and initialize HotSpotOptions which in turn
+    // causes argument parsing to be redone with better error messages.
+    CLEAR_PENDING_EXCEPTION;
+    TempNewSymbol name = SymbolTable::new_symbol("Lcom/oracle/graal/hotspot/HotSpotOptions;", THREAD);
+    instanceKlassHandle hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, THREAD);
+    GUARANTEE_NO_PENDING_EXCEPTION("Error in check_arguments");
+
+    parse_arguments(hotSpotOptionsClass, THREAD);
+    assert(HAS_PENDING_EXCEPTION, "must be");
+
+    ResourceMark rm;
+    Handle exception = PENDING_EXCEPTION;
+    CLEAR_PENDING_EXCEPTION;
+    oop message = java_lang_Throwable::message(exception);
+    if (message != NULL) {
+      tty->print_cr("Error parsing Graal options: %s", java_lang_String::as_utf8_string(message));
+    } else {
+      call_printStackTrace(exception, THREAD);
+    }
+    return JNI_ERR;
+  }
+  return JNI_OK;
+}
+
 bool GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) {
   ResourceMark rm(THREAD);
 
@@ -716,43 +745,51 @@
   return CITime || CITimeEach;
 }
 
+void GraalRuntime::check_required_value(const char* name, int name_len, const char* value, TRAPS) {
+  if (value == NULL) {
+    char buf[200];
+    jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=<value>' format for %.*s option", name_len, name, name_len, name);
+    THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
+  }
+}
+
 void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) {
   char first = arg[0];
   char* name;
   size_t name_len;
-  Handle name_handle;
-  bool valid = true;
+  bool recognized = true;
   if (first == '+' || first == '-') {
     name = arg + 1;
     name_len = strlen(name);
-    name_handle = java_lang_String::create_from_str(name, CHECK);
-    valid = set_option(hotSpotOptionsClass, name, (int)name_len, name_handle, arg, CHECK);
+    recognized = set_option(hotSpotOptionsClass, name, (int)name_len, arg, CHECK);
   } else {
     char* sep = strchr(arg, '=');
+    name = arg;
+    char* value = NULL;
     if (sep != NULL) {
-      name = arg;
       name_len = sep - name;
-      // Temporarily replace '=' with NULL to create the Java string for the option name
-      *sep = '\0';
-      name_handle = java_lang_String::create_from_str(arg, THREAD);
-      *sep = '=';
-      if (HAS_PENDING_EXCEPTION) {
-        return;
+      value = sep + 1;
+    } else {
+      name_len = strlen(name);
+    }
+    recognized = set_option(hotSpotOptionsClass, name, (int)name_len, value, CHECK);
+  }
+
+  if (!recognized) {
+    bool throw_err = hotSpotOptionsClass.is_null();
+    if (!hotSpotOptionsClass.is_null()) {
+      set_option_helper(hotSpotOptionsClass, name, (int)name_len, Handle(), ' ', Handle(), 0L);
+      if (!HAS_PENDING_EXCEPTION) {
+        throw_err = true;
       }
-      valid = set_option(hotSpotOptionsClass, name, (int)name_len, name_handle, sep + 1, CHECK);
-    } else {
+    }
+
+    if (throw_err) {
       char buf[200];
-      jio_snprintf(buf, sizeof(buf), "Value for option %s must use '-G:%s=<value>' format", arg, arg);
+      jio_snprintf(buf, sizeof(buf), "Unrecognized Graal option %.*s", name_len, name);
       THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
     }
   }
-
-  if (!valid) {
-    set_option_helper(hotSpotOptionsClass, name_handle, Handle(), ' ', Handle(), 0L);
-    char buf[200];
-    jio_snprintf(buf, sizeof(buf), "Invalid Graal option %s", arg);
-    THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
-  }
 }
 
 void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) {
@@ -802,7 +839,8 @@
   }
 }
 
-jlong GraalRuntime::parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS) {
+jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS) {
+  check_required_value(name, name_len, value, CHECK_(0L));
   union {
     jint i;
     jlong l;
@@ -829,23 +867,44 @@
   }
   ResourceMark rm(THREAD);
   char buf[200];
-  jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %s: %s", (spec == 'i' ? "numeric" : "float/double"), java_lang_String::as_utf8_string(name()), value);
+  bool missing = strlen(value) == 0;
+  if (missing) {
+    jio_snprintf(buf, sizeof(buf), "Missing %s value for Graal option %.*s", (spec == 'i' ? "numeric" : "float/double"), name_len, name);
+  } else {
+    jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %.*s: %s", (spec == 'i' ? "numeric" : "float/double"), name_len, name, value);
+  }
   THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L);
 }
 
-void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) {
+void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) {
   Thread* THREAD = Thread::current();
+  Handle name_handle;
+  if (name != NULL) {
+    if ((int) strlen(name) > name_len) {
+      // Temporarily replace '=' with NULL to create the Java string for the option name
+      char save = name[name_len];
+      name[name_len] = '\0';
+      name_handle = java_lang_String::create_from_str(name, THREAD);
+      name[name_len] = '=';
+      if (HAS_PENDING_EXCEPTION) {
+        return;
+      }
+    } else {
+      assert((int) strlen(name) == name_len, "must be");
+      name_handle = java_lang_String::create_from_str(name, CHECK);
+    }
+  }
+
   TempNewSymbol setOption = SymbolTable::new_symbol("setOption", THREAD);
   TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", THREAD);
   JavaValue result(T_VOID);
   JavaCallArguments args;
-  args.push_oop(name());
+  args.push_oop(name_handle());
   args.push_oop(option());
   args.push_int(spec);
   args.push_oop(stringValue());
   args.push_long(primitiveValue);
-  JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, THREAD);
-  GUARANTEE_NO_PENDING_EXCEPTION("Error while calling set_option_helper");
+  JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, CHECK);
 }
 
 Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) {
@@ -900,20 +959,23 @@
   }
 }
 
-void GraalRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) {
-  Thread* THREAD = Thread::current();
-  CLEAR_PENDING_EXCEPTION;
-
+void GraalRuntime::call_printStackTrace(Handle exception, Thread* thread) {
   assert(exception->is_a(SystemDictionary::Throwable_klass()), "Throwable instance expected");
   JavaValue result(T_VOID);
   JavaCalls::call_virtual(&result,
                           exception,
-                          KlassHandle(THREAD,
+                          KlassHandle(thread,
                           SystemDictionary::Throwable_klass()),
                           vmSymbols::printStackTrace_name(),
                           vmSymbols::void_method_signature(),
-                          THREAD);
+                          thread);
+}
 
+void GraalRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) {
+  Thread* THREAD = Thread::current();
+  CLEAR_PENDING_EXCEPTION;
+  tty->print_cr(message);
+  call_printStackTrace(exception, THREAD);
   vm_abort(dump_core);
 }
 
--- a/src/share/vm/graal/graalRuntime.hpp	Mon Jun 30 17:27:40 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Mon Jun 30 17:28:53 2014 +0200
@@ -45,11 +45,12 @@
    * Parses the string form of a numeric, float or double option into a jlong (using raw bits for floats/doubles).
    *
    * @param spec 'i', 'f' or 'd' (see HotSpotOptions.setOption())
-   * @param name name option option
+   * @param name option name
+   * @param name_len length of option name
    * @param value string value to parse
    * @throws InternalError if value could not be parsed according to spec
    */
-  static jlong parse_primitive_option_value(char spec, Handle name, const char* value, TRAPS);
+  static jlong parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS);
 
   /**
    * Loads default option value overrides from a <jre_home>/lib/graal.options if it exists. Each
@@ -72,15 +73,26 @@
    * The definition of this method is in graalRuntime.inline.hpp
    * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.
    *
+   * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option
+   * @param name option name
+   * @param name_len length of option name
    * @returns true if the option was found
    * @throws InternalError if there was a problem setting the option's value
    */
-  static bool set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS);
+  static bool set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS);
+
+  /**
+   * Raises an InternalError for an option that expects a value but was specified without a "=<value>" prefix.
+   */
+  static void check_required_value(const char* name, int name_len, const char* value, TRAPS);
 
   /**
    * Java call to HotSpotOptions.setOption(String name, OptionValue<?> option, char spec, String stringValue, long primitiveValue)
+   *
+   * @param name option name
+   * @param name_len length of option name
    */
-  static void set_option_helper(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue);
+  static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue);
 
   /**
    * Instantiates a service object, calls its default constructor and returns it.
@@ -122,6 +134,11 @@
    */
   static void abort_on_pending_exception(Handle exception, const char* message, bool dump_core = false);
 
+  /**
+   * Calls Throwable.printStackTrace() on a given exception.
+   */
+  static void call_printStackTrace(Handle exception, Thread* thread);
+
 #define GUARANTEE_NO_PENDING_EXCEPTION(error_message) do { \
     if (HAS_PENDING_EXCEPTION) { \
       GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, error_message); \
@@ -132,6 +149,18 @@
 
   static BufferBlob* initialize_buffer_blob();
 
+  /**
+   * Checks that all Graal specific VM options presented by the launcher are recognized
+   * and formatted correctly. To set relevant Java fields from the option, parse_arguments()
+   * must be called. This method makes no Java calls apart from creating exception objects
+   * if there is an errors in the Graal options.
+   */
+  static jint check_arguments(TRAPS);
+
+  /**
+   * Parses the Graal specific VM options that were presented by the launcher and sets
+   * the relevants Java fields.
+   */
   static bool parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS);
 
   static BasicType kindToBasicType(jchar ch);
--- a/src/share/vm/runtime/thread.cpp	Mon Jun 30 17:27:40 2014 +0200
+++ b/src/share/vm/runtime/thread.cpp	Mon Jun 30 17:28:53 2014 +0200
@@ -31,6 +31,7 @@
 #include "compiler/compileBroker.hpp"
 #ifdef GRAAL
 #include "graal/graalCompiler.hpp"
+#include "graal/graalRuntime.hpp"
 #endif
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
@@ -3731,6 +3732,14 @@
     Chunk::start_chunk_pool_cleaner_task();
   }
 
+#ifdef GRAAL
+  status = GraalRuntime::check_arguments(main_thread);
+  if (status != JNI_OK) {
+    *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again
+    return status;
+  }
+#endif
+
   // initialize compiler(s)
 #if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK) || defined(COMPILERGRAAL)
   CompileBroker::compilation_init();