[elements] Support dictionary-mode in initialize_elements and remove ResetElements

Bug: 
Change-Id: I240356157c71a544d94f8898029d54010b2f4d37
Reviewed-on: https://chromium-review.googlesource.com/544309
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46173}
This commit is contained in:
Toon Verwaest 2017-06-23 10:41:29 +02:00 committed by Commit Bot
parent 8822219978
commit 2b99d09e62
5 changed files with 48 additions and 57 deletions

View File

@ -1361,43 +1361,44 @@ class DictionaryElementsAccessor
int capacity = dict->Capacity();
uint32_t old_length = 0;
CHECK(array->length()->ToArrayLength(&old_length));
if (length < old_length) {
if (dict->requires_slow_elements()) {
// Find last non-deletable element in range of elements to be
// deleted and adjust range accordingly.
for (int entry = 0; entry < capacity; entry++) {
DisallowHeapAllocation no_gc;
Object* index = dict->KeyAt(entry);
if (index->IsNumber()) {
uint32_t number = static_cast<uint32_t>(index->Number());
if (length <= number && number < old_length) {
PropertyDetails details = dict->DetailsAt(entry);
if (!details.IsConfigurable()) length = number + 1;
}
}
}
}
if (length == 0) {
// Flush the backing store.
JSObject::ResetElements(array);
} else {
DisallowHeapAllocation no_gc;
// Remove elements that should be deleted.
int removed_entries = 0;
for (int entry = 0; entry < capacity; entry++) {
Object* index = dict->KeyAt(entry);
if (index->IsNumber()) {
uint32_t number = static_cast<uint32_t>(index->Number());
if (length <= number && number < old_length) {
dict->ClearEntry(entry);
removed_entries++;
{
DisallowHeapAllocation no_gc;
if (length < old_length) {
if (dict->requires_slow_elements()) {
// Find last non-deletable element in range of elements to be
// deleted and adjust range accordingly.
for (int entry = 0; entry < capacity; entry++) {
Object* index = dict->KeyAt(entry);
if (dict->IsKey(isolate, index)) {
uint32_t number = static_cast<uint32_t>(index->Number());
if (length <= number && number < old_length) {
PropertyDetails details = dict->DetailsAt(entry);
if (!details.IsConfigurable()) length = number + 1;
}
}
}
}
// Update the number of elements.
dict->ElementsRemoved(removed_entries);
if (length == 0) {
// Flush the backing store.
array->initialize_elements();
} else {
// Remove elements that should be deleted.
int removed_entries = 0;
for (int entry = 0; entry < capacity; entry++) {
Object* index = dict->KeyAt(entry);
if (dict->IsKey(isolate, index)) {
uint32_t number = static_cast<uint32_t>(index->Number());
if (length <= number && number < old_length) {
dict->ClearEntry(entry);
removed_entries++;
}
}
}
// Update the number of elements.
dict->ElementsRemoved(removed_entries);
}
}
}
@ -1714,15 +1715,18 @@ class DictionaryElementsAccessor
if (*dictionary == receiver->elements()) continue;
// Otherwise, bailout or update elements
// If switched to initial elements, return true if searching for
// undefined, and false otherwise.
if (receiver->map()->GetInitialElements() == receiver->elements()) {
return Just(search_for_hole);
}
// If switched to fast elements, continue with the correct accessor.
if (receiver->GetElementsKind() != DICTIONARY_ELEMENTS) {
if (receiver->map()->GetInitialElements() == receiver->elements()) {
// If switched to initial elements, return true if searching for
// undefined, and false otherwise.
return Just(search_for_hole);
}
// Otherwise, switch to slow path.
return IncludesValueSlowPath(isolate, receiver, value, k + 1,
length);
ElementsAccessor* accessor = receiver->GetElementsAccessor();
return accessor->IncludesValue(isolate, receiver, value, k + 1,
length);
}
dictionary = handle(
SeededNumberDictionary::cast(receiver->elements()), isolate);

View File

@ -2402,6 +2402,8 @@ FixedArrayBase* Map::GetInitialElements() {
result = GetHeap()->empty_sloppy_arguments_elements();
} else if (has_fixed_typed_array_elements()) {
result = GetHeap()->EmptyFixedTypedArrayForMap(this);
} else if (has_dictionary_elements()) {
result = GetHeap()->empty_slow_element_dictionary();
} else {
UNREACHABLE();
}

View File

@ -5835,20 +5835,6 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
DCHECK(object->HasFastProperties());
}
void JSObject::ResetElements(Handle<JSObject> object) {
Isolate* isolate = object->GetIsolate();
CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
if (object->map()->has_dictionary_elements()) {
Handle<SeededNumberDictionary> new_elements =
SeededNumberDictionary::New(isolate, 0);
object->set_elements(*new_elements);
} else {
object->set_elements(object->map()->GetInitialElements());
}
}
void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
if (dictionary->requires_slow_elements()) return;
dictionary->set_requires_slow_elements();

View File

@ -2149,7 +2149,6 @@ class JSObject: public JSReceiver {
// FixedArray parameter map for a (sloppy) arguments object.
DECL_ACCESSORS(elements, FixedArrayBase)
inline void initialize_elements();
static void ResetElements(Handle<JSObject> object);
static inline void SetMapAndElements(Handle<JSObject> object,
Handle<Map> map,
Handle<FixedArrayBase> elements);

View File

@ -132,7 +132,7 @@ RUNTIME_FUNCTION(Runtime_MoveArrayContents) {
JSObject::SetMapAndElements(to, new_map, new_elements);
to->set_length(from->length());
JSObject::ResetElements(from);
from->initialize_elements();
from->set_length(Smi::kZero);
JSObject::ValidateElements(to);