Commit 11f74547 authored by jbroman's avatar jbroman Committed by Commit bot

Take advantage of fast properties in ValueSerializer when JSObject has them.

This yields a ~20% serialization time improvement on typical JSON-esque data.

BUG=chromium:148757

Review-Url: https://codereview.chromium.org/2304563004
Cr-Commit-Position: refs/heads/master@{#39221}
parent 4b618dbf
......@@ -379,13 +379,59 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
}
Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) {
DCHECK_GT(object->map()->instance_type(), LAST_CUSTOM_ELEMENTS_RECEIVER);
const bool can_serialize_fast =
object->HasFastProperties() && object->elements()->length() == 0;
if (!can_serialize_fast) return WriteJSObjectSlow(object);
Handle<Map> map(object->map(), isolate_);
WriteTag(SerializationTag::kBeginJSObject);
// Write out fast properties as long as they are only data properties and the
// map doesn't change.
uint32_t properties_written = 0;
bool map_changed = false;
for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
Handle<Name> key(map->instance_descriptors()->GetKey(i), isolate_);
if (!key->IsString()) continue;
PropertyDetails details = map->instance_descriptors()->GetDetails(i);
if (details.IsDontEnum()) continue;
Handle<Object> value;
if (V8_LIKELY(!map_changed)) map_changed = *map == object->map();
if (V8_LIKELY(!map_changed && details.type() == DATA)) {
FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
value = JSObject::FastPropertyAt(object, details.representation(),
field_index);
} else {
// This logic should essentially match WriteJSObjectPropertiesSlow.
// If the property is no longer found, do not serialize it.
// This could happen if a getter deleted the property.
LookupIterator it(isolate_, object, key, LookupIterator::OWN);
if (!it.IsFound()) continue;
if (!Object::GetProperty(&it).ToHandle(&value)) return Nothing<bool>();
}
if (!WriteObject(key).FromMaybe(false) ||
!WriteObject(value).FromMaybe(false)) {
return Nothing<bool>();
}
properties_written++;
}
WriteTag(SerializationTag::kEndJSObject);
WriteVarint<uint32_t>(properties_written);
return Just(true);
}
Maybe<bool> ValueSerializer::WriteJSObjectSlow(Handle<JSObject> object) {
WriteTag(SerializationTag::kBeginJSObject);
Handle<FixedArray> keys;
uint32_t properties_written;
if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
ENUMERABLE_STRINGS)
.ToHandle(&keys) ||
!WriteJSObjectProperties(object, keys).To(&properties_written)) {
!WriteJSObjectPropertiesSlow(object, keys).To(&properties_written)) {
return Nothing<bool>();
}
WriteTag(SerializationTag::kEndJSObject);
......@@ -432,7 +478,7 @@ Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) {
Handle<FixedArray> keys =
accumulator.GetKeys(GetKeysConversion::kConvertToString);
uint32_t properties_written;
if (!WriteJSObjectProperties(array, keys).To(&properties_written)) {
if (!WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
return Nothing<bool>();
}
WriteTag(SerializationTag::kEndDenseJSArray);
......@@ -446,7 +492,7 @@ Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) {
if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly,
ENUMERABLE_STRINGS)
.ToHandle(&keys) ||
!WriteJSObjectProperties(array, keys).To(&properties_written)) {
!WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
return Nothing<bool>();
}
WriteTag(SerializationTag::kEndSparseJSArray);
......@@ -614,7 +660,7 @@ Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) {
return Just(true);
}
Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties(
Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow(
Handle<JSObject> object, Handle<FixedArray> keys) {
uint32_t properties_written = 0;
int length = keys->length();
......
......@@ -89,6 +89,7 @@ class ValueSerializer {
void WriteString(Handle<String> string);
Maybe<bool> WriteJSReceiver(Handle<JSReceiver> receiver) WARN_UNUSED_RESULT;
Maybe<bool> WriteJSObject(Handle<JSObject> object) WARN_UNUSED_RESULT;
Maybe<bool> WriteJSObjectSlow(Handle<JSObject> object) WARN_UNUSED_RESULT;
Maybe<bool> WriteJSArray(Handle<JSArray> array) WARN_UNUSED_RESULT;
void WriteJSDate(JSDate* date);
Maybe<bool> WriteJSValue(Handle<JSValue> value) WARN_UNUSED_RESULT;
......@@ -103,7 +104,7 @@ class ValueSerializer {
* buffer. Returns the number of keys actually written, which may be smaller
* if some keys are not own properties when accessed.
*/
Maybe<uint32_t> WriteJSObjectProperties(
Maybe<uint32_t> WriteJSObjectPropertiesSlow(
Handle<JSObject> object, Handle<FixedArray> keys) WARN_UNUSED_RESULT;
/*
......
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