Vector ICs: Make the Oracle gather feedback for vector stores.
authormvstanton <mvstanton@chromium.org>
Fri, 28 Aug 2015 09:01:22 +0000 (02:01 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 28 Aug 2015 09:01:34 +0000 (09:01 +0000)
Also, polymorphic element stores have a slightly different shape for the array
attached to a vector slot. It's of the form [map, map, handler], where the 2nd
map is either a transition map or undefined (the maps are actually in
WeakCells).

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

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

src/type-feedback-vector.cc
src/type-feedback-vector.h
src/type-info.cc
src/type-info.h
src/typing.cc

index fd49513026d5f43c49b5f16cdc2da1ea24ec62c8..fa9c50c8f13773d35c1fea358f08c03875c83c2f 100644 (file)
@@ -584,6 +584,32 @@ void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
 }
 
 
+void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
+                                             MapHandleList* transitioned_maps,
+                                             CodeHandleList* handlers) {
+  int receiver_count = maps->length();
+  DCHECK(receiver_count > 1);
+  Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
+  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+                   SKIP_WRITE_BARRIER);
+
+  Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
+  for (int i = 0; i < receiver_count; ++i) {
+    Handle<Map> map = maps->at(i);
+    Handle<WeakCell> cell = Map::WeakCellForMap(map);
+    array->set(i * 3, *cell);
+    if (!transitioned_maps->at(i).is_null()) {
+      Handle<Map> transitioned_map = transitioned_maps->at(i);
+      cell = Map::WeakCellForMap(transitioned_map);
+      array->set((i * 3) + 1, *cell);
+    } else {
+      array->set((i * 3) + 1, *undefined_value);
+    }
+    array->set((i * 3) + 2, *handlers->at(i));
+  }
+}
+
+
 int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
   Isolate* isolate = GetIsolate();
   Object* feedback = GetFeedback();
@@ -593,10 +619,13 @@ int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
       feedback = GetFeedbackExtra();
     }
     FixedArray* array = FixedArray::cast(feedback);
-    // The array should be of the form [<optional name>], then
-    // [map, handler, map, handler, ... ]
+    // The array should be of the form
+    // [map, handler, map, handler, ...]
+    // or
+    // [map, map, handler, map, map, handler, ...]
     DCHECK(array->length() >= 2);
-    for (int i = 0; i < array->length(); i += 2) {
+    int increment = array->get(1)->IsCode() ? 2 : 3;
+    for (int i = 0; i < array->length(); i += increment) {
       DCHECK(array->get(i)->IsWeakCell());
       WeakCell* cell = WeakCell::cast(array->get(i));
       if (!cell->cleared()) {
@@ -626,13 +655,15 @@ MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
       feedback = GetFeedbackExtra();
     }
     FixedArray* array = FixedArray::cast(feedback);
-    for (int i = 0; i < array->length(); i += 2) {
+    DCHECK(array->length() >= 2);
+    int increment = array->get(1)->IsCode() ? 2 : 3;
+    for (int i = 0; i < array->length(); i += increment) {
       DCHECK(array->get(i)->IsWeakCell());
       WeakCell* cell = WeakCell::cast(array->get(i));
       if (!cell->cleared()) {
         Map* array_map = Map::cast(cell->value());
         if (array_map == *map) {
-          Code* code = Code::cast(array->get(i + 1));
+          Code* code = Code::cast(array->get(i + increment - 1));
           DCHECK(code->kind() == Code::HANDLER);
           return handle(code);
         }
@@ -662,14 +693,18 @@ bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const {
       feedback = GetFeedbackExtra();
     }
     FixedArray* array = FixedArray::cast(feedback);
-    // The array should be of the form [map, handler, map, handler, ... ].
+    // The array should be of the form
+    // [map, handler, map, handler, ...]
+    // or
+    // [map, map, handler, map, map, handler, ...]
     // Be sure to skip handlers whose maps have been cleared.
     DCHECK(array->length() >= 2);
-    for (int i = 0; i < array->length(); i += 2) {
+    int increment = array->get(1)->IsCode() ? 2 : 3;
+    for (int i = 0; i < array->length(); i += increment) {
       DCHECK(array->get(i)->IsWeakCell());
       WeakCell* cell = WeakCell::cast(array->get(i));
       if (!cell->cleared()) {
-        Code* code = Code::cast(array->get(i + 1));
+        Code* code = Code::cast(array->get(i + increment - 1));
         DCHECK(code->kind() == Code::HANDLER);
         code_list->Add(handle(code));
         count++;
@@ -722,5 +757,40 @@ void StoreICNexus::Clear(Code* host) {
 void KeyedStoreICNexus::Clear(Code* host) {
   KeyedStoreIC::Clear(GetIsolate(), host, this);
 }
+
+
+KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
+  KeyedAccessStoreMode mode = STANDARD_STORE;
+  MapHandleList maps;
+  CodeHandleList handlers;
+
+  if (GetKeyType() == PROPERTY) return mode;
+
+  ExtractMaps(&maps);
+  FindHandlers(&handlers, maps.length());
+  for (int i = 0; i < handlers.length(); i++) {
+    // The first handler that isn't the slow handler will have the bits we need.
+    Handle<Code> handler = handlers.at(i);
+    CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
+    uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
+    CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
+          major_key == CodeStub::StoreFastElement ||
+          major_key == CodeStub::StoreElement ||
+          major_key == CodeStub::ElementsTransitionAndStore ||
+          major_key == CodeStub::NoCache);
+    if (major_key != CodeStub::NoCache) {
+      mode = CommonStoreModeBits::decode(minor_key);
+      break;
+    }
+  }
+
+  return mode;
+}
+
+
+IcCheckType KeyedStoreICNexus::GetKeyType() const {
+  // The structure of the vector slots tells us the type.
+  return GetFeedback()->IsName() ? PROPERTY : ELEMENT;
+}
 }  // namespace internal
 }  // namespace v8
index 86292a2ab008d11faf8b449fc171d09c41debc62..29e4402d7d2dac5446ca360655635a5f9b3105a3 100644 (file)
@@ -490,6 +490,12 @@ class KeyedStoreICNexus : public FeedbackNexus {
   // name can be null.
   void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
                             CodeHandleList* handlers);
+  void ConfigurePolymorphic(MapHandleList* maps,
+                            MapHandleList* transitioned_maps,
+                            CodeHandleList* handlers);
+
+  KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
+  IcCheckType GetKeyType() const;
 
   InlineCacheState StateFromFeedback() const override;
   Name* FindFirstName() const override;
index bffeccfbc19810e3742e185fe6e9b489edaf2f3a..15a64ef84510cddac13933d5d1fbd510980d96ee 100644 (file)
@@ -131,6 +131,21 @@ bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) {
 }
 
 
+bool TypeFeedbackOracle::StoreIsUninitialized(FeedbackVectorICSlot slot) {
+  if (!slot.IsInvalid()) {
+    Code::Kind kind = feedback_vector_->GetKind(slot);
+    if (kind == Code::STORE_IC) {
+      StoreICNexus nexus(feedback_vector_, slot);
+      return nexus.StateFromFeedback();
+    } else if (kind == Code::KEYED_STORE_IC) {
+      KeyedStoreICNexus nexus(feedback_vector_, slot);
+      return nexus.StateFromFeedback();
+    }
+  }
+  return true;
+}
+
+
 bool TypeFeedbackOracle::CallIsUninitialized(FeedbackVectorICSlot slot) {
   Handle<Object> value = GetInfo(slot);
   return value->IsUndefined() ||
@@ -180,18 +195,17 @@ void TypeFeedbackOracle::GetStoreModeAndKeyType(
 }
 
 
-void TypeFeedbackOracle::GetLoadKeyType(
-    TypeFeedbackId ast_id, IcCheckType* key_type) {
-  Handle<Object> maybe_code = GetInfo(ast_id);
-  if (maybe_code->IsCode()) {
-    Handle<Code> code = Handle<Code>::cast(maybe_code);
-    if (code->kind() == Code::KEYED_LOAD_IC) {
-      ExtraICState extra_ic_state = code->extra_ic_state();
-      *key_type = KeyedLoadIC::GetKeyType(extra_ic_state);
-      return;
-    }
+void TypeFeedbackOracle::GetStoreModeAndKeyType(
+    FeedbackVectorICSlot slot, KeyedAccessStoreMode* store_mode,
+    IcCheckType* key_type) {
+  if (!slot.IsInvalid()) {
+    KeyedStoreICNexus nexus(feedback_vector_, slot);
+    *store_mode = nexus.GetKeyedAccessStoreMode();
+    *key_type = nexus.GetKeyType();
+  } else {
+    *store_mode = STANDARD_STORE;
+    *key_type = ELEMENT;
   }
-  *key_type = ELEMENT;
 }
 
 
@@ -366,6 +380,15 @@ void TypeFeedbackOracle::AssignmentReceiverTypes(TypeFeedbackId id,
 }
 
 
+void TypeFeedbackOracle::AssignmentReceiverTypes(FeedbackVectorICSlot slot,
+                                                 Handle<Name> name,
+                                                 SmallMapList* receiver_types) {
+  receiver_types->Clear();
+  Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
+  CollectReceiverTypes(slot, name, flags, receiver_types);
+}
+
+
 void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
     TypeFeedbackId id, SmallMapList* receiver_types,
     KeyedAccessStoreMode* store_mode, IcCheckType* key_type) {
@@ -375,6 +398,15 @@ void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
 }
 
 
+void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
+    FeedbackVectorICSlot slot, SmallMapList* receiver_types,
+    KeyedAccessStoreMode* store_mode, IcCheckType* key_type) {
+  receiver_types->Clear();
+  CollectReceiverTypes(slot, receiver_types);
+  GetStoreModeAndKeyType(slot, store_mode, key_type);
+}
+
+
 void TypeFeedbackOracle::CountReceiverTypes(TypeFeedbackId id,
                                             SmallMapList* receiver_types) {
   receiver_types->Clear();
@@ -382,6 +414,15 @@ void TypeFeedbackOracle::CountReceiverTypes(TypeFeedbackId id,
 }
 
 
+void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorICSlot slot,
+                                              Handle<Name> name,
+                                              Code::Flags flags,
+                                              SmallMapList* types) {
+  StoreICNexus nexus(feedback_vector_, slot);
+  CollectReceiverTypes<FeedbackNexus>(&nexus, name, flags, types);
+}
+
+
 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
                                               Handle<Name> name,
                                               Code::Flags flags,
@@ -419,6 +460,13 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
 }
 
 
+void TypeFeedbackOracle::CollectReceiverTypes(FeedbackVectorICSlot slot,
+                                              SmallMapList* types) {
+  KeyedStoreICNexus nexus(feedback_vector_, slot);
+  CollectReceiverTypes<FeedbackNexus>(&nexus, types);
+}
+
+
 template <class T>
 void TypeFeedbackOracle::CollectReceiverTypes(T* obj, SmallMapList* types) {
   MapHandleList maps;
index 7143458a350023381b81247e186573fa170abda3..96539c923b5b96e0162f44147dfe364c2963924a 100644 (file)
@@ -28,6 +28,7 @@ class TypeFeedbackOracle: public ZoneObject {
   InlineCacheState LoadInlineCacheState(TypeFeedbackId id);
   InlineCacheState LoadInlineCacheState(FeedbackVectorICSlot slot);
   bool StoreIsUninitialized(TypeFeedbackId id);
+  bool StoreIsUninitialized(FeedbackVectorICSlot slot);
   bool CallIsUninitialized(FeedbackVectorICSlot slot);
   bool CallIsMonomorphic(FeedbackVectorICSlot slot);
   bool KeyedArrayCallIsHoley(TypeFeedbackId id);
@@ -42,6 +43,9 @@ class TypeFeedbackOracle: public ZoneObject {
   void GetStoreModeAndKeyType(TypeFeedbackId id,
                               KeyedAccessStoreMode* store_mode,
                               IcCheckType* key_type);
+  void GetStoreModeAndKeyType(FeedbackVectorICSlot slot,
+                              KeyedAccessStoreMode* store_mode,
+                              IcCheckType* key_type);
   void GetLoadKeyType(TypeFeedbackId id, IcCheckType* key_type);
 
   void PropertyReceiverTypes(FeedbackVectorICSlot slot, Handle<Name> name,
@@ -51,13 +55,20 @@ class TypeFeedbackOracle: public ZoneObject {
                                   IcCheckType* key_type);
   void AssignmentReceiverTypes(TypeFeedbackId id, Handle<Name> name,
                                SmallMapList* receiver_types);
+  void AssignmentReceiverTypes(FeedbackVectorICSlot slot, Handle<Name> name,
+                               SmallMapList* receiver_types);
   void KeyedAssignmentReceiverTypes(TypeFeedbackId id,
                                     SmallMapList* receiver_types,
                                     KeyedAccessStoreMode* store_mode,
                                     IcCheckType* key_type);
+  void KeyedAssignmentReceiverTypes(FeedbackVectorICSlot slot,
+                                    SmallMapList* receiver_types,
+                                    KeyedAccessStoreMode* store_mode,
+                                    IcCheckType* key_type);
   void CountReceiverTypes(TypeFeedbackId id,
                           SmallMapList* receiver_types);
 
+  void CollectReceiverTypes(FeedbackVectorICSlot slot, SmallMapList* types);
   void CollectReceiverTypes(TypeFeedbackId id,
                             SmallMapList* types);
   template <class T>
@@ -102,6 +113,8 @@ class TypeFeedbackOracle: public ZoneObject {
   Isolate* isolate() const { return isolate_; }
 
  private:
+  void CollectReceiverTypes(FeedbackVectorICSlot slot, Handle<Name> name,
+                            Code::Flags flags, SmallMapList* types);
   void CollectReceiverTypes(TypeFeedbackId id, Handle<Name> name,
                             Code::Flags flags, SmallMapList* types);
   template <class T>
index 1cb7577775622c59880638d2d2bf5067cf5c6d7f..b2b60bde2c7a39dcf2ac56f54fedee8edf2e0237 100644 (file)
@@ -427,18 +427,31 @@ void AstTyper::VisitAssignment(Assignment* expr) {
   Property* prop = expr->target()->AsProperty();
   if (prop != NULL) {
     TypeFeedbackId id = expr->AssignmentFeedbackId();
-    expr->set_is_uninitialized(oracle()->StoreIsUninitialized(id));
+    FeedbackVectorICSlot slot = expr->AssignmentSlot();
+    expr->set_is_uninitialized(FLAG_vector_stores
+                                   ? oracle()->StoreIsUninitialized(slot)
+                                   : oracle()->StoreIsUninitialized(id));
     if (!expr->IsUninitialized()) {
+      SmallMapList* receiver_types = expr->GetReceiverTypes();
       if (prop->key()->IsPropertyName()) {
         Literal* lit_key = prop->key()->AsLiteral();
         DCHECK(lit_key != NULL && lit_key->value()->IsString());
         Handle<String> name = Handle<String>::cast(lit_key->value());
-        oracle()->AssignmentReceiverTypes(id, name, expr->GetReceiverTypes());
+        if (FLAG_vector_stores) {
+          oracle()->AssignmentReceiverTypes(slot, name, receiver_types);
+        } else {
+          oracle()->AssignmentReceiverTypes(id, name, receiver_types);
+        }
       } else {
         KeyedAccessStoreMode store_mode;
         IcCheckType key_type;
-        oracle()->KeyedAssignmentReceiverTypes(id, expr->GetReceiverTypes(),
-                                               &store_mode, &key_type);
+        if (FLAG_vector_stores) {
+          oracle()->KeyedAssignmentReceiverTypes(slot, receiver_types,
+                                                 &store_mode, &key_type);
+        } else {
+          oracle()->KeyedAssignmentReceiverTypes(id, receiver_types,
+                                                 &store_mode, &key_type);
+        }
         expr->set_store_mode(store_mode);
         expr->set_key_type(key_type);
       }