Browse Source

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>
v6
Anna Henningsen 9 years ago
parent
commit
72c60e892c
No known key found for this signature in database GPG Key ID: D8B9F5AEAE84E4CF
  1. 4
      src/node.cc
  2. 3
      src/node_internals.h
  3. 10
      src/util-inl.h
  4. 9
      src/util.cc
  5. 5
      src/util.h
  6. 4
      test/cctest/util.cc

4
src/node.cc

@ -183,6 +183,8 @@ bool trace_warnings = false;
// that is used by lib/module.js // that is used by lib/module.js
bool config_preserve_symlinks = false; bool config_preserve_symlinks = false;
bool v8_initialized = false;
// process-relative uptime base, initialized at start-up // process-relative uptime base, initialized at start-up
static double prog_start_time; static double prog_start_time;
static bool debugger_running; static bool debugger_running;
@ -4490,6 +4492,7 @@ int Start(int argc, char** argv) {
v8_platform.Initialize(v8_thread_pool_size); v8_platform.Initialize(v8_thread_pool_size);
V8::Initialize(); V8::Initialize();
v8_initialized = true;
int exit_code = 1; int exit_code = 1;
{ {
@ -4503,6 +4506,7 @@ int Start(int argc, char** argv) {
StartNodeInstance(&instance_data); StartNodeInstance(&instance_data);
exit_code = instance_data.exit_code(); exit_code = instance_data.exit_code();
} }
v8_initialized = false;
V8::Dispose(); V8::Dispose();
v8_platform.Dispose(); v8_platform.Dispose();

3
src/node_internals.h

@ -37,6 +37,9 @@ namespace node {
// that is used by lib/module.js // that is used by lib/module.js
extern bool config_preserve_symlinks; extern bool config_preserve_symlinks;
// Tells whether it is safe to call v8::Isolate::GetCurrent().
extern bool v8_initialized;
// Forward declaration // Forward declaration
class Environment; class Environment;

10
src/util-inl.h

@ -253,7 +253,15 @@ T* UncheckedRealloc(T* pointer, size_t n) {
return nullptr; 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. // As per spec realloc behaves like malloc if passed nullptr.

9
src/util.cc

@ -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 } // namespace node

5
src/util.h

@ -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* UncheckedMalloc(size_t n) { return UncheckedMalloc<char>(n); }
inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<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__ #ifdef __GNUC__
#define NO_RETURN __attribute__((noreturn)) #define NO_RETURN __attribute__((noreturn))
#else #else

4
test/cctest/util.cc

@ -90,6 +90,10 @@ TEST(UtilTest, ToLower) {
EXPECT_EQ('a', ToLower('A')); EXPECT_EQ('a', ToLower('A'));
} }
namespace node {
void LowMemoryNotification() {}
}
TEST(UtilTest, Malloc) { TEST(UtilTest, Malloc) {
using node::Malloc; using node::Malloc;
EXPECT_NE(nullptr, Malloc<char>(0)); EXPECT_NE(nullptr, Malloc<char>(0));

Loading…
Cancel
Save