--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java 2017-12-13 08:52:23.000000000 -0800 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java 2017-12-13 08:52:23.000000000 -0800 @@ -33,8 +33,9 @@ /** * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the - * low level representation of the value, and a {@link #referenceMask} that describes the location - * of object references in the value, and optionally a {@link #derivedReferenceBase}. + * low level representation of the value, a {@link #referenceMask} that describes the location of + * object references in the value, a {@link #referenceCompressionMask} that indicates which of these + * references are compressed references, and for derived references a {@link #derivedReferenceBase}. * *

Constructing {@link LIRKind} instances

* @@ -52,7 +53,7 @@ * compare-and-swap. For convert operations, {@link LIRKind#combine} should be used. *

* If it is known that the result will be a reference (e.g. pointer arithmetic where the end result - * is a valid oop), {@link LIRKind#reference} should be used. + * is a valid oop), {@link #reference} or {@link LIRKind#compressedReference} should be used. *

* If it is known that the result will neither be a reference nor be derived from a reference, * {@link LIRKind#value} can be used. If the operation producing this value has inputs, this is very @@ -64,19 +65,28 @@ */ public final class LIRKind extends ValueKind { + /** + * The location of object references in the value. If the value is a vector type, each bit + * represents one component of the vector. + */ private final int referenceMask; + /** Mask with 1-bits indicating which references in {@link #referenceMask} are compressed. */ + private final int referenceCompressionMask; + private AllocatableValue derivedReferenceBase; private static final int UNKNOWN_REFERENCE = -1; public static final LIRKind Illegal = unknownReference(ValueKind.Illegal.getPlatformKind()); - private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) { + private LIRKind(PlatformKind platformKind, int referenceMask, int referenceCompressionMask, AllocatableValue derivedReferenceBase) { super(platformKind); this.referenceMask = referenceMask; + this.referenceCompressionMask = referenceCompressionMask; this.derivedReferenceBase = derivedReferenceBase; + assert this.referenceCompressionMask == 0 || this.referenceMask == this.referenceCompressionMask : "mixing compressed and uncompressed references is untested"; assert derivedReferenceBase == null || !derivedReferenceBase.getValueKind(LIRKind.class).isDerivedReference() : "derived reference can't have another derived reference as base"; } @@ -86,15 +96,23 @@ * reference. Otherwise, {@link #combine(Value...)} should be used instead. */ public static LIRKind value(PlatformKind platformKind) { - return new LIRKind(platformKind, 0, null); + return new LIRKind(platformKind, 0, 0, null); } /** - * Create a {@link LIRKind} of type {@code platformKind} that contains a single tracked oop - * reference. + * Create a {@link LIRKind} of type {@code platformKind} that contains a single, tracked, + * uncompressed oop reference. */ public static LIRKind reference(PlatformKind platformKind) { - return derivedReference(platformKind, null); + return derivedReference(platformKind, null, false); + } + + /** + * Create a {@link LIRKind} of type {@code platformKind} that contains a single, tracked, + * compressed oop reference. + */ + public static LIRKind compressedReference(PlatformKind platformKind) { + return derivedReference(platformKind, null, true); } /** @@ -112,10 +130,12 @@ /** * Create a {@link LIRKind} of type {@code platformKind} that contains a derived reference. */ - public static LIRKind derivedReference(PlatformKind platformKind, AllocatableValue base) { + public static LIRKind derivedReference(PlatformKind platformKind, AllocatableValue base, boolean compressed) { int length = platformKind.getVectorLength(); assert 0 < length && length < 32 : "vector of " + length + " references not supported"; - return new LIRKind(platformKind, (1 << length) - 1, base); + int referenceMask = (1 << length) - 1; + int referenceCompressionMask = (compressed ? referenceMask : 0); + return new LIRKind(platformKind, referenceMask, referenceCompressionMask, base); } /** @@ -125,7 +145,7 @@ * used instead to automatically propagate this information. */ public static LIRKind unknownReference(PlatformKind platformKind) { - return new LIRKind(platformKind, UNKNOWN_REFERENCE, null); + return new LIRKind(platformKind, UNKNOWN_REFERENCE, UNKNOWN_REFERENCE, null); } /** @@ -139,9 +159,9 @@ return makeUnknownReference(); } else { if (isValue()) { - return derivedReference(getPlatformKind(), base); + return derivedReference(getPlatformKind(), base, false); } else { - return new LIRKind(getPlatformKind(), referenceMask, base); + return new LIRKind(getPlatformKind(), referenceMask, referenceCompressionMask, base); } } } @@ -240,7 +260,7 @@ return mergeKind; } /* {@code mergeKind} is a reference. */ - if (mergeKind.referenceMask != inputKind.referenceMask) { + if (mergeKind.referenceMask != inputKind.referenceMask || mergeKind.referenceCompressionMask != inputKind.referenceCompressionMask) { /* * Reference masks do not match so the result can only be an unknown reference. */ @@ -284,9 +304,11 @@ } else { // reference type int newLength = Math.min(32, newPlatformKind.getVectorLength()); - int newReferenceMask = referenceMask & (0xFFFFFFFF >>> (32 - newLength)); + int lengthMask = 0xFFFFFFFF >>> (32 - newLength); + int newReferenceMask = referenceMask & lengthMask; + int newReferenceCompressionMask = referenceCompressionMask & lengthMask; assert newReferenceMask != UNKNOWN_REFERENCE; - return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase); + return new LIRKind(newPlatformKind, newReferenceMask, newReferenceCompressionMask, derivedReferenceBase); } } @@ -308,12 +330,14 @@ // repeat reference mask to fill new kind int newReferenceMask = 0; + int newReferenceCompressionMask = 0; for (int i = 0; i < newLength; i += getPlatformKind().getVectorLength()) { newReferenceMask |= referenceMask << i; + newReferenceCompressionMask |= referenceCompressionMask << i; } assert newReferenceMask != UNKNOWN_REFERENCE; - return new LIRKind(newPlatformKind, newReferenceMask, derivedReferenceBase); + return new LIRKind(newPlatformKind, newReferenceMask, newReferenceCompressionMask, derivedReferenceBase); } } @@ -322,7 +346,7 @@ * {@link LIRKind#unknownReference}. */ public LIRKind makeUnknownReference() { - return new LIRKind(getPlatformKind(), UNKNOWN_REFERENCE, null); + return new LIRKind(getPlatformKind(), UNKNOWN_REFERENCE, UNKNOWN_REFERENCE, null); } /** @@ -385,6 +409,17 @@ } /** + * Check whether the {@code idx}th part of this value is a compressed reference. + * + * @param idx The index into the vector if this is a vector kind. Must be 0 if this is a scalar + * kind. + */ + public boolean isCompressedReference(int idx) { + assert 0 <= idx && idx < getPlatformKind().getVectorLength() : "invalid index " + idx + " in " + this; + return !isUnknownReference() && (referenceCompressionMask & (1 << idx)) != 0; + } + + /** * Check whether this kind is a value type that doesn't need to be tracked at safepoints. */ public boolean isValue() { @@ -432,6 +467,7 @@ result = prime * result + ((getPlatformKind() == null) ? 0 : getPlatformKind().hashCode()); result = prime * result + ((getDerivedReferenceBase() == null) ? 0 : getDerivedReferenceBase().hashCode()); result = prime * result + referenceMask; + result = prime * result + referenceCompressionMask; return result; } @@ -445,7 +481,7 @@ } LIRKind other = (LIRKind) obj; - if (getPlatformKind() != other.getPlatformKind() || referenceMask != other.referenceMask) { + if (getPlatformKind() != other.getPlatformKind() || referenceMask != other.referenceMask || referenceCompressionMask != other.referenceCompressionMask) { return false; } if (isDerivedReference()) {