| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 111ccafafeb43637d08894a26b365a63ca81a8ec..9a903f1ff59ad217d25a74e53589927ea1d12ff7 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -6153,10 +6153,9 @@
|
| void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
|
| if (dictionary->requires_slow_elements()) return;
|
| dictionary->set_requires_slow_elements();
|
| + // TODO(verwaest): Remove this hack.
|
| if (map()->is_prototype_map()) {
|
| - // If this object is a prototype (the callee will check), invalidate any
|
| - // prototype chains involving it.
|
| - InvalidatePrototypeChains(map());
|
| + TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
|
| }
|
| }
|
|
|
| @@ -15612,6 +15611,9 @@
|
| // SpiderMonkey behaves this way.
|
| if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
|
|
|
| + bool dictionary_elements_in_chain =
|
| + object->map()->DictionaryElementsInPrototypeChainOnly();
|
| +
|
| bool all_extensible = object->map()->is_extensible();
|
| Handle<JSObject> real_receiver = object;
|
| if (from_javascript) {
|
| @@ -15676,6 +15678,14 @@
|
| Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
|
| DCHECK(new_map->prototype() == *value);
|
| JSObject::MigrateToMap(real_receiver, new_map);
|
| +
|
| + if (from_javascript && !dictionary_elements_in_chain &&
|
| + new_map->DictionaryElementsInPrototypeChainOnly()) {
|
| + // If the prototype chain didn't previously have element callbacks, then
|
| + // KeyedStoreICs need to be cleared to ensure any that involve this
|
| + // map go generic.
|
| + TypeFeedbackVector::ClearAllKeyedStoreICs(isolate);
|
| + }
|
|
|
| heap->ClearInstanceofCache();
|
| DCHECK(size == object->Size());
|
| @@ -17373,7 +17383,7 @@
|
| return bailout;
|
| } else {
|
| Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
|
| - new_dict, pos, value, details, object);
|
| + new_dict, pos, value, details, object->map()->is_prototype_map());
|
| DCHECK(result.is_identical_to(new_dict));
|
| USE(result);
|
| pos++;
|
| @@ -17384,7 +17394,7 @@
|
| return bailout;
|
| } else {
|
| Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
|
| - new_dict, key, value, details, object);
|
| + new_dict, key, value, details, object->map()->is_prototype_map());
|
| DCHECK(result.is_identical_to(new_dict));
|
| USE(result);
|
| }
|
| @@ -17401,7 +17411,7 @@
|
| HandleScope scope(isolate);
|
| Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
|
| new_dict, pos, isolate->factory()->undefined_value(), no_details,
|
| - object);
|
| + object->map()->is_prototype_map());
|
| DCHECK(result.is_identical_to(new_dict));
|
| USE(result);
|
| pos++;
|
| @@ -18173,8 +18183,8 @@
|
| return false;
|
| }
|
|
|
| -void SeededNumberDictionary::UpdateMaxNumberKey(
|
| - uint32_t key, Handle<JSObject> dictionary_holder) {
|
| +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.
|
| @@ -18182,8 +18192,9 @@
|
| // Check if this index is high enough that we should require slow
|
| // elements.
|
| if (key > kRequiresSlowElementsLimit) {
|
| - if (!dictionary_holder.is_null()) {
|
| - dictionary_holder->RequireSlowElements(this);
|
| + if (used_as_prototype) {
|
| + // TODO(verwaest): Remove this hack.
|
| + TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
|
| }
|
| set_requires_slow_elements();
|
| return;
|
| @@ -18196,11 +18207,11 @@
|
| }
|
| }
|
|
|
| +
|
| Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
|
| Handle<SeededNumberDictionary> dictionary, uint32_t key,
|
| - Handle<Object> value, PropertyDetails details,
|
| - Handle<JSObject> dictionary_holder) {
|
| - dictionary->UpdateMaxNumberKey(key, dictionary_holder);
|
| + 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);
|
| }
|
| @@ -18228,8 +18239,8 @@
|
|
|
| Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
|
| Handle<SeededNumberDictionary> dictionary, uint32_t key,
|
| - Handle<Object> value, Handle<JSObject> dictionary_holder) {
|
| - dictionary->UpdateMaxNumberKey(key, dictionary_holder);
|
| + Handle<Object> value, bool used_as_prototype) {
|
| + dictionary->UpdateMaxNumberKey(key, used_as_prototype);
|
| return AtPut(dictionary, key, value);
|
| }
|
|
|
| @@ -18241,13 +18252,13 @@
|
| return AtPut(dictionary, key, value);
|
| }
|
|
|
| +
|
| Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
|
| Handle<SeededNumberDictionary> dictionary, uint32_t key,
|
| - Handle<Object> value, PropertyDetails details,
|
| - Handle<JSObject> dictionary_holder) {
|
| + Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
|
| int entry = dictionary->FindEntry(key);
|
| if (entry == kNotFound) {
|
| - return AddNumberEntry(dictionary, key, value, details, dictionary_holder);
|
| + return AddNumberEntry(dictionary, key, value, details, used_as_prototype);
|
| }
|
| // Preserve enumeration index.
|
| details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
|
|
|