# HG changeset patch # User Gilles Duboscq # Date 1340105118 -7200 # Node ID 1f263f152cdac0ccf252ceaf4b203dff8d9245e6 # Parent 3405794d135c245120301b348bffecc589ab97bb# Parent d05664608cb71b895cf6ab04095a900453866ef0 Merge diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Tue Jun 19 13:25:18 2012 +0200 @@ -82,7 +82,7 @@ VirtualObjectState currentField = objectStates.get(vobj); assert currentField != null; for (int i = 0; i < vobj.fieldsCount(); i++) { - values[i] = toCiValue(currentField.fields().get(i)); + values[i] = toCiValue(currentField.fieldValues().get(i)); } } } @@ -100,7 +100,7 @@ private BytecodeFrame computeFrameForState(FrameState state, LockScope locks, long leafGraphId) { int numLocals = state.localsSize(); int numStack = state.stackSize(); - int numLocks = (locks != null && locks.callerState == state.outerFrameState()) ? locks.stateDepth + 1 : 0; + int numLocks = (locks != null && locks.inliningIdentifier == state.inliningIdentifier()) ? locks.stateDepth + 1 : 0; Value[] values = new Value[numLocals + numStack + numLocks]; for (int i = 0; i < numLocals; i++) { @@ -112,7 +112,7 @@ LockScope nextLock = locks; for (int i = numLocks - 1; i >= 0; i--) { - assert locks != null && nextLock.callerState == state.outerFrameState() && nextLock.stateDepth == i; + assert locks != null && nextLock.inliningIdentifier == state.inliningIdentifier() && nextLock.stateDepth == i; Value owner = toCiValue(nextLock.monitor.object()); Value lockData = nextLock.lockData; @@ -153,7 +153,7 @@ } else if (value != null) { Debug.metric("StateVariables").increment(); Value operand = nodeOperands.get(value); - assert operand != null && (operand instanceof Variable || operand instanceof Constant); + assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand; return operand; } else { diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Jun 19 13:25:18 2012 +0200 @@ -45,6 +45,7 @@ import com.oracle.graal.lir.StandardOp.PhiLabelOp; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.FrameState.InliningIdentifier; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -94,12 +95,10 @@ public final LockScope outer; /** - * The frame state of the caller of the method performing the lock, or null if the outermost method + * The identifier of the actual inlined method instance performing the lock, or null if the outermost method * performs the lock. This information is used to compute the {@link BytecodeFrame} that this lock belongs to. - * We cannot use the actual frame state of the locking method, because it is not unique for a method. The - * caller frame states are unique, i.e., all frame states of inlined methods refer to the same caller frame state. */ - public final FrameState callerState; + public final InliningIdentifier inliningIdentifier; /** * The number of locks already found for this frame state. @@ -116,12 +115,12 @@ */ public final StackSlot lockData; - public LockScope(LockScope outer, FrameState callerState, MonitorEnterNode monitor, StackSlot lockData) { + public LockScope(LockScope outer, InliningIdentifier inliningIdentifier, MonitorEnterNode monitor, StackSlot lockData) { this.outer = outer; - this.callerState = callerState; + this.inliningIdentifier = inliningIdentifier; this.monitor = monitor; this.lockData = lockData; - if (outer != null && outer.callerState == callerState) { + if (outer != null && outer.inliningIdentifier == inliningIdentifier) { this.stateDepth = outer.stateDepth + 1; } else { this.stateDepth = 0; @@ -539,7 +538,7 @@ if (x.eliminated()) { // No code is emitted for eliminated locks, but for proper debug information generation we need to // register the monitor and its lock data. - curLocks = new LockScope(curLocks, x.stateAfter().outerFrameState(), x, lockData); + curLocks = new LockScope(curLocks, x.stateAfter().inliningIdentifier(), x, lockData); return; } @@ -548,7 +547,7 @@ LIRDebugInfo stateBefore = state(); // The state before the monitor enter is used for null checks, so it must not contain the newly locked object. - curLocks = new LockScope(curLocks, x.stateAfter().outerFrameState(), x, lockData); + curLocks = new LockScope(curLocks, x.stateAfter().inliningIdentifier(), x, lockData); // The state after the monitor enter is used for deoptimization, after the monitor has blocked, so it must contain the newly locked object. LIRDebugInfo stateAfter = stateFor(x.stateAfter(), -1); diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Tue Jun 19 13:25:18 2012 +0200 @@ -35,6 +35,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.FrameState.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -771,6 +772,7 @@ * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, false if no such check is required */ public static void inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { + InliningIdentifier identifier = new InliningIdentifier(inlineGraph.method(), invoke.toString()); NodeInputList parameters = invoke.callTarget().arguments(); StructuredGraph graph = (StructuredGraph) invoke.node().graph(); @@ -874,6 +876,7 @@ outerFrameState.setDuringCall(true); } frameState.setOuterFrameState(outerFrameState); + frameState.setInliningIdentifier(identifier); } } } diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Tue Jun 19 13:25:18 2012 +0200 @@ -61,21 +61,9 @@ public static Object newInstance( @Parameter("hub") Object hub, @ConstantParameter("size") int size, - @ConstantParameter("checkInit") boolean checkInit, @ConstantParameter("useTLAB") boolean useTLAB, @ConstantParameter("logType") String logType) { - if (checkInit) { - int klassState = load(hub, 0, klassStateOffset(), Kind.Int); - if (klassState != klassStateFullyInitialized()) { - if (logType != null) { - Log.print(logType); - Log.println(" - uninit alloc"); - } - return verifyOop(NewInstanceStubCall.call(hub)); - } - } - if (useTLAB) { Word thread = asWord(register(r15, wordKind())); Word top = loadWord(thread, threadTlabTopOffset()); @@ -135,16 +123,6 @@ } @Fold - private static int klassStateOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().klassStateOffset; - } - - @Fold - private static int klassStateFullyInitialized() { - return HotSpotGraalRuntime.getInstance().getConfig().klassStateFullyInitialized; - } - - @Fold private static int threadTlabTopOffset() { return HotSpotGraalRuntime.getInstance().getConfig().threadTlabTopOffset; } @@ -186,7 +164,7 @@ this.cache = new Cache(runtime); this.useTLAB = useTLAB; try { - newInstance = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("newInstance", Object.class, int.class, boolean.class, boolean.class, String.class)); + newInstance = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("newInstance", Object.class, int.class, boolean.class, String.class)); } catch (NoSuchMethodException e) { throw new GraalInternalError(e); } @@ -203,7 +181,7 @@ int instanceSize = type.instanceSize(); assert (instanceSize % wordSize()) == 0; assert instanceSize >= 0; - Key key = new Key(newInstance).add("size", instanceSize).add("checkInit", !type.isInitialized()).add("useTLAB", useTLAB).add("logType", LOG_ALLOCATION ? type.name() : null); + Key key = new Key(newInstance).add("size", instanceSize).add("useTLAB", useTLAB).add("logType", LOG_ALLOCATION ? type.name() : null); Arguments arguments = arguments("hub", hub); SnippetTemplate template = cache.get(key); Debug.log("Lowering newInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, arguments); diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Tue Jun 19 13:25:18 2012 +0200 @@ -116,7 +116,7 @@ } public FrameState create(int bci) { - return graph.add(new FrameState(method, bci, locals, stack, stackSize, rethrowException, false)); + return graph.add(new FrameState(method, bci, locals, stack, stackSize, rethrowException, false, null)); } public FrameStateBuilder copy() { diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Jun 19 13:25:18 2012 +0200 @@ -662,7 +662,7 @@ void genNewInstance(int cpi) { JavaType type = lookupType(cpi, NEW); - if (type instanceof ResolvedJavaType) { + if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { NewInstanceNode n = currentGraph.add(new NewInstanceNode((ResolvedJavaType) type)); frameState.apush(append(n)); } else { diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Tue Jun 19 13:25:18 2012 +0200 @@ -37,6 +37,25 @@ */ public final class FrameState extends VirtualState implements Node.IterableNodeType, LIRLowerable { + /** + * An instance of this class is an identifier for all nodes that were generated by one specific inlining operation. + * It is used to generate the correct debug information for nested locks. + */ + public static final class InliningIdentifier { + private final ResolvedJavaMethod method; + private final String context; + + public InliningIdentifier(ResolvedJavaMethod method, String context) { + this.method = method; + this.context = context; + } + + @Override + public String toString() { + return method + "@" + context; + } + } + protected final int localsSize; protected final int stackSize; @@ -46,6 +65,12 @@ private boolean duringCall; /** + * This object identifies the concrete inlining operation that produced this frame state. + * It is set during inlining, therefore for the outermost frame states of a graph this field is null. + */ + private InliningIdentifier inliningIdentifier; + + /** * This BCI should be used for frame states that are built for code with no meaningful BCI. */ public static final int UNKNOWN_BCI = -4; @@ -92,7 +117,7 @@ * @param stackSize size of the stack * @param rethrowException if true the VM should re-throw the exception on top of the stack when deopt'ing using this framestate */ - public FrameState(ResolvedJavaMethod method, int bci, List values, int stackSize, boolean rethrowException, boolean duringCall, List virtualObjectMappings) { + public FrameState(ResolvedJavaMethod method, int bci, List values, int stackSize, boolean rethrowException, boolean duringCall, InliningIdentifier inliningIdentifier, List virtualObjectMappings) { assert stackSize >= 0; assert (bci >= 0 && method != null) || (bci < 0 && method == null && values.isEmpty()); this.method = method; @@ -103,6 +128,7 @@ this.virtualObjectMappings = new NodeInputList<>(this, virtualObjectMappings); this.rethrowException = rethrowException; this.duringCall = duringCall; + this.inliningIdentifier = inliningIdentifier; assert !rethrowException || stackSize == 1 : "must have exception on top of the stack"; } @@ -111,10 +137,10 @@ * @param bci marker bci, needs to be < 0 */ public FrameState(int bci) { - this(null, bci, Collections.emptyList(), 0, false, false, Collections.emptyList()); + this(null, bci, Collections.emptyList(), 0, false, false, null, Collections.emptyList()); } - public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, ValueNode[] stack, int stackSize, boolean rethrowException, boolean duringCall) { + public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, ValueNode[] stack, int stackSize, boolean rethrowException, boolean duringCall, InliningIdentifier inliningIdentifier) { this.method = method; this.bci = bci; this.localsSize = locals.length; @@ -132,6 +158,7 @@ this.virtualObjectMappings = new NodeInputList<>(this); this.rethrowException = rethrowException; this.duringCall = duringCall; + this.inliningIdentifier = inliningIdentifier; assert !rethrowException || stackSize == 1 : "must have exception on top of the stack"; } @@ -148,6 +175,14 @@ this.outerFrameState = x; } + public InliningIdentifier inliningIdentifier() { + return inliningIdentifier; + } + + public void setInliningIdentifier(InliningIdentifier inliningIdentifier) { + this.inliningIdentifier = inliningIdentifier; + } + public boolean rethrowException() { return rethrowException; } @@ -176,7 +211,7 @@ return virtualObjectMappings.get(i); } - public Iterable virtualObjectMappings() { + public NodeInputList virtualObjectMappings() { return virtualObjectMappings; } @@ -184,7 +219,9 @@ * Gets a copy of this frame state. */ public FrameState duplicate(int newBci) { - return duplicate(newBci, false); + FrameState other = graph().add(new FrameState(method, newBci, values, stackSize, rethrowException, duringCall, inliningIdentifier, virtualObjectMappings)); + other.setOuterFrameState(outerFrameState()); + return other; } /** @@ -194,12 +231,21 @@ return duplicate(bci); } - public FrameState duplicate(int newBci, boolean duplicateOuter) { - FrameState other = graph().add(new FrameState(method, newBci, values, stackSize, rethrowException, duringCall, virtualObjectMappings)); + /** + * Duplicates a FrameState, along with a deep copy of all connected VirtualState (outer FrameStates, + * VirtualObjectStates, ...). + */ + @Override + public FrameState duplicateWithVirtualState() { FrameState newOuterFrameState = outerFrameState(); - if (duplicateOuter && newOuterFrameState != null) { - newOuterFrameState = newOuterFrameState.duplicate(newOuterFrameState.bci, duplicateOuter); + if (newOuterFrameState != null) { + newOuterFrameState = newOuterFrameState.duplicateWithVirtualState(); } + ArrayList newVirtualMappings = new ArrayList<>(virtualObjectMappings.size()); + for (VirtualObjectState state : virtualObjectMappings) { + newVirtualMappings.add(state.duplicateWithVirtualState()); + } + FrameState other = graph().add(new FrameState(method, bci, values, stackSize, rethrowException, duringCall, inliningIdentifier, newVirtualMappings)); other.setOuterFrameState(newOuterFrameState); return other; } @@ -221,7 +267,7 @@ } Collections.addAll(copy, pushedValues); - FrameState other = graph().add(new FrameState(method, newBci, copy, copy.size() - localsSize, newRethrowException, false, virtualObjectMappings)); + FrameState other = graph().add(new FrameState(method, newBci, copy, copy.size() - localsSize, newRethrowException, false, inliningIdentifier, virtualObjectMappings)); other.setOuterFrameState(outerFrameState()); return other; } @@ -342,4 +388,14 @@ } return super.verify(); } + + @Override + public void applyToNonVirtual(NodeClosure< ? super ValueNode> closure) { + for (ValueNode value : values.nonNull()) { + closure.apply(value); + } + for (VirtualObjectState state : virtualObjectMappings) { + state.applyToNonVirtual(closure); + } + } } diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Tue Jun 19 13:25:18 2012 +0200 @@ -30,4 +30,12 @@ */ public abstract class VirtualState extends Node { + public interface NodeClosure { + void apply(T node); + } + + public abstract VirtualState duplicateWithVirtualState(); + + public abstract void applyToNonVirtual(NodeClosure closure); + } diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Tue Jun 19 13:25:18 2012 +0200 @@ -102,7 +102,7 @@ EscapeField[] fields = new EscapeField[length]; for (int i = 0; i < length; i++) { Integer representation = i; - fields[i] = new EscapeField("[" + i + "]", representation, ((NewArrayNode) node).elementType()); + fields[i] = new EscapeField(Integer.toString(i), representation, ((NewArrayNode) node).elementType()); } return fields; } diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java Tue Jun 19 13:25:18 2012 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.virtual; +import java.util.*; + import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -32,24 +34,42 @@ public final class VirtualObjectState extends VirtualState implements Node.IterableNodeType, LIRLowerable { @Input private VirtualObjectNode object; - @Input private NodeInputList fields; + @Input private NodeInputList fieldValues; public VirtualObjectNode object() { return object; } - public NodeInputList fields() { - return fields; + public NodeInputList fieldValues() { + return fieldValues; } - public VirtualObjectState(VirtualObjectNode object, ValueNode[] fields) { + public VirtualObjectState(VirtualObjectNode object, ValueNode[] fieldValues) { + assert object.fieldsCount() == fieldValues.length; this.object = object; - assert object.fields().length == fields.length; - this.fields = new NodeInputList<>(this, fields); + this.fieldValues = new NodeInputList<>(this, fieldValues); + } + + private VirtualObjectState(VirtualObjectNode object, List fieldValues) { + assert object.fieldsCount() == fieldValues.size(); + this.object = object; + this.fieldValues = new NodeInputList<>(this, fieldValues); } @Override public void generate(LIRGeneratorTool generator) { // Nothing to do, virtual object states are processed as part of the handling of StateSplit nodes. } + + @Override + public VirtualObjectState duplicateWithVirtualState() { + return graph().add(new VirtualObjectState(object, fieldValues)); + } + + @Override + public void applyToNonVirtual(NodeClosure< ? super ValueNode> closure) { + for (ValueNode value : fieldValues) { + closure.apply(value); + } + } } diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Tue Jun 19 13:25:18 2012 +0200 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011, 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.snippets; + +import static com.oracle.graal.nodes.calc.Condition.*; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.tests.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +/** + * Tests for the {@link Word} type. + */ +public class WordTest extends GraalCompilerTest implements SnippetsInterface { + + private final SnippetInstaller installer; + + public WordTest() { + TargetDescription target = Graal.getRequiredCapability(GraalCompiler.class).target; + installer = new SnippetInstaller(runtime, target); + } + + @Override + protected StructuredGraph parse(Method m) { + ResolvedJavaMethod resolvedMethod = runtime.getResolvedJavaMethod(m); + return installer.makeGraph(resolvedMethod, null); + } + + @Test + public void test_arithmetic() { + long[] words = new long[] {Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE}; + for (long word : words) { + for (int addend = -1000; addend < 1000; addend++) { + test("plus_int", word, addend); + test("plus_int", word, -addend); + test("minus_int", word, addend); + test("minus_int", word, -addend); + } + for (long addend : words) { + test("plus_int", word, (int) addend); + test("minus_int", word, (int) addend); + test("plus_int", word, -((int) addend)); + test("minus_int", word, -((int) addend)); + } + } + } + + @Test + public void test_compare() { + long[] words = new long[] {Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE}; + for (long word1 : words) { + for (long word2 : words) { + for (Condition cond : new Condition[] {AE, AT, EQ, NE, BE, BT}) { + test("compare" + cond.name(), word1, word2); + test("compare" + cond.name(), word2, word1); + } + } + } + } + + @Snippet + public static long plus_int(long word, int addend) { + return Word.fromLong(word).plus(addend).toLong(); + } + + @Snippet + public static long minus_int(long word, int addend) { + return Word.fromLong(word).plus(addend).toLong(); + } + + @Snippet + public static boolean compareAE(long word1, long word2) { + return Word.fromLong(word1).cmp(Condition.AE, Word.fromLong(word2)); + } + @Snippet + public static boolean compareAT(long word1, long word2) { + return Word.fromLong(word1).cmp(Condition.AT, Word.fromLong(word2)); + } + @Snippet + public static boolean compareEQ(long word1, long word2) { + return Word.fromLong(word1).cmp(Condition.EQ, Word.fromLong(word2)); + } + @Snippet + public static boolean compareNE(long word1, long word2) { + return Word.fromLong(word1).cmp(Condition.NE, Word.fromLong(word2)); + } + @Snippet + public static boolean compareBE(long word1, long word2) { + return Word.fromLong(word1).cmp(Condition.BE, Word.fromLong(word2)); + } + @Snippet + public static boolean compareBT(long word1, long word2) { + return Word.fromLong(word1).cmp(Condition.BT, Word.fromLong(word2)); + } + +} diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Tue Jun 19 13:25:18 2012 +0200 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.snippets.Word.Operation; import com.oracle.graal.snippets.nodes.*; /** @@ -67,6 +68,9 @@ return false; } } + if (method.getAnnotation(Operation.class) != null) { + return false; + } return true; } }; diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Jun 19 13:25:18 2012 +0200 @@ -134,10 +134,10 @@ } } - private StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { + public StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { StructuredGraph graph = graphCache.get(method); if (graph == null) { - graph = buildGraph(method, policy); + graph = buildGraph(method, policy == null ? inliningPolicy(method) : policy); //System.out.println("built " + graph); graphCache.put(method, graph); } diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java Tue Jun 19 13:25:18 2012 +0200 @@ -26,6 +26,7 @@ import java.lang.annotation.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.calc.*; /** @@ -46,32 +47,83 @@ * The canonical {@link Operation} represented by a method in the {@link Word} class. */ public enum Opcode { + L2W, + I2W, + W2L, + W2I, PLUS, MINUS, COMPARE; } - private Word() { + private Word(long value) { + this.value = value; + } + + private final long value; + + @Operation(L2W) + public static Word fromLong(long value) { + return new Word(value); + } + + @Operation(I2W) + public static Word fromInt(int value) { + return new Word(value); + } + + @Operation(W2I) + public int toInt() { + return (int) value; + } + + @Operation(W2L) + public long toLong() { + return value; } @Operation(COMPARE) - public native boolean cmp(Condition condition, Word other); + public boolean cmp(Condition condition, Word other) { + long a = value; + long b = other.value; + switch (condition) { + case AE: return (a >= b) ^ ((a < 0) != (b < 0)); + case AT: return (a > b) ^ ((a < 0) != (b < 0)); + case BE: return (a <= b) ^ ((a < 0) != (b < 0)); + case BT: return (a < b) ^ ((a < 0) != (b < 0)); + case EQ: return a == b; + case NE: return a != b; + default: throw new GraalInternalError("Unexpected operation on word: " + condition); + } + } @Operation(PLUS) - public native Word plus(int addend); - - @Operation(PLUS) - public native Word plus(long addend); + public Word plus(int addend) { + return new Word(value + addend); + } @Operation(PLUS) - public native Word plus(Word addend); + public Word plus(long addend) { + return new Word(value + addend); + } - @Operation(MINUS) - public native Word minus(int addend); + @Operation(PLUS) + public Word plus(Word addend) { + return new Word(value + addend.value); + } @Operation(MINUS) - public native Word minus(long addend); + public Word minus(int addend) { + return new Word(value - addend); + } @Operation(MINUS) - public native Word minus(Word addend); + public Word minus(long addend) { + return new Word(value - addend); + } + + @Operation(MINUS) + public Word minus(Word addend) { + return new Word(value - addend.value); + } } diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Tue Jun 19 13:25:18 2012 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.compiler.phases.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.*; +import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.extended.*; @@ -81,7 +81,7 @@ if (operation != null) { NodeInputList arguments = callTargetNode.arguments(); Invoke invoke = (Invoke) callTargetNode.usages().first(); - assert invoke != null; + assert invoke != null : callTargetNode.targetMethod(); Opcode opcode = operation.value(); switch (opcode) { @@ -99,6 +99,40 @@ invoke.intrinsify(op); break; } + + case W2I: { + assert arguments.size() == 1; + ValueNode value = arguments.last(); + ValueNode intValue = fromWordKindTo(graph, value, Kind.Int); + invoke.intrinsify(intValue); + break; + } + + case W2L: { + assert arguments.size() == 1; + ValueNode value = arguments.last(); + ValueNode longValue = fromWordKindTo(graph, value, Kind.Long); + invoke.intrinsify(longValue); + break; + } + + case L2W: { + assert arguments.size() == 1; + ValueNode value = arguments.last(); + assert value.kind() == Kind.Long; + ValueNode wordValue = asWordKind(graph, value); + invoke.intrinsify(wordValue); + break; + } + + case I2W: { + assert arguments.size() == 1; + ValueNode value = arguments.last(); + assert value.kind() == Kind.Int; + invoke.intrinsify(asWordKind(graph, value)); + break; + } + default: { throw new GraalInternalError("Unknown opcode: %s", opcode); } @@ -111,7 +145,7 @@ * Creates comparison node for a given condition and two input values. */ private ValueNode compare(Condition condition, StructuredGraph graph, ValueNode left, ValueNode right) { - assert condition.isUnsigned(); + assert condition.isUnsigned() || condition == Condition.EQ || condition == Condition.NE : condition; assert left.kind() == wordKind; assert right.kind() == wordKind; @@ -158,6 +192,21 @@ return value; } + private static ValueNode fromWordKindTo(StructuredGraph graph, ValueNode value, Kind to) { + Kind from = value.kind(); + if (from != to) { + Op op; + if (from.isLong()) { + op = Op.L2I; + } else { + assert from.isInt(); + op = Op.I2L; + } + return graph.unique(new ConvertNode(op, value)); + } + return value; + } + public boolean isWord(ValueNode node) { return isWord(node.stamp().declaredType()); } diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java Tue Jun 19 13:25:18 2012 +0200 @@ -67,7 +67,7 @@ } final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method); - InstalledCode compiledMethod = compile(riMethod, graph); + InstalledCode compiledMethod = getCode(riMethod, graph); try { Object result = compiledMethod.execute("1", "2", "3"); Assert.assertEquals("1-2-3", result); @@ -81,7 +81,7 @@ Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method); - InstalledCode compiledMethod = compile(riMethod, graph); + InstalledCode compiledMethod = getCode(riMethod, graph); try { Object result = compiledMethod.executeVarargs("1", "2", "3"); Assert.assertEquals("1 2 3", result); @@ -95,7 +95,7 @@ Method method = getMethod("testMethodVirtual"); final StructuredGraph graph = parse(method); final ResolvedJavaMethod riMethod = runtime.getResolvedJavaMethod(method); - InstalledCode compiledMethod = compile(riMethod, graph); + InstalledCode compiledMethod = getCode(riMethod, graph); try { f1 = "0"; Object result = compiledMethod.executeVarargs(this, "1", "2", "3"); @@ -123,7 +123,7 @@ } } - InstalledCode compiledMethod = compile(riMethod, graph); + InstalledCode compiledMethod = getCode(riMethod, graph); final CompilableObject compilableObject = new CompilableObjectImpl(0); Object result; diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java Tue Jun 19 13:25:18 2012 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.tests; import java.lang.reflect.*; +import java.util.*; import java.util.concurrent.*; import junit.framework.*; @@ -163,8 +164,7 @@ } catch (Exception e) { throw new RuntimeException(e); } - InstalledCode compiledMethod = compile(runtime.getResolvedJavaMethod(method), parse(method)); - compiledMethod.method(); + InstalledCode compiledMethod = getCode(runtime.getResolvedJavaMethod(method), parse(method)); if (exception != null) { try { @@ -179,13 +179,35 @@ } } - protected InstalledCode compile(final ResolvedJavaMethod method, final StructuredGraph graph) { - return Debug.scope("Compiling", new DebugDumpScope(String.valueOf(compilationId++), true), new Callable() { + private Map cache = new HashMap<>(); + + /** + * Gets installed code for a given method and graph, compiling it first if necessary. + */ + protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) { + return getCode(method, graph, false); + } + + /** + * Gets installed code for a given method and graph, compiling it first if necessary. + * + * @param forceCompile specifies whether to ignore any previous code cached for the (method, key) pair + */ + protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph, boolean forceCompile) { + if (!forceCompile) { + InstalledCode cached = cache.get(method); + if (cached != null && cached.isValid()) { + return cached; + } + } + InstalledCode installedCode = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(compilationId++), true), new Callable() { public InstalledCode call() throws Exception { CompilationResult targetMethod = runtime.compile(method, graph); return addMethod(method, targetMethod); } }); + cache.put(method, installedCode); + return installedCode; } protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult tm) { diff -r 3405794d135c -r 1f263f152cda graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java Tue Jun 19 13:20:39 2012 +0200 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java Tue Jun 19 13:25:18 2012 +0200 @@ -36,11 +36,13 @@ protected JavaTypeProfile currentProfile; @Override - protected InstalledCode compile(final ResolvedJavaMethod method, final StructuredGraph graph) { + protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) { + boolean forceCompile = false; if (currentProfile != null) { replaceProfile(graph, currentProfile); + forceCompile = true; } - return super.compile(method, graph); + return super.getCode(method, graph, forceCompile); } protected JavaTypeProfile profile(Class... types) { diff -r 3405794d135c -r 1f263f152cda mx/commands.py --- a/mx/commands.py Tue Jun 19 13:20:39 2012 +0200 +++ b/mx/commands.py Tue Jun 19 13:25:18 2012 +0200 @@ -175,7 +175,7 @@ """run one or all DaCapo benchmarks DaCapo options are distinguished from VM options by a '@' prefix. - For example, '@--iterations @5' will pass '--iterations 5' to the + For example, '@-n @5' will pass '-n 5' to the DaCapo harness.""" numTests = {} @@ -624,26 +624,7 @@ elif e == basename + '.class': classes.append(pkg + '.' + basename) - -# Table of unit tests. -# Keys are project names, values are package name lists. -# All source files in the given (project,package) pairs are scanned for lines -# containing '@Test'. These are then determined to be the classes defining -# unit tests. -_unittests = { - 'com.oracle.graal.tests': ['com.oracle.graal.compiler.tests'], -} -_jtttests = { - 'com.oracle.graal.jtt': ['com.oracle.graal.jtt'], -} - -def unittest(args): - """run the Graal Compiler Unit Tests in the GraalVM - - If filters are supplied, only tests whose fully qualified name - include a filter as a substring are run. Negative filters are - those with a '-' prefix. VM args should have a @ prefix.""" - +def _run_tests(args, harnessName, harness): pos = [a for a in args if a[0] != '-' and a[0] != '@' ] neg = [a[1:] for a in args if a[0] == '-'] vmArgs = [a[1:] for a in args if a[0] == '@'] @@ -654,18 +635,30 @@ return True return False - for proj in _unittests.iterkeys(): - p = mx.project(proj) - classes = [] - for pkg in _unittests[proj]: - _find_classes_with_annotations(classes, p, pkg, ['@Test']) + for p in mx.projects(): + if getattr(p, 'testHarness', None) == harnessName: + classes = [] + _find_classes_with_annotations(classes, p, None, ['@Test']) + + if len(pos) != 0: + classes = [c for c in classes if containsAny(c, pos)] + if len(neg) != 0: + classes = [c for c in classes if not containsAny(c, neg)] + + if len(classes) != 0: + mx.log('running tests in ' + p.name) + harness(p, vmArgs, classes) + +def unittest(args): + """run the Graal Compiler Unit Tests in the GraalVM - if len(pos) != 0: - classes = [c for c in classes if containsAny(c, pos)] - if len(neg) != 0: - classes = [c for c in classes if not containsAny(c, neg)] - - vm(['-XX:-BootstrapGraal', '-esa'] + vmArgs + ['-cp', mx.classpath(proj), 'org.junit.runner.JUnitCore'] + classes) + If filters are supplied, only tests whose fully qualified name + include a filter as a substring are run. Negative filters are + those with a '-' prefix. VM args should have a @ prefix.""" + + def harness(p, vmArgs, classes): + vm(['-XX:-BootstrapGraal', '-esa'] + vmArgs + ['-cp', mx.classpath(p.name), 'org.junit.runner.JUnitCore'] + classes) + _run_tests(args, 'unittest', harness) def jtt(args): """run the Java Tester Tests in the GraalVM @@ -674,28 +667,9 @@ include a filter as a substring are run. Negative filters are those with a '-' prefix. VM args should have a @ prefix.""" - pos = [a for a in args if a[0] != '-' and a[0] != '@' ] - neg = [a[1:] for a in args if a[0] == '-'] - vmArgs = [a[1:] for a in args if a[0] == '@'] - - def containsAny(c, substrings): - for s in substrings: - if s in c: - return True - return False - - for proj in _jtttests.iterkeys(): - p = mx.project(proj) - classes = [] - for pkg in _jtttests[proj]: - _find_classes_with_annotations(classes, p, pkg, ['@Test']) - - if len(pos) != 0: - classes = [c for c in classes if containsAny(c, pos)] - if len(neg) != 0: - classes = [c for c in classes if not containsAny(c, neg)] - - vm(['-XX:-BootstrapGraal', '-XX:CompileOnly=com/oracle/graal/jtt', '-XX:CompileCommand=compileonly,java/lang/Object::', '-XX:CompileCommand=quiet', '-Xcomp', '-esa'] + vmArgs + ['-cp', mx.classpath(proj), 'org.junit.runner.JUnitCore'] + classes) + def harness(p, vmArgs, classes): + vm(['-XX:-BootstrapGraal', '-XX:CompileOnly=com/oracle/graal/jtt', '-XX:CompileCommand=compileonly,java/lang/Object::', '-XX:CompileCommand=quiet', '-Xcomp', '-esa'] + vmArgs + ['-cp', mx.classpath(p.name), 'org.junit.runner.JUnitCore'] + classes) + _run_tests(args, 'jtt', harness) def buildvms(args): """build one or more VMs in various configurations""" diff -r 3405794d135c -r 1f263f152cda mx/projects --- a/mx/projects Tue Jun 19 13:20:39 2012 +0200 +++ b/mx/projects Tue Jun 19 13:25:18 2012 +0200 @@ -119,9 +119,10 @@ # graal.snippets.test project@com.oracle.graal.snippets.test@subDir=graal project@com.oracle.graal.snippets.test@sourceDirs=src -project@com.oracle.graal.snippets.test@dependencies=com.oracle.graal.snippets +project@com.oracle.graal.snippets.test@dependencies=com.oracle.graal.snippets,com.oracle.graal.tests project@com.oracle.graal.snippets.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.snippets.test@javaCompliance=1.7 +project@com.oracle.graal.snippets.test@testHarness=unittest # graal.nodes project@com.oracle.graal.nodes@subDir=graal @@ -184,6 +185,7 @@ project@com.oracle.graal.tests@dependencies=JUNIT,com.oracle.graal.printer,com.oracle.graal.api project@com.oracle.graal.tests@checkstyle=com.oracle.graal.graph project@com.oracle.graal.tests@javaCompliance=1.7 +project@com.oracle.graal.tests@testHarness=unittest # graal.jtt project@com.oracle.graal.jtt@subDir=graal @@ -191,6 +193,7 @@ project@com.oracle.graal.jtt@dependencies=JUNIT project@com.oracle.graal.jtt@checkstyle=com.oracle.graal.graph project@com.oracle.graal.jtt@javaCompliance=1.7 +project@com.oracle.graal.jtt@testHarness=jtt # graal.examples project@com.oracle.graal.examples@subDir=graal