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) {
if (elements_kind != PACKED_SMI_ELEMENTS &&
elements_kind != PACKED_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");
return;
}
......@@ -1026,18 +1027,25 @@ void WebSnapshotSerializer::SerializeObject(Handle<JSObject> object) {
// - Serialized value
void WebSnapshotSerializer::SerializeArray(Handle<JSArray> array) {
auto elements_kind = array->GetElementsKind();
if (elements_kind != PACKED_SMI_ELEMENTS &&
elements_kind != PACKED_ELEMENTS) {
Throw("Unsupported array");
return;
}
// TODO(v8:11525): Support sparse arrays & arrays with holes.
uint32_t length = static_cast<uint32_t>(array->length().ToSmi().value());
array_serializer_.WriteUint32(length);
Handle<FixedArray> elements =
handle(FixedArray::cast(array->elements()), isolate_);
for (uint32_t i = 0; i < length; ++i) {
WriteValue(handle(elements->get(i), isolate_), array_serializer_);
// TODO(v8:11525): Support sparse arrays and double arrays.
switch (elements_kind) {
case PACKED_SMI_ELEMENTS:
case PACKED_ELEMENTS:
case HOLEY_SMI_ELEMENTS:
case HOLEY_ELEMENTS: {
uint32_t length = static_cast<uint32_t>(array->length().ToSmi().value());
array_serializer_.WriteUint32(length);
Handle<FixedArray> elements =
handle(FixedArray::cast(array->elements()), isolate_);
for (uint32_t i = 0; i < length; ++i) {
WriteValue(handle(elements->get(i), isolate_), array_serializer_);
}
break;
}
default: {
Throw("Unsupported array");
return;
}
}
}
......@@ -1093,6 +1101,9 @@ void WebSnapshotSerializer::WriteValue(Handle<Object> object,
case Oddball::kUndefined:
serializer.WriteUint32(ValueType::UNDEFINED_CONSTANT);
return;
case Oddball::kTheHole:
serializer.WriteUint32(ValueType::NO_ELEMENT_CONSTANT);
return;
default:
UNREACHABLE();
}
......@@ -2065,14 +2076,22 @@ void WebSnapshotDeserializer::DeserializeArrays() {
}
Handle<FixedArray> elements = factory()->NewFixedArray(length);
ElementsKind elements_kind = PACKED_SMI_ELEMENTS;
bool has_hole = false;
for (uint32_t i = 0; i < length; ++i) {
Object value = ReadValue(elements, i);
DisallowGarbageCollection no_gc;
if (!value.IsSmi()) {
elements_kind = PACKED_ELEMENTS;
}
if (value.IsTheHole()) {
has_hole = true;
}
elements->set(static_cast<int>(i), value);
}
if (has_hole) {
elements_kind = elements_kind == PACKED_ELEMENTS ? HOLEY_ELEMENTS
: HOLEY_SMI_ELEMENTS;
}
Handle<JSArray> array =
factory()->NewJSArrayWithElements(elements, elements_kind, length);
arrays_.set(static_cast<int>(current_array_count_), *array);
......@@ -2176,6 +2195,8 @@ Object WebSnapshotDeserializer::ReadValue(Handle<HeapObject> container,
return roots_.null_value();
case ValueType::UNDEFINED_CONSTANT:
return roots_.undefined_value();
case ValueType::NO_ELEMENT_CONSTANT:
return roots_.the_hole_value();
case ValueType::INTEGER:
return ReadInteger();
case ValueType::DOUBLE:
......
......@@ -45,6 +45,8 @@ class WebSnapshotSerializerDeserializer {
TRUE_CONSTANT,
NULL_CONSTANT,
UNDEFINED_CONSTANT,
// It corresponds to the hole value.
NO_ELEMENT_CONSTANT,
INTEGER,
DOUBLE,
STRING_ID,
......
......@@ -54,6 +54,23 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
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 createObjects() {
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