Commit c4281cd9 authored by jameslahm's avatar jameslahm Committed by V8 LUCI CQ

[web snapshot] Add support for arrays w/holes

This CL adds serialization and deserialization support
for HOLEY_ELEMENTS and HOLEY_SMI_ELEMENTS kind arrays.

Bug: v8:11525
Change-Id: Ib6fdcd1916badd02e567571e1c0748dce85cd8a0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3620753Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: 王澳 <wangao.james@bytedance.com>
Cr-Commit-Position: refs/heads/main@{#80313}
parent 31009706
...@@ -835,7 +835,8 @@ void WebSnapshotSerializer::DiscoverArray(Handle<JSArray> array) { ...@@ -835,7 +835,8 @@ void WebSnapshotSerializer::DiscoverArray(Handle<JSArray> array) {
if (elements_kind != PACKED_SMI_ELEMENTS && if (elements_kind != PACKED_SMI_ELEMENTS &&
elements_kind != PACKED_ELEMENTS && elements_kind != PACKED_ELEMENTS &&
elements_kind != PACKED_SEALED_ELEMENTS && elements_kind != PACKED_SEALED_ELEMENTS &&
elements_kind != PACKED_FROZEN_ELEMENTS) { elements_kind != PACKED_FROZEN_ELEMENTS &&
elements_kind != HOLEY_SMI_ELEMENTS && elements_kind != HOLEY_ELEMENTS) {
Throw("Unsupported array"); Throw("Unsupported array");
return; return;
} }
...@@ -1026,18 +1027,25 @@ void WebSnapshotSerializer::SerializeObject(Handle<JSObject> object) { ...@@ -1026,18 +1027,25 @@ void WebSnapshotSerializer::SerializeObject(Handle<JSObject> object) {
// - Serialized value // - Serialized value
void WebSnapshotSerializer::SerializeArray(Handle<JSArray> array) { void WebSnapshotSerializer::SerializeArray(Handle<JSArray> array) {
auto elements_kind = array->GetElementsKind(); auto elements_kind = array->GetElementsKind();
if (elements_kind != PACKED_SMI_ELEMENTS && // TODO(v8:11525): Support sparse arrays and double arrays.
elements_kind != PACKED_ELEMENTS) { switch (elements_kind) {
Throw("Unsupported array"); case PACKED_SMI_ELEMENTS:
return; case PACKED_ELEMENTS:
} case HOLEY_SMI_ELEMENTS:
// TODO(v8:11525): Support sparse arrays & arrays with holes. case HOLEY_ELEMENTS: {
uint32_t length = static_cast<uint32_t>(array->length().ToSmi().value()); uint32_t length = static_cast<uint32_t>(array->length().ToSmi().value());
array_serializer_.WriteUint32(length); array_serializer_.WriteUint32(length);
Handle<FixedArray> elements = Handle<FixedArray> elements =
handle(FixedArray::cast(array->elements()), isolate_); handle(FixedArray::cast(array->elements()), isolate_);
for (uint32_t i = 0; i < length; ++i) { for (uint32_t i = 0; i < length; ++i) {
WriteValue(handle(elements->get(i), isolate_), array_serializer_); WriteValue(handle(elements->get(i), isolate_), array_serializer_);
}
break;
}
default: {
Throw("Unsupported array");
return;
}
} }
} }
...@@ -1093,6 +1101,9 @@ void WebSnapshotSerializer::WriteValue(Handle<Object> object, ...@@ -1093,6 +1101,9 @@ void WebSnapshotSerializer::WriteValue(Handle<Object> object,
case Oddball::kUndefined: case Oddball::kUndefined:
serializer.WriteUint32(ValueType::UNDEFINED_CONSTANT); serializer.WriteUint32(ValueType::UNDEFINED_CONSTANT);
return; return;
case Oddball::kTheHole:
serializer.WriteUint32(ValueType::NO_ELEMENT_CONSTANT);
return;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -2065,14 +2076,22 @@ void WebSnapshotDeserializer::DeserializeArrays() { ...@@ -2065,14 +2076,22 @@ void WebSnapshotDeserializer::DeserializeArrays() {
} }
Handle<FixedArray> elements = factory()->NewFixedArray(length); Handle<FixedArray> elements = factory()->NewFixedArray(length);
ElementsKind elements_kind = PACKED_SMI_ELEMENTS; ElementsKind elements_kind = PACKED_SMI_ELEMENTS;
bool has_hole = false;
for (uint32_t i = 0; i < length; ++i) { for (uint32_t i = 0; i < length; ++i) {
Object value = ReadValue(elements, i); Object value = ReadValue(elements, i);
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
if (!value.IsSmi()) { if (!value.IsSmi()) {
elements_kind = PACKED_ELEMENTS; elements_kind = PACKED_ELEMENTS;
} }
if (value.IsTheHole()) {
has_hole = true;
}
elements->set(static_cast<int>(i), value); elements->set(static_cast<int>(i), value);
} }
if (has_hole) {
elements_kind = elements_kind == PACKED_ELEMENTS ? HOLEY_ELEMENTS
: HOLEY_SMI_ELEMENTS;
}
Handle<JSArray> array = Handle<JSArray> array =
factory()->NewJSArrayWithElements(elements, elements_kind, length); factory()->NewJSArrayWithElements(elements, elements_kind, length);
arrays_.set(static_cast<int>(current_array_count_), *array); arrays_.set(static_cast<int>(current_array_count_), *array);
...@@ -2176,6 +2195,8 @@ Object WebSnapshotDeserializer::ReadValue(Handle<HeapObject> container, ...@@ -2176,6 +2195,8 @@ Object WebSnapshotDeserializer::ReadValue(Handle<HeapObject> container,
return roots_.null_value(); return roots_.null_value();
case ValueType::UNDEFINED_CONSTANT: case ValueType::UNDEFINED_CONSTANT:
return roots_.undefined_value(); return roots_.undefined_value();
case ValueType::NO_ELEMENT_CONSTANT:
return roots_.the_hole_value();
case ValueType::INTEGER: case ValueType::INTEGER:
return ReadInteger(); return ReadInteger();
case ValueType::DOUBLE: case ValueType::DOUBLE:
......
...@@ -45,6 +45,8 @@ class WebSnapshotSerializerDeserializer { ...@@ -45,6 +45,8 @@ class WebSnapshotSerializerDeserializer {
TRUE_CONSTANT, TRUE_CONSTANT,
NULL_CONSTANT, NULL_CONSTANT,
UNDEFINED_CONSTANT, UNDEFINED_CONSTANT,
// It corresponds to the hole value.
NO_ELEMENT_CONSTANT,
INTEGER, INTEGER,
DOUBLE, DOUBLE,
STRING_ID, STRING_ID,
......
...@@ -54,6 +54,23 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js'); ...@@ -54,6 +54,23 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
assertEquals([5, 6, 7], foo.array); assertEquals([5, 6, 7], foo.array);
})(); })();
(function TestHoleySmiElementsArray() {
function createObjects() {
globalThis.foo = [1,,2];
}
const {foo} = takeAndUseWebSnapshot(createObjects, ['foo']);
assertEquals([1,,2], foo);
})();
(function TestHoleyElementsArray() {
function createObjects() {
globalThis.foo = [1,,"123"];
}
const {foo} = takeAndUseWebSnapshot(createObjects, ['foo']);
assertEquals([1,,"123"], foo);
})();
(function TestEmptyArray() { (function TestEmptyArray() {
function createObjects() { function createObjects() {
globalThis.foo = { globalThis.foo = {
......
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