Index: src/code-stubs.h |
diff --git a/src/code-stubs.h b/src/code-stubs.h |
index 646aee23eb2b87c4ae6ba26c901dd84fdb773cf2..aa6a4101951f3d762df2659d2ae870a677a91cc7 100644 |
--- a/src/code-stubs.h |
+++ b/src/code-stubs.h |
@@ -1047,41 +1047,52 @@ class ICCompareStub: public PlatformCodeStub { |
class CompareNilICStub : public HydrogenCodeStub { |
public: |
- enum Types { |
- kCompareAgainstNull = 1 << 0, |
- kCompareAgainstUndefined = 1 << 1, |
- kCompareAgainstMonomorphicMap = 1 << 2, |
- kCompareAgainstUndetectable = 1 << 3, |
- kFullCompare = kCompareAgainstNull | kCompareAgainstUndefined | |
- kCompareAgainstUndetectable |
+ enum Type { |
+ UNDEFINED, |
+ NULL_TYPE, |
+ MONOMORPHIC_MAP, |
+ UNDETECTABLE, |
+ NUMBER_OF_TYPES |
+ }; |
+ |
+ class Types : public EnumSet<Type, byte> { |
+ public: |
+ Types() : EnumSet<Type, byte>(0) { } |
+ explicit Types(byte bits) : EnumSet<Type, byte>(bits) { } |
+ |
+ static Types FullCompare() { |
+ Types set; |
+ set.Add(UNDEFINED); |
+ set.Add(NULL_TYPE); |
+ set.Add(UNDETECTABLE); |
+ return set; |
+ } |
+ |
+ void Print(StringStream* stream) const; |
}; |
+ // At most 6 different types can be distinguished, because the Code object |
+ // only has room for a single byte to hold a set and there are two more |
+ // boolean flags we need to store. :-P |
+ STATIC_ASSERT(NUMBER_OF_TYPES <= 6); |
+ |
CompareNilICStub(EqualityKind kind, NilValue nil, Types types) |
- : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS), bit_field_(0) { |
- bit_field_ = EqualityKindField::encode(kind) | |
- NilValueField::encode(nil) | |
- TypesField::encode(types); |
+ : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS), types_(types) { |
+ equality_kind_ = kind; |
+ nil_value_ = nil; |
} |
- virtual InlineCacheState GetICState() { |
- Types types = GetTypes(); |
- if (types == kFullCompare) { |
- return MEGAMORPHIC; |
- } else if ((types & kCompareAgainstMonomorphicMap) != 0) { |
- return MONOMORPHIC; |
- } else { |
- return PREMONOMORPHIC; |
- } |
+ explicit CompareNilICStub(Code::ExtraICState ic_state) |
+ : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) { |
+ equality_kind_ = EqualityKindField::decode(ic_state); |
+ nil_value_ = NilValueField::decode(ic_state); |
+ types_ = Types(ExtractTypesFromExtraICState(ic_state)); |
} |
- virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; } |
- |
- Handle<Code> GenerateCode(); |
- |
static Handle<Code> GetUninitialized(Isolate* isolate, |
EqualityKind kind, |
NilValue nil) { |
- return CompareNilICStub(kind, nil).GetCode(isolate); |
+ return CompareNilICStub(kind, nil, CODE_STUB_IS_MISS).GetCode(isolate); |
} |
virtual void InitializeInterfaceDescriptor( |
@@ -1089,53 +1100,76 @@ class CompareNilICStub : public HydrogenCodeStub { |
CodeStubInterfaceDescriptor* descriptor); |
static void InitializeForIsolate(Isolate* isolate) { |
- CompareNilICStub compare_stub(kStrictEquality, kNullValue); |
+ CompareNilICStub compare_stub(kStrictEquality, kNullValue, |
+ CODE_STUB_IS_MISS); |
compare_stub.InitializeInterfaceDescriptor( |
isolate, |
isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC)); |
} |
- virtual Code::ExtraICState GetExtraICState() { |
- return bit_field_; |
+ virtual InlineCacheState GetICState() { |
+ if (types_ == Types::FullCompare()) { |
+ return MEGAMORPHIC; |
+ } else if (types_.Contains(MONOMORPHIC_MAP)) { |
+ return MONOMORPHIC; |
+ } else { |
+ return PREMONOMORPHIC; |
+ } |
} |
- EqualityKind GetKind() { return EqualityKindField::decode(bit_field_); } |
- NilValue GetNilValue() { return NilValueField::decode(bit_field_); } |
- Types GetTypes() { return TypesField::decode(bit_field_); } |
+ virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; } |
- static Types TypesFromExtraICState( |
- Code::ExtraICState state) { |
- return TypesField::decode(state); |
+ Handle<Code> GenerateCode(); |
+ |
+ // extra ic state = nil_value | equality_kind | type_n-1 | ... | type_0 |
+ virtual Code::ExtraICState GetExtraICState() { |
+ return NilValueField::encode(nil_value_) | |
+ EqualityKindField::encode(equality_kind_) | |
+ types_.ToIntegral(); |
} |
- static EqualityKind EqualityKindFromExtraICState( |
+ static byte ExtractTypesFromExtraICState( |
Code::ExtraICState state) { |
- return EqualityKindField::decode(state); |
- } |
- static NilValue NilValueFromExtraICState(Code::ExtraICState state) { |
- return NilValueField::decode(state); |
+ return state & ((1<<NUMBER_OF_TYPES)-1); |
} |
- static Types GetPatchedICFlags(Code::ExtraICState extra_ic_state, |
- Handle<Object> object, |
- bool* already_monomorphic); |
+ void Record(Handle<Object> object); |
+ |
+ bool IsMonomorphic() const { return types_.Contains(MONOMORPHIC_MAP); } |
+ EqualityKind GetKind() const { return equality_kind_; } |
+ NilValue GetNilValue() const { return nil_value_; } |
+ Types GetTypes() const { return types_; } |
+ void ClearTypes() { types_.RemoveAll(); } |
+ void SetKind(EqualityKind kind) { equality_kind_ = kind; } |
+ |
+ virtual void PrintName(StringStream* stream); |
private: |
friend class CompareNilIC; |
- class EqualityKindField : public BitField<EqualityKind, 0, 1> {}; |
- class NilValueField : public BitField<NilValue, 1, 1> {}; |
- class TypesField : public BitField<Types, 3, 4> {}; |
+ CompareNilICStub(EqualityKind kind, NilValue nil, |
+ InitializationState init_state) |
+ : HydrogenCodeStub(init_state), types_(0) { |
+ equality_kind_ = kind; |
+ nil_value_ = nil; |
+ } |
- CompareNilICStub(EqualityKind kind, NilValue nil) |
- : HydrogenCodeStub(CODE_STUB_IS_MISS), bit_field_(0) { |
- bit_field_ = EqualityKindField::encode(kind) | |
- NilValueField::encode(nil); |
+ CompareNilICStub(Code::ExtraICState ic_state, InitializationState init_state) |
+ : HydrogenCodeStub(init_state) { |
+ equality_kind_ = EqualityKindField::decode(ic_state); |
+ nil_value_ = NilValueField::decode(ic_state); |
+ types_ = Types(ExtractTypesFromExtraICState(ic_state)); |
} |
+ class EqualityKindField : public BitField<EqualityKind, NUMBER_OF_TYPES, 1> { |
+ }; |
+ class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES+1, 1> {}; |
+ |
virtual CodeStub::Major MajorKey() { return CompareNilIC; } |
- virtual int NotMissMinorKey() { return bit_field_; } |
+ virtual int NotMissMinorKey() { return GetExtraICState(); } |
- int bit_field_; |
+ EqualityKind equality_kind_; |
+ NilValue nil_value_; |
+ Types types_; |
DISALLOW_COPY_AND_ASSIGN(CompareNilICStub); |
}; |
@@ -1795,26 +1829,17 @@ class ToBooleanStub: public PlatformCodeStub { |
// only has room for a single byte to hold a set of these types. :-P |
STATIC_ASSERT(NUMBER_OF_TYPES <= 8); |
- class Types { |
+ class Types : public EnumSet<Type, byte> { |
public: |
Types() {} |
- explicit Types(byte bits) : set_(bits) {} |
+ explicit Types(byte bits) : EnumSet<Type, byte>(bits) {} |
- bool IsEmpty() const { return set_.IsEmpty(); } |
- bool Contains(Type type) const { return set_.Contains(type); } |
- bool ContainsAnyOf(Types types) const { |
- return set_.ContainsAnyOf(types.set_); |
- } |
- void Add(Type type) { set_.Add(type); } |
- byte ToByte() const { return set_.ToIntegral(); } |
+ byte ToByte() const { return ToIntegral(); } |
void Print(StringStream* stream) const; |
void TraceTransition(Types to) const; |
bool Record(Handle<Object> object); |
bool NeedsMap() const; |
bool CanBeUndetectable() const; |
- |
- private: |
- EnumSet<Type, byte> set_; |
}; |
static Types no_types() { return Types(); } |
@@ -1831,7 +1856,8 @@ class ToBooleanStub: public PlatformCodeStub { |
private: |
Major MajorKey() { return ToBoolean; } |
- int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); } |
+ int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | |
+ types_.ToByte(); } |
virtual void FinishCode(Handle<Code> code) { |
code->set_to_boolean_state(types_.ToByte()); |