Commit 21cfbf04 authored by Shu-yu Guo's avatar Shu-yu Guo Committed by V8 LUCI CQ

[rab/gsab] Support RAB/GSABs in context snapshot

Bug: v8:11111, v8:12731, v8:12742
Change-Id: I2679c0e64faca25a2c16e15fd3a5c727eb941c92
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3551894Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79662}
parent b8b90135
...@@ -37,16 +37,6 @@ namespace internal { ...@@ -37,16 +37,6 @@ namespace internal {
namespace { namespace {
bool RoundUpToPageSize(size_t byte_length, size_t page_size,
size_t max_allowed_byte_length, size_t* pages) {
size_t bytes_wanted = RoundUp(byte_length, page_size);
if (bytes_wanted > max_allowed_byte_length) {
return false;
}
*pages = bytes_wanted / page_size;
return true;
}
Object ConstructBuffer(Isolate* isolate, Handle<JSFunction> target, Object ConstructBuffer(Isolate* isolate, Handle<JSFunction> target,
Handle<JSReceiver> new_target, Handle<Object> length, Handle<JSReceiver> new_target, Handle<Object> length,
Handle<Object> max_length, InitializedFlag initialized) { Handle<Object> max_length, InitializedFlag initialized) {
...@@ -91,21 +81,12 @@ Object ConstructBuffer(Isolate* isolate, Handle<JSFunction> target, ...@@ -91,21 +81,12 @@ Object ConstructBuffer(Isolate* isolate, Handle<JSFunction> target,
NewRangeError(MessageTemplate::kInvalidArrayBufferMaxLength)); NewRangeError(MessageTemplate::kInvalidArrayBufferMaxLength));
} }
size_t page_size = AllocatePageSize(); size_t page_size, initial_pages, max_pages;
size_t initial_pages; MAYBE_RETURN(JSArrayBuffer::GetResizableBackingStorePageConfiguration(
if (!RoundUpToPageSize(byte_length, page_size, isolate, byte_length, max_byte_length, kThrowOnError,
JSArrayBuffer::kMaxByteLength, &initial_pages)) { &page_size, &initial_pages, &max_pages),
THROW_NEW_ERROR_RETURN_FAILURE( ReadOnlyRoots(isolate).exception());
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
}
size_t max_pages;
if (!RoundUpToPageSize(max_byte_length, page_size,
JSArrayBuffer::kMaxByteLength, &max_pages)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewRangeError(MessageTemplate::kInvalidArrayBufferMaxLength));
}
constexpr bool kIsWasmMemory = false; constexpr bool kIsWasmMemory = false;
backing_store = BackingStore::TryAllocateAndPartiallyCommitMemory( backing_store = BackingStore::TryAllocateAndPartiallyCommitMemory(
isolate, byte_length, max_byte_length, page_size, initial_pages, isolate, byte_length, max_byte_length, page_size, initial_pages,
......
...@@ -147,6 +147,36 @@ size_t JSArrayBuffer::GsabByteLength(Isolate* isolate, ...@@ -147,6 +147,36 @@ size_t JSArrayBuffer::GsabByteLength(Isolate* isolate,
return buffer.GetBackingStore()->byte_length(std::memory_order_seq_cst); return buffer.GetBackingStore()->byte_length(std::memory_order_seq_cst);
} }
// static
Maybe<bool> JSArrayBuffer::GetResizableBackingStorePageConfiguration(
Isolate* isolate, size_t byte_length, size_t max_byte_length,
ShouldThrow should_throw, size_t* page_size, size_t* initial_pages,
size_t* max_pages) {
DCHECK_NOT_NULL(page_size);
DCHECK_NOT_NULL(initial_pages);
DCHECK_NOT_NULL(max_pages);
*page_size = AllocatePageSize();
if (!RoundUpToPageSize(byte_length, *page_size, JSArrayBuffer::kMaxByteLength,
initial_pages)) {
if (should_throw == kDontThrow) return Nothing<bool>();
THROW_NEW_ERROR_RETURN_VALUE(
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength),
Nothing<bool>());
}
if (!RoundUpToPageSize(max_byte_length, *page_size,
JSArrayBuffer::kMaxByteLength, max_pages)) {
if (should_throw == kDontThrow) return Nothing<bool>();
THROW_NEW_ERROR_RETURN_VALUE(
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferMaxLength),
Nothing<bool>());
}
return Just(true);
}
ArrayBufferExtension* JSArrayBuffer::EnsureExtension() { ArrayBufferExtension* JSArrayBuffer::EnsureExtension() {
ArrayBufferExtension* extension = this->extension(); ArrayBufferExtension* extension = this->extension();
if (extension != nullptr) return extension; if (extension != nullptr) return extension;
......
...@@ -114,6 +114,11 @@ class JSArrayBuffer ...@@ -114,6 +114,11 @@ class JSArrayBuffer
static size_t GsabByteLength(Isolate* isolate, Address raw_array_buffer); static size_t GsabByteLength(Isolate* isolate, Address raw_array_buffer);
static Maybe<bool> GetResizableBackingStorePageConfiguration(
Isolate* isolate, size_t byte_length, size_t max_byte_length,
ShouldThrow should_throw, size_t* page_size, size_t* initial_pages,
size_t* max_pages);
// Allocates an ArrayBufferExtension for this array buffer, unless it is // Allocates an ArrayBufferExtension for this array buffer, unless it is
// already associated with an extension. // already associated with an extension.
ArrayBufferExtension* EnsureExtension(); ArrayBufferExtension* EnsureExtension();
......
...@@ -61,11 +61,13 @@ void ContextDeserializer::SetupOffHeapArrayBufferBackingStores() { ...@@ -61,11 +61,13 @@ void ContextDeserializer::SetupOffHeapArrayBufferBackingStores() {
for (Handle<JSArrayBuffer> buffer : new_off_heap_array_buffers()) { for (Handle<JSArrayBuffer> buffer : new_off_heap_array_buffers()) {
uint32_t store_index = buffer->GetBackingStoreRefForDeserialization(); uint32_t store_index = buffer->GetBackingStoreRefForDeserialization();
auto bs = backing_store(store_index); auto bs = backing_store(store_index);
// TODO(v8:11111): Support RAB / GSAB.
CHECK(!buffer->is_resizable());
SharedFlag shared = SharedFlag shared =
bs && bs->is_shared() ? SharedFlag::kShared : SharedFlag::kNotShared; bs && bs->is_shared() ? SharedFlag::kShared : SharedFlag::kNotShared;
buffer->Setup(shared, ResizableFlag::kNotResizable, bs); DCHECK_IMPLIES(bs, buffer->is_resizable() == bs->is_resizable());
ResizableFlag resizable = bs && bs->is_resizable()
? ResizableFlag::kResizable
: ResizableFlag::kNotResizable;
buffer->Setup(shared, resizable, bs);
} }
} }
......
...@@ -1160,11 +1160,28 @@ int Deserializer<IsolateT>::ReadSingleBytecodeData(byte data, ...@@ -1160,11 +1160,28 @@ int Deserializer<IsolateT>::ReadSingleBytecodeData(byte data,
return ReadRepeatedObject(slot_accessor, repeats); return ReadRepeatedObject(slot_accessor, repeats);
} }
case kOffHeapBackingStore: { case kOffHeapBackingStore:
case kOffHeapResizableBackingStore: {
int byte_length = source_.GetInt(); int byte_length = source_.GetInt();
std::unique_ptr<BackingStore> backing_store = BackingStore::Allocate( std::unique_ptr<BackingStore> backing_store;
main_thread_isolate(), byte_length, SharedFlag::kNotShared, if (data == kOffHeapBackingStore) {
InitializedFlag::kUninitialized); backing_store = BackingStore::Allocate(
main_thread_isolate(), byte_length, SharedFlag::kNotShared,
InitializedFlag::kUninitialized);
} else {
int max_byte_length = source_.GetInt();
size_t page_size, initial_pages, max_pages;
Maybe<bool> result =
JSArrayBuffer::GetResizableBackingStorePageConfiguration(
nullptr, byte_length, max_byte_length, kDontThrow, &page_size,
&initial_pages, &max_pages);
DCHECK(result.FromJust());
USE(result);
constexpr bool kIsWasmMemory = false;
backing_store = BackingStore::TryAllocateAndPartiallyCommitMemory(
main_thread_isolate(), byte_length, max_byte_length, page_size,
initial_pages, max_pages, kIsWasmMemory, SharedFlag::kNotShared);
}
CHECK_NOT_NULL(backing_store); CHECK_NOT_NULL(backing_store);
source_.CopyRaw(backing_store->buffer_start(), byte_length); source_.CopyRaw(backing_store->buffer_start(), byte_length);
backing_stores_.push_back(std::move(backing_store)); backing_stores_.push_back(std::move(backing_store));
......
...@@ -35,8 +35,8 @@ class SerializerDeserializer : public RootVisitor { ...@@ -35,8 +35,8 @@ class SerializerDeserializer : public RootVisitor {
// clang-format off // clang-format off
#define UNUSED_SERIALIZER_BYTE_CODES(V) \ #define UNUSED_SERIALIZER_BYTE_CODES(V) \
/* Free range 0x1d..0x1f */ \ /* Free range 0x1e..0x1f */ \
V(0x1d) V(0x1e) V(0x1f) \ V(0x1e) V(0x1f) \
/* Free range 0x20..0x2f */ \ /* Free range 0x20..0x2f */ \
V(0x20) V(0x21) V(0x22) V(0x23) V(0x24) V(0x25) V(0x26) V(0x27) \ V(0x20) V(0x21) V(0x22) V(0x23) V(0x24) V(0x25) V(0x26) V(0x27) \
V(0x28) V(0x29) V(0x2a) V(0x2b) V(0x2c) V(0x2d) V(0x2e) V(0x2f) \ V(0x28) V(0x29) V(0x2a) V(0x2b) V(0x2c) V(0x2d) V(0x2e) V(0x2f) \
...@@ -83,7 +83,7 @@ class SerializerDeserializer : public RootVisitor { ...@@ -83,7 +83,7 @@ class SerializerDeserializer : public RootVisitor {
enum Bytecode : byte { enum Bytecode : byte {
// //
// ---------- byte code range 0x00..0x1c ---------- // ---------- byte code range 0x00..0x1d ----------
// //
// 0x00..0x03 Allocate new object, in specified space. // 0x00..0x03 Allocate new object, in specified space.
...@@ -114,6 +114,7 @@ class SerializerDeserializer : public RootVisitor { ...@@ -114,6 +114,7 @@ class SerializerDeserializer : public RootVisitor {
kVariableRepeat, kVariableRepeat,
// Used for embedder-allocated backing stores for TypedArrays. // Used for embedder-allocated backing stores for TypedArrays.
kOffHeapBackingStore, kOffHeapBackingStore,
kOffHeapResizableBackingStore,
// Used for embedder-provided serialization data for embedder fields. // Used for embedder-provided serialization data for embedder fields.
kEmbedderFieldsData, kEmbedderFieldsData,
// Raw data of variable length. // Raw data of variable length.
......
...@@ -474,14 +474,22 @@ void Serializer::ObjectSerializer::SerializePrologue(SnapshotSpace space, ...@@ -474,14 +474,22 @@ void Serializer::ObjectSerializer::SerializePrologue(SnapshotSpace space,
} }
uint32_t Serializer::ObjectSerializer::SerializeBackingStore( uint32_t Serializer::ObjectSerializer::SerializeBackingStore(
void* backing_store, int32_t byte_length) { void* backing_store, int32_t byte_length, Maybe<int32_t> max_byte_length) {
const SerializerReference* reference_ptr = const SerializerReference* reference_ptr =
serializer_->reference_map()->LookupBackingStore(backing_store); serializer_->reference_map()->LookupBackingStore(backing_store);
// Serialize the off-heap backing store. // Serialize the off-heap backing store.
if (!reference_ptr) { if (!reference_ptr) {
sink_->Put(kOffHeapBackingStore, "Off-heap backing store"); if (max_byte_length.IsJust()) {
sink_->Put(kOffHeapResizableBackingStore,
"Off-heap resizable backing store");
} else {
sink_->Put(kOffHeapBackingStore, "Off-heap backing store");
}
sink_->PutInt(byte_length, "length"); sink_->PutInt(byte_length, "length");
if (max_byte_length.IsJust()) {
sink_->PutInt(max_byte_length.FromJust(), "max length");
}
sink_->PutRaw(static_cast<byte*>(backing_store), byte_length, sink_->PutRaw(static_cast<byte*>(backing_store), byte_length,
"BackingStore"); "BackingStore");
DCHECK_NE(0, serializer_->seen_backing_stores_index_); DCHECK_NE(0, serializer_->seen_backing_stores_index_);
...@@ -504,9 +512,15 @@ void Serializer::ObjectSerializer::SerializeJSTypedArray() { ...@@ -504,9 +512,15 @@ void Serializer::ObjectSerializer::SerializeJSTypedArray() {
if (!typed_array->WasDetached()) { if (!typed_array->WasDetached()) {
// Explicitly serialize the backing store now. // Explicitly serialize the backing store now.
JSArrayBuffer buffer = JSArrayBuffer::cast(typed_array->buffer()); JSArrayBuffer buffer = JSArrayBuffer::cast(typed_array->buffer());
// We cannot store byte_length larger than int32 range in the snapshot. // We cannot store byte_length or max_byte_length larger than int32 range
// in the snapshot.
CHECK_LE(buffer.byte_length(), std::numeric_limits<int32_t>::max()); CHECK_LE(buffer.byte_length(), std::numeric_limits<int32_t>::max());
int32_t byte_length = static_cast<int32_t>(buffer.byte_length()); int32_t byte_length = static_cast<int32_t>(buffer.byte_length());
Maybe<int32_t> max_byte_length = Nothing<int32_t>();
if (buffer.is_resizable()) {
CHECK_LE(buffer.max_byte_length(), std::numeric_limits<int32_t>::max());
max_byte_length = Just(static_cast<int32_t>(buffer.max_byte_length()));
}
size_t byte_offset = typed_array->byte_offset(); size_t byte_offset = typed_array->byte_offset();
// We need to calculate the backing store from the data pointer // We need to calculate the backing store from the data pointer
...@@ -514,7 +528,8 @@ void Serializer::ObjectSerializer::SerializeJSTypedArray() { ...@@ -514,7 +528,8 @@ void Serializer::ObjectSerializer::SerializeJSTypedArray() {
void* backing_store = reinterpret_cast<void*>( void* backing_store = reinterpret_cast<void*>(
reinterpret_cast<Address>(typed_array->DataPtr()) - byte_offset); reinterpret_cast<Address>(typed_array->DataPtr()) - byte_offset);
uint32_t ref = SerializeBackingStore(backing_store, byte_length); uint32_t ref =
SerializeBackingStore(backing_store, byte_length, max_byte_length);
typed_array->SetExternalBackingStoreRefForSerialization(ref); typed_array->SetExternalBackingStoreRefForSerialization(ref);
} else { } else {
typed_array->SetExternalBackingStoreRefForSerialization(0); typed_array->SetExternalBackingStoreRefForSerialization(0);
...@@ -526,16 +541,23 @@ void Serializer::ObjectSerializer::SerializeJSTypedArray() { ...@@ -526,16 +541,23 @@ void Serializer::ObjectSerializer::SerializeJSTypedArray() {
void Serializer::ObjectSerializer::SerializeJSArrayBuffer() { void Serializer::ObjectSerializer::SerializeJSArrayBuffer() {
Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(object_); Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(object_);
void* backing_store = buffer->backing_store(); void* backing_store = buffer->backing_store();
// We cannot store byte_length larger than int32 range in the snapshot. // We cannot store byte_length or max_byte_length larger than int32 range in
// the snapshot.
CHECK_LE(buffer->byte_length(), std::numeric_limits<int32_t>::max()); CHECK_LE(buffer->byte_length(), std::numeric_limits<int32_t>::max());
int32_t byte_length = static_cast<int32_t>(buffer->byte_length()); int32_t byte_length = static_cast<int32_t>(buffer->byte_length());
Maybe<int32_t> max_byte_length = Nothing<int32_t>();
if (buffer->is_resizable()) {
CHECK_LE(buffer->max_byte_length(), std::numeric_limits<int32_t>::max());
max_byte_length = Just(static_cast<int32_t>(buffer->max_byte_length()));
}
ArrayBufferExtension* extension = buffer->extension(); ArrayBufferExtension* extension = buffer->extension();
// Only serialize non-empty backing stores. // Only serialize non-empty backing stores.
if (buffer->IsEmpty()) { if (buffer->IsEmpty()) {
buffer->SetBackingStoreRefForSerialization(kEmptyBackingStoreRefSentinel); buffer->SetBackingStoreRefForSerialization(kEmptyBackingStoreRefSentinel);
} else { } else {
uint32_t ref = SerializeBackingStore(backing_store, byte_length); uint32_t ref =
SerializeBackingStore(backing_store, byte_length, max_byte_length);
buffer->SetBackingStoreRefForSerialization(ref); buffer->SetBackingStoreRefForSerialization(ref);
// Ensure deterministic output by setting extension to null during // Ensure deterministic output by setting extension to null during
......
...@@ -470,7 +470,8 @@ class Serializer::ObjectSerializer : public ObjectVisitor { ...@@ -470,7 +470,8 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
ExternalPointerTag tag); ExternalPointerTag tag);
void OutputRawData(Address up_to); void OutputRawData(Address up_to);
void SerializeCode(Map map, int size); void SerializeCode(Map map, int size);
uint32_t SerializeBackingStore(void* backing_store, int32_t byte_length); uint32_t SerializeBackingStore(void* backing_store, int32_t byte_length,
Maybe<int32_t> max_byte_length);
void SerializeJSTypedArray(); void SerializeJSTypedArray();
void SerializeJSArrayBuffer(); void SerializeJSArrayBuffer();
void SerializeExternalString(); void SerializeExternalString();
......
...@@ -659,6 +659,16 @@ V8_INLINE void ZapCode(Address addr, size_t size_in_bytes) { ...@@ -659,6 +659,16 @@ V8_INLINE void ZapCode(Address addr, size_t size_in_bytes) {
std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes); std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes);
} }
inline bool RoundUpToPageSize(size_t byte_length, size_t page_size,
size_t max_allowed_byte_length, size_t* pages) {
size_t bytes_wanted = RoundUp(byte_length, page_size);
if (bytes_wanted > max_allowed_byte_length) {
return false;
}
*pages = bytes_wanted / page_size;
return true;
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -1464,11 +1464,6 @@ ...@@ -1464,11 +1464,6 @@
# Script referenced only through context-dependent SourceTextModule # Script referenced only through context-dependent SourceTextModule
# https://bugs.chromium.org/p/v8/issues/detail?id=11073 # https://bugs.chromium.org/p/v8/issues/detail?id=11073
'tools/processor': [SKIP], 'tools/processor': [SKIP],
# TODO(v8:11111) and
# https://bugs.chromium.org/p/v8/issues/detail?id=12731
'regress/regress-crbug-1306929': [SKIP],
# https://crbug.com/v8/12742
'regress/regress-crbug-1307310': [SKIP],
}], # variant == stress_snapshot and arch == x64 }], # variant == stress_snapshot and arch == x64
############################################################################## ##############################################################################
......
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