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

Unified Diff: src/objects.cc

Issue 1221713003: Distinguish slow from fast sloppy arguments (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 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') | src/objects-debug.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 4c72aa9d6c5e60723e931762a8b20804fd6e30b2..b44f11eda7ee38c00f51b336a4b8f95ac02b8618 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2423,7 +2423,9 @@ Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
ElementsKind from_kind = root_map->elements_kind();
ElementsKind to_kind = old_map->elements_kind();
+ // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
+ to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
!(IsTransitionableFastElementsKind(from_kind) &&
IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
@@ -3559,51 +3561,38 @@ int AccessorInfo::AppendUnique(Handle<Object> descriptors,
}
-static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
- DCHECK(!map.is_null());
+static bool ContainsMap(MapHandleList* maps, Map* map) {
+ DCHECK_NOT_NULL(map);
for (int i = 0; i < maps->length(); ++i) {
- if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
+ if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
}
return false;
}
-template <class T>
-static Handle<T> MaybeNull(T* p) {
- if (p == NULL) return Handle<T>::null();
- return Handle<T>(p);
-}
-
-
-Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
- ElementsKind kind = elements_kind();
- Handle<Map> transitioned_map = Handle<Map>::null();
- Handle<Map> current_map(this);
+Handle<Map> Map::FindTransitionedMap(Handle<Map> map,
+ MapHandleList* candidates) {
+ ElementsKind kind = map->elements_kind();
bool packed = IsFastPackedElementsKind(kind);
+
+ Map* transition = nullptr;
if (IsTransitionableFastElementsKind(kind)) {
- while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
- kind = GetNextMoreGeneralFastElementsKind(kind, false);
- Handle<Map> maybe_transitioned_map =
- MaybeNull(current_map->LookupElementsTransitionMap(kind));
- if (maybe_transitioned_map.is_null()) break;
- if (ContainsMap(candidates, maybe_transitioned_map) &&
- (packed || !IsFastPackedElementsKind(kind))) {
- transitioned_map = maybe_transitioned_map;
- if (!IsFastPackedElementsKind(kind)) packed = false;
+ for (Map* current = map->ElementsTransitionMap();
+ current != nullptr && current->has_fast_elements();
+ current = current->ElementsTransitionMap()) {
+ if (ContainsMap(candidates, current) &&
+ (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
+ transition = current;
+ packed = packed && IsFastPackedElementsKind(current->elements_kind());
}
- current_map = maybe_transitioned_map;
}
}
- return transitioned_map;
+ return transition == nullptr ? Handle<Map>() : handle(transition);
}
static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
Map* current_map = map;
- int target_kind =
- IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
- ? to_kind
- : TERMINAL_FAST_ELEMENTS_KIND;
// Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
// allows to change elements from arbitrary kind to any ExternalArray
@@ -3619,20 +3608,14 @@ static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
}
ElementsKind kind = map->elements_kind();
- while (kind != target_kind) {
- kind = GetNextTransitionElementsKind(kind);
+ while (kind != to_kind) {
Map* next_map = current_map->ElementsTransitionMap();
- if (next_map == NULL) return current_map;
+ if (next_map == nullptr) return current_map;
+ kind = next_map->elements_kind();
current_map = next_map;
}
- Map* next_map = current_map->ElementsTransitionMap();
- if (to_kind != kind && next_map != NULL) {
- DCHECK(to_kind == DICTIONARY_ELEMENTS);
- if (next_map->elements_kind() == to_kind) return next_map;
- }
-
- DCHECK(current_map->elements_kind() == target_kind);
+ DCHECK_EQ(to_kind, current_map->elements_kind());
return current_map;
}
@@ -3640,7 +3623,7 @@ static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
Map* to_map = FindClosestElementsTransition(this, to_kind);
if (to_map->elements_kind() == to_kind) return to_map;
- return NULL;
+ return nullptr;
}
@@ -3681,9 +3664,11 @@ static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
flag = OMIT_TRANSITION;
} else {
flag = INSERT_TRANSITION;
- while (kind != to_kind && !IsTerminalElementsKind(kind)) {
- kind = GetNextTransitionElementsKind(kind);
- current_map = Map::CopyAsElementsKind(current_map, kind, flag);
+ if (IsFastElementsKind(kind)) {
+ while (kind != to_kind && !IsTerminalElementsKind(kind)) {
+ kind = GetNextTransitionElementsKind(kind);
+ current_map = Map::CopyAsElementsKind(current_map, kind, flag);
+ }
}
}
@@ -3705,16 +3690,28 @@ Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
Isolate* isolate = map->GetIsolate();
Context* native_context = isolate->context()->native_context();
- Object* maybe_array_maps = map->is_strong()
- ? native_context->js_array_strong_maps()
- : native_context->js_array_maps();
- if (maybe_array_maps->IsFixedArray()) {
- DisallowHeapAllocation no_gc;
- FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
- if (array_maps->get(from_kind) == *map) {
- Object* maybe_transitioned_map = array_maps->get(to_kind);
- if (maybe_transitioned_map->IsMap()) {
- return handle(Map::cast(maybe_transitioned_map));
+ if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
+ if (*map == native_context->fast_aliased_arguments_map()) {
+ DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
+ return handle(native_context->slow_aliased_arguments_map());
+ }
+ } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
+ if (*map == native_context->slow_aliased_arguments_map()) {
+ DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
+ return handle(native_context->fast_aliased_arguments_map());
+ }
+ } else {
+ Object* maybe_array_maps = map->is_strong()
+ ? native_context->js_array_strong_maps()
+ : native_context->js_array_maps();
+ if (maybe_array_maps->IsFixedArray()) {
+ DisallowHeapAllocation no_gc;
+ FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
+ if (array_maps->get(from_kind) == *map) {
+ Object* maybe_transitioned_map = array_maps->get(to_kind);
+ if (maybe_transitioned_map->IsMap()) {
+ return handle(Map::cast(maybe_transitioned_map));
+ }
}
}
}
@@ -3723,8 +3720,8 @@ Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
bool allow_store_transition = IsTransitionElementsKind(from_kind);
// Only store fast element maps in ascending generality.
if (IsFastElementsKind(to_kind)) {
- allow_store_transition &=
- IsTransitionableFastElementsKind(from_kind) &&
+ allow_store_transition =
+ allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
IsMoreGeneralElementsKindTransition(from_kind, to_kind);
}
@@ -4817,15 +4814,15 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
dictionary = CopyFastElementsToDictionary(array, length, dictionary);
// Switch to using the dictionary as the backing storage for elements.
+ ElementsKind target_kind =
+ is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS;
+ Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
+ // Set the new map first to satify the elements type assert in set_elements().
+ JSObject::MigrateToMap(object, new_map);
+
if (is_arguments) {
FixedArray::cast(object->elements())->set(1, *dictionary);
} else {
- // Set the new map first to satify the elements type assert in
- // set_elements().
- Handle<Map> new_map =
- JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS);
-
- JSObject::MigrateToMap(object, new_map);
object->set_elements(*dictionary);
}
@@ -4839,8 +4836,7 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
}
#endif
- DCHECK(object->HasDictionaryElements() ||
- object->HasDictionaryArgumentsElements());
+ DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
return dictionary;
}
@@ -5337,7 +5333,8 @@ bool JSObject::ReferencesObject(Object* obj) {
if (ReferencesObjectFromElements(elements, kind, obj)) return true;
break;
}
- case SLOPPY_ARGUMENTS_ELEMENTS: {
+ case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
+ case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
FixedArray* parameter_map = FixedArray::cast(elements());
// Check the mapped parameters.
int length = parameter_map->length();
@@ -5435,8 +5432,7 @@ MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
// If there are fast elements we normalize.
Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
- DCHECK(object->HasDictionaryElements() ||
- object->HasDictionaryArgumentsElements());
+ DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
// Make sure that we never go back to fast case.
dictionary->set_requires_slow_elements();
@@ -5864,7 +5860,8 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
}
break;
}
- case SLOPPY_ARGUMENTS_ELEMENTS:
+ case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
+ case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
UNIMPLEMENTED();
break;
@@ -6281,7 +6278,8 @@ void JSObject::DefineElementAccessor(Handle<JSObject> object,
return;
}
break;
- case SLOPPY_ARGUMENTS_ELEMENTS: {
+ case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
+ case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
// Ascertain whether we have read-only properties or an existing
// getter/setter pair in an arguments elements dictionary backing
// store.
@@ -6347,8 +6345,7 @@ void JSObject::SetElementCallback(Handle<JSObject> object,
// Normalize elements to make this operation simple.
bool had_dictionary_elements = object->HasDictionaryElements();
Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
- DCHECK(object->HasDictionaryElements() ||
- object->HasDictionaryArgumentsElements());
+ DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
// Update the dictionary with the new ACCESSOR_CONSTANT property.
dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
details);
@@ -7130,7 +7127,8 @@ Handle<Map> Map::PrepareForDataElement(Handle<Map> map, Handle<Object> value) {
case FAST_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case SLOPPY_ARGUMENTS_ELEMENTS:
+ case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
+ case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case EXTERNAL_##TYPE##_ELEMENTS: \
case TYPE##_ELEMENTS:
@@ -12300,30 +12298,6 @@ void JSObject::EnsureCanContainElements(Handle<JSObject> object,
}
-bool JSObject::HasFastArgumentsElements() {
- Heap* heap = GetHeap();
- if (!elements()->IsFixedArray()) return false;
- FixedArray* elements = FixedArray::cast(this->elements());
- if (elements->map() != heap->sloppy_arguments_elements_map()) {
- return false;
- }
- FixedArray* arguments = FixedArray::cast(elements->get(1));
- return !arguments->IsDictionary();
-}
-
-
-bool JSObject::HasDictionaryArgumentsElements() {
- Heap* heap = GetHeap();
- if (!elements()->IsFixedArray()) return false;
- FixedArray* elements = FixedArray::cast(this->elements());
- if (elements->map() != heap->sloppy_arguments_elements_map()) {
- return false;
- }
- FixedArray* arguments = FixedArray::cast(elements->get(1));
- return arguments->IsDictionary();
-}
-
-
ElementsAccessor* JSObject::GetElementsAccessor() {
return ElementsAccessor::ForKind(GetElementsKind());
}
@@ -12390,7 +12364,9 @@ bool JSObject::WouldConvertToSlowElements(uint32_t index) {
static ElementsKind BestFittingFastElementsKind(JSObject* object) {
- if (object->HasSloppyArgumentsElements()) return SLOPPY_ARGUMENTS_ELEMENTS;
+ if (object->HasSloppyArgumentsElements()) {
+ return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
+ }
DCHECK(object->HasDictionaryElements());
SeededNumberDictionary* dictionary = object->element_dictionary();
ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
@@ -12457,49 +12433,34 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
ElementsKind kind = object->GetElementsKind();
FixedArrayBase* elements = object->elements();
+ ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
if (IsSloppyArgumentsElements(kind)) {
elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
+ dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
}
if (attributes != NONE) {
- kind = DICTIONARY_ELEMENTS;
+ kind = dictionary_kind;
} else if (elements->IsSeededNumberDictionary()) {
kind = ShouldConvertToFastElements(*object,
SeededNumberDictionary::cast(elements),
index, &new_capacity)
? BestFittingFastElementsKind(*object)
- : DICTIONARY_ELEMENTS; // Overwrite in case of arguments.
+ : dictionary_kind; // Overwrite in case of arguments.
} else if (ShouldConvertToSlowElements(
*object, static_cast<uint32_t>(elements->length()), index,
&new_capacity)) {
- kind = DICTIONARY_ELEMENTS;
+ kind = dictionary_kind;
}
- if (kind == DICTIONARY_ELEMENTS && object->HasSloppyArgumentsElements()) {
- // TODO(verwaest): Distinguish fast/slow sloppy elements in ElementsKind.
- Handle<SeededNumberDictionary> dictionary =
- elements->IsSeededNumberDictionary()
- ? handle(SeededNumberDictionary::cast(elements))
- : NormalizeElements(object);
- PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
- Handle<SeededNumberDictionary> new_dictionary =
- SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
- details);
- if (attributes != NONE) new_dictionary->set_requires_slow_elements();
- if (*dictionary != *new_dictionary) {
- FixedArray::cast(object->elements())->set(1, *new_dictionary);
- }
- } else {
- ElementsKind to = value->OptimalElementsKind();
- if (IsHoleyElementsKind(kind) || !object->IsJSArray() ||
- index > old_length) {
- to = GetHoleyElementsKind(to);
- kind = GetHoleyElementsKind(kind);
- }
- to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind;
- ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
- accessor->Add(object, index, value, attributes, new_capacity);
+ ElementsKind to = value->OptimalElementsKind();
+ if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
+ to = GetHoleyElementsKind(to);
+ kind = GetHoleyElementsKind(kind);
}
+ to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind;
+ ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
+ accessor->Add(object, index, value, attributes, new_capacity);
uint32_t new_length = old_length;
Handle<Object> new_length_handle;
@@ -12758,7 +12719,8 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
FixedArray* backing_store = NULL;
switch (GetElementsKind()) {
- case SLOPPY_ARGUMENTS_ELEMENTS:
+ 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);
@@ -13255,7 +13217,8 @@ int JSObject::GetOwnElementKeys(FixedArray* storage,
counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
break;
}
- case SLOPPY_ARGUMENTS_ELEMENTS: {
+ case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
+ case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
FixedArray* parameter_map = FixedArray::cast(elements());
int mapped_length = parameter_map->length() - 2;
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698