Mercurial > hg > truffle
changeset 20981:92fc95e8667d
Add more efficient implementation of HotSpotReferenceMap
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Wed, 15 Apr 2015 10:09:13 -0700 |
parents | abc059cb0acf |
children | 23d6b95bd687 |
files | graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalJavaAccess.hpp |
diffstat | 7 files changed, 460 insertions(+), 243 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Tue Apr 14 11:37:24 2015 -0700 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Wed Apr 15 10:09:13 2015 -0700 @@ -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); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Tue Apr 14 11:37:24 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Wed Apr 15 10:09:13 2015 -0700 @@ -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. + * <p> + * These bits can have the following values (MSB first): + * + * <pre> + * 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 + * </pre> + * + * @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 * </pre> */ - private final BitSet registerRefMap; + private final HotSpotOopMap registerRefMap; /** * Contains 3 bits per stack word. @@ -65,23 +330,23 @@ * 111 - contains two narrow oops * </pre> */ - 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. - * <p> - * These bits can have the following values (LSB first): - * - * <pre> - * 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 - * </pre> - * - * @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); + } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java Tue Apr 14 11:37:24 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetDescription.java Wed Apr 15 10:09:13 2015 -0700 @@ -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); }
--- a/src/share/vm/classfile/systemDictionary.hpp Tue Apr 14 11:37:24 2015 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Wed Apr 15 10:09:13 2015 -0700 @@ -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)) \
--- a/src/share/vm/classfile/vmSymbols.hpp Tue Apr 14 11:37:24 2015 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Wed Apr 15 10:09:13 2015 -0700 @@ -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")) \
--- a/src/share/vm/graal/graalCodeInstaller.cpp Tue Apr 14 11:37:24 2015 -0700 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Wed Apr 15 10:09:13 2015 -0700 @@ -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; }
--- a/src/share/vm/graal/graalJavaAccess.hpp Tue Apr 14 11:37:24 2015 -0700 +++ b/src/share/vm/graal/graalJavaAccess.hpp Wed Apr 15 10:09:13 2015 -0700 @@ -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;") \