Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Unified Diff: src/objects.cc

Issue 1241883002: Cleanup element normalization logic (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 45f7ab9ea32e91083b51d4de6df68028a9810823..4deb64da048e335e582f10797dd0853963dd4496 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -4789,6 +4789,24 @@ static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
}
+Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
+ Handle<JSObject> object, Handle<FixedArrayBase> elements) {
+ DCHECK(!object->HasDictionaryElements());
+ DCHECK(!object->HasSlowArgumentsElements());
+ Isolate* isolate = object->GetIsolate();
+ // Ensure that notifications fire if the array or object prototypes are
+ // normalizing.
+ isolate->UpdateArrayProtectorOnNormalizeElements(object);
+ int length = object->IsJSArray()
+ ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
+ : elements->length();
+ int used = object->GetFastElementsUsage();
+ Handle<SeededNumberDictionary> dictionary =
+ SeededNumberDictionary::New(isolate, used);
+ return CopyFastElementsToDictionary(elements, length, dictionary);
+}
+
+
Handle<SeededNumberDictionary> JSObject::NormalizeElements(
Handle<JSObject> object) {
DCHECK(!object->HasExternalArrayElements() &&
@@ -4796,34 +4814,23 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
Isolate* isolate = object->GetIsolate();
// Find the backing store.
- Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements()));
- bool is_arguments =
- (array->map() == isolate->heap()->sloppy_arguments_elements_map());
+ Handle<FixedArrayBase> elements(object->elements(), isolate);
+ bool is_arguments = object->HasSloppyArgumentsElements();
if (is_arguments) {
- array = handle(FixedArrayBase::cast(
- Handle<FixedArray>::cast(array)->get(1)));
+ FixedArray* parameter_map = FixedArray::cast(*elements);
+ elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate);
+ }
+
+ if (elements->IsDictionary()) {
+ return Handle<SeededNumberDictionary>::cast(elements);
}
- if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array);
DCHECK(object->HasFastSmiOrObjectElements() ||
object->HasFastDoubleElements() ||
object->HasFastArgumentsElements());
- // Ensure that notifications fire if the array or object prototypes are
- // normalizing.
- isolate->UpdateArrayProtectorOnNormalizeElements(object);
-
- // Compute the effective length and allocate a new backing store.
- int length = object->IsJSArray()
- ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
- : array->length();
- int old_capacity = 0;
- int used_elements = 0;
- object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
Handle<SeededNumberDictionary> dictionary =
- SeededNumberDictionary::New(isolate, used_elements);
-
- dictionary = CopyFastElementsToDictionary(array, length, dictionary);
+ GetNormalizedElementDictionary(object, elements);
// Switch to using the dictionary as the backing storage for elements.
ElementsKind target_kind =
@@ -5463,30 +5470,6 @@ bool JSObject::IsExtensible() {
}
-Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
- Handle<JSObject> object) {
- DCHECK(!object->elements()->IsDictionary());
- Isolate* isolate = object->GetIsolate();
- int length = object->IsJSArray()
- ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
- : object->elements()->length();
- if (length > 0) {
- int capacity = 0;
- int used = 0;
- object->GetElementsCapacityAndUsage(&capacity, &used);
- Handle<SeededNumberDictionary> new_element_dictionary =
- SeededNumberDictionary::New(isolate, used);
-
- // Move elements to a dictionary; avoid calling NormalizeElements to avoid
- // unnecessary transitions.
- return CopyFastElementsToDictionary(handle(object->elements()), length,
- new_element_dictionary);
- }
- // No existing elements, use a pre-allocated empty backing store
- return isolate->factory()->empty_slow_element_dictionary();
-}
-
-
template <typename Dictionary>
static void ApplyAttributesToDictionary(Dictionary* dictionary,
const PropertyAttributes attributes) {
@@ -5544,9 +5527,15 @@ MaybeHandle<Object> JSObject::PreventExtensionsWithTransition(
}
Handle<SeededNumberDictionary> new_element_dictionary;
- if (!object->elements()->IsDictionary()) {
- new_element_dictionary = GetNormalizedElementDictionary(object);
- isolate->UpdateArrayProtectorOnNormalizeElements(object);
+ if (!object->HasDictionaryElements()) {
+ int length =
+ object->IsJSArray()
+ ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
+ : object->elements()->length();
+ new_element_dictionary =
+ length == 0 ? isolate->factory()->empty_slow_element_dictionary()
+ : GetNormalizedElementDictionary(
+ object, handle(object->elements()));
}
Handle<Symbol> transition_marker;
@@ -12148,9 +12137,7 @@ static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
// If the fast-case backing storage takes up roughly three times as
// much space (in machine words) as a dictionary backing storage
// would, the object should have slow elements.
- int old_capacity = 0;
- int used_elements = 0;
- object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
+ int used_elements = object->GetFastElementsUsage();
int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
SeededNumberDictionary::kEntrySize;
return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
@@ -12517,79 +12504,48 @@ MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
}
-void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
- *capacity = 0;
- *used = 0;
+template <typename BackingStore>
+static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) {
+ int limit = object->IsJSArray()
+ ? Smi::cast(JSArray::cast(object)->length())->value()
+ : store->length();
+ int used = 0;
+ for (int i = 0; i < limit; ++i) {
+ if (!store->is_the_hole(i)) ++used;
+ }
+ return used;
+}
+
- FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
- FixedArray* backing_store = NULL;
+int JSObject::GetFastElementsUsage() {
+ FixedArrayBase* store = elements();
switch (GetElementsKind()) {
- case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
- case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
- backing_store_base =
- FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
- backing_store = FixedArray::cast(backing_store_base);
- if (backing_store->IsDictionary()) {
- SeededNumberDictionary* dictionary =
- SeededNumberDictionary::cast(backing_store);
- *capacity = dictionary->Capacity();
- *used = dictionary->NumberOfElements();
- break;
- }
- // Fall through.
case FAST_SMI_ELEMENTS:
+ case FAST_DOUBLE_ELEMENTS:
case FAST_ELEMENTS:
- if (IsJSArray()) {
- *capacity = backing_store_base->length();
- *used = Smi::cast(JSArray::cast(this)->length())->value();
- break;
- }
- // Fall through if packing is not guaranteed.
+ // Only JSArray have packed elements.
+ return Smi::cast(JSArray::cast(this)->length())->value();
+ case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
+ store = FixedArray::cast(FixedArray::cast(store)->get(1));
+ // Fall through.
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
- backing_store = FixedArray::cast(backing_store_base);
- *capacity = backing_store->length();
- for (int i = 0; i < *capacity; ++i) {
- if (!backing_store->get(i)->IsTheHole()) ++(*used);
- }
- break;
- case DICTIONARY_ELEMENTS: {
- SeededNumberDictionary* dictionary = element_dictionary();
- *capacity = dictionary->Capacity();
- *used = dictionary->NumberOfElements();
- break;
- }
- case FAST_DOUBLE_ELEMENTS:
- if (IsJSArray()) {
- *capacity = backing_store_base->length();
- *used = Smi::cast(JSArray::cast(this)->length())->value();
- break;
- }
- // Fall through if packing is not guaranteed.
- case FAST_HOLEY_DOUBLE_ELEMENTS: {
- *capacity = elements()->length();
- if (*capacity == 0) break;
- FixedDoubleArray * elms = FixedDoubleArray::cast(elements());
- for (int i = 0; i < *capacity; i++) {
- if (!elms->is_the_hole(i)) ++(*used);
- }
- break;
- }
+ return FastHoleyElementsUsage(this, FixedArray::cast(store));
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
+ if (elements()->length() == 0) return 0;
+ return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
+ case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
+ case DICTIONARY_ELEMENTS:
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case EXTERNAL_##TYPE##_ELEMENTS: \
case TYPE##_ELEMENTS: \
TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
- {
- // External arrays are considered 100% used.
- FixedArrayBase* external_array = FixedArrayBase::cast(elements());
- *capacity = external_array->length();
- *used = external_array->length();
- break;
- }
+ UNREACHABLE();
}
+ return 0;
}
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698