# HG changeset patch # User Stefan Anzinger # Date 1429196946 -7200 # Node ID 68ff637e95b1059f52c0c7c9c721ea8a6a4bf120 # Parent ec36daea3cf0fdcbcc886ecf469acae139dc86bf# Parent e6b59c7b39919b56b74dfe97e85e1a6b98b90243 Merge diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Thu Apr 16 17:09:06 2015 +0200 @@ -25,28 +25,29 @@ import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; import com.oracle.graal.api.meta.*; -public interface ReferenceMap extends Cloneable { +public abstract class ReferenceMap implements Cloneable { - void setRegister(int idx, LIRKind kind); + public abstract void setRegister(int idx, LIRKind kind); - void clearRegister(int idx, LIRKind kind); + public abstract void clearRegister(int idx, LIRKind kind); - void setStackSlot(int offset, LIRKind kind); + public abstract void setStackSlot(int offset, LIRKind kind); - void clearStackSlot(int offset, LIRKind kind); + public abstract void clearStackSlot(int offset, LIRKind kind); - boolean hasRegisterRefMap(); + public abstract boolean hasRegisterRefMap(); - boolean hasFrameRefMap(); + public abstract boolean hasFrameRefMap(); - void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg); + public abstract void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg); - void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg); + public abstract void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg); - ReferenceMap clone(); + @Override + public abstract ReferenceMap clone(); /** * Updates this map with all references marked in {@code other}. */ - void updateUnion(ReferenceMap other); + public abstract void updateUnion(ReferenceMap other); } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Thu Apr 16 17:09:06 2015 +0200 @@ -398,6 +398,22 @@ } } + public static void log(String format, int arg) { + log(DEFAULT_LOG_LEVEL, format, arg); + } + + /** + * Prints a message to the current debug scope's logging stream if logging is enabled. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + */ + public static void log(int logLevel, String format, int arg) { + if (ENABLED) { + DebugScope.getInstance().log(logLevel, format, arg); + } + } + public static void log(String format, Object arg1, Object arg2) { log(DEFAULT_LOG_LEVEL, format, arg1, arg2); } @@ -411,6 +427,45 @@ } } + public static void log(String format, int arg1, Object arg2) { + log(DEFAULT_LOG_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public static void log(int logLevel, String format, int arg1, Object arg2) { + if (ENABLED) { + DebugScope.getInstance().log(logLevel, format, arg1, arg2); + } + } + + public static void log(String format, Object arg1, int arg2) { + log(DEFAULT_LOG_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public static void log(int logLevel, String format, Object arg1, int arg2) { + if (ENABLED) { + DebugScope.getInstance().log(logLevel, format, arg1, arg2); + } + } + + public static void log(String format, int arg1, int arg2) { + log(DEFAULT_LOG_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public static void log(int logLevel, String format, int arg1, int arg2) { + if (ENABLED) { + DebugScope.getInstance().log(logLevel, format, arg1, arg2); + } + } + public static void log(String format, Object arg1, Object arg2, Object arg3) { log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3); } @@ -424,6 +479,19 @@ } } + public static void log(String format, int arg1, int arg2, int arg3) { + log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #log(int, String, Object) + */ + public static void log(int logLevel, String format, int arg1, int arg2, int arg3) { + if (ENABLED) { + DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3); + } + } + public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) { log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4); } @@ -695,6 +763,67 @@ return null; } + public static Indent logAndIndent(String format, int arg) { + return logAndIndent(DEFAULT_LOG_LEVEL, format, arg); + } + + /** + * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public static Indent logAndIndent(int logLevel, String format, int arg) { + if (ENABLED) { + return logvAndIndent(logLevel, format, arg); + } + return null; + } + + public static Indent logAndIndent(String format, int arg1, Object arg2) { + return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public static Indent logAndIndent(int logLevel, String format, int arg1, Object arg2) { + if (ENABLED) { + return logvAndIndent(logLevel, format, arg1, arg2); + } + return null; + } + + public static Indent logAndIndent(String format, Object arg1, int arg2) { + return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public static Indent logAndIndent(int logLevel, String format, Object arg1, int arg2) { + if (ENABLED) { + return logvAndIndent(logLevel, format, arg1, arg2); + } + return null; + } + + public static Indent logAndIndent(String format, int arg1, int arg2) { + return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public static Indent logAndIndent(int logLevel, String format, int arg1, int arg2) { + if (ENABLED) { + return logvAndIndent(logLevel, format, arg1, arg2); + } + return null; + } + public static Indent logAndIndent(String format, Object arg1, Object arg2) { return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2); } @@ -723,6 +852,34 @@ return null; } + public static Indent logAndIndent(String format, int arg1, int arg2, int arg3) { + return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public static Indent logAndIndent(int logLevel, String format, int arg1, int arg2, int arg3) { + if (ENABLED) { + return logvAndIndent(logLevel, format, arg1, arg2, arg3); + } + return null; + } + + public static Indent logAndIndent(String format, Object arg1, int arg2, int arg3) { + return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public static Indent logAndIndent(int logLevel, String format, Object arg1, int arg2, int arg3) { + if (ENABLED) { + return logvAndIndent(logLevel, format, arg1, arg2, arg3); + } + return null; + } + public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) { return logAndIndent(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4); } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Thu Apr 16 17:09:06 2015 +0200 @@ -30,12 +30,277 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -public final class HotSpotReferenceMap implements ReferenceMap, Serializable { +public final class HotSpotReferenceMap extends ReferenceMap implements Serializable { + + static final int OOP64 = 0b1010; + static final int OOP32 = 0b01; + static final int NARROW_LOW = OOP32; + static final int NARROW_HIGH = OOP32 << 2; + static final int NARROW_BOTH = NARROW_LOW | NARROW_HIGH; + + private enum MapEntry { + NoReference(0), + WideOop(OOP64), + NarrowOopLowerHalf(NARROW_LOW), + NarrowOopUpperHalf(NARROW_HIGH), + TwoNarrowOops(NARROW_BOTH), + Illegal(-1); + + MapEntry(int pattern) { + this.pattern = pattern; + } + + final int pattern; + + /** + * Create enum values from OopMap. + *

+ * These bits can have the following values (MSB first): + * + *

+         * 0000 - contains no references
+         * 1010 - contains a wide oop
+         * 0001 - contains a narrow oop in the lower half
+         * 0101 - contains a narrow oop in the upper half
+         * 0101 - contains two narrow oops
+         * 
+ * + * @see HotSpotReferenceMap#registerRefMap + * @see HotSpotReferenceMap#frameRefMap + */ + static MapEntry getFromBits(int idx, HotSpotOopMap set) { + int n = set.get(idx); + switch (n) { + case 0: + return NoReference; + case OOP64: + return WideOop; + case NARROW_LOW: + return NarrowOopLowerHalf; + case NARROW_HIGH: + return NarrowOopUpperHalf; + case NARROW_BOTH: + return TwoNarrowOops; + default: + return Illegal; + } + } + + String toBitString() { + int bits = toBit(this); + if (bits == -1) { + return "---"; + } + return String.format("%3s", Integer.toBinaryString(bits)).replace(' ', '0'); + } + + static int toBit(MapEntry type) { + return type.pattern; + } + } + + /** + * A specialized bit set that represents both wide and narrow oops in an efficient manner. The + * map consists of 4 bit entries that represent 8 bytes of memory. + * + */ + class HotSpotOopMap implements Cloneable, Serializable { + + private static final long serialVersionUID = -4997600265320131213L; + + /** + * Each entry is 4 bits long and covers 8 bytes of memory. + */ + private static final int BITS_PER_ENTRY = 4; + private static final int BITS_PER_ELEMENT = 64; + + public HotSpotOopMap(int i) { + words = new long[(i * BITS_PER_ENTRY + BITS_PER_ELEMENT) / BITS_PER_ELEMENT]; + } + + public HotSpotOopMap(HotSpotOopMap other) { + words = other.words.clone(); + } + + private long[] words; + + private int get(int i) { + return getEntry(i); + } + + private boolean isEmpty() { + for (int i = 0; i < words.length; i++) { + if (words[i] != 0) { + return false; + } + } + return true; + } + + public void or(HotSpotOopMap src) { + if (words.length < src.words.length) { + long[] newWords = new long[src.words.length]; + System.arraycopy(src.words, 0, newWords, 0, src.words.length); + for (int i = 0; i < words.length; i++) { + newWords[i] |= words[i]; + } + words = newWords; + } else { + for (int i = 0; i < src.words.length; i++) { + words[i] |= src.words[i]; + } + } + } + + private void setOop(int regIdx) { + setEntry(regIdx, OOP64); + } + + public int size() { + return words.length * BITS_PER_ELEMENT / BITS_PER_ENTRY; + } + + @Override + public HotSpotOopMap clone() { + return new HotSpotOopMap(this); + } + + private void setNarrowOop(int offset, int index) { + setNarrowEntry(offset + index, OOP32); + } + + private void setEntry(int regIdx, int value) { + assert regIdx % 2 == 0 : "must be alinged"; + int bitIndex = (regIdx >> 1) * BITS_PER_ENTRY; + int wordIndex = bitIndex / BITS_PER_ELEMENT; + int shift = bitIndex - wordIndex * BITS_PER_ELEMENT; + if (wordIndex >= words.length) { + if (value == 0) { + // Nothing to do since bits are clear + return; + } + words = Arrays.copyOf(words, wordIndex + 1); + } + assert verifyUpdate(this, this); + long orig = words[wordIndex]; + words[wordIndex] = (orig & (~(0b1111L << shift))) | ((long) value << shift); + assert get(regIdx / 2) == value; + assert verifyUpdate(this, this); + } + + private void setNarrowEntry(int offset, int value) { + int regIdx = offset >> 1; + boolean low = offset % 2 == 0; + int bitIndex = regIdx * BITS_PER_ENTRY; + int wordIndex = bitIndex / BITS_PER_ELEMENT; + int shift = bitIndex - wordIndex * BITS_PER_ELEMENT; + if (wordIndex >= words.length) { + if (value == 0) { + // Nothing to do since bits are clear + return; + } + words = Arrays.copyOf(words, wordIndex + 1); + } + long originalValue = words[wordIndex]; + int current = ((int) (originalValue >> shift)) & 0b1111; + if (current == OOP64) { + current = 0; + } + long newValue; + if (value != 0) { + newValue = current | (low ? value : (value << 2)); + } else { + newValue = current & (low ? 0b1100 : 0b0011); + } + long masked = originalValue & (~(0b1111L << shift)); + words[wordIndex] = masked | (newValue << shift); + assert verifyUpdate(this, this); + } + + private int getEntry(int regIdx) { + int bitIndex = regIdx * BITS_PER_ENTRY; + int wordIndex = bitIndex / BITS_PER_ELEMENT; + int shift = bitIndex - wordIndex * BITS_PER_ELEMENT; + return ((int) (words[wordIndex] >>> shift)) & 0b1111; + } + + private void clearOop(int offset) { + setEntry(offset, 0); + } + + private void clearNarrowOop(int offset) { + setNarrowEntry(offset, 0); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other instanceof HotSpotOopMap) { + HotSpotOopMap otherMap = (HotSpotOopMap) other; + int limit = Math.min(words.length, otherMap.words.length); + for (int i = 0; i < limit; i++) { + if (words[i] != otherMap.words[i]) { + return false; + } + } + for (int i = limit; i < words.length; i++) { + if (words[i] != 0) { + return false; + } + } + for (int i = limit; i < otherMap.words.length; i++) { + if (otherMap.words[i] != 0) { + return false; + } + } + return true; + } + return false; + } + + @Override + public int hashCode() { + long h = 1234; + for (int i = words.length; --i >= 0;) { + h ^= words[i] * (i + 1); + } + return (int) ((h >> 32) ^ h); + } + + @Override + public String toString() { + int count = 0; + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int idx = 0; idx < size(); idx++) { + MapEntry dstType = MapEntry.getFromBits(idx, this); + if (dstType == MapEntry.NoReference) { + continue; + } + if (count > 0) { + sb.append(", "); + } + if (dstType == MapEntry.Illegal) { + int value = get(idx); + sb.append("0x"); + sb.append(Integer.toHexString(value)); + } else { + sb.append(idx); + sb.append(':'); + sb.append(dstType); + } + count++; + } + sb.append("]"); + return sb.toString(); + } + } private static final long serialVersionUID = -1052183095979496819L; - public static final int BITS_PER_WORD = 3; - /** * Contains 3 bits per scalar register, and n*3 bits per n-word vector register (e.g., on a * 64-bit system, a 256-bit vector register requires 12 reference map bits). @@ -50,7 +315,7 @@ * 111 - contains two narrow oops * */ - private final BitSet registerRefMap; + private final HotSpotOopMap registerRefMap; /** * Contains 3 bits per stack word. @@ -65,23 +330,23 @@ * 111 - contains two narrow oops * */ - private final BitSet frameRefMap; + private final HotSpotOopMap frameRefMap; private final TargetDescription target; public HotSpotReferenceMap(int registerCount, int frameSlotCount, TargetDescription target) { if (registerCount > 0) { - this.registerRefMap = new BitSet(registerCount * BITS_PER_WORD); + this.registerRefMap = new HotSpotOopMap(registerCount); } else { this.registerRefMap = null; } - this.frameRefMap = new BitSet(frameSlotCount * BITS_PER_WORD); + this.frameRefMap = new HotSpotOopMap(frameSlotCount); this.target = target; } private HotSpotReferenceMap(HotSpotReferenceMap other) { - this.registerRefMap = (BitSet) other.registerRefMap.clone(); - this.frameRefMap = (BitSet) other.frameRefMap.clone(); + this.registerRefMap = other.registerRefMap.clone(); + this.frameRefMap = other.frameRefMap.clone(); this.target = other.target; } @@ -92,32 +357,26 @@ // setters - private static void setOop(BitSet map, int startIdx, LIRKind kind) { + private static void setOop(HotSpotOopMap map, int startIdx, LIRKind kind) { int length = kind.getPlatformKind().getVectorLength(); - map.clear(BITS_PER_WORD * startIdx, BITS_PER_WORD * (startIdx + length)); - for (int i = 0, idx = BITS_PER_WORD * startIdx; i < length; i++, idx += BITS_PER_WORD) { + for (int i = 0, idx = startIdx; i < length; i++, idx += 1) { if (kind.isReference(i)) { - map.set(idx); + map.setOop(idx); + } + + } + } + + private static void setNarrowOop(HotSpotOopMap map, int offset, LIRKind kind) { + int length = kind.getPlatformKind().getVectorLength(); + for (int i = 0; i < length; i++) { + if (kind.isReference(i)) { + map.setNarrowOop(offset, i); } } } - private static void setNarrowOop(BitSet map, int idx, LIRKind kind) { - int length = kind.getPlatformKind().getVectorLength(); - int nextIdx = idx + (length + 1) / 2; - map.clear(BITS_PER_WORD * idx, BITS_PER_WORD * nextIdx); - for (int i = 0, regIdx = BITS_PER_WORD * idx; i < length; i += 2, regIdx += BITS_PER_WORD) { - if (kind.isReference(i)) { - map.set(regIdx); - map.set(regIdx + 1); - } - if ((i + 1) < length && kind.isReference(i + 1)) { - map.set(regIdx); - map.set(regIdx + 2); - } - } - } - + @Override public void setRegister(int idx, LIRKind kind) { if (kind.isDerivedReference()) { throw GraalInternalError.shouldNotReachHere("derived reference cannot be inserted in ReferenceMap"); @@ -126,15 +385,16 @@ PlatformKind platformKind = kind.getPlatformKind(); int bytesPerElement = target.getSizeInBytes(platformKind) / platformKind.getVectorLength(); - if (bytesPerElement == target.wordSize) { - setOop(registerRefMap, idx, kind); - } else if (bytesPerElement == target.wordSize / 2) { - setNarrowOop(registerRefMap, idx, kind); + if (bytesPerElement == 8) { + setOop(registerRefMap, idx * 2, kind); + } else if (bytesPerElement == 4) { + setNarrowOop(registerRefMap, idx * 2, kind); } else { assert kind.isValue() : "unsupported reference kind " + kind; } } + @Override public void setStackSlot(int offset, LIRKind kind) { if (kind.isDerivedReference()) { throw GraalInternalError.shouldNotReachHere("derived reference cannot be inserted in ReferenceMap"); @@ -144,109 +404,81 @@ int bytesPerElement = target.getSizeInBytes(platformKind) / platformKind.getVectorLength(); assert offset % bytesPerElement == 0 : "unaligned value in ReferenceMap"; - if (bytesPerElement == target.wordSize) { - setOop(frameRefMap, offset / target.wordSize, kind); - } else if (bytesPerElement == target.wordSize / 2) { - if (platformKind.getVectorLength() > 1) { - setNarrowOop(frameRefMap, offset / target.wordSize, kind); - } else { - // in this case, offset / target.wordSize may not divide evenly - // so setNarrowOop won't work correctly - int idx = offset / target.wordSize; - if (kind.isReference(0)) { - frameRefMap.set(BITS_PER_WORD * idx); - if (offset % target.wordSize == 0) { - frameRefMap.set(BITS_PER_WORD * idx + 1); - } else { - frameRefMap.set(BITS_PER_WORD * idx + 2); - } - } - } + int index = offset / 4; // Addressing is done in increments of 4 bytes + if (bytesPerElement == 8) { + setOop(frameRefMap, index, kind); + } else if (bytesPerElement == 4) { + setNarrowOop(frameRefMap, index, kind); } else { assert kind.isValue() : "unknown reference kind " + kind; } } - public BitSet getFrameMap() { - return frameRefMap == null ? null : (BitSet) frameRefMap.clone(); + public HotSpotOopMap getFrameMap() { + return frameRefMap == null ? null : (HotSpotOopMap) frameRefMap.clone(); } - public BitSet getRegisterMap() { - return registerRefMap == null ? null : (BitSet) registerRefMap.clone(); + public HotSpotOopMap getRegisterMap() { + return registerRefMap == null ? null : (HotSpotOopMap) registerRefMap.clone(); } // clear - private static void clearOop(BitSet map, int startIdx, LIRKind kind) { - int length = kind.getPlatformKind().getVectorLength(); - map.clear(BITS_PER_WORD * startIdx, BITS_PER_WORD * (startIdx + length)); + private static void clearOop(HotSpotOopMap map, int offset, PlatformKind platformKind) { + int length = platformKind.getVectorLength(); + for (int i = 0; i < length; i++) { + map.clearOop(offset + i * 2); + } } - private static void clearNarrowOop(BitSet map, int idx, LIRKind kind) { - int length = kind.getPlatformKind().getVectorLength(); - int nextIdx = idx + (length + 1) / 2; - map.clear(BITS_PER_WORD * idx, BITS_PER_WORD * nextIdx); + private static void clearNarrowOop(HotSpotOopMap map, int offset, PlatformKind platformKind) { + int length = platformKind.getVectorLength(); + for (int i = 0; i < length; i++) { + map.clearNarrowOop(offset + i); + } } + @Override public void clearRegister(int idx, LIRKind kind) { - PlatformKind platformKind = kind.getPlatformKind(); int bytesPerElement = target.getSizeInBytes(platformKind) / platformKind.getVectorLength(); - if (bytesPerElement == target.wordSize) { - clearOop(registerRefMap, idx, kind); - } else if (bytesPerElement == target.wordSize / 2) { - clearNarrowOop(registerRefMap, idx, kind); + if (bytesPerElement == 8) { + clearOop(registerRefMap, idx * 2, platformKind); + } else if (bytesPerElement == 4) { + clearNarrowOop(registerRefMap, idx * 2, platformKind); } else { assert kind.isValue() : "unsupported reference kind " + kind; } } + @Override public void clearStackSlot(int offset, LIRKind kind) { PlatformKind platformKind = kind.getPlatformKind(); int bytesPerElement = target.getSizeInBytes(platformKind) / platformKind.getVectorLength(); assert offset % bytesPerElement == 0 : "unaligned value in ReferenceMap"; - if (bytesPerElement == target.wordSize) { - clearOop(frameRefMap, offset / target.wordSize, kind); - } else if (bytesPerElement == target.wordSize / 2) { - if (platformKind.getVectorLength() > 1) { - clearNarrowOop(frameRefMap, offset / target.wordSize, kind); - } else { - // in this case, offset / target.wordSize may not divide evenly - // so setNarrowOop won't work correctly - int idx = offset / target.wordSize; - if (kind.isReference(0)) { - if (offset % target.wordSize == 0) { - frameRefMap.clear(BITS_PER_WORD * idx + 1); - if (!frameRefMap.get(BITS_PER_WORD * idx + 2)) { - // only reset the first bit if there is no other narrow oop - frameRefMap.clear(BITS_PER_WORD * idx); - } - } else { - frameRefMap.clear(BITS_PER_WORD * idx + 2); - if (!frameRefMap.get(BITS_PER_WORD * idx + 1)) { - // only reset the first bit if there is no other narrow oop - frameRefMap.clear(BITS_PER_WORD * idx); - } - } - } - } + int index = offset / 4; // Addressing is done in increments of 4 bytes + if (bytesPerElement == 8) { + clearOop(frameRefMap, index, platformKind); + } else if (bytesPerElement == 4) { + clearNarrowOop(frameRefMap, index, platformKind); } else { assert kind.isValue() : "unknown reference kind " + kind; } } + @Override public void updateUnion(ReferenceMap otherArg) { HotSpotReferenceMap other = (HotSpotReferenceMap) otherArg; if (registerRefMap != null) { assert other.registerRefMap != null; - updateUnionBitSetRaw(registerRefMap, other.registerRefMap); + updateUnionOopMapRaw(registerRefMap, other.registerRefMap); } else { - assert other.registerRefMap == null || other.registerRefMap.cardinality() == 0 : "Target register reference map is empty but the source is not: " + other.registerRefMap; + assert other.registerRefMap == null || other.registerRefMap.isEmpty() : "Target register reference map is empty but the source is not: " + other.registerRefMap; } - updateUnionBitSetRaw(frameRefMap, other.frameRefMap); + updateUnionOopMapRaw(frameRefMap, other.frameRefMap); } /** @@ -255,111 +487,69 @@ * @see HotSpotReferenceMap#registerRefMap * @see HotSpotReferenceMap#frameRefMap */ - private static void updateUnionBitSetRaw(BitSet dst, BitSet src) { - assert dst.size() == src.size(); - assert UpdateUnionVerifier.verifyUpate(dst, src); + private static void updateUnionOopMapRaw(HotSpotOopMap dst, HotSpotOopMap src) { + assert verifyUpdate(dst, src); dst.or(src); + assert verifyUpdate(dst, dst); } - private enum UpdateUnionVerifier { - NoReference, - WideOop, - NarrowOopLowerHalf, - NarrowOopUpperHalf, - TwoNarrowOops, - Illegal; + static MapEntry[] entries(HotSpotOopMap fixedMap) { + MapEntry[] result = new MapEntry[fixedMap.size()]; + for (int idx = 0; idx < fixedMap.size(); idx++) { + MapEntry dstType = MapEntry.getFromBits(idx, fixedMap); + result[idx] = dstType; + } + return result; + } - /** - * Create enum values from BitSet. - *

- * These bits can have the following values (LSB first): - * - *

-         * 000 - contains no references
-         * 100 - contains a wide oop
-         * 110 - contains a narrow oop in the lower half
-         * 101 - contains a narrow oop in the upper half
-         * 111 - contains two narrow oops
-         * 
- * - * @see HotSpotReferenceMap#registerRefMap - * @see HotSpotReferenceMap#frameRefMap - */ - static UpdateUnionVerifier getFromBits(int idx, BitSet set) { - int n = (set.get(idx) ? 1 : 0) << 0 | (set.get(idx + 1) ? 1 : 0) << 1 | (set.get(idx + 2) ? 1 : 0) << 2; - switch (n) { - case 0: - return NoReference; - case 1: - return WideOop; - case 3: - return NarrowOopLowerHalf; - case 5: - return NarrowOopUpperHalf; - case 7: - return TwoNarrowOops; - default: - return Illegal; + private static boolean verifyUpdate(HotSpotOopMap dst, HotSpotOopMap src) { + return verifyUpdate(dst, src, true); + } + + private static boolean verifyUpdate(HotSpotOopMap dst, HotSpotOopMap src, boolean doAssert) { + for (int idx = 0; idx < Math.min(src.size(), dst.size()); idx++) { + if (!verifyUpdateEntry(idx, dst, src, doAssert)) { + return false; } } - - String toBitString() { - int bits = toBit(this); - if (bits == -1) { - return "---"; - } - return String.format("%3s", Integer.toBinaryString(bits)).replace(' ', '0'); - } + return true; + } - static int toBit(UpdateUnionVerifier type) { - switch (type) { - case NoReference: - return 0; - case WideOop: - return 1; - case NarrowOopLowerHalf: - return 3; - case NarrowOopUpperHalf: - return 5; - case TwoNarrowOops: - return 7; - default: - return -1; - } - } + private static boolean verifyUpdateEntry(int idx, HotSpotOopMap dst, HotSpotOopMap src, boolean doAssert) { + MapEntry dstType = MapEntry.getFromBits(idx, dst); + MapEntry srcType = MapEntry.getFromBits(idx, src); - private static boolean verifyUpate(BitSet dst, BitSet src) { - for (int idx = 0; idx < dst.size(); idx += BITS_PER_WORD) { - if (!verifyUpdateEntry(idx, dst, src)) { - return false; - } - } - return true; + if (dstType == MapEntry.Illegal || srcType == MapEntry.Illegal) { + assert !doAssert : String.format("Illegal RefMap bit pattern: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString()); + return false; } - - private static boolean verifyUpdateEntry(int idx, BitSet dst, BitSet src) { - UpdateUnionVerifier dstType = UpdateUnionVerifier.getFromBits(idx, dst); - UpdateUnionVerifier srcType = UpdateUnionVerifier.getFromBits(idx, src); - - if (dstType == UpdateUnionVerifier.Illegal || srcType == UpdateUnionVerifier.Illegal) { - assert false : String.format("Illegal RefMap bit pattern: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString()); + switch (dstType) { + case NoReference: + return true; + case WideOop: + switch (srcType) { + case NoReference: + case WideOop: + return true; + default: + assert false : String.format("Illegal RefMap combination: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString()); + return false; + } + case TwoNarrowOops: + case NarrowOopLowerHalf: + case NarrowOopUpperHalf: + switch (srcType) { + case TwoNarrowOops: + case NarrowOopLowerHalf: + case NarrowOopUpperHalf: + case NoReference: + return true; + default: + assert false : String.format("Illegal RefMap combination: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString()); + return false; + } + default: return false; - } - switch (dstType) { - case NoReference: - return true; - case WideOop: - switch (srcType) { - case NoReference: - case WideOop: - return true; - default: - assert false : String.format("Illegal RefMap combination: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString()); - return false; - } - default: - return true; - } } } @@ -382,23 +572,50 @@ return false; } + @Override public boolean hasRegisterRefMap() { return registerRefMap != null && registerRefMap.size() > 0; } + @Override public boolean hasFrameRefMap() { return frameRefMap != null && frameRefMap.size() > 0; } + @Override public void appendRegisterMap(StringBuilder sb, RefMapFormatter formatter) { - for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + BITS_PER_WORD)) { - sb.append(' ').append(formatter.formatRegister(reg / BITS_PER_WORD)); + for (int idx = 0; idx < registerRefMap.size(); idx++) { + MapEntry dstType = MapEntry.getFromBits(idx, registerRefMap); + if (dstType != MapEntry.NoReference) { + sb.append(' ').append(formatter.formatRegister(idx)).append(':').append(dstType); + } } } + @Override public void appendFrameMap(StringBuilder sb, RefMapFormatter formatter) { - for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + BITS_PER_WORD)) { - sb.append(' ').append(formatter.formatStackSlot(slot / BITS_PER_WORD)); + for (int idx = 0; idx < frameRefMap.size(); idx++) { + MapEntry dstType = MapEntry.getFromBits(idx, frameRefMap); + if (dstType != MapEntry.NoReference) { + sb.append(' ').append(formatter.formatStackSlot(idx)).append(':').append(dstType); + } } } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (registerRefMap != null) { + sb.append("Registers = "); + sb.append(registerRefMap); + } + sb.append("Stack = "); + sb.append(frameRefMap); + return sb.toString(); + } + + public void verify() { + assert verifyUpdate(frameRefMap, frameRefMap); + assert registerRefMap == null || verifyUpdate(registerRefMap, registerRefMap); + } } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java Thu Apr 16 17:09:06 2015 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; public class HotSpotTargetDescription extends TargetDescription { @@ -32,11 +31,6 @@ } @Override - public int getSizeInBytes(PlatformKind kind) { - return super.getSizeInBytes(kind); - } - - @Override public ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount) { return new HotSpotReferenceMap(hasRegisters ? arch.getRegisterReferenceMapSize() : 0, stackSlotCount, this); } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java Thu Apr 16 17:09:06 2015 +0200 @@ -26,7 +26,6 @@ import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; /** * Represents a constant non-{@code null} object reference, within the compiler and across the @@ -84,14 +83,6 @@ JavaConstant getCallSiteTarget(Assumptions assumptions); /** - * Gets the result of {@link CompositeValueClass#create(Class)} for the {@link Class} object - * represented by this constant. - * - * @return {@code null} if this constant does not represent a {@link Class} object - */ - JavaConstant getCompositeValueClass(); - - /** * Determines if this constant represents an {@linkplain String#intern() interned} string. */ boolean isInternedString(); diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java Thu Apr 16 17:09:06 2015 +0200 @@ -28,9 +28,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.*; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import edu.umd.cs.findbugs.annotations.*; /** * Represents a constant non-{@code null} object reference, within the compiler and across the @@ -184,16 +183,6 @@ return null; } - @SuppressWarnings("unchecked") - public JavaConstant getCompositeValueClass() { - if (object instanceof Class) { - Class c = (Class) object; - assert CompositeValue.class.isAssignableFrom(c) : c; - return HotSpotObjectConstantImpl.forObject(CompositeValueClass.create(c)); - } - return null; - } - @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want") public boolean isInternedString() { if (object instanceof String) { diff -r ec36daea3cf0 -r 68ff637e95b1 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 Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Thu Apr 16 17:09:06 2015 +0200 @@ -25,16 +25,16 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.*; public final class AMD64AddressValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(AMD64AddressValue.class); - private static final long serialVersionUID = -4444600052487578694L; @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue base; @@ -42,12 +42,14 @@ protected final Scale scale; protected final int displacement; + private static final EnumSet flags = EnumSet.of(OperandFlag.REG, OperandFlag.ILLEGAL); + public AMD64AddressValue(LIRKind kind, AllocatableValue base, int displacement) { this(kind, base, Value.ILLEGAL, Scale.Times1, displacement); } public AMD64AddressValue(LIRKind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) { - super(TYPE, kind); + super(kind); this.base = base; this.index = index; this.scale = scale; @@ -56,6 +58,22 @@ assert scale != null; } + @Override + public CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) { + AllocatableValue newBase = (AllocatableValue) proc.doValue(inst, base, mode, flags); + AllocatableValue newIndex = (AllocatableValue) proc.doValue(inst, index, mode, flags); + if (!base.identityEquals(newBase) || !index.identityEquals(newIndex)) { + return new AMD64AddressValue(getLIRKind(), newBase, newIndex, scale, displacement); + } + return this; + } + + @Override + protected void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueConsumer proc) { + proc.visitValue(inst, base, mode, flags); + proc.visitValue(inst, index, mode, flags); + } + private static Register toRegister(AllocatableValue value) { if (value.equals(Value.ILLEGAL)) { return Register.None; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java Thu Apr 16 17:09:06 2015 +0200 @@ -25,33 +25,52 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; public final class SPARCAddressValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(SPARCAddressValue.class); - private static final long serialVersionUID = -3583286416638228207L; @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue base; @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue index; protected final int displacement; + private static final EnumSet flags = EnumSet.of(OperandFlag.REG, OperandFlag.ILLEGAL); + public SPARCAddressValue(LIRKind kind, AllocatableValue base, int displacement) { this(kind, base, Value.ILLEGAL, displacement); } public SPARCAddressValue(LIRKind kind, AllocatableValue base, AllocatableValue index, int displacement) { - super(TYPE, kind); + super(kind); assert isIllegal(index) || displacement == 0; this.base = base; this.index = index; this.displacement = displacement; } + @Override + public CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) { + AllocatableValue newBase = (AllocatableValue) proc.doValue(inst, base, mode, flags); + AllocatableValue newIndex = (AllocatableValue) proc.doValue(inst, index, mode, flags); + if (!base.identityEquals(newBase) || !index.identityEquals(newIndex)) { + return new SPARCAddressValue(getLIRKind(), newBase, newIndex, displacement); + } + return this; + } + + @Override + protected void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueConsumer proc) { + proc.visitValue(inst, base, mode, flags); + proc.visitValue(inst, index, mode, flags); + } + private static Register toRegister(AllocatableValue value) { if (isIllegal(value)) { return Register.None; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Thu Apr 16 17:09:06 2015 +0200 @@ -39,7 +39,6 @@ import com.oracle.graal.asm.sparc.*; import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.debug.internal.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.gen.*; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest1.java Thu Apr 16 17:09:06 2015 +0200 @@ -25,11 +25,14 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static org.junit.Assert.*; +import java.util.*; + import org.junit.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.asm.*; /** @@ -38,17 +41,31 @@ */ public class CompositeValueReplacementTest1 { - private static class NestedCompositeValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class); + private static class TestCompositeValue extends CompositeValue { private static final long serialVersionUID = -8804214200173503527L; @Component({REG, OperandFlag.ILLEGAL}) protected Value value; - public NestedCompositeValue(Value value) { - super(TYPE, LIRKind.Illegal); + public TestCompositeValue(Value value) { + super(LIRKind.Illegal); this.value = value; } + private static final EnumSet flags = EnumSet.of(OperandFlag.REG, OperandFlag.ILLEGAL); + + @Override + public CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) { + Value newValue = proc.doValue(inst, value, mode, flags); + if (!value.identityEquals(newValue)) { + return new TestCompositeValue(newValue); + } + return this; + } + + @Override + protected void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueConsumer proc) { + proc.visitValue(inst, value, mode, flags); + } } private static class DummyValue extends AbstractValue { @@ -98,9 +115,9 @@ private static final class TestOp extends LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class); - @Use({COMPOSITE}) protected NestedCompositeValue compValue; + @Use({COMPOSITE}) protected TestCompositeValue compValue; - public TestOp(NestedCompositeValue compValue) { + public TestOp(TestCompositeValue compValue) { super(TYPE); this.compValue = compValue; } @@ -112,43 +129,12 @@ } - private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) { - NestedCompositeValue compValue = new NestedCompositeValue(value); - for (int i = 0; i < nestingLevel; i++) { - compValue = new NestedCompositeValue(compValue); - } - return compValue; - } - @Test public void replaceCompValueTest0() { DummyValue dummyValue1 = new DummyValue(); DummyValue dummyValue2 = new DummyValue(); DummyValue dummyValue3 = new DummyValue(); - NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0); - LIRInstruction op1 = new TestOp(compValue1); - LIRInstruction op2 = new TestOp(compValue1); - - op1.forEachInput((instruction, value, mode, flags) -> { - assertEquals(dummyValue1, value); - return dummyValue2; - }); - - op2.forEachInput((instruction, value, mode, flags) -> { - assertEquals(dummyValue1, value); - return dummyValue3; - }); - - op1.visitEachInput((instruction, value, mode, flags) -> assertEquals(dummyValue2, value)); - op2.visitEachInput((instruction, value, mode, flags) -> assertEquals(dummyValue3, value)); - } - - @Test - public void replaceCompValueTest1() { - DummyValue dummyValue1 = new DummyValue(); - DummyValue dummyValue2 = new DummyValue(); - DummyValue dummyValue3 = new DummyValue(); - NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1); + TestCompositeValue compValue1 = new TestCompositeValue(dummyValue1); LIRInstruction op1 = new TestOp(compValue1); LIRInstruction op2 = new TestOp(compValue1); diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest2.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest2.java Thu Apr 16 17:01:53 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.test; - -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.asm.*; - -/** - * Same as {@link CompositeValueReplacementTest1} but with value arrays. - * - * @see CompositeValueReplacementTest1 - */ -public class CompositeValueReplacementTest2 { - - private static class NestedCompositeValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class); - - private static final long serialVersionUID = -8804214200173503527L; - @Component({REG, OperandFlag.ILLEGAL}) protected Value[] values; - - public NestedCompositeValue(Value value) { - super(TYPE, LIRKind.Illegal); - this.values = new Value[]{value}; - } - - } - - private static class DummyValue extends AbstractValue { - - private static final long serialVersionUID = -645435039553382737L; - private final int id; - private static int counter = 1; - - protected DummyValue() { - super(LIRKind.Illegal); - this.id = counter++; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + id; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - DummyValue other = (DummyValue) obj; - if (id != other.id) { - return false; - } - return true; - } - - @Override - public String toString() { - return "DummyValue [id=" + id + "]"; - } - - } - - private static final class TestOp extends LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class); - - @Use({COMPOSITE}) protected NestedCompositeValue compValue; - - public TestOp(NestedCompositeValue compValue) { - super(TYPE); - this.compValue = compValue; - } - - @Override - public void emitCode(CompilationResultBuilder crb) { - fail("should not reach!"); - } - - } - - private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) { - NestedCompositeValue compValue = new NestedCompositeValue(value); - for (int i = 0; i < nestingLevel; i++) { - compValue = new NestedCompositeValue(compValue); - } - return compValue; - } - - @Test - public void replaceCompValueTest0() { - DummyValue dummyValue1 = new DummyValue(); - DummyValue dummyValue2 = new DummyValue(); - DummyValue dummyValue3 = new DummyValue(); - NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0); - LIRInstruction op1 = new TestOp(compValue1); - LIRInstruction op2 = new TestOp(compValue1); - - op1.forEachInput((instruction, value, mode, flags) -> { - assertEquals(dummyValue1, value); - return dummyValue2; - }); - - op2.forEachInput((instruction, value, mode, flags) -> { - assertEquals(dummyValue1, value); - return dummyValue3; - }); - - op1.visitEachInput((instruction, value, mode, flags) -> assertEquals(dummyValue2, value)); - op2.visitEachInput((instruction, value, mode, flags) -> assertEquals(dummyValue3, value)); - } - - @Test - public void replaceCompValueTest1() { - DummyValue dummyValue1 = new DummyValue(); - DummyValue dummyValue2 = new DummyValue(); - DummyValue dummyValue3 = new DummyValue(); - NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1); - LIRInstruction op1 = new TestOp(compValue1); - LIRInstruction op2 = new TestOp(compValue1); - - op1.forEachInput((instruction, value, mode, flags) -> { - assertEquals(dummyValue1, value); - return dummyValue2; - }); - - op2.forEachInput((instruction, value, mode, flags) -> { - assertEquals(dummyValue1, value); - return dummyValue3; - }); - - op1.visitEachInput((instruction, value, mode, flags) -> assertEquals(dummyValue2, value)); - op2.visitEachInput((instruction, value, mode, flags) -> assertEquals(dummyValue3, value)); - } -} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest3.java Thu Apr 16 17:01:53 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.test; - -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.asm.*; - -/** - * Same as {@link CompositeValueReplacementTest1} but with for {@link ValuePosition}s. - * - * @see CompositeValueReplacementTest1 - */ -public class CompositeValueReplacementTest3 { - - private static class NestedCompositeValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class); - - private static final long serialVersionUID = -8804214200173503527L; - @Component({REG, OperandFlag.ILLEGAL}) protected Value value; - - public NestedCompositeValue(Value value) { - super(TYPE, LIRKind.Illegal); - this.value = value; - } - - } - - private static class DummyValue extends AbstractValue { - - private static final long serialVersionUID = -645435039553382737L; - private final int id; - private static int counter = 1; - - protected DummyValue() { - super(LIRKind.Illegal); - this.id = counter++; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + id; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - DummyValue other = (DummyValue) obj; - if (id != other.id) { - return false; - } - return true; - } - - @Override - public String toString() { - return "DummyValue [id=" + id + "]"; - } - - } - - private static final class TestOp extends LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class); - - @Use({COMPOSITE}) protected NestedCompositeValue compValue; - - public TestOp(NestedCompositeValue compValue) { - super(TYPE); - this.compValue = compValue; - } - - @Override - public void emitCode(CompilationResultBuilder crb) { - fail("should not reach!"); - } - - } - - private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) { - NestedCompositeValue compValue = new NestedCompositeValue(value); - for (int i = 0; i < nestingLevel; i++) { - compValue = new NestedCompositeValue(compValue); - } - return compValue; - } - - @Test - public void replaceCompValueTest0() { - DummyValue dummyValue1 = new DummyValue(); - DummyValue dummyValue2 = new DummyValue(); - DummyValue dummyValue3 = new DummyValue(); - NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0); - LIRInstruction op1 = new TestOp(compValue1); - LIRInstruction op2 = new TestOp(compValue1); - - op1.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue1, value); - position.set(instruction, dummyValue2); - }); - - op2.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue1, value); - position.set(instruction, dummyValue3); - }); - - op1.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue2, value); - }); - - op2.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue3, value); - }); - } - - @Test - public void replaceCompValueTest1() { - DummyValue dummyValue1 = new DummyValue(); - DummyValue dummyValue2 = new DummyValue(); - DummyValue dummyValue3 = new DummyValue(); - NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1); - LIRInstruction op1 = new TestOp(compValue1); - LIRInstruction op2 = new TestOp(compValue1); - - op1.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue1, value); - position.set(instruction, dummyValue2); - }); - - op2.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue1, value); - position.set(instruction, dummyValue3); - }); - - op1.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue2, value); - }); - - op2.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue3, value); - }); - } -} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/CompositeValueReplacementTest4.java Thu Apr 16 17:01:53 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.test; - -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.asm.*; - -/** - * Same as {@link CompositeValueReplacementTest2} but with value arrays {@link ValuePosition}s. - * - * @see CompositeValueReplacementTest2 - */ -public class CompositeValueReplacementTest4 { - - private static class NestedCompositeValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class); - - private static final long serialVersionUID = -8804214200173503527L; - @Component({REG, OperandFlag.ILLEGAL}) protected Value[] values; - - public NestedCompositeValue(Value value) { - super(TYPE, LIRKind.Illegal); - this.values = new Value[]{value}; - } - - } - - private static class DummyValue extends AbstractValue { - - private static final long serialVersionUID = -645435039553382737L; - private final int id; - private static int counter = 1; - - protected DummyValue() { - super(LIRKind.Illegal); - this.id = counter++; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + id; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - DummyValue other = (DummyValue) obj; - if (id != other.id) { - return false; - } - return true; - } - - @Override - public String toString() { - return "DummyValue [id=" + id + "]"; - } - - } - - private static class TestOp extends LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class); - - @Use({COMPOSITE}) protected NestedCompositeValue compValue; - - public TestOp(NestedCompositeValue compValue) { - super(TYPE); - this.compValue = compValue; - } - - @Override - public void emitCode(CompilationResultBuilder crb) { - fail("should not reach!"); - } - - } - - private static NestedCompositeValue createNestedCompValue(Value value, int nestingLevel) { - NestedCompositeValue compValue = new NestedCompositeValue(value); - for (int i = 0; i < nestingLevel; i++) { - compValue = new NestedCompositeValue(compValue); - } - return compValue; - } - - @Test - public void replaceCompValueTest0() { - DummyValue dummyValue1 = new DummyValue(); - DummyValue dummyValue2 = new DummyValue(); - DummyValue dummyValue3 = new DummyValue(); - NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 0); - LIRInstruction op1 = new TestOp(compValue1); - LIRInstruction op2 = new TestOp(compValue1); - - op1.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue1, value); - position.set(instruction, dummyValue2); - }); - - op2.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue1, value); - position.set(instruction, dummyValue3); - }); - - op1.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue2, value); - }); - - op2.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue3, value); - }); - } - - @Test - public void replaceCompValueTest1() { - DummyValue dummyValue1 = new DummyValue(); - DummyValue dummyValue2 = new DummyValue(); - DummyValue dummyValue3 = new DummyValue(); - NestedCompositeValue compValue1 = createNestedCompValue(dummyValue1, 1); - LIRInstruction op1 = new TestOp(compValue1); - LIRInstruction op2 = new TestOp(compValue1); - - op1.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue1, value); - position.set(instruction, dummyValue2); - }); - - op2.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue1, value); - position.set(instruction, dummyValue3); - }); - - op1.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue2, value); - }); - - op2.forEachInputPos((instruction, position) -> { - Value value = position.get(instruction); - assertEquals(dummyValue3, value); - }); - } -} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest1.java Thu Apr 16 17:01:53 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.test; - -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import static org.junit.Assert.*; - -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.asm.*; - -public class ValuePositionTest1 { - - private static class NestedCompositeValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class); - - private static final long serialVersionUID = -8804214200173503527L; - @Component({REG, OperandFlag.ILLEGAL}) protected Value value; - - public NestedCompositeValue(Value value) { - super(TYPE, LIRKind.Illegal); - this.value = value; - } - - } - - private static class DummyValue extends AbstractValue { - - private static final long serialVersionUID = -645435039553382737L; - private final int id; - private static int counter = 1; - - protected DummyValue() { - super(LIRKind.Illegal); - this.id = counter++; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + id; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - DummyValue other = (DummyValue) obj; - if (id != other.id) { - return false; - } - return true; - } - } - - private static final class TestOp extends LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class); - - @Use({COMPOSITE}) protected NestedCompositeValue compValue; - - public TestOp(NestedCompositeValue compValue) { - super(TYPE); - this.compValue = compValue; - } - - @Override - public void emitCode(CompilationResultBuilder crb) { - fail("should not reach!"); - } - - } - - private static LIRInstruction createNestedOp(Value value, int nestingLevel) { - NestedCompositeValue compValue = new NestedCompositeValue(value); - for (int i = 0; i < nestingLevel; i++) { - compValue = new NestedCompositeValue(compValue); - } - TestOp op = new TestOp(compValue); - return op; - } - - @Test - public void nestedTest0() { - DummyValue dummyValue = new DummyValue(); - LIRInstruction op = createNestedOp(dummyValue, 0); - - List positions = new ArrayList<>(); - - op.forEachInputPos((instruction, position) -> positions.add(position)); - - assertEquals(1, positions.size()); - assertEquals(dummyValue, positions.get(0).get(op)); - } - - @Test - public void nestedTest1() { - DummyValue dummyValue = new DummyValue(); - LIRInstruction op = createNestedOp(dummyValue, 1); - - List positions = new ArrayList<>(); - - op.forEachInputPos((instruction, position) -> positions.add(position)); - - assertEquals(1, positions.size()); - assertEquals(dummyValue, positions.get(0).get(op)); - } - - @Test - public void nestedTest2() { - DummyValue dummyValue = new DummyValue(); - LIRInstruction op = createNestedOp(dummyValue, 2); - - List positions = new ArrayList<>(); - - op.forEachInputPos((instruction, position) -> positions.add(position)); - - assertEquals(1, positions.size()); - assertEquals(dummyValue, positions.get(0).get(op)); - } - -} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest2.java Thu Apr 16 17:01:53 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.test; - -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import static org.junit.Assert.*; - -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.asm.*; - -public class ValuePositionTest2 { - - private static class NestedCompositeValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(NestedCompositeValue.class); - - private static final long serialVersionUID = -2243948303328857965L; - @Component({REG, OperandFlag.ILLEGAL}) protected Value value1; - @Component({REG, OperandFlag.ILLEGAL}) protected Value value2; - - public NestedCompositeValue(Value value1, Value value2) { - super(TYPE, LIRKind.Illegal); - this.value1 = value1; - this.value2 = value2; - } - - } - - private static class DummyValue extends AbstractValue { - - private static final long serialVersionUID = 3620305384660607012L; - private final int id; - private static int counter = 0; - - protected DummyValue() { - super(LIRKind.Illegal); - this.id = counter++; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + id; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - DummyValue other = (DummyValue) obj; - if (id != other.id) { - return false; - } - return true; - } - } - - private static class TestOp extends LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class); - - @Use({COMPOSITE}) protected NestedCompositeValue compValue; - - public TestOp(NestedCompositeValue compValue) { - super(TYPE); - this.compValue = compValue; - } - - @Override - public void emitCode(CompilationResultBuilder crb) { - fail("should not reach!"); - } - - } - - @Test - public void testSetGet() { - DummyValue dummyValue0 = new DummyValue(); - DummyValue dummyValue1 = new DummyValue(); - DummyValue dummyValue2 = new DummyValue(); - DummyValue dummyValue3 = new DummyValue(); - - NestedCompositeValue compValue0 = new NestedCompositeValue(dummyValue0, dummyValue1); - NestedCompositeValue compValue1 = new NestedCompositeValue(compValue0, dummyValue2); - NestedCompositeValue compValue2 = new NestedCompositeValue(dummyValue3, compValue1); - - LIRInstruction op = new TestOp(compValue2); - List positions = new ArrayList<>(); - - op.forEachInputPos((instruction, position) -> positions.add(position)); - - assertEquals(4, positions.size()); - - // replace values - List replValues = new ArrayList<>(); - for (ValuePosition pos : positions) { - Value v = new DummyValue(); - replValues.add(v); - pos.set(op, v); - - } - - // check replaced values - Iterator it = replValues.iterator(); - for (ValuePosition pos : positions) { - Value v = pos.get(op); - assertEquals(it.next(), v); - } - assertFalse(it.hasNext()); - } - -} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest3.java --- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/ValuePositionTest3.java Thu Apr 16 17:01:53 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.test; - -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import static org.junit.Assert.*; - -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.asm.*; - -public class ValuePositionTest3 { - - public static final class TestAddressValue extends CompositeValue { - public static final CompositeValueClass TYPE = CompositeValueClass.create(TestAddressValue.class); - - private static final long serialVersionUID = -2679790860680123026L; - - @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue base; - @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue index; - - public TestAddressValue(LIRKind kind, AllocatableValue base) { - this(kind, base, Value.ILLEGAL); - } - - public TestAddressValue(LIRKind kind, AllocatableValue base, AllocatableValue index) { - super(TYPE, kind); - this.base = base; - this.index = index; - } - } - - private static class DummyValue extends AllocatableValue { - - private static final long serialVersionUID = 3620305384660607012L; - private final int id; - private static int counter = 0; - - protected DummyValue() { - super(LIRKind.Illegal); - this.id = counter++; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + id; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - DummyValue other = (DummyValue) obj; - if (id != other.id) { - return false; - } - return true; - } - - @Override - public String toString() { - return "DummyValue" + id; - } - - } - - private static class TestOp extends LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TestOp.class); - - @Use({COMPOSITE}) protected Value value; - - public TestOp(Value value) { - super(TYPE); - this.value = value; - } - - @Override - public void emitCode(CompilationResultBuilder crb) { - fail("should not reach!"); - } - - @Override - public String toString() { - return "TestOp [" + value + "]"; - } - - } - - @Test - public void test0() { - DummyValue dummyValue0 = new DummyValue(); - DummyValue dummyValue1 = new DummyValue(); - - TestAddressValue compValue0 = new TestAddressValue(LIRKind.Illegal, dummyValue0, dummyValue1); - - LIRInstruction op = new TestOp(compValue0); - - HashMap> positionMap = new HashMap<>(); - HashMap> normalMap = new HashMap<>(); - - op.forEachInputPos(new ValuePositionProcedure() { - - @Override - public void doValue(LIRInstruction instruction, ValuePosition position) { - positionMap.put(position.get(instruction), position.getFlags()); - } - }); - op.visitEachInput(new InstructionValueConsumer() { - - @Override - public void visitValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { - normalMap.put(value, flags); - } - }); - - assertEquals(normalMap.size(), positionMap.size()); - assertTrue(normalMap.keySet().containsAll(positionMap.keySet())); - normalMap.keySet().forEach(key -> { - EnumSet normal = normalMap.get(key); - EnumSet position = positionMap.get(key); - assertTrue(normal.containsAll(position)); - assertTrue(position.containsAll(normal)); - }); - } -} diff -r ec36daea3cf0 -r 68ff637e95b1 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 Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java Thu Apr 16 17:09:06 2015 +0200 @@ -23,17 +23,19 @@ package com.oracle.graal.lir; import java.lang.annotation.*; +import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; /** - * Base class to represent values that need to be stored in more than one register. + * Base class to represent values that need to be stored in more than one register. This is mainly + * intended to support addresses and not general arbitrary nesting of composite values. Because of + * the possibility of sharing of CompositeValues they should be immutable. */ -public abstract class CompositeValue extends AbstractValue implements Cloneable { +public abstract class CompositeValue extends AbstractValue { private static final long serialVersionUID = -169180052684126180L; @@ -44,61 +46,69 @@ OperandFlag[] value() default OperandFlag.REG; } - private final CompositeValueClass valueClass; - private static final DebugMetric COMPOSITE_VALUE_COUNT = Debug.metric("CompositeValues"); - public CompositeValue(CompositeValueClass c, LIRKind kind) { + public CompositeValue(LIRKind kind) { super(kind); COMPOSITE_VALUE_COUNT.increment(); - valueClass = c; - assert c.getClazz() == this.getClass(); + assert CompositeValueClass.get(getClass()) != null; } - final CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) { - return valueClass.forEachComponent(inst, this, mode, proc); + /** + * Invoke {@code proc} on each {@link Value} element of this {@link CompositeValue}. If + * {@code proc} replaces any value then a new CompositeValue should be returned. + * + * @param inst + * @param mode + * @param proc + * @return the original CompositeValue or a copy with any modified values + */ + public abstract CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc); + + /** + * A helper method to visit {@link Value}[] ensuring that a copy of the array is made if it's + * needed. + * + * @param inst + * @param values + * @param mode + * @param proc + * @param flags + * @return the original {@code values} array or a copy if values changed + */ + protected Value[] visitValueArray(LIRInstruction inst, Value[] values, OperandMode mode, InstructionValueProcedure proc, EnumSet flags) { + Value[] newValues = null; + for (int i = 0; i < values.length; i++) { + Value value = values[i]; + Value newValue = proc.doValue(inst, value, mode, flags); + if (!value.identityEquals(newValue)) { + if (newValues == null) { + newValues = values.clone(); + } + newValues[i] = value; + } + } + return newValues != null ? newValues : values; } - final void forEachComponent(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { - valueClass.forEachComponent(inst, this, mode, proc, outerPosition); - } + protected abstract void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueConsumer proc); @Override public String toString() { - return valueClass.toString(this); + return CompositeValueClass.format(this); } @Override public int hashCode() { - return 53 * super.hashCode() + valueClass.hashCode(); + return 53 * super.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof CompositeValue) { CompositeValue other = (CompositeValue) obj; - return super.equals(other) && valueClass.equals(other.valueClass); + return super.equals(other); } return false; } - - CompositeValueClass getValueClass() { - return valueClass; - } - - @Override - public final CompositeValue clone() { - CompositeValue compositeValue = null; - try { - compositeValue = (CompositeValue) super.clone(); - } catch (CloneNotSupportedException e) { - throw new GraalInternalError(e); - } - - // copy value arrays - getValueClass().copyValueArrays(compositeValue); - - return compositeValue; - } - } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Thu Apr 16 17:09:06 2015 +0200 @@ -25,11 +25,12 @@ import java.lang.reflect.*; import java.util.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.CompositeValue.Component; import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRIntrospection.LIRFieldsScanner; +import com.oracle.graal.lir.LIRIntrospection.OperandModeAnnotation; +import com.oracle.graal.lir.LIRIntrospection.Values; /** * Lazily associated metadata for every {@link CompositeValue} type. The metadata includes: @@ -38,20 +39,35 @@ * such fields. * */ -public class CompositeValueClass extends LIRIntrospection { +public final class CompositeValueClass { + + /** + * The CompositeValueClass is only used for formatting for the most part so cache it as a + * ClassValue. + */ + private static final ClassValue> compositeClass = new ClassValue>() { - public static final CompositeValueClass create(Class c) { - return new CompositeValueClass<>(c); + @Override + protected CompositeValueClass computeValue(Class type) { + CompositeValueClass compositeValueClass = new CompositeValueClass<>(type); + assert compositeValueClass.values.getDirectCount() == compositeValueClass.values.getCount() : "only direct fields are allowed in composites"; + return compositeValueClass; + } + + }; + + public static CompositeValueClass get(Class type) { + return compositeClass.get(type); } - public CompositeValueClass(Class clazz) { - this(clazz, new FieldsScanner.DefaultCalcOffset()); - } + private final Class clazz; + private final Values values; + private final Fields data; - public CompositeValueClass(Class clazz, FieldsScanner.CalcOffset calcOffset) { - super(clazz); + private CompositeValueClass(Class clazz) { + this.clazz = clazz; - CompositeValueFieldsScanner vfs = new CompositeValueFieldsScanner(calcOffset); + CompositeValueFieldsScanner vfs = new CompositeValueFieldsScanner(new FieldsScanner.DefaultCalcOffset()); vfs.scan(clazz, CompositeValue.class, false); values = new Values(vfs.valueAnnotations.get(CompositeValue.Component.class)); @@ -80,7 +96,7 @@ @Override public String toString() { StringBuilder str = new StringBuilder(); - str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" components["); + str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" components["); values.appendFields(str); str.append("] data["); data.appendFields(str); @@ -88,31 +104,16 @@ return str.toString(); } - final CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedure proc) { - return super.forEachComponent(inst, obj, values, mode, proc); - } - - final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { - forEach(inst, obj, values, mode, proc, outerPosition); - } - - public String toString(CompositeValue obj) { + public static String format(CompositeValue obj) { + CompositeValueClass valueClass = compositeClass.get(obj.getClass()); StringBuilder result = new StringBuilder(); - appendValues(result, obj, "", "", "{", "}", new String[]{""}, values); + LIRIntrospection.appendValues(result, obj, "", "", "{", "}", new String[]{""}, valueClass.values); - for (int i = 0; i < data.getCount(); i++) { - result.append(" ").append(data.getName(i)).append(": ").append(getFieldString(obj, i, data)); + for (int i = 0; i < valueClass.data.getCount(); i++) { + result.append(" ").append(valueClass.data.getName(i)).append(": ").append(LIRIntrospection.getFieldString(obj, i, valueClass.data)); } return result.toString(); } - - void copyValueArrays(CompositeValue compositeValue) { - for (int i = values.getDirectCount(); i < values.getCount(); i++) { - Value[] valueArray = values.getValueArray(compositeValue, i); - Value[] newValueArray = Arrays.copyOf(valueArray, valueArray.length); - values.setValueArray(compositeValue, i, newValueArray); - } - } } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueConsumer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueConsumer.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueConsumer.java Thu Apr 16 17:09:06 2015 +0200 @@ -29,10 +29,11 @@ import com.oracle.graal.lir.LIRInstruction.OperandMode; /** - * Non-modifying version of {@link InstructionValueProcedure}. + * Functional interface for iterating over a list of values without modifying them. See + * {@link InstructionValueProcedure} for a version that can modify values. */ @FunctionalInterface -public interface InstructionValueConsumer extends InstructionValueProcedure { +public interface InstructionValueConsumer { /** * Iterator method to be overwritten. @@ -43,9 +44,4 @@ * @param flags A set of flags for the value. */ void visitValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags); - - default Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { - visitValue(instruction, value, mode, flags); - return value; - } } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedure.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedure.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InstructionValueProcedure.java Thu Apr 16 17:09:06 2015 +0200 @@ -29,7 +29,8 @@ import com.oracle.graal.lir.LIRInstruction.OperandMode; /** - * Functional interface for iterating over a list of values. + * Functional interface for iterating over a list of values, possibly returning a value to replace + * the old value. */ @FunctionalInterface public interface InstructionValueProcedure { diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Thu Apr 16 17:09:06 2015 +0200 @@ -75,6 +75,22 @@ } /** + * Iterates the frame state and calls the {@link InstructionValueProcedure} for every variable. + * + * @param proc The procedure called for variables. + */ + public void forEachState(LIRInstruction inst, InstructionValueConsumer proc) { + for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) { + processValues(inst, cur.values, proc); + } + if (virtualObjects != null) { + for (VirtualObject obj : virtualObjects) { + processValues(inst, obj.getValues(), proc); + } + } + } + + /** * We filter out constant and illegal values ourself before calling the procedure, so * {@link OperandFlag#CONST} and {@link OperandFlag#ILLEGAL} need not be set. */ @@ -83,29 +99,51 @@ protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedure proc) { for (int i = 0; i < values.length; i++) { Value value = values[i]; - values[i] = processValue(inst, proc, value); - } - } - - protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) { - if (value instanceof StackLockValue) { - StackLockValue monitor = (StackLockValue) value; - Value owner = monitor.getOwner(); - if (owner instanceof AllocatableValue) { - monitor.setOwner(proc.doValue(inst, owner, OperandMode.ALIVE, STATE_FLAGS)); + if (isIllegal(value)) { + continue; } - Value slot = monitor.getSlot(); - if (isVirtualStackSlot(slot)) { - monitor.setSlot(asStackSlotValue(proc.doValue(inst, slot, OperandMode.ALIVE, STATE_FLAGS))); - } - } else { - if (!isIllegal(value) && value instanceof AllocatableValue) { - return proc.doValue(inst, value, OperandMode.ALIVE, STATE_FLAGS); + if (value instanceof AllocatableValue) { + Value result = proc.doValue(inst, value, OperandMode.ALIVE, STATE_FLAGS); + if (!value.identityEquals(result)) { + values[i] = result; + } + } else if (value instanceof StackLockValue) { + StackLockValue monitor = (StackLockValue) value; + Value owner = monitor.getOwner(); + if (owner instanceof AllocatableValue) { + monitor.setOwner(proc.doValue(inst, owner, OperandMode.ALIVE, STATE_FLAGS)); + } + Value slot = monitor.getSlot(); + if (isVirtualStackSlot(slot)) { + monitor.setSlot(asStackSlotValue(proc.doValue(inst, slot, OperandMode.ALIVE, STATE_FLAGS))); + } } else { assert unprocessed(value); } } - return value; + } + + protected void processValues(LIRInstruction inst, Value[] values, InstructionValueConsumer proc) { + for (int i = 0; i < values.length; i++) { + Value value = values[i]; + if (isIllegal(value)) { + continue; + } else if (value instanceof AllocatableValue) { + proc.visitValue(inst, value, OperandMode.ALIVE, STATE_FLAGS); + } else if (value instanceof StackLockValue) { + StackLockValue monitor = (StackLockValue) value; + Value owner = monitor.getOwner(); + if (owner instanceof AllocatableValue) { + proc.visitValue(inst, owner, OperandMode.ALIVE, STATE_FLAGS); + } + Value slot = monitor.getSlot(); + if (isVirtualStackSlot(slot)) { + proc.visitValue(inst, slot, OperandMode.ALIVE, STATE_FLAGS); + } + } else { + assert unprocessed(value); + } + } } private boolean unprocessed(Value value) { diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Thu Apr 16 17:09:06 2015 +0200 @@ -37,8 +37,6 @@ * The base class for an {@code LIRInstruction}. */ public abstract class LIRInstruction { - public static final Value[] NO_OPERANDS = {}; - /** * Constants denoting how a LIR instruction uses an operand. */ @@ -211,23 +209,6 @@ return false; } - // ValuePositionProcedures - public final void forEachInputPos(ValuePositionProcedure proc) { - instructionClass.forEachUsePos(this, proc); - } - - public final void forEachAlivePos(ValuePositionProcedure proc) { - instructionClass.forEachAlivePos(this, proc); - } - - public final void forEachTempPos(ValuePositionProcedure proc) { - instructionClass.forEachTempPos(this, proc); - } - - public final void forEachOutputPos(ValuePositionProcedure proc) { - instructionClass.forEachDefPos(this, proc); - } - // InstructionValueProcedures public final void forEachInput(InstructionValueProcedure proc) { instructionClass.forEachUse(this, proc); diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Thu Apr 16 17:09:06 2015 +0200 @@ -205,22 +205,6 @@ return false; } - final void forEachUsePos(LIRInstruction obj, ValuePositionProcedure proc) { - forEach(obj, obj, uses, OperandMode.USE, proc, ValuePosition.ROOT_VALUE_POSITION); - } - - final void forEachAlivePos(LIRInstruction obj, ValuePositionProcedure proc) { - forEach(obj, obj, alives, OperandMode.ALIVE, proc, ValuePosition.ROOT_VALUE_POSITION); - } - - final void forEachTempPos(LIRInstruction obj, ValuePositionProcedure proc) { - forEach(obj, obj, temps, OperandMode.TEMP, proc, ValuePosition.ROOT_VALUE_POSITION); - } - - final void forEachDefPos(LIRInstruction obj, ValuePositionProcedure proc) { - forEach(obj, obj, defs, OperandMode.DEF, proc, ValuePosition.ROOT_VALUE_POSITION); - } - final void forEachUse(LIRInstruction obj, InstructionValueProcedure proc) { forEach(obj, uses, OperandMode.USE, proc); } @@ -237,6 +221,22 @@ forEach(obj, defs, OperandMode.DEF, proc); } + final void forEachUse(LIRInstruction obj, InstructionValueConsumer proc) { + forEach(obj, uses, OperandMode.USE, proc); + } + + final void forEachAlive(LIRInstruction obj, InstructionValueConsumer proc) { + forEach(obj, alives, OperandMode.ALIVE, proc); + } + + final void forEachTemp(LIRInstruction obj, InstructionValueConsumer proc) { + forEach(obj, temps, OperandMode.TEMP, proc); + } + + final void forEachDef(LIRInstruction obj, InstructionValueConsumer proc) { + forEach(obj, defs, OperandMode.DEF, proc); + } + final void forEachState(LIRInstruction obj, InstructionValueProcedure proc) { for (int i = 0; i < states.getCount(); i++) { LIRFrameState state = (LIRFrameState) states.getObject(obj, i); @@ -246,6 +246,15 @@ } } + final void forEachState(LIRInstruction obj, InstructionValueConsumer proc) { + for (int i = 0; i < states.getCount(); i++) { + LIRFrameState state = (LIRFrameState) states.getObject(obj, i); + if (state != null) { + state.forEachState(obj, proc); + } + } + } + final void forEachState(LIRInstruction obj, InstructionStateProcedure proc) { for (int i = 0; i < states.getCount(); i++) { LIRFrameState state = (LIRFrameState) states.getObject(obj, i); diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Thu Apr 16 17:09:06 2015 +0200 @@ -235,83 +235,34 @@ } } - protected static CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, Values values, OperandMode mode, InstructionValueProcedure proc) { - CompositeValue newCompValue = null; + protected static void forEach(LIRInstruction inst, Values values, OperandMode mode, InstructionValueConsumer proc) { for (int i = 0; i < values.getCount(); i++) { assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); if (i < values.getDirectCount()) { - Value value = values.getValue(obj, i); - Value newValue; + Value value = values.getValue(inst, i); if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; - newValue = composite.forEachComponent(inst, mode, proc); + composite.forEachComponent(inst, mode, proc); } else { - newValue = proc.doValue(inst, value, mode, values.getFlags(i)); - } - if (!value.identityEquals(newValue)) { - // lazy initialize - if (newCompValue == null) { - newCompValue = obj.clone(); - } - values.setValue(newCompValue, i, newValue); + proc.visitValue(inst, value, mode, values.getFlags(i)); } } else { - Value[] valueArray = values.getValueArray(obj, i); - Value[] newValues = null; + Value[] valueArray = values.getValueArray(inst, i); for (int j = 0; j < valueArray.length; j++) { Value value = valueArray[j]; - Value newValue; if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; - newValue = composite.forEachComponent(inst, mode, proc); + composite.forEachComponent(inst, mode, proc); } else { - newValue = proc.doValue(inst, value, mode, values.getFlags(i)); - } - if (!value.identityEquals(newValue)) { - // lazy initialize - if (newValues == null) { - if (newCompValue == null) { - newCompValue = obj.clone(); - } - newValues = values.getValueArray(newCompValue, i); - } - newValues[j] = newValue; + proc.visitValue(inst, value, mode, values.getFlags(i)); } } } } - return newCompValue != null ? newCompValue : obj; - } - - protected static void forEach(LIRInstruction inst, Object obj, Values values, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { - for (int i = 0; i < values.getCount(); i++) { - assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); - - if (i < values.getDirectCount()) { - Value value = values.getValue(obj, i); - doForValue(inst, values, mode, proc, outerPosition, i, ValuePosition.NO_SUBINDEX, value); - } else { - Value[] valueArray = values.getValueArray(obj, i); - for (int j = 0; j < valueArray.length; j++) { - Value value = valueArray[j]; - doForValue(inst, values, mode, proc, outerPosition, i, j, value); - } - } - } } - private static void doForValue(LIRInstruction inst, Values values, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition, int index, int subIndex, Value value) { - ValuePosition position = new ValuePosition(values, index, subIndex, outerPosition); - if (value instanceof CompositeValue) { - CompositeValue composite = (CompositeValue) value; - composite.forEachComponent(inst, mode, proc, position); - } else { - proc.doValue(inst, position); - } - } - - protected void appendValues(StringBuilder sb, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, Fields... fieldsList) { + protected static void appendValues(StringBuilder sb, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, Fields... fieldsList) { int total = 0; for (Fields fields : fieldsList) { total += fields.getCount(); @@ -343,7 +294,7 @@ sb.append(end); } - protected String getFieldString(Object obj, int index, Fields fields) { + protected static String getFieldString(Object obj, int index, Fields fields) { Object value = fields.get(obj, index); Class type = fields.getType(index); if (value == null || type.isPrimitive() || !type.isArray()) { diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueConsumer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueConsumer.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValueConsumer.java Thu Apr 16 17:09:06 2015 +0200 @@ -32,7 +32,7 @@ * Non-modifying version of {@link ValueProcedure}. */ @FunctionalInterface -public interface ValueConsumer extends InstructionValueProcedure { +public interface ValueConsumer extends InstructionValueConsumer { /** * Iterator method to be overwritten. @@ -43,8 +43,7 @@ */ void visitValue(Value value, OperandMode mode, EnumSet flags); - default Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { + default void visitValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet flags) { visitValue(value, mode, flags); - return value; } } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java Thu Apr 16 17:01:53 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.LIRIntrospection.Values; - -/** - * Describes an operand slot for a {@link LIRInstruction}. - */ -public final class ValuePosition { - - /** - * The {@linkplain Values offsets} to the fields of the containing element (either - * {@link LIRInstruction} or {@link CompositeValue}). - */ - private final Values values; - /** - * The index into {@link #values}. - * - * @see Values#getValue(Object, int) - */ - private final int index; - /** - * The sub-index if {@link #index} points to a value array, otherwise {@link #NO_SUBINDEX}. - * - * @see Values#getDirectCount() - * @see Values#getValueArray(Object, int) - */ - private final int subIndex; - /** - * The {@link ValuePosition} of the containing {@link CompositeValue} if this value is part of a - * {@link CompositeValue}, otherwise {@link #ROOT_VALUE_POSITION}. - */ - private final ValuePosition outerPosition; - - public static final int NO_SUBINDEX = -1; - public static final ValuePosition ROOT_VALUE_POSITION = null; - - ValuePosition(Values values, int index, int subIndex, ValuePosition outerPosition) { - this.values = values; - this.index = index; - this.subIndex = subIndex; - this.outerPosition = outerPosition; - } - - /** - * @return True if the value denoted by this {@linkplain ValuePosition position} is part of a - * {@link CompositeValue}. - */ - private boolean isCompositePosition() { - return outerPosition != ROOT_VALUE_POSITION; - } - - /** - * @param inst The instruction this {@linkplain ValuePosition position} belongs to. - * @return The value denoted by this {@linkplain ValuePosition position}. - */ - public Value get(LIRInstruction inst) { - Object obj = inst; - if (isCompositePosition()) { - obj = outerPosition.get(inst); - assert obj instanceof CompositeValue : "The holder of a composite position is not a CompositeValue? " + obj; - } - if (index < values.getDirectCount()) { - return values.getValue(obj, index); - } - return values.getValueArray(obj, index)[subIndex]; - } - - /** - * Sets the value denoted by this {@linkplain ValuePosition position}. - * - * @param inst The instruction this {@linkplain ValuePosition position} belongs to. - */ - public void set(LIRInstruction inst, Value value) { - Object obj = inst; - if (isCompositePosition()) { - CompositeValue compValue = (CompositeValue) outerPosition.get(inst); - CompositeValue newCompValue = compValue.clone(); - outerPosition.set(inst, newCompValue); - obj = newCompValue; - } - if (index < values.getDirectCount()) { - values.setValue(obj, index, value); - } else { - values.getValueArray(obj, index)[subIndex] = value; - } - } - - /** - * @return The flags associated with the value denoted by this {@linkplain ValuePosition - * position}. - */ - public EnumSet getFlags() { - return values.getFlags(index); - } - - @Override - public String toString() { - String str = "(" + index + (subIndex < 0 ? "" : "/" + subIndex) + ")"; - if (isCompositePosition()) { - return outerPosition.toString() + "[" + str + "]"; - } - return str; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + index; - result = prime * result + subIndex; - result = prime * result + ((outerPosition == null) ? 0 : outerPosition.hashCode()); - result = prime * result + ((values == null) ? 0 : values.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ValuePosition other = (ValuePosition) obj; - if (index != other.index) { - return false; - } - if (subIndex != other.subIndex) { - return false; - } - if (outerPosition == null) { - if (other.outerPosition != null) { - return false; - } - } else if (!outerPosition.equals(other.outerPosition)) { - return false; - } - if (values == null) { - if (other.values != null) { - return false; - } - } else if (!values.equals(other.values)) { - return false; - } - return true; - } - -} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePositionProcedure.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePositionProcedure.java Thu Apr 16 17:01:53 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir; - -/** - * Iterator for iterating over a list of {@linkplain ValuePosition value positions}. - */ -@FunctionalInterface -public interface ValuePositionProcedure { - - /** - * Iterator method to be overwritten. This version of the iterator does not take additional - * parameters to keep the signature short. - * - * @param instruction The current instruction. - * @param position The position of the value that is iterated. - */ - void doValue(LIRInstruction instruction, ValuePosition position); -} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java Thu Apr 16 17:09:06 2015 +0200 @@ -554,7 +554,9 @@ // move target is a stack slot that is always correct, so eliminate // instruction if (Debug.isLogEnabled()) { - Debug.log("eliminating move from interval %d to %d", operandNumber(move.getInput()), operandNumber(move.getResult())); + if (Debug.isLogEnabled()) { + Debug.log("eliminating move from interval %d to %d", operandNumber(move.getInput()), operandNumber(move.getResult())); + } } // null-instructions are deleted by assignRegNum instructions.set(j, null); @@ -582,7 +584,9 @@ insertionBuffer.append(j + 1, getSpillMoveFactory().createMove(toLocation, fromLocation)); - Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); + if (Debug.isLogEnabled()) { + Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); + } } interval = interval.next; } @@ -612,7 +616,9 @@ assert temp.spillDefinitionPos() >= temp.from() : "invalid order"; assert temp.spillDefinitionPos() <= temp.from() + 2 : "only intervals defined once at their start-pos can be optimized"; - Debug.log("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos()); + if (Debug.isLogEnabled()) { + Debug.log("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos()); + } prev = temp; temp = temp.next; @@ -695,7 +701,9 @@ int operandNum = operandNumber(operand); if (!liveKill.get(operandNum)) { liveGen.set(operandNum); - Debug.log("liveGen for operand %d", operandNum); + if (Debug.isLogEnabled()) { + Debug.log("liveGen for operand %d", operandNum); + } } if (block.getLoop() != null) { intervalInLoop.setBit(operandNum, block.getLoop().getIndex()); @@ -711,7 +719,9 @@ int operandNum = operandNumber(operand); if (!liveKill.get(operandNum)) { liveGen.set(operandNum); - Debug.log("liveGen in state for operand %d", operandNum); + if (Debug.isLogEnabled()) { + Debug.log("liveGen in state for operand %d", operandNum); + } } } }; @@ -719,7 +729,9 @@ if (isVariable(operand)) { int varNum = operandNumber(operand); liveKill.set(varNum); - Debug.log("liveKill for operand %d", varNum); + if (Debug.isLogEnabled()) { + Debug.log("liveKill for operand %d", varNum); + } if (block.getLoop() != null) { intervalInLoop.setBit(varNum, block.getLoop().getIndex()); } @@ -754,8 +766,10 @@ blockSets.liveIn = new BitSet(liveSize); blockSets.liveOut = new BitSet(liveSize); - Debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen); - Debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill); + if (Debug.isLogEnabled()) { + Debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen); + Debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill); + } } } // end of block iteration @@ -845,7 +859,9 @@ liveIn.andNot(blockSets.liveKill); liveIn.or(blockSets.liveGen); - Debug.log("block %d: livein = %s, liveout = %s", block.getId(), liveIn, blockSets.liveOut); + if (Debug.isLogEnabled()) { + Debug.log("block %d: livein = %s, liveout = %s", block.getId(), liveIn, blockSets.liveOut); + } } } iterationCount++; @@ -983,7 +999,9 @@ // Register use position at even instruction id. interval.addUsePos(to & ~1, registerPriority); - Debug.log("add use: %s, from %d to %d (%s)", interval, from, to, registerPriority.name()); + if (Debug.isLogEnabled()) { + Debug.log("add use: %s, from %d to %d (%s)", interval, from, to, registerPriority.name()); + } } void addTemp(AllocatableValue operand, int tempPos, RegisterPriority registerPriority, LIRKind kind) { @@ -1000,7 +1018,9 @@ interval.addUsePos(tempPos, registerPriority); interval.addMaterializationValue(null); - Debug.log("add temp: %s tempPos %d (%s)", interval, tempPos, RegisterPriority.MustHaveRegister.name()); + if (Debug.isLogEnabled()) { + Debug.log("add temp: %s tempPos %d (%s)", interval, tempPos, RegisterPriority.MustHaveRegister.name()); + } } boolean isProcessed(Value operand) { @@ -1030,7 +1050,9 @@ // also add register priority for dead intervals interval.addRange(defPos, defPos + 1); interval.addUsePos(defPos, registerPriority); - Debug.log("Warning: def of operand %s at %d occurs without use", operand, defPos); + if (Debug.isLogEnabled()) { + Debug.log("Warning: def of operand %s at %d occurs without use", operand, defPos); + } } changeSpillDefinitionPos(interval, defPos); @@ -1040,7 +1062,9 @@ } interval.addMaterializationValue(LinearScan.getMaterializedValue(op, operand, interval)); - Debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name()); + if (Debug.isLogEnabled()) { + Debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name()); + } } /** @@ -1092,7 +1116,9 @@ assert blockForId(op.id()).getPredecessorCount() == 0 : "move from stack must be in first block"; assert isVariable(move.getResult()) : "result of move must be a variable"; - Debug.log("found move from stack slot %s to %s", slot, move.getResult()); + if (Debug.isLogEnabled()) { + Debug.log("found move from stack slot %s to %s", slot, move.getResult()); + } } Interval interval = intervalFor(move.getResult()); @@ -1116,7 +1142,9 @@ } else { from.setLocationHint(to); } - Debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber); + if (Debug.isLogEnabled()) { + Debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber); + } return registerHint; } @@ -1191,7 +1219,9 @@ for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) { assert live.get(operandNum) : "should not stop here otherwise"; AllocatableValue operand = intervalFor(operandNum).operand; - Debug.log("live in %d: %s", operandNum, operand); + if (Debug.isLogEnabled()) { + Debug.log("live in %d: %s", operandNum, operand); + } addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, LIRKind.Illegal); @@ -1220,7 +1250,9 @@ addTemp(r.asValue(), opId, RegisterPriority.None, LIRKind.Illegal); } } - Debug.log("operation destroys all caller-save registers"); + if (Debug.isLogEnabled()) { + Debug.log("operation destroys all caller-save registers"); + } } op.visitEachOutput(outputConsumer); @@ -1413,24 +1445,20 @@ Interval result = interval.getSplitChildAtOpId(opId, mode, this); if (result != null) { - Debug.log("Split child at pos %d of interval %s is %s", opId, interval, result); + if (Debug.isLogEnabled()) { + Debug.log("Split child at pos %d of interval %s is %s", opId, interval, result); + } return result; } throw new BailoutException("LinearScan: interval is null"); } - Interval intervalAtBlockBegin(AbstractBlockBase block, int operandNumber) { - return splitChildAtOpId(intervalFor(operandNumber), getFirstLirInstructionId(block), LIRInstruction.OperandMode.DEF); - } - - Interval intervalAtBlockEnd(AbstractBlockBase block, int operandNumber) { - return splitChildAtOpId(intervalFor(operandNumber), getLastLirInstructionId(block) + 1, LIRInstruction.OperandMode.DEF); - } - void resolveCollectMappings(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, MoveResolver moveResolver) { assert moveResolver.checkEmpty(); + int toBlockFirstInstructionId = getFirstLirInstructionId(toBlock); + int fromBlockLastInstructionId = getLastLirInstructionId(fromBlock) + 1; int numOperands = operandSize(); BitSet liveAtEdge = blockData.get(toBlock).liveIn; @@ -1439,8 +1467,8 @@ assert operandNum < numOperands : "live information set for not exisiting interval"; assert blockData.get(fromBlock).liveOut.get(operandNum) && blockData.get(toBlock).liveIn.get(operandNum) : "interval not live at this edge"; - Interval fromInterval = intervalAtBlockEnd(fromBlock, operandNum); - Interval toInterval = intervalAtBlockBegin(toBlock, operandNum); + Interval fromInterval = splitChildAtOpId(intervalFor(operandNum), fromBlockLastInstructionId, LIRInstruction.OperandMode.DEF); + Interval toInterval = splitChildAtOpId(intervalFor(operandNum), toBlockFirstInstructionId, LIRInstruction.OperandMode.DEF); if (fromInterval != toInterval && !fromInterval.location().equals(toInterval.location())) { // need to insert move instruction @@ -1451,7 +1479,9 @@ void resolveFindInsertPos(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, MoveResolver moveResolver) { if (fromBlock.getSuccessorCount() <= 1) { - Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); + if (Debug.isLogEnabled()) { + Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); + } List instructions = ir.getLIRforBlock(fromBlock); LIRInstruction instr = instructions.get(instructions.size() - 1); @@ -1463,7 +1493,9 @@ } } else { - Debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); + if (Debug.isLogEnabled()) { + Debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); + } if (DetailedAsserts.getValue()) { assert ir.getLIRforBlock(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label"; @@ -1508,7 +1540,9 @@ // prevent optimization of two consecutive blocks if (!blockCompleted.get(pred.getLinearScanNumber()) && !blockCompleted.get(sux.getLinearScanNumber())) { - Debug.log(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId()); + if (Debug.isLogEnabled()) { + Debug.log(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId()); + } blockCompleted.set(block.getLinearScanNumber()); @@ -1535,7 +1569,9 @@ // check for duplicate edges between the same blocks (can happen with switch // blocks) if (!alreadyResolved.get(toBlock.getLinearScanNumber())) { - Debug.log("processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId()); + if (Debug.isLogEnabled()) { + Debug.log("processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId()); + } alreadyResolved.set(toBlock.getLinearScanNumber()); @@ -1841,7 +1877,9 @@ // iterate all blocks where the interval has use positions for (AbstractBlockBase splitBlock : blocksForInterval(splitChild)) { if (dominates(defBlock, splitBlock)) { - Debug.log("Split interval %s, block %s", splitChild, splitBlock); + if (Debug.isLogEnabled()) { + Debug.log("Split interval %s, block %s", splitChild, splitBlock); + } if (spillBlock == null) { spillBlock = splitBlock; } else { @@ -1868,14 +1906,18 @@ assert firstSpillChild != null; if (!defBlock.equals(spillBlock) && spillBlock.equals(blockForId(firstSpillChild.from()))) { AbstractBlockBase dom = spillBlock.getDominator(); - Debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom); + if (Debug.isLogEnabled()) { + Debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom); + } spillBlock = dom; } if (!defBlock.equals(spillBlock)) { assert dominates(defBlock, spillBlock); betterSpillPos.increment(); - Debug.log("Better spill position found (Block %s)", spillBlock); + if (Debug.isLogEnabled()) { + Debug.log("Better spill position found (Block %s)", spillBlock); + } if (defBlock.probability() <= spillBlock.probability()) { // better spill block has the same probability -> do nothing diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java Thu Apr 16 17:09:06 2015 +0200 @@ -297,7 +297,9 @@ int optimalSplitPos = -1; if (minSplitPos == maxSplitPos) { // trivial case, no optimization of split position possible - Debug.log("min-pos and max-pos are equal, no optimization possible"); + if (Debug.isLogEnabled()) { + Debug.log("min-pos and max-pos are equal, no optimization possible"); + } optimalSplitPos = minSplitPos; } else { @@ -319,7 +321,9 @@ assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; if (minBlock == maxBlock) { // split position cannot be moved to block boundary : so split as late as possible - Debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); + if (Debug.isLogEnabled()) { + Debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); + } optimalSplitPos = maxSplitPos; } else { @@ -329,19 +333,25 @@ // as mustHaveRegister) with a hole before each definition. When the register is // needed // for the second definition : an earlier reloading is unnecessary. - Debug.log("interval has hole just before maxSplitPos, so splitting at maxSplitPos"); + if (Debug.isLogEnabled()) { + Debug.log("interval has hole just before maxSplitPos, so splitting at maxSplitPos"); + } optimalSplitPos = maxSplitPos; } else { // seach optimal block boundary between minSplitPos and maxSplitPos - Debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); + if (Debug.isLogEnabled()) { + Debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); + } if (doLoopOptimization) { // Loop optimization: if a loop-end marker is found between min- and // max-position : // then split before this loop int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, allocator.getLastLirInstructionId(minBlock) + 2); - Debug.log("loop optimization: loop end found at pos %d", loopEndPos); + if (Debug.isLogEnabled()) { + Debug.log("loop optimization: loop end found at pos %d", loopEndPos); + } assert loopEndPos > minSplitPos : "invalid order"; if (loopEndPos < maxSplitPos) { @@ -354,15 +364,22 @@ // of the interval (normally, only mustHaveRegister causes a reloading) AbstractBlockBase loopBlock = allocator.blockForId(loopEndPos); - Debug.log("interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); + if (Debug.isLogEnabled()) { + Debug.log("interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); + } assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between"; - optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, allocator.getLastLirInstructionId(loopBlock) + 2); - if (optimalSplitPos == allocator.getLastLirInstructionId(loopBlock) + 2) { + int maxSpillPos = allocator.getLastLirInstructionId(loopBlock) + 2; + optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, maxSpillPos); + if (optimalSplitPos == maxSpillPos) { optimalSplitPos = -1; - Debug.log("loop optimization not necessary"); + if (Debug.isLogEnabled()) { + Debug.log("loop optimization not necessary"); + } } else { - Debug.log("loop optimization successful"); + if (Debug.isLogEnabled()) { + Debug.log("loop optimization successful"); + } } } } @@ -374,7 +391,9 @@ } } } - Debug.log("optimal split position: %d", optimalSplitPos); + if (Debug.isLogEnabled()) { + Debug.log("optimal split position: %d", optimalSplitPos); + } return optimalSplitPos; } @@ -401,7 +420,9 @@ if (optimalSplitPos == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) { // the split position would be just before the end of the interval // . no split at all necessary - Debug.log("no split necessary because optimal split position is at end of interval"); + if (Debug.isLogEnabled()) { + Debug.log("no split necessary because optimal split position is at end of interval"); + } return; } @@ -414,7 +435,9 @@ optimalSplitPos = (optimalSplitPos - 1) | 1; } - Debug.log("splitting at position %d", optimalSplitPos); + if (Debug.isLogEnabled()) { + Debug.log("splitting at position %d", optimalSplitPos); + } assert allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 1) : "split pos must be odd when not on block boundary"; assert !allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 0) : "split pos must be even on block boundary"; @@ -472,7 +495,9 @@ if (isRegister(parent.location())) { if (parent.firstUsage(RegisterPriority.ShouldHaveRegister) == Integer.MAX_VALUE) { // parent is never used, so kick it out of its assigned register - Debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); + if (Debug.isLogEnabled()) { + Debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); + } allocator.assignSpillSlot(parent); handleSpillSlot(parent); } else { @@ -507,7 +532,9 @@ allocator.changeSpillState(spilledPart, optimalSplitPos); if (!allocator.isBlockBegin(optimalSplitPos)) { - Debug.log("inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber); + if (Debug.isLogEnabled()) { + Debug.log("inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber); + } insertMove(optimalSplitPos, interval, spilledPart); } @@ -599,7 +626,9 @@ Interval locationHint = interval.locationHint(true); if (locationHint != null && locationHint.location() != null && isRegister(locationHint.location())) { hint = asRegister(locationHint.location()); - Debug.log("hint register %d from interval %s", hint.number, locationHint); + if (Debug.isLogEnabled()) { + Debug.log("hint register %d from interval %s", hint.number, locationHint); + } } assert interval.location() == null : "register already assigned to interval"; @@ -641,7 +670,9 @@ splitPos = usePos[reg.number]; interval.assignLocation(reg.asValue(interval.kind())); - Debug.log("selected register %d", reg.number); + if (Debug.isLogEnabled()) { + Debug.log("selected register %d", reg.number); + } assert splitPos > 0 : "invalid splitPos"; if (needSplit) { @@ -710,7 +741,9 @@ int regUsePos = (reg == null ? 0 : usePos[reg.number]); if (regUsePos <= firstUsage) { - Debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); + if (Debug.isLogEnabled()) { + Debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); + } if (firstUsage <= interval.from() + 1) { String description = "cannot spill interval that is used in first instruction (possible reason: no register found) firstUsage=" + firstUsage + ", interval.from()=" + @@ -729,7 +762,9 @@ int splitPos = blockPos[reg.number]; - Debug.log("decided to use register %d", reg.number); + if (Debug.isLogEnabled()) { + Debug.log("decided to use register %d", reg.number); + } assert splitPos > 0 : "invalid splitPos"; assert needSplit || splitPos > interval.from() : "splitting interval at from"; @@ -756,7 +791,9 @@ if (isOdd(pos)) { // the current instruction is a call that blocks all registers if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) { - Debug.log("free register cannot be available because all registers blocked by following call"); + if (Debug.isLogEnabled()) { + Debug.log("free register cannot be available because all registers blocked by following call"); + } // safety check that there is really no register available assert !allocFreeRegister(interval) : "found a register for this interval"; @@ -852,7 +889,9 @@ // activating an interval that has a stack slot assigned . split it at first use // position // used for method parameters - Debug.log("interval has spill slot assigned (method parameter) . split it before first use"); + if (Debug.isLogEnabled()) { + Debug.log("interval has spill slot assigned (method parameter) . split it before first use"); + } splitStackInterval(interval); result = false; @@ -860,7 +899,9 @@ if (interval.location() == null) { // interval has not assigned register . normal allocation // (this is the normal case for most intervals) - Debug.log("normal allocation of register"); + if (Debug.isLogEnabled()) { + Debug.log("normal allocation of register"); + } // assign same spill slot to non-intersecting intervals combineSpilledIntervals(interval); @@ -884,7 +925,9 @@ assert interval.isSplitChild(); assert interval.currentSplitChild() != null; assert !interval.currentSplitChild().operand.equals(operand) : "cannot insert move between same interval"; - Debug.log("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber); + if (Debug.isLogEnabled()) { + Debug.log("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber); + } insertMove(interval.from(), interval.currentSplitChild(), interval); } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Thu Apr 16 17:09:06 2015 +0200 @@ -54,10 +54,55 @@ @Override protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { - new Marker(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build(); + new Marker(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build(); } - private static final class Marker { + /** + * Ensures that an element is only in the worklist once. + * + * @param + */ + static class UniqueWorkList> extends ArrayDeque { + private static final long serialVersionUID = 8009554570990975712L; + BitSet valid; + + public UniqueWorkList(int size) { + this.valid = new BitSet(size); + } + + @Override + public T poll() { + T result = super.poll(); + if (result != null) { + valid.set(result.getId(), false); + } + return result; + } + + @Override + public boolean add(T pred) { + if (!valid.get(pred.getId())) { + valid.set(pred.getId(), true); + return super.add(pred); + } + return false; + } + + @Override + public boolean addAll(Collection collection) { + boolean changed = false; + for (T element : collection) { + if (!valid.get(element.getId())) { + valid.set(element.getId(), true); + super.add(element); + changed = true; + } + } + return changed; + } + } + + private static final class Marker> { private final LIR lir; private final FrameMap frameMap; private final RegisterAttributes[] registerAttributes; @@ -72,16 +117,17 @@ liveOutMap = new BlockMap<>(lir.getControlFlowGraph()); } - private void build() { - Deque> worklist = new ArrayDeque<>(); + @SuppressWarnings("unchecked") + void build() { + UniqueWorkList worklist = new UniqueWorkList<>(lir.getControlFlowGraph().getBlocks().size()); for (int i = lir.getControlFlowGraph().getBlocks().size() - 1; i >= 0; i--) { - worklist.add(lir.getControlFlowGraph().getBlocks().get(i)); + worklist.add((T) lir.getControlFlowGraph().getBlocks().get(i)); } for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { liveInMap.put(block, frameMap.initReferenceMap(true)); } while (!worklist.isEmpty()) { - AbstractBlockBase block = worklist.poll(); + AbstractBlockBase block = worklist.poll(); processBlock(block, worklist); } } @@ -101,7 +147,7 @@ return false; } - private void processBlock(AbstractBlockBase block, Deque> worklist) { + private void processBlock(AbstractBlockBase block, UniqueWorkList worklist) { if (updateOutBlock(block)) { try (Indent indent = Debug.logAndIndent("handle block %s", block)) { BlockClosure closure = new BlockClosure(liveOutMap.get(block).clone()); @@ -119,14 +165,6 @@ private static final EnumSet REGISTER_FLAG_SET = EnumSet.of(OperandFlag.REG); private static final LIRKind REFERENCE_KIND = LIRKind.reference(Kind.Object); - private void forEachDestroyedCallerSavedRegister(LIRInstruction op, ValueConsumer consumer) { - if (op.destroysCallerSavedRegisters()) { - for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) { - consumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET); - } - } - } - private final class BlockClosure { private final ReferenceMap currentSet; @@ -145,50 +183,57 @@ private void processInstructionBottomUp(LIRInstruction op) { try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) { // kills - op.visitEachTemp(this::defConsumer); - op.visitEachOutput(this::defConsumer); - forEachDestroyedCallerSavedRegister(op, this::defConsumer); + + op.visitEachTemp(defConsumer); + op.visitEachOutput(defConsumer); + if (op.destroysCallerSavedRegisters()) { + for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) { + defConsumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET); + } + } // gen - values that are considered alive for this state - op.visitEachAlive(this::useConsumer); - op.visitEachState(this::useConsumer); + op.visitEachAlive(useConsumer); + op.visitEachState(useConsumer); // mark locations - op.forEachState((inst, info) -> markLocation(inst, info, this.getCurrentSet())); + op.forEachState(stateConsumer); // gen - op.visitEachInput(this::useConsumer); + op.visitEachInput(useConsumer); } } - /** - * @see InstructionValueConsumer - * @param operand - * @param mode - * @param flags - */ - private void useConsumer(Value operand, OperandMode mode, EnumSet flags) { - LIRKind kind = operand.getLIRKind(); - if (shouldProcessValue(operand) && !kind.isValue() && !kind.isDerivedReference()) { - // no need to insert values and derived reference - Debug.log("set operand: %s", operand); - frameMap.setReference(operand, currentSet); + InstructionStateProcedure stateConsumer = new InstructionStateProcedure() { + public void doState(LIRInstruction inst, LIRFrameState info) { + markLocation(inst, info, getCurrentSet()); } - } + }; - /** - * @see InstructionValueConsumer - * @param operand - * @param mode - * @param flags - */ - private void defConsumer(Value operand, OperandMode mode, EnumSet flags) { - if (shouldProcessValue(operand)) { - Debug.log("clear operand: %s", operand); - frameMap.clearReference(operand, currentSet); - } else { - assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format("Illegal PlatformKind is only allowed for TEMP mode: %s, %s", - operand, mode); + ValueConsumer useConsumer = new ValueConsumer() { + public void visitValue(Value operand, OperandMode mode, EnumSet flags) { + LIRKind kind = operand.getLIRKind(); + if (shouldProcessValue(operand) && !kind.isValue() && !kind.isDerivedReference()) { + // no need to insert values and derived reference + if (Debug.isLogEnabled()) { + Debug.log("set operand: %s", operand); + } + frameMap.setReference(operand, currentSet); + } } - } + }; + + ValueConsumer defConsumer = new ValueConsumer() { + public void visitValue(Value operand, OperandMode mode, EnumSet flags) { + if (shouldProcessValue(operand)) { + if (Debug.isLogEnabled()) { + Debug.log("clear operand: %s", operand); + } + frameMap.clearReference(operand, currentSet); + } else { + assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format( + "Illegal PlatformKind is only allowed for TEMP mode: %s, %s", operand, mode); + } + } + }; protected boolean shouldProcessValue(Value operand) { return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/MoveResolver.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/MoveResolver.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/MoveResolver.java Thu Apr 16 17:09:06 2015 +0200 @@ -206,7 +206,9 @@ insertionBuffer.append(insertIdx, allocator.getSpillMoveFactory().createMove(toOpr, fromOpr)); - Debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); + if (Debug.isLogEnabled()) { + Debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); + } } private void insertMove(Value fromOpr, Interval toInterval) { @@ -216,7 +218,9 @@ AllocatableValue toOpr = toInterval.operand; insertionBuffer.append(insertIdx, allocator.getSpillMoveFactory().createMove(toOpr, fromOpr)); - Debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); + if (Debug.isLogEnabled()) { + Debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); + } } private void resolveMappings() { @@ -286,7 +290,9 @@ } spillInterval.assignLocation(spillSlot); - Debug.log("created new Interval for spilling: %s", spillInterval); + if (Debug.isLogEnabled()) { + Debug.log("created new Interval for spilling: %s", spillInterval); + } // insert a move from register to stack and update the mapping insertMove(fromInterval, spillInterval); @@ -328,7 +334,9 @@ void addMapping(Interval fromInterval, Interval toInterval) { if (isIllegal(toInterval.location()) && toInterval.canMaterialize()) { - Debug.log("no store to rematerializable interval %s needed", toInterval); + if (Debug.isLogEnabled()) { + Debug.log("no store to rematerializable interval %s needed", toInterval); + } return; } if (isIllegal(fromInterval.location()) && fromInterval.canMaterialize()) { @@ -337,7 +345,9 @@ addMapping(rematValue, toInterval); return; } - Debug.log("add move mapping from %s to %s", fromInterval, toInterval); + if (Debug.isLogEnabled()) { + Debug.log("add move mapping from %s to %s", fromInterval, toInterval); + } assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; assert fromInterval.kind().equals(toInterval.kind()); @@ -347,7 +357,9 @@ } void addMapping(Value fromOpr, Interval toInterval) { - Debug.log("add move mapping from %s to %s", fromOpr, toInterval); + if (Debug.isLogEnabled()) { + Debug.log("add move mapping from %s to %s", fromOpr, toInterval); + } assert isConstant(fromOpr) : "only for constants"; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java Thu Apr 16 17:09:06 2015 +0200 @@ -214,8 +214,8 @@ // set instruction id to the index in the lir instruction list inst.setId(opId++); inst.visitEachOutput(loadConsumer); - inst.forEachInput(useConsumer); - inst.forEachAlive(useConsumer); + inst.visitEachInput(useConsumer); + inst.visitEachAlive(useConsumer); } } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java Thu Apr 16 17:09:06 2015 +0200 @@ -161,7 +161,11 @@ } public void markBlocks() { - stream(Flags.USAGE).forEach(block -> setDominatorPath(Flags.SUBTREE, block)); + for (AbstractBlockBase block : getBlocks()) { + if (get(Flags.USAGE, block)) { + setDominatorPath(Flags.SUBTREE, block); + } + } } public boolean isMarked(AbstractBlockBase block) { @@ -169,7 +173,12 @@ } public boolean isLeafBlock(AbstractBlockBase block) { - return block.getDominated().stream().noneMatch(this::isMarked); + for (AbstractBlockBase dom : block.getDominated()) { + if (isMarked(dom)) { + return false; + } + } + return true; } public void setSolution(AbstractBlockBase block) { diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/FixPointIntervalBuilder.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/FixPointIntervalBuilder.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/FixPointIntervalBuilder.java Thu Apr 16 17:09:06 2015 +0200 @@ -172,55 +172,42 @@ private void processInstructionBottomUp(LIRInstruction op) { try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) { // kills - op.visitEachTemp(this::defConsumer); - op.visitEachOutput(this::defConsumer); + op.visitEachTemp(defConsumer); + op.visitEachOutput(defConsumer); // gen - values that are considered alive for this state - op.visitEachAlive(this::useConsumer); - op.visitEachState(this::useConsumer); + op.visitEachAlive(useConsumer); + op.visitEachState(useConsumer); // mark locations // gen - op.visitEachInput(this::useConsumer); + op.visitEachInput(useConsumer); } } - /** - * @see InstructionValueConsumer - * - * @param inst - * @param operand - * @param mode - * @param flags - */ - private void useConsumer(LIRInstruction inst, Value operand, OperandMode mode, EnumSet flags) { - if (isVirtualStackSlot(operand)) { - VirtualStackSlot vslot = asVirtualStackSlot(operand); - addUse(vslot, inst, flags); - usePos.add(inst); - Debug.log("set operand: %s", operand); - currentSet.set(vslot.getId()); + InstructionValueConsumer useConsumer = new InstructionValueConsumer() { + public void visitValue(LIRInstruction inst, Value operand, OperandMode mode, EnumSet flags) { + if (isVirtualStackSlot(operand)) { + VirtualStackSlot vslot = asVirtualStackSlot(operand); + addUse(vslot, inst, flags); + usePos.add(inst); + Debug.log("set operand: %s", operand); + currentSet.set(vslot.getId()); + } } - } + }; - /** - * - * @see InstructionValueConsumer - * - * @param inst - * @param operand - * @param mode - * @param flags - */ - private void defConsumer(LIRInstruction inst, Value operand, OperandMode mode, EnumSet flags) { - if (isVirtualStackSlot(operand)) { - VirtualStackSlot vslot = asVirtualStackSlot(operand); - addDef(vslot, inst); - usePos.add(inst); - Debug.log("clear operand: %s", operand); - currentSet.clear(vslot.getId()); + InstructionValueConsumer defConsumer = new InstructionValueConsumer() { + public void visitValue(LIRInstruction inst, Value operand, OperandMode mode, EnumSet flags) { + if (isVirtualStackSlot(operand)) { + VirtualStackSlot vslot = asVirtualStackSlot(operand); + addDef(vslot, inst); + usePos.add(inst); + Debug.log("clear operand: %s", operand); + currentSet.clear(vslot.getId()); + } + } - - } + }; private void addUse(VirtualStackSlot stackSlot, LIRInstruction inst, EnumSet flags) { StackInterval interval = getOrCreateInterval(stackSlot); diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java Thu Apr 16 17:09:06 2015 +0200 @@ -363,30 +363,26 @@ private void assignStackSlots(Set usePos) { for (LIRInstruction op : usePos) { - op.forEachInput(this::assignSlot); - op.forEachAlive(this::assignSlot); - op.forEachState(this::assignSlot); + op.forEachInput(assignSlot); + op.forEachAlive(assignSlot); + op.forEachState(assignSlot); - op.forEachTemp(this::assignSlot); - op.forEachOutput(this::assignSlot); + op.forEachTemp(assignSlot); + op.forEachOutput(assignSlot); } } - /** - * @see ValueProcedure - * @param value - * @param mode - * @param flags - */ - private Value assignSlot(Value value, OperandMode mode, EnumSet flags) { - if (isVirtualStackSlot(value)) { - VirtualStackSlot slot = asVirtualStackSlot(value); - StackInterval interval = get(slot); - assert interval != null; - return interval.location(); + ValueProcedure assignSlot = new ValueProcedure() { + public Value doValue(Value value, OperandMode mode, EnumSet flags) { + if (isVirtualStackSlot(value)) { + VirtualStackSlot slot = asVirtualStackSlot(value); + StackInterval interval = get(slot); + assert interval != null; + return interval.location(); + } + return value; } - return value; - } + }; // ==================== // diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Thu Apr 16 17:09:06 2015 +0200 @@ -252,11 +252,12 @@ public final void decode(StructuredGraph graph, EncodedGraph encodedGraph) { MethodScope methodScope = new MethodScope(graph, encodedGraph, LoopExplosionKind.NONE); decode(methodScope, null); - cleanupGraph(methodScope); + cleanupGraph(methodScope, null); methodScope.graph.verify(); } protected final void decode(MethodScope methodScope, FixedWithNextNode startNode) { + Graph.Mark start = methodScope.graph.getMark(); LoopScope loopScope = new LoopScope(methodScope); FixedNode firstNode; if (startNode != null) { @@ -284,9 +285,14 @@ } if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { - cleanupGraph(methodScope); + /* + * The startNode can get deleted during graph cleanup, so we use its predecessor (if + * available) as the starting point for loop detection. + */ + FixedNode detectLoopsStart = startNode.predecessor() != null ? (FixedNode) startNode.predecessor() : startNode; + cleanupGraph(methodScope, start); Debug.dump(methodScope.graph, "Before loop detection"); - detectLoops(methodScope.graph, firstNode); + detectLoops(methodScope.graph, detectLoopsStart); } } @@ -1111,18 +1117,21 @@ } } - protected void cleanupGraph(MethodScope methodScope) { + protected void cleanupGraph(MethodScope methodScope, Graph.Mark start) { assert verifyEdges(methodScope); Debug.dump(methodScope.graph, "Before removing redundant merges"); - for (MergeNode mergeNode : methodScope.graph.getNodes(MergeNode.TYPE)) { - if (mergeNode.forwardEndCount() == 1) { - methodScope.graph.reduceTrivialMerge(mergeNode); + for (Node node : methodScope.graph.getNewNodes(start)) { + if (node instanceof MergeNode) { + MergeNode mergeNode = (MergeNode) node; + if (mergeNode.forwardEndCount() == 1) { + methodScope.graph.reduceTrivialMerge(mergeNode); + } } } Debug.dump(methodScope.graph, "Before removing redundant begins"); - for (Node node : methodScope.graph.getNodes()) { + for (Node node : methodScope.graph.getNewNodes(start)) { if (node instanceof BeginNode || node instanceof KillingBeginNode) { if (!(node.predecessor() instanceof ControlSplitNode) && node.hasNoUsages()) { GraphUtil.unlinkFixedNode((AbstractBeginNode) node); @@ -1132,7 +1141,7 @@ } Debug.dump(methodScope.graph, "Before removing unused non-fixed nodes"); - for (Node node : methodScope.graph.getNodes()) { + for (Node node : methodScope.graph.getNewNodes(start)) { if (!(node instanceof FixedNode) && node.hasNoUsages()) { GraphUtil.killCFG(node); } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Thu Apr 16 17:09:06 2015 +0200 @@ -35,8 +35,8 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -@NodeInfo(allowedUsageTypes = {InputType.Extension}) -public final class MemoryMapNode extends FloatingNode implements MemoryMap, LIRLowerable { +@NodeInfo(allowedUsageTypes = {InputType.Extension, InputType.Memory}) +public final class MemoryMapNode extends FloatingNode implements MemoryMap, MemoryNode, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(MemoryMapNode.class); protected final List locationIdentities; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.output --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.output Thu Apr 16 17:09:06 2015 +0200 @@ -0,0 +1,2 @@ +[deoptimizeWhenCompiled] +[deoptimizeWhenCompiled] diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.sl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/sl/TestDeoptInInlinedFunction.sl Thu Apr 16 17:09:06 2015 +0200 @@ -0,0 +1,21 @@ +/* + * This tests that simple arithmetic gets inlined. + */ +function add(a, b) { + deoptimizeWhenCompiled(a == 50); + return a + b; +} + + +function test() { + i = 0; + while (i < 100) { + i = add(i, 1); + } + return i; +} + +function main() { + waitForOptimization(callUntilOptimized(test, 1 == 2)); + test(); +} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SLTruffleGraalTestSuite.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SLTruffleGraalTestSuite.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SLTruffleGraalTestSuite.java Thu Apr 16 17:09:06 2015 +0200 @@ -49,6 +49,7 @@ SLTestRunner.installBuiltin(SLGenerateDummyNodesBuiltinFactory.getInstance()); SLTestRunner.installBuiltin(SLCallFunctionsWithBuiltinFactory.getInstance()); SLTestRunner.installBuiltin(SLIsCompilationConstantBuiltinFactory.getInstance()); + SLTestRunner.installBuiltin(SLDeoptimizeWhenCompiledBuiltinFactory.getInstance()); /* test specific builtins */ SLTestRunner.installBuiltin(SLTestTruffleBoundary01BuiltinFactory.getInstance()); diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLCallUntilOptimizedBuiltin.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLCallUntilOptimizedBuiltin.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLCallUntilOptimizedBuiltin.java Thu Apr 16 17:09:06 2015 +0200 @@ -49,7 +49,12 @@ @Child private IndirectCallNode indirectCall = Truffle.getRuntime().createIndirectCallNode(); @Specialization - public SLFunction callUntilCompiled(VirtualFrame frame, SLFunction function) { + public SLFunction callUntilCompiled(VirtualFrame frame, SLFunction function, @SuppressWarnings("unused") SLNull checkTarget) { + return callUntilCompiled(frame, function, false); + } + + @Specialization + public SLFunction callUntilCompiled(VirtualFrame frame, SLFunction function, boolean checkTarget) { OptimizedCallTarget target = ((OptimizedCallTarget) function.getCallTarget()); for (int i = 0; i < MAX_CALLS; i++) { if (isCompiling(target)) { @@ -63,7 +68,9 @@ // call one more in compiled indirectCall.call(frame, target, EMPTY_ARGS); - checkTarget(target); + if (checkTarget) { + checkTarget(target); + } return function; } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDeoptimizeWhenCompiledBuiltin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLDeoptimizeWhenCompiledBuiltin.java Thu Apr 16 17:09:06 2015 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, 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.truffle.test.builtins; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * Forces a deoptimization as soon as the method runs in compiled code. + */ +@NodeInfo(shortName = "deoptimizeWhenCompiled") +public abstract class SLDeoptimizeWhenCompiledBuiltin extends SLGraalRuntimeBuiltin { + + @Specialization + public SLNull deoptimzeWhenCompiled(boolean condition) { + if (CompilerDirectives.inCompiledCode()) { + if (condition) { + printMessage(); + CompilerDirectives.transferToInterpreterAndInvalidate(); + } + } + return SLNull.SINGLETON; + } + + @TruffleBoundary + private void printMessage() { + getContext().getOutput().println("[deoptimizeWhenCompiled]"); + } +} diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java Thu Apr 16 17:09:06 2015 +0200 @@ -128,9 +128,11 @@ protected class PENonAppendGraphBuilderContext implements GraphBuilderContext { protected final PEMethodScope methodScope; + protected final Invoke invoke; - public PENonAppendGraphBuilderContext(PEMethodScope methodScope) { + public PENonAppendGraphBuilderContext(PEMethodScope methodScope, Invoke invoke) { this.methodScope = methodScope; + this.invoke = invoke; } @Override @@ -210,7 +212,7 @@ @Override public int bci() { - throw unimplemented(); + return invoke.bci(); } @Override @@ -228,8 +230,8 @@ protected FixedWithNextNode lastInstr; protected ValueNode pushedNode; - public PEAppendGraphBuilderContext(PEMethodScope methodScope, FixedWithNextNode lastInstr) { - super(methodScope); + public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr) { + super(inlineScope, inlineScope.invokeData.invoke); this.lastInstr = lastInstr; } @@ -319,14 +321,14 @@ PEMethodScope methodScope = new PEMethodScope(targetGraph, null, null, lookupEncodedGraph(method), method, null, 0, loopExplosionPlugin, invocationPlugins, inlineInvokePlugin, parameterPlugin, null); decode(methodScope, null); - cleanupGraph(methodScope); + cleanupGraph(methodScope, null); methodScope.graph.verify(); } @Override - protected void cleanupGraph(MethodScope methodScope) { + protected void cleanupGraph(MethodScope methodScope, Graph.Mark start) { GraphBuilderPhase.connectLoopEndToBegin(methodScope.graph); - super.cleanupGraph(methodScope); + super.cleanupGraph(methodScope, start); } @Override @@ -378,7 +380,7 @@ } if (methodScope.inlineInvokePlugin != null) { - methodScope.inlineInvokePlugin.notifyOfNoninlinedInvoke(new PENonAppendGraphBuilderContext(methodScope), callTarget.targetMethod(), invokeData.invoke); + methodScope.inlineInvokePlugin.notifyOfNoninlinedInvoke(new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke), callTarget.targetMethod(), invokeData.invoke); } return false; } @@ -439,7 +441,7 @@ } ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]); - GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope); + GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke); InlineInfo inlineInfo = methodScope.inlineInvokePlugin.getInlineInfo(graphBuilderContext, targetMethod, arguments, callTarget.returnType()); if (inlineInfo == null) { return false; @@ -619,7 +621,7 @@ return result; } else if (methodScope.parameterPlugin != null) { - GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope); + GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, null); Node result = methodScope.parameterPlugin.interceptParameter(graphBuilderContext, ((ParameterNode) node).index(), ((ParameterNode) node).stamp()); if (result != null) { return result; @@ -657,7 +659,11 @@ Kind invokeReturnKind = methodScope.invokeData.invoke.asNode().getKind(); FrameState outerState = stateAtReturn.duplicateModified(methodScope.graph, methodScope.invokeData.invoke.bci(), stateAtReturn.rethrowException(), true, invokeReturnKind); - if (methodScope.caller != null) { + /* + * When the encoded graph has methods inlining, we can already have a proper caller + * state. If not, we set the caller state here. + */ + if (outerState.outerFrameState() == null && methodScope.caller != null) { ensureOuterStateDecoded(methodScope.caller); outerState.setOuterFrameState(methodScope.caller.outerState); } @@ -680,7 +686,7 @@ registerNode(methodScope.callerLoopScope, methodScope.invokeData.exceptionOrderId, methodScope.exceptionPlaceholderNode, false, false); FrameState exceptionState = (FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.exceptionStateOrderId); - if (methodScope.caller != null) { + if (exceptionState.outerFrameState() == null && methodScope.caller != null) { ensureOuterStateDecoded(methodScope.caller); exceptionState.setOuterFrameState(methodScope.caller.outerState); } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Apr 16 17:09:06 2015 +0200 @@ -184,7 +184,9 @@ if (original.getAnnotation(TruffleBoundary.class) != null) { return null; } - assert !replacements.hasSubstitution(original, builder.bci()) : "Replacements must have been processed by now"; + if (replacements.hasSubstitution(original, builder.bci())) { + return null; + } assert !builder.parsingReplacement(); if (TruffleCompilerOptions.TruffleFunctionInlining.getValue()) { @@ -260,7 +262,9 @@ if (original.getAnnotation(TruffleBoundary.class) != null) { return null; } - assert !replacements.hasSubstitution(original, builder.bci()) : "Replacements must have been processed by now"; + if (replacements.hasSubstitution(original, builder.bci())) { + return null; + } if (original.equals(callSiteProxyMethod) || original.equals(callDirectMethod)) { return null; @@ -337,7 +341,7 @@ ParameterPlugin parameterPlugin = new InterceptReceiverPlugin(callTarget); - InvocationPlugins decodingInvocationPlugins = new InvocationPlugins(parsingInvocationPlugins.getParent()); + InvocationPlugins decodingInvocationPlugins = new InvocationPlugins(providers.getMetaAccess()); TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), decodingInvocationPlugins, false, snippetReflection); InlineInvokePlugin decodingInlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), (ReplacementsImpl) providers.getReplacements()); if (PrintTruffleExpansionHistogram.getValue()) { diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Thu Apr 16 17:09:06 2015 +0200 @@ -95,14 +95,9 @@ ResolvedJavaType[] skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess()); GraphBuilderPhase phase = (GraphBuilderPhase) backend.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous(); - Plugins graalPlugins = phase.getGraphBuilderConfig().getPlugins(); - InvocationPlugins invocationPlugins = new InvocationPlugins(graalPlugins.getInvocationPlugins()); - Plugins plugins = new Plugins(invocationPlugins); + // copy all plugins from the host + Plugins plugins = new Plugins(phase.getGraphBuilderConfig().getPlugins()); this.config = GraphBuilderConfiguration.getDefault(plugins).withSkippedExceptionTypes(skippedExceptionTypes); - // Since invocationPlugins may include MethodSubstitutionPlugins, we - // need to copy the GenericInvocationPlugins so that @NodeIntrinsics - // and Word methods in method substitutions are handled correctly. - plugins.setGenericInvocationPlugin(graalPlugins.getGenericInvocationPlugin()); this.partialEvaluator = new PartialEvaluator(providers, config, Graal.getRequiredCapability(SnippetReflectionProvider.class)); diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java Thu Apr 16 17:09:06 2015 +0200 @@ -287,4 +287,51 @@ } } + @SuppressWarnings("unused") + @NodeChildren({@NodeChild(value = "a", type = ValueNode.class), @NodeChild(value = "b", type = ValueNode.class)}) + abstract static class TestEvaluatedShortCircuit1 extends Node { + + public abstract Object execute1(VirtualFrame frame, Object value); + + public abstract Object execute2(VirtualFrame frame, Object value, boolean hasB); + + public abstract Object execute3(VirtualFrame frame, Object value, boolean hasB, Object b); + + @ShortCircuit("b") + public boolean needsB(Object a) { + return true; + } + + @Specialization + int call(Object a, boolean hasB, Object b) { + return 42; + } + } + + @SuppressWarnings("unused") + @NodeChildren({@NodeChild(value = "a", type = ValueNode.class), @NodeChild(value = "b", type = ValueNode.class)}) + abstract static class TestEvaluatedShortCircuit2 extends Node { + + public abstract Object execute1(VirtualFrame frame, Object value); + + public abstract Object execute2(VirtualFrame frame, Object value, boolean hasB); + + public abstract Object execute3(VirtualFrame frame, Object value, boolean hasB, Object b); + + @ShortCircuit("b") + public boolean needsB(Object a) { + return true; + } + + @Specialization + int call(int a, boolean hasB, int b) { + return 42; + } + + @Specialization + int call(Object a, boolean hasB, Object b) { + return 42; + } + } + } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteGroupingTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteGroupingTest.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteGroupingTest.java Thu Apr 16 17:09:06 2015 +0200 @@ -144,18 +144,18 @@ } @Specialization(rewriteOn = RuntimeException.class) - int s1() { + double s1() { return 42; } @Specialization - int s2() { + double s2() { return 42; } } - @ExpectError("Incompatible abstract execute methods found [executeDouble(), executeInt()].%") + @ExpectError("Incompatible abstract execute methods found %") abstract static class IncompatibleAbstract1 extends Node { // we don't know how to implement executeDouble @@ -164,7 +164,7 @@ abstract int executeInt(); @Specialization - int s1() { + double s1() { return 42; } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Thu Apr 16 17:09:06 2015 +0200 @@ -66,7 +66,9 @@ private final boolean singleSpecializable; private final int varArgsThreshold; private final Set expectedTypes = new HashSet<>(); + private final Set usedExecuteChildMethods = new HashSet<>(); private boolean nextUsed; + private List usedTypes; private List reachableSpecializations; @@ -210,7 +212,7 @@ } for (ExecutableTypeData execType : usedTypes) { - if (execType.getMethod() == null) { + if (!singleSpecializable && execType.getMethod() == null) { continue; } clazz.add(createExecutableTypeOverride(usedTypes, execType)); @@ -273,7 +275,7 @@ private Element createUnsupportedMethod() { LocalContext locals = LocalContext.load(this); - CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED), getType(UnsupportedSpecializationException.class), "unsupported"); + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED), getType(UnsupportedSpecializationException.class), "unsupported", varArgsThreshold); CodeTreeBuilder builder = method.createBuilder(); builder.startReturn(); @@ -380,6 +382,16 @@ baseSpecialization.addOptional(createCreatePolymorphic(generated)); baseSpecialization.addOptional(createGetNext(baseSpecialization)); + for (NodeExecutionData execution : node.getChildExecutions()) { + Collection specializedTypes = node.findSpecializedTypes(execution); + specializedTypes.add(genericType); + for (TypeMirror specializedType : specializedTypes) { + if (isExecuteChildShared(execution, specializedType)) { + baseSpecialization.addOptional(createExecuteChildMethod(execution, specializedType)); + } + } + } + return node.getUninitializedSpecialization(); } @@ -418,28 +430,13 @@ clazz.add(createFastPathExecuteMethod(null, type, usedTypes)); } - for (NodeExecutionData execution : node.getChildExecutions()) { - Collection specializedTypes = node.findSpecializedTypes(execution); - specializedTypes.add(genericType); - for (TypeMirror specializedType : specializedTypes) { - if (isExecuteChildShared(execution, specializedType)) { - clazz.add(createExecuteChildMethod(execution, specializedType)); - } - } - } - return clazz; } private Element createAcceptAndExecute() { - - TypeMirror[] parameters = new TypeMirror[node.getSignatureSize()]; - Arrays.fill(parameters, genericType); - - ExecutableTypeData executableElement = new ExecutableTypeData(genericType, "acceptAndExecute", context.getType(Frame.class), Arrays.asList(parameters)); - - LocalContext currentLocals = LocalContext.load(this, node.getSignatureSize(), varArgsThreshold); - CodeExecutableElement executable = createExecuteMethod(null, executableElement, currentLocals, false); + ExecutableTypeData executableElement = createSpecializationNodeSignature(node.getSignatureSize()); + LocalContext currentLocals = LocalContext.load(this, executableElement, varArgsThreshold); + CodeExecutableElement executable = createExecuteMethod(null, executableElement, currentLocals, false, varArgsThreshold); executable.getModifiers().add(FINAL); CodeTreeBuilder builder = executable.createBuilder(); @@ -451,6 +448,12 @@ return executable; } + private ExecutableTypeData createSpecializationNodeSignature(int argumentCount) { + TypeMirror[] parameters = new TypeMirror[argumentCount]; + Arrays.fill(parameters, genericType); + return new ExecutableTypeData(node, genericType, "acceptAndExecute", context.getType(Frame.class), Arrays.asList(parameters)); + } + private boolean shouldImplementExecutableType(SpecializationData specialization, ExecutableTypeData executableType) { // always implement the root execute method. they are declared abstract in the base node. if (executableType.getDelegatedTo() == null) { @@ -458,7 +461,7 @@ } // specializations with more parameters are just ignored - if (executableType.getEvaluatedCount() > node.getSignatureSize()) { + if (executableType.getEvaluatedCount() > node.getExecutionCount()) { return false; } @@ -468,8 +471,9 @@ // the evaluated signature might be compatible to the specialization boolean specializationCompatible = true; - for (int i = 0; i < executableType.getEvaluatedCount(); i++) { - TypeMirror evaluatedType = executableType.getEvaluatedParameters().get(i); + List signatureParameters = executableType.getSignatureParameters(); + for (int i = 0; i < signatureParameters.size(); i++) { + TypeMirror evaluatedType = signatureParameters.get(i); TypeMirror specializedType = specialization.findParameterOrDie(node.getChildExecutions().get(i)).getType(); if (!isSubtypeBoxed(context, evaluatedType, specializedType) && !isSubtypeBoxed(context, specializedType, evaluatedType)) { @@ -489,7 +493,7 @@ } // trigger type boxing elimination for unevaluated arguments - for (int i = executableType.getEvaluatedCount(); i < node.getSignatureSize(); i++) { + for (int i = executableType.getEvaluatedCount(); i < node.getExecutionCount(); i++) { NodeExecutionData execution = node.getChildExecutions().get(i); TypeMirror specializedType = specialization.findParameterOrDie(execution).getType(); if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), specializedType)) { @@ -512,8 +516,8 @@ } // trigger generation for evaluated assignable type matches other than generic - for (int i = 0; i < executableType.getEvaluatedCount(); i++) { - TypeMirror evaluatedType = executableType.getEvaluatedParameters().get(i); + for (int i = 0; i < signatureParameters.size(); i++) { + TypeMirror evaluatedType = signatureParameters.get(i); NodeExecutionData execution = node.getChildExecutions().get(i); TypeMirror specializedType = specialization.findParameterOrDie(execution).getType(); @@ -664,12 +668,12 @@ return null; } - LocalContext currentLocals = LocalContext.load(this, node.getSignatureSize(), varArgsThreshold); + LocalContext currentLocals = LocalContext.load(this, createSpecializationNodeSignature(node.getSignatureSize()), varArgsThreshold); currentLocals.loadFastPathState(specialization); CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isIdentical"); method.addParameter(new CodeVariableElement(getType(SpecializationNode.class), "other")); - currentLocals.addParametersTo(method, FRAME_VALUE); + currentLocals.addParametersTo(method, varArgsThreshold, FRAME_VALUE); method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); final CodeTreeBuilder builder = method.createBuilder(); @@ -729,11 +733,11 @@ return null; } TypeMirror specializationNodeType = getType(SpecializationNode.class); - LocalContext currentLocals = LocalContext.load(this, node.getSignatureSize(), varArgsThreshold); + LocalContext currentLocals = LocalContext.load(this, createSpecializationNodeSignature(node.getSignatureSize()), varArgsThreshold); CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), specializationNodeType, "merge"); executable.addParameter(new CodeVariableElement(specializationNodeType, "newNode")); - currentLocals.addParametersTo(executable, FRAME_VALUE); + currentLocals.addParametersTo(executable, varArgsThreshold, FRAME_VALUE); executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = executable.createBuilder(); @@ -802,7 +806,7 @@ private CodeExecutableElement createCreateNext(final Map specializationClasses) { final LocalContext locals = LocalContext.load(this); - CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), getType(SpecializationNode.class), "createNext", FRAME_VALUE); + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), getType(SpecializationNode.class), "createNext", varArgsThreshold, FRAME_VALUE); method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = method.createBuilder(); @@ -834,7 +838,7 @@ locals.removeValue(FRAME_VALUE); } - CodeExecutableElement boundaryMethod = locals.createMethod(modifiers(PRIVATE), getType(boolean.class), "guardFallback", FRAME_VALUE); + CodeExecutableElement boundaryMethod = locals.createMethod(modifiers(PRIVATE), getType(boolean.class), "guardFallback", varArgsThreshold, FRAME_VALUE); if (!frameUsed) { boundaryMethod.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(TruffleBoundary.class))); } @@ -887,7 +891,7 @@ } LocalContext locals = LocalContext.load(this); - CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", FRAME_VALUE); + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", varArgsThreshold, FRAME_VALUE); method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class))); CodeTreeBuilder builder = method.createBuilder(); @@ -950,8 +954,8 @@ } private CodeExecutableElement createExecutableTypeOverride(List usedExecutables, ExecutableTypeData execType) { - LocalContext locals = LocalContext.load(this, execType.getEvaluatedCount(), Integer.MAX_VALUE); - CodeExecutableElement method = createExecuteMethod(null, execType, locals, true); + LocalContext locals = LocalContext.load(this, execType, Integer.MAX_VALUE); + CodeExecutableElement method = createExecuteMethod(null, execType, locals, true, Integer.MAX_VALUE); CodeTreeBuilder builder = method.createBuilder(); if (singleSpecializable) { @@ -1043,17 +1047,38 @@ values.add(createTypeSafeReference(frameLocal, method.getFrameParameter())); } } - for (int parameterIndex = 0; parameterIndex < method.getEvaluatedCount(); parameterIndex++) { - TypeMirror targetParameter = method.getEvaluatedParameters().get(parameterIndex); - LocalVariable variable; - if (executeWith != null && parameterIndex < executeWith.size()) { - variable = currentValues.getValue(executeWith.get(parameterIndex)); + + int evaluatedIndex = 0; + for (int executionIndex = 0; executionIndex < node.getExecutionCount(); executionIndex++) { + NodeExecutionData parameterExecution; + if (executeWith != null && executionIndex < executeWith.size()) { + parameterExecution = executeWith.get(executionIndex); } else { - variable = currentValues.getValue(parameterIndex); + parameterExecution = node.getChildExecutions().get(executionIndex); } - values.add(createTypeSafeReference(variable, targetParameter)); + if (parameterExecution.isShortCircuit()) { + if (evaluatedIndex < method.getEvaluatedCount()) { + TypeMirror targetType = method.getEvaluatedParameters().get(evaluatedIndex); + LocalVariable shortCircuit = currentValues.getShortCircuit(parameterExecution); + if (shortCircuit != null) { + values.add(createTypeSafeReference(shortCircuit, targetType)); + } else { + values.add(CodeTreeBuilder.createBuilder().defaultValue(targetType).build()); + } + evaluatedIndex++; + } + } + if (evaluatedIndex < method.getEvaluatedCount()) { + TypeMirror targetType = method.getEvaluatedParameters().get(evaluatedIndex); + LocalVariable value = currentValues.getValue(parameterExecution); + if (value != null) { + values.add(createTypeSafeReference(value, targetType)); + } else { + values.add(CodeTreeBuilder.createBuilder().defaultValue(targetType).build()); + } + evaluatedIndex++; + } } - return values.toArray(new CodeTree[values.size()]); } @@ -1518,8 +1543,11 @@ } private CodeTree expect(TypeMirror sourceType, TypeMirror forType, CodeTree tree) { - expectedTypes.add(forType); - return TypeSystemCodeGenerator.expect(typeSystem, sourceType, forType, tree); + if (sourceType == null || ElementUtils.needsCastTo(sourceType, forType)) { + expectedTypes.add(forType); + return TypeSystemCodeGenerator.expect(typeSystem, forType, tree); + } + return tree; } private Set findSpecializedExecutableTypes(NodeExecutionData execution, TypeMirror type) { @@ -1554,8 +1582,8 @@ } private Element createFastPathExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, List allTypes) { - LocalContext currentLocals = LocalContext.load(this, executedType.getEvaluatedCount(), varArgsThreshold); - CodeExecutableElement executable = createExecuteMethod(specialization, executedType, currentLocals, false); + LocalContext currentLocals = LocalContext.load(this, executedType, Integer.MAX_VALUE); + CodeExecutableElement executable = createExecuteMethod(specialization, executedType, currentLocals, false, Integer.MAX_VALUE); CodeTreeBuilder builder = executable.createBuilder(); if (specialization == null) { if (executedType.getDelegatedTo() == null) { @@ -1569,28 +1597,17 @@ return executable; } - private CodeExecutableElement createExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, LocalContext currentLocals, boolean originalOverride) { + private static final String VARARGS_NAME = "args"; + + private CodeExecutableElement createExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, LocalContext currentLocals, boolean originalOverride, int varArgs) { TypeMirror returnType = executedType.getReturnType(); - TypeMirror frame = executedType.getFrameParameter(); - List evaluatedParameters = executedType.getEvaluatedParameters(); if (specialization != null) { currentLocals.loadFastPathState(specialization); } - if (frame == null) { - currentLocals.removeValue(FRAME_VALUE); - } else { - currentLocals.set(FRAME_VALUE, currentLocals.get(FRAME_VALUE).newType(frame)); - } - - for (int i = 0; i < Math.min(node.getChildExecutions().size(), evaluatedParameters.size()); i++) { - NodeExecutionData execution = node.getChildExecutions().get(i); - currentLocals.setValue(execution, currentLocals.getValue(execution).newType(evaluatedParameters.get(i))); - } - String methodName; - if (originalOverride) { + if (originalOverride && executedType.getMethod() != null) { methodName = executedType.getMethod().getSimpleName().toString(); } else { methodName = executedType.getUniqueName(); @@ -1608,32 +1625,13 @@ ((CodeVariableElement) executable.getParameters().get(0)).setName(FRAME_VALUE); } - final String varArgsName = "args"; if (executable.isVarArgs()) { - ((CodeVariableElement) executable.getParameters().get(executable.getParameters().size() - 1)).setName(varArgsName); + ((CodeVariableElement) executable.getParameters().get(executable.getParameters().size() - 1)).setName(VARARGS_NAME); } - // rename varargs parameter - int signatureIndex = 0; - for (TypeMirror parameter : executedType.getEvaluatedParameters()) { - LocalVariable var = currentLocals.getValue(signatureIndex); - if (var != null) { - int varArgsIndex = executedType.getVarArgsIndex(executedType.getParameterIndex(signatureIndex)); - if (varArgsIndex >= 0) { - var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + varArgsIndex + "]")); - } else { - ((CodeVariableElement) executable.getParameters().get(executedType.getParameterIndex(signatureIndex))).setName(var.getName()); - } - if (!isObject(parameter)) { - var = var.newType(parameter); - } - currentLocals.setValue(node.getChildExecutions().get(signatureIndex), var); - } - - signatureIndex++; - } + renameOriginalParameters(executedType, executable, currentLocals); } else { - executable = currentLocals.createMethod(modifiers(PUBLIC), returnType, methodName, FRAME_VALUE); + executable = currentLocals.createMethod(modifiers(PUBLIC), returnType, methodName, varArgs, FRAME_VALUE); } executable.getThrownTypes().clear(); @@ -1644,6 +1642,47 @@ return executable; } + private void renameOriginalParameters(ExecutableTypeData executedType, CodeExecutableElement executable, LocalContext currentLocals) { + // rename varargs parameter + int evaluatedIndex = 0; + for (int executionIndex = 0; executionIndex < node.getExecutionCount(); executionIndex++) { + NodeExecutionData execution = node.getChildExecutions().get(executionIndex); + if (execution.isShortCircuit()) { + if (evaluatedIndex < executedType.getEvaluatedCount()) { + TypeMirror evaluatedType = executedType.getEvaluatedParameters().get(evaluatedIndex); + LocalVariable shortCircuit = currentLocals.getShortCircuit(execution); + if (shortCircuit != null) { + currentLocals.setShortCircuitValue(execution, renameExecutableTypeParameter(executable, executedType, evaluatedIndex, evaluatedType, shortCircuit)); + } + evaluatedIndex++; + } + } + if (evaluatedIndex < executedType.getEvaluatedCount()) { + TypeMirror evaluatedType = executedType.getEvaluatedParameters().get(evaluatedIndex); + LocalVariable value = currentLocals.getValue(execution); + if (value != null) { + currentLocals.setValue(execution, renameExecutableTypeParameter(executable, executedType, evaluatedIndex, evaluatedType, value)); + } + evaluatedIndex++; + } + } + } + + private static LocalVariable renameExecutableTypeParameter(CodeExecutableElement method, ExecutableTypeData executedType, int evaluatedIndex, TypeMirror targetType, LocalVariable var) { + int parameterIndex = executedType.getParameterIndex(evaluatedIndex); + int varArgsIndex = executedType.getVarArgsIndex(parameterIndex); + LocalVariable returnVar = var; + if (varArgsIndex >= 0) { + returnVar = returnVar.accessWith(CodeTreeBuilder.singleString(VARARGS_NAME + "[" + varArgsIndex + "]")); + } else { + ((CodeVariableElement) method.getParameters().get(parameterIndex)).setName(returnVar.getName()); + } + if (!isObject(targetType)) { + returnVar = returnVar.newType(targetType); + } + return returnVar; + } + private boolean needsUnexpectedResultException(ExecutableTypeData executedType) { if (!executedType.hasUnexpectedValue(context)) { return false; @@ -1670,8 +1709,9 @@ delegate = findFastPathDelegate((specialization != null ? specialization.getReturnType().getType() : genericType), executableType, allTypes); } + int delegateSignatureCount = delegate != null ? delegate.getSignatureParameters().size() : 0; for (NodeExecutionData execution : node.getChildExecutions()) { - if (specialization == null && delegate != null && execution.getIndex() >= delegate.getEvaluatedCount()) { + if (specialization == null && delegate != null && execution.getIndex() >= delegateSignatureCount) { // we just evaluate children for the next delegate continue; } else if (specialization != null && delegate != null) { @@ -1794,15 +1834,21 @@ private LocalVariable resolveShortCircuit(SpecializationData specialization, NodeExecutionData execution, LocalContext currentLocals) { LocalVariable shortCircuit = null; - SpecializationData resolvedSpecialization = specialization; - if (specialization == null) { - resolvedSpecialization = node.getGenericSpecialization(); - } - if (execution.isShortCircuit()) { - ShortCircuitData shortCircuitData = resolvedSpecialization.getShortCircuits().get(calculateShortCircuitIndex(execution)); - CodeTree access = callTemplateMethod(accessParent(null), shortCircuitData, currentLocals); - shortCircuit = currentLocals.createShortCircuitValue(execution).accessWith(access); + shortCircuit = currentLocals.getShortCircuit(execution); + + if (shortCircuit == null) { + SpecializationData resolvedSpecialization = specialization; + if (specialization == null) { + resolvedSpecialization = node.getGenericSpecialization(); + } + ShortCircuitData shortCircuitData = resolvedSpecialization.getShortCircuits().get(calculateShortCircuitIndex(execution)); + CodeTree access = callTemplateMethod(accessParent(null), shortCircuitData, currentLocals); + shortCircuit = currentLocals.createShortCircuitValue(execution).accessWith(access); + } else { + CodeTree access = shortCircuit.createReference(); + shortCircuit = shortCircuit.nextName().accessWith(access); + } } return shortCircuit; } @@ -2016,9 +2062,13 @@ } private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeMirror targetType) { - LocalContext locals = LocalContext.load(this, 0, varArgsThreshold); - - CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), FRAME_VALUE); + if (!usedExecuteChildMethods.contains(execution)) { + return null; + } + + LocalContext locals = LocalContext.load(this, createSpecializationNodeSignature(0), Integer.MAX_VALUE); + + CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), Integer.MAX_VALUE, FRAME_VALUE); if (hasChildUnexpectedResult(execution, targetType)) { method.getThrownTypes().add(getType(UnexpectedResultException.class)); } @@ -2047,6 +2097,10 @@ private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeMirror targetType) { if (typeSystem.hasImplicitSourceTypes(targetType)) { + if (typeEquals(node.getGenericType(execution), targetType)) { + return null; + } + switch (options.implicitCastOptimization()) { case NONE: return null; @@ -2185,6 +2239,7 @@ if (!isExecuteChildShared(execution, targetValue.getTypeMirror())) { throw new AssertionError("Execute child not shared with method but called."); } + usedExecuteChildMethods.add(execution); CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); builder.tree(targetValue.createReference()).string(" = "); @@ -2594,20 +2649,59 @@ } } - public CodeExecutableElement createMethod(Set modifiers, TypeMirror returnType, String name, String... optionalArguments) { + public CodeExecutableElement createMethod(Set modifiers, TypeMirror returnType, String name, int varArgsThreshold, String... optionalArguments) { CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name); - addParametersTo(method, optionalArguments); + addParametersTo(method, varArgsThreshold, optionalArguments); return method; } - public static LocalContext load(NodeGenFactory factory, int signatureSize, int varargsThreshold) { + public static LocalContext load(NodeGenFactory factory, ExecutableTypeData type, int varargsThreshold) { LocalContext context = new LocalContext(factory); - context.loadValues(signatureSize, varargsThreshold); + context.loadEvaluatedValues(type, varargsThreshold); return context; } + private void loadEvaluatedValues(ExecutableTypeData executedType, int varargsThreshold) { + TypeMirror frame = executedType.getFrameParameter(); + if (frame == null) { + removeValue(FRAME_VALUE); + } else { + set(FRAME_VALUE, new LocalVariable(frame, FRAME_VALUE, null, null)); + } + for (NodeFieldData field : factory.node.getFields()) { + String fieldName = fieldValueName(field); + values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null)); + } + boolean varargs = needsVarargs(false, varargsThreshold); + List evaluatedParameter = executedType.getEvaluatedParameters(); + int evaluatedIndex = 0; + for (int executionIndex = 0; executionIndex < factory.node.getExecutionCount(); executionIndex++) { + NodeExecutionData execution = factory.node.getChildExecutions().get(executionIndex); + if (execution.isShortCircuit()) { + if (evaluatedIndex < executedType.getEvaluatedCount()) { + TypeMirror evaluatedType = evaluatedParameter.get(evaluatedIndex); + LocalVariable shortCircuit = createShortCircuitValue(execution).newType(evaluatedType); + if (varargs) { + shortCircuit = shortCircuit.accessWith(createReadVarargs(evaluatedIndex)); + } + values.put(shortCircuit.getName(), shortCircuit.makeOriginal()); + evaluatedIndex++; + } + } + if (evaluatedIndex < executedType.getEvaluatedCount()) { + TypeMirror evaluatedType = evaluatedParameter.get(evaluatedIndex); + LocalVariable value = createValue(execution, evaluatedType); + if (varargs) { + value = value.accessWith(createReadVarargs(evaluatedIndex)); + } + values.put(value.getName(), value.makeOriginal()); + evaluatedIndex++; + } + } + } + public static LocalContext load(NodeGenFactory factory) { - return load(factory, factory.node.getSignatureSize(), factory.varArgsThreshold); + return load(factory, factory.createSpecializationNodeSignature(factory.node.getSignatureSize()), factory.varArgsThreshold); } public LocalContext copy() { @@ -2701,36 +2795,6 @@ return size >= varArgsThreshold; } - private void loadValues(int evaluatedArguments, int varargsThreshold) { - values.put(FRAME_VALUE, new LocalVariable(factory.getType(Frame.class), FRAME_VALUE, null, null)); - - for (NodeFieldData field : factory.node.getFields()) { - String fieldName = fieldValueName(field); - values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null)); - } - - boolean varargs = needsVarargs(false, varargsThreshold); - for (int i = 0; i < evaluatedArguments; i++) { - List childExecutions = factory.node.getChildExecutions(); - if (i >= childExecutions.size()) { - break; - } - NodeExecutionData execution = childExecutions.get(i); - if (execution.isShortCircuit()) { - LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric(factory.context); - if (varargs) { - shortCircuit = shortCircuit.accessWith(createReadVarargs(i)); - } - values.put(shortCircuit.getName(), shortCircuit.makeOriginal()); - } - LocalVariable value = createValue(execution, factory.genericType); - if (varargs) { - value = value.accessWith(createReadVarargs(i)); - } - values.put(value.getName(), value.makeOriginal()); - } - } - private static CodeTree createReadVarargs(int i) { return CodeTreeBuilder.createBuilder().string("args_[").string(String.valueOf(i)).string("]").build(); } @@ -2766,14 +2830,14 @@ } } - public void addParametersTo(CodeExecutableElement method, String... optionalNames) { + public void addParametersTo(CodeExecutableElement method, int varArgsThreshold, String... optionalNames) { for (String var : optionalNames) { LocalVariable local = values.get(var); if (local != null) { method.addParameter(local.createParameter()); } } - if (needsVarargs(true, factory.varArgsThreshold)) { + if (needsVarargs(true, varArgsThreshold)) { method.addParameter(new CodeVariableElement(factory.getType(Object[].class), "args_")); method.setVarArgs(true); } else { diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Thu Apr 16 17:09:06 2015 +0200 @@ -163,21 +163,36 @@ if (typeEquals(type1, type2)) { return type1; } - TypeElement element1 = fromTypeMirror(type1); - TypeElement element2 = fromTypeMirror(type2); - if (element1 == null || element2 == null) { - if (element1 != null) { - return type1; - } else if (element2 != null) { - return type2; - } + if (isVoid(type1)) { + return type2; + } else if (isVoid(type2)) { + return type1; + } + if (isObject(type1)) { + return type1; + } else if (isObject(type2)) { + return type2; + } + + if (isPrimitive(type1) || isPrimitive(type2)) { return context.getType(Object.class); } - List element1Types = getDirectSuperTypes(element1); - element1Types.add(0, element1); - List element2Types = getDirectSuperTypes(element2); - element2Types.add(0, element2); + if (isSubtype(type1, type2)) { + return type2; + } else if (isSubtype(type2, type1)) { + return type1; + } + + TypeElement element1 = fromTypeMirror(type1); + TypeElement element2 = fromTypeMirror(type2); + + if (element1 == null || element2 == null) { + return context.getType(Object.class); + } + + List element1Types = getSuperTypes(element1); + List element2Types = getSuperTypes(element2); for (TypeElement superType1 : element1Types) { for (TypeElement superType2 : element2Types) { @@ -186,6 +201,7 @@ } } } + return context.getType(Object.class); } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java Thu Apr 16 17:09:06 2015 +0200 @@ -43,6 +43,11 @@ } @Override + public boolean isAnnotated() { + return true; + } + + @Override public boolean matches(VariableElement variable) { if (ElementUtils.findAnnotationMirror(variable.getAnnotationMirrors(), annotationType) != null) { return true; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java Thu Apr 16 17:09:06 2015 +0200 @@ -35,6 +35,7 @@ public class ExecutableTypeData extends MessageContainer implements Comparable { + private final NodeData node; private final ExecutableElement method; private final TypeMirror returnType; private final TypeMirror frameParameter; @@ -44,7 +45,8 @@ private String uniqueName; - public ExecutableTypeData(TypeMirror returnType, String uniqueName, TypeMirror frameParameter, List evaluatedParameters) { + public ExecutableTypeData(NodeData node, TypeMirror returnType, String uniqueName, TypeMirror frameParameter, List evaluatedParameters) { + this.node = node; this.returnType = returnType; this.frameParameter = frameParameter; this.evaluatedParameters = evaluatedParameters; @@ -52,7 +54,8 @@ this.method = null; } - public ExecutableTypeData(ExecutableElement method, int signatureSize, List frameTypes) { + public ExecutableTypeData(NodeData node, ExecutableElement method, int signatureSize, List frameTypes) { + this.node = node; this.method = method; this.returnType = method.getReturnType(); TypeMirror foundFrameParameter = null; @@ -123,6 +126,21 @@ return evaluatedParameters; } + public List getSignatureParameters() { + List signaturetypes = new ArrayList<>(); + int index = 0; + for (NodeExecutionData execution : node.getChildExecutions()) { + if (execution.isShortCircuit()) { + index++; + } + if (index < getEvaluatedCount()) { + signaturetypes.add(getEvaluatedParameters().get(index)); + } + index++; + } + return signaturetypes; + } + public int getVarArgsIndex(int parameterIndex) { if (method.isVarArgs()) { int index = parameterIndex - (method.getParameters().size() - 1); @@ -159,7 +177,7 @@ return evaluatedParameters.size(); } - public boolean canDelegateTo(NodeData node, ExecutableTypeData to) { + public boolean canDelegateTo(ExecutableTypeData to) { ExecutableTypeData from = this; if (to.getEvaluatedCount() < from.getEvaluatedCount()) { return false; @@ -189,8 +207,10 @@ } } - for (int i = from.getEvaluatedCount(); i < to.getEvaluatedCount(); i++) { - TypeMirror delegateToParameter = to.getEvaluatedParameters().get(i); + List fromSignatureParameters = from.getSignatureParameters(); + List toSignatureParameters = to.getSignatureParameters(); + for (int i = fromSignatureParameters.size(); i < toSignatureParameters.size(); i++) { + TypeMirror delegateToParameter = toSignatureParameters.get(i); if (i < node.getChildExecutions().size()) { TypeMirror genericType = node.getGenericType(node.getChildExecutions().get(i)); if (!isSubtypeBoxed(context, genericType, delegateToParameter)) { @@ -206,6 +226,14 @@ ExecutableTypeData o1 = this; ProcessorContext context = ProcessorContext.getInstance(); + if (canDelegateTo(o2)) { + if (!o2.canDelegateTo(this)) { + return 1; + } + } else if (o2.canDelegateTo(this)) { + return -1; + } + int result = Integer.compare(o2.getEvaluatedCount(), o1.getEvaluatedCount()); if (result != 0) { return result; @@ -282,9 +310,22 @@ } } + public String getName() { + if (method != null) { + return method.getSimpleName().toString(); + } else { + return getUniqueName(); + } + + } + + private static String formatType(TypeMirror type) { + return type == null ? "null" : ElementUtils.getSimpleName(type); + } + @Override public String toString() { - return method != null ? ElementUtils.createReferenceName(method) : getUniqueName() + evaluatedParameters.toString(); + return String.format("%s %s(%s,%s)", formatType(getReturnType()), getName(), formatType(getFrameParameter()), getEvaluatedParameters()); } public boolean sameParameters(ExecutableTypeData other) { diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Thu Apr 16 17:09:06 2015 +0200 @@ -134,8 +134,19 @@ return types; } + public int getExecutionCount() { + return getChildExecutions().size(); + } + public int getSignatureSize() { - return getChildExecutions().size(); + int count = 0; + for (NodeExecutionData execution : getChildExecutions()) { + if (execution.isShortCircuit()) { + count++; + } + count++; + } + return count; } public boolean isFrameUsedByAnyGuard() { @@ -567,20 +578,17 @@ if (executable.hasUnexpectedValue(getContext())) { continue; } - if (!typeSystem.hasImplicitSourceTypes(executable.getReturnType())) { - types.add(executable.getReturnType()); - } + types.add(executable.getReturnType()); } } int executionIndex = execution.getIndex(); if (executionIndex >= 0) { for (ExecutableTypeData typeData : getExecutableTypes()) { - if (executionIndex < typeData.getEvaluatedCount()) { - TypeMirror genericType = typeData.getEvaluatedParameters().get(executionIndex); - if (!typeSystem.hasImplicitSourceTypes(genericType)) { - types.add(genericType); - } + List signatureParameters = typeData.getSignatureParameters(); + if (executionIndex < signatureParameters.size()) { + TypeMirror genericType = signatureParameters.get(executionIndex); + types.add(genericType); } } } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java Thu Apr 16 17:09:06 2015 +0200 @@ -59,6 +59,10 @@ this.anyType = anyTypeTemp; } + public boolean isAnnotated() { + return false; + } + public ParameterSpec(ParameterSpec original, TypeMirror newType) { this(original.name, newType); this.local = original.local; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java Thu Apr 16 17:09:06 2015 +0200 @@ -167,14 +167,6 @@ return kind == SpecializationKind.POLYMORPHIC; } - public List getDynamicParameters() { - List uncachedParameters = new ArrayList<>(getParameters()); - for (CacheExpression cacheExpression : getCaches()) { - uncachedParameters.remove(cacheExpression.getParameter()); - } - return uncachedParameters; - } - @Override protected List findChildContainers() { List sinks = new ArrayList<>(); @@ -304,7 +296,7 @@ @Override public String toString() { - return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); + return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getDynamicTypes()); } public boolean isFrameUsed() { diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java Thu Apr 16 17:09:06 2015 +0200 @@ -153,6 +153,14 @@ newParameter.setMethod(this); } + public Iterable getDynamicParameters() { + return new FilteredIterable<>(getParameters(), new Predicate() { + public boolean evaluate(Parameter value) { + return !value.getSpecification().isLocal() && !value.getSpecification().isAnnotated(); + } + }); + } + public Iterable getSignatureParameters() { return new FilteredIterable<>(getParameters(), new Predicate() { public boolean evaluate(Parameter value) { @@ -291,8 +299,8 @@ } public int compareBySignature(TemplateMethod compareMethod) { - List signature1 = getSignatureTypes(this); - List signature2 = getSignatureTypes(compareMethod); + List signature1 = getDynamicTypes(); + List signature2 = compareMethod.getDynamicTypes(); int result = 0; for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) { @@ -307,9 +315,9 @@ return result; } - public static List getSignatureTypes(TemplateMethod method) { + public List getDynamicTypes() { List types = new ArrayList<>(); - for (Parameter param : method.getSignatureParameters()) { + for (Parameter param : getDynamicParameters()) { types.add(param.getType()); } return types; diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Thu Apr 16 17:09:06 2015 +0200 @@ -134,7 +134,7 @@ return null; } for (ImplicitCastData cast : getImplicitCasts()) { - if (cast.getSourceType().equals(sourceType) && cast.getTargetType().equals(targetType)) { + if (ElementUtils.typeEquals(cast.getSourceType(), sourceType) && ElementUtils.typeEquals(cast.getTargetType(), targetType)) { return cast; } } diff -r ec36daea3cf0 -r 68ff637e95b1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Thu Apr 16 17:01:53 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Thu Apr 16 17:09:06 2015 +0200 @@ -148,7 +148,7 @@ node.getFields().addAll(parseFields(lookupTypes, members)); node.getChildren().addAll(parseChildren(lookupTypes, members)); node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members)); - node.getExecutableTypes().addAll(parseExecutableTypeData(members, node.getChildExecutions().size(), context.getFrameTypes(), false)); + node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, node.getSignatureSize(), context.getFrameTypes(), false)); initializeExecutableTypes(node); initializeImportGuards(node, lookupTypes, members); @@ -188,8 +188,13 @@ SpecializationData polymorphic = node.getPolymorphicSpecialization(); if (polymorphic != null) { boolean polymorphicSignatureFound = false; - TypeMirror frame = polymorphic.getFrame() != null ? polymorphic.getFrame().getType() : null; - ExecutableTypeData polymorphicType = new ExecutableTypeData(polymorphic.getReturnType().getType(), "execute", frame, TemplateMethod.getSignatureTypes(polymorphic)); + List dynamicTypes = polymorphic.getDynamicTypes(); + TypeMirror frame = null; + if (polymorphic.getFrame() != null) { + frame = dynamicTypes.remove(0); + } + + ExecutableTypeData polymorphicType = new ExecutableTypeData(node, polymorphic.getReturnType().getType(), "execute", frame, dynamicTypes); for (ExecutableTypeData type : node.getExecutableTypes()) { if (polymorphicType.sameSignature(type)) { polymorphicSignatureFound = true; @@ -214,9 +219,11 @@ } } if (!additionalAbstractRootTypes.isEmpty()) { - node.addError("Incompatible abstract execute methods found %s.", rootTypes); + node.addError("Incompatible abstract execute methods found %s.", additionalAbstractRootTypes); } + namesUnique(node.getExecutableTypes()); + } private static List buildExecutableHierarchy(NodeData node) { @@ -235,7 +242,7 @@ private static void buildExecutableHierarchy(NodeData node, ExecutableTypeData parent, ListIterator executesIterator) { while (executesIterator.hasNext()) { ExecutableTypeData other = executesIterator.next(); - if (other.canDelegateTo(node, parent)) { + if (other.canDelegateTo(parent)) { parent.addDelegatedFrom(other); executesIterator.remove(); } @@ -574,7 +581,7 @@ return executions; } - private List parseExecutableTypeData(List elements, int signatureSize, List frameTypes, boolean includeFinals) { + private List parseExecutableTypeData(NodeData node, List elements, int signatureSize, List frameTypes, boolean includeFinals) { List typeData = new ArrayList<>(); for (ExecutableElement method : ElementFilter.methodsIn(elements)) { Set modifiers = method.getModifiers(); @@ -592,7 +599,7 @@ continue; } - ExecutableTypeData executableType = new ExecutableTypeData(method, signatureSize, context.getFrameTypes()); + ExecutableTypeData executableType = new ExecutableTypeData(node, method, signatureSize, context.getFrameTypes()); if (executableType.getFrameParameter() != null) { boolean supportedType = false; @@ -610,8 +617,12 @@ typeData.add(executableType); } - Collections.sort(typeData); + namesUnique(typeData); + return typeData; + } + + private static void namesUnique(List typeData) { List names = new ArrayList<>(); for (ExecutableTypeData type : typeData) { names.add(type.getUniqueName()); @@ -623,8 +634,6 @@ for (int i = 0; i < typeData.size(); i++) { typeData.get(i).setUniqueName(names.get(i)); } - - return typeData; } private void initializeExecutableTypes(NodeData node) { @@ -632,9 +641,7 @@ Set inconsistentFrameTypes = new HashSet<>(); TypeMirror frameType = null; - Set evaluatedCounts = new HashSet<>(); for (ExecutableTypeData execute : allExecutes) { - evaluatedCounts.add(execute.getEvaluatedCount()); TypeMirror frame = execute.getFrameParameter(); TypeMirror resolvedFrameType; @@ -788,7 +795,7 @@ if (parentNode.getFrameType() != null) { frameTypes = Arrays.asList(parentNode.getFrameType()); } - node.getExecutableTypes().addAll(parseExecutableTypeData(members, child.getExecuteWith().size(), frameTypes, true)); + node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, child.getExecuteWith().size(), frameTypes, true)); node.setFrameType(parentNode.getFrameType()); return node; } @@ -1297,26 +1304,11 @@ } } - private void initializeUninitialized(final NodeData node) { + private static void initializeUninitialized(final NodeData node) { SpecializationData generic = node.getGenericSpecialization(); if (generic == null) { return; } - for (Parameter parameter : generic.getReturnTypeAndParameters()) { - if (ElementUtils.isObject(parameter.getType())) { - continue; - } - Set types = new HashSet<>(); - for (SpecializationData specialization : node.getSpecializations()) { - Parameter actualParameter = specialization.findParameter(parameter.getLocalName()); - if (actualParameter != null) { - types.add(ElementUtils.getQualifiedName(actualParameter.getType())); - } - } - if (types.size() > 1) { - generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, context.getType(Object.class))); - } - } TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters()); // should not use messages from generic specialization uninializedMethod.getMessages().clear(); @@ -1329,7 +1321,6 @@ } SpecializationData generic = node.getGenericSpecialization(); - List types = new ArrayList<>(); Collection frameTypes = new HashSet<>(); @@ -1338,6 +1329,10 @@ frameTypes.add(specialization.getFrame().getType()); } } + if (node.supportsFrame()) { + frameTypes.add(node.getFrameType()); + } + if (!frameTypes.isEmpty()) { frameTypes = ElementUtils.uniqueSortedTypes(frameTypes); TypeMirror frameType; @@ -1378,13 +1373,15 @@ if (usedTypes.size() == 1) { polymorphicType = usedTypes.iterator().next(); + } else { + polymorphicType = ElementUtils.getCommonSuperType(context, usedTypes); + } - if (!isReturnParameter && node.getTypeSystem().hasImplicitSourceTypes(polymorphicType)) { - polymorphicType = context.getType(Object.class); - } - } else { - polymorphicType = context.getType(Object.class); + NodeExecutionData execution = genericParameter.getSpecification().getExecution(); + if (execution != null && !ElementUtils.isSubtypeBoxed(context, polymorphicType, node.getGenericType(execution))) { + throw new AssertionError(String.format("Polymorphic types %s not compatible to generic type %s.", polymorphicType, node.getGenericType(execution))); } + } if (isReturnParameter) { returnType = polymorphicType; @@ -1395,8 +1392,11 @@ } SpecializationMethodParser parser = new SpecializationMethodParser(context, node); + SpecializationData polymorphic = parser.create("Polymorphic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, types); + if (polymorphic == null) { + throw new AssertionError("Failed to parse polymorphic signature. " + parser.createDefaultMethodSpec(null, null, false, null) + " Types: " + returnType + " - " + types); + } - SpecializationData polymorphic = parser.create("Polymorphic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, types); polymorphic.setKind(SpecializationKind.POLYMORPHIC); node.getSpecializations().add(polymorphic); } diff -r ec36daea3cf0 -r 68ff637e95b1 mx/mx_graal.py --- a/mx/mx_graal.py Thu Apr 16 17:01:53 2015 +0200 +++ b/mx/mx_graal.py Thu Apr 16 17:09:06 2015 +0200 @@ -1543,7 +1543,7 @@ with VM('graal', 'product'): with Task('BootstrapWithRegisterPressure:product', tasks) as t: - if t: + if t: registers = 'o0,o1,o2,o3,f8,f9,d32,d34' if platform.processor() == 'sparc' else 'rbx,r11,r10,r14,xmm3,xmm11,xmm14' vm(['-XX:-TieredCompilation', '-G:RegisterPressure=' + registers, '-esa', '-version']) @@ -2160,7 +2160,7 @@ 'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30', 'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192', 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2', - 'sparcv9/hsdis-sparcv9.so': '5f79c312b3dcc55bad551dbb710b11f0048a4ce7', + 'sparcv9/hsdis-sparcv9.so': '970640a9af0bd63641f9063c11275b371a59ee60', } flavoredLib = flavor + "/" + lib diff -r ec36daea3cf0 -r 68ff637e95b1 mxtool/mx.py --- a/mxtool/mx.py Thu Apr 16 17:01:53 2015 +0200 +++ b/mxtool/mx.py Thu Apr 16 17:09:06 2015 +0200 @@ -2115,6 +2115,7 @@ self.javadoc = exe_suffix(join(self.jdk, 'bin', 'javadoc')) self.pack200 = exe_suffix(join(self.jdk, 'bin', 'pack200')) self.toolsjar = join(self.jdk, 'lib', 'tools.jar') + self._classpaths_initialized = False self._bootclasspath = None self._extdirs = None self._endorseddirs = None @@ -2158,22 +2159,24 @@ self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(self.debug_port)] def _init_classpaths(self): - myDir = dirname(__file__) - outDir = join(dirname(__file__), '.jdk' + str(self.version)) - if not exists(outDir): - os.makedirs(outDir) - javaSource = join(myDir, 'ClasspathDump.java') - javaClass = join(outDir, 'ClasspathDump.class') - if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): - subprocess.check_call([self.javac, '-d', _cygpathU2W(outDir), _cygpathU2W(javaSource)], stderr=subprocess.PIPE, stdout=subprocess.PIPE) - self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', _cygpathU2W(outDir), 'ClasspathDump'], stderr=subprocess.PIPE).split('|')] - if self.javaCompliance <= JavaCompliance('1.8'): - # All 3 system properties accessed by ClasspathDump are expected to exist - if not self._bootclasspath or not self._extdirs or not self._endorseddirs: - warn("Could not find all classpaths: boot='" + str(self._bootclasspath) + "' extdirs='" + str(self._extdirs) + "' endorseddirs='" + str(self._endorseddirs) + "'") - self._bootclasspath = _filter_non_existant_paths(self._bootclasspath) - self._extdirs = _filter_non_existant_paths(self._extdirs) - self._endorseddirs = _filter_non_existant_paths(self._endorseddirs) + if not self._classpaths_initialized: + myDir = dirname(__file__) + outDir = join(dirname(__file__), '.jdk' + str(self.version)) + if not exists(outDir): + os.makedirs(outDir) + javaSource = join(myDir, 'ClasspathDump.java') + javaClass = join(outDir, 'ClasspathDump.class') + if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): + subprocess.check_call([self.javac, '-d', _cygpathU2W(outDir), _cygpathU2W(javaSource)], stderr=subprocess.PIPE, stdout=subprocess.PIPE) + self._bootclasspath, self._extdirs, self._endorseddirs = [x if x != 'null' else None for x in subprocess.check_output([self.java, '-cp', _cygpathU2W(outDir), 'ClasspathDump'], stderr=subprocess.PIPE).split('|')] + if self.javaCompliance <= JavaCompliance('1.8'): + # All 3 system properties accessed by ClasspathDump are expected to exist + if not self._bootclasspath or not self._extdirs or not self._endorseddirs: + warn("Could not find all classpaths: boot='" + str(self._bootclasspath) + "' extdirs='" + str(self._extdirs) + "' endorseddirs='" + str(self._endorseddirs) + "'") + self._bootclasspath = _filter_non_existant_paths(self._bootclasspath) + self._extdirs = _filter_non_existant_paths(self._extdirs) + self._endorseddirs = _filter_non_existant_paths(self._endorseddirs) + self._classpaths_initialized = True def __repr__(self): return "JavaConfig(" + str(self.jdk) + ", " + str(self.debug_port) + ")" @@ -2205,35 +2208,23 @@ return self.java_args_pfx + self.java_args + self.java_args_sfx + args def bootclasspath(self): - if self._bootclasspath is None: - self._init_classpaths() + self._init_classpaths() return _separatedCygpathU2W(self._bootclasspath) - def extdirs(self): - if self._extdirs is None: - self._init_classpaths() - return _separatedCygpathU2W(self._extdirs) - - def endorseddirs(self): - if self._endorseddirs is None: - self._init_classpaths() - return _separatedCygpathU2W(self._endorseddirs) """ Add javadoc style options for the library paths of this JDK. """ def javadocLibOptions(self, args): + self._init_classpaths() if args is None: args = [] - if self.bootclasspath(): + if self._bootclasspath: args.append('-bootclasspath') - args.append(self.bootclasspath()) - if self.endorseddirs(): - args.append('-endorseddirs') - args.append(self.endorseddirs()) - if self.extdirs(): + args.append(self._bootclasspath) + if self._extdirs: args.append('-extdirs') - args.append(self.extdirs()) + args.append(self._extdirs) return args """ @@ -2241,24 +2232,26 @@ """ def javacLibOptions(self, args): args = self.javadocLibOptions(args) - if self.endorseddirs(): + if self._endorseddirs: args.append('-endorseddirs') - args.append(self.endorseddirs()) + args.append(self._endorseddirs) return args def containsJar(self, jar): - if self._bootclasspath is None: - self._init_classpaths() - - for e in self._bootclasspath.split(os.pathsep): - if basename(e) == jar: - return True - for d in self._extdirs.split(os.pathsep): - if len(d) and jar in os.listdir(d): - return True - for d in self._endorseddirs.split(os.pathsep): - if len(d) and jar in os.listdir(d): - return True + self._init_classpaths() + + if self._bootclasspath: + for e in self._bootclasspath.split(os.pathsep): + if basename(e) == jar: + return True + if self._extdirs: + for d in self._extdirs.split(os.pathsep): + if len(d) and jar in os.listdir(d): + return True + if self._endorseddirs: + for d in self._endorseddirs.split(os.pathsep): + if len(d) and jar in os.listdir(d): + return True return False def check_get_env(key): @@ -4873,7 +4866,7 @@ '-overview', overviewFile, '-sourcepath', sp, '-source', str(projectJava.javaCompliance)] + - projectJava.javadocLibOptions() + + projectJava.javadocLibOptions([]) + ([] if projectJava.javaCompliance < JavaCompliance('1.8') else ['-Xdoclint:none']) + links + extraArgs + diff -r ec36daea3cf0 -r 68ff637e95b1 src/cpu/x86/vm/registerMap_x86.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/x86/vm/registerMap_x86.cpp Thu Apr 16 17:09:06 2015 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, 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 +#include "vmreg_x86.inline.hpp" + +address RegisterMap::pd_location(VMReg reg) const { + if (reg->is_XMMRegister()) { + int regBase = reg->value() - ConcreteRegisterImpl::max_fpr; + if (regBase % 4 == 0) { + // Reads of the low and high 16 byte parts should be handled by location itself + return NULL; + } + VMReg baseReg = as_XMMRegister(regBase >> 3)->as_VMReg(); + intptr_t offset = (reg->value() - baseReg->value()) * 4; + if (offset >= 16) { + // The high part of YMM registers are saved in a their own area in the frame + baseReg = baseReg->next()->next()->next()->next(); + offset -= 16; + } + address baseLocation = location(baseReg); + if (baseLocation != NULL) { + return baseLocation + offset; + } + } + return NULL; +} diff -r ec36daea3cf0 -r 68ff637e95b1 src/cpu/x86/vm/registerMap_x86.hpp --- a/src/cpu/x86/vm/registerMap_x86.hpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/cpu/x86/vm/registerMap_x86.hpp Thu Apr 16 17:09:06 2015 +0200 @@ -31,11 +31,7 @@ private: // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. - // Since there is none, we just return NULL. - // See registerMap_sparc.hpp for an example of grabbing registers - // from register save areas of a standard layout. - address pd_location(VMReg reg) const {return NULL;} - + address pd_location(VMReg reg) const; // no PD state to clear or copy: void pd_clear() {} void pd_initialize() {} diff -r ec36daea3cf0 -r 68ff637e95b1 src/cpu/x86/vm/register_x86.cpp --- a/src/cpu/x86/vm/register_x86.cpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/cpu/x86/vm/register_x86.cpp Thu Apr 16 17:09:06 2015 +0200 @@ -64,3 +64,28 @@ }; return is_valid() ? names[encoding()] : "xnoreg"; } + +const char* XMMRegisterImpl::sub_word_name(int i) const { + const char* names[number_of_registers * 8] = { + "xmm0:0", "xmm0:1", "xmm0:2", "xmm0:3", "xmm0:4", "xmm0:5", "xmm0:6", "xmm0:7", + "xmm1:0", "xmm1:1", "xmm1:2", "xmm1:3", "xmm1:4", "xmm1:5", "xmm1:6", "xmm1:7", + "xmm2:0", "xmm2:1", "xmm2:2", "xmm2:3", "xmm2:4", "xmm2:5", "xmm2:6", "xmm2:7", + "xmm3:0", "xmm3:1", "xmm3:2", "xmm3:3", "xmm3:4", "xmm3:5", "xmm3:6", "xmm3:7", + "xmm4:0", "xmm4:1", "xmm4:2", "xmm4:3", "xmm4:4", "xmm4:5", "xmm4:6", "xmm4:7", + "xmm5:0", "xmm5:1", "xmm5:2", "xmm5:3", "xmm5:4", "xmm5:5", "xmm5:6", "xmm5:7", + "xmm6:0", "xmm6:1", "xmm6:2", "xmm6:3", "xmm6:4", "xmm6:5", "xmm6:6", "xmm6:7", + "xmm7:0", "xmm7:1", "xmm7:2", "xmm7:3", "xmm7:4", "xmm7:5", "xmm7:6", "xmm7:7", +#ifdef AMD64 + "xmm8:0", "xmm8:1", "xmm8:2", "xmm8:3", "xmm8:4", "xmm8:5", "xmm8:6", "xmm8:7", + "xmm9:0", "xmm9:1", "xmm9:2", "xmm9:3", "xmm9:4", "xmm9:5", "xmm9:6", "xmm9:7", + "xmm10:0", "xmm10:1", "xmm10:2", "xmm10:3", "xmm10:4", "xmm10:5", "xmm10:6", "xmm10:7", + "xmm11:0", "xmm11:1", "xmm11:2", "xmm11:3", "xmm11:4", "xmm11:5", "xmm11:6", "xmm11:7", + "xmm12:0", "xmm12:1", "xmm12:2", "xmm12:3", "xmm12:4", "xmm12:5", "xmm12:6", "xmm12:7", + "xmm13:0", "xmm13:1", "xmm13:2", "xmm13:3", "xmm13:4", "xmm13:5", "xmm13:6", "xmm13:7", + "xmm14:0", "xmm14:1", "xmm14:2", "xmm14:3", "xmm14:4", "xmm14:5", "xmm14:6", "xmm14:7", + "xmm15:0", "xmm15:1", "xmm15:2", "xmm15:3", "xmm15:4", "xmm15:5", "xmm15:6", "xmm15:7", +#endif // AMD64 + }; + assert(i >= 0 && i < 8, "offset too large"); + return is_valid() ? names[encoding() * 8 + i] : "xnoreg"; +} diff -r ec36daea3cf0 -r 68ff637e95b1 src/cpu/x86/vm/register_x86.hpp --- a/src/cpu/x86/vm/register_x86.hpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/cpu/x86/vm/register_x86.hpp Thu Apr 16 17:09:06 2015 +0200 @@ -161,6 +161,7 @@ int encoding() const { assert(is_valid(), err_msg("invalid register (%d)", (int)(intptr_t)this )); return (intptr_t)this; } bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; } const char* name() const; + const char* sub_word_name(int offset) const; }; diff -r ec36daea3cf0 -r 68ff637e95b1 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 16 17:09:06 2015 +0200 @@ -70,9 +70,32 @@ // Capture info about frame layout. Layout offsets are in jint // units because compiler frame slots are jints. #define DEF_XMM_OFFS(regnum) xmm ## regnum ## _off = xmm_off + (regnum)*16/BytesPerInt, xmm ## regnum ## H_off +#define DEF_YMM_HI_OFFS(regnum) ymm_hi ## regnum ## _off = ymm_off + (regnum)*16/BytesPerInt enum layout { fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area - xmm_off = fpu_state_off + 160/BytesPerInt, // offset in fxsave save area +#if defined(COMPILER2) || defined(GRAAL) + ymm_off = fpu_state_off, // offset in fxsave save area + DEF_YMM_HI_OFFS(0), + DEF_YMM_HI_OFFS(1), + DEF_YMM_HI_OFFS(2), + DEF_YMM_HI_OFFS(3), + DEF_YMM_HI_OFFS(4), + DEF_YMM_HI_OFFS(5), + DEF_YMM_HI_OFFS(6), + DEF_YMM_HI_OFFS(7), + DEF_YMM_HI_OFFS(8), + DEF_YMM_HI_OFFS(9), + DEF_YMM_HI_OFFS(10), + DEF_YMM_HI_OFFS(11), + DEF_YMM_HI_OFFS(12), + DEF_YMM_HI_OFFS(13), + DEF_YMM_HI_OFFS(14), + DEF_YMM_HI_OFFS(15), + ymm_hi_save_size = 16 * 16 / BytesPerInt, +#else + ymm_hi_save_size = 0, +#endif + xmm_off = fpu_state_off + 160/BytesPerInt + ymm_hi_save_size, // offset in fxsave save area DEF_XMM_OFFS(0), DEF_XMM_OFFS(1), DEF_XMM_OFFS(2), @@ -89,7 +112,7 @@ DEF_XMM_OFFS(13), DEF_XMM_OFFS(14), DEF_XMM_OFFS(15), - fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt), + fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt) + ymm_hi_save_size, fpu_stateH_end, r15_off, r15H_off, r14_off, r14H_off, @@ -139,19 +162,6 @@ }; OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) { - int vect_words = 0; -#ifdef COMPILER2 - if (save_vectors) { - assert(UseAVX > 0, "256bit vectors are supported only with AVX"); - assert(MaxVectorSize == 32, "only 256bit vectors are supported now"); - // Save upper half of YMM registes - vect_words = 16 * 16 / wordSize; - additional_frame_words += vect_words; - } -#else - assert(!save_vectors, "vectors are generated only by C2"); -#endif - // Always make the frame size 16-byte aligned int frame_size_in_bytes = round_to(additional_frame_words*wordSize + reg_save_size*BytesPerInt, 16); @@ -172,26 +182,34 @@ __ enter(); // rsp becomes 16-byte aligned here __ push_CPU_state(); // Push a multiple of 16 bytes - if (vect_words > 0) { - assert(vect_words*wordSize == 256, ""); - __ subptr(rsp, 256); // Save upper half of YMM registes - __ vextractf128h(Address(rsp, 0),xmm0); - __ vextractf128h(Address(rsp, 16),xmm1); - __ vextractf128h(Address(rsp, 32),xmm2); - __ vextractf128h(Address(rsp, 48),xmm3); - __ vextractf128h(Address(rsp, 64),xmm4); - __ vextractf128h(Address(rsp, 80),xmm5); - __ vextractf128h(Address(rsp, 96),xmm6); - __ vextractf128h(Address(rsp,112),xmm7); - __ vextractf128h(Address(rsp,128),xmm8); - __ vextractf128h(Address(rsp,144),xmm9); - __ vextractf128h(Address(rsp,160),xmm10); - __ vextractf128h(Address(rsp,176),xmm11); - __ vextractf128h(Address(rsp,192),xmm12); - __ vextractf128h(Address(rsp,208),xmm13); - __ vextractf128h(Address(rsp,224),xmm14); - __ vextractf128h(Address(rsp,240),xmm15); +#if defined(COMPILER2) || defined(GRAAL) + __ subptr(rsp, 256); // Save upper half of YMM registers + if (save_vectors) { + assert(UseAVX > 0, "256bit vectors are supported only with AVX"); +#ifdef COMPILER2 + assert(MaxVectorSize == 32, "only 256bit vectors are supported now"); +#endif + // Save upper half of YMM registers + __ vextractf128h(Address(rsp, ymm_hi0_off * BytesPerInt), xmm0); + __ vextractf128h(Address(rsp, ymm_hi1_off * BytesPerInt), xmm1); + __ vextractf128h(Address(rsp, ymm_hi2_off * BytesPerInt), xmm2); + __ vextractf128h(Address(rsp, ymm_hi3_off * BytesPerInt), xmm3); + __ vextractf128h(Address(rsp, ymm_hi4_off * BytesPerInt), xmm4); + __ vextractf128h(Address(rsp, ymm_hi5_off * BytesPerInt), xmm5); + __ vextractf128h(Address(rsp, ymm_hi6_off * BytesPerInt), xmm6); + __ vextractf128h(Address(rsp, ymm_hi7_off * BytesPerInt), xmm7); + __ vextractf128h(Address(rsp, ymm_hi8_off * BytesPerInt), xmm8); + __ vextractf128h(Address(rsp, ymm_hi9_off * BytesPerInt), xmm9); + __ vextractf128h(Address(rsp, ymm_hi10_off * BytesPerInt), xmm10); + __ vextractf128h(Address(rsp, ymm_hi11_off * BytesPerInt), xmm11); + __ vextractf128h(Address(rsp, ymm_hi12_off * BytesPerInt), xmm12); + __ vextractf128h(Address(rsp, ymm_hi13_off * BytesPerInt), xmm13); + __ vextractf128h(Address(rsp, ymm_hi14_off * BytesPerInt), xmm14); + __ vextractf128h(Address(rsp, ymm_hi15_off * BytesPerInt), xmm15); } +#else + assert(!save_vectors, "vectors are generated only by C2 and Graal"); +#endif if (frame::arg_reg_save_area_bytes != 0) { // Allocate argument register save area __ subptr(rsp, frame::arg_reg_save_area_bytes); @@ -240,6 +258,28 @@ map->set_callee_saved(STACK_OFFSET(xmm14_off), xmm14->as_VMReg()); map->set_callee_saved(STACK_OFFSET(xmm15_off), xmm15->as_VMReg()); + +#if defined(COMPILER2) || defined(GRAAL) + if (save_vectors) { + map->set_callee_saved(STACK_OFFSET(ymm_hi0_off ), xmm0->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi1_off ), xmm1->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi2_off ), xmm2->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi3_off ), xmm3->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi4_off ), xmm4->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi5_off ), xmm5->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi6_off ), xmm6->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi7_off ), xmm7->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi8_off ), xmm8->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi9_off ), xmm9->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi10_off), xmm10->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi11_off), xmm11->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi12_off), xmm12->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi13_off), xmm13->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi14_off), xmm14->as_VMReg()->next()->next()->next()->next()); + map->set_callee_saved(STACK_OFFSET(ymm_hi15_off), xmm15->as_VMReg()->next()->next()->next()->next()); + } +#endif + // %%% These should all be a waste but we'll keep things as they were for now if (true) { map->set_callee_saved(STACK_OFFSET( raxH_off ), rax->as_VMReg()->next()); @@ -283,31 +323,33 @@ // Pop arg register save area __ addptr(rsp, frame::arg_reg_save_area_bytes); } -#ifdef COMPILER2 +#if defined(COMPILER2) || defined(GRAAL) if (restore_vectors) { // Restore upper half of YMM registes. assert(UseAVX > 0, "256bit vectors are supported only with AVX"); +#if defined(COMPILER2) assert(MaxVectorSize == 32, "only 256bit vectors are supported now"); - __ vinsertf128h(xmm0, Address(rsp, 0)); - __ vinsertf128h(xmm1, Address(rsp, 16)); - __ vinsertf128h(xmm2, Address(rsp, 32)); - __ vinsertf128h(xmm3, Address(rsp, 48)); - __ vinsertf128h(xmm4, Address(rsp, 64)); - __ vinsertf128h(xmm5, Address(rsp, 80)); - __ vinsertf128h(xmm6, Address(rsp, 96)); - __ vinsertf128h(xmm7, Address(rsp,112)); - __ vinsertf128h(xmm8, Address(rsp,128)); - __ vinsertf128h(xmm9, Address(rsp,144)); - __ vinsertf128h(xmm10, Address(rsp,160)); - __ vinsertf128h(xmm11, Address(rsp,176)); - __ vinsertf128h(xmm12, Address(rsp,192)); - __ vinsertf128h(xmm13, Address(rsp,208)); - __ vinsertf128h(xmm14, Address(rsp,224)); - __ vinsertf128h(xmm15, Address(rsp,240)); - __ addptr(rsp, 256); +#endif + __ vinsertf128h(xmm0, Address(rsp, ymm_hi0_off * BytesPerInt)); + __ vinsertf128h(xmm1, Address(rsp, ymm_hi1_off * BytesPerInt)); + __ vinsertf128h(xmm2, Address(rsp, ymm_hi2_off * BytesPerInt)); + __ vinsertf128h(xmm3, Address(rsp, ymm_hi3_off * BytesPerInt)); + __ vinsertf128h(xmm4, Address(rsp, ymm_hi4_off * BytesPerInt)); + __ vinsertf128h(xmm5, Address(rsp, ymm_hi5_off * BytesPerInt)); + __ vinsertf128h(xmm6, Address(rsp, ymm_hi6_off * BytesPerInt)); + __ vinsertf128h(xmm7, Address(rsp, ymm_hi7_off * BytesPerInt)); + __ vinsertf128h(xmm8, Address(rsp, ymm_hi8_off * BytesPerInt)); + __ vinsertf128h(xmm9, Address(rsp, ymm_hi9_off * BytesPerInt)); + __ vinsertf128h(xmm10, Address(rsp, ymm_hi10_off * BytesPerInt)); + __ vinsertf128h(xmm11, Address(rsp, ymm_hi11_off * BytesPerInt)); + __ vinsertf128h(xmm12, Address(rsp, ymm_hi12_off * BytesPerInt)); + __ vinsertf128h(xmm13, Address(rsp, ymm_hi13_off * BytesPerInt)); + __ vinsertf128h(xmm14, Address(rsp, ymm_hi14_off * BytesPerInt)); + __ vinsertf128h(xmm15, Address(rsp, ymm_hi15_off * BytesPerInt)); } + __ addptr(rsp, 256); #else - assert(!restore_vectors, "vectors are generated only by C2"); + assert(!restore_vectors, "vectors are generated only by C2 and Graal"); #endif // Recover CPU state __ pop_CPU_state(); diff -r ec36daea3cf0 -r 68ff637e95b1 src/cpu/x86/vm/vmreg_x86.cpp --- a/src/cpu/x86/vm/vmreg_x86.cpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/cpu/x86/vm/vmreg_x86.cpp Thu Apr 16 17:09:06 2015 +0200 @@ -48,8 +48,9 @@ XMMRegister xreg = ::as_XMMRegister(0); for ( ; i < ConcreteRegisterImpl::max_xmm ; ) { - for (int j = 0 ; j < 8 ; j++) { - regName[i++] = xreg->name(); + regName[i++] = xreg->name(); + for (int j = 1 ; j < 8 ; j++) { + regName[i++] = xreg->sub_word_name(j); } xreg = xreg->successor(); } diff -r ec36daea3cf0 -r 68ff637e95b1 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Apr 16 17:09:06 2015 +0200 @@ -208,6 +208,7 @@ GRAAL_ONLY(do_klass(HotSpotCompiledRuntimeStub_klass, com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub, Graal)) \ GRAAL_ONLY(do_klass(HotSpotForeignCallLinkageImpl_klass, com_oracle_graal_hotspot_HotSpotForeignCallLinkageImpl, Graal)) \ GRAAL_ONLY(do_klass(HotSpotReferenceMap_klass, com_oracle_graal_hotspot_HotSpotReferenceMap, Graal)) \ + GRAAL_ONLY(do_klass(HotSpotOopMap_klass, com_oracle_graal_hotspot_HotSpotReferenceMap_HotSpotOopMap, Graal)) \ GRAAL_ONLY(do_klass(HotSpotInstalledCode_klass, com_oracle_graal_hotspot_meta_HotSpotInstalledCode, Graal)) \ GRAAL_ONLY(do_klass(HotSpotNmethod_klass, com_oracle_graal_hotspot_meta_HotSpotNmethod, Graal)) \ GRAAL_ONLY(do_klass(HotSpotResolvedJavaMethodImpl_klass, com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethodImpl, Graal)) \ diff -r ec36daea3cf0 -r 68ff637e95b1 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Apr 16 17:09:06 2015 +0200 @@ -310,6 +310,7 @@ GRAAL_ONLY(template(com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub, "com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_HotSpotForeignCallLinkageImpl, "com/oracle/graal/hotspot/HotSpotForeignCallLinkageImpl")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_HotSpotReferenceMap, "com/oracle/graal/hotspot/HotSpotReferenceMap")) \ + GRAAL_ONLY(template(com_oracle_graal_hotspot_HotSpotReferenceMap_HotSpotOopMap, "com/oracle/graal/hotspot/HotSpotReferenceMap$HotSpotOopMap")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_bridge_CompilerToVMImpl, "com/oracle/graal/hotspot/bridge/CompilerToVMImpl")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode, "com/oracle/graal/hotspot/meta/HotSpotInstalledCode")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotNmethod, "com/oracle/graal/hotspot/meta/HotSpotNmethod")) \ diff -r ec36daea3cf0 -r 68ff637e95b1 src/share/vm/compiler/oopMap.cpp --- a/src/share/vm/compiler/oopMap.cpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/share/vm/compiler/oopMap.cpp Thu Apr 16 17:09:06 2015 +0200 @@ -388,68 +388,71 @@ do { omv = oms.current(); oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); - if ( loc != NULL ) { - oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); - oop *derived_loc = loc; - oop val = *base_loc; - if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { - // Ignore NULL oops and decoded NULL narrow oops which - // equal to Universe::narrow_oop_base when a narrow oop - // implicit null check is used in compiled code. - // The narrow_oop_base could be NULL or be the address - // of the page below heap depending on compressed oops mode. - } else - derived_oop_fn(base_loc, derived_loc); + guarantee(loc != NULL, "missing saved register"); + oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); + oop *derived_loc = loc; + oop val = *base_loc; + if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { + // Ignore NULL oops and decoded NULL narrow oops which + // equal to Universe::narrow_oop_base when a narrow oop + // implicit null check is used in compiled code. + // The narrow_oop_base could be NULL or be the address + // of the page below heap depending on compressed oops mode. + } else { + derived_oop_fn(base_loc, derived_loc); } oms.next(); } while (!oms.is_done()); } } - // We want coop, value and oop oop_types + // We want narrowoop and oop oop_types int mask = OopMapValue::oop_value | OopMapValue::narrowoop_value; { for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) { omv = oms.current(); oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); - if ( loc != NULL ) { - if ( omv.type() == OopMapValue::oop_value ) { - oop val = *loc; - if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { - // Ignore NULL oops and decoded NULL narrow oops which - // equal to Universe::narrow_oop_base when a narrow oop - // implicit null check is used in compiled code. - // The narrow_oop_base could be NULL or be the address - // of the page below heap depending on compressed oops mode. - continue; - } + // It should be an error if no location can be found for a + // register mentioned as contained an oop of some kind. Maybe + // this was allowed previously because value_value items might + // be missing? + guarantee(loc != NULL, "missing saved register"); + if ( omv.type() == OopMapValue::oop_value ) { + oop val = *loc; + if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { + // Ignore NULL oops and decoded NULL narrow oops which + // equal to Universe::narrow_oop_base when a narrow oop + // implicit null check is used in compiled code. + // The narrow_oop_base could be NULL or be the address + // of the page below heap depending on compressed oops mode. + continue; + } #ifdef ASSERT - if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || - !Universe::heap()->is_in_or_null(*loc)) { - tty->print_cr("# Found non oop pointer. Dumping state at failure"); - // try to dump out some helpful debugging information - trace_codeblob_maps(fr, reg_map); - omv.print(); - tty->print_cr("register r"); - omv.reg()->print(); - tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc); - // do the real assert. - assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer"); - } + if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || + !Universe::heap()->is_in_or_null(*loc)) { + tty->print_cr("# Found non oop pointer. Dumping state at failure"); + // try to dump out some helpful debugging information + trace_codeblob_maps(fr, reg_map); + omv.print(); + tty->print_cr("register r"); + omv.reg()->print(); + tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc); + // do the real assert. + assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer"); + } #endif // ASSERT - oop_fn->do_oop(loc); - } else if ( omv.type() == OopMapValue::narrowoop_value ) { - narrowOop *nl = (narrowOop*)loc; + oop_fn->do_oop(loc); + } else if ( omv.type() == OopMapValue::narrowoop_value ) { + narrowOop *nl = (narrowOop*)loc; #ifndef VM_LITTLE_ENDIAN - if (!omv.reg()->is_stack()) { - // compressed oops in registers only take up 4 bytes of an - // 8 byte register but they are in the wrong part of the - // word so adjust loc to point at the right place. - nl = (narrowOop*)((address)nl + 4); - } + if (!omv.reg()->is_stack()) { + // compressed oops in registers only take up 4 bytes of an + // 8 byte register but they are in the wrong part of the + // word so adjust loc to point at the right place. + nl = (narrowOop*)((address)nl + 4); + } #endif - oop_fn->do_oop(nl); - } + oop_fn->do_oop(nl); } } } diff -r ec36daea3cf0 -r 68ff637e95b1 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu Apr 16 17:09:06 2015 +0200 @@ -71,35 +71,39 @@ const int MapWordBits = 64; -static bool is_bit_set(typeArrayOop words, int i) { +static int entry_value(typeArrayOop words, int i) { jint words_idx = i / MapWordBits; assert(words_idx >= 0 && words_idx < words->length(), "unexpected index"); jlong word = words->long_at(words_idx); - return (word & (1LL << (i % MapWordBits))) != 0; + return (word >> (i % MapWordBits)) & 15LL; } -static int bitset_size(oop bitset) { - typeArrayOop arr = BitSet::words(bitset); +static int fixedmap_size(oop bitset) { + typeArrayOop arr = HotSpotOopMap::words(bitset); return arr->length() * MapWordBits; } static void set_vmreg_oops(OopMap* map, VMReg reg, typeArrayOop words, int idx) { - bool is_oop = is_bit_set(words, 3 * idx); - if (is_oop) { - bool narrow1 = is_bit_set(words, 3 * idx + 1); - bool narrow2 = is_bit_set(words, 3 * idx + 2); - if (narrow1 || narrow2) { - if (narrow1) { - map->set_narrowoop(reg); - } - if (narrow2) { - map->set_narrowoop(reg->next()); - } - } else { + int value = entry_value(words, 4 * idx); + switch (value) { + case 10: map->set_oop(reg); - } - } else { - map->set_value(reg); + break; + case 5: + map->set_narrowoop(reg); + map->set_narrowoop(reg->next()); + break; + case 1: + map->set_narrowoop(reg); + break; + case 4: + map->set_narrowoop(reg->next()); + break; + case 0: + break; + default: + assert(false, err_msg("unexpected bit pattern at %d = 0x%x", idx, value)); + ShouldNotReachHere(); } } @@ -112,30 +116,30 @@ oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info); if (register_map != NULL) { - typeArrayOop words = BitSet::words(register_map); + typeArrayOop words = HotSpotOopMap::words(register_map); + int mapIdx = 0; for (jint i = 0; i < RegisterImpl::number_of_registers; i++) { - set_vmreg_oops(map, as_Register(i)->as_VMReg(), words, i); + set_vmreg_oops(map, as_Register(i)->as_VMReg(), words, mapIdx); + mapIdx++; } #ifdef TARGET_ARCH_x86 for (jint i = 0; i < XMMRegisterImpl::number_of_registers; i++) { VMReg reg = as_XMMRegister(i)->as_VMReg(); - int idx = RegisterImpl::number_of_registers + 4 * i; for (jint j = 0; j < 4; j++) { - set_vmreg_oops(map, reg->next(2 * j), words, idx + j); + set_vmreg_oops(map, reg->next(2 * j), words, mapIdx++); } } #endif #ifdef TARGET_ARCH_sparc for (jint i = 0; i < FloatRegisterImpl::number_of_registers; i++) { VMReg reg = as_FloatRegister(i)->as_VMReg(); - int idx = RegisterImpl::number_of_registers + i; - set_vmreg_oops(map, reg, words, idx); + set_vmreg_oops(map, reg, words, mapIdx++); } #endif } - typeArrayOop words = BitSet::words(frame_map); - int size = bitset_size(frame_map) / 3; + typeArrayOop words = HotSpotOopMap::words(frame_map); + int size = fixedmap_size(frame_map) / 4; for (jint i = 0; i < size; i++) { // HotSpot stack slots are 4 bytes VMReg reg = VMRegImpl::stack2reg(i * VMRegImpl::slots_per_word); @@ -161,7 +165,6 @@ #endif } } - return map; } diff -r ec36daea3cf0 -r 68ff637e95b1 src/share/vm/graal/graalEnv.cpp --- a/src/share/vm/graal/graalEnv.cpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/share/vm/graal/graalEnv.cpp Thu Apr 16 17:09:06 2015 +0200 @@ -546,6 +546,12 @@ } } else { nm->set_has_unsafe_access(has_unsafe_access); +#ifdef TARGET_ARCH_x86 + // It might be preferable to set this only for methods which + // use vector instructions but we currently don't track this + // and it probably wouldn't make much difference. + nm->set_has_wide_vectors(UseAVX >= 2); +#endif // Record successful registration. // (Put nm into the task handle *before* publishing to the Java heap.) diff -r ec36daea3cf0 -r 68ff637e95b1 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu Apr 16 17:09:06 2015 +0200 @@ -162,15 +162,15 @@ objArrayOop_field(DebugInfo, virtualObjectMapping, "[Lcom/oracle/graal/api/meta/Value;") \ end_class \ start_class(HotSpotReferenceMap) \ - oop_field(HotSpotReferenceMap, registerRefMap, "Ljava/util/BitSet;") \ - oop_field(HotSpotReferenceMap, frameRefMap, "Ljava/util/BitSet;") \ + oop_field(HotSpotReferenceMap, registerRefMap, "Lcom/oracle/graal/hotspot/HotSpotReferenceMap$HotSpotOopMap;") \ + oop_field(HotSpotReferenceMap, frameRefMap, "Lcom/oracle/graal/hotspot/HotSpotReferenceMap$HotSpotOopMap;") \ end_class \ start_class(RegisterSaveLayout) \ objArrayOop_field(RegisterSaveLayout, registers, "[Lcom/oracle/graal/api/code/Register;") \ typeArrayOop_field(RegisterSaveLayout, slots, "[I") \ end_class \ - start_class(BitSet) \ - typeArrayOop_field(BitSet, words, "[J") \ + start_class(HotSpotOopMap) \ + typeArrayOop_field(HotSpotOopMap, words, "[J") \ end_class \ start_class(BytecodeFrame) \ objArrayOop_field(BytecodeFrame, values, "[Lcom/oracle/graal/api/meta/Value;") \ diff -r ec36daea3cf0 -r 68ff637e95b1 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 16 17:01:53 2015 +0200 +++ b/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 16 17:09:06 2015 +0200 @@ -111,9 +111,14 @@ _resolve_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C), "resolve_virtual_call"); _resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call"); +#if defined(COMPILER2) || defined(GRAAL) + // Vectors are generated only by C2 and Graal. #ifdef COMPILER2 - // Vectors are generated only by C2. - if (is_wide_vector(MaxVectorSize)) { + bool support_wide = is_wide_vector(MaxVectorSize) || IS_GRAAL_DEFINED; +#else + bool support_wide = true; +#endif + if (support_wide) { _polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP); } #endif // COMPILER2