OpenJDK / graal / graal-jvmci-8
changeset 8185:3bbdf34536bc
Merge.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sun, 10 Mar 2013 19:51:32 +0100 |
parents | d982f1469cba 4b11a0983557 |
children | bf1c9ae73775 |
files | graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64Address.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTXAddress.java |
diffstat | 50 files changed, 1470 insertions(+), 848 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Sun Mar 10 19:51:32 2013 +0100 @@ -24,12 +24,11 @@ import static com.oracle.graal.api.code.MemoryBarriers.*; import static com.oracle.graal.api.code.Register.RegisterFlag.*; -import static com.oracle.graal.api.meta.Kind.*; import java.nio.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.code.Register.RegisterFlag; /** * Represents the AMD64 architecture. @@ -106,8 +105,6 @@ rip }; - public static final RegisterValue RSP = rsp.asValue(Long); - public AMD64() { super("AMD64", 8,
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64Address.java Sun Mar 10 19:51:18 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2010, 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.amd64; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; - -/** - * Represents an address in target machine memory, specified via some combination of a base - * register, an index register, a displacement and a scale. Note that the base and index registers - * may be a variable that will get a register assigned later by the register allocator. - */ -public final class AMD64Address extends Address { - - private static final long serialVersionUID = -4101548147426595051L; - - private final Value[] baseIndex; - private final Scale scale; - private final int displacement; - - /** - * Creates an {@link AMD64Address} with given base register, no scaling and no displacement. - * - * @param kind the kind of the value being addressed - * @param base the base register - */ - public AMD64Address(Kind kind, Value base) { - this(kind, base, ILLEGAL, Scale.Times1, 0); - } - - /** - * Creates an {@link AMD64Address} with given base register, no scaling and a given - * displacement. - * - * @param kind the kind of the value being addressed - * @param base the base register - * @param displacement the displacement - */ - public AMD64Address(Kind kind, Value base, int displacement) { - this(kind, base, ILLEGAL, Scale.Times1, displacement); - } - - /** - * Creates an {@link AMD64Address} with given base and index registers, scaling and - * displacement. This is the most general constructor. - * - * @param kind the kind of the value being addressed - * @param base the base register - * @param index the index register - * @param scale the scaling factor - * @param displacement the displacement - */ - public AMD64Address(Kind kind, Value base, Value index, Scale scale, int displacement) { - super(kind); - this.baseIndex = new Value[2]; - this.setBase(base); - this.setIndex(index); - this.scale = scale; - this.displacement = displacement; - - assert !isConstant(base) && !isStackSlot(base); - assert !isConstant(index) && !isStackSlot(index); - } - - /** - * A scaling factor used in the SIB addressing mode. - */ - public enum Scale { - Times1(1, 0), Times2(2, 1), Times4(4, 2), Times8(8, 3); - - private Scale(int value, int log2) { - this.value = value; - this.log2 = log2; - } - - /** - * The value (or multiplier) of this scale. - */ - public final int value; - - /** - * The {@linkplain #value value} of this scale log 2. - */ - public final int log2; - - public static Scale fromInt(int scale) { - switch (scale) { - case 1: - return Times1; - case 2: - return Times2; - case 4: - return Times4; - case 8: - return Times8; - default: - throw new IllegalArgumentException(String.valueOf(scale)); - } - } - } - - @Override - public Value[] components() { - return baseIndex; - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - s.append(getKind().getJavaName()).append("["); - String sep = ""; - if (isLegal(getBase())) { - s.append(getBase()); - sep = " + "; - } - if (isLegal(getIndex())) { - s.append(sep).append(getIndex()).append(" * ").append(getScale().value); - sep = " + "; - } - if (getDisplacement() < 0) { - s.append(" - ").append(-getDisplacement()); - } else if (getDisplacement() > 0) { - s.append(sep).append(getDisplacement()); - } - s.append("]"); - return s.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof AMD64Address) { - AMD64Address addr = (AMD64Address) obj; - return getKind() == addr.getKind() && getDisplacement() == addr.getDisplacement() && getBase().equals(addr.getBase()) && getScale() == addr.getScale() && - getIndex().equals(addr.getIndex()); - } - return false; - } - - @Override - public int hashCode() { - return getBase().hashCode() ^ getIndex().hashCode() ^ (getDisplacement() << 4) ^ (getScale().value << 8) ^ (getKind().ordinal() << 12); - } - - /** - * @return Base register that defines the start of the address computation. If not present, is - * denoted by {@link Value#ILLEGAL}. - */ - public Value getBase() { - return baseIndex[0]; - } - - public void setBase(Value base) { - this.baseIndex[0] = base; - } - - /** - * @return Index register, the value of which (possibly scaled by {@link #scale}) is added to - * {@link #getBase}. If not present, is denoted by {@link Value#ILLEGAL}. - */ - public Value getIndex() { - return baseIndex[1]; - } - - public void setIndex(Value index) { - this.baseIndex[1] = index; - } - - /** - * @return Scaling factor for indexing, dependent on target operand size. - */ - public Scale getScale() { - return scale; - } - - /** - * @return Optional additive displacement. - */ - public int getDisplacement() { - return displacement; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/AbstractAddress.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,29 @@ +/* + * 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.api.code; + +/** + * Abstract base class that represents a platform specific address. + */ +public abstract class AbstractAddress { +}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java Sun Mar 10 19:51:18 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2010, 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.api.code; - -import com.oracle.graal.api.meta.*; - -/** - * Base class to represent an address in target machine memory. The concrete representation of the - * address is platform dependent. - */ -public abstract class Address extends Value { - - private static final long serialVersionUID = -1003772042519945089L; - - public Address(Kind kind) { - super(kind); - } - - /** - * The values that this address is composed of. Used by the register allocator to manipulate - * addresses in a platform independent way. - */ - public abstract Value[] components(); -}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Sun Mar 10 19:51:32 2013 +0100 @@ -78,16 +78,6 @@ return (StackSlot) value; } - public static boolean isAddress(Value value) { - assert value != null; - return value instanceof Address; - } - - public static Address asAddress(Value value) { - assert value != null; - return (Address) value; - } - public static boolean isRegister(Value value) { assert value != null; return value instanceof RegisterValue;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2010, 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.asm.amd64; + +import com.oracle.graal.api.code.*; + +/** + * Represents an address in target machine memory, specified via some combination of a base + * register, an index register, a displacement and a scale. Note that the base and index registers + * may be a variable that will get a register assigned later by the register allocator. + */ +public final class AMD64Address extends AbstractAddress { + + private final Register base; + private final Register index; + private final Scale scale; + private final int displacement; + + /** + * Creates an {@link AMD64Address} with given base register, no scaling and no displacement. + * + * @param base the base register + */ + public AMD64Address(Register base) { + this(base, Register.None, Scale.Times1, 0); + } + + /** + * Creates an {@link AMD64Address} with given base register, no scaling and a given + * displacement. + * + * @param base the base register + * @param displacement the displacement + */ + public AMD64Address(Register base, int displacement) { + this(base, Register.None, Scale.Times1, displacement); + } + + /** + * Creates an {@link AMD64Address} with given base and index registers, scaling and + * displacement. This is the most general constructor. + * + * @param base the base register + * @param index the index register + * @param scale the scaling factor + * @param displacement the displacement + */ + public AMD64Address(Register base, Register index, Scale scale, int displacement) { + this.base = base; + this.index = index; + this.scale = scale; + this.displacement = displacement; + } + + /** + * A scaling factor used in the SIB addressing mode. + */ + public enum Scale { + Times1(1, 0), Times2(2, 1), Times4(4, 2), Times8(8, 3); + + private Scale(int value, int log2) { + this.value = value; + this.log2 = log2; + } + + /** + * The value (or multiplier) of this scale. + */ + public final int value; + + /** + * The {@linkplain #value value} of this scale log 2. + */ + public final int log2; + + public static Scale fromInt(int scale) { + switch (scale) { + case 1: + return Times1; + case 2: + return Times2; + case 4: + return Times4; + case 8: + return Times8; + default: + throw new IllegalArgumentException(String.valueOf(scale)); + } + } + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("["); + String sep = ""; + if (getBase() != Register.None) { + s.append(getBase()); + sep = " + "; + } + if (getIndex() != Register.None) { + s.append(sep).append(getIndex()).append(" * ").append(getScale().value); + sep = " + "; + } + if (getDisplacement() < 0) { + s.append(" - ").append(-getDisplacement()); + } else if (getDisplacement() > 0) { + s.append(sep).append(getDisplacement()); + } + s.append("]"); + return s.toString(); + } + + /** + * @return Base register that defines the start of the address computation. If not present, is + * denoted by {@link Register#None}. + */ + public Register getBase() { + return base; + } + + /** + * @return Index register, the value of which (possibly scaled by {@link #getScale}) is added to + * {@link #getBase}. If not present, is denoted by {@link Register#None}. + */ + public Register getIndex() { + return index; + } + + /** + * @return Scaling factor for indexing, dependent on target operand size. + */ + public Scale getScale() { + return scale; + } + + /** + * @return Optional additive displacement. + */ + public int getDisplacement() { + return displacement; + } +}
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Sun Mar 10 19:51:32 2013 +0100 @@ -24,13 +24,11 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.asm.NumUtil.*; import static com.oracle.graal.asm.amd64.AMD64AsmOptions.*; import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; /** @@ -38,19 +36,13 @@ */ public class AMD64Assembler extends AbstractAssembler { - /** - * The kind for pointers and raw registers. Since we know we are 64 bit here, we can hardcode - * it. - */ - private static final Kind Word = Kind.Long; - private static final int MinEncodingNeedsRex = 8; /** * A sentinel value used as a place holder in an instruction stream for an address that will be * patched. */ - private static final AMD64Address Placeholder = new AMD64Address(Kind.Illegal, rip.asValue()); + private static final AMD64Address Placeholder = new AMD64Address(rip); /** * The x86 condition codes used for conditional jumps/moves. @@ -232,8 +224,8 @@ assert (reg & 0x07) == reg; int regenc = reg << 3; - Register base = isLegal(addr.getBase()) ? asRegister(addr.getBase()) : Register.None; - Register index = isLegal(addr.getIndex()) ? asRegister(addr.getIndex()) : Register.None; + Register base = addr.getBase(); + Register index = addr.getIndex(); AMD64Address.Scale scale = addr.getScale(); int disp = addr.getDisplacement(); @@ -1784,8 +1776,8 @@ } } - private static boolean needsRex(Value value) { - return isRegister(value) && asRegister(value).encoding >= MinEncodingNeedsRex; + private static boolean needsRex(Register reg) { + return reg.encoding >= MinEncodingNeedsRex; } private void prefix(AMD64Address adr) { @@ -2252,7 +2244,7 @@ // the code where this idiom is used, in particular the // orderAccess code. lock(); - addl(new AMD64Address(Word, RSP, 0), 0); // Assert the lock# signal here + addl(new AMD64Address(rsp, 0), 0); // Assert the lock# signal here } } } @@ -2293,7 +2285,7 @@ } public void nullCheck(Register r) { - testl(AMD64.rax, new AMD64Address(Word, r.asValue(Word), 0)); + testl(AMD64.rax, new AMD64Address(r, 0)); } @Override @@ -2374,8 +2366,8 @@ } @Override - public AMD64Address makeAddress(Kind kind, Value base, int displacement) { - return new AMD64Address(kind, base, displacement); + public AMD64Address makeAddress(Register base, int displacement) { + return new AMD64Address(base, displacement); } @Override
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Sun Mar 10 19:51:32 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; /** * This class implements commonly used X86 code patterns. @@ -222,7 +221,7 @@ * volatile field! */ public final void movlong(AMD64Address dst, long src) { - AMD64Address high = new AMD64Address(dst.getKind(), dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4); + AMD64Address high = new AMD64Address(dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4); movl(dst, (int) (src & 0xFFFFFFFF)); movl(high, (int) (src >> 32)); } @@ -230,7 +229,7 @@ public final void flog(Register dest, Register value, boolean base10) { assert dest.isFpu() && value.isFpu(); - AMD64Address tmp = new AMD64Address(Kind.Double, AMD64.RSP); + AMD64Address tmp = new AMD64Address(AMD64.rsp); if (base10) { fldlg2(); } else { @@ -264,7 +263,7 @@ private AMD64Address trigPrologue(Register value) { assert value.isFpu(); - AMD64Address tmp = new AMD64Address(Kind.Double, AMD64.RSP); + AMD64Address tmp = new AMD64Address(AMD64.rsp); subq(AMD64.rsp, 8); movsd(tmp, value); fld(tmp); @@ -286,18 +285,16 @@ * @param frameToCSA offset from the frame pointer to the CSA */ public final void save(CalleeSaveLayout csl, int frameToCSA) { - RegisterValue frame = frameRegister.asValue(); for (Register r : csl.registers) { int offset = csl.offsetOf(r); - movq(new AMD64Address(target.wordKind, frame, frameToCSA + offset), r); + movq(new AMD64Address(frameRegister, frameToCSA + offset), r); } } public final void restore(CalleeSaveLayout csl, int frameToCSA) { - RegisterValue frame = frameRegister.asValue(); for (Register r : csl.registers) { int offset = csl.offsetOf(r); - movq(r, new AMD64Address(target.wordKind, frame, frameToCSA + offset)); + movq(r, new AMD64Address(frameRegister, frameToCSA + offset)); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAddress.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,72 @@ +/* + * 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.asm.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +/** + * Represents an address in target machine memory, specified via some combination of a base register + * and a displacement. + */ +public final class PTXAddress extends AbstractAddress { + + private final Register base; + private final long displacement; + + /** + * Creates an {@link PTXAddress} with given base register and no displacement. + * + * @param base the base register + */ + public PTXAddress(Register base) { + this(base, 0); + } + + /** + * Creates an {@link PTXAddress} with given base register and a displacement. This is the most + * general constructor. + * + * @param base the base register + * @param displacement the displacement + */ + public PTXAddress(Register base, long displacement) { + this.base = base; + this.displacement = displacement; + } + + /** + * @return Base register that defines the start of the address computation. If not present, is + * denoted by {@link Value#ILLEGAL}. + */ + public Register getBase() { + return base; + } + + /** + * @return Optional additive displacement. + */ + public long getDisplacement() { + return displacement; + } +}
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Sun Mar 10 19:51:32 2013 +0100 @@ -23,8 +23,6 @@ package com.oracle.graal.asm.ptx; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.ptx.*; public class PTXAssembler extends AbstractPTXAssembler { @@ -177,7 +175,7 @@ emitString("exit;" + " " + ""); } - public final void ld_global_b8(Register d, Register a, int immOff) { + public final void ld_global_b8(Register d, Register a, long immOff) { emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); } @@ -742,8 +740,8 @@ } @Override - public PTXAddress makeAddress(Kind kind, Value base, int displacement) { - return new PTXAddress(kind, base, displacement); + public PTXAddress makeAddress(Register base, int displacement) { + return new PTXAddress(base, displacement); } @Override
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Sun Mar 10 19:51:32 2013 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.asm.sparc; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.sparc.*; @@ -55,13 +54,13 @@ } @Override - public Address makeAddress(Kind kind, Value base, int displacement) { + public AbstractAddress makeAddress(Register base, int displacement) { // SPARC: Implement address calculation. return null; } @Override - public Address getPlaceholder() { + public AbstractAddress getPlaceholder() { // SPARC: Implement address patching. return null; }
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Sun Mar 10 19:51:32 2013 +0100 @@ -25,7 +25,6 @@ import java.nio.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; /** * The platform-independent base class for the assembler. @@ -87,12 +86,12 @@ /** * This is used by the TargetMethodAssembler to convert a {@link StackSlot} to an - * {@link Address}. + * {@link AbstractAddress}. */ - public abstract Address makeAddress(Kind kind, Value base, int displacement); + public abstract AbstractAddress makeAddress(Register base, int displacement); /** * Returns a target specific placeholder address that can be used for code patching. */ - public abstract Address getPlaceholder(); + public abstract AbstractAddress getPlaceholder(); }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Sun Mar 10 19:51:32 2013 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; @@ -158,56 +159,64 @@ append(createMove(dst, src)); } - private AMD64Address prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { - Value baseRegister = base; + private AMD64AddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + AllocatableValue baseRegister; int finalDisp = displacement; if (isConstant(base)) { if (asConstant(base).isNull()) { - baseRegister = Value.ILLEGAL; + baseRegister = AllocatableValue.UNUSED; } else if (asConstant(base).getKind() != Kind.Object) { long newDisplacement = displacement + asConstant(base).asLong(); if (NumUtil.isInt(newDisplacement)) { assert !runtime.needsDataPatch(asConstant(base)); finalDisp = (int) newDisplacement; - baseRegister = Value.ILLEGAL; + baseRegister = AllocatableValue.UNUSED; } else { - Value newBase = newVariable(Kind.Long); + Variable newBase = newVariable(Kind.Long); emitMove(newBase, base); baseRegister = newBase; } + } else { + baseRegister = load(base); } + } else if (base == Value.ILLEGAL) { + baseRegister = AllocatableValue.UNUSED; + } else { + baseRegister = asAllocatable(base); } - Value indexRegister = index; - AMD64Address.Scale scaleEnum; - if (index != Value.ILLEGAL && scale > 0) { - scaleEnum = AMD64Address.Scale.fromInt(scale); + AllocatableValue indexRegister; + Scale scaleEnum; + if (index != Value.ILLEGAL && scale != 0) { + scaleEnum = Scale.fromInt(scale); if (isConstant(index)) { long newDisplacement = finalDisp + asConstant(index).asLong() * scale; // only use the constant index if the resulting displacement fits into a 32 bit // offset if (NumUtil.isInt(newDisplacement)) { finalDisp = (int) newDisplacement; - indexRegister = Value.ILLEGAL; + indexRegister = AllocatableValue.UNUSED; } else { // create a temporary variable for the index, the pointer load cannot handle a // constant index - Value newIndex = newVariable(Kind.Long); + Variable newIndex = newVariable(Kind.Long); emitMove(newIndex, index); indexRegister = newIndex; } + } else { + indexRegister = asAllocatable(index); } } else { - indexRegister = Value.ILLEGAL; - scaleEnum = AMD64Address.Scale.Times1; + indexRegister = AllocatableValue.UNUSED; + scaleEnum = Scale.Times1; } - return new AMD64Address(kind, baseRegister, indexRegister, scaleEnum, finalDisp); + return new AMD64AddressValue(kind, baseRegister, indexRegister, scaleEnum, finalDisp); } @Override public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) { - AMD64Address loadAddress = prepareAddress(kind, base, displacement, index, scale); + AMD64AddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, canTrap ? state() : null)); return result; @@ -215,7 +224,7 @@ @Override public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) { - AMD64Address storeAddress = prepareAddress(kind, base, displacement, index, scale); + AMD64AddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); LIRFrameState state = canTrap ? state() : null; if (isConstant(inputVal)) { @@ -233,7 +242,7 @@ @Override public Variable emitLea(Value base, int displacement, Value index, int scale) { Variable result = newVariable(target().wordKind); - AMD64Address address = prepareAddress(result.getKind(), base, displacement, index, scale); + AMD64AddressValue address = prepareAddress(result.getKind(), base, displacement, index, scale); append(new LeaOp(result, address)); return result; } @@ -922,15 +931,15 @@ Value expected = loadNonConst(operand(node.expected())); Variable newValue = load(operand(node.newValue())); - AMD64Address address; + AMD64AddressValue address; int displacement = node.displacement(); Value index = operand(node.offset()); if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) { assert !runtime.needsDataPatch(asConstant(index)); displacement += (int) asConstant(index).asLong(); - address = new AMD64Address(kind, load(operand(node.object())), displacement); + address = new AMD64AddressValue(kind, load(operand(node.object())), displacement); } else { - address = new AMD64Address(kind, load(operand(node.object())), load(index), AMD64Address.Scale.Times1, displacement); + address = new AMD64AddressValue(kind, load(operand(node.object())), load(index), Scale.Times1, displacement); } RegisterValue rax = AMD64.rax.asValue(kind);
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Sun Mar 10 19:51:32 2013 +0100 @@ -36,11 +36,11 @@ import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.ptx.*; import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp; -import com.oracle.graal.lir.ptx.*; import com.oracle.graal.lir.ptx.PTXCompare.CompareOp; import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp; import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp; @@ -51,7 +51,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.ptx.*; /** * This class implements the PTX specific portion of the LIR generator. @@ -114,40 +113,49 @@ } } - private PTXAddress prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { - Value baseRegister = base; + private PTXAddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + AllocatableValue baseRegister; long finalDisp = displacement; if (isConstant(base)) { if (asConstant(base).isNull()) { - baseRegister = Value.ILLEGAL; + baseRegister = AllocatableValue.UNUSED; } else if (asConstant(base).getKind() != Kind.Object) { finalDisp += asConstant(base).asLong(); - baseRegister = Value.ILLEGAL; + baseRegister = AllocatableValue.UNUSED; + } else { + baseRegister = load(base); } + } else if (base == Value.ILLEGAL) { + baseRegister = AllocatableValue.UNUSED; + } else { + baseRegister = asAllocatable(base); } if (index != Value.ILLEGAL) { if (isConstant(index)) { finalDisp += asConstant(index).asLong() * scale; } else { - Value indexRegister = index; + Value indexRegister; if (scale != 1) { indexRegister = emitMul(index, Constant.forInt(scale)); + } else { + indexRegister = index; } - if (baseRegister == Value.ILLEGAL) { - baseRegister = indexRegister; + + if (baseRegister == AllocatableValue.UNUSED) { + baseRegister = asAllocatable(indexRegister); } else { baseRegister = emitAdd(baseRegister, indexRegister); } } } - return new PTXAddress(kind, baseRegister, finalDisp); + return new PTXAddressValue(kind, baseRegister, finalDisp); } @Override public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) { - PTXAddress loadAddress = prepareAddress(kind, base, displacement, index, scale); + PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, canTrap ? state() : null)); return result; @@ -155,7 +163,7 @@ @Override public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) { - PTXAddress storeAddress = prepareAddress(kind, base, displacement, index, scale); + PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); Variable input = load(inputVal); append(new StoreOp(storeAddress, input, canTrap ? state() : null)); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Sun Mar 10 19:51:32 2013 +0100 @@ -348,7 +348,7 @@ final int id = compilationId++; - InstalledCode installedCode = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true), new Callable<InstalledCode>() { + InstalledCode installedCode = Debug.scope("Compiling", new Object[]{runtime, new DebugDumpScope(String.valueOf(id), true)}, new Callable<InstalledCode>() { public InstalledCode call() throws Exception { final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Sun Mar 10 19:51:32 2013 +0100 @@ -417,8 +417,8 @@ public final int operandNumber; /** - * The {@linkplain RegisterValue register}, {@linkplain StackSlot spill slot} or - * {@linkplain Address address} assigned to this interval. + * The {@linkplain RegisterValue register} or {@linkplain StackSlot spill slot} assigned to this + * interval. */ private Value location; @@ -515,8 +515,8 @@ } /** - * Gets the {@linkplain RegisterValue register}, {@linkplain StackSlot spill slot} or - * {@linkplain Address address} assigned to this interval. + * Gets the {@linkplain RegisterValue register} or {@linkplain StackSlot spill slot} assigned to + * this interval. */ public Value location() { return location;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Sun Mar 10 19:51:32 2013 +0100 @@ -192,10 +192,10 @@ // Traverse assignment graph in depth first order and generate moves in post order // ie. two assignments: b := c, a := b start with node c: - // Call graph: move(NULL, c) -> move(c, b) -> move(b, a) + // Call graph: move(c, NULL) -> move(b, c) -> move(a, b) // Generates moves in this order: move b to a and move c to b // ie. cycle a := b, b := a start with node a - // Call graph: move(NULL, a) -> move(a, b) -> move(b, a) + // Call graph: move(a, NULL) -> move(b, a) -> move(a, b) // Generates moves in this order: move b to temp, move a to b, move temp to a private void move(PhiResolverNode dest, PhiResolverNode src) { if (!dest.visited) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Sun Mar 10 19:51:32 2013 +0100 @@ -32,11 +32,12 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCallTarget.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.*; @@ -128,14 +129,14 @@ Variable newVal = load(operand(x.newValue())); int disp = 0; - AMD64Address address; + AMD64AddressValue address; Value index = operand(x.offset()); if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) { assert !runtime.needsDataPatch(asConstant(index)); disp += (int) ValueUtil.asConstant(index).asLong(); - address = new AMD64Address(kind, load(operand(x.object())), disp); + address = new AMD64AddressValue(kind, load(operand(x.object())), disp); } else { - address = new AMD64Address(kind, load(operand(x.object())), load(index), AMD64Address.Scale.Times1, disp); + address = new AMD64AddressValue(kind, load(operand(x.object())), load(index), Scale.Times1, disp); } RegisterValue rax = AMD64.rax.asValue(kind); @@ -203,7 +204,7 @@ disp -= frameSize; } tasm.blockComment("[stack overflow check]"); - asm.movq(new AMD64Address(asm.target.wordKind, AMD64.RSP, -disp), AMD64.rax); + asm.movq(new AMD64Address(rsp, -disp), AMD64.rax); } } } @@ -223,7 +224,7 @@ if (GraalOptions.ZapStackOnMethodEntry) { final int intSize = 4; for (int i = 0; i < frameSize / intSize; ++i) { - asm.movl(new AMD64Address(Kind.Int, rsp.asValue(), i * intSize), 0xC1C1C1C1); + asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1); } } CalleeSaveLayout csl = frameMap.registerConfig.getCalleeSaveLayout(); @@ -287,7 +288,7 @@ Register inlineCacheKlass = rax; // see definition of IC_Klass in // c1_LIRAssembler_x86.cpp Register receiver = asRegister(cc.getArgument(0)); - AMD64Address src = new AMD64Address(target.wordKind, receiver.asValue(), config.hubOffset); + AMD64Address src = new AMD64Address(receiver, config.hubOffset); asm.cmpq(inlineCacheKlass, src); asm.jcc(ConditionFlag.NotEqual, unverifiedStub);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Sun Mar 10 19:51:32 2013 +0100 @@ -43,8 +43,14 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.amd64.snippets.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.snippets.*; public class AMD64HotSpotRuntime extends HotSpotRuntime { @@ -186,6 +192,24 @@ } + private AMD64ConvertSnippets.Templates convertSnippets; + + @Override + public void installSnippets(Backend backend, SnippetInstaller installer, Assumptions assumptions) { + installer.installSnippets(AMD64ConvertSnippets.class); + convertSnippets = new AMD64ConvertSnippets.Templates(this, assumptions, graalRuntime.getTarget()); + super.installSnippets(backend, installer, assumptions); + } + + @Override + public void lower(Node n, LoweringTool tool) { + if (n instanceof ConvertNode) { + convertSnippets.lower((ConvertNode) n, tool); + } else { + super.lower(n, tool); + } + } + @Override public Register threadRegister() { return r15;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Sun Mar 10 19:51:32 2013 +0100 @@ -26,7 +26,6 @@ import static com.oracle.graal.phases.GraalOptions.*; import sun.misc.*; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; @@ -65,13 +64,13 @@ asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset); tasm.recordMark(Marks.MARK_POLL_FAR); tasm.recordSafepoint(pos, state); - asm.movq(scratch.getRegister(), new AMD64Address(tasm.target.wordKind, scratch)); + asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister())); } else { tasm.recordMark(Marks.MARK_POLL_NEAR); tasm.recordSafepoint(pos, state); // The C++ code transforms the polling page offset into an RIP displacement // to the real address at that offset in the polling page. - asm.movq(scratch.getRegister(), new AMD64Address(tasm.target.wordKind, rip.asValue(), offset)); + asm.movq(scratch.getRegister(), new AMD64Address(rip, offset)); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,191 @@ +/* + * 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.hotspot.amd64.snippets; + +import static com.oracle.graal.snippets.SnippetTemplate.*; +import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.ConvertNode.Op; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.Snippet.Parameter; +import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.snippets.SnippetTemplate.Arguments; +import com.oracle.graal.snippets.SnippetTemplate.Key; + +/** + * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match + * the semantics of the JVM specification. + */ +public class AMD64ConvertSnippets implements SnippetsInterface { + + /** + * Converts a float to an int. + * <p> + * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the + * conversion. If the float value is a NaN, infinity or if the result of the conversion is + * larger than {@link Integer#MAX_VALUE} then CVTTSS2SI returns {@link Integer#MIN_VALUE} and + * extra tests are required on the float value to return the correct int value. + * + * @param input the float being converted + * @param result the result produced by the CVTTSS2SI instruction + */ + @Snippet + public static int f2i(@Parameter("input") float input, @Parameter("result") int result) { + if (result == Integer.MIN_VALUE) { + if (Float.isNaN(input)) { + // input is NaN -> return 0 + return 0; + } else if (input > 0.0f) { + // input is > 0 -> return max int + return Integer.MAX_VALUE; + } + } + return result; + } + + /** + * Converts a float to a long. + * <p> + * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the + * conversion. If the float value is a NaN or infinity then CVTTSS2SI returns + * {@link Long#MIN_VALUE} and extra tests are required on the float value to return the correct + * long value. + * + * @param input the float being converted + * @param result the result produced by the CVTTSS2SI instruction + */ + @Snippet + public static long f2l(@Parameter("input") float input, @Parameter("result") long result) { + if (result == Long.MIN_VALUE) { + if (Float.isNaN(input)) { + // input is NaN -> return 0 + return 0; + } else if (input > 0.0f) { + // input is > 0 -> return max int + return Long.MAX_VALUE; + } + } + return result; + } + + /** + * Converts a double to an int. + * <p> + * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the + * conversion. If the double value is a NaN, infinity or if the result of the conversion is + * larger than {@link Integer#MAX_VALUE} then CVTTSD2SI returns {@link Integer#MIN_VALUE} and + * extra tests are required on the double value to return the correct int value. + * + * @param input the double being converted + * @param result the result produced by the CVTTSS2SI instruction + */ + @Snippet + public static int d2i(@Parameter("input") double input, @Parameter("result") int result) { + if (result == Integer.MIN_VALUE) { + if (Double.isNaN(input)) { + // input is NaN -> return 0 + return 0; + } else if (input > 0.0d) { + // input is positive -> return maxInt + return Integer.MAX_VALUE; + } + } + return result; + } + + /** + * Converts a double to a long. + * <p> + * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the + * conversion. If the double value is a NaN, infinity or if the result of the conversion is + * larger than {@link Long#MAX_VALUE} then CVTTSD2SI returns {@link Long#MIN_VALUE} and extra + * tests are required on the double value to return the correct long value. + * + * @param input the double being converted + * @param result the result produced by the CVTTSS2SI instruction + */ + @Snippet + public static long d2l(@Parameter("input") double input, @Parameter("result") long result) { + if (result == Long.MIN_VALUE) { + if (Double.isNaN(input)) { + // input is NaN -> return 0 + return 0; + } else if (input > 0.0d) { + // input is positive -> return maxInt + return Long.MAX_VALUE; + } + } + return result; + } + + public static class Templates extends AbstractTemplates<AMD64ConvertSnippets> { + + private final ResolvedJavaMethod f2i; + private final ResolvedJavaMethod f2l; + private final ResolvedJavaMethod d2i; + private final ResolvedJavaMethod d2l; + + public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) { + super(runtime, assumptions, target, AMD64ConvertSnippets.class); + f2i = snippet("f2i", float.class, int.class); + f2l = snippet("f2l", float.class, long.class); + d2i = snippet("d2i", double.class, int.class); + d2l = snippet("d2l", double.class, long.class); + } + + public void lower(ConvertNode convert, LoweringTool tool) { + if (convert.opcode == Op.F2I) { + lower0(convert, tool, f2i); + } else if (convert.opcode == Op.F2L) { + lower0(convert, tool, f2l); + } else if (convert.opcode == Op.D2I) { + lower0(convert, tool, d2i); + } else if (convert.opcode == Op.D2L) { + lower0(convert, tool, d2l); + } + } + + private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) { + StructuredGraph graph = (StructuredGraph) convert.graph(); + + // Insert a unique placeholder node in place of the Convert node so that the + // Convert node can be used as an input to the snippet. All usage of the + // Convert node are replaced by the placeholder which in turn is replaced by the + // snippet. + + LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp())); + convert.replaceAtUsages(replacee); + Key key = new Key(snippet); + Arguments arguments = arguments("input", convert.value()).add("result", convert); + SnippetTemplate template = cache.get(key, assumptions); + Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments); + template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_d2l03.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2009, 2012, 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.jtt.bytecode; + +import com.oracle.graal.jtt.*; +import org.junit.*; + +/* + */ +public class BC_d2l03 extends JTTTest { + + public static long test(double divider) { + return (long) (((long) divider) * divider); + } + + @Test + public void run0() throws Throwable { + runTest("test", 34.5D); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,103 @@ +/* + * 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.lir.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; +import com.oracle.graal.lir.*; + +public class AMD64AddressValue extends CompositeValue { + + private static final long serialVersionUID = -4444600052487578694L; + + @Component({REG, UNUSED}) protected AllocatableValue base; + @Component({REG, UNUSED}) protected AllocatableValue index; + protected final Scale scale; + protected final int displacement; + + public AMD64AddressValue(Kind kind, AllocatableValue base, int displacement) { + this(kind, base, AllocatableValue.UNUSED, Scale.Times1, displacement); + } + + public AMD64AddressValue(Kind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) { + super(kind); + this.base = base; + this.index = index; + this.scale = scale; + this.displacement = displacement; + } + + private static Register toRegister(AllocatableValue value) { + if (value == AllocatableValue.UNUSED) { + return Register.None; + } else { + RegisterValue reg = (RegisterValue) value; + return reg.getRegister(); + } + } + + public AMD64Address toAddress() { + return new AMD64Address(toRegister(base), toRegister(index), scale, displacement); + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append(getKind().getJavaName()).append("["); + String sep = ""; + if (isLegal(base)) { + s.append(base); + sep = " + "; + } + if (isLegal(index)) { + s.append(sep).append(index).append(" * ").append(scale.value); + sep = " + "; + } + if (displacement < 0) { + s.append(" - ").append(-displacement); + } else if (displacement > 0) { + s.append(sep).append(displacement); + } + s.append("]"); + return s.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AMD64AddressValue) { + AMD64AddressValue addr = (AMD64AddressValue) obj; + return getKind() == addr.getKind() && displacement == addr.displacement && base.equals(addr.base) && scale == addr.scale && index.equals(addr.index); + } + return false; + } + + @Override + public int hashCode() { + return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ (scale.value << 8) ^ (getKind().ordinal() << 12); + } +}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Sun Mar 10 19:51:32 2013 +0100 @@ -28,8 +28,6 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; @@ -44,10 +42,15 @@ INEG, LNEG, I2L, L2I, I2B, I2C, I2S, F2D, D2F, - I2F, I2D, F2I, D2I, - L2F, L2D, F2L, D2L, - MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; + I2F, I2D, + L2F, L2D, + MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L, + /* + * Converts a float/double to an int/long. The result of the conversion does not comply with Java semantics + * when the input is a NaN, infinity or the conversion result is greater than Integer.MAX_VALUE/Long.MAX_VALUE. + */ + F2I, D2I, F2L, D2L; /** * Unary operation with separate source and destination operand. @@ -339,19 +342,15 @@ case L2D: masm.cvtsi2sdq(asDoubleReg(dst), asLongReg(src)); break; case F2I: masm.cvttss2sil(asIntReg(dst), asFloatReg(src)); - emitConvertFixup(tasm, masm, dst, src); break; case D2I: masm.cvttsd2sil(asIntReg(dst), asDoubleReg(src)); - emitConvertFixup(tasm, masm, dst, src); break; case F2L: masm.cvttss2siq(asLongReg(dst), asFloatReg(src)); - emitConvertFixup(tasm, masm, dst, src); break; case D2L: masm.cvttsd2siq(asLongReg(dst), asDoubleReg(src)); - emitConvertFixup(tasm, masm, dst, src); break; case MOV_I2F: masm.movdl(asFloatReg(dst), asIntReg(src)); break; case MOV_L2D: masm.movdq(asDoubleReg(dst), asLongReg(src)); break; @@ -466,63 +465,6 @@ } } - private static void emitConvertFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value x) { - ConvertSlowPath slowPath = new ConvertSlowPath(result, x); - tasm.stubs.add(slowPath); - switch (result.getKind()) { - case Int: masm.cmpl(asIntReg(result), Integer.MIN_VALUE); break; - case Long: masm.cmpq(asLongReg(result), (AMD64Address) tasm.asLongConstRef(Constant.forLong(java.lang.Long.MIN_VALUE))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - masm.jcc(ConditionFlag.Equal, slowPath.start); - masm.bind(slowPath.continuation); - } - - private static class ConvertSlowPath extends AMD64Code { - public final Label start = new Label(); - public final Label continuation = new Label(); - private final Value result; - private final Value x; - - public ConvertSlowPath(Value result, Value x) { - this.result = result; - this.x = x; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.bind(start); - switch (x.getKind()) { - case Float: masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatConstRef(Constant.FLOAT_0)); break; - case Double: masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleConstRef(Constant.DOUBLE_0)); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - Label nan = new Label(); - masm.jcc(ConditionFlag.Parity, nan); - masm.jcc(ConditionFlag.Below, continuation); - - // input is > 0 -> return maxInt - // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff - switch (result.getKind()) { - case Int: masm.decrementl(asIntReg(result), 1); break; - case Long: masm.decrementq(asLongReg(result), 1); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - masm.jmp(continuation); - - // input is NaN -> return 0 - masm.bind(nan); - masm.xorptr(asRegister(result), asRegister(result)); - masm.jmp(continuation); - } - - @Override - public String description() { - return "convert " + x + " to " + result; - } - } - - private static void verifyKind(AMD64Arithmetic opcode, Value result, Value x, Value y) { assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Sun Mar 10 19:51:32 2013 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.lir.amd64; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.asm.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Sun Mar 10 19:51:32 2013 +0100 @@ -25,7 +25,6 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Sun Mar 10 19:51:32 2013 +0100 @@ -26,13 +26,13 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.amd64.*; -import com.oracle.graal.amd64.AMD64Address.Scale; +import com.oracle.graal.api.code.CompilationResult.JumpTable; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.JumpTable; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.Opcode; @@ -338,11 +338,11 @@ // Set scratch to address of jump table int leaPos = buf.position(); - masm.leaq(scratch, new AMD64Address(tasm.target.wordKind, AMD64.rip.asValue(), 0)); + masm.leaq(scratch, new AMD64Address(AMD64.rip, 0)); int afterLea = buf.position(); // Load jump table entry into scratch and jump to it - masm.movslq(value, new AMD64Address(Kind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0)); + masm.movslq(value, new AMD64Address(scratch, value, Scale.Times4, 0)); masm.addq(scratch, value); masm.jmp(scratch); @@ -354,7 +354,7 @@ // Patch LEA instruction above now that we know the position of the jump table int jumpTablePos = buf.position(); buf.setPosition(leaPos); - masm.leaq(scratch, new AMD64Address(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea)); + masm.leaq(scratch, new AMD64Address(AMD64.rip, jumpTablePos - afterLea)); buf.setPosition(jumpTablePos); // Emit jump table entries
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Sun Mar 10 19:51:32 2013 +0100 @@ -97,10 +97,10 @@ public abstract static class MemOp extends AMD64LIRInstruction { - @Use({ADDR}) protected AMD64Address address; + @Use({COMPOSITE}) protected AMD64AddressValue address; @State protected LIRFrameState state; - public MemOp(AMD64Address address, LIRFrameState state) { + public MemOp(AMD64AddressValue address, LIRFrameState state) { this.address = address; this.state = state; } @@ -120,7 +120,7 @@ @Def({REG}) protected AllocatableValue result; - public LoadOp(AllocatableValue result, AMD64Address address, LIRFrameState state) { + public LoadOp(AllocatableValue result, AMD64AddressValue address, LIRFrameState state) { super(address, state); this.result = result; } @@ -130,28 +130,28 @@ switch (address.getKind()) { case Boolean: case Byte: - masm.movsxb(asRegister(result), address); + masm.movsxb(asRegister(result), address.toAddress()); break; case Char: - masm.movzxl(asRegister(result), address); + masm.movzxl(asRegister(result), address.toAddress()); break; case Short: - masm.movswl(asRegister(result), address); + masm.movswl(asRegister(result), address.toAddress()); break; case Int: - masm.movslq(asRegister(result), address); + masm.movslq(asRegister(result), address.toAddress()); break; case Long: - masm.movq(asRegister(result), address); + masm.movq(asRegister(result), address.toAddress()); break; case Float: - masm.movflt(asFloatReg(result), address); + masm.movflt(asFloatReg(result), address.toAddress()); break; case Double: - masm.movdbl(asDoubleReg(result), address); + masm.movdbl(asDoubleReg(result), address.toAddress()); break; case Object: - masm.movq(asRegister(result), address); + masm.movq(asRegister(result), address.toAddress()); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -163,7 +163,7 @@ @Use({REG}) protected AllocatableValue input; - public StoreOp(AMD64Address address, AllocatableValue input, LIRFrameState state) { + public StoreOp(AMD64AddressValue address, AllocatableValue input, LIRFrameState state) { super(address, state); this.input = input; } @@ -174,26 +174,26 @@ switch (address.getKind()) { case Boolean: case Byte: - masm.movb(address, asRegister(input)); + masm.movb(address.toAddress(), asRegister(input)); break; case Char: case Short: - masm.movw(address, asRegister(input)); + masm.movw(address.toAddress(), asRegister(input)); break; case Int: - masm.movl(address, asRegister(input)); + masm.movl(address.toAddress(), asRegister(input)); break; case Long: - masm.movq(address, asRegister(input)); + masm.movq(address.toAddress(), asRegister(input)); break; case Float: - masm.movflt(address, asFloatReg(input)); + masm.movflt(address.toAddress(), asFloatReg(input)); break; case Double: - masm.movsd(address, asDoubleReg(input)); + masm.movsd(address.toAddress(), asDoubleReg(input)); break; case Object: - masm.movq(address, asRegister(input)); + masm.movq(address.toAddress(), asRegister(input)); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -205,7 +205,7 @@ protected final Constant input; - public StoreConstantOp(AMD64Address address, Constant input, LIRFrameState state) { + public StoreConstantOp(AMD64AddressValue address, Constant input, LIRFrameState state) { super(address, state); this.input = input; } @@ -215,30 +215,30 @@ switch (address.getKind()) { case Boolean: case Byte: - masm.movb(address, input.asInt() & 0xFF); + masm.movb(address.toAddress(), input.asInt() & 0xFF); break; case Char: case Short: - masm.movw(address, input.asInt() & 0xFFFF); + masm.movw(address.toAddress(), input.asInt() & 0xFFFF); break; case Int: - masm.movl(address, input.asInt()); + masm.movl(address.toAddress(), input.asInt()); break; case Long: if (NumUtil.isInt(input.asLong())) { - masm.movslq(address, (int) input.asLong()); + masm.movslq(address.toAddress(), (int) input.asLong()); } else { throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); } break; case Float: - masm.movl(address, floatToRawIntBits(input.asFloat())); + masm.movl(address.toAddress(), floatToRawIntBits(input.asFloat())); break; case Double: throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); case Object: if (input.isNull()) { - masm.movptr(address, 0); + masm.movptr(address.toAddress(), 0); } else { throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); } @@ -252,16 +252,16 @@ public static class LeaOp extends AMD64LIRInstruction { @Def({REG}) protected AllocatableValue result; - @Use({ADDR, UNINITIALIZED}) protected AMD64Address address; + @Use({COMPOSITE, UNINITIALIZED}) protected AMD64AddressValue address; - public LeaOp(AllocatableValue result, AMD64Address address) { + public LeaOp(AllocatableValue result, AMD64AddressValue address) { this.result = result; this.address = address; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.leaq(asLongReg(result), address); + masm.leaq(asLongReg(result), address.toAddress()); } } @@ -316,11 +316,11 @@ public static class CompareAndSwapOp extends AMD64LIRInstruction { @Def protected AllocatableValue result; - @Use({ADDR}) protected AMD64Address address; + @Use({COMPOSITE}) protected AMD64AddressValue address; @Use protected AllocatableValue cmpValue; @Use protected AllocatableValue newValue; - public CompareAndSwapOp(AllocatableValue result, AMD64Address address, AllocatableValue cmpValue, AllocatableValue newValue) { + public CompareAndSwapOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { this.result = result; this.address = address; this.cmpValue = cmpValue; @@ -523,7 +523,7 @@ } } - protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64Address address, AllocatableValue cmpValue, AllocatableValue newValue) { + protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax; if (tasm.target.isMP) { @@ -531,11 +531,11 @@ } switch (cmpValue.getKind()) { case Int: - masm.cmpxchgl(asRegister(newValue), address); + masm.cmpxchgl(asRegister(newValue), address.toAddress()); break; case Long: case Object: - masm.cmpxchgq(asRegister(newValue), address); + masm.cmpxchgq(asRegister(newValue), address.toAddress()); break; default: throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Sun Mar 10 19:51:32 2013 +0100 @@ -25,7 +25,6 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,106 @@ +/* + * 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.lir.ptx; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.lir.*; + +/** + * Represents an address in target machine memory, specified via some combination of a base register + * and a displacement. + */ +public final class PTXAddressValue extends CompositeValue { + + private static final long serialVersionUID = 1802222435353022623L; + + @Component({REG, UNUSED}) private AllocatableValue base; + private final long displacement; + + /** + * Creates an {@link PTXAddressValue} with given base register and no displacement. + * + * @param kind the kind of the value being addressed + * @param base the base register + */ + public PTXAddressValue(Kind kind, AllocatableValue base) { + this(kind, base, 0); + } + + /** + * Creates an {@link PTXAddressValue} with given base register and a displacement. This is the + * most general constructor. + * + * @param kind the kind of the value being addressed + * @param base the base register + * @param displacement the displacement + */ + public PTXAddressValue(Kind kind, AllocatableValue base, long displacement) { + super(kind); + this.base = base; + this.displacement = displacement; + + assert !isStackSlot(base); + } + + public PTXAddress toAddress() { + Register baseReg = base == AllocatableValue.UNUSED ? Register.None : asRegister(base); + return new PTXAddress(baseReg, displacement); + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append(getKind().getJavaName()).append("["); + String sep = ""; + if (isLegal(base)) { + s.append(base); + sep = " + "; + } + if (displacement < 0) { + s.append(" - ").append(-displacement); + } else if (displacement > 0) { + s.append(sep).append(displacement); + } + s.append("]"); + return s.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PTXAddressValue) { + PTXAddressValue addr = (PTXAddressValue) obj; + return getKind() == addr.getKind() && displacement == addr.displacement && base.equals(addr.base); + } + return false; + } + + @Override + public int hashCode() { + return base.hashCode() ^ ((int) displacement << 4) ^ (getKind().ordinal() << 12); + } +}
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java Sun Mar 10 19:51:32 2013 +0100 @@ -36,7 +36,7 @@ @Opcode private final IntrinsicOpcode opcode; @Def protected Value result; - @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input; + @Use({OperandFlag.REG}) protected Value input; public PTXBitManipulationOp(IntrinsicOpcode opcode, Value result, Value input) { this.opcode = opcode;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Sun Mar 10 19:51:32 2013 +0100 @@ -33,7 +33,6 @@ import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.ptx.*; public class PTXMove { @@ -121,10 +120,10 @@ public static class LoadOp extends PTXLIRInstruction { @Def({REG}) protected AllocatableValue result; - @Use({ADDR}) protected PTXAddress address; + @Use({COMPOSITE}) protected PTXAddressValue address; @State protected LIRFrameState state; - public LoadOp(AllocatableValue result, PTXAddress address, LIRFrameState state) { + public LoadOp(AllocatableValue result, PTXAddressValue address, LIRFrameState state) { this.result = result; this.address = address; this.state = state; @@ -132,14 +131,13 @@ @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - Register a = asRegister(address.getBase()); - long immOff = address.getDisplacement(); + PTXAddress addr = address.toAddress(); switch (address.getKind()) { case Int: - masm.ld_global_s32(asRegister(result), a, immOff); + masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; case Object: - masm.ld_global_u32(asRegister(result), a, immOff); + masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -149,11 +147,11 @@ public static class StoreOp extends PTXLIRInstruction { - @Use({ADDR}) protected PTXAddress address; + @Use({COMPOSITE}) protected PTXAddressValue address; @Use({REG}) protected AllocatableValue input; @State protected LIRFrameState state; - public StoreOp(PTXAddress address, AllocatableValue input, LIRFrameState state) { + public StoreOp(PTXAddressValue address, AllocatableValue input, LIRFrameState state) { this.address = address; this.input = input; this.state = state; @@ -161,13 +159,11 @@ @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - Register a = asRegister(address.getBase()); - long immOff = address.getDisplacement(); - assert isRegister(input); + PTXAddress addr = address.toAddress(); switch (address.getKind()) { case Int: - masm.st_global_s32(a, immOff, asRegister(input)); + masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -178,9 +174,9 @@ public static class LeaOp extends PTXLIRInstruction { @Def({REG}) protected AllocatableValue result; - @Use({ADDR, UNINITIALIZED}) protected PTXAddress address; + @Use({COMPOSITE, UNINITIALIZED}) protected PTXAddressValue address; - public LeaOp(AllocatableValue result, PTXAddress address) { + public LeaOp(AllocatableValue result, PTXAddressValue address) { this.result = result; this.address = address; } @@ -211,11 +207,11 @@ public static class CompareAndSwapOp extends PTXLIRInstruction { @Def protected AllocatableValue result; - @Use({ADDR}) protected PTXAddress address; + @Use({COMPOSITE}) protected PTXAddressValue address; @Use protected AllocatableValue cmpValue; @Use protected AllocatableValue newValue; - public CompareAndSwapOp(AllocatableValue result, PTXAddress address, AllocatableValue cmpValue, AllocatableValue newValue) { + public CompareAndSwapOp(AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { this.result = result; this.address = address; this.cmpValue = cmpValue; @@ -276,7 +272,7 @@ } @SuppressWarnings("unused") - protected static void compareAndSwap(TargetMethodAssembler tasm, PTXAssembler masm, AllocatableValue result, PTXAddress address, AllocatableValue cmpValue, AllocatableValue newValue) { + protected static void compareAndSwap(TargetMethodAssembler tasm, PTXAssembler masm, AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { throw new InternalError("NYI"); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,61 @@ +/* + * 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.lir; + +import java.lang.annotation.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; + +/** + * Base class to represent values that need to be stored in more than one register. + */ +public abstract class CompositeValue extends Value { + + private static final long serialVersionUID = -169180052684126180L; + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public static @interface Component { + + OperandFlag[] value() default OperandFlag.REG; + } + + private final CompositeValueClass valueClass; + + public CompositeValue(Kind kind) { + super(kind); + valueClass = CompositeValueClass.get(getClass()); + } + + public final void forEachComponent(OperandMode mode, ValueProcedure proc) { + valueClass.forEachComponent(this, mode, proc); + } + + @Override + public String toString() { + return valueClass.toString(this); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,145 @@ +/* + * 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.lir; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; + +public class CompositeValueClass extends LIRIntrospection { + + public static final CompositeValueClass get(Class<? extends CompositeValue> c) { + CompositeValueClass clazz = (CompositeValueClass) allClasses.get(c); + if (clazz != null) { + return clazz; + } + + // We can have a race of multiple threads creating the LIRInstructionClass at the same time. + // However, only one will be put into the map, and this is the one returned by all threads. + clazz = new CompositeValueClass(c); + CompositeValueClass oldClazz = (CompositeValueClass) allClasses.putIfAbsent(c, clazz); + if (oldClazz != null) { + return oldClazz; + } else { + return clazz; + } + } + + private final int directComponentCount; + private final long[] componentOffsets; + private final EnumSet<OperandFlag>[] componentFlags; + + @SuppressWarnings("unchecked") + public CompositeValueClass(Class<? extends CompositeValue> clazz) { + super(clazz); + + ValueFieldScanner scanner = new ValueFieldScanner(new DefaultCalcOffset()); + scanner.scan(clazz); + + OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class); + directComponentCount = mode.scalarOffsets.size(); + componentOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); + componentFlags = arrayUsingSortedOffsets(mode.flags, componentOffsets, new EnumSet[componentOffsets.length]); + + dataOffsets = sortedLongCopy(scanner.dataOffsets); + + fieldNames = scanner.fieldNames; + fieldTypes = scanner.fieldTypes; + } + + @Override + protected void rescanFieldOffsets(CalcOffset calc) { + ValueFieldScanner scanner = new ValueFieldScanner(calc); + scanner.scan(clazz); + + OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class); + copyInto(componentOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets)); + + copyInto(dataOffsets, sortedLongCopy(scanner.dataOffsets)); + + fieldNames.clear(); + fieldNames.putAll(scanner.fieldNames); + fieldTypes.clear(); + fieldTypes.putAll(scanner.fieldTypes); + } + + private static class ValueFieldScanner extends FieldScanner { + + public ValueFieldScanner(CalcOffset calc) { + super(calc); + + valueAnnotations.put(CompositeValue.Component.class, new OperandModeAnnotation()); + } + + @Override + protected void scan(Class<?> clazz) { + super.scan(clazz); + } + + @Override + protected EnumSet<OperandFlag> getFlags(Field field) { + EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class); + if (field.isAnnotationPresent(CompositeValue.Component.class)) { + result.addAll(Arrays.asList(field.getAnnotation(CompositeValue.Component.class).value())); + } else { + GraalInternalError.shouldNotReachHere(); + } + return result; + } + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" component["); + for (int i = 0; i < componentOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(componentOffsets[i]); + } + str.append("] data["); + for (int i = 0; i < dataOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(dataOffsets[i]); + } + str.append("]"); + return str.toString(); + } + + public final void forEachComponent(CompositeValue obj, OperandMode mode, ValueProcedure proc) { + forEach(obj, directComponentCount, componentOffsets, mode, componentFlags, proc); + } + + public String toString(CompositeValue obj) { + StringBuilder result = new StringBuilder(); + + appendValues(result, obj, "", "", "{", "}", new String[]{""}, componentOffsets); + + for (int i = 0; i < dataOffsets.length; i++) { + result.append(" ").append(fieldNames.get(dataOffsets[i])).append(": ").append(getFieldString(obj, dataOffsets[i])); + } + + return result.toString(); + } +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Sun Mar 10 19:51:32 2013 +0100 @@ -166,9 +166,9 @@ STACK, /** - * The value can be a {@link Address}. + * The value can be a {@link CompositeValue}. */ - ADDR, + COMPOSITE, /** * The value can be a {@link Constant}. @@ -205,10 +205,10 @@ static { ALLOWED_FLAGS = new EnumMap<>(OperandMode.class); - ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED)); - ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED)); - ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, CONST, ILLEGAL, HINT)); - ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, ILLEGAL, HINT)); + ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNUSED, UNINITIALIZED)); + ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNUSED, UNINITIALIZED)); + ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, COMPOSITE, CONST, ILLEGAL, UNUSED, HINT)); + ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, UNUSED, HINT)); } /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Sun Mar 10 19:51:32 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -22,12 +22,8 @@ */ package com.oracle.graal.lir; -import static com.oracle.graal.api.code.ValueUtil.*; - -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.*; @@ -37,7 +33,7 @@ import com.oracle.graal.lir.LIRInstruction.StateProcedure; import com.oracle.graal.lir.LIRInstruction.ValueProcedure; -public class LIRInstructionClass extends FieldIntrospection { +public class LIRInstructionClass extends LIRIntrospection { public static final LIRInstructionClass get(Class<? extends LIRInstruction> c) { LIRInstructionClass clazz = (LIRInstructionClass) allClasses.get(c); @@ -56,11 +52,8 @@ } } - private static final Class<?> INSTRUCTION_CLASS = LIRInstruction.class; - private static final Class<?> VALUE_CLASS = Value.class; - private static final Class<?> CONSTANT_CLASS = Constant.class; - private static final Class<?> VALUE_ARRAY_CLASS = Value[].class; - private static final Class<?> STATE_CLASS = LIRFrameState.class; + private static final Class<LIRInstruction> INSTRUCTION_CLASS = LIRInstruction.class; + private static final Class<LIRFrameState> STATE_CLASS = LIRFrameState.class; private final int directUseCount; private final long[] useOffsets; @@ -81,11 +74,11 @@ private long opcodeOffset; @SuppressWarnings("unchecked") - public LIRInstructionClass(Class<?> clazz) { + public LIRInstructionClass(Class<? extends LIRInstruction> clazz) { super(clazz); assert INSTRUCTION_CLASS.isAssignableFrom(clazz); - FieldScanner scanner = new FieldScanner(new DefaultCalcOffset()); + InstructionFieldScanner scanner = new InstructionFieldScanner(new DefaultCalcOffset()); scanner.scan(clazz); OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class); @@ -120,7 +113,7 @@ @Override protected void rescanFieldOffsets(CalcOffset calc) { - FieldScanner scanner = new FieldScanner(calc); + InstructionFieldScanner scanner = new InstructionFieldScanner(calc); scanner.scan(clazz); OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class); @@ -144,44 +137,22 @@ opcodeOffset = scanner.opcodeOffset; } - private static class OperandModeAnnotation { - - public final ArrayList<Long> scalarOffsets = new ArrayList<>(); - public final ArrayList<Long> arrayOffsets = new ArrayList<>(); - public final Map<Long, EnumSet<OperandFlag>> flags = new HashMap<>(); - } - - protected static class FieldScanner extends BaseFieldScanner { - - public final Map<Class<? extends Annotation>, OperandModeAnnotation> valueAnnotations; - public final ArrayList<Long> stateOffsets = new ArrayList<>(); + private static class InstructionFieldScanner extends FieldScanner { private String opcodeConstant; private long opcodeOffset; - public FieldScanner(CalcOffset calc) { + public InstructionFieldScanner(CalcOffset calc) { super(calc); - valueAnnotations = new HashMap<>(); - valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); // LIRInstruction.Use.class)); - valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); // LIRInstruction.Alive.class)); - valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); // LIRInstruction.Temp.class)); - valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); // LIRInstruction.Def.class)); + valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); + valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); + valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); + valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); } - private OperandModeAnnotation getOperandModeAnnotation(Field field) { - OperandModeAnnotation result = null; - for (Entry<Class<? extends Annotation>, OperandModeAnnotation> entry : valueAnnotations.entrySet()) { - Annotation annotation = field.getAnnotation(entry.getKey()); - if (annotation != null) { - assert result == null : "Field has two operand mode annotations: " + field; - result = entry.getValue(); - } - } - return result; - } - - private static EnumSet<OperandFlag> getFlags(Field field) { + @Override + protected EnumSet<OperandFlag> getFlags(Field field) { EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class); // Unfortunately, annotations cannot have class hierarchies or implement interfaces, so // we have to duplicate the code for every operand mode. @@ -220,25 +191,12 @@ @Override protected void scanField(Field field, Class<?> type, long offset) { - if (VALUE_CLASS.isAssignableFrom(type) && type != CONSTANT_CLASS) { - assert !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final because it is modified by register allocator: " + field; - OperandModeAnnotation annotation = getOperandModeAnnotation(field); - assert annotation != null : "Field must have operand mode annotation: " + field; - annotation.scalarOffsets.add(offset); - 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); - annotation.flags.put(offset, getFlags(field)); - } else if (STATE_CLASS.isAssignableFrom(type)) { + if (STATE_CLASS.isAssignableFrom(type)) { assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; assert field.getAnnotation(LIRInstruction.State.class) != null : "Field must have state annotation: " + field; stateOffsets.add(offset); } else { - assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; - assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field; - dataOffsets.add(offset); + super.scanField(field, type, offset); } if (field.getAnnotation(LIRInstruction.Opcode.class) != null) { @@ -334,39 +292,6 @@ } } - private static void forEach(LIRInstruction obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure proc) { - 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]); - if (isAddress(value)) { - doAddress(asAddress(value), mode, flags[i], proc); - } else { - setValue(obj, offsets[i], proc.doValue(value, mode, flags[i])); - } - } else { - Value[] values = getValueArray(obj, offsets[i]); - for (int j = 0; j < values.length; j++) { - Value value = values[j]; - if (isAddress(value)) { - doAddress(asAddress(value), mode, flags[i], proc); - } else { - values[j] = proc.doValue(value, mode, flags[i]); - } - } - } - } - } - - private static void doAddress(Address address, OperandMode mode, EnumSet<OperandFlag> flags, ValueProcedure proc) { - assert flags.contains(OperandFlag.ADDR); - Value[] components = address.components(); - for (int i = 0; i < components.length; i++) { - components[i] = proc.doValue(components[i], mode, LIRInstruction.ADDRESS_FLAGS); - } - } - public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) { int hintDirectCount = 0; long[] hintOffsets = null; @@ -401,18 +326,6 @@ return null; } - private static Value getValue(LIRInstruction obj, long offset) { - return (Value) unsafe.getObject(obj, offset); - } - - private static void setValue(LIRInstruction obj, long offset, Value value) { - unsafe.putObject(obj, offset, value); - } - - private static Value[] getValueArray(LIRInstruction obj, long offset) { - return (Value[]) unsafe.getObject(obj, offset); - } - private static LIRFrameState getState(LIRInstruction obj, long offset) { return (LIRFrameState) unsafe.getObject(obj, offset); } @@ -447,65 +360,4 @@ return result.toString(); } - - private void appendValues(StringBuilder result, LIRInstruction obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) { - int total = 0; - for (long[] offsets : moffsets) { - total += offsets.length; - } - if (total == 0) { - return; - } - - result.append(start); - if (total > 1) { - result.append(startMultiple); - } - String sep = ""; - for (int i = 0; i < moffsets.length; i++) { - long[] offsets = moffsets[i]; - - for (int j = 0; j < offsets.length; j++) { - result.append(sep).append(prefix[i]); - long offset = offsets[j]; - if (total > 1) { - result.append(fieldNames.get(offset)).append(": "); - } - result.append(getFieldString(obj, offset)); - sep = ", "; - } - } - if (total > 1) { - result.append(endMultiple); - } - result.append(end); - } - - private String getFieldString(Object obj, long offset) { - Class<?> type = fieldTypes.get(offset); - if (type == int.class) { - return String.valueOf(unsafe.getInt(obj, offset)); - } else if (type == long.class) { - return String.valueOf(unsafe.getLong(obj, offset)); - } else if (type == boolean.class) { - return String.valueOf(unsafe.getBoolean(obj, offset)); - } else if (type == float.class) { - return String.valueOf(unsafe.getFloat(obj, offset)); - } else if (type == double.class) { - return String.valueOf(unsafe.getDouble(obj, offset)); - } else if (!type.isPrimitive()) { - Object value = unsafe.getObject(obj, offset); - if (!type.isArray()) { - return String.valueOf(value); - } else if (type == int[].class) { - return Arrays.toString((int[]) value); - } else if (type == double[].class) { - return Arrays.toString((double[]) value); - } else if (!type.getComponentType().isPrimitive()) { - return Arrays.toString((Object[]) value); - } - } - assert false : "unhandled field type: " + type; - return ""; - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2012, 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.lir; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.Map.Entry; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; + +abstract class LIRIntrospection extends FieldIntrospection { + + private static final Class<Value> VALUE_CLASS = Value.class; + private static final Class<Constant> CONSTANT_CLASS = Constant.class; + private static final Class<Value[]> VALUE_ARRAY_CLASS = Value[].class; + + public LIRIntrospection(Class<?> clazz) { + super(clazz); + } + + protected static class OperandModeAnnotation { + + public final ArrayList<Long> scalarOffsets = new ArrayList<>(); + public final ArrayList<Long> arrayOffsets = new ArrayList<>(); + public final Map<Long, EnumSet<OperandFlag>> flags = new HashMap<>(); + } + + protected abstract static class FieldScanner extends BaseFieldScanner { + + public final Map<Class<? extends Annotation>, OperandModeAnnotation> valueAnnotations; + public final ArrayList<Long> stateOffsets = new ArrayList<>(); + + public FieldScanner(CalcOffset calc) { + super(calc); + + valueAnnotations = new HashMap<>(); + } + + protected OperandModeAnnotation getOperandModeAnnotation(Field field) { + OperandModeAnnotation result = null; + for (Entry<Class<? extends Annotation>, OperandModeAnnotation> entry : valueAnnotations.entrySet()) { + Annotation annotation = field.getAnnotation(entry.getKey()); + if (annotation != null) { + assert result == null : "Field has two operand mode annotations: " + field; + result = entry.getValue(); + } + } + return result; + } + + protected abstract EnumSet<OperandFlag> getFlags(Field field); + + @Override + protected void scanField(Field field, Class<?> type, long offset) { + if (VALUE_CLASS.isAssignableFrom(type) && type != CONSTANT_CLASS) { + assert !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final because it is modified by register allocator: " + field; + OperandModeAnnotation annotation = getOperandModeAnnotation(field); + assert annotation != null : "Field must have operand mode annotation: " + field; + annotation.scalarOffsets.add(offset); + 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); + annotation.flags.put(offset, getFlags(field)); + } else { + assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; + assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field; + dataOffsets.add(offset); + } + } + } + + protected static void forEach(Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure proc) { + 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]); + if (value instanceof CompositeValue) { + CompositeValue composite = (CompositeValue) value; + composite.forEachComponent(mode, proc); + } else { + setValue(obj, offsets[i], proc.doValue(value, mode, flags[i])); + } + } else { + Value[] values = getValueArray(obj, offsets[i]); + for (int j = 0; j < values.length; j++) { + Value value = values[j]; + if (value instanceof CompositeValue) { + CompositeValue composite = (CompositeValue) value; + composite.forEachComponent(mode, proc); + } else { + values[j] = proc.doValue(value, mode, flags[i]); + } + } + } + } + } + + protected static Value getValue(Object obj, long offset) { + return (Value) unsafe.getObject(obj, offset); + } + + protected static void setValue(Object obj, long offset, Value value) { + unsafe.putObject(obj, offset, value); + } + + protected static Value[] getValueArray(Object obj, long offset) { + return (Value[]) unsafe.getObject(obj, offset); + } + + protected void appendValues(StringBuilder result, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) { + int total = 0; + for (long[] offsets : moffsets) { + total += offsets.length; + } + if (total == 0) { + return; + } + + result.append(start); + if (total > 1) { + result.append(startMultiple); + } + String sep = ""; + for (int i = 0; i < moffsets.length; i++) { + long[] offsets = moffsets[i]; + + for (int j = 0; j < offsets.length; j++) { + result.append(sep).append(prefix[i]); + long offset = offsets[j]; + if (total > 1) { + result.append(fieldNames.get(offset)).append(": "); + } + result.append(getFieldString(obj, offset)); + sep = ", "; + } + } + if (total > 1) { + result.append(endMultiple); + } + result.append(end); + } + + protected String getFieldString(Object obj, long offset) { + Class<?> type = fieldTypes.get(offset); + if (type == int.class) { + return String.valueOf(unsafe.getInt(obj, offset)); + } else if (type == long.class) { + return String.valueOf(unsafe.getLong(obj, offset)); + } else if (type == boolean.class) { + return String.valueOf(unsafe.getBoolean(obj, offset)); + } else if (type == float.class) { + return String.valueOf(unsafe.getFloat(obj, offset)); + } else if (type == double.class) { + return String.valueOf(unsafe.getDouble(obj, offset)); + } else if (!type.isPrimitive()) { + Object value = unsafe.getObject(obj, offset); + if (!type.isArray()) { + return String.valueOf(value); + } else if (type == int[].class) { + return Arrays.toString((int[]) value); + } else if (type == double[].class) { + return Arrays.toString((double[]) value); + } else if (!type.getComponentType().isPrimitive()) { + return Arrays.toString((Object[]) value); + } + } + assert false : "unhandled field type: " + type; + return ""; + } +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Sun Mar 10 19:51:32 2013 +0100 @@ -150,7 +150,7 @@ compilationResult.recordSafepoint(pos, debugInfo); } - public Address recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { + public AbstractAddress recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { assert data != null; int pos = asm.codeBuffer.position(); Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString()); @@ -176,11 +176,11 @@ /** * Returns the address of a float constant that is embedded as a data references into the code. */ - public Address asFloatConstRef(Value value) { + public AbstractAddress asFloatConstRef(Value value) { return asFloatConstRef(value, 4); } - public Address asFloatConstRef(Value value, int alignment) { + public AbstractAddress asFloatConstRef(Value value, int alignment) { assert value.getKind() == Kind.Float && isConstant(value); return recordDataReferenceInCode((Constant) value, alignment, false); } @@ -188,11 +188,11 @@ /** * Returns the address of a double constant that is embedded as a data references into the code. */ - public Address asDoubleConstRef(Value value) { + public AbstractAddress asDoubleConstRef(Value value) { return asDoubleConstRef(value, 8); } - public Address asDoubleConstRef(Value value, int alignment) { + public AbstractAddress asDoubleConstRef(Value value, int alignment) { assert value.getKind() == Kind.Double && isConstant(value); return recordDataReferenceInCode((Constant) value, alignment, false); } @@ -200,41 +200,39 @@ /** * Returns the address of a long constant that is embedded as a data references into the code. */ - public Address asLongConstRef(Value value) { + public AbstractAddress asLongConstRef(Value value) { assert value.getKind() == Kind.Long && isConstant(value); return recordDataReferenceInCode((Constant) value, 8, false); } - public Address asIntAddr(Value value) { + public AbstractAddress asIntAddr(Value value) { assert value.getKind() == Kind.Int; return asAddress(value); } - public Address asLongAddr(Value value) { + public AbstractAddress asLongAddr(Value value) { assert value.getKind() == Kind.Long; return asAddress(value); } - public Address asObjectAddr(Value value) { + public AbstractAddress asObjectAddr(Value value) { assert value.getKind() == Kind.Object; return asAddress(value); } - public Address asFloatAddr(Value value) { + public AbstractAddress asFloatAddr(Value value) { assert value.getKind() == Kind.Float; return asAddress(value); } - public Address asDoubleAddr(Value value) { + public AbstractAddress asDoubleAddr(Value value) { assert value.getKind() == Kind.Double; return asAddress(value); } - public Address asAddress(Value value) { - if (isStackSlot(value)) { - StackSlot slot = (StackSlot) value; - return asm.makeAddress(slot.getKind(), frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot)); - } - return (Address) value; + public AbstractAddress asAddress(Value value) { + assert isStackSlot(value); + StackSlot slot = asStackSlot(value); + return asm.makeAddress(frameMap.registerConfig.getFrameRegister(), frameMap.offsetForStackSlot(slot)); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Sun Mar 10 19:51:32 2013 +0100 @@ -32,7 +32,7 @@ /** * The {@code ConvertNode} class represents a conversion between primitive types. */ -public final class ConvertNode extends FloatingNode implements Canonicalizable, LIRLowerable { +public final class ConvertNode extends FloatingNode implements Canonicalizable, LIRLowerable, Lowerable { public enum Op { I2L(Int, Long), @@ -162,6 +162,11 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.setResult(this, gen.emitConvert(opcode, gen.operand(value()))); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Sun Mar 10 19:51:32 2013 +0100 @@ -48,4 +48,9 @@ * Gets the closest fixed node preceding the node currently being lowered. */ FixedWithNextNode lastFixedNode(); + + /** + * Sets the closest fixed node preceding the next node to be lowered. + */ + void setLastFixedNode(FixedWithNextNode n); }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Sun Mar 10 19:51:32 2013 +0100 @@ -104,6 +104,11 @@ public FixedWithNextNode lastFixedNode() { return lastFixedNode; } + + public void setLastFixedNode(FixedWithNextNode n) { + assert n == null || n.isAlive() : n; + lastFixedNode = n; + } } private final TargetDescription target; @@ -187,15 +192,15 @@ List<ScheduledNode> nodes = schedule.nodesFor(b); for (Node node : nodes) { - FixedNode lastFixedNext = null; - if (node instanceof FixedWithNextNode) { + FixedNode nextFixedNode = null; + if (node instanceof FixedWithNextNode && node.isAlive()) { FixedWithNextNode fixed = (FixedWithNextNode) node; - lastFixedNext = fixed.next(); - loweringTool.lastFixedNode = fixed; + nextFixedNode = fixed.next(); + loweringTool.setLastFixedNode(fixed); } if (node.isAlive() && !processed.isMarked(node) && node instanceof Lowerable) { - if (loweringTool.lastFixedNode == null) { + if (loweringTool.lastFixedNode() == null) { // We cannot lower the node now because we don't have a fixed node to anchor the // replacements. // This can happen when previous lowerings in this lowering iteration deleted @@ -209,17 +214,17 @@ } } - if (loweringTool.lastFixedNode == node && !node.isAlive()) { - if (lastFixedNext == null) { - loweringTool.lastFixedNode = null; + if (loweringTool.lastFixedNode() == node && !node.isAlive()) { + if (nextFixedNode == null || !nextFixedNode.isAlive()) { + loweringTool.setLastFixedNode(null); } else { - Node prev = lastFixedNext.predecessor(); + Node prev = nextFixedNode.predecessor(); if (prev != node && prev instanceof FixedWithNextNode) { - loweringTool.lastFixedNode = (FixedWithNextNode) prev; - } else if (lastFixedNext instanceof FixedWithNextNode) { - loweringTool.lastFixedNode = (FixedWithNextNode) lastFixedNext; + loweringTool.setLastFixedNode((FixedWithNextNode) prev); + } else if (nextFixedNode instanceof FixedWithNextNode) { + loweringTool.setLastFixedNode((FixedWithNextNode) nextFixedNode); } else { - loweringTool.lastFixedNode = null; + loweringTool.setLastFixedNode(null); } } }
--- a/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTXAddress.java Sun Mar 10 19:51:18 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/* - * 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.ptx; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; - -/** - * Represents an address in target machine memory, specified via some combination of a base register - * and a displacement. - */ -public final class PTXAddress extends Address { - - private static final long serialVersionUID = 8343625682010474837L; - - private final Value[] base; - private final long displacement; - - /** - * Creates an {@link PTXAddress} with given base register and no displacement. - * - * @param kind the kind of the value being addressed - * @param base the base register - */ - public PTXAddress(Kind kind, Value base) { - this(kind, base, 0); - } - - /** - * Creates an {@link PTXAddress} with given base register and a displacement. This is the most - * general constructor. - * - * @param kind the kind of the value being addressed - * @param base the base register - * @param displacement the displacement - */ - public PTXAddress(Kind kind, Value base, long displacement) { - super(kind); - this.base = new Value[1]; - this.setBase(base); - this.displacement = displacement; - - assert !isConstant(base) && !isStackSlot(base); - } - - @Override - public Value[] components() { - return base; - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - s.append(getKind().getJavaName()).append("["); - String sep = ""; - if (isLegal(getBase())) { - s.append(getBase()); - sep = " + "; - } - if (getDisplacement() < 0) { - s.append(" - ").append(-getDisplacement()); - } else if (getDisplacement() > 0) { - s.append(sep).append(getDisplacement()); - } - s.append("]"); - return s.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof PTXAddress) { - PTXAddress addr = (PTXAddress) obj; - return getKind() == addr.getKind() && getDisplacement() == addr.getDisplacement() && getBase().equals(addr.getBase()); - } - return false; - } - - @Override - public int hashCode() { - return getBase().hashCode() ^ ((int) getDisplacement() << 4) ^ (getKind().ordinal() << 12); - } - - /** - * @return Base register that defines the start of the address computation. If not present, is - * denoted by {@link Value#ILLEGAL}. - */ - public Value getBase() { - return base[0]; - } - - public void setBase(Value base) { - this.base[0] = base; - } - - /** - * @return Optional additive displacement. - */ - public long getDisplacement() { - return displacement; - } -}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Sun Mar 10 19:51:32 2013 +0100 @@ -95,7 +95,7 @@ } else { KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool); SnippetTemplate template = cache.get(keyAndArguments.key, assumptions); - template.instantiate(runtime, instanceOf, replacer, tool.lastFixedNode(), keyAndArguments.arguments); + template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments); } }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Sun Mar 10 19:51:32 2013 +0100 @@ -198,7 +198,8 @@ public StructuredGraph call() throws Exception { StructuredGraph graph = parseGraph(method, policy); - new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph); new SnippetFrameStateCleanupPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); @@ -232,7 +233,7 @@ new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); - new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); for (Invoke invoke : graph.getInvokes()) { MethodCallTargetNode callTarget = invoke.methodCallTarget(); @@ -260,7 +261,7 @@ } } - new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Sun Mar 10 19:51:32 2013 +0100 @@ -43,45 +43,21 @@ private final MetaAccessProvider runtime; private final BoxingMethodPool pool; - private final boolean intrinsificationOrFoldingCanBeDeferred; - /** - * @param intrinsificationOrFoldingCanBeDeferred if true, then {@link NonConstantParameterError} - * s are not fatal - */ - public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool, boolean intrinsificationOrFoldingCanBeDeferred) { + public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool) { this.runtime = runtime; this.pool = pool; - this.intrinsificationOrFoldingCanBeDeferred = intrinsificationOrFoldingCanBeDeferred; } @Override protected void run(StructuredGraph graph) { for (Invoke i : graph.getInvokes()) { - try { - if (i.callTarget() instanceof MethodCallTargetNode) { - tryIntrinsify(i); - } - } catch (NonConstantParameterError t) { - if (!intrinsificationOrFoldingCanBeDeferred) { - throw t; - } + if (i.callTarget() instanceof MethodCallTargetNode) { + tryIntrinsify(i); } } } - /** - * Exception raised when an argument to a {@linkplain Fold foldable} or {@link NodeIntrinsic} - * method is not a constant. - */ - @SuppressWarnings("serial") - public static class NonConstantParameterError extends Error { - - public NonConstantParameterError(String message) { - super(message); - } - } - public static Class<?>[] signatureToTypes(Signature signature, ResolvedJavaType accessingClass) { int count = signature.getParameterCount(false); Class<?>[] result = new Class<?>[count]; @@ -91,7 +67,7 @@ return result; } - private void tryIntrinsify(Invoke invoke) { + private boolean tryIntrinsify(Invoke invoke) { ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod(); NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class); ResolvedJavaType declaringClass = target.getDeclaringClass(); @@ -104,6 +80,9 @@ // Prepare the arguments for the reflective constructor call on the node class. Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false); + if (nodeConstructorArguments == null) { + return false; + } // Create the new node instance. Class<?> c = getNodeClass(target, intrinsic); @@ -120,6 +99,9 @@ // Prepare the arguments for the reflective method call Object[] arguments = prepareArguments(invoke, parameterTypes, target, true); + if (arguments == null) { + return false; + } Object receiver = null; if (!invoke.methodCallTarget().isStatic()) { receiver = arguments[0]; @@ -142,6 +124,7 @@ invoke.intrinsify(null); } } + return true; } /** @@ -149,6 +132,8 @@ * to a reflective invocation of a Java constructor or method. * * @param folding specifies if the invocation is for handling a {@link Fold} annotation + * @return the arguments for the reflective invocation or null if an argument of {@code invoke} + * that is expected to be constant isn't */ private Object[] prepareArguments(Invoke invoke, Class<?>[] parameterTypes, ResolvedJavaMethod target, boolean folding) { NodeInputList<ValueNode> arguments = invoke.callTarget().arguments(); @@ -161,8 +146,7 @@ ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i)); if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) { if (!(argument instanceof ConstantNode)) { - throw new NonConstantParameterError("parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.methodCallTarget().targetMethod() + " at " + - sourceLocation(invoke.node()) + ": " + argument); + return null; } ConstantNode constantNode = (ConstantNode) argument; Constant constant = constantNode.asConstant();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationVerificationPhase.java Sun Mar 10 19:51:32 2013 +0100 @@ -0,0 +1,61 @@ +/* + * 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.snippets.Snippet.Fold; + +/** + * Checks that a graph contains no calls to {@link NodeIntrinsic} or {@link Fold} methods. + */ +public class SnippetIntrinsificationVerificationPhase extends Phase { + + public static boolean verify(StructuredGraph graph) { + new SnippetIntrinsificationVerificationPhase().apply(graph); + return true; + } + + @Override + protected void run(StructuredGraph graph) { + for (Invoke i : graph.getInvokes()) { + if (i.callTarget() instanceof MethodCallTargetNode) { + checkInvoke(i); + } + } + } + + private static void checkInvoke(Invoke invoke) { + ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod(); + NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class); + if (intrinsic != null) { + throw new GraalInternalError("Illegal call to node intrinsic in " + invoke.graph() + ": " + invoke); + } else if (target.getAnnotation(Fold.class) != null) { + throw new GraalInternalError("Illegal call to foldable method in " + invoke.graph() + ": " + invoke); + } + } +}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Sun Mar 10 19:51:18 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Sun Mar 10 19:51:32 2013 +0100 @@ -36,6 +36,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; @@ -282,11 +283,12 @@ Debug.dump(snippetCopy, "Before specialization"); if (!replacements.isEmpty()) { // Do deferred intrinsification of node intrinsics - new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); + new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime)).apply(snippetCopy); new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); new CanonicalizerPhase(runtime, assumptions, 0, null).apply(snippetCopy); } + assert SnippetIntrinsificationVerificationPhase.verify(snippetCopy); // Gather the template parameters parameters = new HashMap<>(); @@ -628,10 +630,9 @@ * @param runtime * @param replacee the node that will be replaced * @param replacer object that replaces the usages of {@code replacee} - * @param lastFixedNode the CFG of the snippet is inserted after this node * @param args the arguments to be bound to the flattened positional parameters of the snippet */ - public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, FixedWithNextNode lastFixedNode, SnippetTemplate.Arguments args) { + public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -643,7 +644,8 @@ Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, replacements); Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method()); - assert lastFixedNode != null : replaceeGraph; + FixedWithNextNode lastFixedNode = tool.lastFixedNode(); + assert lastFixedNode != null && lastFixedNode.isAlive() : replaceeGraph; FixedNode next = lastFixedNode.next(); lastFixedNode.setNext(null); FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); @@ -672,10 +674,14 @@ assert returnValue != null || replacee.usages().isEmpty(); replacer.replace(replacee, returnValue); + tool.setLastFixedNode(null); Node returnDuplicate = duplicates.get(returnNode); if (returnDuplicate.isAlive()) { returnDuplicate.clearInputs(); returnDuplicate.replaceAndDelete(next); + if (next != null && next.predecessor() instanceof FixedWithNextNode) { + tool.setLastFixedNode((FixedWithNextNode) next.predecessor()); + } } Debug.dump(replaceeGraph, "After lowering %s with %s", replacee, this);
--- a/mx/commands.py Sun Mar 10 19:51:18 2013 +0100 +++ b/mx/commands.py Sun Mar 10 19:51:32 2013 +0100 @@ -385,7 +385,11 @@ for e in os.listdir(jdks): jreLibDir = join(jdks, e, 'jre', 'lib') if exists(jreLibDir): - shutil.copyfile(graalJar, join(jreLibDir, 'graal.jar')) + # do a copy and then a move to get atomic updating (on Unix) of graal.jar in the JRE + fd, tmp = tempfile.mkstemp(suffix='', prefix='graal.jar', dir=jreLibDir) + shutil.copyfile(graalJar, tmp) + os.close(fd) + shutil.move(tmp, join(jreLibDir, 'graal.jar')) # run a command in the windows SDK Debug Shell def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}):
--- a/mx/projects Sun Mar 10 19:51:18 2013 +0100 +++ b/mx/projects Sun Mar 10 19:51:32 2013 +0100 @@ -248,7 +248,7 @@ # graal.compiler.ptx.test project@com.oracle.graal.compiler.ptx.test@subDir=graal project@com.oracle.graal.compiler.ptx.test@sourceDirs=src -project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test +project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test,com.oracle.graal.ptx project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7 @@ -331,7 +331,7 @@ # graal.asm.ptx project@com.oracle.graal.asm.ptx@subDir=graal project@com.oracle.graal.asm.ptx@sourceDirs=src -project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.asm,com.oracle.graal.ptx +project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.asm project@com.oracle.graal.asm.ptx@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.ptx@javaCompliance=1.7
--- a/mxtool/mx.py Sun Mar 10 19:51:18 2013 +0100 +++ b/mxtool/mx.py Sun Mar 10 19:51:32 2013 +0100 @@ -1651,7 +1651,8 @@ if name.startswith('@'): dname = name[1:] d = distribution(dname) - zf = zipfile.ZipFile(d.path, 'w') + fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(d.path) + '.', dir=dirname(d.path)) + zf = zipfile.ZipFile(tmp, 'w') for p in sorted_deps(d.deps): outputDir = p.output_dir() for root, _, files in os.walk(outputDir): @@ -1660,19 +1661,26 @@ arcname = join(relpath, f).replace(os.sep, '/') zf.write(join(root, f), arcname) zf.close() + os.close(fd) + # Atomic on Unix + shutil.move(tmp, d.path) + #print time.time(), 'move:', tmp, '->', d.path d.notify_updated() else: p = project(name) outputDir = p.output_dir() - jar = join(p.dir, p.name + '.jar') - zf = zipfile.ZipFile(jar, 'w') + fd, tmp = tempfile.mkstemp(suffix='', prefix=p.name, dir=p.dir) + zf = zipfile.ZipFile(tmp, 'w') for root, _, files in os.walk(outputDir): for f in files: relpath = root[len(outputDir) + 1:] arcname = join(relpath, f).replace(os.sep, '/') zf.write(join(root, f), arcname) zf.close() + os.close(fd) + # Atomic on Unix + shutil.move(tmp, join(p.dir, p.name + '.jar')) def canonicalizeprojects(args): """process all project files to canonicalize the dependencies @@ -2255,13 +2263,18 @@ return False -def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False): +def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False): launchOut = XMLDoc(); + consoleOn = 'true' if logToConsole else 'false' launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'}) + launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'}) + launchOut.element('mapEntry', {'key' : 'JAVA_HOME', 'value' : java().jdk}) + launchOut.close('mapAttribute') + if refresh: launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE', 'value': '${project}'}) - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': 'false'}) - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': 'false'}) + launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn}) + launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': consoleOn}) if async: launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true'})