# HG changeset patch # User Doug Simon # Date 1404142133 -7200 # Node ID 8da760bd1575ac9e7dbe5baa975fb407593dc893 # Parent 732a9e80e8dcf6752c11a4b9b01fc667093ec4d6# Parent 81e4af185dd64ec11dd4c6bb5bcf6190cd92fefa Merge. diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/DefaultCanonicalizerTool.java --- /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; + } +} diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java --- 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(" }"); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- 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 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 ? "" : "=")); + 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 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 ? "" : "=")); + } } } } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java --- 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 { +public class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary { public ClassCastNode(Invoke invoke) { super(invoke); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java --- 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java --- 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java --- 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; diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- 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) { diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java --- 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java --- /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 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 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 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)); + } + +} diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java --- /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 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 replValues = new ArrayList<>(); + for (ValuePosition pos : positions) { + Value v = new DummyValue(); + replValues.add(v); + pos.set(op, v); + + } + + // check replaced values + Iterator it = replValues.iterator(); + for (ValuePosition pos : positions) { + Value v = pos.get(op); + assertEquals(it.next(), v); + } + assertFalse(it.hasNext()); + } + +} diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java --- 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; + } + } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java --- 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 getFlags(ValuePosition pos) { + return componentFlags[pos.getIndex()]; + } } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java --- 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; + } } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java --- 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 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); } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java --- 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[] 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); } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java --- /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 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; + } + +} diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- 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 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java --- 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 diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java --- 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 diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionDescriptor.java --- 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; diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- 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) { diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- 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()}.
+ *
+ * During lowering, multiple sources are queried in order to look for a replacement: + *
    + *
  • If {@link #getLoweredSnippetGraph(LoweringTool)} returns a non-null result, this graph is + * used as a replacement.
  • + *
  • If a {@link MethodSubstitution} for the target method is found, this substitution is used as + * a replacement.
  • + *
  • Otherwise, the macro node is replaced with an {@link InvokeNode}. Note that this is only + * possible if the macro node is a {@link MacroStateSplitNode}.
  • + *
+ */ +public class MacroNode extends FixedWithNextNode implements Lowerable { @Input protected final NodeInputList 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; - } } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java --- /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); + } + } +} diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java --- 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- 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, StructuredGraph> cache = new HashMap<>(); private final HashMap, 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java --- 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()) { diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java --- 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; } } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java --- 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); diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java --- 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; diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java --- 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; + } } diff -r 732a9e80e8dc -r 8da760bd1575 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java --- 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 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 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 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("]"); + } + } } diff -r 732a9e80e8dc -r 8da760bd1575 mx/projects --- 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 diff -r 732a9e80e8dc -r 8da760bd1575 mxtool/mx.py --- 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[:] = [] diff -r 732a9e80e8dc -r 8da760bd1575 src/share/vm/graal/graalRuntime.cpp --- 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=' 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=' 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); } diff -r 732a9e80e8dc -r 8da760bd1575 src/share/vm/graal/graalRuntime.hpp --- 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 /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 "=" 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); diff -r 732a9e80e8dc -r 8da760bd1575 src/share/vm/runtime/thread.cpp --- 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();