Commit 946ea532 authored by olivf@chromium.org's avatar olivf@chromium.org

use compare nil ic only for non-strict equality. strict-equality only has one...

use compare nil ic only for non-strict equality. strict-equality only has one check and cannot deopt. should therefore not be part of the stub.

BUG=
R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/16732002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15045 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3a26dda7
...@@ -4765,9 +4765,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, ...@@ -4765,9 +4765,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
VisitForAccumulatorValue(sub_expr); VisitForAccumulatorValue(sub_expr);
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
EqualityKind kind = expr->op() == Token::EQ_STRICT if (expr->op() == Token::EQ_STRICT) {
? kStrictEquality : kNonStrictEquality;
if (kind == kStrictEquality) {
Heap::RootListIndex nil_value = nil == kNullValue ? Heap::RootListIndex nil_value = nil == kNullValue ?
Heap::kNullValueRootIndex : Heap::kNullValueRootIndex :
Heap::kUndefinedValueRootIndex; Heap::kUndefinedValueRootIndex;
...@@ -4775,9 +4773,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, ...@@ -4775,9 +4773,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
__ cmp(r0, r1); __ cmp(r0, r1);
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
} else { } else {
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
kNonStrictEquality,
nil);
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
__ cmp(r0, Operand(0)); __ cmp(r0, Operand(0));
Split(ne, if_true, if_false, fall_through); Split(ne, if_true, if_false, fall_through);
......
...@@ -736,7 +736,7 @@ HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() { ...@@ -736,7 +736,7 @@ HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
CompareNilICStub* stub = casted_stub(); CompareNilICStub* stub = casted_stub();
HIfContinuation continuation; HIfContinuation continuation;
Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map()); Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map());
BuildCompareNil(GetParameter(0), stub->GetKind(), BuildCompareNil(GetParameter(0),
stub->GetTypes(), sentinel_map, stub->GetTypes(), sentinel_map,
RelocInfo::kNoPosition, &continuation); RelocInfo::kNoPosition, &continuation);
IfBuilder if_nil(this, &continuation); IfBuilder if_nil(this, &continuation);
......
...@@ -432,25 +432,18 @@ void ICCompareStub::Generate(MacroAssembler* masm) { ...@@ -432,25 +432,18 @@ void ICCompareStub::Generate(MacroAssembler* masm) {
void CompareNilICStub::Record(Handle<Object> object) { void CompareNilICStub::Record(Handle<Object> object) {
ASSERT(types_ != Types::FullCompare()); ASSERT(types_ != Types::FullCompare());
if (equality_kind_ == kStrictEquality) { if (object->IsNull()) {
// When testing for strict equality only one value will evaluate to true types_.Add(NULL_TYPE);
types_.RemoveAll(); } else if (object->IsUndefined()) {
types_.Add((nil_value_ == kNullValue) ? NULL_TYPE: types_.Add(UNDEFINED);
UNDEFINED); } else if (object->IsUndetectableObject() ||
object->IsOddball() ||
!object->IsHeapObject()) {
types_ = Types::FullCompare();
} else if (IsMonomorphic()) {
types_ = Types::FullCompare();
} else { } else {
if (object->IsNull()) { types_.Add(MONOMORPHIC_MAP);
types_.Add(NULL_TYPE);
} else if (object->IsUndefined()) {
types_.Add(UNDEFINED);
} else if (object->IsUndetectableObject() ||
object->IsOddball() ||
!object->IsHeapObject()) {
types_ = Types::FullCompare();
} else if (IsMonomorphic()) {
types_ = Types::FullCompare();
} else {
types_.Add(MONOMORPHIC_MAP);
}
} }
} }
...@@ -477,8 +470,6 @@ void CompareNilICStub::PrintName(StringStream* stream) { ...@@ -477,8 +470,6 @@ void CompareNilICStub::PrintName(StringStream* stream) {
types_.Print(stream); types_.Print(stream);
stream->Add((nil_value_ == kNullValue) ? "(NullValue|": stream->Add((nil_value_ == kNullValue) ? "(NullValue|":
"(UndefinedValue|"); "(UndefinedValue|");
stream->Add((equality_kind_ == kStrictEquality) ? "StrictEquality)":
"NonStrictEquality)");
} }
......
...@@ -1154,24 +1154,21 @@ class CompareNilICStub : public HydrogenCodeStub { ...@@ -1154,24 +1154,21 @@ class CompareNilICStub : public HydrogenCodeStub {
// boolean flags we need to store. :-P // boolean flags we need to store. :-P
STATIC_ASSERT(NUMBER_OF_TYPES <= 6); STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
CompareNilICStub(EqualityKind kind, NilValue nil, Types types = Types()) CompareNilICStub(NilValue nil, Types types = Types())
: types_(types) { : types_(types) {
equality_kind_ = kind;
nil_value_ = nil; nil_value_ = nil;
} }
CompareNilICStub(Code::ExtraICState ic_state, CompareNilICStub(Code::ExtraICState ic_state,
InitializationState init_state = INITIALIZED) InitializationState init_state = INITIALIZED)
: HydrogenCodeStub(init_state) { : HydrogenCodeStub(init_state) {
equality_kind_ = EqualityKindField::decode(ic_state);
nil_value_ = NilValueField::decode(ic_state); nil_value_ = NilValueField::decode(ic_state);
types_ = Types(ExtractTypesFromExtraICState(ic_state)); types_ = Types(ExtractTypesFromExtraICState(ic_state));
} }
static Handle<Code> GetUninitialized(Isolate* isolate, static Handle<Code> GetUninitialized(Isolate* isolate,
EqualityKind kind,
NilValue nil) { NilValue nil) {
return CompareNilICStub(kind, nil, UNINITIALIZED).GetCode(isolate); return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate);
} }
virtual void InitializeInterfaceDescriptor( virtual void InitializeInterfaceDescriptor(
...@@ -1179,7 +1176,7 @@ class CompareNilICStub : public HydrogenCodeStub { ...@@ -1179,7 +1176,7 @@ class CompareNilICStub : public HydrogenCodeStub {
CodeStubInterfaceDescriptor* descriptor); CodeStubInterfaceDescriptor* descriptor);
static void InitializeForIsolate(Isolate* isolate) { static void InitializeForIsolate(Isolate* isolate) {
CompareNilICStub compare_stub(kStrictEquality, kNullValue, UNINITIALIZED); CompareNilICStub compare_stub(kNullValue, UNINITIALIZED);
compare_stub.InitializeInterfaceDescriptor( compare_stub.InitializeInterfaceDescriptor(
isolate, isolate,
isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC)); isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
...@@ -1199,10 +1196,9 @@ class CompareNilICStub : public HydrogenCodeStub { ...@@ -1199,10 +1196,9 @@ class CompareNilICStub : public HydrogenCodeStub {
Handle<Code> GenerateCode(); Handle<Code> GenerateCode();
// extra ic state = nil_value | equality_kind | type_n-1 | ... | type_0 // extra ic state = nil_value | type_n-1 | ... | type_0
virtual Code::ExtraICState GetExtraICState() { virtual Code::ExtraICState GetExtraICState() {
return NilValueField::encode(nil_value_) | return NilValueField::encode(nil_value_) |
EqualityKindField::encode(equality_kind_) |
types_.ToIntegral(); types_.ToIntegral();
} }
static byte ExtractTypesFromExtraICState( static byte ExtractTypesFromExtraICState(
...@@ -1213,32 +1209,25 @@ class CompareNilICStub : public HydrogenCodeStub { ...@@ -1213,32 +1209,25 @@ class CompareNilICStub : public HydrogenCodeStub {
void Record(Handle<Object> object); void Record(Handle<Object> object);
bool IsMonomorphic() const { return types_.Contains(MONOMORPHIC_MAP); } bool IsMonomorphic() const { return types_.Contains(MONOMORPHIC_MAP); }
EqualityKind GetKind() const { return equality_kind_; }
NilValue GetNilValue() const { return nil_value_; } NilValue GetNilValue() const { return nil_value_; }
Types GetTypes() const { return types_; } Types GetTypes() const { return types_; }
void ClearTypes() { types_.RemoveAll(); } void ClearTypes() { types_.RemoveAll(); }
void SetKind(EqualityKind kind) { equality_kind_ = kind; }
virtual void PrintName(StringStream* stream); virtual void PrintName(StringStream* stream);
private: private:
friend class CompareNilIC; friend class CompareNilIC;
CompareNilICStub(EqualityKind kind, NilValue nil, CompareNilICStub(NilValue nil, InitializationState init_state)
InitializationState init_state)
: HydrogenCodeStub(init_state) { : HydrogenCodeStub(init_state) {
equality_kind_ = kind;
nil_value_ = nil; nil_value_ = nil;
} }
class EqualityKindField : public BitField<EqualityKind, NUMBER_OF_TYPES, 1> { class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES, 1> {};
};
class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES+1, 1> {};
virtual CodeStub::Major MajorKey() { return CompareNilIC; } virtual CodeStub::Major MajorKey() { return CompareNilIC; }
virtual int NotMissMinorKey() { return GetExtraICState(); } virtual int NotMissMinorKey() { return GetExtraICState(); }
EqualityKind equality_kind_;
NilValue nil_value_; NilValue nil_value_;
Types types_; Types types_;
......
...@@ -1698,7 +1698,6 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, ...@@ -1698,7 +1698,6 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
void HGraphBuilder::BuildCompareNil( void HGraphBuilder::BuildCompareNil(
HValue* value, HValue* value,
EqualityKind kind,
CompareNilICStub::Types types, CompareNilICStub::Types types,
Handle<Map> map, Handle<Map> map,
int position, int position,
...@@ -1733,9 +1732,7 @@ void HGraphBuilder::BuildCompareNil( ...@@ -1733,9 +1732,7 @@ void HGraphBuilder::BuildCompareNil(
// emitted below is the actual monomorphic map. // emitted below is the actual monomorphic map.
BuildCheckMap(value, map); BuildCheckMap(value, map);
} else { } else {
if (kind == kNonStrictEquality) { if_nil.Deopt();
if_nil.Deopt();
}
} }
} }
...@@ -9921,19 +9918,22 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, ...@@ -9921,19 +9918,22 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
ASSERT(!HasStackOverflow()); ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL); ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor()); ASSERT(current_block()->HasPredecessor());
EqualityKind kind =
expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality;
HIfContinuation continuation; HIfContinuation continuation;
CompareNilICStub::Types types; CompareNilICStub::Types types;
if (kind == kStrictEquality) { if (expr->op() == Token::EQ_STRICT) {
types.Add((nil == kNullValue) ? CompareNilICStub::NULL_TYPE : IfBuilder if_nil(this);
CompareNilICStub::UNDEFINED); if_nil.If<HCompareObjectEqAndBranch>(
} else { value, (nil == kNullValue) ? graph()->GetConstantNull()
types = CompareNilICStub::Types(expr->compare_nil_types()); : graph()->GetConstantUndefined());
if (types.IsEmpty()) types = CompareNilICStub::Types::FullCompare(); if_nil.Then();
if_nil.Else();
if_nil.CaptureContinuation(&continuation);
return ast_context()->ReturnContinuation(&continuation, expr->id());
} }
types = CompareNilICStub::Types(expr->compare_nil_types());
if (types.IsEmpty()) types = CompareNilICStub::Types::FullCompare();
Handle<Map> map_handle = expr->map(); Handle<Map> map_handle = expr->map();
BuildCompareNil(value, kind, types, map_handle, BuildCompareNil(value, types, map_handle,
expr->position(), &continuation); expr->position(), &continuation);
return ast_context()->ReturnContinuation(&continuation, expr->id()); return ast_context()->ReturnContinuation(&continuation, expr->id());
} }
......
...@@ -1353,7 +1353,6 @@ class HGraphBuilder { ...@@ -1353,7 +1353,6 @@ class HGraphBuilder {
void BuildCompareNil( void BuildCompareNil(
HValue* value, HValue* value,
EqualityKind kind,
CompareNilICStub::Types types, CompareNilICStub::Types types,
Handle<Map> map, Handle<Map> map,
int position, int position,
......
...@@ -4768,18 +4768,14 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, ...@@ -4768,18 +4768,14 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
VisitForAccumulatorValue(sub_expr); VisitForAccumulatorValue(sub_expr);
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
EqualityKind kind = expr->op() == Token::EQ_STRICT
? kStrictEquality : kNonStrictEquality;
Handle<Object> nil_value = nil == kNullValue Handle<Object> nil_value = nil == kNullValue
? isolate()->factory()->null_value() ? isolate()->factory()->null_value()
: isolate()->factory()->undefined_value(); : isolate()->factory()->undefined_value();
if (kind == kStrictEquality) { if (expr->op() == Token::EQ_STRICT) {
__ cmp(eax, nil_value); __ cmp(eax, nil_value);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
} else { } else {
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
kNonStrictEquality,
nil);
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
__ test(eax, eax); __ test(eax, eax);
Split(not_zero, if_true, if_false, fall_through); Split(not_zero, if_true, if_false, fall_through);
......
...@@ -2943,16 +2943,8 @@ void CompareNilIC::Clear(Address address, Code* target) { ...@@ -2943,16 +2943,8 @@ void CompareNilIC::Clear(Address address, Code* target) {
} }
MaybeObject* CompareNilIC::DoCompareNilSlow(EqualityKind kind, MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil,
NilValue nil,
Handle<Object> object) { Handle<Object> object) {
if (kind == kStrictEquality) {
if (nil == kNullValue) {
return Smi::FromInt(object->IsNull());
} else {
return Smi::FromInt(object->IsUndefined());
}
}
if (object->IsNull() || object->IsUndefined()) { if (object->IsNull() || object->IsUndefined()) {
return Smi::FromInt(true); return Smi::FromInt(true);
} }
...@@ -2973,7 +2965,6 @@ MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { ...@@ -2973,7 +2965,6 @@ MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
stub.Record(object); stub.Record(object);
old_types.TraceTransition(stub.GetTypes()); old_types.TraceTransition(stub.GetTypes());
EqualityKind kind = stub.GetKind();
NilValue nil = stub.GetNilValue(); NilValue nil = stub.GetNilValue();
// Find or create the specialized stub to support the new set of types. // Find or create the specialized stub to support the new set of types.
...@@ -2987,7 +2978,7 @@ MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { ...@@ -2987,7 +2978,7 @@ MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
code = stub.GetCode(isolate()); code = stub.GetCode(isolate());
} }
set_target(*code); set_target(*code);
return DoCompareNilSlow(kind, nil, object); return DoCompareNilSlow(nil, object);
} }
......
...@@ -789,8 +789,7 @@ class CompareNilIC: public IC { ...@@ -789,8 +789,7 @@ class CompareNilIC: public IC {
static void Clear(Address address, Code* target); static void Clear(Address address, Code* target);
static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(EqualityKind kind, static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(NilValue nil,
NilValue nil,
Handle<Object> object); Handle<Object> object);
}; };
......
...@@ -909,8 +909,6 @@ Handle<Code> StubCache::ComputeCallMiss(int argc, ...@@ -909,8 +909,6 @@ Handle<Code> StubCache::ComputeCallMiss(int argc,
Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map,
CompareNilICStub& stub) { CompareNilICStub& stub) {
stub.SetKind(kNonStrictEquality);
Handle<String> name(isolate_->heap()->empty_string()); Handle<String> name(isolate_->heap()->empty_string());
if (!receiver_map->is_shared()) { if (!receiver_map->is_shared()) {
Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC,
......
...@@ -146,10 +146,6 @@ class V8 : public AllStatic { ...@@ -146,10 +146,6 @@ class V8 : public AllStatic {
enum NilValue { kNullValue, kUndefinedValue }; enum NilValue { kNullValue, kUndefinedValue };
// JavaScript defines two kinds of equality.
enum EqualityKind { kStrictEquality, kNonStrictEquality };
} } // namespace v8::internal } } // namespace v8::internal
namespace i = v8::internal; namespace i = v8::internal;
......
...@@ -4754,18 +4754,14 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, ...@@ -4754,18 +4754,14 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
VisitForAccumulatorValue(sub_expr); VisitForAccumulatorValue(sub_expr);
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
EqualityKind kind = expr->op() == Token::EQ_STRICT if (expr->op() == Token::EQ_STRICT) {
? kStrictEquality : kNonStrictEquality;
if (kind == kStrictEquality) {
Heap::RootListIndex nil_value = nil == kNullValue ? Heap::RootListIndex nil_value = nil == kNullValue ?
Heap::kNullValueRootIndex : Heap::kNullValueRootIndex :
Heap::kUndefinedValueRootIndex; Heap::kUndefinedValueRootIndex;
__ CompareRoot(rax, nil_value); __ CompareRoot(rax, nil_value);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
} else { } else {
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
kNonStrictEquality,
nil);
CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
__ testq(rax, rax); __ testq(rax, rax);
Split(not_zero, if_true, if_false, fall_through); Split(not_zero, if_true, if_false, fall_through);
......
...@@ -46,9 +46,8 @@ TEST(TypeConstructors) { ...@@ -46,9 +46,8 @@ TEST(TypeConstructors) {
TEST(ExternalICStateParsing) { TEST(ExternalICStateParsing) {
Types types; Types types;
types.Add(CompareNilICStub::UNDEFINED); types.Add(CompareNilICStub::UNDEFINED);
CompareNilICStub stub(kNonStrictEquality, kUndefinedValue, types); CompareNilICStub stub(kUndefinedValue, types);
CompareNilICStub stub2(stub.GetExtraICState()); CompareNilICStub stub2(stub.GetExtraICState());
CHECK_EQ(stub.GetKind(), stub2.GetKind());
CHECK_EQ(stub.GetNilValue(), stub2.GetNilValue()); CHECK_EQ(stub.GetNilValue(), stub2.GetNilValue());
CHECK_EQ(stub.GetTypes().ToIntegral(), stub2.GetTypes().ToIntegral()); CHECK_EQ(stub.GetTypes().ToIntegral(), stub2.GetTypes().ToIntegral());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment