| 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);
|
|
|