# HG changeset patch # User Doug Simon # Date 1367356177 -7200 # Node ID 861a9e0aba38f81fff6fd0a4487db490846c0362 # Parent a14fef4fca7d4a40d226022dfe807d7da40efa4b# Parent ca34e36c53e84ba209ee7072423c03d9d99149c8 Merge. diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java --- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Tue Apr 30 23:09:37 2013 +0200 @@ -23,12 +23,12 @@ package com.oracle.graal.amd64; import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.code.Register.RegisterFlag.*; +import static com.oracle.graal.api.code.Register.*; import java.nio.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Register.RegisterFlag; +import com.oracle.graal.api.code.Register.RegisterCategory; import com.oracle.graal.api.meta.*; /** @@ -36,26 +36,29 @@ */ public class AMD64 extends Architecture { + public static final RegisterCategory CPU = new RegisterCategory("CPU"); + public static final RegisterCategory XMM = new RegisterCategory("XMM"); + // @formatter:off // General purpose CPU registers - public static final Register rax = new Register(0, 0, 8, "rax", CPU, RegisterFlag.Byte); - public static final Register rcx = new Register(1, 1, 8, "rcx", CPU, RegisterFlag.Byte); - public static final Register rdx = new Register(2, 2, 8, "rdx", CPU, RegisterFlag.Byte); - public static final Register rbx = new Register(3, 3, 8, "rbx", CPU, RegisterFlag.Byte); - public static final Register rsp = new Register(4, 4, 8, "rsp", CPU, RegisterFlag.Byte); - public static final Register rbp = new Register(5, 5, 8, "rbp", CPU, RegisterFlag.Byte); - public static final Register rsi = new Register(6, 6, 8, "rsi", CPU, RegisterFlag.Byte); - public static final Register rdi = new Register(7, 7, 8, "rdi", CPU, RegisterFlag.Byte); + public static final Register rax = new Register(0, 0, "rax", CPU); + public static final Register rcx = new Register(1, 1, "rcx", CPU); + public static final Register rdx = new Register(2, 2, "rdx", CPU); + public static final Register rbx = new Register(3, 3, "rbx", CPU); + public static final Register rsp = new Register(4, 4, "rsp", CPU); + public static final Register rbp = new Register(5, 5, "rbp", CPU); + public static final Register rsi = new Register(6, 6, "rsi", CPU); + public static final Register rdi = new Register(7, 7, "rdi", CPU); - public static final Register r8 = new Register(8, 8, 8, "r8", CPU, RegisterFlag.Byte); - public static final Register r9 = new Register(9, 9, 8, "r9", CPU, RegisterFlag.Byte); - public static final Register r10 = new Register(10, 10, 8, "r10", CPU, RegisterFlag.Byte); - public static final Register r11 = new Register(11, 11, 8, "r11", CPU, RegisterFlag.Byte); - public static final Register r12 = new Register(12, 12, 8, "r12", CPU, RegisterFlag.Byte); - public static final Register r13 = new Register(13, 13, 8, "r13", CPU, RegisterFlag.Byte); - public static final Register r14 = new Register(14, 14, 8, "r14", CPU, RegisterFlag.Byte); - public static final Register r15 = new Register(15, 15, 8, "r15", CPU, RegisterFlag.Byte); + public static final Register r8 = new Register(8, 8, "r8", CPU); + public static final Register r9 = new Register(9, 9, "r9", CPU); + public static final Register r10 = new Register(10, 10, "r10", CPU); + public static final Register r11 = new Register(11, 11, "r11", CPU); + public static final Register r12 = new Register(12, 12, "r12", CPU); + public static final Register r13 = new Register(13, 13, "r13", CPU); + public static final Register r14 = new Register(14, 14, "r14", CPU); + public static final Register r15 = new Register(15, 15, "r15", CPU); public static final Register[] cpuRegisters = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, @@ -63,23 +66,23 @@ }; // XMM registers - public static final Register xmm0 = new Register(16, 0, 8, "xmm0", FPU); - public static final Register xmm1 = new Register(17, 1, 8, "xmm1", FPU); - public static final Register xmm2 = new Register(18, 2, 8, "xmm2", FPU); - public static final Register xmm3 = new Register(19, 3, 8, "xmm3", FPU); - public static final Register xmm4 = new Register(20, 4, 8, "xmm4", FPU); - public static final Register xmm5 = new Register(21, 5, 8, "xmm5", FPU); - public static final Register xmm6 = new Register(22, 6, 8, "xmm6", FPU); - public static final Register xmm7 = new Register(23, 7, 8, "xmm7", FPU); + public static final Register xmm0 = new Register(16, 0, "xmm0", XMM); + public static final Register xmm1 = new Register(17, 1, "xmm1", XMM); + public static final Register xmm2 = new Register(18, 2, "xmm2", XMM); + public static final Register xmm3 = new Register(19, 3, "xmm3", XMM); + public static final Register xmm4 = new Register(20, 4, "xmm4", XMM); + public static final Register xmm5 = new Register(21, 5, "xmm5", XMM); + public static final Register xmm6 = new Register(22, 6, "xmm6", XMM); + public static final Register xmm7 = new Register(23, 7, "xmm7", XMM); - public static final Register xmm8 = new Register(24, 8, 8, "xmm8", FPU); - public static final Register xmm9 = new Register(25, 9, 8, "xmm9", FPU); - public static final Register xmm10 = new Register(26, 10, 8, "xmm10", FPU); - public static final Register xmm11 = new Register(27, 11, 8, "xmm11", FPU); - public static final Register xmm12 = new Register(28, 12, 8, "xmm12", FPU); - public static final Register xmm13 = new Register(29, 13, 8, "xmm13", FPU); - public static final Register xmm14 = new Register(30, 14, 8, "xmm14", FPU); - public static final Register xmm15 = new Register(31, 15, 8, "xmm15", FPU); + public static final Register xmm8 = new Register(24, 8, "xmm8", XMM); + public static final Register xmm9 = new Register(25, 9, "xmm9", XMM); + public static final Register xmm10 = new Register(26, 10, "xmm10", XMM); + public static final Register xmm11 = new Register(27, 11, "xmm11", XMM); + public static final Register xmm12 = new Register(28, 12, "xmm12", XMM); + public static final Register xmm13 = new Register(29, 13, "xmm13", XMM); + public static final Register xmm14 = new Register(30, 14, "xmm14", XMM); + public static final Register xmm15 = new Register(31, 15, "xmm15", XMM); public static final Register[] xmmRegisters = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, @@ -96,7 +99,7 @@ /** * Register used to construct an instruction-relative address. */ - public static final Register rip = new Register(32, -1, 0, "rip"); + public static final Register rip = new Register(32, -1, "rip", SPECIAL); public static final Register[] allRegisters = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, @@ -124,54 +127,6 @@ } // @formatter:on - @Override - public int getMaxVectorLength(Kind kind) { - if (supportedAVXVersion > 0) { - switch (kind) { - case Boolean: - return 32; - case Byte: - return 32; - case Short: - return 16; - case Char: - return 16; - case Int: - return 8; - case Float: - return 8; - case Long: - return 4; - case Double: - return 4; - case Object: - return 4; - } - } else { - switch (kind) { - case Boolean: - return 16; - case Byte: - return 16; - case Short: - return 8; - case Char: - return 8; - case Int: - return 4; - case Float: - return 4; - case Long: - return 2; - case Double: - return 2; - case Object: - return 2; - } - } - return 1; - } - public int getSupportedSSEVersion() { return supportedSSEVersion; } @@ -179,4 +134,44 @@ public int getSupportedAVXVersion() { return supportedAVXVersion; } + + @Override + public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { + if (!(platformKind instanceof Kind)) { + return false; + } + + Kind kind = (Kind) platformKind; + if (category == CPU) { + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + case Long: + case Object: + return true; + } + } else if (category == XMM) { + switch (kind) { + case Float: + case Double: + return true; + } + } + + return false; + } + + @Override + public PlatformKind getLargestStorableKind(RegisterCategory category) { + if (category == CPU) { + return Kind.Long; + } else if (category == XMM) { + return Kind.Double; + } else { + return Kind.Illegal; + } + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Tue Apr 30 23:09:37 2013 +0200 @@ -24,6 +24,7 @@ import java.nio.*; +import com.oracle.graal.api.code.Register.RegisterCategory; import com.oracle.graal.api.meta.*; /** @@ -164,4 +165,40 @@ public int getMaxVectorLength(@SuppressWarnings("unused") Kind kind) { return 1; } + + /** + * Gets the size in bytes of the specified kind for this target. + * + * @param kind the kind for which to get the size + * + * @return the size in bytes of {@code kind} + */ + public int getSizeInBytes(PlatformKind kind) { + switch ((Kind) kind) { + case Boolean: + return 1; + case Byte: + return 1; + case Char: + return 2; + case Short: + return 2; + case Int: + return 4; + case Long: + return 8; + case Float: + return 4; + case Double: + return 8; + case Object: + return wordSize; + default: + return 0; + } + } + + public abstract boolean canStoreValue(RegisterCategory category, PlatformKind kind); + + public abstract PlatformKind getLargestStorableKind(RegisterCategory category); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java Tue Apr 30 23:09:37 2013 +0200 @@ -24,6 +24,8 @@ import java.util.*; +import com.oracle.graal.api.meta.*; + /** * The callee save area (CSA) is a contiguous space in a stack frame used to save (and restore) the * values of the caller's registers. This class describes the layout of a CSA in terms of its @@ -69,7 +71,7 @@ * CSA * @param registers the registers that can be saved in the CSA */ - public CalleeSaveLayout(int frameOffsetToCSA, int size, int slotSize, Register... registers) { + public CalleeSaveLayout(Architecture architecture, int frameOffsetToCSA, int size, int slotSize, Register... registers) { this.frameOffsetToCSA = frameOffsetToCSA; assert slotSize == 0 || CodeUtil.isPowerOf2(slotSize); this.slotSize = slotSize; @@ -86,7 +88,8 @@ if (offset > maxOffset) { maxOffset = offset; } - offset += reg.spillSlotSize; + PlatformKind kind = architecture.getLargestStorableKind(reg.getRegisterCategory()); + offset += architecture.getSizeInBytes(kind); } if (size == -1) { this.size = offset; @@ -103,7 +106,8 @@ int index = offset / slotSize; regNumToIndex[reg.number] = index; indexToReg[index] = reg; - offset += reg.spillSlotSize; + PlatformKind kind = architecture.getLargestStorableKind(reg.getRegisterCategory()); + offset += architecture.getSizeInBytes(kind); } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Tue Apr 30 23:09:37 2013 +0200 @@ -34,18 +34,20 @@ private static final long serialVersionUID = -7213269157816016300L; + public static final RegisterCategory SPECIAL = new RegisterCategory("SPECIAL"); + /** * Invalid register. */ - public static final Register None = new Register(-1, -1, 0, "noreg"); + public static final Register None = new Register(-1, -1, "noreg", SPECIAL); /** * Frame pointer of the current method. All spill slots and outgoing stack-based arguments are * addressed relative to this register. */ - public static final Register Frame = new Register(-2, -2, 0, "framereg", RegisterFlag.CPU); + public static final Register Frame = new Register(-2, -2, "framereg", SPECIAL); - public static final Register CallerFrame = new Register(-3, -3, 0, "callerframereg", RegisterFlag.CPU); + public static final Register CallerFrame = new Register(-3, -3, "callerframereg", SPECIAL); /** * The identifier for this register that is unique across all the registers in a @@ -72,42 +74,32 @@ } /** - * The size of the stack slot used to spill the value of this register. + * A platform specific register category that describes which values can be stored in a + * register. */ - public final int spillSlotSize; - - /** - * The set of {@link RegisterFlag} values associated with this register. - */ - private final int flags; + private final RegisterCategory registerCategory; /** * An array of {@link RegisterValue} objects, for this register, with one entry per {@link Kind} * , indexed by {@link Kind#ordinal}. */ - private final RegisterValue[] values; + private final HashMap values; /** - * Attributes that characterize a register in a useful way. - * + * A platform specific register type that describes which values can be stored in a register. */ - public enum RegisterFlag { - /** - * Denotes an integral (i.e. non floating point) register. - */ - CPU, + public static class RegisterCategory { + + private String name; - /** - * Denotes a register whose lowest order byte can be addressed separately. - */ - Byte, + public RegisterCategory(String name) { + this.name = name; + } - /** - * Denotes a floating point register. - */ - FPU; - - public final int mask = 1 << (ordinal() + 1); + @Override + public String toString() { + return name; + } } /** @@ -115,33 +107,19 @@ * * @param number unique identifier for the register * @param encoding the target machine encoding for the register - * @param spillSlotSize the size of the stack slot used to spill the value of the register * @param name the mnemonic name for the register - * @param flags the set of {@link RegisterFlag} values for the register + * @param registerCategory the register category */ - public Register(int number, int encoding, int spillSlotSize, String name, RegisterFlag... flags) { + public Register(int number, int encoding, String name, RegisterCategory registerCategory) { this.number = number; this.name = name; - this.spillSlotSize = spillSlotSize; - this.flags = createMask(flags); + this.registerCategory = registerCategory; this.encoding = encoding; - - values = new RegisterValue[Kind.values().length]; - for (Kind kind : Kind.values()) { - values[kind.ordinal()] = new RegisterValue(kind, this); - } + this.values = new HashMap<>(); } - private static int createMask(RegisterFlag... flags) { - int result = 0; - for (RegisterFlag f : flags) { - result |= f.mask; - } - return result; - } - - public boolean isSet(RegisterFlag f) { - return (flags & f.mask) != 0; + public RegisterCategory getRegisterCategory() { + return registerCategory; } /** @@ -150,8 +128,14 @@ * @param kind the specified kind * @return the {@link RegisterValue} */ - public RegisterValue asValue(Kind kind) { - return values[kind.ordinal()]; + public RegisterValue asValue(PlatformKind kind) { + if (values.containsKey(kind)) { + return values.get(kind); + } else { + RegisterValue ret = new RegisterValue(kind, this); + values.put(kind, ret); + return ret; + } } /** @@ -173,29 +157,6 @@ } /** - * Determines if this a floating point register. - */ - public boolean isFpu() { - return isSet(RegisterFlag.FPU); - } - - /** - * Determines if this a general purpose register. - */ - public boolean isCpu() { - return isSet(RegisterFlag.CPU); - } - - /** - * Determines if this register has the {@link RegisterFlag#Byte} attribute set. - * - * @return {@code true} iff this register has the {@link RegisterFlag#Byte} attribute set. - */ - public boolean isByte() { - return isSet(RegisterFlag.Byte); - } - - /** * Gets a hash code for this register. * * @return the value of {@link #number} @@ -206,27 +167,6 @@ } /** - * Categorizes a set of registers by {@link RegisterFlag}. - * - * @param registers a list of registers to be categorized - * @return a map from each {@link RegisterFlag} constant to the list of registers for which the - * flag is {@linkplain #isSet(RegisterFlag) set} - */ - public static EnumMap categorize(Register[] registers) { - EnumMap result = new EnumMap<>(RegisterFlag.class); - for (RegisterFlag flag : RegisterFlag.values()) { - ArrayList list = new ArrayList<>(); - for (Register r : registers) { - if (r.isSet(flag)) { - list.add(r); - } - } - result.put(flag, list.toArray(new Register[list.size()])); - } - return result; - } - - /** * Gets the maximum register {@linkplain #number number} in a given set of registers. * * @param registers the set of registers to process diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterConfig.java Tue Apr 30 23:09:37 2013 +0200 @@ -22,10 +22,7 @@ */ package com.oracle.graal.api.code; -import java.util.*; - -import com.oracle.graal.api.code.CallingConvention.*; -import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; /** @@ -60,12 +57,11 @@ * given calling convention. * * @param type the type of calling convention - * @param flag specifies whether registers for {@linkplain RegisterFlag#CPU integral} or - * {@linkplain RegisterFlag#FPU floating point} parameters are being requested + * @param kind specifies what kind of registers is being requested * @return the ordered set of registers that may be used to pass parameters in a call conforming * to {@code type} */ - Register[] getCallingConventionRegisters(Type type, RegisterFlag flag); + Register[] getCallingConventionRegisters(Type type, Kind kind); /** * Gets the set of registers that can be used by the register allocator. @@ -73,16 +69,10 @@ Register[] getAllocatableRegisters(); /** - * Gets the set of registers that can be used by the register allocator, - * {@linkplain Register#categorize(Register[]) categorized} by register - * {@linkplain RegisterFlag flags}. - * - * @return a map from each {@link RegisterFlag} constant to the list of - * {@linkplain #getAllocatableRegisters() allocatable} registers for which the flag is - * set - * + * Gets the set of registers that can be used by the register allocator for a value of a + * particular kind. */ - EnumMap getCategorizedAllocatableRegisters(); + Register[] getAllocatableRegisters(PlatformKind kind); /** * Gets the registers whose values must be preserved by a method across any call it makes. @@ -102,7 +92,6 @@ * * @return an array where an element at index i holds the attributes of the register whose * number is i - * @see Register#categorize(Register[]) */ RegisterAttributes[] getAttributesMap(); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java Tue Apr 30 23:09:37 2013 +0200 @@ -27,8 +27,8 @@ /** * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance * of {@link RegisterValue} for each ({@link Register}, {@link Kind}) pair. Use - * {@link Register#asValue(Kind)} to retrieve the canonical {@link RegisterValue} instance for a - * given (register,kind) pair. + * {@link Register#asValue(PlatformKind)} to retrieve the canonical {@link RegisterValue} instance + * for a given (register,kind) pair. */ public final class RegisterValue extends AllocatableValue { @@ -39,14 +39,14 @@ /** * Should only be called from {@link Register#Register} to ensure canonicalization. */ - protected RegisterValue(Kind kind, Register register) { + protected RegisterValue(PlatformKind kind, Register register) { super(kind); this.reg = register; } @Override public int hashCode() { - return (getRegister().number << 4) ^ getKind().ordinal(); + return (getRegister().number << 4) ^ getPlatformKind().hashCode(); } @Override diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java Tue Apr 30 23:09:37 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.api.code; -import static com.oracle.graal.api.meta.Kind.*; +import java.util.*; import com.oracle.graal.api.meta.*; @@ -46,25 +46,20 @@ * @param addFrameSize Specifies if the offset is relative to the stack pointer, or the * beginning of the frame (stack pointer + total frame size). */ - public static StackSlot get(Kind kind, int offset, boolean addFrameSize) { - assert kind.getStackKind() == kind; + public static StackSlot get(PlatformKind kind, int offset, boolean addFrameSize) { assert addFrameSize || offset >= 0; if (offset % CACHE_GRANULARITY == 0) { - StackSlot[][] cache; - int index = offset / CACHE_GRANULARITY; + StackSlot slot; if (!addFrameSize) { - cache = OUT_CACHE; + slot = OUT_CACHE.lookup(kind, offset); } else if (offset >= 0) { - cache = IN_CACHE; + slot = IN_CACHE.lookup(kind, offset); } else { - cache = SPILL_CACHE; - index = -index; + slot = SPILL_CACHE.lookup(kind, offset); } - StackSlot[] slots = cache[kind.ordinal()]; - if (index < slots.length) { - StackSlot slot = slots[index]; - assert slot.getKind() == kind && slot.offset == offset && slot.addFrameSize == addFrameSize; + if (slot != null) { + assert slot.getPlatformKind().equals(kind) && slot.offset == offset && slot.addFrameSize == addFrameSize; return slot; } } @@ -72,10 +67,10 @@ } /** - * Private constructor to enforce use of {@link #get(Kind, int, boolean)} so that a cache can be - * used. + * Private constructor to enforce use of {@link #get(PlatformKind, int, boolean)} so that a + * cache can be used. */ - private StackSlot(Kind kind, int offset, boolean addFrameSize) { + private StackSlot(PlatformKind kind, int offset, boolean addFrameSize) { super(kind); this.offset = offset; this.addFrameSize = addFrameSize; @@ -107,7 +102,7 @@ @Override public int hashCode() { - return getKind().ordinal() ^ (offset << 4) ^ (addFrameSize ? 15 : 0); + return getPlatformKind().hashCode() ^ (offset << 4) ^ (addFrameSize ? 15 : 0); } @Override @@ -117,7 +112,7 @@ } if (o instanceof StackSlot) { StackSlot l = (StackSlot) o; - return l.getKind() == getKind() && l.offset == offset && l.addFrameSize == addFrameSize; + return l.getPlatformKind().equals(getPlatformKind()) && l.offset == offset && l.addFrameSize == addFrameSize; } return false; } @@ -139,7 +134,7 @@ public StackSlot asOutArg() { assert offset >= 0; if (addFrameSize) { - return get(getKind(), offset, false); + return get(getPlatformKind(), offset, false); } return this; } @@ -150,28 +145,48 @@ public StackSlot asInArg() { assert offset >= 0; if (!addFrameSize) { - return get(getKind(), offset, true); + return get(getPlatformKind(), offset, true); } return this; } - private static final int CACHE_GRANULARITY = 8; private static final int SPILL_CACHE_PER_KIND_SIZE = 100; private static final int PARAM_CACHE_PER_KIND_SIZE = 10; + private static final int CACHE_GRANULARITY = 8; - private static final StackSlot[][] SPILL_CACHE = makeCache(SPILL_CACHE_PER_KIND_SIZE, -1, true); - private static final StackSlot[][] IN_CACHE = makeCache(PARAM_CACHE_PER_KIND_SIZE, 1, true); - private static final StackSlot[][] OUT_CACHE = makeCache(PARAM_CACHE_PER_KIND_SIZE, 1, false); + private static class Cache extends HashMap { + + private static final long serialVersionUID = 4424132866289682843L; + + private final int cachePerKindSize; + private final int sign; + private final boolean addFrameSize; + + Cache(int cachePerKindSize, int sign, boolean addFrameSize) { + this.cachePerKindSize = cachePerKindSize; + this.sign = sign; + this.addFrameSize = addFrameSize; + } - private static StackSlot[][] makeCache(int cachePerKindSize, int sign, boolean addFrameSize) { - StackSlot[][] cache = new StackSlot[Kind.values().length][]; - for (Kind kind : new Kind[]{Illegal, Int, Long, Float, Double, Object}) { - StackSlot[] slots = new StackSlot[cachePerKindSize]; - for (int i = 0; i < cachePerKindSize; i++) { - slots[i] = new StackSlot(kind, sign * i * CACHE_GRANULARITY, addFrameSize); + StackSlot lookup(PlatformKind kind, int offset) { + int index = sign * offset / CACHE_GRANULARITY; + StackSlot[] slots = this.get(kind); + if (slots == null) { + slots = new StackSlot[cachePerKindSize]; + for (int i = 0; i < cachePerKindSize; i++) { + slots[i] = new StackSlot(kind, sign * i * CACHE_GRANULARITY, addFrameSize); + } + this.put(kind, slots); } - cache[kind.ordinal()] = slots; + if (index < slots.length) { + return slots[index]; + } else { + return null; + } } - return cache; } + + private static final Cache SPILL_CACHE = new Cache(SPILL_CACHE_PER_KIND_SIZE, -1, true); + private static final Cache IN_CACHE = new Cache(PARAM_CACHE_PER_KIND_SIZE, 1, true); + private static final Cache OUT_CACHE = new Cache(PARAM_CACHE_PER_KIND_SIZE, 1, false); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Tue Apr 30 23:09:37 2013 +0200 @@ -83,39 +83,6 @@ } /** - * Gets the size in bytes of the specified kind for this target. - * - * @param kind the kind for which to get the size - * @return the size in bytes of {@code kind} - */ - public int sizeInBytes(Kind kind) { - // Checkstyle: stop - switch (kind) { - case Boolean: - return 1; - case Byte: - return 1; - case Char: - return 2; - case Short: - return 2; - case Int: - return 4; - case Long: - return 8; - case Float: - return 4; - case Double: - return 8; - case Object: - return wordSize; - default: - return 0; - } - // Checkstyle: resume - } - - /** * Aligns the given frame size (without return instruction pointer) to the stack alignment size * and return the aligned size (without return instruction pointer). * diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java Tue Apr 30 23:09:37 2013 +0200 @@ -168,7 +168,7 @@ @Override public int hashCode() { - return getKind().ordinal() + type.hashCode(); + return getPlatformKind().hashCode() + type.hashCode(); } @Override diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AllocatableValue.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AllocatableValue.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AllocatableValue.java Tue Apr 30 23:09:37 2013 +0200 @@ -32,8 +32,7 @@ public static final AllocatableValue[] NONE = {}; - public AllocatableValue(Kind kind) { - super(kind); + public AllocatableValue(PlatformKind platformKind) { + super(platformKind); } - } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Tue Apr 30 23:09:37 2013 +0200 @@ -38,5 +38,6 @@ Unresolved, JavaSubroutineMismatch, ArithmeticException, - RuntimeConstraint + RuntimeConstraint, + LoopLimitCheck, } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java Tue Apr 30 23:09:37 2013 +0200 @@ -29,7 +29,7 @@ * {@link Kind#Int} for {@code int} and {@link Kind#Object} for all object types. A kind has a * single character short name, a Java name, and a set of flags further describing its behavior. */ -public enum Kind { +public enum Kind implements PlatformKind { /** The primitive boolean kind, represented as an int on the stack. */ Boolean('z', "boolean", true, java.lang.Boolean.TYPE, java.lang.Boolean.class), diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PlatformKind.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PlatformKind.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,31 @@ +/* + * 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.meta; + +/** + * Represents a platform-specific low-level type for values. + */ +public interface PlatformKind { + + String name(); +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Tue Apr 30 23:09:37 2013 +0200 @@ -41,14 +41,20 @@ }; private final Kind kind; + private final PlatformKind platformKind; /** * Initializes a new value of the specified kind. * - * @param kind the kind + * @param platformKind the kind */ - protected Value(Kind kind) { - this.kind = kind; + protected Value(PlatformKind platformKind) { + this.platformKind = platformKind; + if (platformKind instanceof Kind) { + this.kind = (Kind) platformKind; + } else { + this.kind = Kind.Illegal; + } } /** @@ -65,4 +71,11 @@ public final Kind getKind() { return kind; } + + /** + * Returns the platform specific kind used to store this value. + */ + public final PlatformKind getPlatformKind() { + return platformKind; + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Tue Apr 30 23:09:37 2013 +0200 @@ -380,7 +380,7 @@ } public final void addsd(Register dst, Register src) { - assert dst.isFpu() && src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM && src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -389,7 +389,7 @@ } public final void addsd(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefix(src, dst); emitByte(0x0F); @@ -398,7 +398,7 @@ } public final void addss(Register dst, Register src) { - assert dst.isFpu() && src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM && src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -407,7 +407,7 @@ } public final void addss(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefix(src, dst); emitByte(0x0F); @@ -540,7 +540,7 @@ } public final void cvtsd2ss(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefix(src, dst); emitByte(0x0F); @@ -549,8 +549,8 @@ } public final void cvtsd2ss(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -559,7 +559,7 @@ } public final void cvtsi2sdl(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefix(src, dst); emitByte(0x0F); @@ -568,7 +568,7 @@ } public final void cvtsi2sdl(Register dst, Register src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -577,7 +577,7 @@ } public final void cvtsi2ssl(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefix(src, dst); emitByte(0x0F); @@ -586,7 +586,7 @@ } public final void cvtsi2ssl(Register dst, Register src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -595,7 +595,7 @@ } public final void cvtss2sd(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefix(src, dst); emitByte(0x0F); @@ -604,8 +604,8 @@ } public final void cvtss2sd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -622,7 +622,7 @@ } public final void cvttsd2sil(Register dst, Register src) { - assert src.isFpu(); + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -639,7 +639,7 @@ } public final void cvttss2sil(Register dst, Register src) { - assert src.isFpu(); + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -654,7 +654,7 @@ } public final void divsd(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefix(src, dst); emitByte(0x0F); @@ -663,8 +663,8 @@ } public final void divsd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -673,7 +673,7 @@ } public final void divss(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefix(src, dst); emitByte(0x0F); @@ -682,8 +682,8 @@ } public final void divss(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -862,8 +862,8 @@ } public final void movapd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; int dstenc = dst.encoding; int srcenc = src.encoding; emitByte(0x66); @@ -887,8 +887,8 @@ } public final void movaps(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; int dstenc = dst.encoding; int srcenc = src.encoding; if (dstenc < 8) { @@ -918,22 +918,22 @@ } public final void movb(AMD64Address dst, Register src) { - assert src.isByte() : "must have byte register"; + assert src.getRegisterCategory() == AMD64.CPU : "must have byte register"; prefix(dst, src); // , true) emitByte(0x88); emitOperandHelper(src, dst); } public final void movdl(Register dst, Register src) { - if (dst.isFpu()) { - assert !src.isFpu() : "does this hold?"; + if (dst.getRegisterCategory() == AMD64.XMM) { + assert src.getRegisterCategory() != AMD64.XMM : "does this hold?"; emitByte(0x66); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0x6E); emitByte(0xC0 | encode); - } else if (src.isFpu()) { - assert !dst.isFpu(); + } else if (src.getRegisterCategory() == AMD64.XMM) { + assert dst.getRegisterCategory() != AMD64.XMM; emitByte(0x66); // swap src/dst to get correct prefix int encode = prefixAndEncode(src.encoding, dst.encoding); @@ -981,7 +981,7 @@ * {@link AMD64MacroAssembler#movflt(Register, Register)}. */ public final void movlpd(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0x66); prefix(src, dst); emitByte(0x0F); @@ -990,7 +990,7 @@ } public final void movq(Register dst, AMD64Address src) { - if (dst.isFpu()) { + if (dst.getRegisterCategory() == AMD64.XMM) { emitByte(0xF3); prefixq(src, dst); emitByte(0x0F); @@ -1010,7 +1010,7 @@ } public final void movq(AMD64Address dst, Register src) { - if (src.isFpu()) { + if (src.getRegisterCategory() == AMD64.XMM) { emitByte(0x66); prefixq(dst, src); emitByte(0x0F); @@ -1038,8 +1038,8 @@ } public final void movsd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -1048,7 +1048,7 @@ } public final void movsd(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefix(src, dst); emitByte(0x0F); @@ -1057,7 +1057,7 @@ } public final void movsd(AMD64Address dst, Register src) { - assert src.isFpu(); + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefix(dst, src); emitByte(0x0F); @@ -1066,8 +1066,8 @@ } public final void movss(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -1076,7 +1076,7 @@ } public final void movss(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefix(src, dst); emitByte(0x0F); @@ -1085,7 +1085,7 @@ } public final void movss(AMD64Address dst, Register src) { - assert src.isFpu(); + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefix(dst, src); emitByte(0x0F); @@ -1137,7 +1137,7 @@ } public final void mulsd(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefix(src, dst); emitByte(0x0F); @@ -1146,8 +1146,8 @@ } public final void mulsd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixAndEncode(dst.encoding, src.encoding); @@ -1157,7 +1157,7 @@ } public final void mulss(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefix(src, dst); @@ -1167,8 +1167,8 @@ } public final void mulss(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -1512,8 +1512,8 @@ } public final void sqrtsd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; // HMM Table D-1 says sse2 // assert is64 || target.supportsSSE(); emitByte(0xF2); @@ -1545,8 +1545,8 @@ } public final void subsd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -1555,7 +1555,7 @@ } public final void subsd(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefix(src, dst); @@ -1565,8 +1565,8 @@ } public final void subss(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -1575,7 +1575,7 @@ } public final void subss(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefix(src, dst); @@ -1611,20 +1611,20 @@ } public final void ucomisd(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0x66); ucomiss(dst, src); } public final void ucomisd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0x66); ucomiss(dst, src); } public final void ucomiss(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; prefix(src, dst); emitByte(0x0F); @@ -1633,8 +1633,8 @@ } public final void ucomiss(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; + assert src.getRegisterCategory() == AMD64.XMM; int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0x2E); @@ -1668,7 +1668,7 @@ } public final void andps(Register dst, Register src) { - assert dst.isFpu() && src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM && src.getRegisterCategory() == AMD64.XMM; int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0x54); @@ -1676,7 +1676,7 @@ } public final void andps(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; prefix(src, dst); emitByte(0x0F); emitByte(0x54); @@ -1694,7 +1694,7 @@ } public final void orps(Register dst, Register src) { - assert dst.isFpu() && src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM && src.getRegisterCategory() == AMD64.XMM; int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0x56); @@ -1702,7 +1702,7 @@ } public final void orps(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; prefix(src, dst); emitByte(0x0F); emitByte(0x56); @@ -1720,7 +1720,7 @@ } public final void xorps(Register dst, Register src) { - assert dst.isFpu() && src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM && src.getRegisterCategory() == AMD64.XMM; int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0x57); @@ -1728,7 +1728,7 @@ } public final void xorps(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; prefix(src, dst); emitByte(0x0F); emitByte(0x57); @@ -2014,7 +2014,7 @@ } public final void cvtsi2sdq(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); prefixq(src, dst); emitByte(0x0F); @@ -2023,7 +2023,7 @@ } public final void cvtsi2sdq(Register dst, Register src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixqAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -2032,7 +2032,7 @@ } public final void cvtsi2ssq(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); prefixq(src, dst); emitByte(0x0F); @@ -2041,7 +2041,7 @@ } public final void cvtsi2ssq(Register dst, Register src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixqAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -2058,7 +2058,7 @@ } public final void cvttsd2siq(Register dst, Register src) { - assert src.isFpu(); + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); int encode = prefixqAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -2075,7 +2075,7 @@ } public final void cvttss2siq(Register dst, Register src) { - assert src.isFpu(); + assert src.getRegisterCategory() == AMD64.XMM; emitByte(0xF3); int encode = prefixqAndEncode(dst.encoding, src.encoding); emitByte(0x0F); @@ -2154,13 +2154,12 @@ // table D-1 says MMX/SSE2 emitByte(0x66); - if (dst.isFpu()) { - assert dst.isFpu(); + if (dst.getRegisterCategory() == AMD64.XMM) { int encode = prefixqAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0x6E); emitByte(0xC0 | encode); - } else if (src.isFpu()) { + } else if (src.getRegisterCategory() == AMD64.XMM) { // swap src/dst to get correct prefix int encode = prefixqAndEncode(src.encoding, dst.encoding); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Tue Apr 30 23:09:37 2013 +0200 @@ -166,21 +166,12 @@ } } - public final void signExtendByte(Register reg) { - if (reg.isByte()) { - movsxb(reg, reg); - } else { - shll(reg, 24); - sarl(reg, 24); - } - } - public final void signExtendShort(Register reg) { movsxw(reg, reg); } public final void movflt(Register dst, Register src) { - assert dst.isFpu() && src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM && src.getRegisterCategory() == AMD64.XMM; if (UseXmmRegToRegMoveAll) { movaps(dst, src); } else { @@ -189,17 +180,17 @@ } public final void movflt(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; movss(dst, src); } public final void movflt(AMD64Address dst, Register src) { - assert src.isFpu(); + assert src.getRegisterCategory() == AMD64.XMM; movss(dst, src); } public final void movdbl(Register dst, Register src) { - assert dst.isFpu() && src.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM && src.getRegisterCategory() == AMD64.XMM; if (UseXmmRegToRegMoveAll) { movapd(dst, src); } else { @@ -208,7 +199,7 @@ } public final void movdbl(Register dst, AMD64Address src) { - assert dst.isFpu(); + assert dst.getRegisterCategory() == AMD64.XMM; if (UseXmmLoadAndClearUpper) { movsd(dst, src); } else { @@ -227,7 +218,7 @@ } public final void flog(Register dest, Register value, boolean base10) { - assert dest.isFpu() && value.isFpu(); + assert dest.getRegisterCategory() == AMD64.XMM && value.getRegisterCategory() == AMD64.XMM; AMD64Address tmp = new AMD64Address(AMD64.rsp); if (base10) { @@ -262,7 +253,7 @@ } private AMD64Address trigPrologue(Register value) { - assert value.isFpu(); + assert value.getRegisterCategory() == AMD64.XMM; AMD64Address tmp = new AMD64Address(AMD64.rsp); subq(AMD64.rsp, 8); movsd(tmp, value); @@ -271,7 +262,7 @@ } private void trigEpilogue(Register dest, AMD64Address tmp) { - assert dest.isFpu(); + assert dest.getRegisterCategory() == AMD64.XMM; fstp(tmp); movsd(dest, tmp); addq(AMD64.rsp, 8); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Apr 30 23:09:37 2013 +0200 @@ -87,11 +87,11 @@ private static final RegisterValue RDX_L = AMD64.rdx.asValue(Kind.Long); private static final RegisterValue RCX_I = AMD64.rcx.asValue(Kind.Int); - public static class AMD64SpillMoveFactory implements LIR.SpillMoveFactory { + private class AMD64SpillMoveFactory implements LIR.SpillMoveFactory { @Override public LIRInstruction createMove(AllocatableValue result, Value input) { - return AMD64LIRGenerator.createMove(result, input); + return AMD64LIRGenerator.this.createMove(result, input); } } @@ -143,7 +143,7 @@ return result; } - private static AMD64LIRInstruction createMove(AllocatableValue dst, Value src) { + protected AMD64LIRInstruction createMove(AllocatableValue dst, Value src) { if (src instanceof AMD64AddressValue) { return new LeaOp(dst, (AMD64AddressValue) src); } else if (isRegister(src) || isStackSlot(dst)) { @@ -525,7 +525,7 @@ } private void emitDivRem(AMD64Arithmetic op, Value a, Value b, LIRFrameState state) { - AllocatableValue rax = AMD64.rax.asValue(a.getKind()); + AllocatableValue rax = AMD64.rax.asValue(a.getPlatformKind()); emitMove(rax, a); append(new DivRemOp(op, rax, asAllocatable(b), state)); } @@ -554,12 +554,12 @@ emitDivRem(LDIV, a, b, state(deopting)); return emitMove(RAX_L); case Float: { - Variable result = newVariable(a.getKind()); + Variable result = newVariable(a.getPlatformKind()); append(new BinaryRegStack(FDIV, result, asAllocatable(a), asAllocatable(b))); return result; } case Double: { - Variable result = newVariable(a.getKind()); + Variable result = newVariable(a.getPlatformKind()); append(new BinaryRegStack(DDIV, result, asAllocatable(a), asAllocatable(b))); return result; } @@ -657,7 +657,7 @@ } private Variable emitShift(AMD64Arithmetic op, Value a, Value b) { - Variable result = newVariable(a.getKind()); + Variable result = newVariable(a.getPlatformKind()); AllocatableValue input = asAllocatable(a); if (isConstant(b)) { append(new BinaryRegConst(op, result, input, asConstant(b))); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Tue Apr 30 23:09:37 2013 +0200 @@ -24,6 +24,7 @@ import java.lang.reflect.Method; +import org.junit.Ignore; import org.junit.Test; /** @@ -36,7 +37,12 @@ compile("testAddConst1I"); } - public static int testAddConst1I(int a) { + @Ignore + public void testAddInvoke() { + invoke(compile("testAddConst1I"), new Integer(42)); + } + + public int testAddConst1I(int a) { return a + 1; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Tue Apr 30 23:09:37 2013 +0200 @@ -24,33 +24,57 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.ptx.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; +import com.oracle.graal.api.code.CompilationResult; +import com.oracle.graal.api.code.SpeculationLog; +import com.oracle.graal.api.code.TargetDescription; +import com.oracle.graal.api.runtime.Graal; +import com.oracle.graal.compiler.GraalCompiler; +import com.oracle.graal.compiler.ptx.PTXBackend; +import com.oracle.graal.compiler.test.GraalCompilerTest; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.java.GraphBuilderConfiguration; +import com.oracle.graal.java.GraphBuilderPhase; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.spi.GraalCodeCacheProvider; +import com.oracle.graal.phases.OptimisticOptimizations; +import com.oracle.graal.phases.PhasePlan; import com.oracle.graal.phases.PhasePlan.PhasePosition; -import com.oracle.graal.ptx.*; +import com.oracle.graal.ptx.PTX; public abstract class PTXTestBase extends GraalCompilerTest { + private StructuredGraph sg; + protected CompilationResult compile(String test) { StructuredGraph graph = parse(test); + sg = graph; Debug.dump(graph, "Graph"); TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); - PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target); + PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(GraalCodeCacheProvider.class), target); PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); new PTXPhase().apply(graph); - CompilationResult result = GraalCompiler.compileMethod(runtime, graalRuntime().getReplacements(), ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE, - new SpeculationLog()); + CompilationResult result = GraalCompiler.compileMethod(runtime, graalRuntime().getReplacements(), + ptxBackend, target, graph.method(), graph, null, phasePlan, + OptimisticOptimizations.NONE, new SpeculationLog()); return result; } + protected StructuredGraph getStructuredGraph() { + return sg; + } + + @SuppressWarnings("unused") + protected void invoke(CompilationResult result, Object... args) { + try { + // not quite yet - need multi-architecture Method changes from JDK-8013168 + // Object[] executeArgs = argsWithReceiver(this, args); + // InstalledCode installedCode = runtime.addMethod(getStructuredGraph().method(), result); + // installedCode.executeVarargs(executeArgs); + } catch (Throwable th) { + th.printStackTrace(); + } + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Tue Apr 30 23:09:37 2013 +0200 @@ -50,9 +50,6 @@ @Override public void enter(TargetMethodAssembler tasm) { - Buffer codeBuffer = tasm.asm.codeBuffer; - codeBuffer.emitString(".version 1.4"); - codeBuffer.emitString(".target sm_10"); // codeBuffer.emitString(".address_size 32"); // PTX ISA version 2.3 } @@ -62,6 +59,11 @@ } @Override + protected AbstractAssembler createAssembler(FrameMap frameMap) { + return new PTXAssembler(target, frameMap.registerConfig); + } + + @Override public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { // Omit the frame if the method: // - has no spill slots or other slots allocated during register allocation @@ -69,9 +71,9 @@ // - has no incoming arguments passed on the stack // - has no instructions with debug info FrameMap frameMap = lirGen.frameMap; - AbstractAssembler masm = new PTXAssembler(target, frameMap.registerConfig); + AbstractAssembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(); - TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult); + TargetMethodAssembler tasm = new PTXTargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult); tasm.setFrameSize(frameMap.frameSize()); return tasm; } @@ -81,6 +83,8 @@ // Emit the prologue final String name = method.getName(); Buffer codeBuffer = tasm.asm.codeBuffer; + codeBuffer.emitString(".version 1.4"); + codeBuffer.emitString(".target sm_10"); codeBuffer.emitString0(".entry " + name + " ("); codeBuffer.emitString(""); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx; + +import com.oracle.graal.api.code.CodeCacheProvider; +import com.oracle.graal.api.code.CompilationResult; +import com.oracle.graal.api.code.TargetDescription; +import com.oracle.graal.asm.AbstractAssembler; +import com.oracle.graal.hotspot.HotSpotGraalRuntime; +import com.oracle.graal.hotspot.bridge.CompilerToGPU; +import com.oracle.graal.hotspot.meta.HotSpotMethod; +import com.oracle.graal.lir.FrameMap; +import com.oracle.graal.lir.asm.FrameContext; +import com.oracle.graal.lir.asm.TargetMethodAssembler; + +public class PTXTargetMethodAssembler extends TargetMethodAssembler { + + private static CompilerToGPU toGPU = HotSpotGraalRuntime.graalRuntime().getCompilerToGPU(); + private static boolean validDevice = toGPU.deviceInit(); + + // detach ?? + + public PTXTargetMethodAssembler(TargetDescription target, + CodeCacheProvider runtime, FrameMap frameMap, + AbstractAssembler asm, FrameContext frameContext, + CompilationResult compilationResult) { + super(target, runtime, frameMap, asm, frameContext, compilationResult); + } + + @Override + public CompilationResult finishTargetMethod(Object name, boolean isStub) { + CompilationResult graalCompile = super.finishTargetMethod(name, isStub); + + try { + if (validDevice) { + HotSpotMethod method = (HotSpotMethod) name; + toGPU.generateKernel(graalCompile.getTargetCode(), method.getName()); + } + } catch (Throwable th) { + th.printStackTrace(); + } + + return graalCompile; // for now + } +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Tue Apr 30 23:09:37 2013 +0200 @@ -35,12 +35,12 @@ public void testImplies() { StructuredGraph graph = new StructuredGraph(); - EndNode trueEnd = graph.add(new EndNode()); - EndNode falseEnd = graph.add(new EndNode()); + AbstractEndNode trueEnd = graph.add(new EndNode()); + AbstractEndNode falseEnd = graph.add(new EndNode()); - BeginNode trueBegin = graph.add(new BeginNode()); + AbstractBeginNode trueBegin = graph.add(new BeginNode()); trueBegin.setNext(trueEnd); - BeginNode falseBegin = graph.add(new BeginNode()); + AbstractBeginNode falseBegin = graph.add(new BeginNode()); falseBegin.setNext(falseEnd); IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5)); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierVerificationTest.java Tue Apr 30 23:09:37 2013 +0200 @@ -683,7 +683,7 @@ } @Override - protected State afterSplit(BeginNode node, State oldState) { + protected State afterSplit(AbstractBeginNode node, State oldState) { return new State(); } }; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Apr 30 23:09:37 2013 +0200 @@ -146,7 +146,7 @@ plan.runPhases(PhasePosition.LOW_LEVEL, graph); - LowTierContext lowTierContext = new LowTierContext(runtime, assumptions, replacements, target); + LowTierContext lowTierContext = new LowTierContext(runtime, assumptions, replacements, target, optimisticOpts); Suites.DEFAULT.getLowTier().apply(graph, lowTierContext); final SchedulePhase schedule = new SchedulePhase(); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Tue Apr 30 23:09:37 2013 +0200 @@ -430,7 +430,7 @@ /** * The kind of this interval. */ - private Kind kind; + private PlatformKind kind; /** * The head of the list of ranges describing this interval. This list is sorted by @@ -501,15 +501,15 @@ void assignLocation(AllocatableValue newLocation) { if (isRegister(newLocation)) { assert this.location == null : "cannot re-assign location for " + this; - if (newLocation.getKind() == Kind.Illegal && kind != Kind.Illegal) { + if (newLocation.getPlatformKind() == Kind.Illegal && kind != Kind.Illegal) { this.location = asRegister(newLocation).asValue(kind); return; } } else { assert this.location == null || isRegister(this.location) : "cannot re-assign location for " + this; assert isStackSlot(newLocation); - assert newLocation.getKind() != Kind.Illegal; - assert newLocation.getKind() == this.kind; + assert newLocation.getPlatformKind() != Kind.Illegal; + assert newLocation.getPlatformKind() == this.kind; } this.location = newLocation; } @@ -522,14 +522,13 @@ return location; } - public Kind kind() { + public PlatformKind kind() { assert !isRegister(operand) : "cannot access type for fixed interval"; return kind; } - void setKind(Kind kind) { + void setKind(PlatformKind kind) { assert isRegister(operand) || this.kind() == Kind.Illegal || this.kind() == kind : "overwriting existing type"; - assert kind == kind.getStackKind() || kind == Kind.Short : "these kinds should have int type registers"; this.kind = kind; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue Apr 30 23:09:37 2013 +0200 @@ -305,7 +305,7 @@ intervals = Arrays.copyOf(intervals, intervals.length * 2); } intervalsSize++; - Variable variable = new Variable(source.kind(), ir.nextVariable(), asVariable(source.operand).flag); + Variable variable = new Variable(source.kind(), ir.nextVariable()); assert variables.size() == variable.index; variables.add(variable); @@ -968,7 +968,7 @@ TTY.println(blockData.get(block).liveOut.toString()); } - void addUse(AllocatableValue operand, int from, int to, RegisterPriority registerPriority, Kind kind) { + void addUse(AllocatableValue operand, int from, int to, RegisterPriority registerPriority, PlatformKind kind) { if (!isProcessed(operand)) { return; } @@ -987,7 +987,7 @@ interval.addUsePos(to & ~1, registerPriority); } - void addTemp(AllocatableValue operand, int tempPos, RegisterPriority registerPriority, Kind kind) { + void addTemp(AllocatableValue operand, int tempPos, RegisterPriority registerPriority, PlatformKind kind) { if (!isProcessed(operand)) { return; } @@ -1008,7 +1008,7 @@ return !isRegister(operand) || attributes(asRegister(operand)).isAllocatable(); } - void addDef(AllocatableValue operand, int defPos, RegisterPriority registerPriority, Kind kind) { + void addDef(AllocatableValue operand, int defPos, RegisterPriority registerPriority, PlatformKind kind) { if (!isProcessed(operand)) { return; } @@ -1197,7 +1197,7 @@ @Override public Value doValue(Value operand, OperandMode mode, EnumSet flags) { if (isVariableOrRegister(operand)) { - addDef((AllocatableValue) operand, opId, registerPriorityOfOutputOperand(op), operand.getKind().getStackKind()); + addDef((AllocatableValue) operand, opId, registerPriorityOfOutputOperand(op), operand.getPlatformKind()); addRegisterHint(op, operand, mode, flags, true); } return operand; @@ -1208,7 +1208,7 @@ @Override public Value doValue(Value operand, OperandMode mode, EnumSet flags) { if (isVariableOrRegister(operand)) { - addTemp((AllocatableValue) operand, opId, RegisterPriority.MustHaveRegister, operand.getKind().getStackKind()); + addTemp((AllocatableValue) operand, opId, RegisterPriority.MustHaveRegister, operand.getPlatformKind()); addRegisterHint(op, operand, mode, flags, false); } return operand; @@ -1220,7 +1220,7 @@ public Value doValue(Value operand, OperandMode mode, EnumSet flags) { if (isVariableOrRegister(operand)) { RegisterPriority p = registerPriorityOfInputOperand(flags); - addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getKind().getStackKind()); + addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getPlatformKind()); addRegisterHint(op, operand, mode, flags, false); } return operand; @@ -1232,7 +1232,7 @@ public Value doValue(Value operand, OperandMode mode, EnumSet flags) { if (isVariableOrRegister(operand)) { RegisterPriority p = registerPriorityOfInputOperand(flags); - addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getKind().getStackKind()); + addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getPlatformKind()); addRegisterHint(op, operand, mode, flags, false); } return operand; @@ -1247,7 +1247,7 @@ @Override public Value doValue(Value operand) { - addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getKind().getStackKind()); + addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getPlatformKind()); return operand; } }); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Tue Apr 30 23:09:37 2013 +0200 @@ -29,7 +29,6 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.alloc.Interval.RegisterBinding; import com.oracle.graal.compiler.alloc.Interval.RegisterPriority; @@ -811,8 +810,7 @@ } void initVarsForAlloc(Interval interval) { - EnumMap categorizedRegs = allocator.frameMap.registerConfig.getCategorizedAllocatableRegisters(); - availableRegs = categorizedRegs.get(asVariable(interval.operand).flag); + availableRegs = allocator.frameMap.registerConfig.getAllocatableRegisters(interval.kind()); } static boolean isMove(LIRInstruction op, Interval from, Interval to) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java Tue Apr 30 23:09:37 2013 +0200 @@ -207,7 +207,7 @@ } private void insertMove(Value fromOpr, Interval toInterval) { - assert fromOpr.getKind() == toInterval.kind() : "move between different types"; + assert fromOpr.getPlatformKind() == toInterval.kind() : "move between different types"; assert insertIdx != -1 : "must setup insert position first"; AllocatableValue toOpr = toInterval.operand; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Apr 30 23:09:37 2013 +0200 @@ -142,23 +142,18 @@ /** * Creates a new {@linkplain Variable variable}. * - * @param kind The kind of the new variable. + * @param platformKind The kind of the new variable. * @return a new variable */ @Override - public Variable newVariable(Kind kind) { - Kind stackKind = kind.getStackKind(); - switch (stackKind) { - case Int: - case Long: - case Object: - return new Variable(stackKind, lir.nextVariable(), Register.RegisterFlag.CPU); - case Float: - case Double: - return new Variable(stackKind, lir.nextVariable(), Register.RegisterFlag.FPU); - default: - throw GraalInternalError.shouldNotReachHere(); + public Variable newVariable(PlatformKind platformKind) { + PlatformKind stackKind; + if (platformKind instanceof Kind) { + stackKind = ((Kind) platformKind).getStackKind(); + } else { + stackKind = platformKind; } + return new Variable(stackKind, lir.nextVariable()); } @Override @@ -476,7 +471,7 @@ } @Override - public void visitEndNode(EndNode end) { + public void visitEndNode(AbstractEndNode end) { moveToPhi(end.merge(), end); } @@ -487,7 +482,7 @@ public void visitLoopEnd(LoopEndNode x) { } - private void moveToPhi(MergeNode merge, EndNode pred) { + private void moveToPhi(MergeNode merge, AbstractEndNode pred) { if (GraalOptions.TraceLIRGeneratorLevel >= 1) { TTY.println("MOVE TO PHI from " + pred + " to " + merge); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Tue Apr 30 23:09:37 2013 +0200 @@ -34,6 +34,8 @@ addPhase(new FrameStateAssignmentPhase()); + addPhase(new ExpandLogicPhase()); + addPhase(new DeadCodeEliminationPhase()); } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Tue Apr 30 23:09:37 2013 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -52,6 +53,8 @@ public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir); + protected abstract AbstractAssembler createAssembler(FrameMap frameMap); + public abstract TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult); /** diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Tue Apr 30 23:09:37 2013 +0200 @@ -477,7 +477,11 @@ } public NodeMap createNodeMap() { - return new NodeMap<>(this); + return createNodeMap(false); + } + + public NodeMap createNodeMap(boolean autoGrow) { + return new NodeMap<>(this, autoGrow); } public NodeFlood createNodeFlood() { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Apr 30 23:09:37 2013 +0200 @@ -759,8 +759,11 @@ } public boolean edgesEqual(Node node, Node other) { + return inputsEqual(node, other) && successorsEqual(node, other); + } + + public boolean inputsEqual(Node node, Node other) { assert node.getClass() == clazz && other.getClass() == clazz; - int index = 0; while (index < directInputCount) { if (getNode(other, inputOffsets[index]) != getNode(node, inputOffsets[index])) { @@ -775,8 +778,12 @@ } index++; } + return true; + } - index = 0; + public boolean successorsEqual(Node node, Node other) { + assert node.getClass() == clazz && other.getClass() == clazz; + int index = 0; while (index < directSuccessorCount) { if (getNode(other, successorOffsets[index]) != getNode(node, successorOffsets[index])) { return false; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Tue Apr 30 23:09:37 2013 +0200 @@ -29,19 +29,23 @@ public final class NodeMap { private final Graph graph; + private final boolean autogrow; private Object[] values; - private int size; public NodeMap(Graph graph) { + this(graph, false); + } + + public NodeMap(Graph graph, boolean autogrow) { this.graph = graph; - values = new Object[graph.nodeIdCount()]; - size = values.length; + this.values = new Object[graph.nodeIdCount()]; + this.autogrow = autogrow; } public NodeMap(NodeMap copyFrom) { this.graph = copyFrom.graph; this.values = Arrays.copyOf(copyFrom.values, copyFrom.values.length); - this.size = copyFrom.size; + this.autogrow = copyFrom.autogrow; } @SuppressWarnings("unchecked") @@ -60,14 +64,21 @@ } public int size() { - return size; + return values.length; } public boolean isNew(Node node) { - return node.id() >= size; + return node.id() >= size(); + } + + public void grow() { + this.values = Arrays.copyOf(values, graph.nodeIdCount()); } private void check(Node node) { + if (autogrow && isNew(node)) { + grow(); + } assert node.graph() == graph : "this node is not part of the graph"; assert !isNew(node) : "this node was added to the graph after creating the node map : " + node; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java --- a/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java Tue Apr 30 23:09:37 2013 +0200 @@ -30,7 +30,6 @@ import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.asm.amd64.*; @@ -71,7 +70,7 @@ @Override public void generateCode(AMD64Assembler asm) { - Register arg = getArgumentRegister(0, RegisterFlag.CPU); + Register arg = getArgumentRegister(0, Kind.Int); asm.addl(arg, 5); asm.movl(rax, arg); asm.ret(0); @@ -89,7 +88,7 @@ @Override public void generateCode(AMD64Assembler asm) { - Register arg = getArgumentRegister(0, RegisterFlag.CPU); + Register arg = getArgumentRegister(0, Kind.Long); asm.addq(arg, 1); asm.movq(rax, arg); asm.ret(0); @@ -117,8 +116,8 @@ Assert.assertArrayEquals(expectedCode, actualCode); } - private Register getArgumentRegister(int index, RegisterFlag flag) { - Register[] regs = runtime.lookupRegisterConfig().getCallingConventionRegisters(CallingConvention.Type.JavaCall, flag); + private Register getArgumentRegister(int index, Kind kind) { + Register[] regs = runtime.lookupRegisterConfig().getCallingConventionRegisters(CallingConvention.Type.JavaCall, kind); return regs[index]; } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Apr 30 23:09:37 2013 +0200 @@ -140,6 +140,11 @@ } @Override + protected AbstractAssembler createAssembler(FrameMap frameMap) { + return new AMD64MacroAssembler(target, frameMap.registerConfig); + } + + @Override public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { // Omit the frame if the method: // - has no spill slots or other slots allocated during register allocation @@ -151,7 +156,7 @@ LIR lir = gen.lir; boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame(); - AbstractAssembler masm = new AMD64MacroAssembler(target, frameMap.registerConfig); + AbstractAssembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(); TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult); tasm.setFrameSize(frameMap.frameSize()); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Tue Apr 30 23:09:37 2013 +0200 @@ -24,7 +24,6 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; @@ -39,7 +38,7 @@ * initial LIR generation is finished. Until then, we use a placeholder variable so that LIR * verification is successful. */ - private static final Variable PLACEHOLDER = new Variable(Kind.Long, Integer.MAX_VALUE, Register.RegisterFlag.CPU); + private static final Variable PLACEHOLDER = new Variable(Kind.Long, Integer.MAX_VALUE); @Use({REG, STACK}) protected AllocatableValue savedRbp = PLACEHOLDER; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Tue Apr 30 23:09:37 2013 +0200 @@ -30,9 +30,9 @@ /** * AMD64 specific implementation of {@link HotSpotGraalRuntime}. */ -final class AMD64HotSpotGraalRuntime extends HotSpotGraalRuntime { +public class AMD64HotSpotGraalRuntime extends HotSpotGraalRuntime { - private AMD64HotSpotGraalRuntime() { + protected AMD64HotSpotGraalRuntime() { } /** @@ -40,16 +40,25 @@ */ public static HotSpotGraalRuntime makeInstance() { if (graalRuntime() == null) { - setInstance(new AMD64HotSpotGraalRuntime()); + HotSpotGraalRuntimeFactory factory = findFactory("AMD64"); + if (factory != null) { + setInstance(factory.createRuntime()); + } else { + setInstance(new AMD64HotSpotGraalRuntime()); + } } return graalRuntime(); } + protected Architecture createArchitecture() { + return new AMD64(config.useSSE, config.useAVX); + } + @Override protected TargetDescription createTarget() { final int stackFrameAlignment = 16; final int implicitNullCheckLimit = 4096; - return new TargetDescription(new AMD64(config.useSSE, config.useAVX), true, stackFrameAlignment, implicitNullCheckLimit, true); + return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, true); } @Override diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue Apr 30 23:09:37 2013 +0200 @@ -54,13 +54,13 @@ /** * LIR generator specialized for AMD64 HotSpot. */ -final class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator { +public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator { private HotSpotRuntime runtime() { return (HotSpotRuntime) runtime; } - AMD64HotSpotLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + protected AMD64HotSpotLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { super(graph, runtime, target, frameMap, method, lir); } @@ -198,11 +198,19 @@ if (needsCalleeSave) { Register[] savedRegisters = frameMap.registerConfig.getAllocatableRegisters(); savedRegisterLocations = new StackSlot[savedRegisters.length]; + AMD64LIRInstruction[] savingMoves = new AMD64LIRInstruction[savedRegisters.length]; + AMD64LIRInstruction[] restoringMoves = new AMD64LIRInstruction[savedRegisters.length]; for (int i = 0; i < savedRegisters.length; i++) { - StackSlot spillSlot = frameMap.allocateSpillSlot(Kind.Long); + PlatformKind kind = target.arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); + assert kind != Kind.Illegal; + StackSlot spillSlot = frameMap.allocateSpillSlot(kind); savedRegisterLocations[i] = spillSlot; + + RegisterValue register = savedRegisters[i].asValue(kind); + savingMoves[i] = createMove(spillSlot, register); + restoringMoves[i] = createMove(register, spillSlot); } - save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations); + save = new AMD64SaveRegistersOp(savingMoves, restoringMoves, savedRegisterLocations); append(save); Value thread = args[0]; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Tue Apr 30 23:09:37 2013 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; -import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; @@ -38,9 +37,11 @@ // @formatter:off public class AMD64HotSpotRegisterConfig implements RegisterConfig { + private final Architecture architecture; + private final Register[] allocatable = initAllocatable(); - private final EnumMap categorized = Register.categorize(allocatable); + private final HashMap categorized = new HashMap<>(); private final RegisterAttributes[] attributesMap; @@ -49,9 +50,21 @@ return allocatable.clone(); } - @Override - public EnumMap getCategorizedAllocatableRegisters() { - return categorized.clone(); + public Register[] getAllocatableRegisters(PlatformKind kind) { + if (categorized.containsKey(kind)) { + return categorized.get(kind); + } + + ArrayList list = new ArrayList<>(); + for (Register reg : getAllocatableRegisters()) { + if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { + list.add(reg); + } + } + + Register[] ret = list.toArray(new Register[0]); + categorized.put(kind, ret); + return ret; } @Override @@ -93,7 +106,9 @@ return allocatable; } - public AMD64HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) { + public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config, boolean globalStubConfig) { + this.architecture = architecture; + if (config.windowsOs) { javaGeneralParameterRegisters = new Register[] {rdx, r8, r9, rdi, rsi, rcx}; nativeGeneralParameterRegisters = new Register[] {rcx, rdx, r8, r9}; @@ -109,7 +124,7 @@ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }; - csl = new CalleeSaveLayout(0, -1, 8, regs); + csl = new CalleeSaveLayout(architecture, 0, -1, 8, regs); } else { csl = null; } @@ -135,10 +150,11 @@ return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } - public Register[] getCallingConventionRegisters(Type type, RegisterFlag flag) { - if (flag == RegisterFlag.FPU) { + public Register[] getCallingConventionRegisters(Type type, Kind kind) { + if (architecture.canStoreValue(XMM, kind)) { return xmmParameterRegisters; } + assert architecture.canStoreValue(CPU, kind); return type == Type.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters; } @@ -178,7 +194,7 @@ if (locations[i] == null) { locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize); + currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize); } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Apr 30 23:09:37 2013 +0200 @@ -187,6 +187,6 @@ @Override protected RegisterConfig createRegisterConfig(boolean globalStubConfig) { - return new AMD64HotSpotRegisterConfig(config, globalStubConfig); + return new AMD64HotSpotRegisterConfig(graalRuntime.getTarget().arch, config, globalStubConfig); } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Tue Apr 30 23:09:37 2013 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.sparc.*; import com.oracle.graal.hotspot.*; @@ -47,6 +48,12 @@ } @Override + protected AbstractAssembler createAssembler(FrameMap frameMap) { + // SPARC: Create assembler. + return null; + } + + @Override public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { // SPARC: Create assembler. return null; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Apr 30 23:09:37 2013 +0200 @@ -84,6 +84,15 @@ runtime.compilerToVm = toVM; } + protected static HotSpotGraalRuntimeFactory findFactory(String architecture) { + for (HotSpotGraalRuntimeFactory factory : ServiceLoader.loadInstalled(HotSpotGraalRuntimeFactory.class)) { + if (factory.getArchitecture().equals(architecture) && factory.getName().equals(GraalOptions.GraalRuntime)) { + return factory; + } + } + return null; + } + private static Kind wordKind; /** @@ -114,8 +123,9 @@ return unsafe.getInt(object, offset); } - protected/* final */CompilerToVM compilerToVm; - protected/* final */VMToCompiler vmToCompiler; + protected/* final */CompilerToVM compilerToVm; + protected/* final */CompilerToGPU compilerToGpu; + protected/* final */VMToCompiler vmToCompiler; protected final HotSpotRuntime runtime; protected final TargetDescription target; @@ -128,12 +138,14 @@ private final HotSpotBackend backend; protected HotSpotGraalRuntime() { - CompilerToVM toVM = new CompilerToVMImpl(); + CompilerToVM toVM = new CompilerToVMImpl(); + CompilerToGPU toGPU = new CompilerToGPUImpl(); // initialize VmToCompiler VMToCompiler toCompiler = new VMToCompilerImpl(this); - compilerToVm = toVM; + compilerToVm = toVM; + compilerToGpu = toGPU; vmToCompiler = toCompiler; config = new HotSpotVMConfig(); compilerToVm.initializeConfiguration(config); @@ -215,6 +227,10 @@ return vmToCompiler; } + public CompilerToGPU getCompilerToGPU() { + return compilerToGpu; + } + public JavaType lookupType(String name, HotSpotResolvedObjectType accessingClass, boolean eagerResolve) { if (name.length() == 1 && vmToCompiler instanceof VMToCompilerImpl) { VMToCompilerImpl impl = (VMToCompilerImpl) vmToCompiler; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntimeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntimeFactory.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2011, 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.hotspot; + +public interface HotSpotGraalRuntimeFactory { + + HotSpotGraalRuntime createRuntime(); + + String getArchitecture(); + + String getName(); +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Apr 30 23:09:37 2013 +0200 @@ -394,6 +394,7 @@ public int deoptReasonJsrMismatch; public int deoptReasonDiv0Check; public int deoptReasonConstraint; + public int deoptReasonLoopLimitCheck; public int deoptActionNone; public int deoptActionMaybeRecompile; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,55 @@ +/* + * 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.bridge; + +import com.oracle.graal.api.code.InvalidInstalledCodeException; + +/** + * Calls from Java into the GPU. + */ +public interface CompilerToGPU { + + /** + * Attempts to initialize and create a valid context with the GPU. + * + * @return whether the GPU context has been initialized and is valid. + */ + boolean deviceInit(); + + /** + * Attempts to detach from a valid GPU context. + * + * @return whether the GPU context has been properly disposed. + */ + boolean deviceDetach(); + + /** + * Attempts to generate and return a bound function to the + * loaded method kernel on the GPU. + * + * @param code the text or binary values for a method kernel + * @return the value of the bound kernel in GPU space. + */ + long generateKernel(byte[] code, String name) throws InvalidInstalledCodeException; +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,40 @@ +/* + * 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.hotspot.bridge; + +import com.oracle.graal.api.code.InvalidInstalledCodeException; + + +/** + * Entries into the HotSpot GPU interface from Java code. + */ +public class CompilerToGPUImpl implements CompilerToGPU { + + public native boolean deviceInit(); + + public native long generateKernel(byte[] code, String name) throws InvalidInstalledCodeException; + + public native boolean deviceDetach(); + +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 30 23:09:37 2013 +0200 @@ -25,7 +25,6 @@ import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.code.DeoptimizationAction.*; import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.code.Register.RegisterFlag.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.api.meta.Value.*; import static com.oracle.graal.graph.UnsafeAccess.*; @@ -41,7 +40,6 @@ import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; import static com.oracle.graal.hotspot.stubs.NewMultiArrayStub.*; import static com.oracle.graal.hotspot.stubs.RegisterFinalizerStub.*; -import static com.oracle.graal.hotspot.stubs.Stub.*; import static com.oracle.graal.hotspot.stubs.ThreadIsInterruptedStub.*; import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*; import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; @@ -59,7 +57,6 @@ import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.CompilationResult.Infopoint; import com.oracle.graal.api.code.CompilationResult.Mark; -import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; @@ -195,13 +192,12 @@ int currentStackOffset = 0; for (int i = 0; i < arguments.length; i++) { Kind kind = arguments[i]; - RegisterFlag flag = kind == Kind.Float || kind == Kind.Double ? FPU : CPU; - Register[] ccRegs = globalStubRegConfig.getCallingConventionRegisters(type, flag); + Register[] ccRegs = globalStubRegConfig.getCallingConventionRegisters(type, kind); if (i < ccRegs.length) { result[i] = ccRegs[i].asValue(kind); } else { result[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, false); - currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize); + currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize); } } return result; @@ -734,7 +730,7 @@ ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); // An unsafe read must not floating outside its block as may float above an explicit // null check on its object. - memoryRead.dependencies().add(BeginNode.prevBegin(load)); + memoryRead.dependencies().add(AbstractBeginNode.prevBegin(load)); graph.replaceFixedWithFixed(load, memoryRead); } else if (n instanceof UnsafeStoreNode) { UnsafeStoreNode store = (UnsafeStoreNode) n; @@ -867,7 +863,7 @@ } private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { - int scale = this.graalRuntime.getTarget().sizeInBytes(elementKind); + int scale = this.graalRuntime.getTarget().arch.getSizeInBytes(elementKind); return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale); } @@ -998,6 +994,8 @@ return config.deoptReasonDiv0Check; case RuntimeConstraint: return config.deoptReasonConstraint; + case LoopLimitCheck: + return config.deoptReasonLoopLimitCheck; default: throw GraalInternalError.shouldNotReachHere(); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Apr 30 23:09:37 2013 +0200 @@ -261,7 +261,7 @@ final int alignment = target.wordSize; final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); final Integer length = lengthNode.isConstant() ? Integer.valueOf(lengthNode.asConstant().asInt()) : null; - int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind)); + int log2ElementSize = CodeUtil.log2(target.arch.getSizeInBytes(elementKind)); if (!useTLAB) { ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph); /* diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Tue Apr 30 23:09:37 2013 +0200 @@ -253,7 +253,7 @@ } } - public void insertProxies(BeginNode begin) { + public void insertProxies(AbstractBeginNode begin) { for (int i = 0; i < localsSize(); i++) { ValueNode value = localAt(i); if (value != null) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -679,11 +679,7 @@ } private void genGoto() { - double probability = profilingInfo.getBranchTakenProbability(bci()); - if (probability < 0) { - probability = 1; - } - appendGoto(createTarget(probability, currentBlock.successors.get(0), frameState)); + appendGoto(createTarget(1, currentBlock.successors.get(0), frameState)); assert currentBlock.numNormalSuccessors() == 1; } @@ -725,8 +721,8 @@ } condition = currentGraph.unique(condition); - BeginNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState); - BeginNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState); + AbstractBeginNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState); + AbstractBeginNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState); IfNode ifNode = negate ? new IfNode(condition, falseSuccessor, trueSuccessor, 1 - probability) : new IfNode(condition, trueSuccessor, falseSuccessor, probability); append(currentGraph.add(ifNode)); @@ -1493,7 +1489,7 @@ BlockPlaceholderNode placeholder = (BlockPlaceholderNode) block.firstInstruction; // The EndNode for the already existing edge. - EndNode end = currentGraph.add(new EndNode()); + AbstractEndNode end = currentGraph.add(new EndNode()); // The MergeNode that replaces the placeholder. MergeNode mergeNode = currentGraph.add(new MergeNode()); FixedNode next = placeholder.next(); @@ -1508,7 +1504,7 @@ MergeNode mergeNode = (MergeNode) block.firstInstruction; // The EndNode for the newly merged edge. - EndNode newEnd = currentGraph.add(new EndNode()); + AbstractEndNode newEnd = currentGraph.add(new EndNode()); Target target = checkLoopExit(newEnd, block, state); FixedNode result = target.fixed; block.entryState.merge(mergeNode, target.state); @@ -1522,9 +1518,9 @@ * Returns a block begin node with the specified state. If the specified probability is 0, the * block deoptimizes immediately. */ - private BeginNode createBlockTarget(double probability, Block block, FrameStateBuilder stateAfter) { + private AbstractBeginNode createBlockTarget(double probability, Block block, FrameStateBuilder stateAfter) { FixedNode target = createTarget(probability, block, stateAfter); - BeginNode begin = BeginNode.begin(target); + AbstractBeginNode begin = AbstractBeginNode.begin(target); assert !(target instanceof DeoptimizeNode && begin.stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize " + "to a bci _before_ the actual if, so that the interpreter can update the profiling information."; @@ -1705,7 +1701,7 @@ if (block.isLoopHeader) { // Create the loop header block, which later will merge the backward branches of the // loop. - EndNode preLoopEnd = currentGraph.add(new EndNode()); + AbstractEndNode preLoopEnd = currentGraph.add(new EndNode()); LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode()); lastInstr.setNext(preLoopEnd); // Add the single non-loop predecessor of the loop header. @@ -1773,7 +1769,7 @@ frameState.clearNonLiveLocals(currentBlock.localsLiveOut); } if (lastInstr instanceof StateSplit) { - if (lastInstr.getClass() == BeginNode.class) { + if (lastInstr.getClass() == AbstractBeginNode.class) { // BeginNodes do not need a frame state } else { StateSplit stateSplit = (StateSplit) lastInstr; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/JTTTest.java Tue Apr 30 23:09:37 2013 +0200 @@ -60,9 +60,9 @@ Object[] args = argsWithReceiver(receiver, argsToBind); JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m)); assert parameterTypes.length == args.length; - for (int i = 0; i < argsToBind.length; i++) { + for (int i = 0; i < args.length; i++) { LocalNode local = graph.getLocal(i); - Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]); + Constant c = Constant.forBoxed(parameterTypes[i].getKind(), args[i]); ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph); local.replaceAtUsages(replacement); } @@ -99,8 +99,10 @@ Result expect = executeExpected(method, receiver, args); test(method, expect, receiver, args); - this.argsToBind = args; - test(method, expect, receiver, args); - this.argsToBind = null; + if (args.length > 0) { + this.argsToBind = args; + test(method, expect, receiver, args); + this.argsToBind = null; + } } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Tue Apr 30 23:09:37 2013 +0200 @@ -41,11 +41,11 @@ protected final Scale scale; protected final int displacement; - public AMD64AddressValue(Kind kind, AllocatableValue base, int displacement) { + public AMD64AddressValue(PlatformKind kind, AllocatableValue base, int displacement) { this(kind, base, Value.ILLEGAL, Scale.Times1, displacement); } - public AMD64AddressValue(Kind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) { + public AMD64AddressValue(PlatformKind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) { super(kind); this.base = base; this.index = index; @@ -91,13 +91,13 @@ 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 getPlatformKind() == addr.getPlatformKind() && 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); + return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ (scale.value << 8) ^ getPlatformKind().hashCode(); } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Tue Apr 30 23:09:37 2013 +0200 @@ -255,8 +255,8 @@ public DivRemOp(AMD64Arithmetic opcode, AllocatableValue x, AllocatableValue y, LIRFrameState state) { this.opcode = opcode; - this.divResult = AMD64.rax.asValue(x.getKind()); - this.remResult = AMD64.rdx.asValue(x.getKind()); + this.divResult = AMD64.rax.asValue(x.getPlatformKind()); + this.remResult = AMD64.rdx.asValue(x.getPlatformKind()); this.x = x; this.y = y; this.state = state; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java Tue Apr 30 23:09:37 2013 +0200 @@ -52,12 +52,9 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Register[] savedRegisters = save.savedRegisters; - for (int i = 0; i < savedRegisters.length; i++) { - if (savedRegisters[i] != null) { - StackSlot input = slots[i]; - RegisterValue result = savedRegisters[i].asValue(input.getKind()); - AMD64Move.move(tasm, masm, result, input); + for (AMD64LIRInstruction restoringMove : save.restoringMoves) { + if (restoringMove != null) { + restoringMove.emitCode(tasm, masm); } } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Tue Apr 30 23:09:37 2013 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.asm.*; /** @@ -39,29 +40,31 @@ public final class AMD64SaveRegistersOp extends AMD64LIRInstruction { /** - * The registers (potentially) saved by this operation. + * The move instructions for saving the registers. */ - protected final Register[] savedRegisters; + protected final AMD64LIRInstruction[] savingMoves; + + /** + * The move instructions for restoring the registers. + */ + protected final AMD64LIRInstruction[] restoringMoves; /** * The slots to which the registers are saved. */ @Def(STACK) protected final StackSlot[] slots; - public AMD64SaveRegistersOp(Register[] savedRegisters, StackSlot[] slots) { - this.savedRegisters = savedRegisters; + public AMD64SaveRegistersOp(AMD64LIRInstruction[] savingMoves, AMD64LIRInstruction[] restoringMoves, StackSlot[] slots) { + this.savingMoves = savingMoves; + this.restoringMoves = restoringMoves; this.slots = slots; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - for (int i = 0; i < savedRegisters.length; i++) { - if (savedRegisters[i] != null) { - StackSlot result = slots[i]; - RegisterValue input = savedRegisters[i].asValue(result.getKind()); - AMD64Move.move(tasm, masm, result, input); - } else { - assert savedRegisters[i] == null; + for (AMD64LIRInstruction savingMove : savingMoves) { + if (savingMove != null) { + savingMove.emitCode(tasm, masm); } } } @@ -73,10 +76,12 @@ */ public void updateAndDescribePreservation(Set notSaved, DebugInfo debugInfo, FrameMap frameMap) { int preserved = 0; - for (int i = 0; i < savedRegisters.length; i++) { - if (savedRegisters[i] != null) { - if (notSaved.contains(savedRegisters[i])) { - savedRegisters[i] = null; + for (int i = 0; i < savingMoves.length; i++) { + if (savingMoves[i] != null) { + Register register = ValueUtil.asRegister(((MoveOp) savingMoves[i]).getInput()); + if (notSaved.contains(register)) { + savingMoves[i] = null; + restoringMoves[i] = null; } else { preserved++; } @@ -86,9 +91,9 @@ Register[] keys = new Register[preserved]; int[] values = new int[keys.length]; int mapIndex = 0; - for (int i = 0; i < savedRegisters.length; i++) { - if (savedRegisters[i] != null) { - keys[mapIndex] = savedRegisters[i]; + for (int i = 0; i < savingMoves.length; i++) { + if (savingMoves[i] != null) { + keys[mapIndex] = ValueUtil.asRegister(((MoveOp) savingMoves[i]).getInput()); values[mapIndex] = frameMap.indexForStackSlot(slots[i]); mapIndex++; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java Tue Apr 30 23:09:37 2013 +0200 @@ -48,7 +48,7 @@ * @param kind the kind of the value being addressed * @param base the base register */ - public PTXAddressValue(Kind kind, AllocatableValue base) { + public PTXAddressValue(PlatformKind kind, AllocatableValue base) { this(kind, base, 0); } @@ -60,7 +60,7 @@ * @param base the base register * @param displacement the displacement */ - public PTXAddressValue(Kind kind, AllocatableValue base, long displacement) { + public PTXAddressValue(PlatformKind kind, AllocatableValue base, long displacement) { super(kind); this.base = base; this.displacement = displacement; @@ -95,13 +95,13 @@ 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 getPlatformKind() == addr.getPlatformKind() && displacement == addr.displacement && base.equals(addr.base); } return false; } @Override public int hashCode() { - return base.hashCode() ^ ((int) displacement << 4) ^ (getKind().ordinal() << 12); + return base.hashCode() ^ ((int) displacement << 4) ^ getPlatformKind().hashCode(); } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java Tue Apr 30 23:09:37 2013 +0200 @@ -45,7 +45,7 @@ private final CompositeValueClass valueClass; - public CompositeValue(Kind kind) { + public CompositeValue(PlatformKind kind) { super(kind); valueClass = CompositeValueClass.get(getClass()); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Tue Apr 30 23:09:37 2013 +0200 @@ -197,7 +197,7 @@ // Without this, frameNeedsAllocating() would never return true. int total = 0; for (StackSlot s : freedSlots) { - total += target.sizeInBytes(s.getKind()); + total += target.arch.getSizeInBytes(s.getKind()); } int initialSpillSize = returnAddressSize() + calleeSaveAreaSize(); if (total == spillSize - initialSpillSize) { @@ -266,7 +266,7 @@ hasOutgoingStackArguments = hasOutgoingStackArguments || argsSize > 0; } - private StackSlot getSlot(Kind kind, int additionalOffset) { + private StackSlot getSlot(PlatformKind kind, int additionalOffset) { return StackSlot.get(kind, -spillSize + additionalOffset, true); } @@ -277,12 +277,12 @@ * @param kind The kind of the spill slot to be reserved. * @return A spill slot denoting the reserved memory area. */ - public StackSlot allocateSpillSlot(Kind kind) { + public StackSlot allocateSpillSlot(PlatformKind kind) { assert frameSize == -1 : "frame size must not yet be fixed"; if (freedSlots != null) { for (Iterator iter = freedSlots.iterator(); iter.hasNext();) { StackSlot s = iter.next(); - if (s.getKind() == kind) { + if (s.getPlatformKind() == kind) { iter.remove(); if (freedSlots.isEmpty()) { freedSlots = null; @@ -291,7 +291,7 @@ } } } - int size = target.sizeInBytes(kind); + int size = target.arch.getSizeInBytes(kind); spillSize = NumUtil.roundUp(spillSize + size, size); return getSlot(kind, 0); } @@ -299,8 +299,8 @@ private Set freedSlots; /** - * Frees a spill slot that was obtained via {@link #allocateSpillSlot(Kind)} such that it can be - * reused for the next allocation request for the same kind of slot. + * Frees a spill slot that was obtained via {@link #allocateSpillSlot(PlatformKind)} such that + * it can be reused for the next allocation request for the same kind of slot. */ public void freeSpillSlot(StackSlot slot) { if (freedSlots == null) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java Tue Apr 30 23:09:37 2013 +0200 @@ -39,22 +39,15 @@ public final int index; /** - * The type of register that this variable needs to get assigned. - */ - public final Register.RegisterFlag flag; - - /** * Creates a new variable. * * @param kind * @param index */ - public Variable(Kind kind, int index, Register.RegisterFlag flag) { + public Variable(PlatformKind kind, int index) { super(kind); - assert kind == kind.getStackKind() : "Variables can be only created for stack kinds"; assert index >= 0; this.index = index; - this.flag = flag; } @Override diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Tue Apr 30 23:09:37 2013 +0200 @@ -22,9 +22,11 @@ */ package com.oracle.graal.loop; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.type.*; public class BasicInductionVariable extends InductionVariable { @@ -113,8 +115,19 @@ } @Override - public ValueNode extremumNode() { - return IntegerArithmeticNode.add(IntegerArithmeticNode.mul(strideNode(), loop.counted().maxTripCountNode()), init); + public ValueNode extremumNode(boolean assumePositiveTripCount, Kind kind) { + Kind fromKind = phi.kind(); + Graph graph = phi.graph(); + ValueNode stride = strideNode(); + ValueNode maxTripCount = loop.counted().maxTripCountNode(assumePositiveTripCount); + ValueNode initNode = this.initNode(); + if (fromKind != kind) { + Op convertOp = Op.getOp(fromKind, kind); + stride = graph.unique(new ConvertNode(convertOp, stride)); + maxTripCount = graph.unique(new ConvertNode(convertOp, maxTripCount)); + initNode = graph.unique(new ConvertNode(convertOp, initNode)); + } + return IntegerArithmeticNode.add(IntegerArithmeticNode.mul(stride, IntegerArithmeticNode.sub(maxTripCount, ConstantNode.forIntegerKind(kind, 1, graph))), initNode); } @Override @@ -124,6 +137,6 @@ @Override public long constantExtremum() { - return constantStride() * loop.counted().constantMaxTripCount() + constantInit(); + return constantStride() * (loop.counted().constantMaxTripCount() - 1) + constantInit(); } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Tue Apr 30 23:09:37 2013 +0200 @@ -22,9 +22,14 @@ */ package com.oracle.graal.loop; +import static com.oracle.graal.nodes.calc.IntegerArithmeticNode.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.loop.InductionVariable.Direction; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; public class CountedLoopInfo { @@ -32,19 +37,39 @@ private InductionVariable iv; private ValueNode end; private boolean oneOff; + private ValueNode overflowGuard; + private AbstractBeginNode body; - CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff) { + CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, AbstractBeginNode body) { this.loop = loop; this.iv = iv; this.end = end; this.oneOff = oneOff; + this.body = body; } public ValueNode maxTripCountNode() { - // TODO (gd) stuarte and respect oneOff - throw GraalInternalError.unimplemented("division is a fixed node that needs to be inserted into the control flow"); - // return IntegerArithmeticNode.div(IntegerArithmeticNode.sub(end, iv.initNode()), - // iv.strideNode()); + return maxTripCountNode(false); + } + + public ValueNode maxTripCountNode(boolean assumePositive) { + StructuredGraph graph = (StructuredGraph) iv.valueNode().graph(); + Kind kind = iv.valueNode().kind(); + IntegerArithmeticNode range = IntegerArithmeticNode.sub(end, iv.initNode()); + if (oneOff) { + if (iv.direction() == Direction.Up) { + range = IntegerArithmeticNode.add(range, ConstantNode.forIntegerKind(kind, 1, graph)); + } else { + range = IntegerArithmeticNode.sub(range, ConstantNode.forIntegerKind(kind, 1, graph)); + } + } + IntegerDivNode div = graph.add(new IntegerDivNode(kind, range, iv.strideNode())); + graph.addBeforeFixed(loop.entryPoint(), div); + ConstantNode zero = ConstantNode.forIntegerKind(kind, 0, graph); + if (assumePositive) { + return div; + } + return graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(zero, div)), div, zero)); } public boolean isConstantMaxTripCount() { @@ -80,4 +105,53 @@ public String toString() { return "iv=" + iv + " until " + end + (oneOff ? iv.direction() == Direction.Up ? "+1" : "-1" : ""); } + + public ValueNode getLimit() { + return end; + } + + public ValueNode getStart() { + return iv.initNode(); + } + + public boolean isLimitIncluded() { + return oneOff; + } + + public AbstractBeginNode getBody() { + return body; + } + + public Direction getDirection() { + return iv.direction(); + } + + public ValueNode getOverFlowGuard() { + if (overflowGuard == null) { + Kind kind = iv.valueNode().kind(); + Graph graph = iv.valueNode().graph(); + CompareNode cond; // we use a negated guard with a < condition to achieve a >= + ConstantNode one = ConstantNode.forIntegerKind(kind, 1, graph); + if (iv.direction() == Direction.Up) { + IntegerArithmeticNode v1 = sub(ConstantNode.forIntegerKind(kind, kind.getMaxValue(), graph), sub(iv.strideNode(), one)); + if (oneOff) { + v1 = sub(v1, one); + } + cond = graph.unique(new IntegerLessThanNode(v1, end)); + } else { + assert iv.direction() == Direction.Down; + IntegerArithmeticNode v1 = add(ConstantNode.forIntegerKind(kind, kind.getMinValue(), graph), add(iv.strideNode(), one)); + if (oneOff) { + v1 = add(v1, one); + } + cond = graph.unique(new IntegerLessThanNode(end, v1)); + } + overflowGuard = graph.unique(new GuardNode(cond, BeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true)); + } + return overflowGuard; + } + + public Kind getKind() { + return iv.valueNode().kind(); + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Tue Apr 30 23:09:37 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.loop; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -86,8 +87,8 @@ } @Override - public ValueNode extremumNode() { - return op(offset, base.extremumNode()); + public ValueNode extremumNode(boolean assumePositiveTripCount, Kind kind) { + return op(base.extremumNode(assumePositiveTripCount, kind), ConvertNode.convert(kind, offset)); } @Override diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Tue Apr 30 23:09:37 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.loop; +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.type.*; @@ -96,8 +97,8 @@ } @Override - public ValueNode extremumNode() { - return IntegerArithmeticNode.mul(base.extremumNode(), scale); + public ValueNode extremumNode(boolean assumePositiveTripCount, Kind kind) { + return IntegerArithmeticNode.mul(base.extremumNode(assumePositiveTripCount, kind), ConvertNode.convert(kind, scale)); } @Override diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java Tue Apr 30 23:09:37 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.loop; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -48,6 +49,10 @@ this.loop = loop; } + public LoopEx getLoop() { + return loop; + } + public abstract Direction direction(); public abstract ValueNode valueNode(); @@ -64,7 +69,11 @@ public abstract long constantStride(); - public abstract ValueNode extremumNode(); + public ValueNode extremumNode() { + return extremumNode(false, valueNode().kind()); + } + + public abstract ValueNode extremumNode(boolean assumePositiveTripCount, Kind kind); public abstract boolean isConstantExtremum(); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java Tue Apr 30 23:09:37 2013 +0200 @@ -46,7 +46,7 @@ private Collection findBasic() { List bivs = new LinkedList<>(); LoopBeginNode loopBegin = loop.loopBegin(); - EndNode forwardEnd = loopBegin.forwardEnd(); + AbstractEndNode forwardEnd = loopBegin.forwardEnd(); for (PhiNode phi : loopBegin.phis()) { ValueNode backValue = phi.singleBackValue(); if (backValue == null) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Tue Apr 30 23:09:37 2013 +0200 @@ -39,6 +39,7 @@ private LoopFragmentWhole whole; private CountedLoopInfo counted; // TODO (gd) detect private LoopsData data; + private InductionVariables ivs; LoopEx(Loop lirLoop, LoopsData data) { this.lirLoop = lirLoop; @@ -148,9 +149,9 @@ return data; } - public NodeBitMap nodesInLoopFrom(BeginNode point, BeginNode until) { - Collection blocks = new LinkedList<>(); - Collection exits = new LinkedList<>(); + public NodeBitMap nodesInLoopFrom(AbstractBeginNode point, AbstractBeginNode until) { + Collection blocks = new LinkedList<>(); + Collection exits = new LinkedList<>(); Queue work = new LinkedList<>(); ControlFlowGraph cfg = loopsData().controlFlowGraph(); work.add(cfg.blockFor(point)); @@ -169,4 +170,11 @@ } return LoopFragment.computeNodes(point.graph(), blocks, exits); } + + public InductionVariables getInductionVariables() { + if (ivs == null) { + ivs = new InductionVariables(this); + } + return ivs; + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Tue Apr 30 23:09:37 2013 +0200 @@ -145,13 +145,13 @@ } } - protected static NodeBitMap computeNodes(Graph graph, Collection blocks) { - return computeNodes(graph, blocks, Collections. emptyList()); + protected static NodeBitMap computeNodes(Graph graph, Collection blocks) { + return computeNodes(graph, blocks, Collections. emptyList()); } - protected static NodeBitMap computeNodes(Graph graph, Collection blocks, Collection earlyExits) { + protected static NodeBitMap computeNodes(Graph graph, Collection blocks, Collection earlyExits) { final NodeBitMap nodes = graph.createNodeBitMap(true); - for (BeginNode b : blocks) { + for (AbstractBeginNode b : blocks) { for (Node n : b.getBlockNodes()) { if (n instanceof Invoke) { nodes.mark(((Invoke) n).callTarget()); @@ -165,7 +165,7 @@ nodes.mark(n); } } - for (BeginNode earlyExit : earlyExits) { + for (AbstractBeginNode earlyExit : earlyExits) { FrameState stateAfter = earlyExit.stateAfter(); if (stateAfter != null) { nodes.mark(stateAfter); @@ -183,7 +183,7 @@ } } - for (BeginNode b : blocks) { + for (AbstractBeginNode b : blocks) { for (Node n : b.getBlockNodes()) { for (Node usage : n.usages()) { markFloating(usage, nodes); @@ -223,8 +223,8 @@ return false; } - public static Collection toHirBlocks(Collection blocks) { - List hir = new ArrayList<>(blocks.size()); + public static Collection toHirBlocks(Collection blocks) { + List hir = new ArrayList<>(blocks.size()); for (Block b : blocks) { hir.add(b.getBeginNode()); } @@ -238,18 +238,18 @@ protected void mergeEarlyExits() { assert isDuplicate(); StructuredGraph graph = graph(); - for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) { + for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) { FixedNode next = earlyExit.next(); if (earlyExit.isDeleted() || !this.original().contains(earlyExit)) { continue; } - BeginNode newEarlyExit = getDuplicatedNode(earlyExit); + AbstractBeginNode newEarlyExit = getDuplicatedNode(earlyExit); if (newEarlyExit == null) { continue; } MergeNode merge = graph.add(new MergeNode()); - EndNode originalEnd = graph.add(new EndNode()); - EndNode newEnd = graph.add(new EndNode()); + AbstractEndNode originalEnd = graph.add(new EndNode()); + AbstractEndNode newEnd = graph.add(new EndNode()); merge.addForwardEnd(originalEnd); merge.addForwardEnd(newEnd); earlyExit.setNext(originalEnd); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Tue Apr 30 23:09:37 2013 +0200 @@ -89,13 +89,13 @@ patchNodes(dataFixBefore); - BeginNode end = mergeEnds(); + AbstractBeginNode end = mergeEnds(); original().patchPeeling(this); mergeEarlyExits(); - BeginNode entry = getDuplicatedNode(loop.loopBegin()); + AbstractBeginNode entry = getDuplicatedNode(loop.loopBegin()); FrameState state = entry.stateAfter(); if (state != null) { entry.setStateAfter(null); @@ -213,24 +213,24 @@ } } - private BeginNode mergeEnds() { + private AbstractBeginNode mergeEnds() { assert isDuplicate(); - List endsToMerge = new LinkedList<>(); - Map reverseEnds = new HashMap<>(); // map peel's exit to the - // corresponding loop exits + List endsToMerge = new LinkedList<>(); + Map reverseEnds = new HashMap<>(); // map peel's exit to the + // corresponding loop exits LoopBeginNode loopBegin = original().loop().loopBegin(); for (LoopEndNode le : loopBegin.loopEnds()) { - EndNode duplicate = getDuplicatedNode(le); + AbstractEndNode duplicate = getDuplicatedNode(le); if (duplicate != null) { endsToMerge.add(duplicate); reverseEnds.put(duplicate, le); } } mergedInitializers = new IdentityHashMap<>(); - BeginNode newExit; + AbstractBeginNode newExit; StructuredGraph graph = graph(); if (endsToMerge.size() == 1) { - EndNode end = endsToMerge.get(0); + AbstractEndNode end = endsToMerge.get(0); assert end.usages().count() == 0; newExit = graph.add(new BeginNode()); end.replaceAtPredecessor(newExit); @@ -245,13 +245,13 @@ duplicateState = state.duplicateWithVirtualState(); newExitMerge.setStateAfter(duplicateState); } - for (EndNode end : endsToMerge) { + for (AbstractEndNode end : endsToMerge) { newExitMerge.addForwardEnd(end); } for (final PhiNode phi : loopBegin.phis().snapshot()) { final PhiNode firstPhi = graph.add(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), newExitMerge) : new PhiNode(phi.type(), newExitMerge, phi.getIdentity())); - for (EndNode end : newExitMerge.forwardEnds()) { + for (AbstractEndNode end : newExitMerge.forwardEnds()) { LoopEndNode loopEnd = reverseEnds.get(end); ValueNode prim = prim(phi.valueAt(loopEnd)); assert prim != null; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Tue Apr 30 23:09:37 2013 +0200 @@ -60,12 +60,12 @@ public static boolean shouldUnswitch(LoopEx loop, ControlSplitNode controlSplit) { Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator(); - BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null; + AbstractBeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null; int loopTotal = loop.size(); int inBranchTotal = 0; double maxProbability = 0; for (Node successor : controlSplit.successors()) { - BeginNode branch = (BeginNode) successor; + AbstractBeginNode branch = (AbstractBeginNode) successor; inBranchTotal += loop.nodesInLoopFrom(branch, postDom).cardinality(); // this may count // twice because // of fall-through diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Tue Apr 30 23:09:37 2013 +0200 @@ -78,19 +78,19 @@ // original loop is used as first successor Position firstPosition = successors.nextPosition(); NodeClass controlSplitClass = controlSplitNode.getNodeClass(); - controlSplitClass.set(newControlSplit, firstPosition, BeginNode.begin(originalLoop.entryPoint())); + controlSplitClass.set(newControlSplit, firstPosition, AbstractBeginNode.begin(originalLoop.entryPoint())); StructuredGraph graph = (StructuredGraph) controlSplitNode.graph(); while (successors.hasNext()) { Position position = successors.nextPosition(); // create a new loop duplicate, connect it and simplify it LoopFragmentWhole duplicateLoop = originalLoop.duplicate(); - controlSplitClass.set(newControlSplit, position, BeginNode.begin(duplicateLoop.entryPoint())); + controlSplitClass.set(newControlSplit, position, AbstractBeginNode.begin(duplicateLoop.entryPoint())); ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode); - graph.removeSplitPropagate(duplicatedControlSplit, (BeginNode) controlSplitClass.get(duplicatedControlSplit, position)); + graph.removeSplitPropagate(duplicatedControlSplit, (AbstractBeginNode) controlSplitClass.get(duplicatedControlSplit, position)); } // original loop is simplified last to avoid deleting controlSplitNode too early - graph.removeSplitPropagate(controlSplitNode, (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition)); + graph.removeSplitPropagate(controlSplitNode, (AbstractBeginNode) controlSplitClass.get(controlSplitNode, firstPosition)); // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms) } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java Tue Apr 30 23:09:37 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.extended.*; public class LoopsData { @@ -92,6 +93,9 @@ InductionVariables ivs = new InductionVariables(loop); LoopBeginNode loopBegin = loop.loopBegin(); FixedNode next = loopBegin.next(); + while (next instanceof FixedGuardNode || next instanceof ValueAnchorNode) { + next = ((FixedWithNextNode) next).next(); + } if (next instanceof IfNode) { IfNode ifNode = (IfNode) next; boolean negated = false; @@ -150,7 +154,7 @@ default: throw GraalInternalError.shouldNotReachHere(); } - loop.setCounted(new CountedLoopInfo(loop, iv, limit, oneOff)); + loop.setCounted(new CountedLoopInfo(loop, iv, limit, oneOff, negated ? ifNode.falseSuccessor() : ifNode.trueSuccessor())); } } } @@ -158,4 +162,18 @@ public ControlFlowGraph controlFlowGraph() { return cfg; } + + public InductionVariable getInductionVariable(ValueNode value) { + InductionVariable match = null; + for (LoopEx loop : loops()) { + InductionVariable iv = loop.getInductionVariables().get(value); + if (iv != null) { + if (match != null) { + return null; + } + match = iv; + } + } + return match; + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011, 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.loop.phases; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +public class LoopSafepointEliminationPhase extends BasePhase { + + @Override + protected void run(StructuredGraph graph, LowTierContext context) { + LoopsData loops = new LoopsData(graph); + if (context.getOptimisticOptimizations().useLoopLimitChecks()) { + loops.detectedCountedLoops(); + for (LoopEx loop : loops.countedLoops()) { + if (loop.lirLoop().children.isEmpty() && loop.counted().getKind() == Kind.Int) { + loop.loopBegin().dependencies().add(loop.counted().getOverFlowGuard()); + for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) { + loopEnd.disableSafepoint(); + } + } + } + } + for (LoopEx loop : loops.countedLoops()) { + for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) { + Block b = loops.controlFlowGraph().blockFor(loopEnd); + blocks: while (b != loop.lirLoop().header) { + assert b != null; + for (FixedNode node : b.getNodes()) { + if (node instanceof Invoke || node instanceof RuntimeCallNode) { + loopEnd.disableSafepoint(); + break blocks; + } + } + b = b.getDominator(); + } + } + } + } +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -77,7 +77,7 @@ sb.append(loop).append(" at ").append(controlSplit).append(" ["); NodeClassIterator it = controlSplit.successors().iterator(); while (it.hasNext()) { - sb.append(controlSplit.probability((BeginNode) it.next())); + sb.append(controlSplit.probability((AbstractBeginNode) it.next())); if (it.hasNext()) { sb.append(", "); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,187 @@ +/* + * 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.nodes; + +import static com.oracle.graal.graph.iterators.NodePredicates.*; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, Node.IterableNodeType { + + @Input(notDataflow = true) private FrameState stateAfter; + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return false; + } + + protected AbstractBeginNode() { + super(StampFactory.dependency()); + } + + protected AbstractBeginNode(Stamp stamp) { + super(stamp); + } + + public static AbstractBeginNode begin(FixedNode with) { + if (with instanceof AbstractBeginNode) { + return (AbstractBeginNode) with; + } + AbstractBeginNode begin = with.graph().add(new BeginNode()); + begin.setNext(with); + return begin; + } + + @Override + public void simplify(SimplifierTool tool) { + FixedNode prev = (FixedNode) this.predecessor(); + if (prev == null) { + // This is the start node. + } else if (prev instanceof ControlSplitNode) { + // This begin node is necessary. + } else { + // This begin node can be removed and all guards moved up to the preceding begin node. + prepareDelete(); + tool.addToWorkList(next()); + ((StructuredGraph) graph()).removeFixed(this); + } + } + + public static AbstractBeginNode prevBegin(FixedNode from) { + Node prevBegin = from; + while (prevBegin != null) { + if (prevBegin instanceof AbstractBeginNode) { + return (AbstractBeginNode) prevBegin; + } + prevBegin = prevBegin.predecessor(); + } + return null; + } + + private void evacuateGuards(FixedNode evacuateFrom) { + if (!usages().isEmpty()) { + AbstractBeginNode prevBegin = prevBegin(evacuateFrom); + assert prevBegin != null; + for (Node anchored : anchored().snapshot()) { + anchored.replaceFirstInput(this, prevBegin); + } + } + } + + public void prepareDelete() { + prepareDelete((FixedNode) predecessor()); + } + + public void prepareDelete(FixedNode evacuateFrom) { + removeProxies(); + evacuateGuards(evacuateFrom); + } + + public void removeProxies() { + for (ProxyNode vpn : proxies().snapshot()) { + // can not use graph.replaceFloating because vpn.value may be null during killCFG + vpn.replaceAtUsages(vpn.value()); + vpn.safeDelete(); + } + } + + @Override + public boolean verify() { + assertTrue(predecessor() != null || this == ((StructuredGraph) graph()).start() || this instanceof MergeNode, "begin nodes must be connected"); + return super.verify(); + } + + @Override + public void generate(LIRGeneratorTool gen) { + // nop + } + + public NodeIterable guards() { + return usages().filter(GuardNode.class); + } + + public NodeIterable anchored() { + return usages().filter(isNotA(ProxyNode.class)); + } + + public NodeIterable proxies() { + return usages().filter(ProxyNode.class); + } + + public NodeIterable getBlockNodes() { + return new AbstractNodeIterable() { + + @Override + public Iterator iterator() { + return new BlockNodeIterator(AbstractBeginNode.this); + } + }; + } + + private class BlockNodeIterator implements Iterator { + + private FixedNode current; + + public BlockNodeIterator(FixedNode next) { + this.current = next; + } + + @Override + public boolean hasNext() { + return current != null; + } + + @Override + public FixedNode next() { + FixedNode ret = current; + if (ret == null) { + throw new NoSuchElementException(); + } + if (!(current instanceof FixedWithNextNode) || (current instanceof AbstractBeginNode && current != AbstractBeginNode.this)) { + current = null; + } else { + current = ((FixedWithNextNode) current).next(); + } + return ret; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,56 @@ +/* + * 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.nodes; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public abstract class AbstractEndNode extends FixedNode implements Node.IterableNodeType, LIRLowerable { + + protected AbstractEndNode() { + super(StampFactory.forVoid()); + } + + @Override + public void generate(LIRGeneratorTool gen) { + gen.visitEndNode(this); + } + + public MergeNode merge() { + return (MergeNode) usages().first(); + } + + @Override + public boolean verify() { + assertTrue(usages().count() <= 1, "at most one usage"); + return super.verify(); + } + + @Override + public Iterable cfgSuccessors() { + return Arrays.asList(merge()); + } +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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,32 +22,9 @@ */ package com.oracle.graal.nodes; -import static com.oracle.graal.graph.iterators.NodePredicates.*; - -import java.util.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.iterators.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public class BeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, Node.IterableNodeType { - - @Input(notDataflow = true) private FrameState stateAfter; - - public FrameState stateAfter() { - return stateAfter; - } - - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - updateUsages(stateAfter, x); - stateAfter = x; - } - - public boolean hasSideEffect() { - return false; - } +public final class BeginNode extends AbstractBeginNode { public BeginNode() { super(StampFactory.dependency()); @@ -57,134 +34,6 @@ super(stamp); } - public static BeginNode begin(FixedNode with) { - if (with instanceof BeginNode) { - return (BeginNode) with; - } - BeginNode begin = with.graph().add(new BeginNode()); - begin.setNext(with); - return begin; - } - - @Override - public void simplify(SimplifierTool tool) { - FixedNode prev = (FixedNode) this.predecessor(); - if (prev == null) { - // This is the start node. - } else if (prev instanceof ControlSplitNode) { - // This begin node is necessary. - } else { - // This begin node can be removed and all guards moved up to the preceding begin node. - prepareDelete(); - tool.addToWorkList(next()); - ((StructuredGraph) graph()).removeFixed(this); - } - } - - public static BeginNode prevBegin(FixedNode from) { - Node prevBegin = from; - while (prevBegin != null) { - if (prevBegin instanceof BeginNode) { - return (BeginNode) prevBegin; - } - prevBegin = prevBegin.predecessor(); - } - return null; - } - - private void evacuateGuards(FixedNode evacuateFrom) { - if (!usages().isEmpty()) { - BeginNode prevBegin = prevBegin(evacuateFrom); - assert prevBegin != null; - for (Node anchored : anchored().snapshot()) { - anchored.replaceFirstInput(this, prevBegin); - } - } - } - - public void prepareDelete() { - prepareDelete((FixedNode) predecessor()); - } - - public void prepareDelete(FixedNode evacuateFrom) { - removeProxies(); - evacuateGuards(evacuateFrom); - } - - public void removeProxies() { - for (ProxyNode vpn : proxies().snapshot()) { - // can not use graph.replaceFloating because vpn.value may be null during killCFG - vpn.replaceAtUsages(vpn.value()); - vpn.safeDelete(); - } - } - - @Override - public boolean verify() { - assertTrue(predecessor() != null || this == ((StructuredGraph) graph()).start() || this instanceof MergeNode, "begin nodes must be connected"); - return super.verify(); - } - - @Override - public void generate(LIRGeneratorTool gen) { - // nop - } - - public NodeIterable guards() { - return usages().filter(GuardNode.class); - } - - public NodeIterable anchored() { - return usages().filter(isNotA(ProxyNode.class)); - } - - public NodeIterable proxies() { - return usages().filter(ProxyNode.class); - } - - public NodeIterable getBlockNodes() { - return new AbstractNodeIterable() { - - @Override - public Iterator iterator() { - return new BlockNodeIterator(BeginNode.this); - } - }; - } - - private class BlockNodeIterator implements Iterator { - - private FixedNode current; - - public BlockNodeIterator(FixedNode next) { - this.current = next; - } - - @Override - public boolean hasNext() { - return current != null; - } - - @Override - public FixedNode next() { - FixedNode ret = current; - if (ret == null) { - throw new NoSuchElementException(); - } - if (!(current instanceof FixedWithNextNode) || (current instanceof BeginNode && current != BeginNode.this)) { - current = null; - } else { - current = ((FixedWithNextNode) current).next(); - } - return ret; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - @NodeIntrinsic public static native BeginNode anchor(@ConstantNodeParameter Stamp stamp); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -25,11 +25,11 @@ import com.oracle.graal.nodes.type.*; /** - * Base class for {@link BeginNode}s that are associated with a frame state. TODO (dnsimon) this not - * needed until {@link BeginNode} no longer implements {@link StateSplit} which is not possible + * Base class for {@link AbstractBeginNode}s that are associated with a frame state. TODO (dnsimon) this not + * needed until {@link AbstractBeginNode} no longer implements {@link StateSplit} which is not possible * until loop peeling works without requiring begin nodes to have frames states */ -public abstract class BeginStateSplitNode extends BeginNode implements StateSplit { +public abstract class BeginStateSplitNode extends AbstractBeginNode implements StateSplit { public BeginStateSplitNode() { } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -34,5 +34,5 @@ super(stamp); } - public abstract double probability(BeginNode successor); + public abstract double probability(AbstractBeginNode successor); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EndNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -22,35 +22,5 @@ */ package com.oracle.graal.nodes; -import java.util.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -public class EndNode extends FixedNode implements Node.IterableNodeType, LIRLowerable { - - public EndNode() { - super(StampFactory.forVoid()); - } - - @Override - public void generate(LIRGeneratorTool gen) { - gen.visitEndNode(this); - } - - public MergeNode merge() { - return (MergeNode) usages().first(); - } - - @Override - public boolean verify() { - assertTrue(usages().count() <= 1, "at most one usage"); - return super.verify(); - } - - @Override - public Iterable cfgSuccessors() { - return Arrays.asList(merge()); - } +public final class EndNode extends AbstractEndNode { } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -29,7 +29,7 @@ * This node will be inserted at point specified by {@link StructuredGraph#getEntryBCI()}, usually * by the graph builder. */ -public class EntryMarkerNode extends BeginNode implements Node.IterableNodeType, Simplifiable, LIRLowerable { +public class EntryMarkerNode extends AbstractBeginNode implements Node.IterableNodeType, Simplifiable, LIRLowerable { @Override public void simplify(SimplifierTool tool) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -101,7 +101,8 @@ } @Override - public Negatable negate() { + public Negatable negate(LogicNode cond) { + assert cond == condition(); negated = !negated; return this; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -104,7 +104,8 @@ } @Override - public Negatable negate() { + public Negatable negate(LogicNode cond) { + assert cond == condition(); negated = !negated; return this; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -43,8 +43,8 @@ */ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, Negatable { - @Successor private BeginNode trueSuccessor; - @Successor private BeginNode falseSuccessor; + @Successor private AbstractBeginNode trueSuccessor; + @Successor private AbstractBeginNode falseSuccessor; @Input private LogicNode condition; private double trueSuccessorProbability; @@ -58,10 +58,10 @@ } public IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) { - this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), trueSuccessorProbability); + this(condition, AbstractBeginNode.begin(trueSuccessor), AbstractBeginNode.begin(falseSuccessor), trueSuccessorProbability); } - public IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) { + public IfNode(LogicNode condition, AbstractBeginNode trueSuccessor, AbstractBeginNode falseSuccessor, double trueSuccessorProbability) { super(StampFactory.forVoid()); this.condition = condition; this.falseSuccessor = falseSuccessor; @@ -75,7 +75,7 @@ * * @return the true successor */ - public BeginNode trueSuccessor() { + public AbstractBeginNode trueSuccessor() { return trueSuccessor; } @@ -84,16 +84,16 @@ * * @return the false successor */ - public BeginNode falseSuccessor() { + public AbstractBeginNode falseSuccessor() { return falseSuccessor; } - public void setTrueSuccessor(BeginNode node) { + public void setTrueSuccessor(AbstractBeginNode node) { updatePredecessor(trueSuccessor, node); trueSuccessor = node; } - public void setFalseSuccessor(BeginNode node) { + public void setFalseSuccessor(AbstractBeginNode node) { updatePredecessor(falseSuccessor, node); falseSuccessor = node; } @@ -104,14 +104,15 @@ * @param istrue {@code true} if the true successor is requested, {@code false} otherwise * @return the corresponding successor */ - public BeginNode successor(boolean istrue) { + public AbstractBeginNode successor(boolean istrue) { return istrue ? trueSuccessor : falseSuccessor; } @Override - public Negatable negate() { - BeginNode trueSucc = trueSuccessor(); - BeginNode falseSucc = falseSuccessor(); + public Negatable negate(LogicNode cond) { + assert cond == condition(); + AbstractBeginNode trueSucc = trueSuccessor(); + AbstractBeginNode falseSucc = falseSuccessor(); setTrueSuccessor(null); setFalseSuccessor(null); setTrueSuccessor(falseSucc); @@ -125,7 +126,7 @@ } @Override - public double probability(BeginNode successor) { + public double probability(AbstractBeginNode successor) { return successor == trueSuccessor ? trueSuccessorProbability : 1 - trueSuccessorProbability; } @@ -169,7 +170,7 @@ } if (falseSuccessor().usages().isEmpty() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) { - BeginNode intermediateBegin = falseSuccessor(); + AbstractBeginNode intermediateBegin = falseSuccessor(); IfNode nextIf = (IfNode) intermediateBegin.next(); double probabilityB = (1.0 - this.trueSuccessorProbability) * nextIf.trueSuccessorProbability; if (this.trueSuccessorProbability < probabilityB) { @@ -178,7 +179,7 @@ if (prepareForSwap(tool.runtime(), condition(), nextIf.condition(), this.trueSuccessorProbability, probabilityB)) { // Reording is allowed from (if1 => begin => if2) to (if2 => begin => if1). assert intermediateBegin.next() == nextIf; - BeginNode bothFalseBegin = nextIf.falseSuccessor(); + AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor(); nextIf.setFalseSuccessor(null); intermediateBegin.setNext(null); this.setFalseSuccessor(null); @@ -322,9 +323,9 @@ * @return true if a transformation was made, false otherwise */ private boolean removeOrMaterializeIf(SimplifierTool tool) { - if (trueSuccessor().next() instanceof EndNode && falseSuccessor().next() instanceof EndNode) { - EndNode trueEnd = (EndNode) trueSuccessor().next(); - EndNode falseEnd = (EndNode) falseSuccessor().next(); + if (trueSuccessor().next() instanceof AbstractEndNode && falseSuccessor().next() instanceof AbstractEndNode) { + AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next(); + AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next(); MergeNode merge = trueEnd.merge(); if (merge == falseEnd.merge() && merge.forwardEndCount() == 2 && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) { Iterator phis = merge.phis().iterator(); @@ -447,7 +448,7 @@ } } - List mergePredecessors = merge.cfgPredecessors().snapshot(); + List mergePredecessors = merge.cfgPredecessors().snapshot(); assert phi.valueCount() == merge.forwardEndCount(); Constant[] xs = constantValues(compare.x(), merge); @@ -461,19 +462,19 @@ return false; } - List falseEnds = new ArrayList<>(mergePredecessors.size()); - List trueEnds = new ArrayList<>(mergePredecessors.size()); - Map phiValues = new HashMap<>(mergePredecessors.size()); + List falseEnds = new ArrayList<>(mergePredecessors.size()); + List trueEnds = new ArrayList<>(mergePredecessors.size()); + Map phiValues = new HashMap<>(mergePredecessors.size()); - BeginNode oldFalseSuccessor = falseSuccessor(); - BeginNode oldTrueSuccessor = trueSuccessor(); + AbstractBeginNode oldFalseSuccessor = falseSuccessor(); + AbstractBeginNode oldTrueSuccessor = trueSuccessor(); setFalseSuccessor(null); setTrueSuccessor(null); - Iterator ends = mergePredecessors.iterator(); + Iterator ends = mergePredecessors.iterator(); for (int i = 0; i < xs.length; i++) { - EndNode end = ends.next(); + AbstractEndNode end = ends.next(); phiValues.put(end, phi.valueAt(end)); if (compare.condition().foldCondition(xs[i], ys[i], tool.runtime(), compare.unorderedIsTrue())) { trueEnds.add(end); @@ -525,8 +526,8 @@ } else if (node instanceof FixedWithNextNode) { FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node; node = fixedWithNextNode.next(); - } else if (node instanceof EndNode) { - EndNode endNode = (EndNode) node; + } else if (node instanceof AbstractEndNode) { + AbstractEndNode endNode = (AbstractEndNode) node; node = endNode.merge(); } else if (node instanceof ControlSinkNode) { return true; @@ -545,12 +546,12 @@ * @param oldMerge the merge being removed * @param phiValues the values of the phi at the merge, keyed by the merge ends */ - private void connectEnds(List ends, Map phiValues, BeginNode successor, MergeNode oldMerge, SimplifierTool tool) { + private void connectEnds(List ends, Map phiValues, AbstractBeginNode successor, MergeNode oldMerge, SimplifierTool tool) { if (ends.isEmpty()) { GraphUtil.killCFG(successor); } else { if (ends.size() == 1) { - EndNode end = ends.get(0); + AbstractEndNode end = ends.get(0); ((FixedWithNextNode) end.predecessor()).setNext(successor); oldMerge.removeEnd(end); GraphUtil.killCFG(end); @@ -561,7 +562,7 @@ PhiNode oldPhi = (PhiNode) oldMerge.usages().first(); PhiNode newPhi = graph().add(new PhiNode(oldPhi.stamp(), newMerge)); - for (EndNode end : ends) { + for (AbstractEndNode end : ends) { newPhi.addInput(phiValues.get(end)); newMerge.addForwardEnd(end); } @@ -613,12 +614,12 @@ } private void removeEmptyIf(SimplifierTool tool) { - BeginNode originalTrueSuccessor = trueSuccessor(); - BeginNode originalFalseSuccessor = falseSuccessor(); - assert originalTrueSuccessor.next() instanceof EndNode && originalFalseSuccessor.next() instanceof EndNode; + AbstractBeginNode originalTrueSuccessor = trueSuccessor(); + AbstractBeginNode originalFalseSuccessor = falseSuccessor(); + assert originalTrueSuccessor.next() instanceof AbstractEndNode && originalFalseSuccessor.next() instanceof AbstractEndNode; - EndNode trueEnd = (EndNode) originalTrueSuccessor.next(); - EndNode falseEnd = (EndNode) originalFalseSuccessor.next(); + AbstractEndNode trueEnd = (AbstractEndNode) originalTrueSuccessor.next(); + AbstractEndNode falseEnd = (AbstractEndNode) originalFalseSuccessor.next(); assert trueEnd.merge() == falseEnd.merge(); FixedWithNextNode pred = (FixedWithNextNode) predecessor(); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -34,7 +34,7 @@ @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}") public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint, LIRLowerable { - @Successor private BeginNode next; + @Successor private AbstractBeginNode next; @Successor private DispatchBeginNode exceptionEdge; @Input private final CallTargetNode callTarget; @Input private FrameState deoptState; @@ -61,11 +61,11 @@ exceptionEdge = x; } - public BeginNode next() { + public AbstractBeginNode next() { return next; } - public void setNext(BeginNode x) { + public void setNext(AbstractBeginNode x) { updatePredecessor(next, x); next = x; } @@ -121,7 +121,7 @@ @Override public void setNext(FixedNode x) { if (x != null) { - this.setNext(BeginNode.begin(x)); + this.setNext(AbstractBeginNode.begin(x)); } else { this.setNext(null); } @@ -170,7 +170,7 @@ } public void killExceptionEdge() { - BeginNode edge = exceptionEdge(); + AbstractBeginNode edge = exceptionEdge(); setExceptionEdge(null); GraphUtil.killCFG(edge); } @@ -205,7 +205,7 @@ private static final double EXCEPTION_PROBA = 1e-5; @Override - public double probability(BeginNode successor) { + public double probability(AbstractBeginNode successor) { return successor == next ? 1 - EXCEPTION_PROBA : EXCEPTION_PROBA; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicBinaryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicBinaryNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.spi.*; + +public abstract class LogicBinaryNode extends LogicNode implements Negatable, Node.IterableNodeType { + + @Input private LogicNode x; + @Input private LogicNode y; + private boolean xNegated; + private boolean yNegated; + + public LogicBinaryNode(LogicNode x, LogicNode y) { + this(x, false, y, false); + } + + public LogicBinaryNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated) { + this.x = x; + this.xNegated = xNegated; + this.y = y; + this.yNegated = yNegated; + } + + public LogicNode getX() { + return x; + } + + public LogicNode getY() { + return y; + } + + public boolean isXNegated() { + return xNegated; + } + + public boolean isYNegated() { + return yNegated; + } + + @Override + public Negatable negate(LogicNode condition) { + if (condition == x) { + xNegated = !xNegated; + } + if (condition == y) { + yNegated = !yNegated; + } + return this; + } +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConjunctionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConjunctionNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.nodes.spi.*; + +/** + * This node is true if {@link #getX() x} and {@link #getY() y} are true. + * + */ +public class LogicConjunctionNode extends LogicBinaryNode implements Canonicalizable { + + public LogicConjunctionNode(LogicNode x, LogicNode y) { + this(x, false, y, false); + } + + public LogicConjunctionNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated) { + super(x, xNegated, y, yNegated); + } + + @Override + public LogicNode canonical(CanonicalizerTool tool) { + LogicNode x = getX(); + LogicNode y = getY(); + if (x == y) { + return x; + } + if (x instanceof LogicConstantNode) { + if (((LogicConstantNode) x).getValue() ^ isXNegated()) { + if (isYNegated()) { + negateUsages(); + } + return y; + } else { + return LogicConstantNode.contradiction(graph()); + } + } + if (y instanceof LogicConstantNode) { + if (((LogicConstantNode) y).getValue() ^ isYNegated()) { + if (isXNegated()) { + negateUsages(); + } + return x; + } else { + return LogicConstantNode.contradiction(graph()); + } + } + return this; + } +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicDisjunctionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicDisjunctionNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.nodes.spi.*; + +/** + * This node is true if {@link #getX() x} or {@link #getY() y} are true. + * + */ +public class LogicDisjunctionNode extends LogicBinaryNode implements Canonicalizable { + + public LogicDisjunctionNode(LogicNode x, LogicNode y) { + this(x, false, y, false); + } + + public LogicDisjunctionNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated) { + super(x, xNegated, y, yNegated); + } + + @Override + public LogicNode canonical(CanonicalizerTool tool) { + LogicNode x = getX(); + LogicNode y = getY(); + if (x == y) { + return x; + } + if (x instanceof LogicConstantNode) { + if (((LogicConstantNode) x).getValue() ^ isXNegated()) { + return LogicConstantNode.tautology(graph()); + } else { + if (isYNegated()) { + negateUsages(); + } + return y; + } + } + if (y instanceof LogicConstantNode) { + if (((LogicConstantNode) y).getValue() ^ isYNegated()) { + return LogicConstantNode.tautology(graph()); + } else { + if (isXNegated()) { + negateUsages(); + } + return x; + } + } + return this; + } + +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -40,7 +40,7 @@ public void negateUsages() { for (Node n : usages().snapshot()) { assert n instanceof Negatable; - ((Negatable) n).negate(); + ((Negatable) n).negate(this); } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -87,7 +87,7 @@ return snapshot; } - public EndNode forwardEnd() { + public AbstractEndNode forwardEnd() { assert forwardEndCount() == 1; return forwardEndAt(0); } @@ -98,7 +98,7 @@ } @Override - protected void deleteEnd(EndNode end) { + protected void deleteEnd(AbstractEndNode end) { if (end instanceof LoopEndNode) { LoopEndNode loopEnd = (LoopEndNode) end; loopEnd.setLoopBegin(null); @@ -122,7 +122,7 @@ } @Override - public int phiPredecessorIndex(EndNode pred) { + public int phiPredecessorIndex(AbstractEndNode pred) { if (pred instanceof LoopEndNode) { LoopEndNode loopEnd = (LoopEndNode) pred; if (loopEnd.loopBegin() == this) { @@ -136,7 +136,7 @@ } @Override - public EndNode phiPredecessorAt(int index) { + public AbstractEndNode phiPredecessorAt(int index) { if (index < forwardEndCount()) { return forwardEndAt(index); } @@ -173,7 +173,7 @@ // nothing yet } - public boolean isLoopExit(BeginNode begin) { + public boolean isLoopExit(AbstractBeginNode begin) { return begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == this; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -public final class LoopEndNode extends EndNode { +public final class LoopEndNode extends AbstractEndNode { @Input(notDataflow = true) private LoopBeginNode loopBegin; private boolean canSafepoint; @@ -60,9 +60,6 @@ } public boolean canSafepoint() { - if (!canSafepoint) { - return canSafepoint; - } return canSafepoint; } @@ -81,7 +78,7 @@ /** * Returns the 0-based index of this loop end. This is not the index into {@link PhiNode} - * values at the loop begin. Use {@link MergeNode#phiPredecessorIndex(EndNode)} for this + * values at the loop begin. Use {@link MergeNode#phiPredecessorIndex(AbstractEndNode)} for this * purpose. * * @return The 0-based index of this loop end. diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -35,18 +35,18 @@ */ public class MergeNode extends BeginStateSplitNode implements Node.IterableNodeType, LIRLowerable { - @Input(notDataflow = true) private final NodeInputList ends = new NodeInputList<>(this); + @Input(notDataflow = true) private final NodeInputList ends = new NodeInputList<>(this); @Override public void generate(LIRGeneratorTool gen) { gen.visitMerge(this); } - public int forwardEndIndex(EndNode end) { + public int forwardEndIndex(AbstractEndNode end) { return ends.indexOf(end); } - public void addForwardEnd(EndNode end) { + public void addForwardEnd(AbstractEndNode end) { ends.add(end); } @@ -54,12 +54,12 @@ return ends.size(); } - public EndNode forwardEndAt(int index) { + public AbstractEndNode forwardEndAt(int index) { return ends.get(index); } @Override - public NodeIterable cfgPredecessors() { + public NodeIterable cfgPredecessors() { return ends; } @@ -79,7 +79,7 @@ * * @param pred the end to remove */ - public void removeEnd(EndNode pred) { + public void removeEnd(AbstractEndNode pred) { int predIndex = phiPredecessorIndex(pred); assert predIndex != -1; deleteEnd(pred); @@ -95,7 +95,7 @@ } } - protected void deleteEnd(EndNode end) { + protected void deleteEnd(AbstractEndNode end) { ends.remove(end); } @@ -103,7 +103,7 @@ ends.clear(); } - public NodeIterable forwardEnds() { + public NodeIterable forwardEnds() { return ends; } @@ -111,11 +111,11 @@ return forwardEndCount(); } - public int phiPredecessorIndex(EndNode pred) { + public int phiPredecessorIndex(AbstractEndNode pred) { return forwardEndIndex(pred); } - public EndNode phiPredecessorAt(int index) { + public AbstractEndNode phiPredecessorAt(int index) { return forwardEndAt(index); } @@ -143,8 +143,8 @@ @Override public void simplify(SimplifierTool tool) { FixedNode next = next(); - if (next instanceof EndNode) { - EndNode origLoopEnd = (EndNode) next; + if (next instanceof AbstractEndNode) { + AbstractEndNode origLoopEnd = (AbstractEndNode) next; MergeNode merge = origLoopEnd.merge(); if (merge instanceof LoopBeginNode && !(origLoopEnd instanceof LoopEndNode)) { return; @@ -169,8 +169,8 @@ int numEnds = this.forwardEndCount(); StructuredGraph graph = (StructuredGraph) graph(); for (int i = 0; i < numEnds - 1; i++) { - EndNode end = forwardEndAt(numEnds - 1 - i); - EndNode newEnd; + AbstractEndNode end = forwardEndAt(numEnds - 1 - i); + AbstractEndNode newEnd; if (merge instanceof LoopBeginNode) { newEnd = graph.add(new LoopEndNode((LoopBeginNode) merge)); } else { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -159,7 +159,7 @@ values.set(i, x); } - public ValueNode valueAt(EndNode pred) { + public ValueNode valueAt(AbstractEndNode pred) { return valueAt(merge().phiPredecessorIndex(pred)); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -37,12 +37,12 @@ @NodeInfo(nameTemplate = "{p#type/s}Proxy") public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable { - @Input(notDataflow = true) private BeginNode proxyPoint; + @Input(notDataflow = true) private AbstractBeginNode proxyPoint; @Input private ValueNode value; private final PhiType type; private final Object identity; - public ProxyNode(ValueNode value, BeginNode exit, PhiType type, Object identity) { + public ProxyNode(ValueNode value, AbstractBeginNode exit, PhiType type, Object identity) { super(type == PhiType.Value ? value.stamp() : type.stamp); this.type = type; this.identity = identity; @@ -65,7 +65,7 @@ return value().stamp(); } - public BeginNode proxyPoint() { + public AbstractBeginNode proxyPoint() { return proxyPoint; } @@ -108,11 +108,11 @@ } } - public static ProxyNode forValue(ValueNode value, BeginNode exit, StructuredGraph graph) { + public static ProxyNode forValue(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) { return graph.unique(new ProxyNode(value, exit, PhiType.Value, null)); } - public static ProxyNode forMemory(ValueNode value, BeginNode exit, Object location, StructuredGraph graph) { + public static ProxyNode forMemory(ValueNode value, AbstractBeginNode exit, Object location, StructuredGraph graph) { return graph.unique(new ProxyNode(value, exit, PhiType.Memory, location)); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Tue Apr 30 23:09:37 2013 +0200 @@ -50,14 +50,14 @@ private final int entryBCI; /** - * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node. + * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() start} node. */ public StructuredGraph() { this(null, null); } /** - * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node. + * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() start} node. */ public StructuredGraph(String name, ResolvedJavaMethod method) { this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI); @@ -214,8 +214,8 @@ */ public void removeFixed(FixedWithNextNode node) { assert node != null; - if (node instanceof BeginNode) { - ((BeginNode) node).prepareDelete(); + if (node instanceof AbstractBeginNode) { + ((AbstractBeginNode) node).prepareDelete(); } assert node.usages().isEmpty() : node + " " + node.usages(); FixedNode next = node.next(); @@ -251,7 +251,7 @@ node.safeDelete(); } - public void removeSplit(ControlSplitNode node, BeginNode survivingSuccessor) { + public void removeSplit(ControlSplitNode node, AbstractBeginNode survivingSuccessor) { assert node != null; assert node.usages().isEmpty(); assert survivingSuccessor != null; @@ -260,7 +260,7 @@ node.safeDelete(); } - public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) { + public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor) { assert node != null; assert node.usages().isEmpty(); assert survivingSuccessor != null; @@ -271,13 +271,13 @@ for (Node successor : snapshot) { if (successor != null && successor.isAlive()) { if (successor != survivingSuccessor) { - GraphUtil.killCFG((BeginNode) successor); + GraphUtil.killCFG((AbstractBeginNode) successor); } } } } - public void replaceSplit(ControlSplitNode node, Node replacement, BeginNode survivingSuccessor) { + public void replaceSplit(ControlSplitNode node, Node replacement, AbstractBeginNode survivingSuccessor) { if (replacement instanceof FixedWithNextNode) { replaceSplitWithFixed(node, (FixedWithNextNode) replacement, survivingSuccessor); } else { @@ -287,7 +287,7 @@ } } - public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, BeginNode survivingSuccessor) { + public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, AbstractBeginNode survivingSuccessor) { assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement; assert survivingSuccessor != null; node.clearSuccessors(); @@ -295,7 +295,7 @@ node.replaceAndDelete(replacement); } - public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, BeginNode survivingSuccessor) { + public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, AbstractBeginNode survivingSuccessor) { assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement; assert survivingSuccessor != null; node.clearSuccessors(); @@ -348,7 +348,7 @@ if (merge instanceof LoopBeginNode) { ((LoopBeginNode) merge).removeExits(); } - EndNode singleEnd = merge.forwardEndAt(0); + AbstractEndNode singleEnd = merge.forwardEndAt(0); FixedNode sux = merge.next(); FrameState stateAfter = merge.stateAfter(); // evacuateGuards diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -101,6 +101,16 @@ return this; } + protected void setX(ValueNode x) { + updateUsages(this.x, x); + this.x = x; + } + + protected void setY(ValueNode y) { + updateUsages(this.y, y); + this.y = y; + } + protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { throw new GraalInternalError("NormalizeCompareNode connected to %s (%s %s %s)", this, constant, normalizeNode, mirrored); } @@ -123,6 +133,14 @@ return optimizeNormalizeCmp(y().asConstant(), (NormalizeCompareNode) x(), false); } } + if (x() instanceof ConvertNode && y() instanceof ConvertNode) { + ConvertNode convertX = (ConvertNode) x(); + ConvertNode convertY = (ConvertNode) y(); + if (convertX.opcode.isLossless() && convertY.opcode.isLossless()) { + setX(convertX.value()); + setY(convertY.value()); + } + } return this; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -94,7 +94,8 @@ } @Override - public Negatable negate() { + public Negatable negate(LogicNode cond) { + assert condition() == cond; ConditionalNode replacement = graph().unique(new ConditionalNode(condition, falseValue(), trueValue())); ((StructuredGraph) graph()).replaceFloating(this, replacement); return replacement; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.meta.Kind.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -34,34 +35,97 @@ */ public final class ConvertNode extends FloatingNode implements Canonicalizable, LIRLowerable, Lowerable { - public enum Op { - I2L(Int, Long), - L2I(Long, Int), - I2B(Int, Byte), - I2C(Int, Char), - I2S(Int, Short), - F2D(Float, Double), - D2F(Double, Float), - I2F(Int, Float), - I2D(Int, Double), - F2I(Float, Int), - D2I(Double, Int), - L2F(Long, Float), - L2D(Long, Double), - F2L(Float, Long), - D2L(Double, Long), - UNSIGNED_I2L(Int, Long), - MOV_I2F(Int, Float), - MOV_L2D(Long, Double), - MOV_F2I(Float, Int), - MOV_D2L(Double, Long); + public static enum Op { + I2L(Int, Long, true), + L2I(Long, Int, false), + I2B(Int, Byte, false), + I2C(Int, Char, false), + I2S(Int, Short, false), + F2D(Float, Double, false), + D2F(Double, Float, false), + I2F(Int, Float, false), + I2D(Int, Double, true), + F2I(Float, Int, false), + D2I(Double, Int, false), + L2F(Long, Float, false), + L2D(Long, Double, false), + F2L(Float, Long, false), + D2L(Double, Long, false), + UNSIGNED_I2L(Int, Long, true), + MOV_I2F(Int, Float, false), + MOV_L2D(Long, Double, false), + MOV_F2I(Float, Int, false), + MOV_D2L(Double, Long, false); public final Kind from; public final Kind to; + public final boolean lossless; - private Op(Kind from, Kind to) { + private Op(Kind from, Kind to, boolean lossless) { this.from = from; this.to = to; + this.lossless = lossless; + } + + public boolean isLossless() { + return lossless; + } + + public static Op getOp(Kind from, Kind to) { + switch (from) { + case Int: + switch (to) { + case Byte: + return I2B; + case Char: + return I2C; + case Short: + return I2S; + case Long: + return I2L; + case Float: + return I2F; + case Double: + return I2D; + default: + throw GraalInternalError.shouldNotReachHere(); + } + case Long: + switch (to) { + case Int: + return L2I; + case Float: + return L2F; + case Double: + return L2D; + default: + throw GraalInternalError.shouldNotReachHere(); + } + case Float: + switch (to) { + case Int: + return F2I; + case Long: + return F2L; + case Double: + return F2D; + default: + throw GraalInternalError.shouldNotReachHere(); + } + case Double: + switch (to) { + case Int: + return D2I; + case Long: + return D2L; + case Float: + return D2F; + default: + throw GraalInternalError.shouldNotReachHere(); + } + default: + throw GraalInternalError.shouldNotReachHere(); + } } } @@ -171,6 +235,14 @@ gen.setResult(this, gen.emitConvert(opcode, gen.operand(value()))); } + public static ValueNode convert(Kind toKind, ValueNode value) { + Kind fromKind = value.kind(); + if (fromKind == toKind) { + return value; + } + return value.graph().unique(new ConvertNode(Op.getOp(fromKind, toKind), value)); + } + @NodeIntrinsic public static native float convert(@ConstantNodeParameter Op op, int value); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -99,6 +99,13 @@ } } + if (next() instanceof IntegerDivNode) { + NodeClass nodeClass = NodeClass.get(this.getClass()); + if (next().getClass() == this.getClass() && nodeClass.inputsEqual(this, next()) && nodeClass.valueEqual(this, next())) { + return next(); + } + } + return this; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -69,6 +69,10 @@ if (x() instanceof NegateNode) { return ((NegateNode) x()).x(); } + if (x() instanceof IntegerSubNode) { + IntegerSubNode sub = (IntegerSubNode) x; + return IntegerArithmeticNode.sub(sub.y(), sub.x()); + } return this; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Tue Apr 30 23:09:37 2013 +0200 @@ -29,7 +29,7 @@ public final class Block { - protected final BeginNode beginNode; + protected final AbstractBeginNode beginNode; protected int id; @@ -46,7 +46,7 @@ private boolean align; private int linearScanNumber; - protected Block(BeginNode node) { + protected Block(AbstractBeginNode node) { this.beginNode = node; this.id = ControlFlowGraph.BLOCK_ID_INITIAL; @@ -57,7 +57,7 @@ return id; } - public BeginNode getBeginNode() { + public AbstractBeginNode getBeginNode() { return beginNode; } @@ -150,7 +150,7 @@ } else { cur = ((FixedWithNextNode) cur).next(); } - assert !(cur instanceof BeginNode); + assert !(cur instanceof AbstractBeginNode); return result; } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Tue Apr 30 23:09:37 2013 +0200 @@ -58,7 +58,7 @@ protected ControlFlowGraph(StructuredGraph graph) { this.graph = graph; - this.nodeToBlock = graph.createNodeMap(); + this.nodeToBlock = graph.createNodeMap(true); } public Block[] getBlocks() { @@ -135,7 +135,7 @@ last = cur; cur = cur.successors().first(); - } while (cur != null && !(cur instanceof BeginNode)); + } while (cur != null && !(cur instanceof AbstractBeginNode)); block.endNode = (FixedNode) last; } @@ -144,8 +144,8 @@ // Find all block headers int numBlocks = 0; for (Node node : graph.getNodes()) { - if (node instanceof BeginNode) { - Block block = new Block((BeginNode) node); + if (node instanceof AbstractBeginNode) { + Block block = new Block((AbstractBeginNode) node); numBlocks++; identifyBlock(block); } @@ -247,7 +247,7 @@ for (Block b : loop.blocks) { for (Block sux : b.getSuccessors()) { if (sux.loop != loop) { - BeginNode begin = sux.getBeginNode(); + AbstractBeginNode begin = sux.getBeginNode(); if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) { Debug.log("Unexpected loop exit with %s, including whole branch in the loop", sux); unexpected.add(sux); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -48,7 +48,7 @@ * @param keyProbabilities the probabilities of the keys * @param keySuccessors the successor index for each key */ - public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { + public IntegerSwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { super(value, successors, keySuccessors, keyProbabilities); assert keySuccessors.length == keys.length + 1; assert keySuccessors.length == keyProbabilities.length; @@ -66,7 +66,7 @@ * @param keySuccessors the successor index for each key */ public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) { - this(value, new BeginNode[successorCount], keys, keyProbabilities, keySuccessors); + this(value, new AbstractBeginNode[successorCount], keys, keyProbabilities, keySuccessors); } /** @@ -124,7 +124,7 @@ tool.addToWorkList(defaultSuccessor()); ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessor()); } else if (validKeys != keys.length) { - ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount()); + ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount()); int[] newKeys = new int[validKeys]; int[] newKeySuccessors = new int[validKeys + 1]; double[] newKeyProbabilities = new double[validKeys + 1]; @@ -153,14 +153,14 @@ } for (int i = 0; i < blockSuccessorCount(); i++) { - BeginNode successor = blockSuccessor(i); + AbstractBeginNode successor = blockSuccessor(i); if (!newSuccessors.contains(successor)) { tool.deleteBranch(successor); } setBlockSuccessor(i, null); } - BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]); + AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]); IntegerSwitchNode newSwitch = graph().add(new IntegerSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors)); ((FixedWithNextNode) predecessor()).setNext(newSwitch); GraphUtil.killWithUnusedFloatingInputs(this); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -34,7 +34,7 @@ */ public abstract class SwitchNode extends ControlSplitNode { - @Successor protected final NodeSuccessorList successors; + @Successor protected final NodeSuccessorList successors; @Input private ValueNode value; private double[] keyProbabilities; private int[] keySuccessors; @@ -45,7 +45,7 @@ * @param value the instruction that provides the value to be switched over * @param successors the list of successors of this switch */ - public SwitchNode(ValueNode value, BeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) { + public SwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) { super(StampFactory.forVoid()); assert keySuccessors.length == keyProbabilities.length; this.successors = new NodeSuccessorList<>(this, successors); @@ -55,7 +55,7 @@ } @Override - public double probability(BeginNode successor) { + public double probability(AbstractBeginNode successor) { double sum = 0; for (int i = 0; i < keySuccessors.length; i++) { if (successors.get(keySuccessors[i]) == successor) { @@ -89,7 +89,7 @@ /** * Returns the successor for the key at the given index. */ - public BeginNode keySuccessor(int i) { + public AbstractBeginNode keySuccessor(int i) { return successors.get(keySuccessors[i]); } @@ -107,11 +107,11 @@ return keySuccessors[keySuccessors.length - 1]; } - public BeginNode blockSuccessor(int i) { + public AbstractBeginNode blockSuccessor(int i) { return successors.get(i); } - public void setBlockSuccessor(int i, BeginNode s) { + public void setBlockSuccessor(int i, AbstractBeginNode s) { successors.set(i, s); } @@ -124,7 +124,7 @@ * * @return the default successor */ - public BeginNode defaultSuccessor() { + public AbstractBeginNode defaultSuccessor() { if (defaultSuccessorIndex() == -1) { throw new GraalInternalError("unexpected"); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -90,7 +90,7 @@ @Override public void generate(LIRGeneratorTool generator) { if (kind() != object().kind()) { - assert generator.target().sizeInBytes(kind()) == generator.target().sizeInBytes(object().kind()) : "unsafe cast cannot be used to change the size of a value"; + assert generator.target().arch.getSizeInBytes(kind()) == generator.target().arch.getSizeInBytes(object().kind()) : "unsafe cast cannot be used to change the size of a value"; AllocatableValue result = generator.newVariable(kind()); generator.emitMove(result, generator.operand(object())); generator.setResult(this, result); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -100,7 +100,7 @@ if (permanent) { return; } - for (ValueNode node : dependencies().nonNull().and(isNotA(BeginNode.class))) { + for (ValueNode node : dependencies().nonNull().and(isNotA(AbstractBeginNode.class))) { State state = tool.getObjectState(node); if (state == null || state.getState() != EscapeState.Virtual) { return; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Tue Apr 30 23:09:37 2013 +0200 @@ -50,7 +50,7 @@ * @param keyProbabilities the probabilities of the keys * @param keySuccessors the successor index for each key */ - public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { + public TypeSwitchNode(ValueNode value, AbstractBeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { super(value, successors, keySuccessors, keyProbabilities); assert successors.length <= keys.length + 1; assert keySuccessors.length == keyProbabilities.length; @@ -110,7 +110,7 @@ tool.addToWorkList(defaultSuccessor()); ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessor()); } else if (validKeys != keys.length) { - ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount()); + ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount()); ResolvedJavaType[] newKeys = new ResolvedJavaType[validKeys]; int[] newKeySuccessors = new int[validKeys + 1]; double[] newKeyProbabilities = new double[validKeys + 1]; @@ -139,14 +139,14 @@ } for (int i = 0; i < blockSuccessorCount(); i++) { - BeginNode successor = blockSuccessor(i); + AbstractBeginNode successor = blockSuccessor(i); if (!newSuccessors.contains(successor)) { tool.deleteBranch(successor); } setBlockSuccessor(i, null); } - BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]); + AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]); TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors)); ((FixedWithNextNode) predecessor()).setNext(newSwitch); GraphUtil.killWithUnusedFloatingInputs(this); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Tue Apr 30 23:09:37 2013 +0200 @@ -49,7 +49,7 @@ Value operand(ValueNode object); - AllocatableValue newVariable(Kind kind); + AllocatableValue newVariable(PlatformKind kind); Value setResult(ValueNode x, Value operand); @@ -116,7 +116,7 @@ // Handling of block-end nodes still needs to be unified in the LIRGenerator. void visitMerge(MergeNode i); - void visitEndNode(EndNode i); + void visitEndNode(AbstractEndNode i); void visitLoopEnd(LoopEndNode i); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Negatable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Negatable.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Negatable.java Tue Apr 30 23:09:37 2013 +0200 @@ -28,15 +28,15 @@ * This interface marks a node as being able to negate its effect, this is intended for nodes that * depend on a BooleanNode condition. The canonical representation of has, for example, no way to * represent a != b. If such an expression appears during canonicalization the negated expression - * will be created (a == b) and the usages will be negated, using this interface's {@link #negate()} - * method. + * will be created (a == b) and the usages will be negated, using this interface's + * {@link #negate(LogicNode)} method. */ public interface Negatable { /** * Tells this node that a condition it depends has been negated, and that it thus needs to - * invert its own effect. For example, an {@link IfNode} would switch its true and false - * successors. + * invert the effects of this condition. For example, an {@link IfNode} would switch its true + * and false successors. */ - Negatable negate(); + Negatable negate(LogicNode condition); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java Tue Apr 30 23:09:37 2013 +0200 @@ -147,7 +147,7 @@ private void processMerge(MergeNode merge, DominatorInfo info) { // TTY.println("processMerge(" + merge + ", " + info + ")"); - for (EndNode end : merge.cfgPredecessors()) { + for (AbstractEndNode end : merge.cfgPredecessors()) { toExplore.add(end); infoMap.set(end, info.createChild(end)); // TTY.println(" Enqueue end : " + end + " with " + infoMap.get(end)); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Tue Apr 30 23:09:37 2013 +0200 @@ -44,9 +44,9 @@ public static void killCFG(FixedNode node) { assert node.isAlive(); - if (node instanceof EndNode) { + if (node instanceof AbstractEndNode) { // We reached a control flow end. - EndNode end = (EndNode) node; + AbstractEndNode end = (AbstractEndNode) node; killEnd(end); } else { // Normal control flow node. @@ -63,7 +63,7 @@ propagateKill(node); } - private static void killEnd(EndNode end) { + private static void killEnd(AbstractEndNode end) { MergeNode merge = end.merge(); if (merge != null) { merge.removeEnd(end); @@ -152,7 +152,7 @@ } public static void checkRedundantProxy(ProxyNode vpn) { - BeginNode proxyPoint = vpn.proxyPoint(); + AbstractBeginNode proxyPoint = vpn.proxyPoint(); if (proxyPoint instanceof LoopExitNode) { LoopExitNode exit = (LoopExitNode) proxyPoint; LoopBeginNode loopBegin = exit.loopBegin(); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -213,7 +213,7 @@ } @Override - public void afterSplit(BeginNode node) { + public void afterSplit(AbstractBeginNode node) { } @Override @@ -355,7 +355,7 @@ } } - private void registerControlSplitInfo(Node pred, BeginNode begin) { + private void registerControlSplitInfo(Node pred, AbstractBeginNode begin) { assert pred != null && begin != null; if (pred instanceof IfNode) { @@ -461,8 +461,8 @@ @Override protected void node(FixedNode node) { - if (node instanceof BeginNode) { - BeginNode begin = (BeginNode) node; + if (node instanceof AbstractBeginNode) { + AbstractBeginNode begin = (AbstractBeginNode) node; Node pred = node.predecessor(); if (pred != null) { @@ -501,8 +501,8 @@ GraphUtil.killWithUnusedFloatingInputs(compare); } } - } else if (node instanceof EndNode) { - EndNode endNode = (EndNode) node; + } else if (node instanceof AbstractEndNode) { + AbstractEndNode endNode = (AbstractEndNode) node; for (PhiNode phi : endNode.merge().phis()) { int index = endNode.merge().phiPredecessorIndex(endNode); ValueNode value = phi.valueAt(index); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -32,11 +32,11 @@ public class ConvertDeoptimizeToGuardPhase extends Phase { - private static BeginNode findBeginNode(Node startNode) { + private static AbstractBeginNode findBeginNode(Node startNode) { Node n = startNode; while (true) { - if (n instanceof BeginNode) { - return (BeginNode) n; + if (n instanceof AbstractBeginNode) { + return (AbstractBeginNode) n; } else { n = n.predecessor(); } @@ -57,17 +57,17 @@ new DeadCodeEliminationPhase().apply(graph); } - private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) { + private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) { if (deoptBegin instanceof MergeNode) { MergeNode mergeNode = (MergeNode) deoptBegin; Debug.log("Visiting %s followed by %s", mergeNode, deopt); - List begins = new ArrayList<>(); - for (EndNode end : mergeNode.forwardEnds()) { - BeginNode newBeginNode = findBeginNode(end); + List begins = new ArrayList<>(); + for (AbstractEndNode end : mergeNode.forwardEnds()) { + AbstractBeginNode newBeginNode = findBeginNode(end); assert !begins.contains(newBeginNode); begins.add(newBeginNode); } - for (BeginNode begin : begins) { + for (AbstractBeginNode begin : begins) { assert !begin.isDeleted(); visitDeoptBegin(begin, deopt, graph); } @@ -75,7 +75,7 @@ return; } else if (deoptBegin.predecessor() instanceof IfNode) { IfNode ifNode = (IfNode) deoptBegin.predecessor(); - BeginNode otherBegin = ifNode.trueSuccessor(); + AbstractBeginNode otherBegin = ifNode.trueSuccessor(); LogicNode conditionNode = ifNode.condition(); FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.action(), deoptBegin == ifNode.trueSuccessor())); FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor(); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -90,7 +90,7 @@ } @Override - public void afterSplit(BeginNode node) { + public void afterSplit(AbstractBeginNode node) { } @Override diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -52,8 +52,8 @@ private static void iterateSuccessors(NodeFlood flood) { for (Node current : flood) { - if (current instanceof EndNode) { - EndNode end = (EndNode) current; + if (current instanceof AbstractEndNode) { + AbstractEndNode end = (AbstractEndNode) current; flood.add(end.merge()); } else { for (Node successor : current.successors()) { @@ -64,7 +64,7 @@ } private static void disconnectCFGNodes(NodeFlood flood, StructuredGraph graph) { - for (EndNode node : graph.getNodes(EndNode.class)) { + for (AbstractEndNode node : graph.getNodes(AbstractEndNode.class)) { if (!flood.isMarked(node)) { MergeNode merge = node.merge(); if (merge != null && flood.isMarked(merge)) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -119,8 +119,8 @@ if (guard.dependencies().size() != 1) { continue; } - for (EndNode end : merge.forwardEnds()) { - BeginNode begin = BeginNode.prevBegin(end); + for (AbstractEndNode end : merge.forwardEnds()) { + AbstractBeginNode begin = AbstractBeginNode.prevBegin(end); boolean found = false; for (GuardNode predecessorGuard : begin.guards()) { if (predecessorGuard.dependencies().size() != 1) { @@ -140,8 +140,8 @@ Graph graph = merge.graph(); for (GuardNode guard : hits) { PhiNode phi = graph.add(new PhiNode(PhiType.Guard, merge, null)); - for (EndNode otherEnd : merge.forwardEnds()) { - phi.addInput(graph.unique(new GuardNode(guard.condition(), BeginNode.prevBegin(otherEnd), guard.reason(), guard.action(), guard.negated()))); + for (AbstractEndNode otherEnd : merge.forwardEnds()) { + phi.addInput(graph.unique(new GuardNode(guard.condition(), AbstractBeginNode.prevBegin(otherEnd), guard.reason(), guard.action(), guard.negated()))); } guard.replaceAndDelete(phi); metricPRGuardsEliminatedAtMerge.increment(); @@ -152,7 +152,7 @@ private static boolean eliminateAtControlSplit(ControlSplitNode controlSplit) { Map> conditionToGuard = new HashMap<>(); for (Node successor : controlSplit.successors()) { - BeginNode begin = (BeginNode) successor; + AbstractBeginNode begin = (AbstractBeginNode) successor; for (GuardNode guard : begin.guards()) { if (guard.dependencies().size() != 1) { continue; @@ -175,9 +175,9 @@ } DeoptimizationReason reason = null; DeoptimizationAction action = DeoptimizationAction.None; - Set begins = new HashSet<>(3); + Set begins = new HashSet<>(3); for (GuardNode guard : guards) { - BeginNode begin = (BeginNode) guard.dependencies().first(); + AbstractBeginNode begin = (AbstractBeginNode) guard.dependencies().first(); begins.add(begin); if (guard.action().ordinal() > action.ordinal()) { action = guard.action(); @@ -191,7 +191,7 @@ if (begins.size() == controlSplit.successors().count()) { hits = true; Condition condition = entry.getKey(); - GuardNode newGuard = controlSplit.graph().unique(new GuardNode(condition.conditionNode, BeginNode.prevBegin(controlSplit), reason, action, condition.negated)); + GuardNode newGuard = controlSplit.graph().unique(new GuardNode(condition.conditionNode, AbstractBeginNode.prevBegin(controlSplit), reason, action, condition.negated)); for (GuardNode guard : guards) { guard.replaceAndDelete(newGuard); metricPRGuardsEliminatedAtSplit.increment(); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013, 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.phases.common; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.phases.*; + +public class ExpandLogicPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + for (LogicBinaryNode logic : graph.getNodes(LogicBinaryNode.class)) { + processBinary(logic); + } + } + + private static void processBinary(LogicBinaryNode binary) { + while (binary.usages().isNotEmpty()) { + Node usage = binary.usages().first(); + if (usage instanceof LogicBinaryNode) { + processBinary((LogicBinaryNode) usage); + } else if (usage instanceof IfNode) { + if (binary instanceof LogicConjunctionNode) { + processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, false); + } else if (binary instanceof LogicDisjunctionNode) { + processIf(binary.getX(), !binary.isXNegated(), binary.getY(), !binary.isYNegated(), (IfNode) usage, true); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else if (usage instanceof ConditionalNode) { + if (binary instanceof LogicConjunctionNode) { + processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage, false); + } else if (binary instanceof LogicDisjunctionNode) { + processConditional(binary.getX(), !binary.isXNegated(), binary.getY(), !binary.isYNegated(), (ConditionalNode) usage, true); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + binary.safeDelete(); + } + + private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, boolean negateTargets) { + AbstractBeginNode trueTarget = negateTargets ? ifNode.falseSuccessor() : ifNode.trueSuccessor(); + AbstractBeginNode falseTarget = negateTargets ? ifNode.trueSuccessor() : ifNode.falseSuccessor(); + double p = Math.sqrt(ifNode.probability(trueTarget)); + ifNode.clearSuccessors(); + Graph graph = ifNode.graph(); + MergeNode falseTargetMerge = graph.add(new MergeNode()); + falseTargetMerge.setNext(falseTarget); + EndNode firstFalseEnd = graph.add(new EndNode()); + EndNode secondFalseEnd = graph.add(new EndNode()); + falseTargetMerge.addForwardEnd(firstFalseEnd); + falseTargetMerge.addForwardEnd(secondFalseEnd); + AbstractBeginNode firstFalseTarget = AbstractBeginNode.begin(firstFalseEnd); + AbstractBeginNode secondFalseTarget = AbstractBeginNode.begin(secondFalseEnd); + AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? firstFalseTarget : trueTarget, yNegated ? trueTarget : firstFalseTarget, yNegated ? 1 - p : p))); + IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondFalseTarget : secondIf, xNegated ? secondIf : secondFalseTarget, xNegated ? 1 - p : p)); + ifNode.replaceAtPredecessor(firstIf); + ifNode.safeDelete(); + } + + private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional, boolean negateTargets) { + ValueNode trueTarget = negateTargets ? conditional.falseValue() : conditional.trueValue(); + ValueNode falseTarget = negateTargets ? conditional.trueValue() : conditional.falseValue(); + Graph graph = conditional.graph(); + ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget)); + ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? falseTarget : secondConditional, xNegated ? secondConditional : falseTarget)); + conditional.replaceAndDelete(firstConditional); + } +} diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -105,7 +105,7 @@ } @Override - protected Set afterSplit(BeginNode node, Set oldState) { + protected Set afterSplit(AbstractBeginNode node, Set oldState) { return new HashSet<>(oldState); } @@ -214,7 +214,7 @@ } @Override - protected MemoryMap afterSplit(BeginNode node, MemoryMap oldState) { + protected MemoryMap afterSplit(AbstractBeginNode node, MemoryMap oldState) { MemoryMap result = new MemoryMap(oldState); if (node.predecessor() instanceof InvokeWithExceptionNode) { /* diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -171,11 +171,11 @@ private void lowerToIf(GuardNode guard) { StructuredGraph graph = (StructuredGraph) guard.graph(); - BeginNode fastPath = graph.add(new BeginNode()); + AbstractBeginNode fastPath = graph.add(new BeginNode()); DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason())); - BeginNode deoptBranch = BeginNode.begin(deopt); - BeginNode trueSuccessor; - BeginNode falseSuccessor; + AbstractBeginNode deoptBranch = AbstractBeginNode.begin(deopt); + AbstractBeginNode trueSuccessor; + AbstractBeginNode falseSuccessor; insertLoopExits(deopt); if (guard.negated()) { trueSuccessor = deoptBranch; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -532,7 +532,7 @@ return result; } - private void queueMerge(EndNode end) { + private void queueMerge(AbstractEndNode end) { MergeNode merge = end.merge(); if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) { queuedNodes.mark(merge); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Apr 30 23:09:37 2013 +0200 @@ -495,7 +495,7 @@ } // create one separate block for each invoked method - BeginNode[] successors = new BeginNode[numberOfMethods + 1]; + AbstractBeginNode[] successors = new AbstractBeginNode[numberOfMethods + 1]; for (int i = 0; i < numberOfMethods; i++) { successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, true); } @@ -507,7 +507,7 @@ } else { unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)); } - successors[successors.length - 1] = BeginNode.begin(unknownTypeSux); + successors[successors.length - 1] = AbstractBeginNode.begin(unknownTypeSux); // replace the invoke exception edge if (invoke instanceof InvokeWithExceptionNode) { @@ -533,7 +533,7 @@ // do the actual inlining for every invoke for (int i = 0; i < numberOfMethods; i++) { - BeginNode node = successors[i]; + AbstractBeginNode node = successors[i]; Invoke invokeForInlining = (Invoke) node.next(); ResolvedJavaType commonType; @@ -616,10 +616,10 @@ private void inlineSingleMethod(StructuredGraph graph, InliningCallback callback, Replacements replacements, Assumptions assumptions, MetaAccessProvider runtime) { assert concretes.size() == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; - BeginNode calleeEntryNode = graph.add(new BeginNode()); + AbstractBeginNode calleeEntryNode = graph.add(new BeginNode()); - BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); - BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux}; + AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); + AbstractBeginNode[] successors = new AbstractBeginNode[]{calleeEntryNode, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, false, runtime); calleeEntryNode.setNext(invoke.asNode()); @@ -628,7 +628,7 @@ inline(invoke, concrete, callback, replacements, assumptions, false); } - private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider runtime) { + private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, AbstractBeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider runtime) { assert ptypes.size() >= 1; Kind hubKind = ((MethodCallTargetNode) invoke.callTarget()).targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); @@ -728,13 +728,13 @@ return costEstimateMethodDispatch < costEstimateTypeDispatch; } - private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, - boolean useForInlining) { + private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, + PhiNode exceptionObjectPhi, boolean useForInlining) { Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining); - BeginNode calleeEntryNode = graph.add(new BeginNode()); + AbstractBeginNode calleeEntryNode = graph.add(new BeginNode()); calleeEntryNode.setNext(duplicatedInvoke.asNode()); - EndNode endNode = graph.add(new EndNode()); + AbstractEndNode endNode = graph.add(new EndNode()); duplicatedInvoke.setNext(endNode); returnMerge.addForwardEnd(endNode); @@ -769,7 +769,7 @@ // set new state (pop old exception object, push new one) newExceptionEdge.setStateAfter(stateAfterException.duplicateModified(stateAfterException.bci, stateAfterException.rethrowException(), Kind.Object, newExceptionEdge)); - EndNode endNode = graph.add(new EndNode()); + AbstractEndNode endNode = graph.add(new EndNode()); newExceptionEdge.setNext(endNode); exceptionMerge.addForwardEnd(endNode); exceptionObjectPhi.addInput(newExceptionEdge); @@ -812,9 +812,9 @@ private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target, MetaAccessProvider runtime) { InliningUtil.receiverNullCheck(invoke); - BeginNode invocationEntry = graph.add(new BeginNode()); - BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); - BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux}; + AbstractBeginNode invocationEntry = graph.add(new BeginNode()); + AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); + AbstractBeginNode[] successors = new AbstractBeginNode[]{invocationEntry, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, true, runtime); invocationEntry.setNext(invoke.asNode()); @@ -824,8 +824,8 @@ replaceInvokeCallTarget(invoke, graph, kind, target); } - private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) { - return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated))); + private static AbstractBeginNode createUnknownTypeSuccessor(StructuredGraph graph) { + return AbstractBeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated))); } @Override @@ -1175,7 +1175,7 @@ } } // ensure proper anchoring of things that were anchored to the StartNode - replacements.put(entryPointNode, BeginNode.prevBegin(invoke.asNode())); + replacements.put(entryPointNode, AbstractBeginNode.prevBegin(invoke.asNode())); assert invoke.asNode().successors().first() != null : invoke; assert invoke.asNode().predecessor() != null; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -169,7 +169,7 @@ fixedCount++; } if (fixedCount > 1) { - if (fixed instanceof EndNode && !(((EndNode) fixed).merge() instanceof LoopBeginNode)) { + if (fixed instanceof AbstractEndNode && !(((AbstractEndNode) fixed).merge() instanceof LoopBeginNode)) { metricDuplicationEnd.increment(); if (decision.doTransform(merge, fixedCount)) { metricDuplicationEndPerformed.increment(); @@ -246,18 +246,18 @@ fixed = ((FixedWithNextNode) fixed).next(); } - EndNode endAfter = createNewMerge(fixed, stateAfter); + AbstractEndNode endAfter = createNewMerge(fixed, stateAfter); MergeNode mergeAfter = endAfter.merge(); fixedNodes.add(endAfter); final HashSet duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter); mergeAfter.clearEnds(); expandDuplicated(duplicatedNodes, mergeAfter); - List endSnapshot = merge.forwardEnds().snapshot(); + List endSnapshot = merge.forwardEnds().snapshot(); List phiSnapshot = merge.phis().snapshot(); int endIndex = 0; - for (final EndNode forwardEnd : merge.forwardEnds()) { + for (final AbstractEndNode forwardEnd : merge.forwardEnds()) { Map duplicates; if (replacements == null || replacements.get(endIndex) == null) { duplicates = graph.addDuplicates(duplicatedNodes, (DuplicationReplacement) null); @@ -269,14 +269,14 @@ for (Map.Entry phi : bottomPhis.entrySet()) { phi.getValue().initializeValueAt(merge.forwardEndIndex(forwardEnd), (ValueNode) duplicates.get(phi.getKey())); } - mergeAfter.addForwardEnd((EndNode) duplicates.get(endAfter)); + mergeAfter.addForwardEnd((AbstractEndNode) duplicates.get(endAfter)); // re-wire the duplicated ValueAnchorNode to the predecessor of the corresponding // EndNode FixedNode anchorDuplicate = (FixedNode) duplicates.get(anchor); ((FixedWithNextNode) forwardEnd.predecessor()).setNext(anchorDuplicate); // move dependencies on the ValueAnchorNode to the previous BeginNode - BeginNode prevBegin = BeginNode.prevBegin(anchorDuplicate); + AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(anchorDuplicate); anchorDuplicate.replaceAtUsages(prevBegin); // re-wire the phi duplicates to the correct input @@ -293,7 +293,7 @@ endIndex++; } GraphUtil.killCFG(merge); - for (EndNode forwardEnd : endSnapshot) { + for (AbstractEndNode forwardEnd : endSnapshot) { forwardEnd.safeDelete(); } for (PhiNode phi : phiSnapshot) { @@ -428,9 +428,9 @@ * @param stateAfterMerge The frame state that should be used for the merge. * @return The newly created end node. */ - private EndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) { + private AbstractEndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) { MergeNode newBottomMerge = graph.add(new MergeNode()); - EndNode newBottomEnd = graph.add(new EndNode()); + AbstractEndNode newBottomEnd = graph.add(new EndNode()); newBottomMerge.addForwardEnd(newBottomEnd); newBottomMerge.setStateAfter(stateAfterMerge); ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Apr 30 23:09:37 2013 +0200 @@ -37,6 +37,7 @@ public static int Threads = 4; public static String CompilerConfiguration = "basic"; + public static String GraalRuntime = "basic"; // inlining settings public static boolean Inline = true; @@ -106,6 +107,7 @@ public static int LoopMaxUnswitch = 3; public static int LoopUnswitchMaxIncrease = 50; public static int LoopUnswitchUncertaintyBoost = 5; + public static boolean UseLoopLimitChecks = true; // debugging settings public static boolean ZapStackOnMethodEntry = ____; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Tue Apr 30 23:09:37 2013 +0200 @@ -34,7 +34,7 @@ private static final DebugMetric disabledOptimisticOptsMetric = Debug.metric("DisabledOptimisticOpts"); public static enum Optimization { - RemoveNeverExecutedCode, UseTypeCheckedInlining, UseTypeCheckHints, UseExceptionProbabilityForOperations, UseExceptionProbability + RemoveNeverExecutedCode, UseTypeCheckedInlining, UseTypeCheckHints, UseExceptionProbabilityForOperations, UseExceptionProbability, UseLoopLimitChecks } private final Set enabledOpts; @@ -47,6 +47,7 @@ addOptimization(method, DeoptimizationReason.TypeCheckedInliningViolated, Optimization.UseTypeCheckedInlining); addOptimization(method, DeoptimizationReason.OptimizedTypeCheckViolated, Optimization.UseTypeCheckHints); addOptimization(method, DeoptimizationReason.NotCompiledExceptionHandler, Optimization.UseExceptionProbability); + addOptimization(method, DeoptimizationReason.LoopLimitCheck, Optimization.UseLoopLimitChecks); } private void addOptimization(ResolvedJavaMethod method, DeoptimizationReason deoptReason, Optimization optimization) { @@ -109,6 +110,10 @@ return GraalOptions.UseExceptionProbabilityForOperations && enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations); } + public boolean useLoopLimitChecks() { + return GraalOptions.UseLoopLimitChecks && enabledOpts.contains(Optimization.UseLoopLimitChecks); + } + public boolean lessOptimisticThan(OptimisticOptimizations other) { for (Optimization opt : Optimization.values()) { if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java Tue Apr 30 23:09:37 2013 +0200 @@ -70,7 +70,7 @@ if (scope.start instanceof LoopBeginNode) { assert scope.parent != null; double parentProbability = 0; - for (EndNode end : ((LoopBeginNode) scope.start).forwardEnds()) { + for (AbstractEndNode end : ((LoopBeginNode) scope.start).forwardEnds()) { parentProbability += nodeProbabilities.get(end); } return parentProbability / scope.parent.minPathProbability; @@ -170,7 +170,7 @@ int pathBeginCount = pathBeginNodes.size(); for (Node sux : controlSplit.successors()) { - double probability = controlSplit.probability((BeginNode) sux); + double probability = controlSplit.probability((AbstractBeginNode) sux); if (probability > maxProbability) { maxProbability = probability; maxSux = sux; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Tue Apr 30 23:09:37 2013 +0200 @@ -208,7 +208,7 @@ } @Override - public void afterSplit(BeginNode node) { + public void afterSplit(AbstractBeginNode node) { assert node.predecessor() != null; Node pred = node.predecessor(); if (pred instanceof Invoke) { @@ -275,7 +275,7 @@ } @Override - public void afterSplit(BeginNode node) { + public void afterSplit(AbstractBeginNode node) { // nothing to do... } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java Tue Apr 30 23:09:37 2013 +0200 @@ -36,5 +36,5 @@ void loopEnds(LoopBeginNode loopBegin, List loopEndStates); - void afterSplit(BeginNode node); + void afterSplit(AbstractBeginNode node); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Tue Apr 30 23:09:37 2013 +0200 @@ -43,7 +43,7 @@ public abstract class PostOrderNodeIterator> { private final NodeBitMap visitedEnds; - private final Deque nodeQueue; + private final Deque nodeQueue; private final IdentityHashMap nodeStates; private final FixedNode start; @@ -109,13 +109,13 @@ for (Node node : successors) { if (node != null) { nodeStates.put((FixedNode) node.predecessor(), state); - nodeQueue.addFirst((BeginNode) node); + nodeQueue.addFirst((AbstractBeginNode) node); } } } else { for (Node node : x.successors()) { if (node != null) { - nodeQueue.addFirst((BeginNode) node); + nodeQueue.addFirst((AbstractBeginNode) node); } } } @@ -124,7 +124,7 @@ private FixedNode nextQueuedNode() { int maxIterations = nodeQueue.size(); while (maxIterations-- > 0) { - BeginNode node = nodeQueue.removeFirst(); + AbstractBeginNode node = nodeQueue.removeFirst(); if (node instanceof MergeNode) { MergeNode merge = (MergeNode) node; state = nodeStates.get(merge.forwardEndAt(0)).clone(); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Tue Apr 30 23:09:37 2013 +0200 @@ -115,16 +115,16 @@ current = successor; continue; } else { - if (current.getEndNode() instanceof EndNode) { + if (current.getEndNode() instanceof AbstractEndNode) { assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode(); - EndNode end = (EndNode) current.getEndNode(); + AbstractEndNode end = (AbstractEndNode) current.getEndNode(); // add the end node and see if the merge is ready for processing assert !states.containsKey(end); states.put(end, state); MergeNode merge = end.merge(); boolean endsVisited = true; - for (EndNode forwardEnd : merge.forwardEnds()) { + for (AbstractEndNode forwardEnd : merge.forwardEnds()) { if (!states.containsKey(forwardEnd)) { endsVisited = false; break; @@ -162,7 +162,7 @@ MergeNode merge = (MergeNode) current.getBeginNode(); ArrayList mergedStates = new ArrayList<>(merge.forwardEndCount()); for (Block predecessor : current.getPredecessors()) { - EndNode end = (EndNode) predecessor.getEndNode(); + AbstractEndNode end = (AbstractEndNode) predecessor.getEndNode(); mergedStates.add(states.get(end)); } state = closure.merge(current, mergedStates); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Tue Apr 30 23:09:37 2013 +0200 @@ -41,7 +41,7 @@ protected abstract StateT merge(MergeNode merge, List states); - protected abstract StateT afterSplit(BeginNode node, StateT oldState); + protected abstract StateT afterSplit(AbstractBeginNode node, StateT oldState); protected abstract Map processLoop(LoopBeginNode loop, StateT initialState); } @@ -70,7 +70,7 @@ } public static Map apply(NodeIteratorClosure closure, FixedNode start, StateT initialState, Set boundary) { - Deque nodeQueue = new ArrayDeque<>(); + Deque nodeQueue = new ArrayDeque<>(); IdentityHashMap blockEndStates = new IdentityHashMap<>(); StateT state = initialState; @@ -107,7 +107,7 @@ assert !blockEndStates.containsKey(current); blockEndStates.put(current, state); boolean endsVisited = true; - for (EndNode forwardEnd : merge.forwardEnds()) { + for (AbstractEndNode forwardEnd : merge.forwardEnds()) { if (!blockEndStates.containsKey(forwardEnd)) { endsVisited = false; break; @@ -116,7 +116,7 @@ if (endsVisited) { ArrayList states = new ArrayList<>(merge.forwardEndCount()); for (int i = 0; i < merge.forwardEndCount(); i++) { - EndNode forwardEnd = merge.forwardEndAt(i); + AbstractEndNode forwardEnd = merge.forwardEndAt(i); assert blockEndStates.containsKey(forwardEnd); StateT other = blockEndStates.get(forwardEnd); states.add(other); @@ -134,11 +134,11 @@ continue; } else { while (successors.hasNext()) { - BeginNode successor = (BeginNode) successors.next(); + AbstractBeginNode successor = (AbstractBeginNode) successors.next(); blockEndStates.put(successor, closure.afterSplit(successor, state)); nodeQueue.add(successor); } - state = closure.afterSplit((BeginNode) firstSuccessor, state); + state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state); current = firstSuccessor; continue; } @@ -151,7 +151,7 @@ } else { current = nodeQueue.removeFirst(); state = blockEndStates.get(current); - assert !(current instanceof MergeNode) && current instanceof BeginNode; + assert !(current instanceof MergeNode) && current instanceof AbstractBeginNode; } } while (true); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java Tue Apr 30 23:09:37 2013 +0200 @@ -141,7 +141,7 @@ return result; } - private void queueMerge(EndNode end) { + private void queueMerge(AbstractEndNode end) { MergeNode merge = end.merge(); if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) { queue(merge); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -652,7 +652,7 @@ } } - if (instruction instanceof BeginNode) { + if (instruction instanceof AbstractBeginNode) { ArrayList proxies = (instruction instanceof LoopExitNode) ? new ArrayList() : null; for (ScheduledNode inBlock : blockToNodesMap.get(b)) { if (!visited.isMarked(inBlock)) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/LowTierContext.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/LowTierContext.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/LowTierContext.java Tue Apr 30 23:09:37 2013 +0200 @@ -25,17 +25,24 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; public class LowTierContext extends PhaseContext { private final TargetDescription target; + private final OptimisticOptimizations optimisticOpts; - public LowTierContext(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements, TargetDescription target) { + public LowTierContext(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements, TargetDescription target, OptimisticOptimizations optimisticOpts) { super(runtime, assumptions, replacements); this.target = target; + this.optimisticOpts = optimisticOpts; } public TargetDescription getTarget() { return target; } + + public OptimisticOptimizations getOptimisticOptimizations() { + return optimisticOpts; + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Tue Apr 30 23:09:37 2013 +0200 @@ -162,7 +162,7 @@ PhiNode phi = (PhiNode) node; assert nodeBlock.getBeginNode() == phi.merge(); for (Block pred : nodeBlock.getPredecessors()) { - schedule(phi.valueAt((EndNode) pred.getEndNode()), pred); + schedule(phi.valueAt((AbstractEndNode) pred.getEndNode()), pred); } } else { @@ -471,7 +471,7 @@ return "-"; } String prefix; - if (node instanceof BeginNode && lir == null) { + if (node instanceof AbstractBeginNode && lir == null) { prefix = "B"; } else if (node instanceof ValueNode) { ValueNode value = (ValueNode) node; diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Tue Apr 30 23:09:37 2013 +0200 @@ -165,9 +165,9 @@ printProperty(bit, "true"); } } - if (node.getClass() == BeginNode.class) { + if (node.getClass() == AbstractBeginNode.class) { printProperty("shortName", "B"); - } else if (node.getClass() == EndNode.class) { + } else if (node.getClass() == AbstractEndNode.class) { printProperty("shortName", "E"); } if (node.predecessor() != null) { diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java --- a/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java Tue Apr 30 23:09:37 2013 +0200 @@ -23,18 +23,21 @@ package com.oracle.graal.ptx; import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.code.Register.RegisterFlag.*; import java.nio.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.code.Register.RegisterCategory; +import com.oracle.graal.api.meta.*; /** * Represents the PTX architecture. */ public class PTX extends Architecture { + public static final RegisterCategory CPU = new RegisterCategory("CPU"); + public static final RegisterCategory FPU = new RegisterCategory("FPU"); + // @formatter:off /* @@ -49,23 +52,23 @@ */ // General purpose registers - public static final Register r0 = new Register(0, 0, 8, "r0", CPU, RegisterFlag.Byte); - public static final Register r1 = new Register(1, 1, 8, "r1", CPU, RegisterFlag.Byte); - public static final Register r2 = new Register(2, 2, 8, "r2", CPU, RegisterFlag.Byte); - public static final Register r3 = new Register(3, 3, 8, "r3", CPU, RegisterFlag.Byte); - public static final Register r4 = new Register(4, 4, 8, "r4", CPU, RegisterFlag.Byte); - public static final Register r5 = new Register(5, 5, 8, "r5", CPU, RegisterFlag.Byte); - public static final Register r6 = new Register(6, 6, 8, "r6", CPU, RegisterFlag.Byte); - public static final Register r7 = new Register(7, 7, 8, "r7", CPU, RegisterFlag.Byte); + public static final Register r0 = new Register(0, 0, "r0", CPU); + public static final Register r1 = new Register(1, 1, "r1", CPU); + public static final Register r2 = new Register(2, 2, "r2", CPU); + public static final Register r3 = new Register(3, 3, "r3", CPU); + public static final Register r4 = new Register(4, 4, "r4", CPU); + public static final Register r5 = new Register(5, 5, "r5", CPU); + public static final Register r6 = new Register(6, 6, "r6", CPU); + public static final Register r7 = new Register(7, 7, "r7", CPU); - public static final Register r8 = new Register(8, 8, 8, "r8", CPU, RegisterFlag.Byte); - public static final Register r9 = new Register(9, 9, 8, "r9", CPU, RegisterFlag.Byte); - public static final Register r10 = new Register(10, 10, 8, "r10", CPU, RegisterFlag.Byte); - public static final Register r11 = new Register(11, 11, 8, "r11", CPU, RegisterFlag.Byte); - public static final Register r12 = new Register(12, 12, 8, "r12", CPU, RegisterFlag.Byte); - public static final Register r13 = new Register(13, 13, 8, "r13", CPU, RegisterFlag.Byte); - public static final Register r14 = new Register(14, 14, 8, "r14", CPU, RegisterFlag.Byte); - public static final Register r15 = new Register(15, 15, 8, "r15", CPU, RegisterFlag.Byte); + public static final Register r8 = new Register(8, 8, "r8", CPU); + public static final Register r9 = new Register(9, 9, "r9", CPU); + public static final Register r10 = new Register(10, 10, "r10", CPU); + public static final Register r11 = new Register(11, 11, "r11", CPU); + public static final Register r12 = new Register(12, 12, "r12", CPU); + public static final Register r13 = new Register(13, 13, "r13", CPU); + public static final Register r14 = new Register(14, 14, "r14", CPU); + public static final Register r15 = new Register(15, 15, "r15", CPU); public static final Register[] gprRegisters = { r0, r1, r2, r3, r4, r5, r6, r7, @@ -73,23 +76,23 @@ }; // Floating point registers - public static final Register f0 = new Register(16, 0, 8, "f0", FPU); - public static final Register f1 = new Register(17, 1, 8, "f1", FPU); - public static final Register f2 = new Register(18, 2, 8, "f2", FPU); - public static final Register f3 = new Register(19, 3, 8, "f3", FPU); - public static final Register f4 = new Register(20, 4, 8, "f4", FPU); - public static final Register f5 = new Register(21, 5, 8, "f5", FPU); - public static final Register f6 = new Register(22, 6, 8, "f6", FPU); - public static final Register f7 = new Register(23, 7, 8, "f7", FPU); + public static final Register f0 = new Register(16, 0, "f0", FPU); + public static final Register f1 = new Register(17, 1, "f1", FPU); + public static final Register f2 = new Register(18, 2, "f2", FPU); + public static final Register f3 = new Register(19, 3, "f3", FPU); + public static final Register f4 = new Register(20, 4, "f4", FPU); + public static final Register f5 = new Register(21, 5, "f5", FPU); + public static final Register f6 = new Register(22, 6, "f6", FPU); + public static final Register f7 = new Register(23, 7, "f7", FPU); - public static final Register f8 = new Register(24, 8, 8, "f8", FPU); - public static final Register f9 = new Register(25, 9, 8, "f9", FPU); - public static final Register f10 = new Register(26, 10, 8, "f10", FPU); - public static final Register f11 = new Register(27, 11, 8, "f11", FPU); - public static final Register f12 = new Register(28, 12, 8, "f12", FPU); - public static final Register f13 = new Register(29, 13, 8, "f13", FPU); - public static final Register f14 = new Register(30, 14, 8, "f14", FPU); - public static final Register f15 = new Register(31, 15, 8, "f15", FPU); + public static final Register f8 = new Register(24, 8, "f8", FPU); + public static final Register f9 = new Register(25, 9, "f9", FPU); + public static final Register f10 = new Register(26, 10, "f10", FPU); + public static final Register f11 = new Register(27, 11, "f11", FPU); + public static final Register f12 = new Register(28, 12, "f12", FPU); + public static final Register f13 = new Register(29, 13, "f13", FPU); + public static final Register f14 = new Register(30, 14, "f14", FPU); + public static final Register f15 = new Register(31, 15, "f15", FPU); public static final Register[] fpuRegisters = { f0, f1, f2, f3, f4, f5, f6, f7, @@ -116,4 +119,44 @@ 8); } // @formatter:on + + @Override + public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { + if (!(platformKind instanceof Kind)) { + return false; + } + + Kind kind = (Kind) platformKind; + if (category == CPU) { + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + case Long: + case Object: + return true; + } + } else if (category == FPU) { + switch (kind) { + case Float: + case Double: + return true; + } + } + + return false; + } + + @Override + public PlatformKind getLargestStorableKind(RegisterCategory category) { + if (category == CPU) { + return Kind.Long; + } else if (category == FPU) { + return Kind.Double; + } else { + return Kind.Illegal; + } + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetFrameStateCleanupPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetFrameStateCleanupPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetFrameStateCleanupPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -93,7 +93,7 @@ } @Override - protected CleanupState afterSplit(BeginNode node, CleanupState oldState) { + protected CleanupState afterSplit(AbstractBeginNode node, CleanupState oldState) { return new CleanupState(oldState.containsFrameState); } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java --- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Tue Apr 30 23:09:37 2013 +0200 @@ -27,6 +27,8 @@ import java.nio.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Register.RegisterCategory; +import com.oracle.graal.api.meta.*; /** * Represents the SPARC architecture. @@ -39,4 +41,16 @@ super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, null, LOAD_STORE | STORE_STORE, 1, 0, 8); // SPARC: Fix architecture parameters. } + + @Override + public boolean canStoreValue(RegisterCategory category, PlatformKind kind) { + // TODO Auto-generated method stub + return false; + } + + @Override + public PlatformKind getLargestStorableKind(RegisterCategory category) { + // TODO Auto-generated method stub + return null; + } } diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -139,8 +139,8 @@ IdentityHashMap path = new IdentityHashMap<>(); flood.add(graph.start()); for (Node current : flood) { - if (current instanceof EndNode) { - EndNode end = (EndNode) current; + if (current instanceof AbstractEndNode) { + AbstractEndNode end = (AbstractEndNode) current; flood.add(end.merge()); if (!path.containsKey(end.merge())) { path.put(end.merge(), end); diff -r a14fef4fca7d -r 861a9e0aba38 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Tue Apr 30 00:53:33 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Tue Apr 30 23:09:37 2013 +0200 @@ -272,7 +272,7 @@ graph.addBeforeFixed(invoke.asNode(), read); // The read must not float outside its block otherwise it may float above an explicit zero // check on its base address - read.dependencies().add(BeginNode.prevBegin(invoke.asNode())); + read.dependencies().add(AbstractBeginNode.prevBegin(invoke.asNode())); return read; } diff -r a14fef4fca7d -r 861a9e0aba38 make/bsd/makefiles/buildtree.make --- a/make/bsd/makefiles/buildtree.make Tue Apr 30 00:53:33 2013 +0200 +++ b/make/bsd/makefiles/buildtree.make Tue Apr 30 23:09:37 2013 +0200 @@ -243,7 +243,9 @@ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ - echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,altsrc,gpu/ptx) \\"; \ + echo "$(call gamma-path,commonsrc,gpu/ptx)"; \ echo; \ echo "Src_Dirs_I = \\"; \ echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \ @@ -259,7 +261,9 @@ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ - echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,altsrc,gpu) \\"; \ + echo "$(call gamma-path,commonsrc,gpu)"; \ [ -n "$(CFLAGS_BROWSE)" ] && \ echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ [ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \ diff -r a14fef4fca7d -r 861a9e0aba38 make/bsd/makefiles/launcher.make --- a/make/bsd/makefiles/launcher.make Tue Apr 30 00:53:33 2013 +0200 +++ b/make/bsd/makefiles/launcher.make Tue Apr 30 23:09:37 2013 +0200 @@ -67,7 +67,7 @@ # framework libraries. ifeq ($(OS_VENDOR),Darwin) - LFLAGS_LAUNCHER += -framework CoreFoundation + LFLAGS_LAUNCHER += -framework CoreFoundation -framework ApplicationServices endif LIBS_LAUNCHER += -l$(JVM) $(LIBS) diff -r a14fef4fca7d -r 861a9e0aba38 make/bsd/makefiles/vm.make --- a/make/bsd/makefiles/vm.make Tue Apr 30 00:53:33 2013 +0200 +++ b/make/bsd/makefiles/vm.make Tue Apr 30 23:09:37 2013 +0200 @@ -128,6 +128,10 @@ LIBS += -lm -pthread +ifeq ($(OS_VENDOR),Darwin) + LIBS += -framework ApplicationServices -framework IOKit +endif + # By default, link the *.o into the library, not the executable. LINK_INTO$(LINK_INTO) = LIBJVM @@ -157,6 +161,7 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm +SOURCE_PATHS+=$(HS_COMMON_SRC)/gpu/ptx ifndef JAVASE_EMBEDDED SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ @@ -179,7 +184,9 @@ SHARK_PATHS := $(GAMMADIR)/src/share/vm/shark GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/graal) +GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/ptx) GRAAL_PATHS += $(HS_COMMON_SRC)/share/vm/graal +GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/ptx # Include dirs per type. Src_Dirs/CORE := $(CORE_PATHS) diff -r a14fef4fca7d -r 861a9e0aba38 make/linux/makefiles/buildtree.make --- a/make/linux/makefiles/buildtree.make Tue Apr 30 00:53:33 2013 +0200 +++ b/make/linux/makefiles/buildtree.make Tue Apr 30 23:09:37 2013 +0200 @@ -238,7 +238,9 @@ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ - echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,altsrc,gpu/ptx) \\"; \ + echo "$(call gamma-path,commonsrc,gpu/ptx)"; \ echo; \ echo "Src_Dirs_I = \\"; \ echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \ @@ -253,8 +255,9 @@ echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ - echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ - echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,altsrc,gpu) \\"; \ + echo "$(call gamma-path,commonsrc,gpu)"; \ [ -n "$(CFLAGS_BROWSE)" ] && \ echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ [ -n "$(ENABLE_FULL_DEBUG_SYMBOLS)" ] && \ diff -r a14fef4fca7d -r 861a9e0aba38 make/linux/makefiles/vm.make --- a/make/linux/makefiles/vm.make Tue Apr 30 00:53:33 2013 +0200 +++ b/make/linux/makefiles/vm.make Tue Apr 30 23:09:37 2013 +0200 @@ -157,6 +157,7 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm +SOURCE_PATHS+=$(HS_COMMON_SRC)/gpu/ptx ifndef JAVASE_EMBEDDED ifneq (${ARCH},arm) @@ -181,7 +182,9 @@ SHARK_PATHS := $(GAMMADIR)/src/share/vm/shark GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/graal) +GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/ptx) GRAAL_PATHS += $(HS_COMMON_SRC)/share/vm/graal +GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/ptx # Include dirs per type. Src_Dirs/CORE := $(CORE_PATHS) diff -r a14fef4fca7d -r 861a9e0aba38 mx/projects --- a/mx/projects Tue Apr 30 00:53:33 2013 +0200 +++ b/mx/projects Tue Apr 30 23:09:37 2013 +0200 @@ -295,7 +295,7 @@ # graal.compiler.ptx project@com.oracle.graal.compiler.ptx@subDir=graal project@com.oracle.graal.compiler.ptx@sourceDirs=src -project@com.oracle.graal.compiler.ptx@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.ptx +project@com.oracle.graal.compiler.ptx@dependencies=com.oracle.graal.lir.ptx,com.oracle.graal.hotspot project@com.oracle.graal.compiler.ptx@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.ptx@javaCompliance=1.7 diff -r a14fef4fca7d -r 861a9e0aba38 src/gpu/ptx/gpu_ptx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gpu/ptx/gpu_ptx.cpp Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,168 @@ +/* + * 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. + * + */ + + +#include "runtime/gpu.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + +void * gpu::Ptx::_device_context; + +gpu::Ptx::cuda_cu_init_func_t gpu::Ptx::_cuda_cu_init; +gpu::Ptx::cuda_cu_ctx_create_func_t gpu::Ptx::_cuda_cu_ctx_create; +gpu::Ptx::cuda_cu_ctx_detach_func_t gpu::Ptx::_cuda_cu_ctx_detach; +gpu::Ptx::cuda_cu_ctx_synchronize_func_t gpu::Ptx::_cuda_cu_ctx_synchronize; +gpu::Ptx::cuda_cu_device_get_count_func_t gpu::Ptx::_cuda_cu_device_get_count; +gpu::Ptx::cuda_cu_device_get_name_func_t gpu::Ptx::_cuda_cu_device_get_name; +gpu::Ptx::cuda_cu_device_get_func_t gpu::Ptx::_cuda_cu_device_get; +gpu::Ptx::cuda_cu_device_compute_capability_func_t gpu::Ptx::_cuda_cu_device_compute_capability; +gpu::Ptx::cuda_cu_launch_kernel_func_t gpu::Ptx::_cuda_cu_launch_kernel; +gpu::Ptx::cuda_cu_module_get_function_func_t gpu::Ptx::_cuda_cu_module_get_function; +gpu::Ptx::cuda_cu_module_load_data_ex_func_t gpu::Ptx::_cuda_cu_module_load_data_ex; + +void gpu::probe_linkage() { +#ifdef __APPLE__ + set_gpu_linkage(gpu::Ptx::probe_linkage_apple()); +#else + set_gpu_linkage(false); +#endif +} + +void gpu::initialize_gpu() { + if (gpu::has_gpu_linkage()) { + set_initialized(gpu::Ptx::initialize_gpu()); + } +} + +void gpu::generate_kernel(unsigned char *code, int code_len, const char *name) { + if (gpu::has_gpu_linkage()) { + gpu::Ptx::generate_kernel(code, code_len, name); + } +} + +#define __CUDA_API_VERSION 5000 + +bool gpu::Ptx::initialize_gpu() { + int status = _cuda_cu_init(0, __CUDA_API_VERSION); + if (TraceWarpLoading) { + tty->print_cr("gpu_ptx::_cuda_cu_init: %d", status); + } + + int device_count = 0; + status = _cuda_cu_device_get_count(&device_count); + if (TraceWarpLoading) { + tty->print_cr("gpu_ptx::_cuda_cu_device_get_count(%d): %d", device_count, status); + } + + int device_id = 0, cu_device = 0; + status = _cuda_cu_device_get(&cu_device, device_id); + if (TraceWarpLoading) { + tty->print_cr("gpu_ptx::_cuda_cu_device_get(%d): %d", cu_device, status); + } + + int major, minor; + status = _cuda_cu_device_compute_capability(&major, &minor, cu_device); + if (TraceWarpLoading) { + tty->print_cr("gpu_ptx::_cuda_cu_device_compute_capability(major %d, minor %d): %d", + major, minor, status); + } + + char device_name[256]; + status = _cuda_cu_device_get_name(device_name, 256, cu_device); + if (TraceWarpLoading) { + tty->print_cr("gpu_ptx::_cuda_cu_device_get_name(%s): %d", device_name, status); + } + + status = _cuda_cu_ctx_create(&_device_context, 0, cu_device); + if (TraceWarpLoading) { + tty->print_cr("gpu_ptx::_cuda_cu_ctx_create(%x): %d", _device_context, status); + } + + return status == 0; // CUDA_SUCCESS +} + +void gpu::Ptx::generate_kernel(unsigned char *code, int code_len, const char *name) { + + void *cu_module; + const unsigned int jit_num_options = 3; + int *jit_options = new int[jit_num_options]; + void **jit_option_values = new void *[jit_num_options]; + + jit_options[0] = 4; // CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES + int jit_log_buffer_size = 1024; + jit_option_values[0] = (void *)(size_t)jit_log_buffer_size; + + jit_options[1] = 3; // CU_JIT_INFO_LOG_BUFFER + char *jit_log_buffer = new char[jit_log_buffer_size]; + jit_option_values[1] = jit_log_buffer; + + jit_options[2] = 0; // CU_JIT_MAX_REGISTERS + int jit_register_count = 32; + jit_option_values[2] = (void *)(size_t)jit_register_count; + + int status = _cuda_cu_module_load_data_ex(&cu_module, code, + jit_num_options, jit_options, (void **)jit_option_values); + if (TraceWarpLoading) { + tty->print_cr("gpu_ptx::_cuda_cu_module_load_data_ex(%x): %d", cu_module, status); + tty->print_cr("gpu_ptx::jit_log_buffer\n%s", jit_log_buffer); + } + + void *cu_function; + + status = _cuda_cu_module_get_function(&cu_function, cu_module, name); + if (TraceWarpLoading) { + tty->print_cr("gpu_ptx::_cuda_cu_module_get_function(%s):%x %d", name, cu_function, status); + } +} + + +#ifdef __APPLE__ +bool gpu::Ptx::probe_linkage_apple() { + void *handle = dlopen("/usr/local/cuda/lib/libcuda.dylib", RTLD_LAZY); + if (handle != NULL) { + _cuda_cu_init = + CAST_TO_FN_PTR(cuda_cu_init_func_t, dlsym(handle, "cuInit")); + _cuda_cu_ctx_create = + CAST_TO_FN_PTR(cuda_cu_ctx_create_func_t, dlsym(handle, "cuCtxCreate")); + _cuda_cu_ctx_detach = + CAST_TO_FN_PTR(cuda_cu_ctx_detach_func_t, dlsym(handle, "cuCtxDetach")); + _cuda_cu_ctx_synchronize = + CAST_TO_FN_PTR(cuda_cu_ctx_synchronize_func_t, dlsym(handle, "cuCtxSynchronize")); + _cuda_cu_device_get_count = + CAST_TO_FN_PTR(cuda_cu_device_get_count_func_t, dlsym(handle, "cuDeviceGetCount")); + _cuda_cu_device_get_name = + CAST_TO_FN_PTR(cuda_cu_device_get_name_func_t, dlsym(handle, "cuDeviceGetName")); + _cuda_cu_device_get = + CAST_TO_FN_PTR(cuda_cu_device_get_func_t, dlsym(handle, "cuDeviceGet")); + _cuda_cu_device_compute_capability = + CAST_TO_FN_PTR(cuda_cu_device_compute_capability_func_t, dlsym(handle, "cuDeviceComputeCapability")); + _cuda_cu_module_get_function = + CAST_TO_FN_PTR(cuda_cu_module_get_function_func_t, dlsym(handle, "cuModuleGetFunction")); + _cuda_cu_module_load_data_ex = + CAST_TO_FN_PTR(cuda_cu_module_load_data_ex_func_t, dlsym(handle, "cuModuleLoadDataEx")); + return true; + } + return false; +} +#endif \ No newline at end of file diff -r a14fef4fca7d -r 861a9e0aba38 src/gpu/ptx/gpu_ptx.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gpu/ptx/gpu_ptx.hpp Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,68 @@ +/* + * 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. + * + */ + +#ifndef GPU_PTX_HPP +#define GPU_PTX_HPP + +class Ptx { + friend class gpu; + + protected: + static void probe_linkage(); +#ifdef __APPLE__ + static bool probe_linkage_apple(); +#endif + static bool initialize_gpu(); + static void generate_kernel(unsigned char *code, int code_len, const char *name); + +private: + typedef int (*cuda_cu_init_func_t)(unsigned int, int); + typedef int (*cuda_cu_ctx_create_func_t)(void *, int, int); + typedef int (*cuda_cu_ctx_detach_func_t)(int *); + typedef int (*cuda_cu_ctx_synchronize_func_t)(int *); + typedef int (*cuda_cu_device_get_count_func_t)(int *); + typedef int (*cuda_cu_device_get_name_func_t)(char *, int, int); + typedef int (*cuda_cu_device_get_func_t)(int *, int); + typedef int (*cuda_cu_device_compute_capability_func_t)(int *, int *, int); + typedef int (*cuda_cu_launch_kernel_func_t)(int *, int *, int); + typedef int (*cuda_cu_module_get_function_func_t)(void *, void *, const char *); + typedef int (*cuda_cu_module_load_data_ex_func_t)(void *, void *, unsigned int, int *, void **); + + static cuda_cu_init_func_t _cuda_cu_init; + static cuda_cu_ctx_create_func_t _cuda_cu_ctx_create; + static cuda_cu_ctx_detach_func_t _cuda_cu_ctx_detach; + static cuda_cu_ctx_synchronize_func_t _cuda_cu_ctx_synchronize; + static cuda_cu_device_get_count_func_t _cuda_cu_device_get_count; + static cuda_cu_device_get_name_func_t _cuda_cu_device_get_name; + static cuda_cu_device_get_func_t _cuda_cu_device_get; + static cuda_cu_device_compute_capability_func_t _cuda_cu_device_compute_capability; + static cuda_cu_launch_kernel_func_t _cuda_cu_launch_kernel; + static cuda_cu_module_get_function_func_t _cuda_cu_module_get_function; + static cuda_cu_module_load_data_ex_func_t _cuda_cu_module_load_data_ex; + +protected: + static void * _device_context; +}; + +#endif // GPU_PTX_HPP diff -r a14fef4fca7d -r 861a9e0aba38 src/os/bsd/vm/gpu_bsd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/gpu_bsd.cpp Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,99 @@ +/* + * 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. + * + */ + +#include "runtime/gpu.hpp" +#include "utilities/ostream.hpp" + +#ifdef __APPLE__ +#include +#include +#endif + +void gpu::probe_gpu() { +#ifdef __APPLE__ + set_available(gpu::Bsd::probe_gpu_apple()); + if (TraceWarpLoading) { + tty->print_cr("gpu_bsd::probe_gpu(APPLE): %d", gpu::is_available()); + } +#else + if (TraceWarpLoading) { + tty->print_cr("gpu_bsd::probe_gpu(not APPLE)"); + } + set_available(false); +#endif +} + +#ifdef __APPLE__ +/* + * This is rudimentary at best, but until we decide on a CUDA Compiler Compatibility + * level, this will have to suffice. + */ +bool gpu::Bsd::probe_gpu_apple() { + CGError err = CGDisplayNoErr; + CGDisplayCount displayCount = 0; + CFDataRef vendorID, deviceID, model; + CGDirectDisplayID *displays; + IOOptionBits options = kIORegistryIterateRecursively | kIORegistryIterateParents; + io_registry_entry_t displayPort; + + err = CGGetActiveDisplayList(0, NULL, &displayCount); + displays = (CGDirectDisplayID *)calloc((size_t)displayCount, sizeof(CGDirectDisplayID)); + err = CGGetActiveDisplayList(displayCount, displays, &displayCount); + + for (CGDisplayCount i = 0; i < displayCount; i++) { + displayPort = CGDisplayIOServicePort(displays[i]); + vendorID = (CFDataRef)IORegistryEntrySearchCFProperty(displayPort, kIOServicePlane, CFSTR("vendor-id"), + kCFAllocatorDefault, options); + deviceID = (CFDataRef)IORegistryEntrySearchCFProperty(displayPort, kIOServicePlane, CFSTR("device-id"), + kCFAllocatorDefault, options); + model = (CFDataRef)IORegistryEntrySearchCFProperty(displayPort, kIOServicePlane, CFSTR("model"), + kCFAllocatorDefault, options); + if (TraceWarpLoading) { + tty->print_cr("vendor: 0x%08X", *((UInt32*)CFDataGetBytePtr(vendorID))); + tty->print_cr("device: 0x%08X", *((UInt32*)CFDataGetBytePtr(deviceID))); + tty->print_cr("model: %s", CFDataGetBytePtr(model)); + } + UInt32 vendor = *((UInt32*)CFDataGetBytePtr(vendorID)); + if (vendor != 0x10DE) { + return false; + } else { + /* + * see https://developer.nvidia.com/cuda-gpus + * see http://en.wikipedia.org/wiki/CUDA#Supported_GPUs + * see http://www.pcidatabase.com/reports.php?type=csv + * + * Only supporting GK104, GK106, GK107 and GK110 GPUs for now, + * which is CUDA Computer Capability 3.0 and greater. + */ + switch (*((UInt32*)CFDataGetBytePtr(deviceID))) { + case 0x11C0: + return true; // NVIDIA GeForce GTX 660 + default: + return false; + } + } + } + return false; +} +#endif \ No newline at end of file diff -r a14fef4fca7d -r 861a9e0aba38 src/os/bsd/vm/gpu_bsd.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/gpu_bsd.hpp Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,39 @@ +/* + * 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. + * + */ + +#ifndef OS_BSD_VM_GPU_BSD_HPP +#define OS_BSD_VM_GPU_BSD_HPP + + +class Bsd { + friend class gpu; + + protected: + static bool probe_gpu(); +#ifdef __APPLE__ + static bool probe_gpu_apple(); +#endif +}; + +#endif // OS_BSD_VM_GPU_BSD_HPP diff -r a14fef4fca7d -r 861a9e0aba38 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Tue Apr 30 00:53:33 2013 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Tue Apr 30 23:09:37 2013 +0200 @@ -28,6 +28,7 @@ #include "graal/graalJavaAccess.hpp" #include "graal/graalVMToCompiler.hpp" #include "graal/graalCompilerToVM.hpp" +#include "graal/graalCompilerToGPU.hpp" #include "graal/graalEnv.hpp" #include "graal/graalRuntime.hpp" #include "runtime/arguments.hpp" @@ -65,6 +66,13 @@ vm_abort(false); } env->RegisterNatives(klass, CompilerToVM_methods, CompilerToVM_methods_count()); + + klass = env->FindClass("com/oracle/graal/hotspot/bridge/CompilerToGPUImpl"); + if (klass == NULL) { + tty->print_cr("graal CompilerToGPUImpl class not found"); + vm_abort(false); + } + env->RegisterNatives(klass, CompilerToGPU_methods, CompilerToGPU_methods_count()); ResourceMark rm; HandleMark hm; diff -r a14fef4fca7d -r 861a9e0aba38 src/share/vm/graal/graalCompilerToGPU.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalCompilerToGPU.cpp Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,124 @@ +/* + * 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. + */ + +#include "precompiled.hpp" + +#include "graal/graalCompiler.hpp" +#include "graal/graalEnv.hpp" +#include "runtime/gpu.hpp" + + +// Entry to native method implementation that transitions current thread to '_thread_in_vm'. +#define C2V_VMENTRY(result_type, name, signature) \ + JNIEXPORT result_type JNICALL c2v_ ## name signature { \ + TRACE_graal_3("CompilerToGPU::" #name); \ + GRAAL_VM_ENTRY_MARK; \ + +// Entry to native method implementation that calls a JNI function +// and hence cannot transition current thread to '_thread_in_vm'. +#define C2V_ENTRY(result_type, name, signature) \ + JNIEXPORT result_type JNICALL c2v_ ## name signature { \ + TRACE_graal_3("CompilerToGPU::" #name); \ + +#define C2V_END } + + +C2V_VMENTRY(jlong, generateKernel, (JNIEnv *env, jobject, jbyteArray code, jstring name)) + if (gpu::is_available() == false || gpu::has_gpu_linkage() == false && gpu::is_initialized()) { + tty->print_cr("generateKernel - not available / no linkage / not initialized"); + return 0; + } + jboolean is_copy; + jbyte *bytes = env->GetByteArrayElements(code, &is_copy); + jint len = env->GetArrayLength(code); + const char *namestr = env->GetStringUTFChars(name, &is_copy); + gpu::generate_kernel((unsigned char *)bytes, len, namestr); + env->ReleaseByteArrayElements(code, bytes, 0); + env->ReleaseStringUTFChars(name, namestr); + + return 42; +C2V_END + +C2V_VMENTRY(jboolean, deviceInit, (JNIEnv *env, jobject)) + if (gpu::is_available() == false || gpu::has_gpu_linkage() == false) { + tty->print_cr("deviceInit - not available / no linkage"); + return false; + } + if (gpu::is_initialized()) { + tty->print_cr("deviceInit - already initialized"); + return true; + } + gpu::initialize_gpu(); + return gpu::is_initialized(); +C2V_END + +C2V_VMENTRY(jboolean, deviceDetach, (JNIEnv *env, jobject)) +return true; +C2V_END + + +#define CC (char*) /*cast a literal from (const char*)*/ +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) + +#define RESOLVED_TYPE "Lcom/oracle/graal/api/meta/ResolvedJavaType;" +#define TYPE "Lcom/oracle/graal/api/meta/JavaType;" +#define METHOD "Lcom/oracle/graal/api/meta/JavaMethod;" +#define FIELD "Lcom/oracle/graal/api/meta/JavaField;" +#define SIGNATURE "Lcom/oracle/graal/api/meta/Signature;" +#define CONSTANT_POOL "Lcom/oracle/graal/api/meta/ConstantPool;" +#define CONSTANT "Lcom/oracle/graal/api/meta/Constant;" +#define KIND "Lcom/oracle/graal/api/meta/Kind;" +#define LOCAL "Lcom/oracle/graal/api/meta/Local;" +#define RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;" +#define EXCEPTION_HANDLERS "[Lcom/oracle/graal/api/meta/ExceptionHandler;" +#define REFLECT_METHOD "Ljava/lang/reflect/Method;" +#define REFLECT_CONSTRUCTOR "Ljava/lang/reflect/Constructor;" +#define REFLECT_FIELD "Ljava/lang/reflect/Field;" +#define STRING "Ljava/lang/String;" +#define OBJECT "Ljava/lang/Object;" +#define CLASS "Ljava/lang/Class;" +#define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;" +#define HS_RESOLVED_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;" +#define HS_RESOLVED_JAVA_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaType;" +#define HS_RESOLVED_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;" +#define HS_RESOLVED_FIELD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaField;" +#define HS_COMP_RESULT "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;" +#define HS_CONFIG "Lcom/oracle/graal/hotspot/HotSpotVMConfig;" +#define HS_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotMethod;" +#define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;" +#define METHOD_DATA "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;" +#define METASPACE_METHOD "J" +#define METASPACE_METHOD_DATA "J" +#define NMETHOD "J" +#define GPUSPACE_METHOD "J" + +JNINativeMethod CompilerToGPU_methods[] = { + {CC"generateKernel", CC"([B" STRING ")"GPUSPACE_METHOD, FN_PTR(generateKernel)}, + {CC"deviceInit", CC"()Z", FN_PTR(deviceInit)}, + {CC"deviceDetach", CC"()Z", FN_PTR(deviceDetach)}, +}; + +int CompilerToGPU_methods_count() { + return sizeof(CompilerToGPU_methods) / sizeof(JNINativeMethod); +} + diff -r a14fef4fca7d -r 861a9e0aba38 src/share/vm/graal/graalCompilerToGPU.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalCompilerToGPU.hpp Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef SHARE_VM_GRAAL_GRAAL_COMPILER_TO_GPU_HPP +#define SHARE_VM_GRAAL_GRAAL_COMPILER_TO_GPU_HPP + +#include "prims/jni.h" + +extern JNINativeMethod CompilerToGPU_methods[]; +int CompilerToGPU_methods_count(); + + +#endif // SHARE_VM_GRAAL_GRAAL_COMPILER_TO_GPU_HPP diff -r a14fef4fca7d -r 861a9e0aba38 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Apr 30 00:53:33 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Apr 30 23:09:37 2013 +0200 @@ -802,6 +802,7 @@ set_int("deoptReasonJsrMismatch", Deoptimization::Reason_jsr_mismatch); set_int("deoptReasonDiv0Check", Deoptimization::Reason_div0_check); set_int("deoptReasonConstraint", Deoptimization::Reason_constraint); + set_int("deoptReasonLoopLimitCheck", Deoptimization::Reason_loop_limit_check); set_int("deoptActionNone", Deoptimization::Action_none); set_int("deoptActionMaybeRecompile", Deoptimization::Action_maybe_recompile); diff -r a14fef4fca7d -r 861a9e0aba38 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Tue Apr 30 00:53:33 2013 +0200 +++ b/src/share/vm/runtime/globals.hpp Tue Apr 30 23:09:37 2013 +0200 @@ -3691,6 +3691,9 @@ product(bool , AllowNonVirtualCalls, false, \ "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ \ + develop(bool, TraceWarpLoading, false, \ + "trace external GPU warp loading") \ + \ experimental(uintx, ArrayAllocatorMallocLimit, \ SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \ "Allocation less than this value will be allocated " \ diff -r a14fef4fca7d -r 861a9e0aba38 src/share/vm/runtime/gpu.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/runtime/gpu.cpp Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,40 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "runtime/gpu.hpp" +#include "ptx/gpu_ptx.hpp" + +bool gpu::_available = false; // does the hardware exist? +bool gpu::_gpu_linkage = false; // is the driver library to access the GPU installed +bool gpu::_initialized = false; // is the GPU defvice initialized + +void gpu::init() { +#ifdef TARGET_OS_FAMILY_bsd + gpu::probe_gpu(); +#endif + // need multi-gpu TARGET ifdef + gpu::probe_linkage(); +} + diff -r a14fef4fca7d -r 861a9e0aba38 src/share/vm/runtime/gpu.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/runtime/gpu.hpp Tue Apr 30 23:09:37 2013 +0200 @@ -0,0 +1,85 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_RUNTIME_GPU_HPP +#define SHARE_VM_RUNTIME_GPU_HPP + +#include "runtime/atomic.hpp" + +// gpu defines the interface to the graphics processor; this includes traditional +// GPU services such as graphics kernel load and execute. + + +class gpu: AllStatic { +public: + static void init(void); + + static void probe_gpu(); + + static void probe_linkage(); + + static void initialize_gpu(); + + static void generate_kernel(unsigned char *code, int code_len, const char *name); + + static void set_available(bool value) { + _available = value; + } + + static bool is_available() { return _available; } + + static void set_initialized(bool value) { + _initialized = value; + } + + static bool is_initialized() { return _initialized; } + + static void set_gpu_linkage(bool value) { + _gpu_linkage = value; + } + + static bool has_gpu_linkage() { return _gpu_linkage; } + +protected: + static bool _available; + static bool _gpu_linkage; + static bool _initialized; + + // Platform dependent stuff +#ifdef TARGET_OS_FAMILY_linux +#endif +#ifdef TARGET_OS_FAMILY_solaris +#endif +#ifdef TARGET_OS_FAMILY_windows +#endif +#ifdef TARGET_OS_FAMILY_bsd +# include "gpu_bsd.hpp" +#endif + +# include "ptx/gpu_ptx.hpp" + +}; + + +#endif // SHARE_VM_RUNTIME_GPU_HPP diff -r a14fef4fca7d -r 861a9e0aba38 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Tue Apr 30 00:53:33 2013 +0200 +++ b/src/share/vm/runtime/thread.cpp Tue Apr 30 23:09:37 2013 +0200 @@ -54,6 +54,7 @@ #include "runtime/deoptimization.hpp" #include "runtime/fprofiler.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/gpu.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" @@ -3307,6 +3308,9 @@ // Initialize the os module before using TLS os::init(); + // probe for warp capability + gpu::init(); + // Initialize system properties. Arguments::init_system_properties();