summaryrefslogtreecommitdiff
blob: 1cd49ec178bb1ddf38ccdfa78771f52eae5b96c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
From 2493dac20f0b4134bbf02ac48dffde6c2643608b Mon Sep 17 00:00:00 2001
From: Elvis Pranskevichus <elvis@magic.io>
Date: Sat, 11 Jun 2016 18:27:19 -0400
Subject: [PATCH] Add support for external V8 snapshots

---
 src/node.cc | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/src/node.cc b/src/node.cc
index cbe1538..521708a 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -4037,6 +4037,90 @@ Environment* CreateEnvironment(Isolate* isolate,
   return env;
 }
 
+#include <sys/mman.h>
+
+const char kProcSelfExe[] = "/proc/self/exe";
+const char kNativesFileName[] = "natives_blob.bin";
+const char kSnapshotFileName[] = "snapshot_blob.bin";
+const char *g_mapped_natives = nullptr;
+const char *g_mapped_snapshot = nullptr;
+
+static char* SnapshotPath(const char* filename) {
+  char *path;
+  char *dir;
+  ssize_t r;
+
+  path = reinterpret_cast<char*>(malloc(4096 + strlen(filename) + 2));
+  if (path == nullptr) {
+    fprintf(stderr, "out of memory\n");
+    ABORT();
+  }
+
+  r = readlink(kProcSelfExe, path, 4096 + 1);
+  if (r == -1) {
+    perror("could not determine node executable directory");
+    ABORT();
+  }
+
+  path[r] = '\0';
+
+  dir = strrchr(path, '/');
+
+  strcpy(dir + 1, filename);
+
+  return path;
+}
+
+static void LoadV8Snapshot(const char* name, const char** addr, size_t *size) {
+  char *path = SnapshotPath(name);
+  int fd;
+  struct stat sb;
+
+  fd = open(path, O_RDONLY);
+
+  if (fd == -1) {
+    fprintf(stderr, "could not open snapshot file '%s': %s\n",
+            path, sys_errlist[errno]);
+    ABORT();
+  }
+
+  if (fstat(fd, &sb) == -1) {
+    fprintf(stderr, "could not stat snapshot file '%s': %s\n",
+            path, sys_errlist[errno]);
+    ABORT();
+  }
+
+  *size = sb.st_size;
+
+  *addr = reinterpret_cast<const char*>(
+            mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0));
+  if (*addr == MAP_FAILED) {
+    fprintf(stderr, "could not read snapshot file '%s': %s\n",
+            path, sys_errlist[errno]);
+    ABORT();
+  }
+
+  close(fd);
+  free(path);
+}
+
+static void LoadV8Snapshots() {
+  size_t natives_size;
+  size_t snapshot_size;
+
+  LoadV8Snapshot(kNativesFileName, &g_mapped_natives, &natives_size);
+  LoadV8Snapshot(kSnapshotFileName, &g_mapped_snapshot, &snapshot_size);
+
+  v8::StartupData natives;
+  natives.data = g_mapped_natives;
+  natives.raw_size = natives_size;
+  V8::SetNativesDataBlob(&natives);
+
+  v8::StartupData snapshot;
+  snapshot.data = g_mapped_snapshot;
+  snapshot.raw_size = snapshot_size;
+  V8::SetSnapshotDataBlob(&snapshot);
+}
 
 // Entry point for new node instances, also called directly for the main
 // node instance.
@@ -4142,6 +4226,8 @@ int Start(int argc, char** argv) {
   const char** exec_argv;
   Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
 
+  LoadV8Snapshots();
+
 #if HAVE_OPENSSL
   // V8 on Windows doesn't have a good source of entropy. Seed it from
   // OpenSSL's pool.
-- 
2.7.3