// conflict.
ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
(1 << String::kArrayIndexValueBits));
- // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in
- // the low kHashShift bits.
- Ubfx(hash, hash, String::kHashShift, String::kArrayIndexValueBits);
- SmiTag(index, hash);
+ DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash);
}
template<typename Field>
void DecodeField(Register dst, Register src) {
+ Ubfx(dst, src, Field::kShift, Field::kSize);
+ }
+
+ template<typename Field>
+ void DecodeField(Register reg) {
+ DecodeField<Field>(reg, reg);
+ }
+
+ template<typename Field>
+ void DecodeFieldToSmi(Register dst, Register src) {
static const int shift = Field::kShift;
- static const int mask = Field::kMask >> shift;
- static const int size = Field::kSize;
- mov(dst, Operand(src, LSR, shift));
- if (shift + size != 32) {
+ static const int mask = Field::kMask >> shift << kSmiTagSize;
+ STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0);
+ STATIC_ASSERT(kSmiTag == 0);
+ if (shift < kSmiTagSize) {
+ mov(dst, Operand(src, LSL, kSmiTagSize - shift));
+ and_(dst, dst, Operand(mask));
+ } else if (shift > kSmiTagSize) {
+ mov(dst, Operand(src, LSR, shift - kSmiTagSize));
and_(dst, dst, Operand(mask));
+ } else {
+ and_(dst, src, Operand(mask));
}
}
template<typename Field>
- void DecodeField(Register reg) {
+ void DecodeFieldToSmi(Register reg) {
DecodeField<Field>(reg, reg);
}
// conflict.
ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
(1 << String::kArrayIndexValueBits));
- // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in
- // the low kHashShift bits.
- STATIC_ASSERT(kSmiTag == 0);
- Ubfx(hash, hash, String::kHashShift, String::kArrayIndexValueBits);
- SmiTag(index, hash);
+ DecodeField<String::ArrayIndexValueBits>(index, hash);
+ SmiTag(index, index);
}
// reserved for it does not conflict.
ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
(1 << String::kArrayIndexValueBits));
- // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in
- // the low kHashShift bits.
- and_(hash, String::kArrayIndexValueMask);
- STATIC_ASSERT(String::kHashShift >= kSmiTagSize && kSmiTag == 0);
- if (String::kHashShift > kSmiTagSize) {
- shr(hash, String::kHashShift - kSmiTagSize);
- }
if (!index.is(hash)) {
mov(index, hash);
}
+ DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
}
void DecodeField(Register reg) {
static const int shift = Field::kShift;
static const int mask = Field::kMask >> Field::kShift;
- sar(reg, shift);
+ if (shift != 0) {
+ sar(reg, shift);
+ }
and_(reg, Immediate(mask));
}
+
+ template<typename Field>
+ void DecodeFieldToSmi(Register reg) {
+ static const int shift = Field::kShift;
+ static const int mask = (Field::kMask >> Field::kShift) << kSmiTagSize;
+ STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0);
+ STATIC_ASSERT(kSmiTag == 0);
+ if (shift < kSmiTagSize) {
+ shl(reg, kSmiTagSize - shift);
+ } else if (shift > kSmiTagSize) {
+ sar(reg, shift - kSmiTagSize);
+ }
+ and_(reg, Immediate(mask));
+ }
+
void LoadPowerOf2(XMMRegister dst, Register scratch, int power);
// Abort execution if argument is not a number, enabled via --debug-code.
uint32_t field = hash_field();
if ((field & kIsNotArrayIndexMask) != 0) return false;
// Isolate the array index form the full hash field.
- *index = (kArrayIndexHashMask & field) >> kHashShift;
+ *index = ArrayIndexValueBits::decode(field);
return true;
} else {
return ComputeArrayIndex(index);
ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
(1 << String::kArrayIndexValueBits));
- value <<= String::kHashShift;
- value |= length << String::kArrayIndexHashLengthShift;
+ value <<= String::ArrayIndexValueBits::kShift;
+ value |= length << String::ArrayIndexLengthBits::kShift;
ASSERT((value & String::kIsNotArrayIndexMask) == 0);
ASSERT((length > String::kMaxCachedArrayIndexLength) ||
STATIC_ASSERT((kArrayIndexLengthBits > 0));
- static const int kArrayIndexHashLengthShift =
- kArrayIndexValueBits + kNofHashBitFields;
-
- static const int kArrayIndexHashMask = (1 << kArrayIndexHashLengthShift) - 1;
-
- static const int kArrayIndexValueMask =
- ((1 << kArrayIndexValueBits) - 1) << kHashShift;
+ class ArrayIndexValueBits : public BitField<unsigned int, kNofHashBitFields,
+ kArrayIndexValueBits> {};
+ class ArrayIndexLengthBits : public BitField<unsigned int,
+ kNofHashBitFields + kArrayIndexValueBits,
+ kArrayIndexLengthBits> {};
// Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
// could use a mask to test if the length of string is less than or equal to
STATIC_ASSERT(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
static const unsigned int kContainsCachedArrayIndexMask =
- (~kMaxCachedArrayIndexLength << kArrayIndexHashLengthShift) |
+ (~kMaxCachedArrayIndexLength << ArrayIndexLengthBits::kShift) |
kIsNotArrayIndexMask;
// Value of empty hash field indicating that the hash is not computed.
// reserved for it does not conflict.
ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
(1 << String::kArrayIndexValueBits));
- // We want the smi-tagged index in key. Even if we subsequently go to
- // the slow case, converting the key to a smi is always valid.
- // key: string key
- // hash: key's hash field, including its array index value.
- andp(hash, Immediate(String::kArrayIndexValueMask));
- shrp(hash, Immediate(String::kHashShift));
- // Here we actually clobber the key which will be used if calling into
- // runtime later. However as the new key is the numeric value of a string key
- // there is no difference in using either key.
- Integer32ToSmi(index, hash);
+ if (!hash.is(index)) {
+ movl(index, hash);
+ }
+ DecodeFieldToSmi<String::ArrayIndexValueBits>(index);
}
void DecodeField(Register reg) {
static const int shift = Field::kShift;
static const int mask = Field::kMask >> Field::kShift;
- shrp(reg, Immediate(shift));
+ if (shift != 0) {
+ shrp(reg, Immediate(shift));
+ }
andp(reg, Immediate(mask));
}
+ template<typename Field>
+ void DecodeFieldToSmi(Register reg) {
+ andp(reg, Immediate(Field::kMask));
+ shlp(reg, Immediate(kSmiShift - Field::kShift));
+ }
+
// Abort execution if argument is not a number, enabled via --debug-code.
void AssertNumber(Register object);