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( ...@@ -7967,56 +7967,32 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
if (details.location() != kField) continue; if (details.location() != kField) continue;
DCHECK_EQ(kData, details.kind()); DCHECK_EQ(kData, details.kind());
FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i); FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
if (object->IsUnboxedDoubleField(index)) { if (copy->IsUnboxedDoubleField(index)) continue;
if (copying) { Object* raw = copy->RawFastPropertyAt(index);
// Ensure that all bits of the double value are preserved. if (raw->IsMutableHeapNumber()) {
uint64_t value = object->RawFastDoublePropertyAsBitsAt(index); if (!copying) continue;
copy->RawFastDoublePropertyAsBitsAtPut(index, value); DCHECK(details.representation().IsDouble());
} uint64_t double_value = HeapNumber::cast(raw)->value_as_bits();
} else { Handle<HeapNumber> value = isolate->factory()->NewHeapNumber(MUTABLE);
Handle<Object> value(object->RawFastPropertyAt(index), isolate); value->set_value_as_bits(double_value);
if (value->IsJSObject()) { copy->FastPropertyAtPut(index, *value);
ASSIGN_RETURN_ON_EXCEPTION( } else if (raw->IsJSObject()) {
isolate, value, Handle<JSObject> value(JSObject::cast(raw), isolate);
VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), ASSIGN_RETURN_ON_EXCEPTION(
JSObject); isolate, value, VisitElementOrProperty(copy, value), JSObject);
if (copying) { if (copying) copy->FastPropertyAtPut(index, *value);
copy->FastPropertyAtPut(index, *value);
}
} else {
if (copying) {
Representation representation = details.representation();
value = Object::NewStorageFor(isolate, value, representation);
copy->FastPropertyAtPut(index, *value);
}
}
} }
} }
} else { } else {
// Only deep copy fields from the object literal expression. Handle<NameDictionary> dict(NameDictionary::cast(copy->properties()));
// In particular, don't try to copy the length attribute of for (int i = 0; i < dict->Capacity(); i++) {
// an array. Object* raw = dict->ValueAt(i);
PropertyFilter filter = static_cast<PropertyFilter>( if (!raw->IsJSObject()) continue;
ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE); DCHECK(dict->KeyAt(i)->IsName());
KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly, filter); Handle<JSObject> value(JSObject::cast(raw), isolate);
accumulator.CollectOwnPropertyNames(copy, copy); ASSIGN_RETURN_ON_EXCEPTION(
Handle<FixedArray> names = accumulator.GetKeys(); isolate, value, VisitElementOrProperty(copy, value), JSObject);
for (int i = 0; i < names->length(); i++) { if (copying) dict->ValueAtPut(i, *value);
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();
}
}
} }
} }
...@@ -8033,17 +8009,12 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk( ...@@ -8033,17 +8009,12 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
#endif #endif
} else { } else {
for (int i = 0; i < elements->length(); i++) { for (int i = 0; i < elements->length(); i++) {
Handle<Object> value(elements->get(i), isolate); Object* raw = elements->get(i);
if (value->IsJSObject()) { if (!raw->IsJSObject()) continue;
Handle<JSObject> result; Handle<JSObject> value(JSObject::cast(raw), isolate);
ASSIGN_RETURN_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
isolate, result, isolate, value, VisitElementOrProperty(copy, value), JSObject);
VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), if (copying) elements->set(i, *value);
JSObject);
if (copying) {
elements->set(i, *result);
}
}
} }
} }
break; break;
...@@ -8053,20 +8024,12 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk( ...@@ -8053,20 +8024,12 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
copy->element_dictionary()); copy->element_dictionary());
int capacity = element_dictionary->Capacity(); int capacity = element_dictionary->Capacity();
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = element_dictionary->KeyAt(i); Object* raw = element_dictionary->ValueAt(i);
if (element_dictionary->IsKey(isolate, k)) { if (!raw->IsJSObject()) continue;
Handle<Object> value(element_dictionary->ValueAt(i), isolate); Handle<JSObject> value(JSObject::cast(raw), isolate);
if (value->IsJSObject()) { ASSIGN_RETURN_ON_EXCEPTION(
Handle<JSObject> result; isolate, value, VisitElementOrProperty(copy, value), JSObject);
ASSIGN_RETURN_ON_EXCEPTION( if (copying) element_dictionary->ValueAtPut(i, *value);
isolate, result,
VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
JSObject);
if (copying) {
element_dictionary->ValueAtPut(i, *result);
}
}
}
} }
break; 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