Reviewers: Yang,

Description:
[IC] Make SeededNumberDictionary::UpdateMaxNumberKey prototype aware

Only walk the heap clearing KeyedStoreICs when the dictionary in question
belongs to an object that's used as a prototype.
This is a temporary mitigation until we have a way to clear such ICs without
having to walk the heap.

BUG=v8:4335
LOG=y
R=yang...@chromium.org

Please review this at https://codereview.chromium.org/1275363002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+52, -47 lines):
  M src/elements.cc
  M src/lookup.cc
  M src/objects.h
  M src/objects.cc
  M src/runtime/runtime-array.cc


Index: src/elements.cc
diff --git a/src/elements.cc b/src/elements.cc
index 76269eb87b3f47d8256965bfd208029f312f3b07..3e80d5570b90e46e9de434d8c9f79abaa104721a 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -956,8 +956,9 @@ class DictionaryElementsAccessor
             ? JSObject::NormalizeElements(object)
             : handle(SeededNumberDictionary::cast(object->elements()));
     Handle<SeededNumberDictionary> new_dictionary =
-        SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
-                                               details);
+        SeededNumberDictionary::AddNumberEntry(
+            dictionary, index, value, details,
+            object->map()->is_prototype_map());
     if (attributes != NONE) object->RequireSlowElements(*new_dictionary);
     if (dictionary.is_identical_to(new_dictionary)) return;
     object->set_elements(*new_dictionary);
@@ -1639,8 +1640,9 @@ class SlowSloppyArgumentsElementsAccessor
             : JSObject::NormalizeElements(object);
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
     Handle<SeededNumberDictionary> new_dictionary =
-        SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
-                                               details);
+        SeededNumberDictionary::AddNumberEntry(
+            dictionary, index, value, details,
+            object->map()->is_prototype_map());
     if (attributes != NONE) object->RequireSlowElements(*new_dictionary);
     if (*dictionary != *new_dictionary) {
       FixedArray::cast(object->elements())->set(1, *new_dictionary);
@@ -1672,8 +1674,8 @@ class SlowSloppyArgumentsElementsAccessor
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
       Handle<SeededNumberDictionary> arguments(
           SeededNumberDictionary::cast(parameter_map->get(1)));
-      arguments = SeededNumberDictionary::AddNumberEntry(arguments, entry,
-                                                         value, details);
+      arguments = SeededNumberDictionary::AddNumberEntry(
+ arguments, entry, value, details, object->map()->is_prototype_map());
       // If the attributes were NONE, we would have called set rather than
       // reconfigure.
       DCHECK_NE(NONE, attributes);
Index: src/lookup.cc
diff --git a/src/lookup.cc b/src/lookup.cc
index 75d460328daf13eba580f8db59ba47afd9780b0b..4d32143242ad98e5f5b970cbae98246dc78647cc 100644
--- a/src/lookup.cc
+++ b/src/lookup.cc
@@ -306,7 +306,11 @@ void LookupIterator::TransitionToAccessorPair(Handle<Object> pair,
     Handle<SeededNumberDictionary> dictionary =
         JSObject::NormalizeElements(receiver);

- dictionary = SeededNumberDictionary::Set(dictionary, index_, pair, details); + // We unconditionally pass used_as_prototype=false here because the call
+    // to RequireSlowElements takes care of the required IC clearing and
+    // we don't want to walk the heap twice.
+    dictionary =
+ SeededNumberDictionary::Set(dictionary, index_, pair, details, false);
     receiver->RequireSlowElements(*dictionary);

     if (receiver->HasSlowArgumentsElements()) {
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 12c8d17c383974a20b587f12012e319f26281c6c..8f3f1875e861853732fa8d79d42ac16145840803 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -4909,9 +4909,8 @@ void JSObject::ResetElements(Handle<JSObject> object) {


 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
-    Handle<FixedArrayBase> array,
-    int length,
-    Handle<SeededNumberDictionary> dictionary) {
+    Handle<FixedArrayBase> array, int length,
+    Handle<SeededNumberDictionary> dictionary, bool used_as_prototype) {
   Isolate* isolate = array->GetIsolate();
   Factory* factory = isolate->factory();
   bool has_double_elements = array->IsFixedDoubleArray();
@@ -4930,8 +4929,8 @@ static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
     }
     if (!value->IsTheHole()) {
       PropertyDetails details = PropertyDetails::Empty();
-      dictionary =
- SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
+      dictionary = SeededNumberDictionary::AddNumberEntry(
+          dictionary, i, value, details, used_as_prototype);
     }
   }
   return dictionary;
@@ -4962,7 +4961,8 @@ Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
   int used = object->GetFastElementsUsage();
   Handle<SeededNumberDictionary> dictionary =
       SeededNumberDictionary::New(isolate, used);
-  return CopyFastElementsToDictionary(elements, length, dictionary);
+  return CopyFastElementsToDictionary(elements, length, dictionary,
+                                      object->map()->is_prototype_map());
 }


@@ -13867,7 +13867,7 @@ Handle<Object> JSObject::PrepareSlowElementsForSort(
         return bailout;
       } else {
         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
-            new_dict, pos, value, details);
+ new_dict, pos, value, details, object->map()->is_prototype_map());
         DCHECK(result.is_identical_to(new_dict));
         USE(result);
         pos++;
@@ -13878,7 +13878,7 @@ Handle<Object> JSObject::PrepareSlowElementsForSort(
       return bailout;
     } else {
       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
-          new_dict, key, value, details);
+ new_dict, key, value, details, object->map()->is_prototype_map());
       DCHECK(result.is_identical_to(new_dict));
       USE(result);
     }
@@ -13894,7 +13894,8 @@ Handle<Object> JSObject::PrepareSlowElementsForSort(
     }
     HandleScope scope(isolate);
     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
-        new_dict, pos, isolate->factory()->undefined_value(), no_details);
+        new_dict, pos, isolate->factory()->undefined_value(), no_details,
+        object->map()->is_prototype_map());
     DCHECK(result.is_identical_to(new_dict));
     USE(result);
     pos++;
@@ -14633,7 +14634,8 @@ void Dictionary<Derived, Shape, Key>::AddEntry(
 }


-void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
+void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key,
+                                                bool used_as_prototype) {
   DisallowHeapAllocation no_allocation;
   // If the dictionary requires slow elements an element has already
   // been added at a high index.
@@ -14641,8 +14643,10 @@ void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
   // Check if this index is high enough that we should require slow
   // elements.
   if (key > kRequiresSlowElementsLimit) {
-    // TODO(verwaest): Remove this hack.
-    GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
+    if (used_as_prototype) {
+      // TODO(verwaest): Remove this hack.
+      GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
+    }
     set_requires_slow_elements();
     return;
   }
@@ -14656,11 +14660,9 @@ void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {


 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
-    Handle<SeededNumberDictionary> dictionary,
-    uint32_t key,
-    Handle<Object> value,
-    PropertyDetails details) {
-  dictionary->UpdateMaxNumberKey(key);
+    Handle<SeededNumberDictionary> dictionary, uint32_t key,
+ Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
+  dictionary->UpdateMaxNumberKey(key, used_as_prototype);
   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
   return Add(dictionary, key, value, details);
 }
@@ -14676,10 +14678,9 @@ Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(


 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
-    Handle<SeededNumberDictionary> dictionary,
-    uint32_t key,
-    Handle<Object> value) {
-  dictionary->UpdateMaxNumberKey(key);
+    Handle<SeededNumberDictionary> dictionary, uint32_t key,
+    Handle<Object> value, bool used_as_prototype) {
+  dictionary->UpdateMaxNumberKey(key, used_as_prototype);
   return AtPut(dictionary, key, value);
 }

@@ -14693,13 +14694,11 @@ Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(


 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
-    Handle<SeededNumberDictionary> dictionary,
-    uint32_t key,
-    Handle<Object> value,
-    PropertyDetails details) {
+    Handle<SeededNumberDictionary> dictionary, uint32_t key,
+ Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
   int entry = dictionary->FindEntry(key);
   if (entry == kNotFound) {
-    return AddNumberEntry(dictionary, key, value, details);
+ return AddNumberEntry(dictionary, key, value, details, used_as_prototype);
   }
   // Preserve enumeration index.
details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 8e64fe38da799f8c772a11ccda4977442703d94f..f8db36600174d7e1c2f147f316368dac3afbf7fb 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -3448,24 +3448,19 @@ class SeededNumberDictionary

   // Type specific at put (default NONE attributes is used when adding).
   MUST_USE_RESULT static Handle<SeededNumberDictionary> AtNumberPut(
-      Handle<SeededNumberDictionary> dictionary,
-      uint32_t key,
-      Handle<Object> value);
+      Handle<SeededNumberDictionary> dictionary, uint32_t key,
+      Handle<Object> value, bool used_as_prototype);
   MUST_USE_RESULT static Handle<SeededNumberDictionary> AddNumberEntry(
-      Handle<SeededNumberDictionary> dictionary,
-      uint32_t key,
-      Handle<Object> value,
-      PropertyDetails details);
+      Handle<SeededNumberDictionary> dictionary, uint32_t key,
+ Handle<Object> value, PropertyDetails details, bool used_as_prototype);

   // Set an existing entry or add a new one if needed.
   // Return the updated dictionary.
   MUST_USE_RESULT static Handle<SeededNumberDictionary> Set(
-      Handle<SeededNumberDictionary> dictionary,
-      uint32_t key,
-      Handle<Object> value,
-      PropertyDetails details);
+      Handle<SeededNumberDictionary> dictionary, uint32_t key,
+ Handle<Object> value, PropertyDetails details, bool used_as_prototype);

-  void UpdateMaxNumberKey(uint32_t key);
+  void UpdateMaxNumberKey(uint32_t key, bool used_as_prototype);

   // If slow elements are required we will never go back to fast-case
   // for the elements kept in this dictionary.  We require slow
Index: src/runtime/runtime-array.cc
diff --git a/src/runtime/runtime-array.cc b/src/runtime/runtime-array.cc
index e29ecd6c83727c57be00751bc2bac3cbdebbfa38..3e05f766ab8b3d1e473acab1cb7214bff83bbb97 100644
--- a/src/runtime/runtime-array.cc
+++ b/src/runtime/runtime-array.cc
@@ -154,8 +154,10 @@ class ArrayConcatVisitor {
     DCHECK(!fast_elements());
     Handle<SeededNumberDictionary> dict(
         SeededNumberDictionary::cast(*storage_));
+    // The object holding this backing store has just been allocated, so
+    // it cannot yet be used as a prototype.
     Handle<SeededNumberDictionary> result =
-        SeededNumberDictionary::AtNumberPut(dict, index, elm);
+        SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
     if (!result.is_identical_to(dict)) {
       // Dictionary needed to grow.
       clear_storage();
@@ -207,8 +209,11 @@ class ArrayConcatVisitor {
       HandleScope loop_scope(isolate_);
       Handle<Object> element(current_storage->get(i), isolate_);
       if (!element->IsTheHole()) {
+ // The object holding this backing store has just been allocated, so
+        // it cannot yet be used as a prototype.
         Handle<SeededNumberDictionary> new_storage =
-            SeededNumberDictionary::AtNumberPut(slow_storage, i, element);
+            SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
+                                                false);
         if (!new_storage.is_identical_to(slow_storage)) {
           slow_storage = loop_scope.CloseAndEscape(new_storage);
         }


--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to