22#include " node_snapshotable.h"
33#include < iostream>
44#include < sstream>
5+ #include < vector>
56#include " base_object-inl.h"
67#include " debug_utils-inl.h"
78#include " env-inl.h"
@@ -135,11 +136,10 @@ std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
135136 return output;
136137}
137138
138- class FileIO {
139+ class SnapshotSerializerDeserializer {
139140 public:
140- explicit FileIO (FILE* file)
141- : f(file),
142- is_debug(per_process::enabled_debug_list.enabled(
141+ SnapshotSerializerDeserializer ()
142+ : is_debug(per_process::enabled_debug_list.enabled(
143143 DebugCategory::MKSNAPSHOT)) {}
144144
145145 template <typename ... Args>
@@ -181,14 +181,14 @@ class FileIO {
181181 return name;
182182 }
183183
184- FILE* f = nullptr ;
185184 bool is_debug = false ;
186185};
187186
188- class FileReader : public FileIO {
187+ class SnapshotDeserializer : public SnapshotSerializerDeserializer {
189188 public:
190- explicit FileReader (FILE* file) : FileIO(file) {}
191- ~FileReader () {}
189+ explicit SnapshotDeserializer (const std::vector<char >* s)
190+ : SnapshotSerializerDeserializer(), sink(s) {}
191+ ~SnapshotDeserializer () {}
192192
193193 // Helper for reading numeric types.
194194 template <typename T>
@@ -233,19 +233,19 @@ class FileReader : public FileIO {
233233
234234 CHECK_GT (length, 0 ); // There should be no empty strings.
235235 MallocedBuffer<char > buf (length + 1 );
236- size_t r = fread (buf.data , 1 , length + 1 , f);
237- CHECK_EQ (r, length + 1 );
236+ memcpy (buf.data , sink->data () + read_total, length + 1 );
238237 std::string result (buf.data , length); // This creates a copy of buf.data.
239238
240239 if (is_debug) {
241- Debug (" \" %s\" , read %d bytes\n " , result.c_str (), r );
240+ Debug (" \" %s\" , read %zu bytes\n " , result.c_str (), length + 1 );
242241 }
243242
244- read_total += r ;
243+ read_total += length + 1 ;
245244 return result;
246245 }
247246
248247 size_t read_total = 0 ;
248+ const std::vector<char >* sink = nullptr ;
249249
250250 private:
251251 // Helper for reading an array of numeric types.
@@ -258,15 +258,15 @@ class FileReader : public FileIO {
258258 Debug (" Read<%s>()(%d-byte), count=%d: " , name.c_str (), sizeof (T), count);
259259 }
260260
261- size_t r = fread (out, sizeof (T), count, f) ;
262- CHECK_EQ (r, count );
261+ size_t size = sizeof (T) * count ;
262+ memcpy (out, sink-> data () + read_total, size );
263263
264264 if (is_debug) {
265265 std::string str =
266266 " { " + std::to_string (out[0 ]) + (count > 1 ? " , ... }" : " }" );
267- Debug (" %s, read %d bytes\n " , str.c_str (), r );
267+ Debug (" %s, read %zu bytes\n " , str.c_str (), size );
268268 }
269- read_total += r ;
269+ read_total += size ;
270270 }
271271
272272 // Helper for reading numeric vectors.
@@ -300,10 +300,15 @@ class FileReader : public FileIO {
300300 }
301301};
302302
303- class FileWriter : public FileIO {
303+ class SnapshotSerializer : public SnapshotSerializerDeserializer {
304304 public:
305- explicit FileWriter (FILE* file) : FileIO(file) {}
306- ~FileWriter () {}
305+ SnapshotSerializer () : SnapshotSerializerDeserializer() {
306+ // Currently the snapshot blob built with an empty script is around 4MB.
307+ // So use that as the default sink size.
308+ sink.reserve (4 * 1024 * 1024 );
309+ }
310+ ~SnapshotSerializer () {}
311+ std::vector<char > sink;
307312
308313 // Helper for writing numeric types.
309314 template <typename T>
@@ -349,15 +354,15 @@ class FileWriter : public FileIO {
349354 size_t written_total = Write<size_t >(data.size ());
350355 if (is_debug) {
351356 std::string str = ToStr (data);
352- Debug (" WriteString(), length=%d : \" %s\"\n " , data.size (), data.c_str ());
357+ Debug (" WriteString(), length=%zu : \" %s\"\n " , data.size (), data.c_str ());
353358 }
354359
355- size_t r = fwrite (data. c_str (), 1 , data. size () + 1 , f);
356- CHECK_EQ (r, data.size () + 1 );
357- written_total += r ;
360+ // Write the null-terminated string.
361+ sink. insert (sink. end (), data. c_str (), data. c_str () + data.size () + 1 );
362+ written_total += data. size () ;
358363
359364 if (is_debug) {
360- Debug (" WriteString() wrote %d bytes\n " , written_total);
365+ Debug (" WriteString() wrote %zu bytes\n " , written_total);
361366 }
362367
363368 return written_total;
@@ -372,20 +377,21 @@ class FileWriter : public FileIO {
372377 std::string str =
373378 " { " + std::to_string (data[0 ]) + (count > 1 ? " , ... }" : " }" );
374379 std::string name = GetName<T>();
375- Debug (" Write<%s>() (%d -byte), count=%d : %s" ,
380+ Debug (" Write<%s>() (%zu -byte), count=%zu : %s" ,
376381 name.c_str (),
377382 sizeof (T),
378383 count,
379384 str.c_str ());
380385 }
381386
382- size_t r = fwrite (data, sizeof (T), count, f);
383- CHECK_EQ (r, count);
387+ size_t size = sizeof (T) * count;
388+ const char * pos = reinterpret_cast <const char *>(data);
389+ sink.insert (sink.end (), pos, pos + (sizeof (T) * count));
384390
385391 if (is_debug) {
386- Debug (" , wrote %d bytes\n " , r );
392+ Debug (" , wrote %zu bytes\n " , size );
387393 }
388- return r ;
394+ return size ;
389395 }
390396
391397 // Helper for writing numeric vectors.
@@ -418,19 +424,19 @@ class FileWriter : public FileIO {
418424// [ 4/8 bytes ] length
419425// [ |length| bytes ] contents
420426template <>
421- std::string FileReader ::Read () {
427+ std::string SnapshotDeserializer ::Read () {
422428 return ReadString ();
423429}
424430template <>
425- size_t FileWriter ::Write (const std::string& data) {
431+ size_t SnapshotSerializer ::Write (const std::string& data) {
426432 return WriteString (data);
427433}
428434
429435// Layout of v8::StartupData
430436// [ 4/8 bytes ] raw_size
431437// [ |raw_size| bytes ] contents
432438template <>
433- v8::StartupData FileReader ::Read () {
439+ v8::StartupData SnapshotDeserializer ::Read () {
434440 Debug (" Read<v8::StartupData>()\n " );
435441
436442 int raw_size = Read<int >();
@@ -445,7 +451,7 @@ v8::StartupData FileReader::Read() {
445451}
446452
447453template <>
448- size_t FileWriter ::Write (const v8::StartupData& data) {
454+ size_t SnapshotSerializer ::Write (const v8::StartupData& data) {
449455 Debug (" \n Write<v8::StartupData>() size=%d\n " , data.raw_size );
450456
451457 CHECK_GT (data.raw_size , 0 ); // There should be no startup data of size 0.
@@ -462,7 +468,7 @@ size_t FileWriter::Write(const v8::StartupData& data) {
462468// [ 4/8 bytes ] length of module code cache
463469// [ ... ] |length| bytes of module code cache
464470template <>
465- builtins::CodeCacheInfo FileReader ::Read () {
471+ builtins::CodeCacheInfo SnapshotDeserializer ::Read () {
466472 Debug (" Read<builtins::CodeCacheInfo>()\n " );
467473
468474 builtins::CodeCacheInfo result{ReadString (), ReadVector<uint8_t >()};
@@ -475,7 +481,7 @@ builtins::CodeCacheInfo FileReader::Read() {
475481}
476482
477483template <>
478- size_t FileWriter ::Write (const builtins::CodeCacheInfo& data) {
484+ size_t SnapshotSerializer ::Write (const builtins::CodeCacheInfo& data) {
479485 Debug (" \n Write<builtins::CodeCacheInfo>() id = %s"
480486 " , size=%d\n " ,
481487 data.id .c_str (),
@@ -495,7 +501,7 @@ size_t FileWriter::Write(const builtins::CodeCacheInfo& data) {
495501// [ 4/8 bytes ] index in the snapshot blob, can be used with
496502// GetDataFromSnapshotOnce().
497503template <>
498- PropInfo FileReader ::Read () {
504+ PropInfo SnapshotDeserializer ::Read () {
499505 Debug (" Read<PropInfo>()\n " );
500506
501507 PropInfo result;
@@ -512,7 +518,7 @@ PropInfo FileReader::Read() {
512518}
513519
514520template <>
515- size_t FileWriter ::Write (const PropInfo& data) {
521+ size_t SnapshotSerializer ::Write (const PropInfo& data) {
516522 if (is_debug) {
517523 std::string str = ToStr (data);
518524 Debug (" Write<PropInfo>() %s\n " , str.c_str ());
@@ -535,7 +541,7 @@ size_t FileWriter::Write(const PropInfo& data) {
535541// [ ... ] snapshot indices of each element in
536542// native_execution_async_resources
537543template <>
538- AsyncHooks::SerializeInfo FileReader ::Read () {
544+ AsyncHooks::SerializeInfo SnapshotDeserializer ::Read () {
539545 Debug (" Read<AsyncHooks::SerializeInfo>()\n " );
540546
541547 AsyncHooks::SerializeInfo result;
@@ -553,7 +559,7 @@ AsyncHooks::SerializeInfo FileReader::Read() {
553559 return result;
554560}
555561template <>
556- size_t FileWriter ::Write (const AsyncHooks::SerializeInfo& data) {
562+ size_t SnapshotSerializer ::Write (const AsyncHooks::SerializeInfo& data) {
557563 if (is_debug) {
558564 std::string str = ToStr (data);
559565 Debug (" Write<AsyncHooks::SerializeInfo>() %s\n " , str.c_str ());
@@ -573,7 +579,7 @@ size_t FileWriter::Write(const AsyncHooks::SerializeInfo& data) {
573579// Layout of TickInfo::SerializeInfo
574580// [ 4/8 bytes ] snapshot index of fields
575581template <>
576- TickInfo::SerializeInfo FileReader ::Read () {
582+ TickInfo::SerializeInfo SnapshotDeserializer ::Read () {
577583 Debug (" Read<TickInfo::SerializeInfo>()\n " );
578584
579585 TickInfo::SerializeInfo result;
@@ -588,7 +594,7 @@ TickInfo::SerializeInfo FileReader::Read() {
588594}
589595
590596template <>
591- size_t FileWriter ::Write (const TickInfo::SerializeInfo& data) {
597+ size_t SnapshotSerializer ::Write (const TickInfo::SerializeInfo& data) {
592598 if (is_debug) {
593599 std::string str = ToStr (data);
594600 Debug (" Write<TickInfo::SerializeInfo>() %s\n " , str.c_str ());
@@ -603,7 +609,7 @@ size_t FileWriter::Write(const TickInfo::SerializeInfo& data) {
603609// Layout of TickInfo::SerializeInfo
604610// [ 4/8 bytes ] snapshot index of fields
605611template <>
606- ImmediateInfo::SerializeInfo FileReader ::Read () {
612+ ImmediateInfo::SerializeInfo SnapshotDeserializer ::Read () {
607613 per_process::Debug (DebugCategory::MKSNAPSHOT,
608614 " Read<ImmediateInfo::SerializeInfo>()\n " );
609615
@@ -617,7 +623,7 @@ ImmediateInfo::SerializeInfo FileReader::Read() {
617623}
618624
619625template <>
620- size_t FileWriter ::Write (const ImmediateInfo::SerializeInfo& data) {
626+ size_t SnapshotSerializer ::Write (const ImmediateInfo::SerializeInfo& data) {
621627 if (is_debug) {
622628 std::string str = ToStr (data);
623629 Debug (" Write<ImmediateInfo::SerializeInfo>() %s\n " , str.c_str ());
@@ -635,7 +641,7 @@ size_t FileWriter::Write(const ImmediateInfo::SerializeInfo& data) {
635641// [ 4/8 bytes ] snapshot index of milestones
636642// [ 4/8 bytes ] snapshot index of observers
637643template <>
638- performance::PerformanceState::SerializeInfo FileReader ::Read () {
644+ performance::PerformanceState::SerializeInfo SnapshotDeserializer ::Read () {
639645 per_process::Debug (DebugCategory::MKSNAPSHOT,
640646 " Read<PerformanceState::SerializeInfo>()\n " );
641647
@@ -651,7 +657,7 @@ performance::PerformanceState::SerializeInfo FileReader::Read() {
651657}
652658
653659template <>
654- size_t FileWriter ::Write (
660+ size_t SnapshotSerializer ::Write (
655661 const performance::PerformanceState::SerializeInfo& data) {
656662 if (is_debug) {
657663 std::string str = ToStr (data);
@@ -673,7 +679,7 @@ size_t FileWriter::Write(
673679// [ 4/8 bytes ] length of template_values vector
674680// [ ... ] |length| of PropInfo data
675681template <>
676- IsolateDataSerializeInfo FileReader ::Read () {
682+ IsolateDataSerializeInfo SnapshotDeserializer ::Read () {
677683 per_process::Debug (DebugCategory::MKSNAPSHOT,
678684 " Read<IsolateDataSerializeInfo>()\n " );
679685
@@ -688,7 +694,7 @@ IsolateDataSerializeInfo FileReader::Read() {
688694}
689695
690696template <>
691- size_t FileWriter ::Write (const IsolateDataSerializeInfo& data) {
697+ size_t SnapshotSerializer ::Write (const IsolateDataSerializeInfo& data) {
692698 if (is_debug) {
693699 std::string str = ToStr (data);
694700 Debug (" Write<IsolateDataSerializeInfo>() %s\n " , str.c_str ());
@@ -702,7 +708,7 @@ size_t FileWriter::Write(const IsolateDataSerializeInfo& data) {
702708}
703709
704710template <>
705- RealmSerializeInfo FileReader ::Read () {
711+ RealmSerializeInfo SnapshotDeserializer ::Read () {
706712 per_process::Debug (DebugCategory::MKSNAPSHOT, " Read<RealmSerializeInfo>()\n " );
707713 RealmSerializeInfo result;
708714 result.builtins = ReadVector<std::string>();
@@ -713,7 +719,7 @@ RealmSerializeInfo FileReader::Read() {
713719}
714720
715721template <>
716- size_t FileWriter ::Write (const RealmSerializeInfo& data) {
722+ size_t SnapshotSerializer ::Write (const RealmSerializeInfo& data) {
717723 if (is_debug) {
718724 std::string str = ToStr (data);
719725 Debug (" \n Write<RealmSerializeInfo>() %s\n " , str.c_str ());
@@ -730,7 +736,7 @@ size_t FileWriter::Write(const RealmSerializeInfo& data) {
730736}
731737
732738template <>
733- EnvSerializeInfo FileReader ::Read () {
739+ EnvSerializeInfo SnapshotDeserializer ::Read () {
734740 per_process::Debug (DebugCategory::MKSNAPSHOT, " Read<EnvSerializeInfo>()\n " );
735741 EnvSerializeInfo result;
736742 result.async_hooks = Read<AsyncHooks::SerializeInfo>();
@@ -747,7 +753,7 @@ EnvSerializeInfo FileReader::Read() {
747753}
748754
749755template <>
750- size_t FileWriter ::Write (const EnvSerializeInfo& data) {
756+ size_t SnapshotSerializer ::Write (const EnvSerializeInfo& data) {
751757 if (is_debug) {
752758 std::string str = ToStr (data);
753759 Debug (" \n Write<EnvSerializeInfo>() %s\n " , str.c_str ());
@@ -780,7 +786,7 @@ size_t FileWriter::Write(const EnvSerializeInfo& data) {
780786// [ ... ] |length| bytes of node platform
781787// [ 4 bytes ] v8 cache version tag
782788template <>
783- SnapshotMetadata FileReader ::Read () {
789+ SnapshotMetadata SnapshotDeserializer ::Read () {
784790 per_process::Debug (DebugCategory::MKSNAPSHOT, " Read<SnapshotMetadata>()\n " );
785791
786792 SnapshotMetadata result;
@@ -798,7 +804,7 @@ SnapshotMetadata FileReader::Read() {
798804}
799805
800806template <>
801- size_t FileWriter ::Write (const SnapshotMetadata& data) {
807+ size_t SnapshotSerializer ::Write (const SnapshotMetadata& data) {
802808 if (is_debug) {
803809 std::string str = ToStr (data);
804810 Debug (" \n Write<SnapshotMetadata>() %s\n " , str.c_str ());
@@ -833,7 +839,7 @@ size_t FileWriter::Write(const SnapshotMetadata& data) {
833839// [ ... ] code_cache
834840
835841void SnapshotData::ToBlob (FILE* out) const {
836- FileWriter w (out) ;
842+ SnapshotSerializer w ;
837843 w.Debug (" SnapshotData::ToBlob()\n " );
838844
839845 size_t written_total = 0 ;
@@ -850,11 +856,24 @@ void SnapshotData::ToBlob(FILE* out) const {
850856 written_total += w.Write <EnvSerializeInfo>(env_info);
851857 w.Debug (" Write code_cache\n " );
852858 written_total += w.WriteVector <builtins::CodeCacheInfo>(code_cache);
859+ size_t num_written = fwrite (w.sink .data (), w.sink .size (), 1 , out);
860+ CHECK_EQ (num_written, 1 );
853861 w.Debug (" SnapshotData::ToBlob() Wrote %d bytes\n " , written_total);
854862}
855863
856864bool SnapshotData::FromBlob (SnapshotData* out, FILE* in) {
857- FileReader r (in);
865+ CHECK_EQ (ftell (in), 0 );
866+ int err = fseek (in, 0 , SEEK_END);
867+ CHECK_EQ (err, 0 );
868+ size_t size = ftell (in);
869+ err = fseek (in, 0 , SEEK_SET);
870+ CHECK_EQ (err, 0 );
871+
872+ std::vector<char > sink (size);
873+ size_t num_read = fread (sink.data (), size, 1 , in);
874+ CHECK_EQ (num_read, 1 );
875+
876+ SnapshotDeserializer r (&sink);
858877 r.Debug (" SnapshotData::FromBlob()\n " );
859878
860879 DCHECK_EQ (out->data_ownership , SnapshotData::DataOwnership::kOwned );
0 commit comments