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
This commit is contained in:
parent
28aca51e8f
commit
bdf4fc96b0
@ -784,8 +784,7 @@ HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
|
||||
CompareNilICStub* stub = casted_stub();
|
||||
HIfContinuation continuation;
|
||||
Handle<Map> sentinel_map(isolate->heap()->meta_map());
|
||||
Handle<Type> type =
|
||||
CompareNilICStub::StateToType(isolate, stub->GetState(), sentinel_map);
|
||||
Handle<Type> type = stub->GetType(isolate, sentinel_map);
|
||||
BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation);
|
||||
IfBuilder if_nil(this, &continuation);
|
||||
if_nil.Then();
|
||||
|
@ -534,7 +534,7 @@ void ICCompareStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void CompareNilICStub::UpdateStatus(Handle<Object> 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> 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<Type> CompareNilICStub::StateToType(
|
||||
Handle<Type> CompareNilICStub::GetType(
|
||||
Isolate* isolate,
|
||||
State state,
|
||||
Handle<Map> map) {
|
||||
if (state.Contains(CompareNilICStub::GENERIC)) {
|
||||
if (state_.Contains(CompareNilICStub::GENERIC)) {
|
||||
return handle(Type::Any(), isolate);
|
||||
}
|
||||
|
||||
Handle<Type> 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<Type> CompareNilICStub::StateToType(
|
||||
}
|
||||
|
||||
|
||||
Handle<Type> CompareNilICStub::GetInputType(
|
||||
Isolate* isolate,
|
||||
Handle<Map> map) {
|
||||
Handle<Type> output_type = GetType(isolate, map);
|
||||
Handle<Type> 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()) {
|
||||
|
@ -1260,49 +1260,16 @@ class ICCompareStub: public PlatformCodeStub {
|
||||
|
||||
class CompareNilICStub : public HydrogenCodeStub {
|
||||
public:
|
||||
enum CompareNilType {
|
||||
UNDEFINED,
|
||||
NULL_TYPE,
|
||||
MONOMORPHIC_MAP,
|
||||
UNDETECTABLE,
|
||||
GENERIC,
|
||||
NUMBER_OF_TYPES
|
||||
};
|
||||
Handle<Type> GetType(Isolate* isolate, Handle<Map> map = Handle<Map>());
|
||||
Handle<Type> GetInputType(Isolate* isolate, Handle<Map> map);
|
||||
|
||||
class State : public EnumSet<CompareNilType, byte> {
|
||||
public:
|
||||
State() : EnumSet<CompareNilType, byte>(0) { }
|
||||
explicit State(byte bits) : EnumSet<CompareNilType, byte>(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<Type> StateToType(
|
||||
Isolate* isolate, State state, Handle<Map> map = Handle<Map>());
|
||||
|
||||
// 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<Code> GetUninitialized(Isolate* isolate,
|
||||
@ -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<Code> 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> 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<NilValue, NUMBER_OF_TYPES, 1> {};
|
||||
// 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<CompareNilType, byte> {
|
||||
public:
|
||||
State() : EnumSet<CompareNilType, byte>(0) { }
|
||||
explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
|
||||
|
||||
void Print(StringStream* stream) const;
|
||||
};
|
||||
|
||||
CompareNilICStub(NilValue nil, InitializationState init_state)
|
||||
: HydrogenCodeStub(init_state), nil_value_(nil) { }
|
||||
|
||||
class NilValueField : public BitField<NilValue, 0, 1> {};
|
||||
class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {};
|
||||
|
||||
virtual CodeStub::Major MajorKey() { return CompareNilIC; }
|
||||
virtual int NotMissMinorKey() { return GetExtraICState(); }
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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<Type> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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 <stdlib.h>
|
||||
|
||||
#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());
|
||||
}
|
Loading…
Reference in New Issue
Block a user