Index: src/ic.cc |
diff --git a/src/ic.cc b/src/ic.cc |
index e0ebdddf018c0046d83d15f8ab1c0916a84e47ad..40676abc3d1d7213d873e26d5c7067d1307c1a72 100644 |
--- a/src/ic.cc |
+++ b/src/ic.cc |
@@ -347,6 +347,7 @@ void IC::Clear(Address address) { |
case Code::CALL_IC: return CallIC::Clear(address, target); |
case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target); |
case Code::COMPARE_IC: return CompareIC::Clear(address, target); |
+ case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); |
case Code::UNARY_OP_IC: |
case Code::BINARY_OP_IC: |
case Code::TO_BOOLEAN_IC: |
@@ -2770,6 +2771,93 @@ 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); |
+ |
+ SetTargetAtAddress(address, GetRawUninitialized(kind, nil)); |
+} |
+ |
+ |
+MaybeObject* CompareNilIC::DoCompareNilSlow(EqualityKind kind, |
+ NilValue nil, |
+ 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()) { |
+ return Smi::FromInt(true); |
+ } |
+ return Smi::FromInt(object->IsUndetectableObject()); |
+} |
+ |
+ |
+MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { |
+ Code::ExtraICState extra_ic_state = target()->extended_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); |
+ |
+ EqualityKind kind = |
+ CompareNilICStub::EqualityKindFromExtraICState(extra_ic_state); |
+ NilValue nil = |
+ CompareNilICStub::NilValueFromExtraICState(extra_ic_state); |
+ |
+ // Find or create the specialized stub to support the new set of types. |
+ CompareNilICStub stub(kind, nil, types); |
+ Handle<Code> code; |
+ if ((types & CompareNilICStub::kCompareAgainstMonomorphicMap) != 0) { |
+ Handle<Map> monomorphic_map(already_monomorphic |
+ ? target()->FindFirstMap() |
+ : HeapObject::cast(*object)->map()); |
+ code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, |
+ nil, |
+ stub.GetTypes()); |
+ } else { |
+ code = stub.GetCode(isolate()); |
+ } |
+ |
+ patch(*code); |
+ |
+ return DoCompareNilSlow(kind, nil, object); |
+} |
+ |
+ |
+void CompareNilIC::patch(Code* code) { |
+ set_target(code); |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss) { |
+ HandleScope scope(isolate); |
+ Handle<Object> object = args.at<Object>(0); |
+ CompareNilIC ic(isolate); |
+ return ic.CompareNil(object); |
+} |
+ |
+ |
RUNTIME_FUNCTION(MaybeObject*, Unreachable) { |
UNREACHABLE(); |
CHECK(false); |