Skip to content

Commit 451c7a7

Browse files
committed
src: support fs and v8 binding data in snapshot
1 parent 9b7b6d7 commit 451c7a7

21 files changed

+477
-47
lines changed

lib/fs.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ const {
6767

6868
const pathModule = require('path');
6969
const { isArrayBufferView } = require('internal/util/types');
70+
71+
// We need to get the statValues from the binding at the callsite since
72+
// it's re-initialized after deserialization.
73+
7074
const binding = internalBinding('fs');
7175
const { Buffer } = require('buffer');
7276
const {
@@ -81,7 +85,7 @@ const {
8185
uvException
8286
} = require('internal/errors');
8387

84-
const { FSReqCallback, statValues } = binding;
88+
const { FSReqCallback } = binding;
8589
const { toPathIfFileURL } = require('internal/url');
8690
const internalUtil = require('internal/util');
8791
const {
@@ -1756,8 +1760,8 @@ function realpathSync(p, options) {
17561760

17571761
// Continue if not a symlink, break if a pipe/socket
17581762
if (knownHard[base] || cache?.get(base) === base) {
1759-
if (isFileType(statValues, S_IFIFO) ||
1760-
isFileType(statValues, S_IFSOCK)) {
1763+
if (isFileType(binding.statValues, S_IFIFO) ||
1764+
isFileType(binding.statValues, S_IFSOCK)) {
17611765
break;
17621766
}
17631767
continue;
@@ -1899,8 +1903,8 @@ function realpath(p, options, callback) {
18991903

19001904
// Continue if not a symlink, break if a pipe/socket
19011905
if (knownHard[base]) {
1902-
if (isFileType(statValues, S_IFIFO) ||
1903-
isFileType(statValues, S_IFSOCK)) {
1906+
if (isFileType(binding.statValues, S_IFIFO) ||
1907+
isFileType(binding.statValues, S_IFSOCK)) {
19041908
return callback(null, encodeRealpathResult(p, options));
19051909
}
19061910
return process.nextTick(LOOP);

lib/internal/bootstrap/node.js

+3
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ process.emitWarning = emitWarning;
347347
// Note: only after this point are the timers effective
348348
}
349349

350+
require('fs');
351+
internalBinding('v8');
352+
350353
function setupPrepareStackTrace() {
351354
const {
352355
setEnhanceStackForFatalException,

lib/v8.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ function getHeapSnapshot() {
7272
return new HeapSnapshotStream(handle);
7373
}
7474

75+
// We need to get the buffer from the binding at the callsite since
76+
// it's re-initialized after deserialization.
77+
const binding = internalBinding('v8');
78+
7579
const {
7680
cachedDataVersionTag,
7781
setFlagsFromString: _setFlagsFromString,
78-
heapStatisticsBuffer,
79-
heapSpaceStatisticsBuffer,
80-
heapCodeStatisticsBuffer,
8182
updateHeapStatisticsBuffer,
8283
updateHeapSpaceStatisticsBuffer,
8384
updateHeapCodeStatisticsBuffer,
@@ -106,7 +107,7 @@ const {
106107
kCodeAndMetadataSizeIndex,
107108
kBytecodeAndMetadataSizeIndex,
108109
kExternalScriptSourceSizeIndex
109-
} = internalBinding('v8');
110+
} = binding;
110111

111112
const kNumberOfHeapSpaces = kHeapSpaces.length;
112113

@@ -116,7 +117,7 @@ function setFlagsFromString(flags) {
116117
}
117118

118119
function getHeapStatistics() {
119-
const buffer = heapStatisticsBuffer;
120+
const buffer = binding.heapStatisticsBuffer;
120121

121122
updateHeapStatisticsBuffer();
122123

@@ -137,7 +138,7 @@ function getHeapStatistics() {
137138

138139
function getHeapSpaceStatistics() {
139140
const heapSpaceStatistics = new Array(kNumberOfHeapSpaces);
140-
const buffer = heapSpaceStatisticsBuffer;
141+
const buffer = binding.heapSpaceStatisticsBuffer;
141142

142143
for (let i = 0; i < kNumberOfHeapSpaces; i++) {
143144
updateHeapSpaceStatisticsBuffer(i);
@@ -154,7 +155,7 @@ function getHeapSpaceStatistics() {
154155
}
155156

156157
function getHeapCodeStatistics() {
157-
const buffer = heapCodeStatisticsBuffer;
158+
const buffer = binding.heapCodeStatisticsBuffer;
158159

159160
updateHeapCodeStatisticsBuffer();
160161
return {

src/aliased_buffer.h

+5
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ class AliasedBufferBase {
198198
return js_array_.Get(isolate_);
199199
}
200200

201+
void Release() {
202+
DCHECK_NULL(index_);
203+
js_array_.Reset();
204+
}
205+
201206
/**
202207
* Get the underlying v8::ArrayBuffer underlying the TypedArray and
203208
* overlaying the native buffer

src/base_object.h

+4
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ class BaseObject : public MemoryRetainer {
158158

159159
virtual inline void OnGCCollect();
160160

161+
bool is_snapshotable() const { return is_snapshotable_; }
162+
void set_is_snapshotable(bool val) { is_snapshotable_ = val; }
163+
161164
private:
162165
v8::Local<v8::Object> WrappedObject() const override;
163166
bool IsRootNode() const override;
@@ -206,6 +209,7 @@ class BaseObject : public MemoryRetainer {
206209

207210
Environment* env_;
208211
PointerData* pointer_data_ = nullptr;
212+
bool is_snapshotable_ = false;
209213
};
210214

211215
// Global alias for FromJSObject() to avoid churn.

src/env-inl.h

+11
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,17 @@ void Environment::ForEachBaseObject(T&& iterator) {
10851085
}
10861086
}
10871087

1088+
template <typename T>
1089+
void Environment::ForEachBindingData(T&& iterator) {
1090+
BindingDataStore* map = static_cast<BindingDataStore*>(
1091+
context()->GetAlignedPointerFromEmbedderData(
1092+
ContextEmbedderIndex::kBindingListIndex));
1093+
DCHECK_NOT_NULL(map);
1094+
for (auto& it : *map) {
1095+
iterator(it.first, it.second);
1096+
}
1097+
}
1098+
10881099
void Environment::modify_base_object_count(int64_t delta) {
10891100
base_object_count_ += delta;
10901101
}

src/env.cc

+26
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
#include "node_buffer.h"
99
#include "node_context_data.h"
1010
#include "node_errors.h"
11+
#include "node_file.h"
1112
#include "node_internals.h"
1213
#include "node_options-inl.h"
1314
#include "node_process.h"
15+
#include "node_v8.h"
1416
#include "node_v8_platform-inl.h"
1517
#include "node_worker.h"
1618
#include "req_wrap-inl.h"
@@ -1249,6 +1251,7 @@ EnvSerializeInfo Environment::Serialize(SnapshotCreator* creator) {
12491251
EnvSerializeInfo info;
12501252
Local<Context> ctx = context();
12511253

1254+
SerializeBindingData(this, creator, &info);
12521255
// Currently all modules are compiled without cache in builtin snapshot
12531256
// builder.
12541257
info.native_modules = std::vector<std::string>(
@@ -1315,6 +1318,9 @@ std::ostream& operator<<(std::ostream& output,
13151318

13161319
std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
13171320
output << "{\n"
1321+
<< "// -- bindings begins --\n"
1322+
<< i.bindings << ",\n"
1323+
<< "// -- bindings ends --\n"
13181324
<< "// -- native_modules begins --\n"
13191325
<< i.native_modules << ",\n"
13201326
<< "// -- native_modules ends --\n"
@@ -1340,9 +1346,29 @@ std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
13401346
return output;
13411347
}
13421348

1349+
void Environment::EnqueueDeserializeRequest(DeserializeRequest request) {
1350+
deserialize_requests_.push_back(std::move(request));
1351+
}
1352+
1353+
void Environment::RunDeserializeRequests() {
1354+
HandleScope scope(isolate());
1355+
Local<Context> ctx = context();
1356+
Isolate* is = isolate();
1357+
while (!deserialize_requests_.empty()) {
1358+
DeserializeRequest request(std::move(deserialize_requests_.front()));
1359+
deserialize_requests_.pop_front();
1360+
Local<Object> holder = request.holder.Get(is);
1361+
request.cb(ctx, holder, request.info);
1362+
request.holder.Reset(); // unnecessary?
1363+
request.info->Delete();
1364+
}
1365+
}
1366+
13431367
void Environment::DeserializeProperties(const EnvSerializeInfo* info) {
13441368
Local<Context> ctx = context();
13451369

1370+
RunDeserializeRequests();
1371+
13461372
native_modules_in_snapshot = info->native_modules;
13471373
async_hooks_.Deserialize(ctx);
13481374
immediate_info_.Deserialize(ctx);

src/env.h

+22
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "node_main_instance.h"
3838
#include "node_options.h"
3939
#include "node_perf_common.h"
40+
#include "node_snapshotable.h"
4041
#include "req_wrap.h"
4142
#include "util.h"
4243
#include "uv.h"
@@ -936,8 +937,22 @@ struct PropInfo {
936937
SnapshotIndex index; // In the snapshot
937938
};
938939

940+
typedef void (*DeserializeRequestCallback)(v8::Local<v8::Context>,
941+
v8::Local<v8::Object> holder,
942+
InternalFieldInfo* info);
943+
struct DeserializeRequest {
944+
DeserializeRequestCallback cb;
945+
v8::Global<v8::Object> holder;
946+
InternalFieldInfo* info; // Owned by the request
947+
948+
// Move constructor
949+
DeserializeRequest(DeserializeRequest&& other) = default;
950+
};
951+
939952
struct EnvSerializeInfo {
953+
std::vector<PropInfo> bindings;
940954
std::vector<std::string> native_modules;
955+
941956
AsyncHooks::SerializeInfo async_hooks;
942957
TickInfo::SerializeInfo tick_info;
943958
ImmediateInfo::SerializeInfo immediate_info;
@@ -971,6 +986,8 @@ class Environment : public MemoryRetainer {
971986

972987
void PrintAllBaseObjects();
973988
void VerifyNoStrongBaseObjects();
989+
void EnqueueDeserializeRequest(DeserializeRequest request);
990+
void RunDeserializeRequests();
974991
// Should be called before InitializeInspector()
975992
void InitializeDiagnostics();
976993

@@ -1408,6 +1425,9 @@ class Environment : public MemoryRetainer {
14081425
void AddUnmanagedFd(int fd);
14091426
void RemoveUnmanagedFd(int fd);
14101427

1428+
template <typename T>
1429+
void ForEachBindingData(T&& iterator);
1430+
14111431
private:
14121432
inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
14131433
const char* errmsg);
@@ -1496,6 +1516,8 @@ class Environment : public MemoryRetainer {
14961516
bool is_in_inspector_console_call_ = false;
14971517
#endif
14981518

1519+
std::list<DeserializeRequest> deserialize_requests_;
1520+
14991521
// handle_wrap_queue_ and req_wrap_queue_ needs to be at a fixed offset from
15001522
// the start of the class because it is used by
15011523
// src/node_postmortem_metadata.cc to calculate offsets and generate debug

src/node_dir.cc

+9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "node_dir.h"
2+
#include "node_external_reference.h"
23
#include "node_file-inl.h"
34
#include "node_process.h"
45
#include "memory_tracker-inl.h"
@@ -362,8 +363,16 @@ void Initialize(Local<Object> target,
362363
env->set_dir_instance_template(dirt);
363364
}
364365

366+
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
367+
registry->Register(OpenDir);
368+
registry->Register(DirHandle::New);
369+
registry->Register(DirHandle::Read);
370+
registry->Register(DirHandle::Close);
371+
}
372+
365373
} // namespace fs_dir
366374

367375
} // end namespace node
368376

369377
NODE_MODULE_CONTEXT_AWARE_INTERNAL(fs_dir, node::fs_dir::Initialize)
378+
NODE_MODULE_EXTERNAL_REFERENCE(fs_dir, node::fs_dir::RegisterExternalReferences)

src/node_external_reference.h

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class ExternalReferenceRegistry {
5353
V(credentials) \
5454
V(env_var) \
5555
V(errors) \
56+
V(fs) \
57+
V(fs_dir) \
5658
V(handle_wrap) \
5759
V(messaging) \
5860
V(native_module) \
@@ -65,6 +67,7 @@ class ExternalReferenceRegistry {
6567
V(trace_events) \
6668
V(timers) \
6769
V(types) \
70+
V(v8) \
6871
V(worker)
6972

7073
#if NODE_HAVE_I18N_SUPPORT

0 commit comments

Comments
 (0)