| 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());
|
|
|