Commit 990bad7f authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[runtime] Speed up nested object literal copying

This speeds up fast-mode object copying by ~2x and __proto__:null cases by ~20x.

Bug: 
Change-Id: Ic3893ae4c87063f0c8c524ef55c0e786b7a87192
Reviewed-on: https://chromium-review.googlesource.com/516983
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45536}
parent 5d670fa4
......@@ -7967,56 +7967,32 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
if (details.location() != kField) continue;
DCHECK_EQ(kData, details.kind());
FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
if (object->IsUnboxedDoubleField(index)) {
if (copying) {
// Ensure that all bits of the double value are preserved.
uint64_t value = object->RawFastDoublePropertyAsBitsAt(index);
copy->RawFastDoublePropertyAsBitsAtPut(index, value);
}
} else {
Handle<Object> value(object->RawFastPropertyAt(index), isolate);
if (value->IsJSObject()) {
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value,
VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
JSObject);
if (copying) {
copy->FastPropertyAtPut(index, *value);
}
} else {
if (copying) {
Representation representation = details.representation();
value = Object::NewStorageFor(isolate, value, representation);
copy->FastPropertyAtPut(index, *value);
}
}
if (copy->IsUnboxedDoubleField(index)) continue;
Object* raw = copy->RawFastPropertyAt(index);
if (raw->IsMutableHeapNumber()) {
if (!copying) continue;
DCHECK(details.representation().IsDouble());
uint64_t double_value = HeapNumber::cast(raw)->value_as_bits();
Handle<HeapNumber> value = isolate->factory()->NewHeapNumber(MUTABLE);
value->set_value_as_bits(double_value);
copy->FastPropertyAtPut(index, *value);
} else if (raw->IsJSObject()) {
Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) copy->FastPropertyAtPut(index, *value);
}
}
} else {
// Only deep copy fields from the object literal expression.
// In particular, don't try to copy the length attribute of
// an array.
PropertyFilter filter = static_cast<PropertyFilter>(
ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE);
KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly, filter);
accumulator.CollectOwnPropertyNames(copy, copy);
Handle<FixedArray> names = accumulator.GetKeys();
for (int i = 0; i < names->length(); i++) {
DCHECK(names->get(i)->IsName());
Handle<Name> name(Name::cast(names->get(i)));
Handle<Object> value =
JSObject::GetProperty(copy, name).ToHandleChecked();
if (value->IsJSObject()) {
Handle<JSObject> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
JSObject);
if (copying) {
// Creating object copy for literals. No strict mode needed.
JSObject::SetProperty(copy, name, result, SLOPPY).Assert();
}
}
Handle<NameDictionary> dict(NameDictionary::cast(copy->properties()));
for (int i = 0; i < dict->Capacity(); i++) {
Object* raw = dict->ValueAt(i);
if (!raw->IsJSObject()) continue;
DCHECK(dict->KeyAt(i)->IsName());
Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) dict->ValueAtPut(i, *value);
}
}
......@@ -8033,17 +8009,12 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
#endif
} else {
for (int i = 0; i < elements->length(); i++) {
Handle<Object> value(elements->get(i), isolate);
if (value->IsJSObject()) {
Handle<JSObject> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
JSObject);
if (copying) {
elements->set(i, *result);
}
}
Object* raw = elements->get(i);
if (!raw->IsJSObject()) continue;
Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) elements->set(i, *value);
}
}
break;
......@@ -8053,20 +8024,12 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
copy->element_dictionary());
int capacity = element_dictionary->Capacity();
for (int i = 0; i < capacity; i++) {
Object* k = element_dictionary->KeyAt(i);
if (element_dictionary->IsKey(isolate, k)) {
Handle<Object> value(element_dictionary->ValueAt(i), isolate);
if (value->IsJSObject()) {
Handle<JSObject> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
JSObject);
if (copying) {
element_dictionary->ValueAtPut(i, *result);
}
}
}
Object* raw = element_dictionary->ValueAt(i);
if (!raw->IsJSObject()) continue;
Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) element_dictionary->ValueAtPut(i, *value);
}
break;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment