Skip to content

Commit e9e9b50

Browse files
committed
src: avoid copying SEA snapshot data
Signed-off-by: Colin McDonnell <3084745+colinhacks@users.noreply.github.com>
1 parent 718cfe4 commit e9e9b50

3 files changed

Lines changed: 43 additions & 15 deletions

File tree

src/env.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ struct SnapshotData {
583583
// The result of v8::SnapshotCreator::CreateBlob() during the snapshot
584584
// building process.
585585
v8::StartupData v8_snapshot_blob_data{nullptr, 0};
586+
DataOwnership v8_snapshot_blob_data_ownership = DataOwnership::kOwned;
586587

587588
IsolateDataSerializeInfo isolate_data_info;
588589
// TODO(joyeecheung): there should be a vector of env_info once we snapshot
@@ -602,7 +603,11 @@ struct SnapshotData {
602603
bool Check() const;
603604
static bool FromFile(SnapshotData* out, FILE* in);
604605
static bool FromBlob(SnapshotData* out, const std::vector<char>& in);
605-
static bool FromBlob(SnapshotData* out, std::string_view in);
606+
// If the V8 data is not owned, `in` must outlive `out`.
607+
static bool FromBlob(SnapshotData* out,
608+
std::string_view in,
609+
DataOwnership v8_snapshot_blob_data_ownership =
610+
DataOwnership::kOwned);
606611
static const SnapshotData* FromEmbedderWrapper(
607612
const EmbedderSnapshotData* data);
608613
EmbedderSnapshotData::Pointer AsEmbedderWrapper() const;

src/node.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,11 @@ bool LoadSnapshotData(const SnapshotData** snapshot_data_ptr) {
15221522
std::unique_ptr<SnapshotData> read_data =
15231523
std::make_unique<SnapshotData>();
15241524
std::string_view snapshot = sea.main_code_or_snapshot;
1525-
if (SnapshotData::FromBlob(read_data.get(), snapshot)) {
1525+
// The SEA resource remains mapped for the process lifetime, so V8 can
1526+
// consume the startup data directly from the executable image.
1527+
if (SnapshotData::FromBlob(read_data.get(),
1528+
snapshot,
1529+
SnapshotData::DataOwnership::kNotOwned)) {
15261530
*snapshot_data_ptr = read_data.release();
15271531
return true;
15281532
} else {

src/node_snapshotable.cc

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,27 @@ class SnapshotDeserializer : public BlobDeserializer<SnapshotDeserializer> {
158158
template <typename T>
159159
requires(!std::is_arithmetic_v<T> && !std::same_as<T, std::string>)
160160
T Read();
161+
162+
v8::StartupData ReadV8StartupData(
163+
SnapshotData::DataOwnership ownership) {
164+
Debug("Read<v8::StartupData>()\n");
165+
166+
int raw_size = ReadArithmetic<int>();
167+
Debug("size=%d\n", raw_size);
168+
169+
CHECK_GT(raw_size, 0); // There should be no startup data of size 0.
170+
if (ownership == SnapshotData::DataOwnership::kOwned) {
171+
// The data pointer of v8::StartupData would be deleted so it must be
172+
// new'ed.
173+
std::unique_ptr<char> buf = std::unique_ptr<char>(new char[raw_size]);
174+
ReadArithmetic<char>(buf.get(), raw_size);
175+
return v8::StartupData{buf.release(), raw_size};
176+
}
177+
178+
const char* data = sink.data() + read_total;
179+
read_total += raw_size;
180+
return v8::StartupData{data, raw_size};
181+
}
161182
};
162183

163184
class SnapshotSerializer : public BlobSerializer<SnapshotSerializer> {
@@ -181,17 +202,7 @@ class SnapshotSerializer : public BlobSerializer<SnapshotSerializer> {
181202
// [ |raw_size| bytes ] contents
182203
template <>
183204
v8::StartupData SnapshotDeserializer::Read() {
184-
Debug("Read<v8::StartupData>()\n");
185-
186-
int raw_size = ReadArithmetic<int>();
187-
Debug("size=%d\n", raw_size);
188-
189-
CHECK_GT(raw_size, 0); // There should be no startup data of size 0.
190-
// The data pointer of v8::StartupData would be deleted so it must be new'ed.
191-
std::unique_ptr<char> buf = std::unique_ptr<char>(new char[raw_size]);
192-
ReadArithmetic<char>(buf.get(), raw_size);
193-
194-
return v8::StartupData{buf.release(), raw_size};
205+
return ReadV8StartupData(SnapshotData::DataOwnership::kOwned);
195206
}
196207

197208
template <>
@@ -640,7 +651,9 @@ bool SnapshotData::FromBlob(SnapshotData* out, const std::vector<char>& in) {
640651
return FromBlob(out, std::string_view(in.data(), in.size()));
641652
}
642653

643-
bool SnapshotData::FromBlob(SnapshotData* out, std::string_view in) {
654+
bool SnapshotData::FromBlob(SnapshotData* out,
655+
std::string_view in,
656+
DataOwnership v8_snapshot_blob_data_ownership) {
644657
SnapshotDeserializer r(in);
645658
r.Debug("SnapshotData::FromBlob()\n");
646659

@@ -656,7 +669,9 @@ bool SnapshotData::FromBlob(SnapshotData* out, std::string_view in) {
656669
return false;
657670
}
658671

659-
out->v8_snapshot_blob_data = r.Read<v8::StartupData>();
672+
out->v8_snapshot_blob_data =
673+
r.ReadV8StartupData(v8_snapshot_blob_data_ownership);
674+
out->v8_snapshot_blob_data_ownership = v8_snapshot_blob_data_ownership;
660675
r.Debug("Read isolate_data_info\n");
661676
out->isolate_data_info = r.Read<IsolateDataSerializeInfo>();
662677
out->env_info = r.Read<EnvSerializeInfo>();
@@ -701,6 +716,7 @@ bool SnapshotData::Check() const {
701716

702717
SnapshotData::~SnapshotData() {
703718
if (data_ownership == DataOwnership::kOwned &&
719+
v8_snapshot_blob_data_ownership == DataOwnership::kOwned &&
704720
v8_snapshot_blob_data.data != nullptr) {
705721
delete[] v8_snapshot_blob_data.data;
706722
}
@@ -822,6 +838,9 @@ namespace node {
822838
// -- v8_snapshot_blob_data begins --
823839
{ v8_snapshot_blob_data, v8_snapshot_blob_size },
824840
// -- v8_snapshot_blob_data ends --
841+
// -- v8_snapshot_blob_data_ownership begins --
842+
SnapshotData::DataOwnership::kNotOwned,
843+
// -- v8_snapshot_blob_data_ownership ends --
825844
// -- isolate_data_info begins --
826845
)" << data->isolate_data_info
827846
<< R"(

0 commit comments

Comments
 (0)