summaryrefslogtreecommitdiff
path: root/src/node.cc
diff options
context:
space:
mode:
authorGus Caplan <me@gus.host>2019-04-15 16:09:51 -0500
committerSam Roberts <vieuxtech@gmail.com>2019-05-16 10:52:53 -0700
commitf2061930c83cb579410a7f26bed726d6568575e3 (patch)
treeddcfcc116344fd03d5d04721df49eacb0059dd13 /src/node.cc
parentcca375f4af235ed7e7f763b2e35532ae843a5854 (diff)
downloadandroid-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.tar.gz
android-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.tar.bz2
android-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.zip
src: enable V8's WASM trap handlers
This uses SIGSEGV handlers to catch WASM out of bound (OOB) memory accesses instead of inserting OOB checks inline, resulting in a 25%-30% speed increase. Note that installing a custom SIGSEGV handler will break this, resulting in potentially scary behaviour. Refs: https://github.com/nodejs/node/issues/14927 PR-URL: https://github.com/nodejs/node/pull/27246 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'src/node.cc')
-rw-r--r--src/node.cc58
1 files changed, 55 insertions, 3 deletions
diff --git a/src/node.cc b/src/node.cc
index 953465e04a..7dccd7ce57 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -70,6 +70,17 @@
#include "node_report.h"
#endif
+#if defined(__APPLE__) || defined(__linux__)
+#define NODE_USE_V8_WASM_TRAP_HANDLER 1
+#else
+#define NODE_USE_V8_WASM_TRAP_HANDLER 0
+#endif
+
+#if NODE_USE_V8_WASM_TRAP_HANDLER
+#include <atomic>
+#include "v8-wasm-trap-handler-posix.h"
+#endif // NODE_USE_V8_WASM_TRAP_HANDLER
+
// ========== global C headers ==========
#include <fcntl.h> // _O_RDWR
@@ -177,7 +188,8 @@ void WaitForInspectorDisconnect(Environment* env) {
#endif
}
-void SignalExit(int signo) {
+#ifdef __POSIX__
+void SignalExit(int signo, siginfo_t* info, void* ucontext) {
uv_tty_reset_mode();
#ifdef __FreeBSD__
// FreeBSD has a nasty bug, see RegisterSignalHandler for details
@@ -188,6 +200,7 @@ void SignalExit(int signo) {
#endif
raise(signo);
}
+#endif // __POSIX__
MaybeLocal<Value> ExecuteBootstrapper(Environment* env,
const char* id,
@@ -434,14 +447,39 @@ void LoadEnvironment(Environment* env) {
USE(StartMainThreadExecution(env));
}
+#if NODE_USE_V8_WASM_TRAP_HANDLER
+static std::atomic<void (*)(int signo, siginfo_t* info, void* ucontext)>
+ previous_sigsegv_action;
+
+void TrapWebAssemblyOrContinue(int signo, siginfo_t* info, void* ucontext) {
+ if (!v8::TryHandleWebAssemblyTrapPosix(signo, info, ucontext)) {
+ auto prev = previous_sigsegv_action.load();
+ if (prev != nullptr) {
+ prev(signo, info, ucontext);
+ } else {
+ uv_tty_reset_mode();
+ raise(signo);
+ }
+ }
+}
+#endif // NODE_USE_V8_WASM_TRAP_HANDLER
#ifdef __POSIX__
void RegisterSignalHandler(int signal,
- void (*handler)(int signal),
+ void (*handler)(int signal,
+ siginfo_t* info,
+ void* ucontext),
bool reset_handler) {
+#if NODE_USE_V8_WASM_TRAP_HANDLER
+ if (signal == SIGSEGV) {
+ CHECK(previous_sigsegv_action.is_lock_free());
+ previous_sigsegv_action.store(handler);
+ return;
+ }
+#endif // NODE_USE_V8_WASM_TRAP_HANDLER
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
- sa.sa_handler = handler;
+ sa.sa_sigaction = handler;
#ifndef __FreeBSD__
// FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
// in turn set for a libthr wrapper. This leads to a crash.
@@ -499,6 +537,20 @@ inline void PlatformInit() {
RegisterSignalHandler(SIGINT, SignalExit, true);
RegisterSignalHandler(SIGTERM, SignalExit, true);
+#if NODE_USE_V8_WASM_TRAP_HANDLER
+ // Tell V8 to disable emitting WebAssembly
+ // memory bounds checks. This means that we have
+ // to catch the SIGSEGV in TrapWebAssemblyOrContinue
+ // and pass the signal context to V8.
+ {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = TrapWebAssemblyOrContinue;
+ CHECK_EQ(sigaction(SIGSEGV, &sa, nullptr), 0);
+ }
+ V8::EnableWebAssemblyTrapHandler(false);
+#endif // NODE_USE_V8_WASM_TRAP_HANDLER
+
// Raise the open file descriptor limit.
struct rlimit lim;
if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {