Vector ICs: Changes to the IC system to support vector-based stores.
authormvstanton <mvstanton@chromium.org>
Tue, 30 Jun 2015 09:51:43 +0000 (02:51 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 30 Jun 2015 09:51:54 +0000 (09:51 +0000)
BUG=

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

Cr-Commit-Position: refs/heads/master@{#29371}

src/ic/ic-inl.h
src/ic/ic.cc
src/ic/ic.h
src/type-feedback-vector.cc
src/type-feedback-vector.h

index 55572f7..95fbfc4 100644 (file)
@@ -98,10 +98,11 @@ void IC::SetTargetAtAddress(Address address, Code* target,
 
   DCHECK(target->is_inline_cache_stub() || target->is_compare_ic_stub());
 
-  // Don't use this for load_ics when --vector-ics is turned on.
   DCHECK(!target->is_inline_cache_stub() ||
          (target->kind() != Code::LOAD_IC &&
-          target->kind() != Code::KEYED_LOAD_IC));
+          target->kind() != Code::KEYED_LOAD_IC &&
+          (!FLAG_vector_stores || (target->kind() != Code::STORE_IC &&
+                                   target->kind() != Code::KEYED_STORE_IC))));
 
   Heap* heap = target->GetHeap();
   Code* old_target = GetTargetAtAddress(address, constant_pool);
index f6584f6..bbeb834 100644 (file)
@@ -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;
 }
 
index 06ac716..743459c 100644 (file)
@@ -114,7 +114,9 @@ class IC {
 
   static bool ICUseVector(Code::Kind kind) {
     return kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC ||
-           kind == Code::CALL_IC;
+           kind == Code::CALL_IC ||
+           (FLAG_vector_stores &&
+            (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC));
   }
 
  protected:
@@ -497,7 +499,8 @@ class StoreIC : public IC {
     return StoreICState(flag).GetExtraICState();
   }
 
-  StoreIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
+  StoreIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
+      : IC(depth, isolate, nexus) {
     DCHECK(IsStoreStub());
   }
 
@@ -531,6 +534,8 @@ class StoreIC : public IC {
   bool LookupForWrite(LookupIterator* it, Handle<Object> value,
                       JSReceiver::StoreFromKeyed store_mode);
 
+  static void Clear(Isolate* isolate, Code* host, StoreICNexus* nexus);
+
  protected:
   // Stub accessors.
   Handle<Code> megamorphic_stub() override;
@@ -594,7 +599,9 @@ class KeyedStoreIC : public StoreIC {
     return IcCheckTypeField::decode(extra_state);
   }
 
-  KeyedStoreIC(FrameDepth depth, Isolate* isolate) : StoreIC(depth, isolate) {
+  KeyedStoreIC(FrameDepth depth, Isolate* isolate,
+               KeyedStoreICNexus* nexus = NULL)
+      : StoreIC(depth, isolate, nexus) {
     DCHECK(target()->is_keyed_store_stub());
   }
 
@@ -619,6 +626,8 @@ class KeyedStoreIC : public StoreIC {
   static Handle<Code> initialize_stub_in_optimized_code(
       Isolate* isolate, LanguageMode language_mode, State initialization_state);
 
+  static void Clear(Isolate* isolate, Code* host, KeyedStoreICNexus* nexus);
+
  protected:
   virtual Handle<Code> pre_monomorphic_stub() const {
     return pre_monomorphic_stub(isolate(), language_mode());
index 55ac5cf..adf0a50 100644 (file)
@@ -211,9 +211,15 @@ void TypeFeedbackVector::ClearICSlotsImpl(SharedFunctionInfo* shared,
       } else if (kind == Code::KEYED_LOAD_IC) {
         KeyedLoadICNexus nexus(this, slot);
         nexus.Clear(host);
+      } else if (kind == Code::STORE_IC) {
+        DCHECK(FLAG_vector_stores);
+        StoreICNexus nexus(this, slot);
+        nexus.Clear(host);
+      } else if (kind == Code::KEYED_STORE_IC) {
+        DCHECK(FLAG_vector_stores);
+        KeyedStoreICNexus nexus(this, slot);
+        nexus.Clear(host);
       }
-      // TODO(mvstanton): Handle clearing of store ics when FLAG_vector_stores
-      // is true.
     }
   }
 }
@@ -258,6 +264,31 @@ void FeedbackNexus::InstallHandlers(Handle<FixedArray> array,
 }
 
 
+void FeedbackNexus::ConfigureUninitialized() {
+  SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+              SKIP_WRITE_BARRIER);
+  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+                   SKIP_WRITE_BARRIER);
+}
+
+
+void FeedbackNexus::ConfigurePremonomorphic() {
+  SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()),
+              SKIP_WRITE_BARRIER);
+  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+                   SKIP_WRITE_BARRIER);
+}
+
+
+void FeedbackNexus::ConfigureMegamorphic() {
+  Isolate* isolate = GetIsolate();
+  SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
+              SKIP_WRITE_BARRIER);
+  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+                   SKIP_WRITE_BARRIER);
+}
+
+
 InlineCacheState LoadICNexus::StateFromFeedback() const {
   Isolate* isolate = GetIsolate();
   Object* feedback = GetFeedback();
@@ -308,6 +339,56 @@ InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
 }
 
 
+InlineCacheState StoreICNexus::StateFromFeedback() const {
+  Isolate* isolate = GetIsolate();
+  Object* feedback = GetFeedback();
+
+  if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
+    return UNINITIALIZED;
+  } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
+    return MEGAMORPHIC;
+  } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
+    return PREMONOMORPHIC;
+  } else if (feedback->IsFixedArray()) {
+    // Determine state purely by our structure, don't check if the maps are
+    // cleared.
+    return POLYMORPHIC;
+  } else if (feedback->IsWeakCell()) {
+    // Don't check if the map is cleared.
+    return MONOMORPHIC;
+  }
+
+  return UNINITIALIZED;
+}
+
+
+InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
+  Isolate* isolate = GetIsolate();
+  Object* feedback = GetFeedback();
+
+  if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
+    return UNINITIALIZED;
+  } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
+    return PREMONOMORPHIC;
+  } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
+    return MEGAMORPHIC;
+  } else if (feedback->IsFixedArray()) {
+    // Determine state purely by our structure, don't check if the maps are
+    // cleared.
+    return POLYMORPHIC;
+  } else if (feedback->IsWeakCell()) {
+    // Don't check if the map is cleared.
+    return MONOMORPHIC;
+  } else if (feedback->IsName()) {
+    Object* extra = GetFeedbackExtra();
+    FixedArray* extra_array = FixedArray::cast(extra);
+    return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
+  }
+
+  return UNINITIALIZED;
+}
+
+
 InlineCacheState CallICNexus::StateFromFeedback() const {
   Isolate* isolate = GetIsolate();
   Object* feedback = GetFeedback();
@@ -339,14 +420,6 @@ int CallICNexus::ExtractCallCount() {
 void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
 
 
-void CallICNexus::ConfigureGeneric() {
-  SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
-              SKIP_WRITE_BARRIER);
-  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
-                   SKIP_WRITE_BARRIER);
-}
-
-
 void CallICNexus::ConfigureMonomorphicArray() {
   Object* feedback = GetFeedback();
   if (!feedback->IsAllocationSite()) {
@@ -358,14 +431,6 @@ void CallICNexus::ConfigureMonomorphicArray() {
 }
 
 
-void CallICNexus::ConfigureUninitialized() {
-  SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
-              SKIP_WRITE_BARRIER);
-  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
-                   SKIP_WRITE_BARRIER);
-}
-
-
 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
   Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
   SetFeedback(*new_cell);
@@ -373,51 +438,41 @@ void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
 }
 
 
-void KeyedLoadICNexus::ConfigureMegamorphic() {
-  Isolate* isolate = GetIsolate();
-  SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
-              SKIP_WRITE_BARRIER);
-  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
-                   SKIP_WRITE_BARRIER);
-}
-
-
-void LoadICNexus::ConfigureMegamorphic() {
-  SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
-              SKIP_WRITE_BARRIER);
-  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
-                   SKIP_WRITE_BARRIER);
-}
-
-
-void LoadICNexus::ConfigurePremonomorphic() {
-  SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()),
-              SKIP_WRITE_BARRIER);
-  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
-                   SKIP_WRITE_BARRIER);
+void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
+                                       Handle<Code> handler) {
+  Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+  SetFeedback(*cell);
+  SetFeedbackExtra(*handler);
 }
 
 
-void KeyedLoadICNexus::ConfigurePremonomorphic() {
-  Isolate* isolate = GetIsolate();
-  SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(isolate),
-              SKIP_WRITE_BARRIER);
-  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
-                   SKIP_WRITE_BARRIER);
+void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
+                                            Handle<Map> receiver_map,
+                                            Handle<Code> handler) {
+  Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+  if (name.is_null()) {
+    SetFeedback(*cell);
+    SetFeedbackExtra(*handler);
+  } else {
+    SetFeedback(*name);
+    Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
+    array->set(0, *cell);
+    array->set(1, *handler);
+  }
 }
 
 
-void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
-                                       Handle<Code> handler) {
+void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
+                                        Handle<Code> handler) {
   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
   SetFeedback(*cell);
   SetFeedbackExtra(*handler);
 }
 
 
-void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
-                                            Handle<Map> receiver_map,
-                                            Handle<Code> handler) {
+void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name,
+                                             Handle<Map> receiver_map,
+                                             Handle<Code> handler) {
   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
   if (name.is_null()) {
     SetFeedback(*cell);
@@ -461,6 +516,36 @@ void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
 }
 
 
+void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
+                                        CodeHandleList* handlers) {
+  Isolate* isolate = GetIsolate();
+  int receiver_count = maps->length();
+  Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
+  InstallHandlers(array, maps, handlers);
+  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+                   SKIP_WRITE_BARRIER);
+}
+
+
+void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
+                                             MapHandleList* maps,
+                                             CodeHandleList* handlers) {
+  int receiver_count = maps->length();
+  DCHECK(receiver_count > 1);
+  Handle<FixedArray> array;
+  if (name.is_null()) {
+    array = EnsureArrayOfSize(receiver_count * 2);
+    SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+                     SKIP_WRITE_BARRIER);
+  } else {
+    SetFeedback(*name);
+    array = EnsureExtraArrayOfSize(receiver_count * 2);
+  }
+
+  InstallHandlers(array, maps, handlers);
+}
+
+
 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
   Isolate* isolate = GetIsolate();
   Object* feedback = GetFeedback();
@@ -580,5 +665,24 @@ Name* KeyedLoadICNexus::FindFirstName() const {
   }
   return NULL;
 }
+
+
+Name* KeyedStoreICNexus::FindFirstName() const {
+  Object* feedback = GetFeedback();
+  if (feedback->IsString()) {
+    return Name::cast(feedback);
+  }
+  return NULL;
+}
+
+
+void StoreICNexus::Clear(Code* host) {
+  StoreIC::Clear(GetIsolate(), host, this);
+}
+
+
+void KeyedStoreICNexus::Clear(Code* host) {
+  KeyedStoreIC::Clear(GetIsolate(), host, this);
+}
 }  // namespace internal
 }  // namespace v8
index ee2d200..a6f7221 100644 (file)
@@ -294,6 +294,10 @@ class FeedbackNexus {
   virtual bool FindHandlers(CodeHandleList* code_list, int length = -1) const;
   virtual Name* FindFirstName() const { return NULL; }
 
+  virtual void ConfigureUninitialized();
+  virtual void ConfigurePremonomorphic();
+  virtual void ConfigureMegamorphic();
+
   Object* GetFeedback() const { return vector()->Get(slot()); }
   Object* GetFeedbackExtra() const {
     DCHECK(TypeFeedbackVector::elements_per_ic_slot() > 1);
@@ -349,8 +353,6 @@ class CallICNexus : public FeedbackNexus {
 
   void Clear(Code* host);
 
-  void ConfigureUninitialized();
-  void ConfigureGeneric();
   void ConfigureMonomorphicArray();
   void ConfigureMonomorphic(Handle<JSFunction> function);
 
@@ -363,8 +365,7 @@ class CallICNexus : public FeedbackNexus {
   MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const override {
     return MaybeHandle<Code>();
   }
-  virtual bool FindHandlers(CodeHandleList* code_list,
-                            int length = -1) const override {
+  bool FindHandlers(CodeHandleList* code_list, int length = -1) const override {
     return length == 0;
   }
 
@@ -385,8 +386,6 @@ class LoadICNexus : public FeedbackNexus {
 
   void Clear(Code* host);
 
-  void ConfigureMegamorphic();
-  void ConfigurePremonomorphic();
   void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler);
 
   void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers);
@@ -408,8 +407,53 @@ class KeyedLoadICNexus : public FeedbackNexus {
 
   void Clear(Code* host);
 
-  void ConfigureMegamorphic();
-  void ConfigurePremonomorphic();
+  // name can be a null handle for element loads.
+  void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
+                            Handle<Code> handler);
+  // name can be null.
+  void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
+                            CodeHandleList* handlers);
+
+  InlineCacheState StateFromFeedback() const override;
+  Name* FindFirstName() const override;
+};
+
+
+class StoreICNexus : public FeedbackNexus {
+ public:
+  StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot)
+      : FeedbackNexus(vector, slot) {
+    DCHECK(vector->GetKind(slot) == Code::STORE_IC);
+  }
+  StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot)
+      : FeedbackNexus(vector, slot) {
+    DCHECK(vector->GetKind(slot) == Code::STORE_IC);
+  }
+
+  void Clear(Code* host);
+
+  void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler);
+
+  void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers);
+
+  InlineCacheState StateFromFeedback() const override;
+};
+
+
+class KeyedStoreICNexus : public FeedbackNexus {
+ public:
+  KeyedStoreICNexus(Handle<TypeFeedbackVector> vector,
+                    FeedbackVectorICSlot slot)
+      : FeedbackNexus(vector, slot) {
+    DCHECK(vector->GetKind(slot) == Code::KEYED_STORE_IC);
+  }
+  KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot)
+      : FeedbackNexus(vector, slot) {
+    DCHECK(vector->GetKind(slot) == Code::KEYED_STORE_IC);
+  }
+
+  void Clear(Code* host);
+
   // name can be a null handle for element loads.
   void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
                             Handle<Code> handler);