Use the BitField class for Code::Flags.

Use the BitField helper class for the code flags, so that we do not have to
define both a shift and a mask explicitly.  This makes changing the flags
layout simpler.

Also, make the 'mask' and 'max' members of BitField into constants, because
they are constant and so that they can be used as constant expressions.
E.g., so they can be used in declaring other const members or in static
asserts.

R=fschneider@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/7787028

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9232 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 57b9e9d9
......@@ -146,7 +146,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
StringDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
__ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
__ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
__ tst(scratch1, Operand(PropertyDetails::TypeField::kMask << kSmiTagSize));
__ b(ne, miss);
// Get the value at the masked, scaled index and return.
......@@ -194,9 +194,9 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
const int kElementsStartOffset = StringDictionary::kHeaderSize +
StringDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
const int kTypeAndReadOnlyMask
= (PropertyDetails::TypeField::mask() |
PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
const int kTypeAndReadOnlyMask =
(PropertyDetails::TypeField::kMask |
PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
__ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
__ tst(scratch1, Operand(kTypeAndReadOnlyMask));
__ b(ne, miss);
......
......@@ -1421,7 +1421,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
const int kDetailsOffset =
NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
ldr(t1, FieldMemOperand(t2, kDetailsOffset));
tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask())));
tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
b(ne, miss);
// Get the value at the masked, scaled index and return.
......
......@@ -49,11 +49,11 @@ class CompilationInfo BASE_EMBEDDED {
ASSERT(Isolate::Current() == isolate_);
return isolate_;
}
bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; }
bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
bool is_lazy() const { return IsLazy::decode(flags_); }
bool is_eval() const { return IsEval::decode(flags_); }
bool is_global() const { return IsGlobal::decode(flags_); }
bool is_strict_mode() const { return IsStrictMode::decode(flags_); }
bool is_in_loop() const { return IsInLoop::decode(flags_); }
FunctionLiteral* function() const { return function_; }
Scope* scope() const { return scope_; }
Handle<Code> code() const { return code_; }
......
......@@ -144,7 +144,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
StringDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
__ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
__ j(not_zero, miss_label);
// Get the value at the masked, scaled index.
......@@ -198,9 +198,9 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
StringDictionary::kHeaderSize +
StringDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
const int kTypeAndReadOnlyMask
= (PropertyDetails::TypeField::mask() |
PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
const int kTypeAndReadOnlyMask =
(PropertyDetails::TypeField::kMask |
PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
__ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
Immediate(kTypeAndReadOnlyMask));
__ j(not_zero, miss_label);
......
......@@ -840,7 +840,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
ASSERT_EQ(NORMAL, 0);
test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
j(not_zero, miss);
// Get the value at the masked, scaled index.
......
......@@ -165,8 +165,7 @@ class LUnallocated: public LOperand {
}
Policy policy() const { return PolicyField::decode(value_); }
void set_policy(Policy policy) {
value_ &= ~PolicyField::mask();
value_ |= PolicyField::encode(policy);
value_ = PolicyField::update(value_, policy);
}
int fixed_index() const {
return static_cast<int>(value_) >> kFixedIndexShift;
......@@ -177,8 +176,7 @@ class LUnallocated: public LOperand {
}
void set_virtual_register(unsigned id) {
value_ &= ~VirtualRegisterField::mask();
value_ |= VirtualRegisterField::encode(id);
value_ = VirtualRegisterField::update(value_, id);
}
LUnallocated* CopyUnconstrained() {
......
......@@ -146,7 +146,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
__ lw(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
__ And(at,
scratch1,
Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
Operand(PropertyDetails::TypeField::kMask << kSmiTagSize));
__ Branch(miss, ne, at, Operand(zero_reg));
// Get the value at the masked, scaled index and return.
......@@ -196,9 +196,9 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
const int kElementsStartOffset = StringDictionary::kHeaderSize +
StringDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
const int kTypeAndReadOnlyMask
= (PropertyDetails::TypeField::mask() |
PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
const int kTypeAndReadOnlyMask =
(PropertyDetails::TypeField::kMask |
PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
__ lw(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
__ And(at, scratch1, Operand(kTypeAndReadOnlyMask));
__ Branch(miss, ne, at, Operand(zero_reg));
......
......@@ -441,7 +441,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
const int kDetailsOffset =
NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
lw(reg1, FieldMemOperand(reg2, kDetailsOffset));
And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask())));
And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
Branch(miss, ne, at, Operand(zero_reg));
// Get the value at the masked, scaled index and return.
......
......@@ -2867,7 +2867,7 @@ Code::Flags Code::flags() {
void Code::set_flags(Code::Flags flags) {
STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
// Make sure that all call stubs have an arguments count.
ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
......@@ -3104,22 +3104,14 @@ Code::Flags Code::ComputeFlags(Kind kind,
(kind == STORE_IC) ||
(kind == KEYED_STORE_IC));
// Compute the bit mask.
int bits = kind << kFlagsKindShift;
if (in_loop) bits |= kFlagsICInLoopMask;
bits |= ic_state << kFlagsICStateShift;
bits |= type << kFlagsTypeShift;
bits |= extra_ic_state << kFlagsExtraICStateShift;
bits |= argc << kFlagsArgumentsCountShift;
if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
// Cast to flags and validate result before returning it.
Flags result = static_cast<Flags>(bits);
ASSERT(ExtractKindFromFlags(result) == kind);
ASSERT(ExtractICStateFromFlags(result) == ic_state);
ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
ASSERT(ExtractTypeFromFlags(result) == type);
ASSERT(ExtractExtraICStateFromFlags(result) == extra_ic_state);
ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
return result;
int bits = KindField::encode(kind)
| ICInLoopField::encode(in_loop)
| ICStateField::encode(ic_state)
| TypeField::encode(type)
| ExtraICStateField::encode(extra_ic_state)
| (argc << kFlagsArgumentsCountShift)
| CacheHolderField::encode(holder);
return static_cast<Flags>(bits);
}
......@@ -3135,32 +3127,27 @@ Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
Code::Kind Code::ExtractKindFromFlags(Flags flags) {
int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
return static_cast<Kind>(bits);
return KindField::decode(flags);
}
InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
return static_cast<InlineCacheState>(bits);
return ICStateField::decode(flags);
}
Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
int bits = (flags & kFlagsExtraICStateMask) >> kFlagsExtraICStateShift;
return static_cast<ExtraICState>(bits);
return ExtraICStateField::decode(flags);
}
InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
int bits = (flags & kFlagsICInLoopMask);
return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
return ICInLoopField::decode(flags);
}
PropertyType Code::ExtractTypeFromFlags(Flags flags) {
int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
return static_cast<PropertyType>(bits);
return TypeField::decode(flags);
}
......@@ -3170,13 +3157,12 @@ int Code::ExtractArgumentsCountFromFlags(Flags flags) {
InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
int bits = (flags & kFlagsCacheInPrototypeMapMask);
return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
return CacheHolderField::decode(flags);
}
Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
int bits = flags & ~kFlagsTypeMask;
int bits = flags & ~TypeField::kMask;
return static_cast<Flags>(bits);
}
......@@ -4437,9 +4423,7 @@ PropertyAttributes AccessorInfo::property_attributes() {
void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
ASSERT(AttributesField::is_valid(attributes));
int rest_value = flag()->value() & ~AttributesField::mask();
set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
}
......
......@@ -3756,13 +3756,14 @@ class Code: public HeapObject {
InLoopFlag in_loop = NOT_IN_LOOP,
int argc = -1);
static inline Kind ExtractKindFromFlags(Flags flags);
static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags);
static inline PropertyType ExtractTypeFromFlags(Flags flags);
static inline int ExtractArgumentsCountFromFlags(Flags flags);
static inline Kind ExtractKindFromFlags(Flags flags);
static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
static inline int ExtractArgumentsCountFromFlags(Flags flags);
static inline Flags RemoveTypeFromFlags(Flags flags);
// Convert a target address into a code object.
......@@ -3882,25 +3883,20 @@ class Code: public HeapObject {
static const int kSafepointTableOffsetOffset = kStackSlotsOffset + kIntSize;
static const int kStackCheckTableOffsetOffset = kStackSlotsOffset + kIntSize;
// Flags layout.
static const int kFlagsICStateShift = 0;
static const int kFlagsICInLoopShift = 3;
static const int kFlagsTypeShift = 4;
static const int kFlagsKindShift = 8;
static const int kFlagsICHolderShift = 12;
static const int kFlagsExtraICStateShift = 13;
static const int kFlagsArgumentsCountShift = 15;
// Flags layout. BitField<type, shift, size>.
class ICStateField: public BitField<InlineCacheState, 0, 3> {};
class ICInLoopField: public BitField<InLoopFlag, 3, 1> {};
class TypeField: public BitField<PropertyType, 4, 4> {};
class KindField: public BitField<Kind, 8, 4> {};
class CacheHolderField: public BitField<InlineCacheHolderFlag, 12, 1> {};
class ExtraICStateField: public BitField<ExtraICState, 13, 2> {};
static const int kFlagsICStateMask = 0x00000007; // 00000000111
static const int kFlagsICInLoopMask = 0x00000008; // 00000001000
static const int kFlagsTypeMask = 0x000000F0; // 00001110000
static const int kFlagsKindMask = 0x00000F00; // 11110000000
static const int kFlagsCacheInPrototypeMapMask = 0x00001000;
static const int kFlagsExtraICStateMask = 0x00006000;
static const int kFlagsArgumentsCountMask = 0xFFFF8000;
// Signed field cannot be encoded using the BitField class.
static const int kFlagsArgumentsCountShift = 15;
static const int kFlagsArgumentsCountMask = 0xffff8000;
static const int kFlagsNotUsedInLookup =
(kFlagsICInLoopMask | kFlagsTypeMask | kFlagsCacheInPrototypeMapMask);
ICInLoopField::kMask | TypeField::kMask | CacheHolderField::kMask;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
......
......@@ -68,8 +68,8 @@ SafepointTable::SafepointTable(Code* code) {
entries_ = pc_and_deoptimization_indexes_ +
(length_ * kPcAndDeoptimizationIndexSize);
ASSERT(entry_size_ > 0);
ASSERT_EQ(SafepointEntry::DeoptimizationIndexField::max(),
Safepoint::kNoDeoptimizationIndex);
STATIC_ASSERT(SafepointEntry::DeoptimizationIndexField::kMax ==
Safepoint::kNoDeoptimizationIndex);
}
......
......@@ -74,7 +74,7 @@ Code* StubCache::Set(String* name, Map* map, Code* code) {
// the bits are the least significant so they will be the ones
// masked out.
ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
ASSERT(Code::kFlagsICStateShift == 0);
STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
// Make sure that the code type is not included in the hash.
ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
......
......@@ -382,7 +382,7 @@ class StubCache {
// We always set the in_loop bit to zero when generating the lookup code
// so do it here too so the hash codes match.
uint32_t iflags =
(static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
(static_cast<uint32_t>(flags) & ~Code::ICInLoopField::kMask);
uint32_t key = seed - string_low32bits + iflags;
return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
}
......
......@@ -203,16 +203,17 @@ inline int StrLength(const char* string) {
template<class T, int shift, int size>
class BitField {
public:
// A uint32_t mask of bit field. To use all bits of a uint32 in a
// bitfield without compiler warnings we have to compute 2^32 without
// using a shift count of 32.
static const uint32_t kMask = ((1U << shift) << size) - (1U << shift);
// Value for the field with all bits set.
static const T kMax = static_cast<T>((1U << size) - 1);
// Tells whether the provided value fits into the bit field.
static bool is_valid(T value) {
return (static_cast<uint32_t>(value) & ~((1U << (size)) - 1)) == 0;
}
// Returns a uint32_t mask of bit field.
static uint32_t mask() {
// To use all bits of a uint32 in a bitfield without compiler warnings we
// have to compute 2^32 without using a shift count of 32.
return ((1U << shift) << size) - (1U << shift);
return (static_cast<uint32_t>(value) & ~kMax) == 0;
}
// Returns a uint32_t with the bit field value encoded.
......@@ -223,17 +224,12 @@ class BitField {
// Returns a uint32_t with the bit field value updated.
static uint32_t update(uint32_t previous, T value) {
return (previous & ~mask()) | encode(value);
return (previous & ~kMask) | encode(value);
}
// Extracts the bit field from the value.
static T decode(uint32_t value) {
return static_cast<T>((value & mask()) >> shift);
}
// Value for the field with all bits set.
static T max() {
return decode(mask());
return static_cast<T>((value & kMask) >> shift);
}
};
......
......@@ -145,7 +145,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
__ Test(Operand(elements, r1, times_pointer_size,
kDetailsOffset - kHeapObjectTag),
Smi::FromInt(PropertyDetails::TypeField::mask()));
Smi::FromInt(PropertyDetails::TypeField::kMask));
__ j(not_zero, miss_label);
// Get the value at the masked, scaled index.
......@@ -201,9 +201,9 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
StringDictionary::kHeaderSize +
StringDictionary::kElementsStartIndex * kPointerSize;
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
const int kTypeAndReadOnlyMask
= (PropertyDetails::TypeField::mask() |
PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
const int kTypeAndReadOnlyMask =
(PropertyDetails::TypeField::kMask |
PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
__ Test(Operand(elements,
scratch1,
times_pointer_size,
......
......@@ -3303,7 +3303,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
ASSERT_EQ(NORMAL, 0);
Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
Smi::FromInt(PropertyDetails::TypeField::mask()));
Smi::FromInt(PropertyDetails::TypeField::kMask));
j(not_zero, miss);
// Get the value at the masked, scaled index.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment