Skip to content

Commit 1faf6f4

Browse files
committed
src: snapshot Environment upon instantiation
This includes the initial Environment (without running bootstrap scripts) into the builtin snapshot PR-URL: #32984 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
1 parent f045387 commit 1faf6f4

16 files changed

+710
-164
lines changed

src/aliased_buffer.h

+57-9
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

66
#include <cinttypes>
7+
#include <iostream>
78
#include "util-inl.h"
89
#include "v8.h"
910

1011
namespace node {
1112

13+
typedef size_t AliasedBufferInfo;
14+
1215
/**
1316
* Do not use this class directly when creating instances of it - use the
1417
* Aliased*Array defined at the end of this file instead.
@@ -32,9 +35,15 @@ template <class NativeT,
3235
typename = std::enable_if_t<std::is_scalar<NativeT>::value>>
3336
class AliasedBufferBase {
3437
public:
35-
AliasedBufferBase(v8::Isolate* isolate, const size_t count)
36-
: isolate_(isolate), count_(count), byte_offset_(0) {
38+
AliasedBufferBase(v8::Isolate* isolate,
39+
const size_t count,
40+
const AliasedBufferInfo* info = nullptr)
41+
: isolate_(isolate), count_(count), byte_offset_(0), info_(info) {
3742
CHECK_GT(count, 0);
43+
if (info != nullptr) {
44+
// Will be deserialized later.
45+
return;
46+
}
3847
const v8::HandleScope handle_scope(isolate_);
3948
const size_t size_in_bytes =
4049
MultiplyWithOverflowCheck(sizeof(NativeT), count);
@@ -62,10 +71,17 @@ class AliasedBufferBase {
6271
v8::Isolate* isolate,
6372
const size_t byte_offset,
6473
const size_t count,
65-
const AliasedBufferBase<uint8_t, v8::Uint8Array>& backing_buffer)
66-
: isolate_(isolate), count_(count), byte_offset_(byte_offset) {
74+
const AliasedBufferBase<uint8_t, v8::Uint8Array>& backing_buffer,
75+
const AliasedBufferInfo* info = nullptr)
76+
: isolate_(isolate),
77+
count_(count),
78+
byte_offset_(byte_offset),
79+
info_(info) {
80+
if (info != nullptr) {
81+
// Will be deserialized later.
82+
return;
83+
}
6784
const v8::HandleScope handle_scope(isolate_);
68-
6985
v8::Local<v8::ArrayBuffer> ab = backing_buffer.GetArrayBuffer();
7086

7187
// validate that the byte_offset is aligned with sizeof(NativeT)
@@ -86,10 +102,33 @@ class AliasedBufferBase {
86102
count_(that.count_),
87103
byte_offset_(that.byte_offset_),
88104
buffer_(that.buffer_) {
105+
DCHECK_NULL(info_);
89106
js_array_ = v8::Global<V8T>(that.isolate_, that.GetJSArray());
90107
}
91108

109+
AliasedBufferInfo Serialize(v8::Local<v8::Context> context,
110+
v8::SnapshotCreator* creator) {
111+
DCHECK_NULL(info_);
112+
return creator->AddData(context, GetJSArray());
113+
}
114+
115+
inline void Deserialize(v8::Local<v8::Context> context) {
116+
DCHECK_NOT_NULL(info_);
117+
v8::Local<V8T> arr =
118+
context->GetDataFromSnapshotOnce<V8T>(*info_).ToLocalChecked();
119+
// These may not hold true for AliasedBuffers that have grown, so should
120+
// be removed when we expand the snapshot support.
121+
DCHECK_EQ(count_, arr->Length());
122+
DCHECK_EQ(byte_offset_, arr->ByteOffset());
123+
uint8_t* raw =
124+
static_cast<uint8_t*>(arr->Buffer()->GetBackingStore()->Data());
125+
buffer_ = reinterpret_cast<NativeT*>(raw + byte_offset_);
126+
js_array_.Reset(isolate_, arr);
127+
info_ = nullptr;
128+
}
129+
92130
AliasedBufferBase& operator=(AliasedBufferBase&& that) noexcept {
131+
DCHECK_NULL(info_);
93132
this->~AliasedBufferBase();
94133
isolate_ = that.isolate_;
95134
count_ = that.count_;
@@ -155,6 +194,7 @@ class AliasedBufferBase {
155194
* Get the underlying v8 TypedArray overlayed on top of the native buffer
156195
*/
157196
v8::Local<V8T> GetJSArray() const {
197+
DCHECK_NULL(info_);
158198
return js_array_.Get(isolate_);
159199
}
160200

@@ -171,6 +211,7 @@ class AliasedBufferBase {
171211
* through the GetValue/SetValue/operator[] methods
172212
*/
173213
inline const NativeT* GetNativeBuffer() const {
214+
DCHECK_NULL(info_);
174215
return buffer_;
175216
}
176217

@@ -186,13 +227,15 @@ class AliasedBufferBase {
186227
*/
187228
inline void SetValue(const size_t index, NativeT value) {
188229
DCHECK_LT(index, count_);
230+
DCHECK_NULL(info_);
189231
buffer_[index] = value;
190232
}
191233

192234
/**
193235
* Get value at position index
194236
*/
195237
inline const NativeT GetValue(const size_t index) const {
238+
DCHECK_NULL(info_);
196239
DCHECK_LT(index, count_);
197240
return buffer_[index];
198241
}
@@ -201,6 +244,7 @@ class AliasedBufferBase {
201244
* Effectively, a synonym for GetValue/SetValue
202245
*/
203246
Reference operator[](size_t index) {
247+
DCHECK_NULL(info_);
204248
return Reference(this, index);
205249
}
206250

@@ -216,6 +260,7 @@ class AliasedBufferBase {
216260
// Should only be used on an owning array, not one created as a sub array of
217261
// an owning `AliasedBufferBase`.
218262
void reserve(size_t new_capacity) {
263+
DCHECK_NULL(info_);
219264
DCHECK_GE(new_capacity, count_);
220265
DCHECK_EQ(byte_offset_, 0);
221266
const v8::HandleScope handle_scope(isolate_);
@@ -244,11 +289,14 @@ class AliasedBufferBase {
244289
}
245290

246291
private:
247-
v8::Isolate* isolate_;
248-
size_t count_;
249-
size_t byte_offset_;
250-
NativeT* buffer_;
292+
v8::Isolate* isolate_ = nullptr;
293+
size_t count_ = 0;
294+
size_t byte_offset_ = 0;
295+
NativeT* buffer_ = nullptr;
251296
v8::Global<V8T> js_array_;
297+
298+
// Deserialize data
299+
const AliasedBufferInfo* info_ = nullptr;
252300
};
253301

254302
typedef AliasedBufferBase<int32_t, v8::Int32Array> AliasedInt32Array;

src/api/environment.cc

+1-7
Original file line numberDiff line numberDiff line change
@@ -350,13 +350,7 @@ Environment* CreateEnvironment(
350350
// TODO(addaleax): This is a much better place for parsing per-Environment
351351
// options than the global parse call.
352352
Environment* env = new Environment(
353-
isolate_data,
354-
context,
355-
args,
356-
exec_args,
357-
flags,
358-
thread_id);
359-
env->InitializeMainContext(context);
353+
isolate_data, context, args, exec_args, nullptr, flags, thread_id);
360354
#if HAVE_INSPECTOR
361355
if (inspector_parent_handle) {
362356
env->InitializeInspector(

src/debug_utils.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ void FWrite(FILE* file, const std::string& str);
4646
V(INSPECTOR_PROFILER) \
4747
V(CODE_CACHE) \
4848
V(NGTCP2_DEBUG) \
49-
V(WASI)
49+
V(WASI) \
50+
V(MKSNAPSHOT)
5051

5152
enum class DebugCategory {
5253
#define V(name) name,

src/env-inl.h

-29
Original file line numberDiff line numberDiff line change
@@ -70,29 +70,6 @@ inline v8::Local<v8::String> IsolateData::async_wrap_provider(int index) const {
7070
return async_wrap_providers_[index].Get(isolate_);
7171
}
7272

73-
inline AsyncHooks::AsyncHooks()
74-
: async_ids_stack_(env()->isolate(), 16 * 2),
75-
fields_(env()->isolate(), kFieldsCount),
76-
async_id_fields_(env()->isolate(), kUidFieldsCount) {
77-
clear_async_id_stack();
78-
79-
// Always perform async_hooks checks, not just when async_hooks is enabled.
80-
// TODO(AndreasMadsen): Consider removing this for LTS releases.
81-
// See discussion in https://github.com/nodejs/node/pull/15454
82-
// When removing this, do it by reverting the commit. Otherwise the test
83-
// and flag changes won't be included.
84-
fields_[kCheck] = 1;
85-
86-
// kDefaultTriggerAsyncId should be -1, this indicates that there is no
87-
// specified default value and it should fallback to the executionAsyncId.
88-
// 0 is not used as the magic value, because that indicates a missing context
89-
// which is different from a default context.
90-
async_id_fields_[AsyncHooks::kDefaultTriggerAsyncId] = -1;
91-
92-
// kAsyncIdCounter should start at 1 because that'll be the id the execution
93-
// context during bootstrap (code that runs before entering uv_run()).
94-
async_id_fields_[AsyncHooks::kAsyncIdCounter] = 1;
95-
}
9673
inline AliasedUint32Array& AsyncHooks::fields() {
9774
return fields_;
9875
}
@@ -277,9 +254,6 @@ inline void Environment::PopAsyncCallbackScope() {
277254
async_callback_scope_depth_--;
278255
}
279256

280-
inline ImmediateInfo::ImmediateInfo(v8::Isolate* isolate)
281-
: fields_(isolate, kFieldsCount) {}
282-
283257
inline AliasedUint32Array& ImmediateInfo::fields() {
284258
return fields_;
285259
}
@@ -304,9 +278,6 @@ inline void ImmediateInfo::ref_count_dec(uint32_t decrement) {
304278
fields_[kRefCount] -= decrement;
305279
}
306280

307-
inline TickInfo::TickInfo(v8::Isolate* isolate)
308-
: fields_(isolate, kFieldsCount) {}
309-
310281
inline AliasedUint8Array& TickInfo::fields() {
311282
return fields_;
312283
}

0 commit comments

Comments
 (0)