[elements] Introduce SloppyArgumentsElements helper
This CL introduces SloppyArgumentsElements to encapsulate all the constants for SLOW_ and FAST_SLOPPY_ARGUMENTS_KINDS. This will serve as a better documentation and reduces the use of undocumented constants. Change-Id: I7a5b4e79f02573161d8a83aaf6f69fc490883aa5 Reviewed-on: https://chromium-review.googlesource.com/467666 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#44433}
This commit is contained in:
parent
b5b87aecf1
commit
4817c544ab
@ -7167,7 +7167,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
|
||||
elements_kind != GetInitialFastElementsKind()) {
|
||||
possible_transitioned_maps.Add(map);
|
||||
}
|
||||
if (IsSloppyArgumentsElements(elements_kind)) {
|
||||
if (IsSloppyArgumentsElementsKind(elements_kind)) {
|
||||
HInstruction* result =
|
||||
BuildKeyedGeneric(access_type, expr, slot, object, key, val);
|
||||
*has_side_effects = result->HasObservableSideEffects();
|
||||
|
@ -86,8 +86,7 @@ inline bool IsDictionaryElementsKind(ElementsKind kind) {
|
||||
return kind == DICTIONARY_ELEMENTS;
|
||||
}
|
||||
|
||||
|
||||
inline bool IsSloppyArgumentsElements(ElementsKind kind) {
|
||||
inline bool IsSloppyArgumentsElementsKind(ElementsKind kind) {
|
||||
return kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS ||
|
||||
kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
}
|
||||
|
269
src/elements.cc
269
src/elements.cc
@ -1152,8 +1152,8 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
}
|
||||
|
||||
uint32_t nof_indices = 0;
|
||||
bool needs_sorting =
|
||||
IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind());
|
||||
bool needs_sorting = IsDictionaryElementsKind(kind()) ||
|
||||
IsSloppyArgumentsElementsKind(kind());
|
||||
combined_keys = Subclass::DirectCollectElementIndicesImpl(
|
||||
isolate, object, backing_store,
|
||||
needs_sorting ? GetKeysConversion::kKeepNumbers : convert, filter,
|
||||
@ -1178,7 +1178,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
|
||||
// For holey elements and arguments we might have to shrink the collected
|
||||
// keys since the estimates might be off.
|
||||
if (IsHoleyElementsKind(kind()) || IsSloppyArgumentsElements(kind())) {
|
||||
if (IsHoleyElementsKind(kind()) || IsSloppyArgumentsElementsKind(kind())) {
|
||||
// Shrink combined_keys to the final size.
|
||||
int final_size = nof_indices + nof_property_keys;
|
||||
DCHECK_LE(final_size, combined_keys->length());
|
||||
@ -1840,7 +1840,7 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
|
||||
// Dynamically ask for the elements kind here since we manually redirect
|
||||
// the operations for argument backing stores.
|
||||
if (obj->GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
|
||||
FixedArray::cast(obj->elements())->set(1, empty);
|
||||
SloppyArgumentsElements::cast(obj->elements())->set_arguments(empty);
|
||||
} else {
|
||||
obj->set_elements(empty);
|
||||
}
|
||||
@ -3098,31 +3098,31 @@ class SloppyArgumentsElementsAccessor
|
||||
USE(KindTraits::Kind);
|
||||
}
|
||||
|
||||
static void ConvertArgumentsStoreResult(
|
||||
Isolate* isolate, Handle<SloppyArgumentsElements> elements,
|
||||
Handle<Object> result) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase* parameters,
|
||||
uint32_t entry) {
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(parameters), isolate);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
Handle<SloppyArgumentsElements> elements(
|
||||
SloppyArgumentsElements::cast(parameters), isolate);
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry < length) {
|
||||
// Read context mapped entry.
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object* probe = parameter_map->get(entry + 2);
|
||||
Context* context = Context::cast(parameter_map->get(0));
|
||||
Object* probe = elements->get_mapped_entry(entry);
|
||||
DCHECK(!probe->IsTheHole(isolate));
|
||||
Context* context = elements->context();
|
||||
int context_entry = Smi::cast(probe)->value();
|
||||
DCHECK(!context->get(context_entry)->IsTheHole(isolate));
|
||||
return handle(context->get(context_entry), isolate);
|
||||
} else {
|
||||
// Object is not mapped, defer to the arguments.
|
||||
// Entry is not context mapped, defer to the arguments.
|
||||
Handle<Object> result = ArgumentsAccessor::GetImpl(
|
||||
isolate, FixedArray::cast(parameter_map->get(1)), entry - length);
|
||||
// Elements of the arguments object in slow mode might be slow aliases.
|
||||
if (result->IsAliasedArgumentsEntry()) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
AliasedArgumentsEntry* alias = AliasedArgumentsEntry::cast(*result);
|
||||
Context* context = Context::cast(parameter_map->get(0));
|
||||
int context_entry = alias->aliased_context_slot();
|
||||
DCHECK(!context->get(context_entry)->IsTheHole(isolate));
|
||||
return handle(context->get(context_entry), isolate);
|
||||
}
|
||||
return result;
|
||||
isolate, elements->arguments(), entry - length);
|
||||
return Subclass::ConvertArgumentsStoreResult(isolate, elements, result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3143,20 +3143,24 @@ class SloppyArgumentsElementsAccessor
|
||||
|
||||
static inline void SetImpl(FixedArrayBase* store, uint32_t entry,
|
||||
Object* value) {
|
||||
FixedArray* parameter_map = FixedArray::cast(store);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
SloppyArgumentsElements* elements = SloppyArgumentsElements::cast(store);
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry < length) {
|
||||
Object* probe = parameter_map->get(entry + 2);
|
||||
Context* context = Context::cast(parameter_map->get(0));
|
||||
// Store context mapped entry.
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object* probe = elements->get_mapped_entry(entry);
|
||||
DCHECK(!probe->IsTheHole(store->GetIsolate()));
|
||||
Context* context = elements->context();
|
||||
int context_entry = Smi::cast(probe)->value();
|
||||
DCHECK(!context->get(context_entry)->IsTheHole(store->GetIsolate()));
|
||||
context->set(context_entry, value);
|
||||
} else {
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
// Entry is not context mapped defer to arguments.
|
||||
FixedArray* arguments = elements->arguments();
|
||||
Object* current = ArgumentsAccessor::GetRaw(arguments, entry - length);
|
||||
if (current->IsAliasedArgumentsEntry()) {
|
||||
AliasedArgumentsEntry* alias = AliasedArgumentsEntry::cast(current);
|
||||
Context* context = Context::cast(parameter_map->get(0));
|
||||
Context* context = elements->context();
|
||||
int context_entry = alias->aliased_context_slot();
|
||||
DCHECK(!context->get(context_entry)->IsTheHole(store->GetIsolate()));
|
||||
context->set(context_entry, value);
|
||||
@ -3173,30 +3177,32 @@ class SloppyArgumentsElementsAccessor
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static uint32_t GetCapacityImpl(JSObject* holder,
|
||||
FixedArrayBase* backing_store) {
|
||||
FixedArray* parameter_map = FixedArray::cast(backing_store);
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
return parameter_map->length() - 2 +
|
||||
static uint32_t GetCapacityImpl(JSObject* holder, FixedArrayBase* store) {
|
||||
SloppyArgumentsElements* elements = SloppyArgumentsElements::cast(store);
|
||||
FixedArray* arguments = elements->arguments();
|
||||
return elements->parameter_map_length() +
|
||||
ArgumentsAccessor::GetCapacityImpl(holder, arguments);
|
||||
}
|
||||
|
||||
static uint32_t GetMaxNumberOfEntries(JSObject* holder,
|
||||
FixedArrayBase* backing_store) {
|
||||
FixedArray* parameter_map = FixedArray::cast(backing_store);
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
return parameter_map->length() - 2 +
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(backing_store);
|
||||
FixedArrayBase* arguments = elements->arguments();
|
||||
return elements->parameter_map_length() +
|
||||
ArgumentsAccessor::GetMaxNumberOfEntries(holder, arguments);
|
||||
}
|
||||
|
||||
static uint32_t NumberOfElementsImpl(JSObject* receiver,
|
||||
FixedArrayBase* backing_store) {
|
||||
FixedArray* parameter_map = FixedArray::cast(backing_store);
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
Isolate* isolate = receiver->GetIsolate();
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(backing_store);
|
||||
FixedArrayBase* arguments = elements->arguments();
|
||||
uint32_t nof_elements = 0;
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
for (uint32_t entry = 0; entry < length; entry++) {
|
||||
if (HasParameterMapArg(parameter_map, entry)) nof_elements++;
|
||||
if (HasParameterMapArg(isolate, elements, entry)) nof_elements++;
|
||||
}
|
||||
return nof_elements +
|
||||
ArgumentsAccessor::NumberOfElementsImpl(receiver, arguments);
|
||||
@ -3217,71 +3223,75 @@ class SloppyArgumentsElementsAccessor
|
||||
|
||||
static bool HasEntryImpl(Isolate* isolate, FixedArrayBase* parameters,
|
||||
uint32_t entry) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(parameters);
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry < length) {
|
||||
return HasParameterMapArg(parameter_map, entry);
|
||||
return HasParameterMapArg(isolate, elements, entry);
|
||||
}
|
||||
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
FixedArrayBase* arguments = elements->arguments();
|
||||
return ArgumentsAccessor::HasEntryImpl(isolate, arguments, entry - length);
|
||||
}
|
||||
|
||||
static bool HasAccessorsImpl(JSObject* holder,
|
||||
FixedArrayBase* backing_store) {
|
||||
FixedArray* parameter_map = FixedArray::cast(backing_store);
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(backing_store);
|
||||
FixedArray* arguments = elements->arguments();
|
||||
return ArgumentsAccessor::HasAccessorsImpl(holder, arguments);
|
||||
}
|
||||
|
||||
static uint32_t GetIndexForEntryImpl(FixedArrayBase* parameters,
|
||||
uint32_t entry) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(parameters);
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry < length) return entry;
|
||||
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
FixedArray* arguments = elements->arguments();
|
||||
return ArgumentsAccessor::GetIndexForEntryImpl(arguments, entry - length);
|
||||
}
|
||||
|
||||
static uint32_t GetEntryForIndexImpl(Isolate* isolate, JSObject* holder,
|
||||
FixedArrayBase* parameters,
|
||||
uint32_t index, PropertyFilter filter) {
|
||||
FixedArray* parameter_map = FixedArray::cast(parameters);
|
||||
if (HasParameterMapArg(parameter_map, index)) return index;
|
||||
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(parameters);
|
||||
if (HasParameterMapArg(isolate, elements, index)) return index;
|
||||
FixedArray* arguments = elements->arguments();
|
||||
uint32_t entry = ArgumentsAccessor::GetEntryForIndexImpl(
|
||||
isolate, holder, arguments, index, filter);
|
||||
if (entry == kMaxUInt32) return kMaxUInt32;
|
||||
return (parameter_map->length() - 2) + entry;
|
||||
return elements->parameter_map_length() + entry;
|
||||
}
|
||||
|
||||
static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) {
|
||||
FixedArray* parameter_map = FixedArray::cast(holder->elements());
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(holder->elements());
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry < length) {
|
||||
return PropertyDetails(kData, NONE, 0, PropertyCellType::kNoCell);
|
||||
}
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
FixedArray* arguments = elements->arguments();
|
||||
return ArgumentsAccessor::GetDetailsImpl(arguments, entry - length);
|
||||
}
|
||||
|
||||
static bool HasParameterMapArg(FixedArray* parameter_map, uint32_t index) {
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
static bool HasParameterMapArg(Isolate* isolate,
|
||||
SloppyArgumentsElements* elements,
|
||||
uint32_t index) {
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (index >= length) return false;
|
||||
return !parameter_map->get(index + 2)->IsTheHole(
|
||||
parameter_map->GetIsolate());
|
||||
return !elements->get_mapped_entry(index)->IsTheHole(isolate);
|
||||
}
|
||||
|
||||
static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
|
||||
FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
||||
uint32_t length = static_cast<uint32_t>(parameter_map->length()) - 2;
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(obj->elements());
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry < length) {
|
||||
// TODO(kmillikin): We could check if this was the last aliased
|
||||
// parameter, and revert to normal elements in that case. That
|
||||
// would enable GC of the context.
|
||||
parameter_map->set_the_hole(entry + 2);
|
||||
elements->set_mapped_entry(entry, obj->GetHeap()->the_hole_value());
|
||||
} else {
|
||||
Subclass::DeleteFromArguments(obj, entry - length);
|
||||
}
|
||||
@ -3308,11 +3318,12 @@ class SloppyArgumentsElementsAccessor
|
||||
Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
|
||||
PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
|
||||
uint32_t insertion_index = 0) {
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(*backing_store), isolate);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
Handle<SloppyArgumentsElements> elements =
|
||||
Handle<SloppyArgumentsElements>::cast(backing_store);
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
if (parameter_map->get(i + 2)->IsTheHole(isolate)) continue;
|
||||
if (elements->get_mapped_entry(i)->IsTheHole(isolate)) continue;
|
||||
if (convert == GetKeysConversion::kConvertToString) {
|
||||
Handle<String> index_string = isolate->factory()->Uint32ToString(i);
|
||||
list->set(insertion_index, *index_string);
|
||||
@ -3322,7 +3333,7 @@ class SloppyArgumentsElementsAccessor
|
||||
insertion_index++;
|
||||
}
|
||||
|
||||
Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1)));
|
||||
Handle<FixedArray> store(elements->arguments(), isolate);
|
||||
return ArgumentsAccessor::DirectCollectElementIndicesImpl(
|
||||
isolate, object, store, convert, filter, list, nof_indices,
|
||||
insertion_index);
|
||||
@ -3334,20 +3345,19 @@ class SloppyArgumentsElementsAccessor
|
||||
uint32_t start_from, uint32_t length) {
|
||||
DCHECK(JSObject::PrototypeHasNoElements(isolate, *object));
|
||||
Handle<Map> original_map = handle(object->map(), isolate);
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()),
|
||||
isolate);
|
||||
Handle<SloppyArgumentsElements> elements(
|
||||
SloppyArgumentsElements::cast(object->elements()), isolate);
|
||||
bool search_for_hole = value->IsUndefined(isolate);
|
||||
|
||||
for (uint32_t k = start_from; k < length; ++k) {
|
||||
uint32_t entry = GetEntryForIndexImpl(isolate, *object, *parameter_map, k,
|
||||
ALL_PROPERTIES);
|
||||
uint32_t entry =
|
||||
GetEntryForIndexImpl(isolate, *object, *elements, k, ALL_PROPERTIES);
|
||||
if (entry == kMaxUInt32) {
|
||||
if (search_for_hole) return Just(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle<Object> element_k =
|
||||
Subclass::GetImpl(isolate, *parameter_map, entry);
|
||||
Handle<Object> element_k = Subclass::GetImpl(isolate, *elements, entry);
|
||||
|
||||
if (element_k->IsAccessorPair()) {
|
||||
LookupIterator it(isolate, object, k, LookupIterator::OWN);
|
||||
@ -3376,18 +3386,17 @@ class SloppyArgumentsElementsAccessor
|
||||
uint32_t start_from, uint32_t length) {
|
||||
DCHECK(JSObject::PrototypeHasNoElements(isolate, *object));
|
||||
Handle<Map> original_map = handle(object->map(), isolate);
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()),
|
||||
isolate);
|
||||
Handle<SloppyArgumentsElements> elements(
|
||||
SloppyArgumentsElements::cast(object->elements()), isolate);
|
||||
|
||||
for (uint32_t k = start_from; k < length; ++k) {
|
||||
uint32_t entry = GetEntryForIndexImpl(isolate, *object, *parameter_map, k,
|
||||
ALL_PROPERTIES);
|
||||
uint32_t entry =
|
||||
GetEntryForIndexImpl(isolate, *object, *elements, k, ALL_PROPERTIES);
|
||||
if (entry == kMaxUInt32) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle<Object> element_k =
|
||||
Subclass::GetImpl(isolate, *parameter_map, entry);
|
||||
Handle<Object> element_k = Subclass::GetImpl(isolate, *elements, entry);
|
||||
|
||||
if (element_k->IsAccessorPair()) {
|
||||
LookupIterator it(isolate, object, k, LookupIterator::OWN);
|
||||
@ -3424,10 +3433,26 @@ class SlowSloppyArgumentsElementsAccessor
|
||||
SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
||||
ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
||||
|
||||
static Handle<Object> ConvertArgumentsStoreResult(
|
||||
Isolate* isolate, Handle<SloppyArgumentsElements> elements,
|
||||
Handle<Object> result) {
|
||||
// Elements of the arguments object in slow mode might be slow aliases.
|
||||
if (result->IsAliasedArgumentsEntry()) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
AliasedArgumentsEntry* alias = AliasedArgumentsEntry::cast(*result);
|
||||
Context* context = elements->context();
|
||||
int context_entry = alias->aliased_context_slot();
|
||||
DCHECK(!context->get(context_entry)->IsTheHole(isolate));
|
||||
return handle(context->get(context_entry), isolate);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static void DeleteFromArguments(Handle<JSObject> obj, uint32_t entry) {
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements()));
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
Handle<SloppyArgumentsElements> elements(
|
||||
SloppyArgumentsElements::cast(obj->elements()), isolate);
|
||||
Handle<SeededNumberDictionary> dict(
|
||||
SeededNumberDictionary::cast(parameter_map->get(1)));
|
||||
SeededNumberDictionary::cast(elements->arguments()), isolate);
|
||||
// TODO(verwaest): Remove reliance on index in Shrink.
|
||||
uint32_t index = GetIndexForEntryImpl(*dict, entry);
|
||||
Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry);
|
||||
@ -3435,18 +3460,20 @@ class SlowSloppyArgumentsElementsAccessor
|
||||
DCHECK(result->IsTrue(dict->GetIsolate()));
|
||||
Handle<FixedArray> new_elements =
|
||||
SeededNumberDictionary::Shrink(dict, index);
|
||||
parameter_map->set(1, *new_elements);
|
||||
elements->set_arguments(*new_elements);
|
||||
}
|
||||
|
||||
static void AddImpl(Handle<JSObject> object, uint32_t index,
|
||||
Handle<Object> value, PropertyAttributes attributes,
|
||||
uint32_t new_capacity) {
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
Handle<FixedArrayBase> old_elements(
|
||||
FixedArrayBase::cast(parameter_map->get(1)));
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
Handle<SloppyArgumentsElements> elements(
|
||||
SloppyArgumentsElements::cast(object->elements()), isolate);
|
||||
Handle<FixedArrayBase> old_arguments(
|
||||
FixedArrayBase::cast(elements->arguments()), isolate);
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
old_elements->IsSeededNumberDictionary()
|
||||
? Handle<SeededNumberDictionary>::cast(old_elements)
|
||||
old_arguments->IsSeededNumberDictionary()
|
||||
? Handle<SeededNumberDictionary>::cast(old_arguments)
|
||||
: JSObject::NormalizeElements(object);
|
||||
PropertyDetails details(kData, attributes, 0, PropertyCellType::kNoCell);
|
||||
Handle<SeededNumberDictionary> new_dictionary =
|
||||
@ -3454,7 +3481,7 @@ class SlowSloppyArgumentsElementsAccessor
|
||||
details, object);
|
||||
if (attributes != NONE) object->RequireSlowElements(*new_dictionary);
|
||||
if (*dictionary != *new_dictionary) {
|
||||
FixedArray::cast(object->elements())->set(1, *new_dictionary);
|
||||
elements->set_arguments(*new_dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3462,19 +3489,20 @@ class SlowSloppyArgumentsElementsAccessor
|
||||
Handle<FixedArrayBase> store, uint32_t entry,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes) {
|
||||
Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store);
|
||||
uint32_t length = parameter_map->length() - 2;
|
||||
Isolate* isolate = store->GetIsolate();
|
||||
Handle<SloppyArgumentsElements> elements =
|
||||
Handle<SloppyArgumentsElements>::cast(store);
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry < length) {
|
||||
Object* probe = parameter_map->get(entry + 2);
|
||||
Object* probe = elements->get_mapped_entry(entry);
|
||||
DCHECK(!probe->IsTheHole(isolate));
|
||||
Context* context = Context::cast(parameter_map->get(0));
|
||||
Context* context = elements->context();
|
||||
int context_entry = Smi::cast(probe)->value();
|
||||
DCHECK(!context->get(context_entry)->IsTheHole(isolate));
|
||||
context->set(context_entry, *value);
|
||||
|
||||
// Redefining attributes of an aliased element destroys fast aliasing.
|
||||
parameter_map->set_the_hole(isolate, entry + 2);
|
||||
elements->set_mapped_entry(entry, isolate->heap()->the_hole_value());
|
||||
// For elements that are still writable we re-establish slow aliasing.
|
||||
if ((attributes & READ_ONLY) == 0) {
|
||||
value = isolate->factory()->NewAliasedArgumentsEntry(context_entry);
|
||||
@ -3482,17 +3510,16 @@ class SlowSloppyArgumentsElementsAccessor
|
||||
|
||||
PropertyDetails details(kData, attributes, 0, PropertyCellType::kNoCell);
|
||||
Handle<SeededNumberDictionary> arguments(
|
||||
SeededNumberDictionary::cast(parameter_map->get(1)), isolate);
|
||||
SeededNumberDictionary::cast(elements->arguments()), isolate);
|
||||
arguments = SeededNumberDictionary::AddNumberEntry(
|
||||
arguments, entry, value, details, object);
|
||||
// If the attributes were NONE, we would have called set rather than
|
||||
// reconfigure.
|
||||
DCHECK_NE(NONE, attributes);
|
||||
object->RequireSlowElements(*arguments);
|
||||
parameter_map->set(1, *arguments);
|
||||
elements->set_arguments(*arguments);
|
||||
} else {
|
||||
Handle<FixedArrayBase> arguments(
|
||||
FixedArrayBase::cast(parameter_map->get(1)), isolate);
|
||||
Handle<FixedArrayBase> arguments(elements->arguments(), isolate);
|
||||
DictionaryElementsAccessor::ReconfigureImpl(
|
||||
object, arguments, entry - length, value, attributes);
|
||||
}
|
||||
@ -3511,10 +3538,17 @@ class FastSloppyArgumentsElementsAccessor
|
||||
FastHoleyObjectElementsAccessor,
|
||||
ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
||||
|
||||
static Handle<Object> ConvertArgumentsStoreResult(
|
||||
Isolate* isolate, Handle<SloppyArgumentsElements> paramtere_map,
|
||||
Handle<Object> result) {
|
||||
DCHECK(!result->IsAliasedArgumentsEntry());
|
||||
return result;
|
||||
}
|
||||
|
||||
static Handle<FixedArray> GetArguments(Isolate* isolate,
|
||||
FixedArrayBase* backing_store) {
|
||||
FixedArray* parameter_map = FixedArray::cast(backing_store);
|
||||
return Handle<FixedArray>(FixedArray::cast(parameter_map->get(1)), isolate);
|
||||
FixedArrayBase* store) {
|
||||
SloppyArgumentsElements* elements = SloppyArgumentsElements::cast(store);
|
||||
return Handle<FixedArray>(elements->arguments(), isolate);
|
||||
}
|
||||
|
||||
static Handle<JSObject> SliceImpl(Handle<JSObject> receiver, uint32_t start,
|
||||
@ -3557,14 +3591,15 @@ class FastSloppyArgumentsElementsAccessor
|
||||
Handle<Object> value, PropertyAttributes attributes,
|
||||
uint32_t new_capacity) {
|
||||
DCHECK_EQ(NONE, attributes);
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
Handle<FixedArrayBase> old_elements(
|
||||
FixedArrayBase::cast(parameter_map->get(1)));
|
||||
if (old_elements->IsSeededNumberDictionary() ||
|
||||
static_cast<uint32_t>(old_elements->length()) < new_capacity) {
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
Handle<SloppyArgumentsElements> elements(
|
||||
SloppyArgumentsElements::cast(object->elements()), isolate);
|
||||
Handle<FixedArray> old_arguments(elements->arguments(), isolate);
|
||||
if (old_arguments->IsSeededNumberDictionary() ||
|
||||
static_cast<uint32_t>(old_arguments->length()) < new_capacity) {
|
||||
GrowCapacityAndConvertImpl(object, new_capacity);
|
||||
}
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
FixedArray* arguments = elements->arguments();
|
||||
// For fast holey objects, the entry equals the index. The code above made
|
||||
// sure that there's enough space to store the value. We cannot convert
|
||||
// index to entry explicitly since the slot still contains the hole, so the
|
||||
@ -3579,8 +3614,9 @@ class FastSloppyArgumentsElementsAccessor
|
||||
PropertyAttributes attributes) {
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
JSObject::NormalizeElements(object);
|
||||
FixedArray::cast(*store)->set(1, *dictionary);
|
||||
uint32_t length = static_cast<uint32_t>(store->length()) - 2;
|
||||
SloppyArgumentsElements* elements = SloppyArgumentsElements::cast(*store);
|
||||
elements->set_arguments(*dictionary);
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry >= length) {
|
||||
entry = dictionary->FindEntry(entry - length) + length;
|
||||
}
|
||||
@ -3605,19 +3641,22 @@ class FastSloppyArgumentsElementsAccessor
|
||||
|
||||
static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
|
||||
uint32_t capacity) {
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1)));
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
Handle<SloppyArgumentsElements> elements(
|
||||
SloppyArgumentsElements::cast(object->elements()), isolate);
|
||||
Handle<FixedArray> old_arguments(FixedArray::cast(elements->arguments()),
|
||||
isolate);
|
||||
ElementsKind from_kind = object->GetElementsKind();
|
||||
// This method should only be called if there's a reason to update the
|
||||
// elements.
|
||||
DCHECK(from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS ||
|
||||
static_cast<uint32_t>(old_elements->length()) < capacity);
|
||||
Handle<FixedArrayBase> elements =
|
||||
ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
|
||||
static_cast<uint32_t>(old_arguments->length()) < capacity);
|
||||
Handle<FixedArrayBase> arguments =
|
||||
ConvertElementsWithCapacity(object, old_arguments, from_kind, capacity);
|
||||
Handle<Map> new_map = JSObject::GetElementsTransitionMap(
|
||||
object, FAST_SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
JSObject::MigrateToMap(object, new_map);
|
||||
parameter_map->set(1, *elements);
|
||||
elements->set_arguments(FixedArray::cast(*arguments));
|
||||
JSObject::ValidateElements(object);
|
||||
}
|
||||
};
|
||||
|
@ -172,7 +172,7 @@ Handle<Object> ElementHandlerCompiler::GetKeyedLoadHandler(
|
||||
}
|
||||
|
||||
ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
if (IsSloppyArgumentsElements(elements_kind)) {
|
||||
if (IsSloppyArgumentsElementsKind(elements_kind)) {
|
||||
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
|
||||
return KeyedLoadSloppyArgumentsStub(isolate).GetCode();
|
||||
}
|
||||
|
@ -200,6 +200,8 @@ bool HeapObject::IsFixedArray() const {
|
||||
instance_type == TRANSITION_ARRAY_TYPE;
|
||||
}
|
||||
|
||||
bool HeapObject::IsSloppyArgumentsElements() const { return IsFixedArray(); }
|
||||
|
||||
bool HeapObject::IsJSGeneratorObject() const {
|
||||
return map()->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
|
||||
IsJSAsyncGeneratorObject();
|
||||
@ -697,6 +699,7 @@ CAST_ACCESSOR(UnseededNumberDictionary)
|
||||
CAST_ACCESSOR(WeakCell)
|
||||
CAST_ACCESSOR(WeakFixedArray)
|
||||
CAST_ACCESSOR(WeakHashTable)
|
||||
CAST_ACCESSOR(SloppyArgumentsElements)
|
||||
|
||||
#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
|
||||
STRUCT_LIST(MAKE_STRUCT_CAST)
|
||||
@ -1581,6 +1584,29 @@ FixedArrayBase* JSObject::elements() const {
|
||||
return static_cast<FixedArrayBase*>(array);
|
||||
}
|
||||
|
||||
Context* SloppyArgumentsElements::context() {
|
||||
return Context::cast(get(kContextIndex));
|
||||
}
|
||||
|
||||
FixedArray* SloppyArgumentsElements::arguments() {
|
||||
return FixedArray::cast(get(kArgumentsIndex));
|
||||
}
|
||||
|
||||
void SloppyArgumentsElements::set_arguments(FixedArray* arguments) {
|
||||
set(kArgumentsIndex, arguments);
|
||||
}
|
||||
|
||||
uint32_t SloppyArgumentsElements::parameter_map_length() {
|
||||
return length() - kParameterMapStart;
|
||||
}
|
||||
|
||||
Object* SloppyArgumentsElements::get_mapped_entry(uint32_t entry) {
|
||||
return get(entry + kParameterMapStart);
|
||||
}
|
||||
|
||||
void SloppyArgumentsElements::set_mapped_entry(uint32_t entry, Object* object) {
|
||||
set(entry + kParameterMapStart, object);
|
||||
}
|
||||
|
||||
void AllocationSite::Initialize() {
|
||||
set_transition_info(Smi::kZero);
|
||||
@ -4553,7 +4579,7 @@ bool Map::has_fast_double_elements() {
|
||||
bool Map::has_fast_elements() { return IsFastElementsKind(elements_kind()); }
|
||||
|
||||
bool Map::has_sloppy_arguments_elements() {
|
||||
return IsSloppyArgumentsElements(elements_kind());
|
||||
return IsSloppyArgumentsElementsKind(elements_kind());
|
||||
}
|
||||
|
||||
bool Map::has_fast_sloppy_arguments_elements() {
|
||||
@ -7031,7 +7057,7 @@ ElementsKind JSObject::GetElementsKind() {
|
||||
} else {
|
||||
DCHECK(kind > DICTIONARY_ELEMENTS);
|
||||
}
|
||||
DCHECK(!IsSloppyArgumentsElements(kind) ||
|
||||
DCHECK(!IsSloppyArgumentsElementsKind(kind) ||
|
||||
(elements()->IsFixedArray() && elements()->length() >= 2));
|
||||
}
|
||||
#endif
|
||||
@ -7085,7 +7111,7 @@ bool JSObject::HasSlowArgumentsElements() {
|
||||
|
||||
|
||||
bool JSObject::HasSloppyArgumentsElements() {
|
||||
return IsSloppyArgumentsElements(GetElementsKind());
|
||||
return IsSloppyArgumentsElementsKind(GetElementsKind());
|
||||
}
|
||||
|
||||
bool JSObject::HasStringWrapperElements() {
|
||||
|
@ -383,12 +383,40 @@ void PrintFixedArrayElements(std::ostream& os, FixedArray* array) {
|
||||
}
|
||||
}
|
||||
|
||||
void PrintSloppyArgumentElements(std::ostream& os, ElementsKind kind,
|
||||
SloppyArgumentsElements* elements) {
|
||||
FixedArray* arguments_store = elements->arguments();
|
||||
os << "\n 0: context= " << Brief(elements->context())
|
||||
<< "\n 1: arguments_store= " << Brief(arguments_store)
|
||||
<< "\n parameter to context slot map:";
|
||||
for (uint32_t i = 0; i < elements->parameter_map_length(); i++) {
|
||||
uint32_t raw_index = i + SloppyArgumentsElements::kParameterMapStart;
|
||||
os << "\n " << raw_index << ": param(" << i
|
||||
<< ")= " << Brief(elements->get_mapped_entry(i));
|
||||
}
|
||||
if (arguments_store->length() == 0) return;
|
||||
os << "\n }"
|
||||
<< "\n - arguments_store = " << Brief(arguments_store) << " "
|
||||
<< ElementsKindToString(arguments_store->map()->elements_kind()) << " {";
|
||||
if (kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
|
||||
PrintFixedArrayElements(os, arguments_store);
|
||||
} else {
|
||||
DCHECK_EQ(kind, SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
|
||||
SeededNumberDictionary::cast(arguments_store)->Print(os);
|
||||
}
|
||||
os << "\n }";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool JSObject::PrintElements(std::ostream& os) { // NOLINT
|
||||
void JSObject::PrintElements(std::ostream& os) { // NOLINT
|
||||
// Don't call GetElementsKind, its validation code can cause the printer to
|
||||
// fail when debugging.
|
||||
if (elements()->length() == 0) return false;
|
||||
os << " - elements= " << Brief(elements()) << " {";
|
||||
if (elements()->length() == 0) {
|
||||
os << " }\n";
|
||||
return;
|
||||
}
|
||||
switch (map()->elements_kind()) {
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case FAST_SMI_ELEMENTS:
|
||||
@ -417,20 +445,14 @@ bool JSObject::PrintElements(std::ostream& os) { // NOLINT
|
||||
SeededNumberDictionary::cast(elements())->Print(os);
|
||||
break;
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
FixedArray* p = FixedArray::cast(elements());
|
||||
os << "\n parameter map:";
|
||||
for (int i = 2; i < p->length(); i++) {
|
||||
os << " " << (i - 2) << ":" << Brief(p->get(i));
|
||||
}
|
||||
os << "\n context: " << Brief(p->get(0))
|
||||
<< "\n arguments: " << Brief(p->get(1));
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
PrintSloppyArgumentElements(os, map()->elements_kind(),
|
||||
SloppyArgumentsElements::cast(elements()));
|
||||
break;
|
||||
}
|
||||
case NO_ELEMENTS:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
os << "\n }\n";
|
||||
}
|
||||
|
||||
|
||||
@ -465,9 +487,7 @@ static void JSObjectPrintBody(std::ostream& os, JSObject* obj, // NOLINT
|
||||
if (obj->PrintProperties(os)) os << "\n ";
|
||||
os << "}\n";
|
||||
if (print_elements && obj->elements()->length() > 0) {
|
||||
os << " - elements = " << Brief(obj->elements()) << " {";
|
||||
if (obj->PrintElements(os)) os << "\n ";
|
||||
os << "}\n";
|
||||
obj->PrintElements(os);
|
||||
}
|
||||
int embedder_fields = obj->GetEmbedderFieldCount();
|
||||
if (embedder_fields > 0) {
|
||||
|
@ -7300,15 +7300,15 @@ bool JSObject::ReferencesObject(Object* obj) {
|
||||
}
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
FixedArray* parameter_map = FixedArray::cast(elements());
|
||||
SloppyArgumentsElements* elements =
|
||||
SloppyArgumentsElements::cast(this->elements());
|
||||
// Check the mapped parameters.
|
||||
int length = parameter_map->length();
|
||||
for (int i = 2; i < length; ++i) {
|
||||
Object* value = parameter_map->get(i);
|
||||
for (uint32_t i = 0; i < elements->parameter_map_length(); ++i) {
|
||||
Object* value = elements->get_mapped_entry(i);
|
||||
if (!value->IsTheHole(heap->isolate()) && value == obj) return true;
|
||||
}
|
||||
// Check the arguments.
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
FixedArray* arguments = elements->arguments();
|
||||
kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
|
||||
FAST_HOLEY_ELEMENTS;
|
||||
if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
|
||||
@ -15590,7 +15590,7 @@ Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
|
||||
ElementsKind kind = object->GetElementsKind();
|
||||
FixedArrayBase* elements = object->elements();
|
||||
ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
|
||||
if (IsSloppyArgumentsElements(kind)) {
|
||||
if (IsSloppyArgumentsElementsKind(kind)) {
|
||||
elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
|
||||
dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
|
||||
} else if (IsStringWrapperElementsKind(kind)) {
|
||||
@ -15884,7 +15884,7 @@ int JSObject::GetFastElementsUsage() {
|
||||
return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value()
|
||||
: store->length();
|
||||
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
||||
store = FixedArray::cast(FixedArray::cast(store)->get(1));
|
||||
store = SloppyArgumentsElements::cast(store)->arguments();
|
||||
// Fall through.
|
||||
case FAST_HOLEY_SMI_ELEMENTS:
|
||||
case FAST_HOLEY_ELEMENTS:
|
||||
|
@ -1097,7 +1097,8 @@ template <class C> inline bool Is(Object* obj);
|
||||
V(ObjectHashTable) \
|
||||
V(ObjectHashSet) \
|
||||
V(WeakHashTable) \
|
||||
V(OrderedHashTable)
|
||||
V(OrderedHashTable) \
|
||||
V(SloppyArgumentsElements)
|
||||
|
||||
#define ODDBALL_LIST(V) \
|
||||
V(Undefined, undefined_value) \
|
||||
@ -2483,7 +2484,7 @@ class JSObject: public JSReceiver {
|
||||
DECLARE_VERIFIER(JSObject)
|
||||
#ifdef OBJECT_PRINT
|
||||
bool PrintProperties(std::ostream& os); // NOLINT
|
||||
bool PrintElements(std::ostream& os); // NOLINT
|
||||
void PrintElements(std::ostream& os); // NOLINT
|
||||
#endif
|
||||
#if defined(DEBUG) || defined(OBJECT_PRINT)
|
||||
void PrintTransitions(std::ostream& os); // NOLINT
|
||||
@ -2877,6 +2878,46 @@ class FixedDoubleArray: public FixedArrayBase {
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
|
||||
};
|
||||
|
||||
// Helper class to access FAST_ and SLOW_SLOPPY_ARGUMENTS_ELEMENTS
|
||||
//
|
||||
// +---+-----------------------+
|
||||
// | 0 | Context* context |
|
||||
// +---------------------------+
|
||||
// | 1 | FixedArray* arguments +----+ FAST_HOLEY_ELEMENTS
|
||||
// +---------------------------+ v-----+-----------+
|
||||
// | 2 | Object* param_1_map | | 0 | the_hole |
|
||||
// |...| ... | | ... | ... |
|
||||
// |n+1| Object* param_n_map | | n-1 | the_hole |
|
||||
// +---------------------------+ | n | element_1 |
|
||||
// | ... | ... |
|
||||
// |n+m-1| element_m |
|
||||
// +-----------------+
|
||||
//
|
||||
// Parameter maps give the index into the provided context. If a map entry is
|
||||
// the_hole it means that the given entry has been deleted from the arguments
|
||||
// object.
|
||||
// The arguments backing store kind depends on the ElementsKind of the outer
|
||||
// JSArgumentsObject:
|
||||
// - FAST_SLOPPY_ARGUMENTS_ELEMENTS: FAST_HOLEY_ELEMENTS
|
||||
// - SLOW_SLOPPY_ARGUMENTS_ELEMENTS: DICTIONARY_ELEMENTS
|
||||
class SloppyArgumentsElements : public FixedArray {
|
||||
public:
|
||||
static const int kContextIndex = 0;
|
||||
static const int kArgumentsIndex = 1;
|
||||
static const uint32_t kParameterMapStart = 2;
|
||||
|
||||
inline Context* context();
|
||||
inline FixedArray* arguments();
|
||||
inline void set_arguments(FixedArray* arguments);
|
||||
inline uint32_t parameter_map_length();
|
||||
inline Object* get_mapped_entry(uint32_t entry);
|
||||
inline void set_mapped_entry(uint32_t entry, Object* object);
|
||||
|
||||
DECLARE_CAST(SloppyArgumentsElements)
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(SloppyArgumentsElements);
|
||||
};
|
||||
|
||||
class WeakFixedArray : public FixedArray {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user