From bdf4fc96b0d35cceab1dd2d2d214c046e23edc48 Mon Sep 17 00:00:00 2001 From: "olivf@chromium.org" Date: Thu, 11 Jul 2013 17:20:57 +0000 Subject: [PATCH] Encapsulate compare nil ic_state. BUG= R=rossberg@chromium.org Review URL: https://codereview.chromium.org/18602003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15639 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/code-stubs-hydrogen.cc | 3 +- src/code-stubs.cc | 33 +++++---- src/code-stubs.h | 90 ++++++++++-------------- src/objects.cc | 14 ---- src/objects.h | 4 -- src/type-info.cc | 9 +-- test/cctest/cctest.gyp | 1 - test/cctest/test-compare-nil-ic-stub.cc | 91 ------------------------- 8 files changed, 59 insertions(+), 186 deletions(-) delete mode 100644 test/cctest/test-compare-nil-ic-stub.cc diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index b6e5ffd2ce..d5bb5e7ed1 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -784,8 +784,7 @@ HValue* CodeStubGraphBuilder::BuildCodeInitializedStub() { CompareNilICStub* stub = casted_stub(); HIfContinuation continuation; Handle sentinel_map(isolate->heap()->meta_map()); - Handle type = - CompareNilICStub::StateToType(isolate, stub->GetState(), sentinel_map); + Handle type = stub->GetType(isolate, sentinel_map); BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation); IfBuilder if_nil(this, &continuation); if_nil.Then(); diff --git a/src/code-stubs.cc b/src/code-stubs.cc index efeba633f1..5f6616ea07 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -534,7 +534,7 @@ void ICCompareStub::Generate(MacroAssembler* masm) { void CompareNilICStub::UpdateStatus(Handle object) { - ASSERT(state_ != State::Generic()); + ASSERT(!state_.Contains(GENERIC)); State old_state(state_); if (object->IsNull()) { state_.Add(NULL_TYPE); @@ -543,9 +543,11 @@ void CompareNilICStub::UpdateStatus(Handle object) { } else if (object->IsUndetectableObject() || object->IsOddball() || !object->IsHeapObject()) { - state_ = State::Generic(); + state_.RemoveAll(); + state_.Add(GENERIC); } else if (IsMonomorphic()) { - state_ = State::Generic(); + state_.RemoveAll(); + state_.Add(GENERIC); } else { state_.Add(MONOMORPHIC_MAP); } @@ -592,33 +594,28 @@ void CompareNilICStub::State::Print(StringStream* stream) const { 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"); if (Contains(GENERIC)) printer.Add("Generic"); stream->Add(")"); } -Handle CompareNilICStub::StateToType( +Handle CompareNilICStub::GetType( Isolate* isolate, - State state, Handle map) { - if (state.Contains(CompareNilICStub::GENERIC)) { + if (state_.Contains(CompareNilICStub::GENERIC)) { return handle(Type::Any(), isolate); } Handle result(Type::None(), isolate); - if (state.Contains(CompareNilICStub::UNDEFINED)) { + if (state_.Contains(CompareNilICStub::UNDEFINED)) { result = handle(Type::Union(result, handle(Type::Undefined(), isolate)), isolate); } - if (state.Contains(CompareNilICStub::NULL_TYPE)) { + if (state_.Contains(CompareNilICStub::NULL_TYPE)) { result = handle(Type::Union(result, handle(Type::Null(), isolate)), isolate); } - if (state.Contains(CompareNilICStub::UNDETECTABLE)) { - result = handle(Type::Union(result, handle(Type::Undetectable(), isolate)), - isolate); - } else if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) { + if (state_.Contains(CompareNilICStub::MONOMORPHIC_MAP)) { Type* type = map.is_null() ? Type::Detectable() : Type::Class(map); result = handle(Type::Union(result, handle(type, isolate)), isolate); } @@ -627,6 +624,16 @@ Handle CompareNilICStub::StateToType( } +Handle CompareNilICStub::GetInputType( + Isolate* isolate, + Handle map) { + Handle output_type = GetType(isolate, map); + Handle nil_type = handle(nil_value_ == kNullValue + ? Type::Null() : Type::Undefined(), isolate); + return handle(Type::Union(output_type, nil_type), isolate); +} + + void InstanceofStub::PrintName(StringStream* stream) { const char* args = ""; if (HasArgsInRegisters()) { diff --git a/src/code-stubs.h b/src/code-stubs.h index eb80859ccb..2555592da8 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -1260,50 +1260,17 @@ class ICCompareStub: public PlatformCodeStub { class CompareNilICStub : public HydrogenCodeStub { public: - enum CompareNilType { - UNDEFINED, - NULL_TYPE, - MONOMORPHIC_MAP, - UNDETECTABLE, - GENERIC, - NUMBER_OF_TYPES - }; + Handle GetType(Isolate* isolate, Handle map = Handle()); + Handle GetInputType(Isolate* isolate, Handle map); - class State : public EnumSet { - public: - State() : EnumSet(0) { } - explicit State(byte bits) : EnumSet(bits) { } - - static State Generic() { - State set; - set.Add(UNDEFINED); - set.Add(NULL_TYPE); - set.Add(UNDETECTABLE); - set.Add(GENERIC); - return set; - } - - void Print(StringStream* stream) const; - }; - - static Handle StateToType( - Isolate* isolate, State state, Handle map = Handle()); - - // 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(NilValue nil, State state = State()) - : nil_value_(nil), state_(state) { - } + explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { } CompareNilICStub(Code::ExtraICState ic_state, InitializationState init_state = INITIALIZED) - : HydrogenCodeStub(init_state) { - nil_value_ = NilValueField::decode(ic_state); - state_ = State(ExtractTypesFromExtraICState(ic_state)); - } + : HydrogenCodeStub(init_state), + nil_value_(NilValueField::decode(ic_state)), + state_(State(TypesField::decode(ic_state))) { + } static Handle GetUninitialized(Isolate* isolate, NilValue nil) { @@ -1322,7 +1289,7 @@ class CompareNilICStub : public HydrogenCodeStub { } virtual InlineCacheState GetICState() { - if (state_ == State::Generic()) { + if (state_.Contains(GENERIC)) { return MEGAMORPHIC; } else if (state_.Contains(MONOMORPHIC_MAP)) { return MONOMORPHIC; @@ -1335,22 +1302,15 @@ class CompareNilICStub : public HydrogenCodeStub { Handle GenerateCode(); - // extra ic state = nil_value | type_n-1 | ... | type_0 virtual Code::ExtraICState GetExtraICState() { - return NilValueField::encode(nil_value_) | state_.ToIntegral(); - } - static byte ExtractTypesFromExtraICState(Code::ExtraICState state) { - return state & ((1 << NUMBER_OF_TYPES) - 1); - } - static NilValue ExtractNilValueFromExtraICState(Code::ExtraICState state) { - return NilValueField::decode(state); + return NilValueField::encode(nil_value_) | + TypesField::encode(state_.ToIntegral()); } void UpdateStatus(Handle object); bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); } NilValue GetNilValue() const { return nil_value_; } - State GetState() const { return state_; } void ClearState() { state_.RemoveAll(); } virtual void PrintState(StringStream* stream); @@ -1359,12 +1319,32 @@ class CompareNilICStub : public HydrogenCodeStub { private: friend class CompareNilIC; - CompareNilICStub(NilValue nil, InitializationState init_state) - : HydrogenCodeStub(init_state) { - nil_value_ = nil; - } + enum CompareNilType { + UNDEFINED, + NULL_TYPE, + MONOMORPHIC_MAP, + GENERIC, + NUMBER_OF_TYPES + }; - class NilValueField : public BitField {}; + // 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); + + class State : public EnumSet { + public: + State() : EnumSet(0) { } + explicit State(byte bits) : EnumSet(bits) { } + + void Print(StringStream* stream) const; + }; + + CompareNilICStub(NilValue nil, InitializationState init_state) + : HydrogenCodeStub(init_state), nil_value_(nil) { } + + class NilValueField : public BitField {}; + class TypesField : public BitField {}; virtual CodeStub::Major MajorKey() { return CompareNilIC; } virtual int NotMissMinorKey() { return GetExtraICState(); } diff --git a/src/objects.cc b/src/objects.cc index 05cc9e9ba6..0fe9ecef73 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -9975,20 +9975,6 @@ void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { } -byte Code::compare_nil_state() { - ASSERT(is_compare_nil_ic_stub()); - return CompareNilICStub::ExtractTypesFromExtraICState( - extended_extra_ic_state()); -} - - -byte Code::compare_nil_value() { - ASSERT(is_compare_nil_ic_stub()); - return CompareNilICStub::ExtractNilValueFromExtraICState( - extended_extra_ic_state()); -} - - void Code::InvalidateRelocation() { set_relocation_info(GetHeap()->empty_byte_array()); } diff --git a/src/objects.h b/src/objects.h index 470d8e89ae..9917047619 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4673,10 +4673,6 @@ class Code: public HeapObject { // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in. inline byte to_boolean_state(); - // [compare_nil]: For kind COMPARE_NIL_IC tells what state the stub is in. - byte compare_nil_state(); - byte compare_nil_value(); - // [has_function_cache]: For kind STUB tells whether there is a function // cache is passed to the stub. inline bool has_function_cache(); diff --git a/src/type-info.cc b/src/type-info.cc index 6db810e6ea..b905a74716 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -377,12 +377,9 @@ void TypeFeedbackOracle::CompareType(TypeFeedbackId id, CompareIC::StubInfoToType( stub_minor_key, left_type, right_type, combined_type, map, isolate()); } else if (code->is_compare_nil_ic_stub()) { - CompareNilICStub::State state(code->compare_nil_state()); - *combined_type = CompareNilICStub::StateToType(isolate_, state, map); - Handle nil_type = handle(code->compare_nil_value() == kNullValue - ? Type::Null() : Type::Undefined(), isolate_); - *left_type = *right_type = - handle(Type::Union(*combined_type, nil_type), isolate_); + CompareNilICStub stub(code->extended_extra_ic_state()); + *combined_type = stub.GetType(isolate_, map); + *left_type = *right_type = stub.GetInputType(isolate_, map); } } diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index 4e5d649743..da6a1a833b 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -54,7 +54,6 @@ '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 deleted file mode 100644 index 78bb6fd3ba..0000000000 --- a/test/cctest/test-compare-nil-ic-stub.cc +++ /dev/null @@ -1,91 +0,0 @@ -// 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; - -typedef CompareNilICStub::State State; - -TEST(StateConstructors) { - State state; - state.Add(CompareNilICStub::MONOMORPHIC_MAP); - State state2(state); - CHECK_EQ(state.ToIntegral(), state2.ToIntegral()); -} - - -TEST(ExternalICStateParsing) { - State state; - state.Add(CompareNilICStub::UNDEFINED); - CompareNilICStub stub(kUndefinedValue, state); - CompareNilICStub stub2(stub.GetExtraICState()); - CHECK_EQ(stub.GetNilValue(), stub2.GetNilValue()); - CHECK_EQ(stub.GetState().ToIntegral(), stub2.GetState().ToIntegral()); -} - - -TEST(SettingState) { - State 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(ClearState) { - State state; - state.Add(CompareNilICStub::NULL_TYPE); - state.RemoveAll(); - CHECK(state.IsEmpty()); -} - - -TEST(Generic) { - State state; - CHECK(State::Generic() != state); - state.Add(CompareNilICStub::UNDEFINED); - CHECK(state != State::Generic()); - state.Add(CompareNilICStub::NULL_TYPE); - CHECK(state != State::Generic()); - state.Add(CompareNilICStub::UNDETECTABLE); - CHECK(state != State::Generic()); - state.Add(CompareNilICStub::GENERIC); - CHECK(state == State::Generic()); -}