src: notify V8 for low memory when alloc fails
Call `v8::Isolate::GetCurrent()->LowMemoryNotification()` when an allocation fails to give V8 a chance to clean up and return memory before retrying (and possibly giving up). PR-URL: https://github.com/nodejs/node/pull/8482 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Ilkka Myller <ilkka.myller@nodefield.com>
This commit is contained in:
parent
ea94086ad2
commit
72c60e892c
@ -183,6 +183,8 @@ bool trace_warnings = false;
|
||||
// that is used by lib/module.js
|
||||
bool config_preserve_symlinks = false;
|
||||
|
||||
bool v8_initialized = false;
|
||||
|
||||
// process-relative uptime base, initialized at start-up
|
||||
static double prog_start_time;
|
||||
static bool debugger_running;
|
||||
@ -4490,6 +4492,7 @@ int Start(int argc, char** argv) {
|
||||
|
||||
v8_platform.Initialize(v8_thread_pool_size);
|
||||
V8::Initialize();
|
||||
v8_initialized = true;
|
||||
|
||||
int exit_code = 1;
|
||||
{
|
||||
@ -4503,6 +4506,7 @@ int Start(int argc, char** argv) {
|
||||
StartNodeInstance(&instance_data);
|
||||
exit_code = instance_data.exit_code();
|
||||
}
|
||||
v8_initialized = false;
|
||||
V8::Dispose();
|
||||
|
||||
v8_platform.Dispose();
|
||||
|
@ -37,6 +37,9 @@ namespace node {
|
||||
// that is used by lib/module.js
|
||||
extern bool config_preserve_symlinks;
|
||||
|
||||
// Tells whether it is safe to call v8::Isolate::GetCurrent().
|
||||
extern bool v8_initialized;
|
||||
|
||||
// Forward declaration
|
||||
class Environment;
|
||||
|
||||
|
@ -253,7 +253,15 @@ T* UncheckedRealloc(T* pointer, size_t n) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<T*>(realloc(pointer, full_size));
|
||||
void* allocated = realloc(pointer, full_size);
|
||||
|
||||
if (UNLIKELY(allocated == nullptr)) {
|
||||
// Tell V8 that memory is low and retry.
|
||||
LowMemoryNotification();
|
||||
allocated = realloc(pointer, full_size);
|
||||
}
|
||||
|
||||
return static_cast<T*>(allocated);
|
||||
}
|
||||
|
||||
// As per spec realloc behaves like malloc if passed nullptr.
|
||||
|
@ -77,4 +77,13 @@ BufferValue::BufferValue(Isolate* isolate, Local<Value> value) {
|
||||
}
|
||||
}
|
||||
|
||||
void LowMemoryNotification() {
|
||||
if (v8_initialized) {
|
||||
auto isolate = v8::Isolate::GetCurrent();
|
||||
if (isolate != nullptr) {
|
||||
isolate->LowMemoryNotification();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
|
@ -44,6 +44,11 @@ inline char* Calloc(size_t n) { return Calloc<char>(n); }
|
||||
inline char* UncheckedMalloc(size_t n) { return UncheckedMalloc<char>(n); }
|
||||
inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); }
|
||||
|
||||
// Used by the allocation functions when allocation fails.
|
||||
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
|
||||
// whether V8 is initialized.
|
||||
void LowMemoryNotification();
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define NO_RETURN __attribute__((noreturn))
|
||||
#else
|
||||
|
@ -90,6 +90,10 @@ TEST(UtilTest, ToLower) {
|
||||
EXPECT_EQ('a', ToLower('A'));
|
||||
}
|
||||
|
||||
namespace node {
|
||||
void LowMemoryNotification() {}
|
||||
}
|
||||
|
||||
TEST(UtilTest, Malloc) {
|
||||
using node::Malloc;
|
||||
EXPECT_NE(nullptr, Malloc<char>(0));
|
||||
|
Loading…
x
Reference in New Issue
Block a user