From: olivf@chromium.org Date: Thu, 16 May 2013 10:59:17 +0000 (+0000) Subject: Encapsulating Type information in the CompareICStub X-Git-Tag: upstream/4.7.83~14212 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c3dde4bd9d1cd1873aece5700274c07bd139cbef;p=platform%2Fupstream%2Fv8.git Encapsulating Type information in the CompareICStub Encapsulate type information in a convenient wrapper instead of storing it in a naked bitfield. This especially facilitates transitioning to a new state and converting from/to the extraICState representation. Additionally cleaning up ToBooleanICStub::Types for consistency. BUG= R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/14862009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14704 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/code-stubs.cc b/src/code-stubs.cc index 1847140..312febc 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -408,41 +408,50 @@ void ICCompareStub::Generate(MacroAssembler* masm) { } -CompareNilICStub::Types CompareNilICStub::GetPatchedICFlags( - Code::ExtraICState extra_ic_state, - Handle object, - bool* already_monomorphic) { - Types types = TypesField::decode(extra_ic_state); - NilValue nil = NilValueField::decode(extra_ic_state); - EqualityKind kind = EqualityKindField::decode(extra_ic_state); - ASSERT(types != CompareNilICStub::kFullCompare); - *already_monomorphic = - (types & CompareNilICStub::kCompareAgainstMonomorphicMap) != 0; - if (kind == kStrictEquality) { - if (nil == kNullValue) { - return CompareNilICStub::kCompareAgainstNull; - } else { - return CompareNilICStub::kCompareAgainstUndefined; - } +void CompareNilICStub::Record(Handle object) { + ASSERT(types_ != Types::FullCompare()); + if (equality_kind_ == kStrictEquality) { + // When testing for strict equality only one value will evaluate to true + types_.RemoveAll(); + types_.Add((nil_value_ == kNullValue) ? NULL_TYPE: + UNDEFINED); } else { if (object->IsNull()) { - types = static_cast( - types | CompareNilICStub::kCompareAgainstNull); + types_.Add(NULL_TYPE); } else if (object->IsUndefined()) { - types = static_cast( - types | CompareNilICStub::kCompareAgainstUndefined); + types_.Add(UNDEFINED); } else if (object->IsUndetectableObject() || object->IsOddball() || !object->IsHeapObject()) { - types = CompareNilICStub::kFullCompare; - } else if ((types & CompareNilICStub::kCompareAgainstMonomorphicMap) != 0) { - types = CompareNilICStub::kFullCompare; + types_ = Types::FullCompare(); + } else if (IsMonomorphic()) { + types_ = Types::FullCompare(); } else { - types = static_cast( - types | CompareNilICStub::kCompareAgainstMonomorphicMap); + types_.Add(MONOMORPHIC_MAP); } } - return types; +} + + +void CompareNilICStub::PrintName(StringStream* stream) { + stream->Add("CompareNilICStub_"); + types_.Print(stream); + stream->Add((nil_value_ == kNullValue) ? "(NullValue|": + "(UndefinedValue|"); + stream->Add((equality_kind_ == kStrictEquality) ? "StrictEquality)": + "NonStrictEquality)"); +} + + +void CompareNilICStub::Types::Print(StringStream* stream) const { + stream->Add("("); + SimpleListPrinter printer(stream); + if (IsEmpty()) printer.Add("None"); + if (Contains(UNDEFINED)) printer.Add("Undefined"); + if (Contains(NULL_TYPE)) printer.Add("Null"); + if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap"); + if (Contains(UNDETECTABLE)) printer.Add("Undetectable"); + stream->Add(")"); } @@ -552,15 +561,18 @@ void ToBooleanStub::PrintName(StringStream* stream) { void ToBooleanStub::Types::Print(StringStream* stream) const { - if (IsEmpty()) stream->Add("None"); - if (Contains(UNDEFINED)) stream->Add("Undefined"); - if (Contains(BOOLEAN)) stream->Add("Bool"); - if (Contains(NULL_TYPE)) stream->Add("Null"); - if (Contains(SMI)) stream->Add("Smi"); - if (Contains(SPEC_OBJECT)) stream->Add("SpecObject"); - if (Contains(STRING)) stream->Add("String"); - if (Contains(SYMBOL)) stream->Add("Symbol"); - if (Contains(HEAP_NUMBER)) stream->Add("HeapNumber"); + stream->Add("("); + SimpleListPrinter printer(stream); + if (IsEmpty()) printer.Add("None"); + if (Contains(UNDEFINED)) printer.Add("Undefined"); + if (Contains(BOOLEAN)) printer.Add("Bool"); + if (Contains(NULL_TYPE)) printer.Add("Null"); + if (Contains(SMI)) printer.Add("Smi"); + if (Contains(SPEC_OBJECT)) printer.Add("SpecObject"); + if (Contains(STRING)) printer.Add("String"); + if (Contains(SYMBOL)) printer.Add("Symbol"); + if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber"); + stream->Add(")"); } diff --git a/src/code-stubs.h b/src/code-stubs.h index 646aee2..aa6a410 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 { + public: + Types() : EnumSet(0) { } + explicit Types(byte bits) : EnumSet(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 GenerateCode(); - static Handle 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 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< object, - bool* already_monomorphic); + void Record(Handle 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 {}; - class NilValueField : public BitField {}; - class TypesField : public BitField {}; + 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 { + }; + class NilValueField : public BitField {}; + 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 { public: Types() {} - explicit Types(byte bits) : set_(bits) {} + explicit Types(byte bits) : EnumSet(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); bool NeedsMap() const; bool CanBeUndetectable() const; - - private: - EnumSet 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->set_to_boolean_state(types_.ToByte()); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index de3254a..939a5fa 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -1812,27 +1812,27 @@ void HGraphBuilder::BuildCompareNil( HIfContinuation* continuation) { IfBuilder if_nil(this, position); bool needs_or = false; - if ((types & CompareNilICStub::kCompareAgainstNull) != 0) { + if (types.Contains(CompareNilICStub::NULL_TYPE)) { if (needs_or) if_nil.Or(); if_nil.If(value, graph()->GetConstantNull()); needs_or = true; } - if ((types & CompareNilICStub::kCompareAgainstUndefined) != 0) { + if (types.Contains(CompareNilICStub::UNDEFINED)) { if (needs_or) if_nil.Or(); if_nil.If(value, graph()->GetConstantUndefined()); needs_or = true; } // Handle either undetectable or monomorphic, not both. - ASSERT(((types & CompareNilICStub::kCompareAgainstUndetectable) == 0) || - ((types & CompareNilICStub::kCompareAgainstMonomorphicMap) == 0)); - if ((types & CompareNilICStub::kCompareAgainstUndetectable) != 0) { + ASSERT(!types.Contains(CompareNilICStub::UNDETECTABLE) || + !types.Contains(CompareNilICStub::MONOMORPHIC_MAP)); + if (types.Contains(CompareNilICStub::UNDETECTABLE)) { if (needs_or) if_nil.Or(); if_nil.If(value); } else { if_nil.Then(); if_nil.Else(); - if ((types & CompareNilICStub::kCompareAgainstMonomorphicMap) != 0) { + if (types.Contains(CompareNilICStub::MONOMORPHIC_MAP)) { BuildCheckNonSmi(value); // For ICs, the map checked below is a sentinel map that gets replaced by // the monomorphic map when the code is used as a template to generate a @@ -10823,15 +10823,13 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, TypeFeedbackId id = expr->CompareOperationFeedbackId(); CompareNilICStub::Types types; if (kind == kStrictEquality) { - if (nil == kNullValue) { - types = CompareNilICStub::kCompareAgainstNull; - } else { - types = CompareNilICStub::kCompareAgainstUndefined; - } + types.Add((nil == kNullValue) ? CompareNilICStub::NULL_TYPE : + CompareNilICStub::UNDEFINED); } else { - types = static_cast( - oracle()->CompareNilTypes(id)); - if (types == 0) types = CompareNilICStub::kFullCompare; + types = CompareNilICStub::Types(oracle()->CompareNilTypes(id)); + if (types.IsEmpty()) { + types = CompareNilICStub::Types::FullCompare(); + } } Handle map_handle(oracle()->CompareNilMonomorphicReceiverType(id)); BuildCompareNil(value, kind, types, map_handle, diff --git a/src/ic.cc b/src/ic.cc index 75c22c4..ea0c1fb 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -2888,25 +2888,17 @@ RUNTIME_FUNCTION(Code*, CompareIC_Miss) { } -Code* CompareNilIC::GetRawUninitialized(EqualityKind kind, - NilValue nil) { - CompareNilICStub stub(kind, nil); - Code* code = NULL; - CHECK(stub.FindCodeInCache(&code, Isolate::Current())); - return code; -} - - void CompareNilIC::Clear(Address address, Code* target) { if (target->ic_state() == UNINITIALIZED) return; Code::ExtraICState state = target->extended_extra_ic_state(); - EqualityKind kind = - CompareNilICStub::EqualityKindFromExtraICState(state); - NilValue nil = - CompareNilICStub::NilValueFromExtraICState(state); + CompareNilICStub stub(state, CompareNilICStub::CODE_STUB_IS_MISS); + stub.ClearTypes(); - SetTargetAtAddress(address, GetRawUninitialized(kind, nil)); + Code* code = NULL; + CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); + + SetTargetAtAddress(address, code); } @@ -2930,28 +2922,24 @@ MaybeObject* CompareNilIC::DoCompareNilSlow(EqualityKind kind, MaybeObject* CompareNilIC::CompareNil(Handle object) { Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state(); + CompareNilICStub stub(extra_ic_state); + // Extract the current supported types from the patched IC and calculate what // types must be supported as a result of the miss. - bool already_monomorphic; - CompareNilICStub::Types types = - CompareNilICStub::GetPatchedICFlags(extra_ic_state, - object, &already_monomorphic); + bool already_monomorphic = stub.IsMonomorphic(); + + stub.Record(object); - EqualityKind kind = - CompareNilICStub::EqualityKindFromExtraICState(extra_ic_state); - NilValue nil = - CompareNilICStub::NilValueFromExtraICState(extra_ic_state); + EqualityKind kind = stub.GetKind(); + NilValue nil = stub.GetNilValue(); // Find or create the specialized stub to support the new set of types. - CompareNilICStub stub(kind, nil, types); Handle code; - if ((types & CompareNilICStub::kCompareAgainstMonomorphicMap) != 0) { + if (stub.IsMonomorphic()) { Handle monomorphic_map(already_monomorphic ? target()->FindFirstMap() : HeapObject::cast(*object)->map()); - code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, - nil, - stub.GetTypes()); + code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); } else { code = stub.GetCode(isolate()); } diff --git a/src/ic.h b/src/ic.h index 739f34c..a044f0c 100644 --- a/src/ic.h +++ b/src/ic.h @@ -787,8 +787,6 @@ class CompareNilIC: public IC { static Handle GetUninitialized(); - static Code* GetRawUninitialized(EqualityKind kind, NilValue nil); - static void Clear(Address address, Code* target); void patch(Code* code); diff --git a/src/objects.cc b/src/objects.cc index 845fd45..ba7cdb1 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -9844,9 +9844,10 @@ void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { VisitExternalReferences(p, p + 1); } -byte Code::compare_nil_state() { +byte Code::compare_nil_types() { ASSERT(is_compare_nil_ic_stub()); - return CompareNilICStub::TypesFromExtraICState(extended_extra_ic_state()); + return CompareNilICStub::ExtractTypesFromExtraICState( + extended_extra_ic_state()); } diff --git a/src/objects.h b/src/objects.h index 6787da5..d466f65 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4620,7 +4620,7 @@ class Code: public HeapObject { inline void set_to_boolean_state(byte value); // [compare_nil]: For kind COMPARE_NIL_IC tells what state the stub is in. - byte compare_nil_state(); + byte compare_nil_types(); // [has_function_cache]: For kind STUB tells whether there is a function // cache is passed to the stub. diff --git a/src/string-stream.h b/src/string-stream.h index 0ba8f52..88b4afe 100644 --- a/src/string-stream.h +++ b/src/string-stream.h @@ -187,6 +187,31 @@ class StringStream { }; +// Utility class to print a list of items to a stream, divided by a separator. +class SimpleListPrinter { + public: + explicit SimpleListPrinter(StringStream* stream, char separator = ',') { + separator_ = separator; + stream_ = stream; + first_ = true; + } + + void Add(const char* str) { + if (first_) { + first_ = false; + } else { + stream_->Put(separator_); + } + stream_->Add(str); + } + + private: + bool first_; + char separator_; + StringStream* stream_; +}; + + } } // namespace v8::internal #endif // V8_STRING_STREAM_H_ diff --git a/src/stub-cache.cc b/src/stub-cache.cc index f43c9ac..89dee10 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -907,9 +907,8 @@ Handle StubCache::ComputeCallMiss(int argc, Handle StubCache::ComputeCompareNil(Handle receiver_map, - NilValue nil, - CompareNilICStub::Types types) { - CompareNilICStub stub(kNonStrictEquality, nil, types); + CompareNilICStub& stub) { + stub.SetKind(kNonStrictEquality); Handle name(isolate_->heap()->empty_string()); if (!receiver_map->is_shared()) { diff --git a/src/stub-cache.h b/src/stub-cache.h index cbaeace..9365d96 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -281,8 +281,7 @@ class StubCache { // --- Handle ComputeCompareNil(Handle receiver_map, - NilValue nil, - CompareNilICStub::Types types); + CompareNilICStub& stub); // --- diff --git a/src/type-info.cc b/src/type-info.cc index d52536e..21dcf74 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -643,9 +643,9 @@ byte TypeFeedbackOracle::CompareNilTypes(TypeFeedbackId id) { Handle object = GetInfo(id); if (object->IsCode() && Handle::cast(object)->is_compare_nil_ic_stub()) { - return Handle::cast(object)->compare_nil_state(); + return Handle::cast(object)->compare_nil_types(); } else { - return CompareNilICStub::kFullCompare; + return CompareNilICStub::Types::FullCompare().ToIntegral(); } } diff --git a/src/utils.h b/src/utils.h index 90d7f3c..93cded1 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1040,6 +1040,7 @@ class EnumSet { void Intersect(const EnumSet& set) { bits_ &= set.bits_; } T ToIntegral() const { return bits_; } bool operator==(const EnumSet& set) { return bits_ == set.bits_; } + bool operator!=(const EnumSet& set) { return bits_ != set.bits_; } EnumSet operator|(const EnumSet& set) const { return EnumSet(bits_ | set.bits_); } diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index ecffeaa..0a91ed5 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -53,6 +53,7 @@ 'test-bignum.cc', 'test-bignum-dtoa.cc', 'test-circular-queue.cc', + 'test-compare-nil-ic-stub.cc', 'test-compiler.cc', 'test-conversions.cc', 'test-cpu-profiler.cc', diff --git a/test/cctest/test-compare-nil-ic-stub.cc b/test/cctest/test-compare-nil-ic-stub.cc new file mode 100644 index 0000000..6177fde --- /dev/null +++ b/test/cctest/test-compare-nil-ic-stub.cc @@ -0,0 +1,86 @@ +// Copyright 2006-2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "v8.h" +#include "cctest.h" +#include "code-stubs.h" + + +using namespace v8::internal; + +#define Types CompareNilICStub::Types + +TEST(TypeConstructors) { + Types types; + types.Add(CompareNilICStub::MONOMORPHIC_MAP); + Types types2(types); + CHECK_EQ(types.ToIntegral(), types2.ToIntegral()); +} + +TEST(ExternalICStateParsing) { + Types types; + types.Add(CompareNilICStub::UNDEFINED); + CompareNilICStub stub(kNonStrictEquality, kUndefinedValue, types); + CompareNilICStub stub2(stub.GetExtraICState()); + CHECK_EQ(stub.GetKind(), stub2.GetKind()); + CHECK_EQ(stub.GetNilValue(), stub2.GetNilValue()); + CHECK_EQ(stub.GetTypes().ToIntegral(), stub2.GetTypes().ToIntegral()); +} + +TEST(SettingTypes) { + Types state; + CHECK(state.IsEmpty()); + state.Add(CompareNilICStub::NULL_TYPE); + CHECK(!state.IsEmpty()); + CHECK(state.Contains(CompareNilICStub::NULL_TYPE)); + CHECK(!state.Contains(CompareNilICStub::UNDEFINED)); + CHECK(!state.Contains(CompareNilICStub::UNDETECTABLE)); + state.Add(CompareNilICStub::UNDEFINED); + CHECK(state.Contains(CompareNilICStub::UNDEFINED)); + CHECK(state.Contains(CompareNilICStub::NULL_TYPE)); + CHECK(!state.Contains(CompareNilICStub::UNDETECTABLE)); +} + +TEST(ClearTypes) { + Types state; + state.Add(CompareNilICStub::NULL_TYPE); + state.RemoveAll(); + CHECK(state.IsEmpty()); +} + +TEST(FullCompare) { + Types state; + CHECK(Types::FullCompare() != state); + state.Add(CompareNilICStub::UNDEFINED); + CHECK(state != Types::FullCompare()); + state.Add(CompareNilICStub::NULL_TYPE); + CHECK(state != Types::FullCompare()); + state.Add(CompareNilICStub::UNDETECTABLE); + CHECK(state == Types::FullCompare()); +}