Commit df9822f4 authored by jkummerow's avatar jkummerow Committed by Commit bot

[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=yangguo@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#30076}
parent a45ed17b
......@@ -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);
......
......@@ -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()) {
......
......@@ -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());
......
......@@ -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
......
......@@ -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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment