[web snapshot] Support resizable ArrayBuffer, detached
... ArrayBuffer and shared ArrayBuffer. Bug: v8:11525 Change-Id: I6b3f78d5cf6528123b40c49f2767ade2b6bfbed1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3706279 Commit-Queue: 王澳 <wangao.james@bytedance.com> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/main@{#81189}
This commit is contained in:
parent
70289dd72a
commit
cc709727e7
@ -2988,31 +2988,15 @@ void Factory::TypeAndSizeForElementsKind(ElementsKind kind,
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void ForFixedTypedArray(ExternalArrayType array_type, size_t* element_size,
|
||||
ElementsKind* element_kind) {
|
||||
switch (array_type) {
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
||||
case kExternal##Type##Array: \
|
||||
*element_size = sizeof(ctype); \
|
||||
*element_kind = TYPE##_ELEMENTS; \
|
||||
return;
|
||||
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Handle<JSArrayBufferView> Factory::NewJSArrayBufferView(
|
||||
Handle<Map> map, Handle<FixedArrayBase> elements,
|
||||
Handle<JSArrayBuffer> buffer, size_t byte_offset, size_t byte_length) {
|
||||
CHECK_LE(byte_length, buffer->byte_length());
|
||||
CHECK_LE(byte_offset, buffer->byte_length());
|
||||
CHECK_LE(byte_offset + byte_length, buffer->byte_length());
|
||||
if (!IsRabGsabTypedArrayElementsKind(map->elements_kind())) {
|
||||
CHECK_LE(byte_length, buffer->GetByteLength());
|
||||
CHECK_LE(byte_offset, buffer->GetByteLength());
|
||||
CHECK_LE(byte_offset + byte_length, buffer->GetByteLength());
|
||||
}
|
||||
|
||||
Handle<JSArrayBufferView> array_buffer_view = Handle<JSArrayBufferView>::cast(
|
||||
NewJSObjectFromMap(map, AllocationType::kYoung));
|
||||
DisallowGarbageCollection no_gc;
|
||||
@ -3035,28 +3019,17 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
|
||||
size_t length) {
|
||||
size_t element_size;
|
||||
ElementsKind elements_kind;
|
||||
ForFixedTypedArray(type, &element_size, &elements_kind);
|
||||
JSTypedArray::ForFixedTypedArray(type, &element_size, &elements_kind);
|
||||
size_t byte_length = length * element_size;
|
||||
|
||||
CHECK_LE(length, JSTypedArray::kMaxLength);
|
||||
CHECK_EQ(length, byte_length / element_size);
|
||||
CHECK_EQ(0, byte_offset % ElementsKindToByteSize(elements_kind));
|
||||
|
||||
Handle<Map> map;
|
||||
switch (elements_kind) {
|
||||
#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype) \
|
||||
case TYPE##_ELEMENTS: \
|
||||
map = \
|
||||
handle(isolate()->native_context()->type##_array_fun().initial_map(), \
|
||||
isolate()); \
|
||||
break;
|
||||
|
||||
TYPED_ARRAYS(TYPED_ARRAY_FUN)
|
||||
#undef TYPED_ARRAY_FUN
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
Handle<Map> map(
|
||||
isolate()->raw_native_context().TypedArrayElementsKindToCtorMap(
|
||||
elements_kind),
|
||||
isolate());
|
||||
Handle<JSTypedArray> typed_array =
|
||||
Handle<JSTypedArray>::cast(NewJSArrayBufferView(
|
||||
map, empty_byte_array(), buffer, byte_offset, byte_length));
|
||||
|
@ -1036,6 +1036,7 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
||||
|
||||
private:
|
||||
friend class FactoryBase<Factory>;
|
||||
friend class WebSnapshotDeserializer;
|
||||
|
||||
// ------
|
||||
// Customization points for FactoryBase
|
||||
|
@ -295,6 +295,28 @@ ScriptContextTable NativeContext::synchronized_script_context_table() const {
|
||||
get(SCRIPT_CONTEXT_TABLE_INDEX, kAcquireLoad));
|
||||
}
|
||||
|
||||
Map NativeContext::TypedArrayElementsKindToCtorMap(
|
||||
ElementsKind element_kind) const {
|
||||
int ctor_index = Context::FIRST_FIXED_TYPED_ARRAY_FUN_INDEX + element_kind -
|
||||
ElementsKind::FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
|
||||
Map map = Map::cast(JSFunction::cast(get(ctor_index)).initial_map());
|
||||
DCHECK_EQ(map.elements_kind(), element_kind);
|
||||
DCHECK(InstanceTypeChecker::IsJSTypedArray(map.instance_type()));
|
||||
return map;
|
||||
}
|
||||
|
||||
Map NativeContext::TypedArrayElementsKindToRabGsabCtorMap(
|
||||
ElementsKind element_kind) const {
|
||||
int ctor_index = Context::FIRST_RAB_GSAB_TYPED_ARRAY_MAP_INDEX +
|
||||
element_kind -
|
||||
ElementsKind::FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
|
||||
Map map = Map::cast(get(ctor_index));
|
||||
DCHECK_EQ(map.elements_kind(),
|
||||
GetCorrespondingRabGsabElementsKind(element_kind));
|
||||
DCHECK(InstanceTypeChecker::IsJSTypedArray(map.instance_type()));
|
||||
return map;
|
||||
}
|
||||
|
||||
void NativeContext::SetOptimizedCodeListHead(Object head) {
|
||||
set(OPTIMIZED_CODE_LIST, head, UPDATE_WRITE_BARRIER, kReleaseStore);
|
||||
}
|
||||
|
@ -740,6 +740,11 @@ class NativeContext : public Context {
|
||||
return Context::global_object();
|
||||
}
|
||||
|
||||
inline Map TypedArrayElementsKindToCtorMap(ElementsKind element_kind) const;
|
||||
|
||||
inline Map TypedArrayElementsKindToRabGsabCtorMap(
|
||||
ElementsKind element_kind) const;
|
||||
|
||||
// Dispatched behavior.
|
||||
DECL_PRINTER(NativeContext)
|
||||
DECL_VERIFIER(NativeContext)
|
||||
|
@ -230,6 +230,23 @@ bool JSTypedArray::IsDetachedOrOutOfBounds() const {
|
||||
return out_of_bounds;
|
||||
}
|
||||
|
||||
// static
|
||||
inline void JSTypedArray::ForFixedTypedArray(ExternalArrayType array_type,
|
||||
size_t* element_size,
|
||||
ElementsKind* element_kind) {
|
||||
switch (array_type) {
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
||||
case kExternal##Type##Array: \
|
||||
*element_size = sizeof(ctype); \
|
||||
*element_kind = TYPE##_ELEMENTS; \
|
||||
return;
|
||||
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
size_t JSTypedArray::length() const {
|
||||
DCHECK(!is_length_tracking());
|
||||
DCHECK(!is_backed_by_rab());
|
||||
|
@ -310,6 +310,10 @@ class JSTypedArray
|
||||
inline bool IsOutOfBounds() const;
|
||||
inline bool IsDetachedOrOutOfBounds() const;
|
||||
|
||||
static inline void ForFixedTypedArray(ExternalArrayType array_type,
|
||||
size_t* element_size,
|
||||
ElementsKind* element_kind);
|
||||
|
||||
static size_t LengthTrackingGsabBackedTypedArrayLength(Isolate* isolate,
|
||||
Address raw_array);
|
||||
|
||||
@ -372,6 +376,7 @@ class JSTypedArray
|
||||
template <typename IsolateT>
|
||||
friend class Deserializer;
|
||||
friend class Factory;
|
||||
friend class WebSnapshotDeserializer;
|
||||
|
||||
DECL_PRIMITIVE_SETTER(length, size_t)
|
||||
// Reads the "length" field, doesn't assert the TypedArray is not RAB / GSAB
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "src/base/platform/wrappers.h"
|
||||
#include "src/handles/handles.h"
|
||||
#include "src/logging/runtime-call-stats-scope.h"
|
||||
#include "src/objects/contexts.h"
|
||||
#include "src/objects/contexts-inl.h"
|
||||
#include "src/objects/js-array-buffer-inl.h"
|
||||
#include "src/objects/js-regexp-inl.h"
|
||||
#include "src/objects/script.h"
|
||||
@ -1211,20 +1211,8 @@ void WebSnapshotSerializer::DiscoverElements(Handle<JSObject> object) {
|
||||
|
||||
void WebSnapshotSerializer::DiscoverArrayBuffer(
|
||||
Handle<JSArrayBuffer> array_buffer) {
|
||||
// TODO(v8:11525): Support SharedArrayBuffer.
|
||||
if (array_buffer->is_shared()) {
|
||||
Throw("Unsupported SharedArrayBuffer");
|
||||
return;
|
||||
}
|
||||
// TODO(v8:11525): Support detached ArrayBuffer.
|
||||
if (array_buffer->was_detached()) {
|
||||
Throw("Unsupported detached ArrayBuffer");
|
||||
return;
|
||||
}
|
||||
// TODO(v8:11525): Support resizable ArrayBuffer.
|
||||
if (array_buffer->is_resizable()) {
|
||||
Throw("Unsupported resizable ArrayBuffer");
|
||||
return;
|
||||
CHECK_EQ(array_buffer->GetByteLength(), 0);
|
||||
}
|
||||
uint32_t id;
|
||||
if (InsertIntoIndexMap(array_buffer_ids_, *array_buffer, id)) {
|
||||
@ -1639,40 +1627,91 @@ void WebSnapshotSerializer::SerializeElements(Handle<JSObject> object,
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t WebSnapshotSerializerDeserializer::ArrayBufferKindToFlags(
|
||||
Handle<JSArrayBuffer> array_buffer) {
|
||||
return DetachedBitField::encode(array_buffer->was_detached()) |
|
||||
SharedBitField::encode(array_buffer->is_shared()) |
|
||||
ResizableBitField::encode(array_buffer->is_resizable());
|
||||
}
|
||||
|
||||
// Format (serialized array buffer):
|
||||
// - Length
|
||||
// - ArrayBufferFlags, including was_detached, is_shared and is_resizable.
|
||||
// - Byte length
|
||||
// - if is_resizable
|
||||
// - Max byte length
|
||||
// - Raw bytes
|
||||
void WebSnapshotSerializer::SerializeArrayBuffer(
|
||||
Handle<JSArrayBuffer> array_buffer) {
|
||||
size_t byte_length = array_buffer->byte_length();
|
||||
size_t byte_length = array_buffer->GetByteLength();
|
||||
if (byte_length > std::numeric_limits<uint32_t>::max()) {
|
||||
Throw("Too large array buffer");
|
||||
return;
|
||||
}
|
||||
array_buffer_serializer_.WriteUint32(ArrayBufferKindToFlags(array_buffer));
|
||||
|
||||
array_buffer_serializer_.WriteUint32(static_cast<uint32_t>(byte_length));
|
||||
if (array_buffer->is_resizable()) {
|
||||
size_t max_byte_length = array_buffer->max_byte_length();
|
||||
if (max_byte_length > std::numeric_limits<uint32_t>::max()) {
|
||||
Throw("Too large resizable array buffer");
|
||||
return;
|
||||
}
|
||||
array_buffer_serializer_.WriteUint32(
|
||||
static_cast<uint32_t>(array_buffer->max_byte_length()));
|
||||
}
|
||||
array_buffer_serializer_.WriteRawBytes(array_buffer->backing_store(),
|
||||
byte_length);
|
||||
}
|
||||
|
||||
uint32_t WebSnapshotSerializerDeserializer::ArrayBufferViewKindToFlags(
|
||||
Handle<JSArrayBufferView> array_buffer_view) {
|
||||
return LengthTrackingBitField::encode(
|
||||
array_buffer_view->is_length_tracking());
|
||||
}
|
||||
|
||||
// static
|
||||
ExternalArrayType
|
||||
WebSnapshotSerializerDeserializer::TypedArrayTypeToExternalArrayType(
|
||||
TypedArrayType type) {
|
||||
switch (type) {
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
||||
case k##Type##Array: \
|
||||
return kExternal##Type##Array;
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// static
|
||||
WebSnapshotSerializerDeserializer::TypedArrayType
|
||||
WebSnapshotSerializerDeserializer::ExternalArrayTypeToTypedArrayType(
|
||||
ExternalArrayType type) {
|
||||
switch (type) {
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
||||
case kExternal##Type##Array: \
|
||||
return TypedArrayType::k##Type##Array;
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// Format (serialized typed array):
|
||||
// - TypedArrayType
|
||||
// - Serialized ArrayBuffer
|
||||
// - ArrayBufferViewFlags, including is_length_tracking
|
||||
// - Byte offset
|
||||
// - Byte length
|
||||
// - If not is_length_tracking
|
||||
// - Byte length
|
||||
void WebSnapshotSerializer::SerializeTypedArray(
|
||||
Handle<JSTypedArray> typed_array) {
|
||||
TypedArrayType typed_array_type = TypedArrayType::kUint8Array;
|
||||
switch (typed_array->type()) {
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
||||
case kExternal##Type##Array: \
|
||||
typed_array_type = TypedArrayType::k##Type##Array; \
|
||||
break;
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
}
|
||||
TypedArrayType typed_array_type =
|
||||
ExternalArrayTypeToTypedArrayType(typed_array->type());
|
||||
typed_array_serializer_.WriteUint32(typed_array_type);
|
||||
WriteValue(typed_array->GetBuffer(), typed_array_serializer_);
|
||||
// TODO(v8:11525): Implement WriteByte.
|
||||
typed_array_serializer_.WriteUint32(ArrayBufferViewKindToFlags(typed_array));
|
||||
if (typed_array->byte_offset() > std::numeric_limits<uint32_t>::max()) {
|
||||
Throw("Too large byte offset in TypedArray");
|
||||
return;
|
||||
@ -1683,9 +1722,10 @@ void WebSnapshotSerializer::SerializeTypedArray(
|
||||
Throw("Too large byte length in TypedArray");
|
||||
return;
|
||||
}
|
||||
typed_array_serializer_.WriteUint32(
|
||||
static_cast<uint32_t>(typed_array->byte_length()));
|
||||
// TODO(v8:11525): Serialize the bit field in a browser-independent way.
|
||||
if (!typed_array->is_length_tracking()) {
|
||||
typed_array_serializer_.WriteUint32(
|
||||
static_cast<uint32_t>(typed_array->byte_length()));
|
||||
}
|
||||
}
|
||||
|
||||
// Format (serialized export):
|
||||
@ -3245,21 +3285,83 @@ void WebSnapshotDeserializer::DeserializeArrayBuffers() {
|
||||
array_buffers_ = *array_buffers_handle_;
|
||||
for (; current_array_buffer_count_ < array_buffer_count_;
|
||||
++current_array_buffer_count_) {
|
||||
uint32_t flags;
|
||||
uint32_t byte_length;
|
||||
if (!deserializer_->ReadUint32(&byte_length) ||
|
||||
if (!deserializer_->ReadUint32(&flags) ||
|
||||
!deserializer_->ReadUint32(&byte_length) ||
|
||||
byte_length > static_cast<size_t>(deserializer_->end_ -
|
||||
deserializer_->position_)) {
|
||||
Throw("Malformed array buffer");
|
||||
return;
|
||||
}
|
||||
MaybeHandle<JSArrayBuffer> result =
|
||||
isolate_->factory()->NewJSArrayBufferAndBackingStore(
|
||||
byte_length, InitializedFlag::kUninitialized);
|
||||
Handle<JSArrayBuffer> array_buffer;
|
||||
if (!result.ToHandle(&array_buffer)) {
|
||||
Throw("Create array buffer failed");
|
||||
|
||||
uint32_t mask = DetachedBitField::kMask | SharedBitField::kMask |
|
||||
ResizableBitField::kMask;
|
||||
if ((flags | mask) != mask) {
|
||||
Throw("Malformed array buffer");
|
||||
return;
|
||||
}
|
||||
bool was_detached = DetachedBitField::decode(flags);
|
||||
CHECK_IMPLIES(was_detached, (byte_length == 0));
|
||||
SharedFlag shared = SharedBitField::decode(flags) ? SharedFlag::kShared
|
||||
: SharedFlag::kNotShared;
|
||||
CHECK_IMPLIES(was_detached, (shared == SharedFlag::kNotShared));
|
||||
ResizableFlag resizable = ResizableBitField::decode(flags)
|
||||
? ResizableFlag::kResizable
|
||||
: ResizableFlag::kNotResizable;
|
||||
uint32_t max_byte_length = byte_length;
|
||||
if (resizable == ResizableFlag::kResizable) {
|
||||
if (!deserializer_->ReadUint32(&max_byte_length)) {
|
||||
Throw("Malformed array buffer");
|
||||
return;
|
||||
}
|
||||
CHECK_GE(max_byte_length, byte_length);
|
||||
}
|
||||
|
||||
Handle<Map> map;
|
||||
if (shared == SharedFlag::kNotShared) {
|
||||
map = handle(
|
||||
isolate_->raw_native_context().array_buffer_fun().initial_map(),
|
||||
isolate_);
|
||||
} else {
|
||||
map = handle(isolate_->raw_native_context()
|
||||
.shared_array_buffer_fun()
|
||||
.initial_map(),
|
||||
isolate_);
|
||||
}
|
||||
Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(
|
||||
isolate_->factory()->NewJSObjectFromMap(map, AllocationType::kYoung));
|
||||
array_buffer->Setup(shared, resizable, nullptr);
|
||||
|
||||
std::unique_ptr<BackingStore> backing_store;
|
||||
if (was_detached) {
|
||||
array_buffer->set_was_detached(true);
|
||||
} else {
|
||||
if (resizable == ResizableFlag::kNotResizable) {
|
||||
backing_store = BackingStore::Allocate(isolate_, byte_length, shared,
|
||||
InitializedFlag::kUninitialized);
|
||||
} else {
|
||||
size_t page_size, initial_pages, max_pages;
|
||||
if (JSArrayBuffer::GetResizableBackingStorePageConfiguration(
|
||||
isolate_, byte_length, max_byte_length, kThrowOnError,
|
||||
&page_size, &initial_pages, &max_pages)
|
||||
.IsNothing()) {
|
||||
Throw("Create array buffer failed");
|
||||
return;
|
||||
}
|
||||
backing_store = BackingStore::TryAllocateAndPartiallyCommitMemory(
|
||||
isolate_, byte_length, max_byte_length, page_size, initial_pages,
|
||||
max_pages, false, shared);
|
||||
}
|
||||
if (!backing_store) {
|
||||
Throw("Create array buffer failed");
|
||||
return;
|
||||
}
|
||||
array_buffer->Attach(std::move(backing_store));
|
||||
}
|
||||
|
||||
array_buffer->set_max_byte_length(max_byte_length);
|
||||
|
||||
if (byte_length > 0) {
|
||||
memcpy(array_buffer->backing_store(), deserializer_->position_,
|
||||
byte_length);
|
||||
@ -3291,36 +3393,80 @@ void WebSnapshotDeserializer::DeserializeTypedArrays() {
|
||||
Handle<JSArrayBuffer> array_buffer(
|
||||
JSArrayBuffer::cast(std::get<0>(ReadValue())), isolate_);
|
||||
uint32_t byte_offset = 0;
|
||||
uint32_t flags = 0;
|
||||
if (!deserializer_->ReadUint32(&flags) ||
|
||||
!deserializer_->ReadUint32(&byte_offset)) {
|
||||
Throw("Malformed typed array");
|
||||
return;
|
||||
}
|
||||
size_t element_size = 0;
|
||||
ElementsKind element_kind = UINT8_ELEMENTS;
|
||||
JSTypedArray::ForFixedTypedArray(
|
||||
TypedArrayTypeToExternalArrayType(
|
||||
static_cast<TypedArrayType>(typed_array_type)),
|
||||
&element_size, &element_kind);
|
||||
|
||||
Handle<Map> map(
|
||||
isolate_->raw_native_context().TypedArrayElementsKindToCtorMap(
|
||||
element_kind),
|
||||
isolate_);
|
||||
uint32_t mask = LengthTrackingBitField::kMask;
|
||||
if ((flags | mask) != mask) {
|
||||
Throw("Malformed typed array");
|
||||
return;
|
||||
}
|
||||
|
||||
if (byte_offset % element_size != 0) {
|
||||
Throw("Malformed typed array");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t byte_length = 0;
|
||||
if (!deserializer_->ReadUint32(&byte_offset) ||
|
||||
!deserializer_->ReadUint32(&byte_length)) {
|
||||
Throw("Malformed typed array");
|
||||
return;
|
||||
size_t length = 0;
|
||||
bool is_length_tracking = LengthTrackingBitField::decode(flags);
|
||||
|
||||
if (is_length_tracking) {
|
||||
CHECK(array_buffer->is_resizable());
|
||||
} else {
|
||||
if (!deserializer_->ReadUint32(&byte_length)) {
|
||||
Throw("Malformed typed array");
|
||||
return;
|
||||
}
|
||||
if (byte_length % element_size != 0) {
|
||||
Throw("Malformed typed array");
|
||||
return;
|
||||
}
|
||||
length = byte_length / element_size;
|
||||
if (length > JSTypedArray::kMaxLength) {
|
||||
Throw("Too large typed array");
|
||||
return;
|
||||
}
|
||||
}
|
||||
ExternalArrayType external_array_type = kExternalInt8Array;
|
||||
unsigned element_size = 0;
|
||||
switch (static_cast<TypedArrayType>(typed_array_type)) {
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
||||
case TypedArrayType::k##Type##Array: \
|
||||
external_array_type = kExternal##Type##Array; \
|
||||
element_size = sizeof(ctype); \
|
||||
break;
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
|
||||
bool rabGsab = array_buffer->is_resizable() &&
|
||||
(!array_buffer->is_shared() || is_length_tracking);
|
||||
if (rabGsab) {
|
||||
map = handle(
|
||||
isolate_->raw_native_context().TypedArrayElementsKindToRabGsabCtorMap(
|
||||
element_kind),
|
||||
isolate_);
|
||||
}
|
||||
if (element_size == 0 || byte_offset % element_size != 0 ||
|
||||
byte_length % element_size != 0) {
|
||||
Throw("Malformed typed array");
|
||||
return;
|
||||
|
||||
Handle<JSTypedArray> typed_array =
|
||||
Handle<JSTypedArray>::cast(factory()->NewJSArrayBufferView(
|
||||
map, factory()->empty_byte_array(), array_buffer, byte_offset,
|
||||
byte_length));
|
||||
|
||||
{
|
||||
DisallowGarbageCollection no_gc;
|
||||
JSTypedArray raw = *typed_array;
|
||||
raw.set_length(length);
|
||||
raw.SetOffHeapDataPtr(isolate_, array_buffer->backing_store(),
|
||||
byte_offset);
|
||||
raw.set_is_length_tracking(is_length_tracking);
|
||||
raw.set_is_backed_by_rab(array_buffer->is_resizable() &&
|
||||
!array_buffer->is_shared());
|
||||
}
|
||||
size_t length = byte_length / element_size;
|
||||
if (length > JSTypedArray::kMaxLength) {
|
||||
Throw("Too large TypedArray");
|
||||
return;
|
||||
}
|
||||
// TODO(v8:11525): Set the bit_field for typed_array correctly.
|
||||
Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray(
|
||||
external_array_type, array_buffer, byte_offset, length);
|
||||
|
||||
typed_arrays_.set(static_cast<int>(current_typed_array_count_),
|
||||
*typed_array);
|
||||
|
@ -85,6 +85,11 @@ class WebSnapshotSerializerDeserializer {
|
||||
kBigUint64Array,
|
||||
};
|
||||
|
||||
static inline ExternalArrayType TypedArrayTypeToExternalArrayType(
|
||||
TypedArrayType type);
|
||||
static inline TypedArrayType ExternalArrayTypeToTypedArrayType(
|
||||
ExternalArrayType type);
|
||||
|
||||
static constexpr uint8_t kMagicNumber[4] = {'+', '+', '+', ';'};
|
||||
|
||||
enum ContextType : uint8_t { FUNCTION, BLOCK };
|
||||
@ -100,6 +105,11 @@ class WebSnapshotSerializerDeserializer {
|
||||
uint32_t AttributesToFlags(PropertyDetails details);
|
||||
PropertyAttributes FlagsToAttributes(uint32_t flags);
|
||||
|
||||
uint32_t ArrayBufferViewKindToFlags(
|
||||
Handle<JSArrayBufferView> array_buffer_view);
|
||||
|
||||
uint32_t ArrayBufferKindToFlags(Handle<JSArrayBuffer> array_buffer);
|
||||
|
||||
// The maximum count of items for each value type (strings, objects etc.)
|
||||
static constexpr uint32_t kMaxItemCount =
|
||||
static_cast<uint32_t>(FixedArray::kMaxLength - 1);
|
||||
@ -123,6 +133,22 @@ class WebSnapshotSerializerDeserializer {
|
||||
Isolate* isolate_;
|
||||
const char* error_message_ = nullptr;
|
||||
|
||||
// Encode JSArrayBufferFlags, including was_detached, is_shared, is_resizable.
|
||||
// DetachedBitField indicates whether the ArrayBuffer was detached.
|
||||
using DetachedBitField = base::BitField<bool, 0, 1>;
|
||||
// SharedBitField indicates whether the ArrayBuffer is SharedArrayBuffer.
|
||||
using SharedBitField = DetachedBitField::Next<bool, 1>;
|
||||
// ResizableBitField indicates whether the ArrayBuffer is ResizableArrayBuffer
|
||||
// or GrowableSharedArrayBuffer.
|
||||
using ResizableBitField = SharedBitField::Next<bool, 1>;
|
||||
|
||||
// Encode JSArrayBufferViewFlags, including is_length_tracking, see
|
||||
// https://github.com/tc39/proposal-resizablearraybuffer.
|
||||
// LengthTrackingBitField indicates whether the ArrayBufferView should track
|
||||
// the length of the backing buffer, that is whether the ArrayBufferView is
|
||||
// constructed without the specified length argument.
|
||||
using LengthTrackingBitField = base::BitField<bool, 0, 1>;
|
||||
|
||||
private:
|
||||
WebSnapshotSerializerDeserializer(const WebSnapshotSerializerDeserializer&) =
|
||||
delete;
|
||||
|
85
test/mjsunit/web-snapshot/web-snapshot-array-buffer.js
Normal file
85
test/mjsunit/web-snapshot/web-snapshot-array-buffer.js
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-d8-web-snapshot-api --allow-natives-syntax --harmony-rab-gsab
|
||||
|
||||
'use strict';
|
||||
|
||||
d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
|
||||
|
||||
(function TestSharedArrayBuffer() {
|
||||
function createObjects() {
|
||||
const growableArrayBuffer = new SharedArrayBuffer(5, { maxByteLength: 10 });
|
||||
globalThis.growableArrayBuffer = growableArrayBuffer;
|
||||
const array1 = new Uint8Array(growableArrayBuffer);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
array1[i] = i;
|
||||
}
|
||||
|
||||
const arrayBuffer = new SharedArrayBuffer(5);
|
||||
globalThis.arrayBuffer = arrayBuffer;
|
||||
const array2 = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
array2[i] = i;
|
||||
}
|
||||
}
|
||||
const { growableArrayBuffer, arrayBuffer } = takeAndUseWebSnapshot(createObjects, ['growableArrayBuffer', 'arrayBuffer']);
|
||||
assertEquals(growableArrayBuffer.byteLength, 5);
|
||||
assertEquals(growableArrayBuffer.maxByteLength, 10);
|
||||
assertTrue(growableArrayBuffer.growable);
|
||||
const array1 = new Uint8Array(growableArrayBuffer);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
assertEquals(array1[i], i);
|
||||
}
|
||||
|
||||
assertEquals(arrayBuffer.byteLength, 5);
|
||||
assertEquals(arrayBuffer.maxByteLength, 5);
|
||||
assertFalse(arrayBuffer.growable, false);
|
||||
const array2 = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
assertEquals(array2[i], i);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TestArrayBuffer() {
|
||||
function createObjects() {
|
||||
const resizableArrayBuffer = new ArrayBuffer(5, {maxByteLength: 10});
|
||||
globalThis.resizableArrayBuffer = resizableArrayBuffer;
|
||||
const array1 = new Uint8Array(resizableArrayBuffer);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
array1[i] = i;
|
||||
}
|
||||
|
||||
const arrayBuffer = new ArrayBuffer(5);
|
||||
globalThis.arrayBuffer = arrayBuffer;
|
||||
const array2 = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
array2[i] = i;
|
||||
}
|
||||
|
||||
const detachedArrayBuffer = new ArrayBuffer(5);
|
||||
%ArrayBufferDetach(detachedArrayBuffer);
|
||||
globalThis.detachedArrayBuffer = detachedArrayBuffer;
|
||||
}
|
||||
const { resizableArrayBuffer, arrayBuffer, detachedArrayBuffer } = takeAndUseWebSnapshot(createObjects, ['resizableArrayBuffer', 'arrayBuffer', 'detachedArrayBuffer']);
|
||||
assertEquals(resizableArrayBuffer.byteLength, 5);
|
||||
assertEquals(resizableArrayBuffer.maxByteLength, 10);
|
||||
assertTrue(resizableArrayBuffer.resizable)
|
||||
const array1 = new Uint8Array(resizableArrayBuffer);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
assertEquals(array1[i], i);
|
||||
}
|
||||
|
||||
assertEquals(arrayBuffer.byteLength, 5);
|
||||
assertEquals(arrayBuffer.maxByteLength, 5);
|
||||
assertFalse(arrayBuffer.resizable)
|
||||
const array2 = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
assertEquals(array2[i], i);
|
||||
}
|
||||
|
||||
assertEquals(detachedArrayBuffer.byteLength, 0);
|
||||
assertEquals(detachedArrayBuffer.maxByteLength, 0);
|
||||
})()
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-d8-web-snapshot-api --allow-natives-syntax
|
||||
// Flags: --experimental-d8-web-snapshot-api --allow-natives-syntax --harmony-rab-gsab
|
||||
|
||||
'use strict';
|
||||
|
||||
@ -11,47 +11,47 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
(function TestTypedArray() {
|
||||
function createObjects() {
|
||||
const int8Array = new Int8Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
int8Array[i] = i;
|
||||
}
|
||||
const uint8Array = new Uint8Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
uint8Array[i] = i;
|
||||
}
|
||||
const uint8ClampedArray = new Uint8ClampedArray(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
uint8ClampedArray[i] = i;
|
||||
}
|
||||
const int16Array = new Int16Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
int16Array[i] = i;
|
||||
}
|
||||
const uint16Array = new Uint16Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
uint16Array[i] = i;
|
||||
}
|
||||
const int32Array = new Int32Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
int32Array[i] = i;
|
||||
}
|
||||
const uint32Array = new Uint32Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
uint32Array[i] = i;
|
||||
}
|
||||
const float32Array = new Float32Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
float32Array[i] = i + 0.2;
|
||||
}
|
||||
const float64Array = new Float64Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
float64Array[i] = i + 0.2;
|
||||
}
|
||||
const bigInt64Array = new BigInt64Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bigInt64Array[i] = BigInt(i);
|
||||
}
|
||||
const bigUint64Array = new BigUint64Array(3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bigUint64Array[i] = BigInt(i);
|
||||
}
|
||||
globalThis.int8Array = int8Array;
|
||||
@ -65,72 +65,90 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
globalThis.float64Array = float64Array;
|
||||
globalThis.bigInt64Array = bigInt64Array;
|
||||
globalThis.bigUint64Array = bigUint64Array;
|
||||
|
||||
}
|
||||
const { int8Array, uint8Array, uint8ClampedArray, int16Array, uint16Array,
|
||||
int32Array, uint32Array, float32Array, float64Array, bigInt64Array, bigUint64Array } = takeAndUseWebSnapshot(createObjects, [
|
||||
'int8Array', 'uint8Array', 'uint8ClampedArray', 'int16Array', 'uint16Array',
|
||||
'int32Array', 'uint32Array', 'float32Array', 'float64Array', 'bigInt64Array',
|
||||
'bigUint64Array'
|
||||
]);
|
||||
const {
|
||||
int8Array,
|
||||
uint8Array,
|
||||
uint8ClampedArray,
|
||||
int16Array,
|
||||
uint16Array,
|
||||
int32Array,
|
||||
uint32Array,
|
||||
float32Array,
|
||||
float64Array,
|
||||
bigInt64Array,
|
||||
bigUint64Array,
|
||||
} =
|
||||
takeAndUseWebSnapshot(createObjects, [
|
||||
'int8Array',
|
||||
'uint8Array',
|
||||
'uint8ClampedArray',
|
||||
'int16Array',
|
||||
'uint16Array',
|
||||
'int32Array',
|
||||
'uint32Array',
|
||||
'float32Array',
|
||||
'float64Array',
|
||||
'bigInt64Array',
|
||||
'bigUint64Array',
|
||||
]);
|
||||
assertNotSame(globalThis.int8Array, int8Array);
|
||||
assertEquals(int8Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(int8Array[i], i);
|
||||
}
|
||||
assertNotSame(globalThis.uint8Array, uint8Array);
|
||||
assertEquals(uint8Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(uint8Array[i], i);
|
||||
}
|
||||
assertNotSame(globalThis.uint8ClampedArray, uint8ClampedArray);
|
||||
assertEquals(uint8ClampedArray.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(uint8ClampedArray[i], i);
|
||||
}
|
||||
assertNotSame(globalThis.int16Array, int16Array);
|
||||
assertEquals(int16Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(int16Array[i], i);
|
||||
}
|
||||
assertNotSame(globalThis.uint16Array, uint16Array);
|
||||
assertEquals(uint16Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(uint16Array[i], i);
|
||||
}
|
||||
assertNotSame(globalThis.int32Array, int32Array);
|
||||
assertEquals(int32Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(int32Array[i], i);
|
||||
}
|
||||
assertNotSame(globalThis.uint32Array, uint32Array);
|
||||
assertEquals(uint32Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(uint32Array[i], i);
|
||||
}
|
||||
assertNotSame(globalThis.float32Array, float32Array);
|
||||
assertEquals(float32Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEqualsDelta(float32Array[i], i + 0.2);
|
||||
}
|
||||
assertNotSame(globalThis.float64Array, float64Array);
|
||||
assertEquals(float64Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEqualsDelta(float64Array[i], i + 0.2);
|
||||
}
|
||||
assertNotSame(globalThis.bigInt64Array, bigInt64Array);
|
||||
assertEquals(bigInt64Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(bigInt64Array[i], BigInt(i));
|
||||
}
|
||||
assertNotSame(globalThis.bigUint64Array, bigUint64Array);
|
||||
assertEquals(bigUint64Array.length, 3);
|
||||
for (let i = 0; i < 3; i++){
|
||||
for (let i = 0; i < 3; i++) {
|
||||
assertEquals(bigUint64Array[i], BigInt(i));
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
(function TestInt8Array() {
|
||||
function createObjects() {
|
||||
const array = new Int8Array([-129, -128, 1, 127, 128]);
|
||||
@ -138,7 +156,10 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
const array2 = new Int8Array(array.buffer, 1, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], 127);
|
||||
assertEquals(array[1], -128);
|
||||
@ -158,7 +179,10 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
const array2 = new Uint8Array(array.buffer, 1, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], 255);
|
||||
assertEquals(array[1], 0);
|
||||
@ -173,12 +197,15 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
|
||||
(function TestUint8ClampedArray() {
|
||||
function createObjects() {
|
||||
const array = new Uint8ClampedArray([-1,0, 2,255, 256]);
|
||||
const array = new Uint8ClampedArray([-1, 0, 2, 255, 256]);
|
||||
globalThis.array = array;
|
||||
const array2 = new Uint8ClampedArray(array.buffer, 1, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], 0);
|
||||
assertEquals(array[1], 0);
|
||||
@ -198,7 +225,10 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
const array2 = new Int16Array(array.buffer, 2, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], 32767);
|
||||
assertEquals(array[1], -32768);
|
||||
@ -213,12 +243,15 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
|
||||
(function TestUint16Array() {
|
||||
function createObjects() {
|
||||
const array = new Uint16Array([-1,0, 2,65535, 65536]);
|
||||
const array = new Uint16Array([-1, 0, 2, 65535, 65536]);
|
||||
globalThis.array = array;
|
||||
const array2 = new Uint16Array(array.buffer, 2, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], 65535);
|
||||
assertEquals(array[1], 0);
|
||||
@ -233,12 +266,21 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
|
||||
(function TestInt32Array() {
|
||||
function createObjects() {
|
||||
const array = new Int32Array([-2147483649, -2147483648, 1, 2147483647, 2147483648]);
|
||||
const array = new Int32Array([
|
||||
-2147483649,
|
||||
-2147483648,
|
||||
1,
|
||||
2147483647,
|
||||
2147483648,
|
||||
]);
|
||||
globalThis.array = array;
|
||||
const array2 = new Int32Array(array.buffer, 4, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], 2147483647);
|
||||
assertEquals(array[1], -2147483648);
|
||||
@ -253,12 +295,15 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
|
||||
(function TestUint32Array() {
|
||||
function createObjects() {
|
||||
const array = new Uint32Array([-1,0, 2,4294967295, 4294967296]);
|
||||
const array = new Uint32Array([-1, 0, 2, 4294967295, 4294967296]);
|
||||
globalThis.array = array;
|
||||
const array2 = new Uint32Array(array.buffer, 4, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], 4294967295);
|
||||
assertEquals(array[1], 0);
|
||||
@ -273,17 +318,26 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
|
||||
(function TestBigInt64Array() {
|
||||
function createObjects() {
|
||||
const array = new BigInt64Array([BigInt(-(2**63))-1n, BigInt(-(2**63)), 1n, BigInt((2**63)) - 1n, BigInt((2**63))]);
|
||||
const array = new BigInt64Array([
|
||||
BigInt(-(2 ** 63)) - 1n,
|
||||
BigInt(-(2 ** 63)),
|
||||
1n,
|
||||
BigInt(2 ** 63) - 1n,
|
||||
BigInt(2 ** 63),
|
||||
]);
|
||||
globalThis.array = array;
|
||||
const array2 = new BigInt64Array(array.buffer, 8, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], BigInt((2**63)) - 1n);
|
||||
assertEquals(array[1], BigInt(-(2**63)));
|
||||
assertEquals(array[0], BigInt(2 ** 63) - 1n);
|
||||
assertEquals(array[1], BigInt(-(2 ** 63)));
|
||||
assertEquals(array[2], 1n);
|
||||
assertEquals(array[3], BigInt((2**63)) - 1n);
|
||||
assertEquals(array[3], BigInt(2 ** 63) - 1n);
|
||||
assertEquals(array[4], BigInt(-(2 ** 63)));
|
||||
assertSame(array.buffer, array2.buffer);
|
||||
assertEquals(array2.length, 2);
|
||||
@ -293,20 +347,93 @@ d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
|
||||
|
||||
(function TestBigUint32Array() {
|
||||
function createObjects() {
|
||||
const array = new BigUint64Array([-1n, 0n, 2n,BigInt(2**64)-1n, BigInt(2**64)]);
|
||||
const array = new BigUint64Array([
|
||||
-1n,
|
||||
0n,
|
||||
2n,
|
||||
BigInt(2 ** 64) - 1n,
|
||||
BigInt(2 ** 64),
|
||||
]);
|
||||
globalThis.array = array;
|
||||
const array2 = new BigUint64Array(array.buffer, 8, 2);
|
||||
globalThis.array2 = array2;
|
||||
}
|
||||
const { array, array2 } = takeAndUseWebSnapshot(createObjects, ['array', 'array2']);
|
||||
const {array, array2} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
]);
|
||||
assertEquals(array.length, 5);
|
||||
assertEquals(array[0], BigInt(2**64)-1n);
|
||||
assertEquals(array[0], BigInt(2 ** 64) - 1n);
|
||||
assertEquals(array[1], 0n);
|
||||
assertEquals(array[2], 2n);
|
||||
assertEquals(array[3], BigInt(2**64)-1n);
|
||||
assertEquals(array[3], BigInt(2 ** 64) - 1n);
|
||||
assertEquals(array[4], 0n);
|
||||
assertSame(array.buffer, array2.buffer);
|
||||
assertEquals(array2.length, 2);
|
||||
assertEquals(array2[0], array[1]);
|
||||
assertEquals(array2[1], array[2]);
|
||||
})();
|
||||
|
||||
(function TestResizableTypedArray() {
|
||||
function createObjects() {
|
||||
let resizableArrayBuffer = new ArrayBuffer(1024, {
|
||||
maxByteLength: 1024 * 2,
|
||||
});
|
||||
// 0 offset, auto length
|
||||
let array = new Uint32Array(resizableArrayBuffer);
|
||||
globalThis.array = array;
|
||||
|
||||
// Non-0 offset, auto length
|
||||
let array2 = new Uint32Array(resizableArrayBuffer, 256);
|
||||
globalThis.array2 = array2;
|
||||
|
||||
// Non-0 offset, fixed length
|
||||
let array3 = new Uint32Array(resizableArrayBuffer, 128, 4);
|
||||
globalThis.array3 = array3;
|
||||
}
|
||||
const {array, array2, array3} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
'array3',
|
||||
]);
|
||||
assertTrue(array.buffer.resizable);
|
||||
assertEquals(array.length, 256); // (1024 - 0) / 4
|
||||
assertEquals(array2.length, 192); // (1024 - 256) / 4
|
||||
assertEquals(array3.length, 4);
|
||||
array.buffer.resize(1024 * 2);
|
||||
assertEquals(array.length, 512); // (2048 - 0) / 4
|
||||
assertEquals(array2.length, 448); // (2048 - 256) / 4
|
||||
assertEquals(array3.length, 4);
|
||||
})();
|
||||
|
||||
(function TestGrowableTypedArray() {
|
||||
function createObjects() {
|
||||
let resizableArrayBuffer = new SharedArrayBuffer(1024, {
|
||||
maxByteLength: 1024 * 2,
|
||||
});
|
||||
// 0 offset, auto length
|
||||
let array = new Uint32Array(resizableArrayBuffer);
|
||||
globalThis.array = array;
|
||||
|
||||
// Non-0 offset, auto length
|
||||
let array2 = new Uint32Array(resizableArrayBuffer, 256);
|
||||
globalThis.array2 = array2;
|
||||
|
||||
// Non-0 offset, fixed length
|
||||
let array3 = new Uint32Array(resizableArrayBuffer, 128, 4);
|
||||
globalThis.array3 = array3;
|
||||
}
|
||||
const {array, array2, array3} = takeAndUseWebSnapshot(createObjects, [
|
||||
'array',
|
||||
'array2',
|
||||
'array3',
|
||||
]);
|
||||
assertTrue(array.buffer.growable);
|
||||
assertEquals(array.length, 256); // (1024 - 0) / 4
|
||||
assertEquals(array2.length, 192); // (1024 - 256) / 4
|
||||
assertEquals(array3.length, 4);
|
||||
array.buffer.grow(1024 * 2);
|
||||
assertEquals(array.length, 512); // (2048 - 0) / 4
|
||||
assertEquals(array2.length, 448); // (2048 - 256) / 4
|
||||
assertEquals(array3.length, 4);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user