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 ...@@ -956,8 +956,9 @@ class DictionaryElementsAccessor
? JSObject::NormalizeElements(object) ? JSObject::NormalizeElements(object)
: handle(SeededNumberDictionary::cast(object->elements())); : handle(SeededNumberDictionary::cast(object->elements()));
Handle<SeededNumberDictionary> new_dictionary = Handle<SeededNumberDictionary> new_dictionary =
SeededNumberDictionary::AddNumberEntry(dictionary, index, value, SeededNumberDictionary::AddNumberEntry(
details); dictionary, index, value, details,
object->map()->is_prototype_map());
if (attributes != NONE) object->RequireSlowElements(*new_dictionary); if (attributes != NONE) object->RequireSlowElements(*new_dictionary);
if (dictionary.is_identical_to(new_dictionary)) return; if (dictionary.is_identical_to(new_dictionary)) return;
object->set_elements(*new_dictionary); object->set_elements(*new_dictionary);
...@@ -1639,8 +1640,9 @@ class SlowSloppyArgumentsElementsAccessor ...@@ -1639,8 +1640,9 @@ class SlowSloppyArgumentsElementsAccessor
: JSObject::NormalizeElements(object); : JSObject::NormalizeElements(object);
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
Handle<SeededNumberDictionary> new_dictionary = Handle<SeededNumberDictionary> new_dictionary =
SeededNumberDictionary::AddNumberEntry(dictionary, index, value, SeededNumberDictionary::AddNumberEntry(
details); dictionary, index, value, details,
object->map()->is_prototype_map());
if (attributes != NONE) object->RequireSlowElements(*new_dictionary); if (attributes != NONE) object->RequireSlowElements(*new_dictionary);
if (*dictionary != *new_dictionary) { if (*dictionary != *new_dictionary) {
FixedArray::cast(object->elements())->set(1, *new_dictionary); FixedArray::cast(object->elements())->set(1, *new_dictionary);
...@@ -1672,8 +1674,8 @@ class SlowSloppyArgumentsElementsAccessor ...@@ -1672,8 +1674,8 @@ class SlowSloppyArgumentsElementsAccessor
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
Handle<SeededNumberDictionary> arguments( Handle<SeededNumberDictionary> arguments(
SeededNumberDictionary::cast(parameter_map->get(1))); SeededNumberDictionary::cast(parameter_map->get(1)));
arguments = SeededNumberDictionary::AddNumberEntry(arguments, entry, arguments = SeededNumberDictionary::AddNumberEntry(
value, details); arguments, entry, value, details, object->map()->is_prototype_map());
// If the attributes were NONE, we would have called set rather than // If the attributes were NONE, we would have called set rather than
// reconfigure. // reconfigure.
DCHECK_NE(NONE, attributes); DCHECK_NE(NONE, attributes);
......
...@@ -306,7 +306,11 @@ void LookupIterator::TransitionToAccessorPair(Handle<Object> pair, ...@@ -306,7 +306,11 @@ void LookupIterator::TransitionToAccessorPair(Handle<Object> pair,
Handle<SeededNumberDictionary> dictionary = Handle<SeededNumberDictionary> dictionary =
JSObject::NormalizeElements(receiver); 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); receiver->RequireSlowElements(*dictionary);
if (receiver->HasSlowArgumentsElements()) { if (receiver->HasSlowArgumentsElements()) {
......
...@@ -4909,9 +4909,8 @@ void JSObject::ResetElements(Handle<JSObject> object) { ...@@ -4909,9 +4909,8 @@ void JSObject::ResetElements(Handle<JSObject> object) {
static Handle<SeededNumberDictionary> CopyFastElementsToDictionary( static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
Handle<FixedArrayBase> array, Handle<FixedArrayBase> array, int length,
int length, Handle<SeededNumberDictionary> dictionary, bool used_as_prototype) {
Handle<SeededNumberDictionary> dictionary) {
Isolate* isolate = array->GetIsolate(); Isolate* isolate = array->GetIsolate();
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
bool has_double_elements = array->IsFixedDoubleArray(); bool has_double_elements = array->IsFixedDoubleArray();
...@@ -4930,8 +4929,8 @@ static Handle<SeededNumberDictionary> CopyFastElementsToDictionary( ...@@ -4930,8 +4929,8 @@ static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
} }
if (!value->IsTheHole()) { if (!value->IsTheHole()) {
PropertyDetails details = PropertyDetails::Empty(); PropertyDetails details = PropertyDetails::Empty();
dictionary = dictionary = SeededNumberDictionary::AddNumberEntry(
SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details); dictionary, i, value, details, used_as_prototype);
} }
} }
return dictionary; return dictionary;
...@@ -4962,7 +4961,8 @@ Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary( ...@@ -4962,7 +4961,8 @@ Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
int used = object->GetFastElementsUsage(); int used = object->GetFastElementsUsage();
Handle<SeededNumberDictionary> dictionary = Handle<SeededNumberDictionary> dictionary =
SeededNumberDictionary::New(isolate, used); 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( ...@@ -13867,7 +13867,7 @@ Handle<Object> JSObject::PrepareSlowElementsForSort(
return bailout; return bailout;
} else { } else {
Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 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)); DCHECK(result.is_identical_to(new_dict));
USE(result); USE(result);
pos++; pos++;
...@@ -13878,7 +13878,7 @@ Handle<Object> JSObject::PrepareSlowElementsForSort( ...@@ -13878,7 +13878,7 @@ Handle<Object> JSObject::PrepareSlowElementsForSort(
return bailout; return bailout;
} else { } else {
Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 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)); DCHECK(result.is_identical_to(new_dict));
USE(result); USE(result);
} }
...@@ -13894,7 +13894,8 @@ Handle<Object> JSObject::PrepareSlowElementsForSort( ...@@ -13894,7 +13894,8 @@ Handle<Object> JSObject::PrepareSlowElementsForSort(
} }
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 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)); DCHECK(result.is_identical_to(new_dict));
USE(result); USE(result);
pos++; pos++;
...@@ -14633,7 +14634,8 @@ void Dictionary<Derived, Shape, Key>::AddEntry( ...@@ -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; DisallowHeapAllocation no_allocation;
// If the dictionary requires slow elements an element has already // If the dictionary requires slow elements an element has already
// been added at a high index. // been added at a high index.
...@@ -14641,8 +14643,10 @@ void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { ...@@ -14641,8 +14643,10 @@ void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
// Check if this index is high enough that we should require slow // Check if this index is high enough that we should require slow
// elements. // elements.
if (key > kRequiresSlowElementsLimit) { if (key > kRequiresSlowElementsLimit) {
// TODO(verwaest): Remove this hack. if (used_as_prototype) {
GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); // TODO(verwaest): Remove this hack.
GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
}
set_requires_slow_elements(); set_requires_slow_elements();
return; return;
} }
...@@ -14656,11 +14660,9 @@ void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { ...@@ -14656,11 +14660,9 @@ void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
Handle<SeededNumberDictionary> dictionary, Handle<SeededNumberDictionary> dictionary, uint32_t key,
uint32_t key, Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
Handle<Object> value, dictionary->UpdateMaxNumberKey(key, used_as_prototype);
PropertyDetails details) {
dictionary->UpdateMaxNumberKey(key);
SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
return Add(dictionary, key, value, details); return Add(dictionary, key, value, details);
} }
...@@ -14676,10 +14678,9 @@ Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( ...@@ -14676,10 +14678,9 @@ Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
Handle<SeededNumberDictionary> dictionary, Handle<SeededNumberDictionary> dictionary, uint32_t key,
uint32_t key, Handle<Object> value, bool used_as_prototype) {
Handle<Object> value) { dictionary->UpdateMaxNumberKey(key, used_as_prototype);
dictionary->UpdateMaxNumberKey(key);
return AtPut(dictionary, key, value); return AtPut(dictionary, key, value);
} }
...@@ -14693,13 +14694,11 @@ Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut( ...@@ -14693,13 +14694,11 @@ Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
Handle<SeededNumberDictionary> SeededNumberDictionary::Set( Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
Handle<SeededNumberDictionary> dictionary, Handle<SeededNumberDictionary> dictionary, uint32_t key,
uint32_t key, Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
Handle<Object> value,
PropertyDetails details) {
int entry = dictionary->FindEntry(key); int entry = dictionary->FindEntry(key);
if (entry == kNotFound) { if (entry == kNotFound) {
return AddNumberEntry(dictionary, key, value, details); return AddNumberEntry(dictionary, key, value, details, used_as_prototype);
} }
// Preserve enumeration index. // Preserve enumeration index.
details = details.set_index(dictionary->DetailsAt(entry).dictionary_index()); details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
......
...@@ -3448,24 +3448,19 @@ class SeededNumberDictionary ...@@ -3448,24 +3448,19 @@ class SeededNumberDictionary
// Type specific at put (default NONE attributes is used when adding). // Type specific at put (default NONE attributes is used when adding).
MUST_USE_RESULT static Handle<SeededNumberDictionary> AtNumberPut( MUST_USE_RESULT static Handle<SeededNumberDictionary> AtNumberPut(
Handle<SeededNumberDictionary> dictionary, Handle<SeededNumberDictionary> dictionary, uint32_t key,
uint32_t key, Handle<Object> value, bool used_as_prototype);
Handle<Object> value);
MUST_USE_RESULT static Handle<SeededNumberDictionary> AddNumberEntry( MUST_USE_RESULT static Handle<SeededNumberDictionary> AddNumberEntry(
Handle<SeededNumberDictionary> dictionary, Handle<SeededNumberDictionary> dictionary, uint32_t key,
uint32_t key, Handle<Object> value, PropertyDetails details, bool used_as_prototype);
Handle<Object> value,
PropertyDetails details);
// Set an existing entry or add a new one if needed. // Set an existing entry or add a new one if needed.
// Return the updated dictionary. // Return the updated dictionary.
MUST_USE_RESULT static Handle<SeededNumberDictionary> Set( MUST_USE_RESULT static Handle<SeededNumberDictionary> Set(
Handle<SeededNumberDictionary> dictionary, Handle<SeededNumberDictionary> dictionary, uint32_t key,
uint32_t key, Handle<Object> value, PropertyDetails details, bool used_as_prototype);
Handle<Object> value,
PropertyDetails details);
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 // If slow elements are required we will never go back to fast-case
// for the elements kept in this dictionary. We require slow // for the elements kept in this dictionary. We require slow
......
...@@ -154,8 +154,10 @@ class ArrayConcatVisitor { ...@@ -154,8 +154,10 @@ class ArrayConcatVisitor {
DCHECK(!fast_elements()); DCHECK(!fast_elements());
Handle<SeededNumberDictionary> dict( Handle<SeededNumberDictionary> dict(
SeededNumberDictionary::cast(*storage_)); 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 = Handle<SeededNumberDictionary> result =
SeededNumberDictionary::AtNumberPut(dict, index, elm); SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
if (!result.is_identical_to(dict)) { if (!result.is_identical_to(dict)) {
// Dictionary needed to grow. // Dictionary needed to grow.
clear_storage(); clear_storage();
...@@ -207,8 +209,11 @@ class ArrayConcatVisitor { ...@@ -207,8 +209,11 @@ class ArrayConcatVisitor {
HandleScope loop_scope(isolate_); HandleScope loop_scope(isolate_);
Handle<Object> element(current_storage->get(i), isolate_); Handle<Object> element(current_storage->get(i), isolate_);
if (!element->IsTheHole()) { 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 = 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)) { if (!new_storage.is_identical_to(slow_storage)) {
slow_storage = loop_scope.CloseAndEscape(new_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