Move elements normalization to the ElementsAccessor
This speeds up element normalization. BUG= Review URL: https://codereview.chromium.org/1802733002 Cr-Commit-Position: refs/heads/master@{#34812}
This commit is contained in:
parent
7f19628a5b
commit
b015dd11af
@ -845,6 +845,17 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
from, from_start, *to, from_kind, to_start, packed_size, copy_size);
|
||||
}
|
||||
|
||||
Handle<SeededNumberDictionary> Normalize(Handle<JSObject> object) final {
|
||||
return ElementsAccessorSubclass::NormalizeImpl(object,
|
||||
handle(object->elements()));
|
||||
}
|
||||
|
||||
static Handle<SeededNumberDictionary> NormalizeImpl(
|
||||
Handle<JSObject> object, Handle<FixedArrayBase> elements) {
|
||||
UNREACHABLE();
|
||||
return Handle<SeededNumberDictionary>();
|
||||
}
|
||||
|
||||
void CollectElementIndices(Handle<JSObject> object,
|
||||
Handle<FixedArrayBase> backing_store,
|
||||
KeyAccumulator* keys, uint32_t range,
|
||||
@ -1293,6 +1304,36 @@ class FastElementsAccessor
|
||||
|
||||
typedef typename KindTraits::BackingStore BackingStore;
|
||||
|
||||
static Handle<SeededNumberDictionary> NormalizeImpl(
|
||||
Handle<JSObject> object, Handle<FixedArrayBase> store) {
|
||||
Isolate* isolate = store->GetIsolate();
|
||||
ElementsKind kind = FastElementsAccessorSubclass::kind();
|
||||
|
||||
// Ensure that notifications fire if the array or object prototypes are
|
||||
// normalizing.
|
||||
if (IsFastSmiOrObjectElementsKind(kind)) {
|
||||
isolate->UpdateArrayProtectorOnNormalizeElements(object);
|
||||
}
|
||||
|
||||
int capacity = object->GetFastElementsUsage();
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
SeededNumberDictionary::New(isolate, capacity);
|
||||
|
||||
PropertyDetails details = PropertyDetails::Empty();
|
||||
bool used_as_prototype = object->map()->is_prototype_map();
|
||||
int j = 0;
|
||||
for (int i = 0; j < capacity; i++) {
|
||||
if (IsHoleyElementsKind(kind)) {
|
||||
if (BackingStore::cast(*store)->is_the_hole(i)) continue;
|
||||
}
|
||||
Handle<Object> value = FastElementsAccessorSubclass::GetImpl(*store, i);
|
||||
dictionary = SeededNumberDictionary::AddNumberEntry(
|
||||
dictionary, i, value, details, used_as_prototype);
|
||||
j++;
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
static void DeleteAtEnd(Handle<JSObject> obj,
|
||||
Handle<BackingStore> backing_store, uint32_t entry) {
|
||||
uint32_t length = static_cast<uint32_t>(backing_store->length());
|
||||
@ -2403,6 +2444,13 @@ class FastSloppyArgumentsElementsAccessor
|
||||
FastHoleyObjectElementsAccessor,
|
||||
ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
||||
|
||||
static Handle<SeededNumberDictionary> NormalizeImpl(
|
||||
Handle<JSObject> object, Handle<FixedArrayBase> elements) {
|
||||
FixedArray* parameter_map = FixedArray::cast(*elements);
|
||||
Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
||||
return FastHoleyObjectElementsAccessor::NormalizeImpl(object, arguments);
|
||||
}
|
||||
|
||||
static void DeleteFromArguments(Handle<JSObject> obj, uint32_t entry) {
|
||||
FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
||||
Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
||||
@ -2625,6 +2673,11 @@ class FastStringWrapperElementsAccessor
|
||||
: StringWrapperElementsAccessor<
|
||||
FastStringWrapperElementsAccessor, FastHoleyObjectElementsAccessor,
|
||||
ElementsKindTraits<FAST_STRING_WRAPPER_ELEMENTS>>(name) {}
|
||||
|
||||
static Handle<SeededNumberDictionary> NormalizeImpl(
|
||||
Handle<JSObject> object, Handle<FixedArrayBase> elements) {
|
||||
return FastHoleyObjectElementsAccessor::NormalizeImpl(object, elements);
|
||||
}
|
||||
};
|
||||
|
||||
class SlowStringWrapperElementsAccessor
|
||||
|
@ -149,6 +149,8 @@ class ElementsAccessor {
|
||||
|
||||
virtual Handle<Object> Shift(Handle<JSArray> receiver) = 0;
|
||||
|
||||
virtual Handle<SeededNumberDictionary> Normalize(Handle<JSObject> object) = 0;
|
||||
|
||||
protected:
|
||||
friend class LookupIterator;
|
||||
|
||||
|
@ -5696,35 +5696,6 @@ void JSObject::ResetElements(Handle<JSObject> object) {
|
||||
}
|
||||
|
||||
|
||||
static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
|
||||
Handle<FixedArrayBase> array, int length,
|
||||
Handle<SeededNumberDictionary> dictionary, bool used_as_prototype) {
|
||||
Isolate* isolate = array->GetIsolate();
|
||||
Factory* factory = isolate->factory();
|
||||
bool has_double_elements = array->IsFixedDoubleArray();
|
||||
for (int i = 0; i < length; i++) {
|
||||
Handle<Object> value;
|
||||
if (has_double_elements) {
|
||||
Handle<FixedDoubleArray> double_array =
|
||||
Handle<FixedDoubleArray>::cast(array);
|
||||
if (double_array->is_the_hole(i)) {
|
||||
value = factory->the_hole_value();
|
||||
} else {
|
||||
value = factory->NewHeapNumber(double_array->get_scalar(i));
|
||||
}
|
||||
} else {
|
||||
value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
|
||||
}
|
||||
if (!value->IsTheHole()) {
|
||||
PropertyDetails details = PropertyDetails::Empty();
|
||||
dictionary = SeededNumberDictionary::AddNumberEntry(
|
||||
dictionary, i, value, details, used_as_prototype);
|
||||
}
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
|
||||
void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
|
||||
if (dictionary->requires_slow_elements()) return;
|
||||
dictionary->set_requires_slow_elements();
|
||||
@ -5735,40 +5706,23 @@ void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
object->map()->is_prototype_map());
|
||||
}
|
||||
|
||||
|
||||
Handle<SeededNumberDictionary> JSObject::NormalizeElements(
|
||||
Handle<JSObject> object) {
|
||||
DCHECK(!object->HasFixedTypedArrayElements());
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
|
||||
// Find the backing store.
|
||||
Handle<FixedArrayBase> elements(object->elements(), isolate);
|
||||
bool is_arguments = object->HasSloppyArgumentsElements();
|
||||
if (is_arguments) {
|
||||
FixedArray* parameter_map = FixedArray::cast(*elements);
|
||||
elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate);
|
||||
}
|
||||
{
|
||||
DisallowHeapAllocation no_gc;
|
||||
FixedArrayBase* elements = object->elements();
|
||||
|
||||
if (elements->IsDictionary()) {
|
||||
return Handle<SeededNumberDictionary>::cast(elements);
|
||||
if (is_arguments) {
|
||||
FixedArray* parameter_map = FixedArray::cast(elements);
|
||||
elements = FixedArrayBase::cast(parameter_map->get(1));
|
||||
}
|
||||
|
||||
if (elements->IsDictionary()) {
|
||||
return handle(SeededNumberDictionary::cast(elements), isolate);
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK(object->HasFastSmiOrObjectElements() ||
|
||||
@ -5777,7 +5731,7 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
|
||||
object->HasFastStringWrapperElements());
|
||||
|
||||
Handle<SeededNumberDictionary> dictionary =
|
||||
GetNormalizedElementDictionary(object, elements);
|
||||
object->GetElementsAccessor()->Normalize(object);
|
||||
|
||||
// Switch to using the dictionary as the backing storage for elements.
|
||||
ElementsKind target_kind = is_arguments
|
||||
@ -7764,8 +7718,7 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
|
||||
: object->elements()->length();
|
||||
new_element_dictionary =
|
||||
length == 0 ? isolate->factory()->empty_slow_element_dictionary()
|
||||
: GetNormalizedElementDictionary(
|
||||
object, handle(object->elements()));
|
||||
: object->GetElementsAccessor()->Normalize(object);
|
||||
}
|
||||
|
||||
Handle<Symbol> transition_marker;
|
||||
|
@ -2541,9 +2541,6 @@ class JSObject: public JSReceiver {
|
||||
|
||||
static Handle<Smi> GetOrCreateIdentityHash(Handle<JSObject> object);
|
||||
|
||||
static Handle<SeededNumberDictionary> GetNormalizedElementDictionary(
|
||||
Handle<JSObject> object, Handle<FixedArrayBase> elements);
|
||||
|
||||
// Helper for fast versions of preventExtensions, seal, and freeze.
|
||||
// attrs is one of NONE, SEALED, or FROZEN (depending on the operation).
|
||||
template <PropertyAttributes attrs>
|
||||
|
Loading…
Reference in New Issue
Block a user