# HG changeset patch # User Thomas Wuerthinger # Date 1363019300 -3600 # Node ID 1c82ddf25b20772659866351a3d84242cf0f25c2 # Parent 4ba3455566e002b07f25267f61c8313aa3e672bb# Parent 4508b693afa672ad0452aa6da84b84b14292c802 Merge. diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Mar 11 17:28:20 2013 +0100 @@ -439,7 +439,7 @@ } public final void bsfq(Register dst, AMD64Address src) { - emitByte(Prefix.REXW); + prefixq(src, dst); emitByte(0x0F); emitByte(0xBC); emitOperandHelper(dst, src); @@ -453,7 +453,7 @@ } public final void bsrq(Register dst, AMD64Address src) { - emitByte(Prefix.REXW); + prefixq(src, dst); emitByte(0x0F); emitByte(0xBD); emitOperandHelper(dst, src); @@ -539,6 +539,15 @@ } } + public final void cvtsd2ss(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF2); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x5A); + emitOperandHelper(dst, src); + } + public final void cvtsd2ss(Register dst, Register src) { assert dst.isFpu(); assert src.isFpu(); @@ -549,6 +558,15 @@ emitByte(0xC0 | encode); } + public final void cvtsi2sdl(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF2); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x2A); + emitOperandHelper(dst, src); + } + public final void cvtsi2sdl(Register dst, Register src) { assert dst.isFpu(); emitByte(0xF2); @@ -558,6 +576,15 @@ emitByte(0xC0 | encode); } + public final void cvtsi2ssl(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x2A); + emitOperandHelper(dst, src); + } + public final void cvtsi2ssl(Register dst, Register src) { assert dst.isFpu(); emitByte(0xF3); @@ -567,6 +594,15 @@ emitByte(0xC0 | encode); } + public final void cvtss2sd(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x5A); + emitOperandHelper(dst, src); + } + public final void cvtss2sd(Register dst, Register src) { assert dst.isFpu(); assert src.isFpu(); @@ -577,6 +613,14 @@ emitByte(0xC0 | encode); } + public final void cvttsd2sil(Register dst, AMD64Address src) { + emitByte(0xF2); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x2C); + emitOperandHelper(dst, src); + } + public final void cvttsd2sil(Register dst, Register src) { assert src.isFpu(); emitByte(0xF2); @@ -586,6 +630,14 @@ emitByte(0xC0 | encode); } + public final void cvttss2sil(Register dst, AMD64Address src) { + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x2C); + emitOperandHelper(dst, src); + } + public final void cvttss2sil(Register dst, Register src) { assert src.isFpu(); emitByte(0xF3); @@ -1055,6 +1107,13 @@ emitByte(0xC0 | encode); } + public final void movsxw(Register dst, AMD64Address src) { + prefix(src, dst); + emitByte(0x0F); + emitByte(0xBF); + emitOperandHelper(dst, src); + } + public final void movw(AMD64Address dst, int imm16) { emitByte(0x66); // switch to 16-bit mode prefix(dst); @@ -1954,6 +2013,15 @@ emitOperandHelper(reg, adr); } + public final void cvtsi2sdq(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF2); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0x2A); + emitOperandHelper(dst, src); + } + public final void cvtsi2sdq(Register dst, Register src) { assert dst.isFpu(); emitByte(0xF2); @@ -1963,6 +2031,15 @@ emitByte(0xC0 | encode); } + public final void cvtsi2ssq(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF3); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0x2A); + emitOperandHelper(dst, src); + } + public final void cvtsi2ssq(Register dst, Register src) { assert dst.isFpu(); emitByte(0xF3); @@ -1972,6 +2049,14 @@ emitByte(0xC0 | encode); } + public final void cvttsd2siq(Register dst, AMD64Address src) { + emitByte(0xF2); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0x2C); + emitOperandHelper(dst, src); + } + public final void cvttsd2siq(Register dst, Register src) { assert src.isFpu(); emitByte(0xF2); @@ -1981,6 +2066,14 @@ emitByte(0xC0 | encode); } + public final void cvttss2siq(Register dst, AMD64Address src) { + emitByte(0xF3); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0x2C); + emitOperandHelper(dst, src); + } + public final void cvttss2siq(Register dst, Register src) { assert src.isFpu(); emitByte(0xF3); diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java Mon Mar 11 17:28:20 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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.compiler.amd64.test; + +import org.junit.*; + +import com.oracle.graal.compiler.test.backend.*; + +public class AMD64AllocatorTest extends AllocatorTest { + + @Test + public void test1() { + test("test1snippet", 2, 1, 0); + } + + public static long test1snippet(long x) { + return x + 5; + } + + @Ignore + @Test + public void test2() { + test("test2snippet", 2, 0, 0); + } + + public static long test2snippet(long x) { + return x * 5; + } + + @Ignore + @Test + public void test3() { + test("test3snippet", 4, 1, 0); + } + + public static long test3snippet(long x) { + return x / 3 + x % 3; + } + +} diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Mar 11 17:28:20 2013 +0100 @@ -41,36 +41,7 @@ public class AllocatorTest extends GraalCompilerTest { - @Test - public void test1() { - test("test1snippet", 2, 1, 0); - } - - public static long test1snippet(long x) { - return x + 5; - } - - @Ignore - @Test - public void test2() { - test("test2snippet", 2, 0, 0); - } - - public static long test2snippet(long x) { - return x * 5; - } - - @Ignore - @Test - public void test3() { - test("test3snippet", 4, 1, 0); - } - - public static long test3snippet(long x) { - return x / 3 + x % 3; - } - - private void test(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) { + protected void test(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) { final StructuredGraph graph = parse(snippet); Debug.scope("AllocatorTest", new Object[]{graph, graph.method(), backend.target}, new Runnable() { @@ -91,7 +62,7 @@ }); } - class RegisterStats { + private class RegisterStats { public final LIR lir; public HashSet registers = new HashSet<>(); diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java Mon Mar 11 17:28:20 2013 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.snippets.SnippetTemplate.*; import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -58,6 +59,7 @@ @Snippet public static int f2i(@Parameter("input") float input, @Parameter("result") int result) { if (result == Integer.MIN_VALUE) { + probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { // input is NaN -> return 0 return 0; @@ -83,6 +85,7 @@ @Snippet public static long f2l(@Parameter("input") float input, @Parameter("result") long result) { if (result == Long.MIN_VALUE) { + probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { // input is NaN -> return 0 return 0; @@ -108,6 +111,7 @@ @Snippet public static int d2i(@Parameter("input") double input, @Parameter("result") int result) { if (result == Integer.MIN_VALUE) { + probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { // input is NaN -> return 0 return 0; @@ -133,6 +137,7 @@ @Snippet public static long d2l(@Parameter("input") double input, @Parameter("result") long result) { if (result == Long.MIN_VALUE) { + probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { // input is NaN -> return 0 return 0; diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Mar 11 17:28:20 2013 +0100 @@ -62,4 +62,13 @@ public static GraphBuilderConfiguration getSnippetDefault() { return new GraphBuilderConfiguration(true, true); } + + /** + * Returns {@code true} if it is an error for a class/field/method resolution to fail. + * The default is the same result as returned by {@link #eagerResolving()}. + * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}. + */ + public boolean unresolvedIsError() { + return eagerResolving; + } } diff -r 4ba3455566e0 -r 1c82ddf25b20 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 Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Mar 11 17:28:20 2013 +0100 @@ -114,6 +114,20 @@ private Block[] loopHeaders; + /** + * Gets the current frame state being processed by this builder. + */ + protected FrameStateBuilder getCurrentFrameState() { + return frameState; + } + + /** + * Gets the graph being processed by this builder. + */ + protected StructuredGraph getGraph() { + return currentGraph; + } + public GraphBuilderPhase(MetaAccessProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; @@ -261,6 +275,99 @@ return handler.catchTypeCPI() == 0; } + /** + * @param type the unresolved type of the constant + */ + protected void handleUnresolvedLoadConstant(JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); + } + + /** + * @param type the unresolved type of the type check + * @param object the object value whose type is being checked against {@code type} + */ + protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the unresolved type of the type check + * @param object the object value whose type is being checked against {@code type} + */ + protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { + BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); + DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)); + IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); + append(ifNode); + lastInstr = successor; + frameState.ipush(appendConstant(Constant.INT_0)); + } + + /** + * @param type the type being instantiated + */ + protected void handleUnresolvedNewInstance(JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the type of the array being instantiated + * @param length the length of the array + */ + protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the type being instantiated + * @param dims the dimensions for the multi-array + */ + protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param field the unresolved field + * @param receiver the object containing the field or {@code null} if {@code field} is static + */ + protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { + Kind kind = field.getKind(); + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + } + + /** + * @param field the unresolved field + * @param value the value being stored to the field + * @param receiver the object containing the field or {@code null} if {@code field} is static + */ + protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + } + + /** + * @param representation + * @param type + */ + protected void handleUnresolvedExceptionType(Representation representation, JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + } + + protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) { + boolean withReceiver = invokeKind != InvokeKind.Static; + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver)); + Kind kind = javaMethod.getSignature().getReturnKind(); + if (kind != Kind.Void) { + frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + } + } + private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); @@ -307,8 +414,7 @@ if (type instanceof ResolvedJavaType) { frameState.push(Kind.Object, append(ConstantNode.forConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass), runtime, currentGraph))); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); + handleUnresolvedLoadConstant(type); } } else if (con instanceof Constant) { Constant constant = (Constant) con; @@ -636,21 +742,21 @@ private JavaType lookupType(int cpi, int bytecode) { eagerResolvingForSnippets(cpi, bytecode); JavaType result = constantPool.lookupType(cpi, bytecode); - assert !graphBuilderConfig.eagerResolving() || result instanceof ResolvedJavaType; + assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType; return result; } private JavaMethod lookupMethod(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaMethod result = constantPool.lookupMethod(cpi, opcode); - assert !graphBuilderConfig.eagerResolving() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; + assert !graphBuilderConfig.unresolvedIsError() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; return result; } private JavaField lookupField(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaField result = constantPool.lookupField(cpi, opcode); - assert !graphBuilderConfig.eagerResolving() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; + assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; return result; } @@ -683,16 +789,13 @@ private void genCheckCast() { int cpi = stream().readCPI(); JavaType type = lookupType(cpi, CHECKCAST); - boolean initialized = type instanceof ResolvedJavaType; - if (initialized) { - ValueNode object = frameState.apop(); + ValueNode object = frameState.apop(); + if (type instanceof ResolvedJavaType) { CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) type, object, getProfileForTypeCheck((ResolvedJavaType) type))); append(checkCast); frameState.apush(checkCast); } else { - ValueNode object = frameState.apop(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedCheckCast(type, object); } } @@ -706,12 +809,7 @@ ConditionalNode conditional = currentGraph.unique(new ConditionalNode(currentGraph.unique(instanceOfNode), ConstantNode.forInt(1, currentGraph), ConstantNode.forInt(0, currentGraph))); frameState.ipush(append(conditional)); } else { - BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); - DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)); - IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); - append(ifNode); - lastInstr = successor; - frameState.ipush(appendConstant(Constant.INT_0)); + handleUnresolvedInstanceOf(type, object); } } @@ -721,8 +819,7 @@ NewInstanceNode n = currentGraph.add(new NewInstanceNode((ResolvedJavaType) type, true, false)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewInstance(type); } } @@ -772,8 +869,7 @@ NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true, false)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewObjectArray(type, length); } } @@ -789,8 +885,7 @@ FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((ResolvedJavaType) type, dims)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewMultiArray(type, dims); } } @@ -803,8 +898,7 @@ LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (ResolvedJavaField) field)); appendOptimizedLoadField(kind, load); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedLoadField(field, receiver); } } @@ -890,7 +984,7 @@ StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (ResolvedJavaField) field, value)); appendOptimizedStoreField(store); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedStoreField(field, value, receiver); } } @@ -905,8 +999,7 @@ appendOptimizedLoadField(kind, load); } } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedLoadField(field, null); } } @@ -916,15 +1009,15 @@ StoreFieldNode store = currentGraph.add(new StoreFieldNode(null, (ResolvedJavaField) field, value)); appendOptimizedStoreField(store); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedStoreField(field, value, null); } } - private ConstantNode genTypeOrDeopt(Representation representation, JavaType holder, boolean initialized) { + private ConstantNode genTypeOrDeopt(Representation representation, JavaType type, boolean initialized) { if (initialized) { - return appendConstant(((ResolvedJavaType) holder).getEncoding(representation)); + return appendConstant(((ResolvedJavaType) type).getEncoding(representation)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedExceptionType(representation, type); return null; } } @@ -944,13 +1037,13 @@ ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; ResolvedJavaType holder = resolvedTarget.getDeclaringClass(); if (!holder.isInitialized() && GraalOptions.ResolveClassBeforeStaticInvoke) { - genInvokeDeopt(target, false); + handleUnresolvedInvoke(target, InvokeKind.Static); } else { ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false)); appendInvoke(InvokeKind.Static, resolvedTarget, args); } } else { - genInvokeDeopt(target, false); + handleUnresolvedInvoke(target, InvokeKind.Static); } } @@ -959,7 +1052,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); genInvokeIndirect(InvokeKind.Interface, (ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); + handleUnresolvedInvoke(target, InvokeKind.Interface); } } @@ -968,7 +1061,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); + handleUnresolvedInvoke(target, InvokeKind.Virtual); } } @@ -980,16 +1073,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); invokeDirect((ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); - } - } - - private void genInvokeDeopt(JavaMethod unresolvedTarget, boolean withReceiver) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.popArguments(unresolvedTarget.getSignature().getParameterSlots(withReceiver), unresolvedTarget.getSignature().getParameterCount(withReceiver)); - Kind kind = unresolvedTarget.getSignature().getReturnKind(); - if (kind != Kind.Void) { - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedInvoke(target, InvokeKind.Special); } } @@ -1213,7 +1297,7 @@ } } - private ConstantNode appendConstant(Constant constant) { + protected ConstantNode appendConstant(Constant constant) { assert constant != null; return ConstantNode.forConstant(constant, runtime, currentGraph); } @@ -1224,7 +1308,7 @@ return fixed; } - private ValueNode append(FixedWithNextNode x) { + protected ValueNode append(FixedWithNextNode x) { return appendWithBCI(x); } @@ -1232,7 +1316,7 @@ return v; } - private ValueNode appendWithBCI(FixedWithNextNode x) { + protected ValueNode appendWithBCI(FixedWithNextNode x) { assert x.predecessor() == null : "instruction should not have been appended yet"; assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; lastInstr.setNext(x); diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Mar 11 17:28:20 2013 +0100 @@ -58,7 +58,7 @@ public static class Unary2Op extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; @Def({REG}) protected AllocatableValue result; - @Use({REG}) protected AllocatableValue x; + @Use({REG, STACK}) protected AllocatableValue x; public Unary2Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { this.opcode = opcode; @@ -455,6 +455,33 @@ case DSUB: masm.subsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; case DMUL: masm.mulsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; case DDIV: masm.divsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + + case I2B: masm.movsxb(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case I2S: masm.movsxw(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case I2L: masm.movslq(asLongReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case F2D: masm.cvtss2sd(asDoubleReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break; + case D2F: masm.cvtsd2ss(asFloatReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + case I2F: masm.cvtsi2ssl(asFloatReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case I2D: masm.cvtsi2sdl(asDoubleReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case L2F: masm.cvtsi2ssq(asFloatReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case L2D: masm.cvtsi2sdq(asDoubleReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case F2I: + masm.cvttss2sil(asIntReg(dst), (AMD64Address) tasm.asFloatAddr(src)); + break; + case D2I: + masm.cvttsd2sil(asIntReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); + break; + case F2L: + masm.cvttss2siq(asLongReg(dst), (AMD64Address) tasm.asFloatAddr(src)); + break; + case D2L: + masm.cvttsd2siq(asLongReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); + break; + case MOV_I2F: masm.movss(asFloatReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case MOV_L2D: masm.movsd(asDoubleReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case MOV_F2I: masm.movl(asIntReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break; + case MOV_D2L: masm.movq(asLongReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + default: throw GraalInternalError.shouldNotReachHere(); } } diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Mar 11 17:28:20 2013 +0100 @@ -63,7 +63,10 @@ // make sure that the displacement word of the call ends up word aligned int offset = masm.codeBuffer.position(); offset += tasm.target.arch.getMachineCodeCallDisplacementOffset(); - masm.nop(tasm.target.wordSize - offset % tasm.target.wordSize); + int modulus = tasm.target.wordSize; + if (offset % modulus != 0) { + masm.nop(modulus - offset % modulus); + } } } diff -r 4ba3455566e0 -r 1c82ddf25b20 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 Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Mon Mar 11 17:28:20 2013 +0100 @@ -22,11 +22,14 @@ */ package com.oracle.graal.lir; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; import java.util.Map.Entry; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; @@ -37,6 +40,8 @@ private static final Class VALUE_CLASS = Value.class; private static final Class CONSTANT_CLASS = Constant.class; + private static final Class REGISTER_VALUE_CLASS = RegisterValue.class; + private static final Class STACK_SLOT_CLASS = StackSlot.class; private static final Class VALUE_ARRAY_CLASS = Value[].class; public LIRIntrospection(Class clazz) { @@ -82,11 +87,15 @@ OperandModeAnnotation annotation = getOperandModeAnnotation(field); assert annotation != null : "Field must have operand mode annotation: " + field; annotation.scalarOffsets.add(offset); + EnumSet flags = getFlags(field); + assert verifyFlags(field, type, flags); annotation.flags.put(offset, getFlags(field)); } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) { OperandModeAnnotation annotation = getOperandModeAnnotation(field); assert annotation != null : "Field must have operand mode annotation: " + field; annotation.arrayOffsets.add(offset); + EnumSet flags = getFlags(field); + assert verifyFlags(field, type.getComponentType(), flags); annotation.flags.put(offset, getFlags(field)); } else { assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; @@ -94,6 +103,19 @@ dataOffsets.add(offset); } } + + private static boolean verifyFlags(Field field, Class type, EnumSet flags) { + if (flags.contains(REG)) { + assert type.isAssignableFrom(REGISTER_VALUE_CLASS) : "Cannot assign RegisterValue to field with REG flag:" + field; + } + if (flags.contains(STACK)) { + assert type.isAssignableFrom(STACK_SLOT_CLASS) : "Cannot assign StackSlot to field with STACK flag:" + field; + } + if (flags.contains(CONST)) { + assert type.isAssignableFrom(CONSTANT_CLASS) : "Cannot assign Constant to field with CONST flag:" + field; + } + return true; + } } protected static void forEach(Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, ValueProcedure proc) { diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Mon Mar 11 17:28:20 2013 +0100 @@ -29,10 +29,14 @@ /** * Marks a position in the graph where a safepoint should be emitted. */ -public final class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType { +public class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType { public SafepointNode() { - super(StampFactory.forVoid()); + this(StampFactory.forVoid()); + } + + public SafepointNode(Stamp stamp) { + super(stamp); } @Override diff -r 4ba3455566e0 -r 1c82ddf25b20 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Mar 11 17:28:20 2013 +0100 @@ -53,6 +53,9 @@ if (kind() != Kind.Object || object().kind() != Kind.Object) { return false; } + if (stamp() == StampFactory.forNodeIntrinsic()) { + return false; + } if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) { // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull // guard, but the diff -r 4ba3455566e0 -r 1c82ddf25b20 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 Mon Mar 11 17:28:03 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Mar 11 17:28:20 2013 +0100 @@ -53,10 +53,10 @@ */ public class SnippetInstaller { - private final MetaAccessProvider runtime; - private final TargetDescription target; - private final Assumptions assumptions; - private final BoxingMethodPool pool; + protected final MetaAccessProvider runtime; + protected final TargetDescription target; + protected final Assumptions assumptions; + protected final BoxingMethodPool pool; private final Thread owner; /** @@ -191,6 +191,19 @@ } } + /** + * Does final processing of a snippet graph. + */ + protected void finalizeGraph(ResolvedJavaMethod method, StructuredGraph graph) { + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph); + + new SnippetFrameStateCleanupPhase().apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + new InsertStateAfterPlaceholderPhase().apply(graph); + } + public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { return Debug.scope("BuildSnippetGraph", new Object[]{method}, new Callable() { @@ -198,13 +211,7 @@ public StructuredGraph call() throws Exception { StructuredGraph graph = parseGraph(method, policy); - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); - assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph); - - new SnippetFrameStateCleanupPhase().apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - new InsertStateAfterPlaceholderPhase().apply(graph); + finalizeGraph(method, graph); Debug.dump(graph, "%s: Final", method.getName()); @@ -222,8 +229,10 @@ return graph; } - private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { - assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method; + /** + * Builds the initial graph for a snippet. + */ + protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod method) { final StructuredGraph graph = new StructuredGraph(method); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE); @@ -232,9 +241,42 @@ Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName()); new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + return graph; + } + + /** + * Called after a graph is inlined. + * + * @param caller the graph into which {@code callee} was inlined + * @param callee the graph that was inlined into {@code caller} + */ + protected void afterInline(StructuredGraph caller, StructuredGraph callee) { + if (GraalOptions.OptCanonicalizer) { + new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller); + new CanonicalizerPhase(runtime, assumptions).apply(caller); + } + } + + /** + * Called after all inlining for a given graph is complete. + */ + protected void afterInlining(StructuredGraph graph) { new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); + + new DeadCodeEliminationPhase().apply(graph); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(runtime, assumptions).apply(graph); + } + } + + private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { + assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method; + final StructuredGraph graph = buildInitialGraph(method); + for (Invoke invoke : graph.getInvokes()) { MethodCallTargetNode callTarget = invoke.methodCallTarget(); ResolvedJavaMethod callee = callTarget.targetMethod(); @@ -244,31 +286,19 @@ InliningUtil.inline(invoke, originalGraph, true); Debug.dump(graph, "after inlining %s", callee); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInline(graph, originalGraph); substituteCallsOriginal = true; } else { if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) { StructuredGraph targetGraph = parseGraph(callee, policy); InliningUtil.inline(invoke, targetGraph, true); Debug.dump(graph, "after inlining %s", callee); - if (GraalOptions.OptCanonicalizer) { - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInline(graph, targetGraph); } } } - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); - - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - - new DeadCodeEliminationPhase().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInlining(graph); for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { end.disableSafepoint(); diff -r 4ba3455566e0 -r 1c82ddf25b20 mx/projects --- a/mx/projects Mon Mar 11 17:28:03 2013 +0100 +++ b/mx/projects Mon Mar 11 17:28:20 2013 +0100 @@ -238,6 +238,13 @@ project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.amd64@javaCompliance=1.7 +# graal.compiler.amd64.test +project@com.oracle.graal.compiler.amd64.test@subDir=graal +project@com.oracle.graal.compiler.amd64.test@sourceDirs=src +project@com.oracle.graal.compiler.amd64.test@dependencies=com.oracle.graal.compiler.test +project@com.oracle.graal.compiler.amd64.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.compiler.amd64.test@javaCompliance=1.7 + # graal.compiler.ptx project@com.oracle.graal.compiler.ptx@subDir=graal project@com.oracle.graal.compiler.ptx@sourceDirs=src diff -r 4ba3455566e0 -r 1c82ddf25b20 mxtool/mx.py --- a/mxtool/mx.py Mon Mar 11 17:28:03 2013 +0100 +++ b/mxtool/mx.py Mon Mar 11 17:28:20 2013 +0100 @@ -2337,6 +2337,14 @@ out.open('project', {'name' : p.name, 'default' : 'default', 'basedir' : '.'}) out.element('description', data='Builds, tests, and runs the project ' + p.name + '.') out.element('import', {'file' : 'nbproject/build-impl.xml'}) + out.open('target', {'name' : '-post-compile'}) + out.open('exec', { 'executable' : sys.executable}) + out.element('env', {'key' : 'JAVA_HOME', 'value' : java().jdk}) + out.element('arg', {'value' : os.path.abspath(__file__)}) + out.element('arg', {'value' : 'archive'}) + out.element('arg', {'value' : '@GRAAL'}) + out.close('exec') + out.close('target') out.close('project') updated = update_file(join(p.dir, 'build.xml'), out.xml(indent='\t', newl='\n')) or updated