| Index: src/ic.cc
|
| diff --git a/src/ic.cc b/src/ic.cc
|
| index 28bbd94e82837600a808d4a56e58514fd26db918..0f1c3b416e97dd7264c0b24d85b396420086f403 100644
|
| --- a/src/ic.cc
|
| +++ b/src/ic.cc
|
| @@ -501,7 +501,14 @@ void CallIC::Clear(Isolate* isolate,
|
| Code* target,
|
| ConstantPoolArray* constant_pool) {
|
| // Currently, CallIC doesn't have state changes.
|
| - ASSERT(target->ic_state() == v8::internal::GENERIC);
|
| + if (target->ic_state() != v8::internal::MONOMORPHIC) return;
|
| + CallIC::State existing_state(target->extra_ic_state());
|
| +
|
| + // Monomorphic array stubs don't need to be cleared because
|
| + // 1) the stub doesn't store information that should be cleared, and
|
| + // 2) the AllocationSite stored in the type feedback vector is immune
|
| + // from gc type feedback clearing.
|
| + ASSERT(existing_state.stub_type() == MONOMORPHIC_ARRAY);
|
| }
|
|
|
|
|
| @@ -1818,18 +1825,50 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
|
|
|
| CallIC::State::State(ExtraICState extra_ic_state)
|
| : argc_(ArgcBits::decode(extra_ic_state)),
|
| - call_type_(CallTypeBits::decode(extra_ic_state)) {
|
| + call_type_(CallTypeBits::decode(extra_ic_state)),
|
| + stub_type_(StubTypeBits::decode(extra_ic_state)) {
|
| }
|
|
|
|
|
| ExtraICState CallIC::State::GetExtraICState() const {
|
| ExtraICState extra_ic_state =
|
| ArgcBits::encode(argc_) |
|
| - CallTypeBits::encode(call_type_);
|
| + CallTypeBits::encode(call_type_) |
|
| + StubTypeBits::encode(stub_type_);
|
| return extra_ic_state;
|
| }
|
|
|
|
|
| +bool CallIC::DoCustomHandler(Handle<Object> receiver,
|
| + Handle<Object> function,
|
| + Handle<FixedArray> vector,
|
| + Handle<Smi> slot,
|
| + const State& state) {
|
| + ASSERT(FLAG_use_ic && function->IsJSFunction());
|
| +
|
| + // Are we the array function?
|
| + Handle<JSFunction> array_function = Handle<JSFunction>(
|
| + isolate()->context()->native_context()->array_function(), isolate());
|
| + if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
|
| + // Alter the slot.
|
| + Handle<AllocationSite> new_site = isolate()->factory()->NewAllocationSite();
|
| + vector->set(slot->value(), *new_site);
|
| + State new_state = state.ToMonomorphicArrayCallState();
|
| + CallICStub stub(isolate(), new_state);
|
| + set_target(*stub.GetCode());
|
| + Handle<String> name;
|
| + if (array_function->shared()->name()->IsString()) {
|
| + name = Handle<String>(String::cast(array_function->shared()->name()),
|
| + isolate());
|
| + }
|
| +
|
| + TRACE_IC("CallIC (Array call)", name);
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| void CallIC::HandleMiss(Handle<Object> receiver,
|
| Handle<Object> function,
|
| Handle<FixedArray> vector,
|
| @@ -1837,18 +1876,35 @@ void CallIC::HandleMiss(Handle<Object> receiver,
|
| State state(target()->extra_ic_state());
|
| Object* feedback = vector->get(slot->value());
|
|
|
| - if (feedback->IsJSFunction() || !function->IsJSFunction()) {
|
| + if (feedback->IsJSFunction() || !function->IsJSFunction() ||
|
| + state.stub_type() != DEFAULT) {
|
| // We are going generic.
|
| - ASSERT(!function->IsJSFunction() || *function != feedback);
|
| -
|
| vector->set(slot->value(),
|
| *TypeFeedbackInfo::MegamorphicSentinel(isolate()),
|
| SKIP_WRITE_BARRIER);
|
| +
|
| + State new_state = state.ToGenericState();
|
| + if (new_state != state) {
|
| + // Only happens when the array ic goes generic.
|
| + ASSERT(state.stub_type() == MONOMORPHIC_ARRAY &&
|
| + FLAG_use_ic);
|
| + CallICStub stub(isolate(), new_state);
|
| + Handle<Code> code = stub.GetCode();
|
| + set_target(*code);
|
| + }
|
| +
|
| TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
|
| } else {
|
| // If we came here feedback must be the uninitialized sentinel,
|
| // and we are going monomorphic.
|
| ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()));
|
| +
|
| + // Do we want to install a custom handler?
|
| + if (FLAG_use_ic &&
|
| + DoCustomHandler(receiver, function, vector, slot, state)) {
|
| + return;
|
| + }
|
| +
|
| Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
|
| Handle<Object> name(js_function->shared()->name(), isolate());
|
| TRACE_IC("CallIC", name);
|
|
|