| Index: src/ic/ic.cc
|
| diff --git a/src/ic/ic.cc b/src/ic/ic.cc
|
| index f6584f69223b5b235bd40bed5199ebee27a5a479..bbeb834ce3c8fb80a1454ad9fe3e59ac84253b1a 100644
|
| --- a/src/ic/ic.cc
|
| +++ b/src/ic/ic.cc
|
| @@ -16,6 +16,7 @@
|
| #include "src/ic/ic-inl.h"
|
| #include "src/ic/ic-compiler.h"
|
| #include "src/ic/stub-cache.h"
|
| +#include "src/macro-assembler.h"
|
| #include "src/prototype.h"
|
| #include "src/runtime/runtime.h"
|
|
|
| @@ -488,8 +489,10 @@ void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
|
| case Code::KEYED_LOAD_IC:
|
| return;
|
| case Code::STORE_IC:
|
| + if (FLAG_vector_stores) return;
|
| return StoreIC::Clear(isolate, address, target, constant_pool);
|
| case Code::KEYED_STORE_IC:
|
| + if (FLAG_vector_stores) return;
|
| return KeyedStoreIC::Clear(isolate, address, target, constant_pool);
|
| case Code::COMPARE_IC:
|
| return CompareIC::Clear(isolate, address, target, constant_pool);
|
| @@ -548,6 +551,14 @@ void StoreIC::Clear(Isolate* isolate, Address address, Code* target,
|
| }
|
|
|
|
|
| +void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) {
|
| + if (IsCleared(nexus)) return;
|
| + State state = nexus->StateFromFeedback();
|
| + nexus->ConfigurePremonomorphic();
|
| + OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC);
|
| +}
|
| +
|
| +
|
| void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target,
|
| Address constant_pool) {
|
| if (IsCleared(target)) return;
|
| @@ -557,6 +568,15 @@ void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target,
|
| }
|
|
|
|
|
| +void KeyedStoreIC::Clear(Isolate* isolate, Code* host,
|
| + KeyedStoreICNexus* nexus) {
|
| + if (IsCleared(nexus)) return;
|
| + State state = nexus->StateFromFeedback();
|
| + nexus->ConfigurePremonomorphic();
|
| + OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC);
|
| +}
|
| +
|
| +
|
| void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
|
| Address constant_pool) {
|
| DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
|
| @@ -591,24 +611,10 @@ static bool MigrateDeprecated(Handle<Object> object) {
|
|
|
| void IC::ConfigureVectorState(IC::State new_state) {
|
| DCHECK(UseVector());
|
| - if (kind() == Code::LOAD_IC) {
|
| - LoadICNexus* nexus = casted_nexus<LoadICNexus>();
|
| - if (new_state == PREMONOMORPHIC) {
|
| - nexus->ConfigurePremonomorphic();
|
| - } else if (new_state == MEGAMORPHIC) {
|
| - nexus->ConfigureMegamorphic();
|
| - } else {
|
| - UNREACHABLE();
|
| - }
|
| - } else if (kind() == Code::KEYED_LOAD_IC) {
|
| - KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
|
| - if (new_state == PREMONOMORPHIC) {
|
| - nexus->ConfigurePremonomorphic();
|
| - } else if (new_state == MEGAMORPHIC) {
|
| - nexus->ConfigureMegamorphic();
|
| - } else {
|
| - UNREACHABLE();
|
| - }
|
| + if (new_state == PREMONOMORPHIC) {
|
| + nexus()->ConfigurePremonomorphic();
|
| + } else if (new_state == MEGAMORPHIC) {
|
| + nexus()->ConfigureMegamorphic();
|
| } else {
|
| UNREACHABLE();
|
| }
|
| @@ -625,10 +631,16 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
|
| if (kind() == Code::LOAD_IC) {
|
| LoadICNexus* nexus = casted_nexus<LoadICNexus>();
|
| nexus->ConfigureMonomorphic(map, handler);
|
| - } else {
|
| - DCHECK(kind() == Code::KEYED_LOAD_IC);
|
| + } else if (kind() == Code::KEYED_LOAD_IC) {
|
| KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
|
| nexus->ConfigureMonomorphic(name, map, handler);
|
| + } else if (kind() == Code::STORE_IC) {
|
| + StoreICNexus* nexus = casted_nexus<StoreICNexus>();
|
| + nexus->ConfigureMonomorphic(map, handler);
|
| + } else {
|
| + DCHECK(kind() == Code::KEYED_STORE_IC);
|
| + KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
|
| + nexus->ConfigureMonomorphic(name, map, handler);
|
| }
|
|
|
| vector_set_ = true;
|
| @@ -643,10 +655,16 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
|
| if (kind() == Code::LOAD_IC) {
|
| LoadICNexus* nexus = casted_nexus<LoadICNexus>();
|
| nexus->ConfigurePolymorphic(maps, handlers);
|
| - } else {
|
| - DCHECK(kind() == Code::KEYED_LOAD_IC);
|
| + } else if (kind() == Code::KEYED_LOAD_IC) {
|
| KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
|
| nexus->ConfigurePolymorphic(name, maps, handlers);
|
| + } else if (kind() == Code::STORE_IC) {
|
| + StoreICNexus* nexus = casted_nexus<StoreICNexus>();
|
| + nexus->ConfigurePolymorphic(maps, handlers);
|
| + } else {
|
| + DCHECK(kind() == Code::KEYED_STORE_IC);
|
| + KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
|
| + nexus->ConfigurePolymorphic(name, maps, handlers);
|
| }
|
|
|
| vector_set_ = true;
|
| @@ -668,11 +686,8 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
|
| if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
|
| // Rewrite to the generic keyed load stub.
|
| if (FLAG_use_ic) {
|
| - if (UseVector()) {
|
| - ConfigureVectorState(MEGAMORPHIC);
|
| - } else {
|
| - set_target(*megamorphic_stub());
|
| - }
|
| + DCHECK(UseVector());
|
| + ConfigureVectorState(MEGAMORPHIC);
|
| TRACE_IC("LoadIC", name);
|
| TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
|
| }
|
| @@ -1614,7 +1629,11 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
|
| if (state() == UNINITIALIZED) {
|
| // This is the first time we execute this inline cache. Set the target to
|
| // the pre monomorphic stub to delay setting the monomorphic state.
|
| - set_target(*pre_monomorphic_stub());
|
| + if (FLAG_vector_stores) {
|
| + ConfigureVectorState(PREMONOMORPHIC);
|
| + } else {
|
| + set_target(*pre_monomorphic_stub());
|
| + }
|
| TRACE_IC("StoreIC", lookup->name());
|
| return;
|
| }
|
| @@ -2053,11 +2072,20 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
|
| StoreIC::Store(object, Handle<Name>::cast(key), value,
|
| JSReceiver::MAY_BE_STORE_FROM_KEYED),
|
| Object);
|
| - if (!is_target_set()) {
|
| - TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
|
| - "unhandled internalized string key");
|
| - TRACE_IC("StoreIC", key);
|
| - set_target(*stub);
|
| + if (FLAG_vector_stores) {
|
| + if (!is_vector_set()) {
|
| + ConfigureVectorState(MEGAMORPHIC);
|
| + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
|
| + "unhandled internalized string key");
|
| + TRACE_IC("StoreIC", key);
|
| + }
|
| + } else {
|
| + if (!is_target_set()) {
|
| + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
|
| + "unhandled internalized string key");
|
| + TRACE_IC("StoreIC", key);
|
| + set_target(*stub);
|
| + }
|
| }
|
| return store_handle;
|
| }
|
| @@ -2114,17 +2142,28 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
|
| Object);
|
| }
|
|
|
| - DCHECK(!is_target_set());
|
| - Code* megamorphic = *megamorphic_stub();
|
| - if (*stub == megamorphic) {
|
| - TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
|
| - }
|
| - if (*stub == *slow_stub()) {
|
| - TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub");
|
| - }
|
| - DCHECK(!stub.is_null());
|
| - if (!AddressIsDeoptimizedCode()) {
|
| - set_target(*stub);
|
| + if (FLAG_vector_stores) {
|
| + if (!is_vector_set() || stub.is_null()) {
|
| + Code* megamorphic = *megamorphic_stub();
|
| + if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) {
|
| + ConfigureVectorState(MEGAMORPHIC);
|
| + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
|
| + *stub == megamorphic ? "set generic" : "slow stub");
|
| + }
|
| + }
|
| + } else {
|
| + DCHECK(!is_target_set());
|
| + Code* megamorphic = *megamorphic_stub();
|
| + if (*stub == megamorphic) {
|
| + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
|
| + } else if (*stub == *slow_stub()) {
|
| + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub");
|
| + }
|
| +
|
| + DCHECK(!stub.is_null());
|
| + if (!AddressIsDeoptimizedCode()) {
|
| + set_target(*stub);
|
| + }
|
| }
|
| TRACE_IC("StoreIC", key);
|
|
|
| @@ -2173,7 +2212,7 @@ void CallIC::PatchMegamorphic(Handle<Object> function) {
|
|
|
| // We are going generic.
|
| CallICNexus* nexus = casted_nexus<CallICNexus>();
|
| - nexus->ConfigureGeneric();
|
| + nexus->ConfigureMegamorphic();
|
|
|
| // Vector-based ICs have a different calling convention in optimized code
|
| // than full code so the correct stub has to be chosen.
|
| @@ -2208,7 +2247,7 @@ void CallIC::HandleMiss(Handle<Object> function) {
|
|
|
| if (feedback->IsWeakCell() || !function->IsJSFunction()) {
|
| // We are going generic.
|
| - nexus->ConfigureGeneric();
|
| + nexus->ConfigureMegamorphic();
|
| } else {
|
| // The feedback is either uninitialized or an allocation site.
|
| // It might be an allocation site because if we re-compile the full code
|
| @@ -2352,14 +2391,37 @@ RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) {
|
| RUNTIME_FUNCTION(StoreIC_Miss) {
|
| TimerEventScope<TimerEventIcMiss> timer(isolate);
|
| HandleScope scope(isolate);
|
| - DCHECK(args.length() == 3);
|
| - StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
| Handle<Object> receiver = args.at<Object>(0);
|
| Handle<Name> key = args.at<Name>(1);
|
| - ic.UpdateState(receiver, key);
|
| + Handle<Object> value = args.at<Object>(2);
|
| Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
|
| +
|
| + if (FLAG_vector_stores) {
|
| + DCHECK(args.length() == 5);
|
| + Handle<Smi> slot = args.at<Smi>(3);
|
| + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
|
| + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
| + if (vector->GetKind(vector_slot) == Code::STORE_IC) {
|
| + StoreICNexus nexus(vector, vector_slot);
|
| + StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + } else {
|
| + DCHECK(vector->GetKind(vector_slot) == Code::KEYED_STORE_IC);
|
| + KeyedStoreICNexus nexus(vector, vector_slot);
|
| + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + }
|
| + } else {
|
| + DCHECK(args.length() == 3);
|
| + StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + }
|
| return *result;
|
| }
|
|
|
| @@ -2367,14 +2429,37 @@ RUNTIME_FUNCTION(StoreIC_Miss) {
|
| RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) {
|
| TimerEventScope<TimerEventIcMiss> timer(isolate);
|
| HandleScope scope(isolate);
|
| - DCHECK(args.length() == 3 || args.length() == 4);
|
| - StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
|
| Handle<Object> receiver = args.at<Object>(0);
|
| Handle<Name> key = args.at<Name>(1);
|
| - ic.UpdateState(receiver, key);
|
| + Handle<Object> value = args.at<Object>(2);
|
| Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
|
| +
|
| + if (FLAG_vector_stores) {
|
| + DCHECK(args.length() == 5);
|
| + Handle<Smi> slot = args.at<Smi>(3);
|
| + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
|
| + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
| + if (vector->GetKind(vector_slot) == Code::STORE_IC) {
|
| + StoreICNexus nexus(vector, vector_slot);
|
| + StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + } else {
|
| + DCHECK(vector->GetKind(vector_slot) == Code::KEYED_STORE_IC);
|
| + KeyedStoreICNexus nexus(vector, vector_slot);
|
| + KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + }
|
| + } else {
|
| + DCHECK(args.length() == 3 || args.length() == 4);
|
| + StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + }
|
| return *result;
|
| }
|
|
|
| @@ -2383,14 +2468,28 @@ RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) {
|
| RUNTIME_FUNCTION(KeyedStoreIC_Miss) {
|
| TimerEventScope<TimerEventIcMiss> timer(isolate);
|
| HandleScope scope(isolate);
|
| - DCHECK(args.length() == 3);
|
| - KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
| Handle<Object> receiver = args.at<Object>(0);
|
| Handle<Object> key = args.at<Object>(1);
|
| - ic.UpdateState(receiver, key);
|
| + Handle<Object> value = args.at<Object>(2);
|
| Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
|
| +
|
| + if (FLAG_vector_stores) {
|
| + DCHECK(args.length() == 5);
|
| + Handle<Smi> slot = args.at<Smi>(3);
|
| + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
|
| + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
| + KeyedStoreICNexus nexus(vector, vector_slot);
|
| + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + } else {
|
| + DCHECK(args.length() == 3);
|
| + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + }
|
| return *result;
|
| }
|
|
|
| @@ -2398,14 +2497,28 @@ RUNTIME_FUNCTION(KeyedStoreIC_Miss) {
|
| RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) {
|
| TimerEventScope<TimerEventIcMiss> timer(isolate);
|
| HandleScope scope(isolate);
|
| - DCHECK(args.length() == 3);
|
| - KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
|
| Handle<Object> receiver = args.at<Object>(0);
|
| Handle<Object> key = args.at<Object>(1);
|
| - ic.UpdateState(receiver, key);
|
| + Handle<Object> value = args.at<Object>(2);
|
| Handle<Object> result;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
|
| +
|
| + if (FLAG_vector_stores) {
|
| + DCHECK(args.length() == 5);
|
| + Handle<Smi> slot = args.at<Smi>(3);
|
| + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
|
| + FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
| + KeyedStoreICNexus nexus(vector, vector_slot);
|
| + KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| + ic.Store(receiver, key, value));
|
| + } else {
|
| + DCHECK(args.length() == 3);
|
| + KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
|
| + ic.UpdateState(receiver, key);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
|
| + }
|
| return *result;
|
| }
|
|
|
|
|