From 0157e3ebca5692620090b2c1f1abede81512bc87 Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Mon, 19 Nov 2018 17:00:25 -0800 Subject: [PATCH] src,deps: add ABI safe use of CheckMemoryPressure CheckMemoryPressure cannot be used ABI-safely from v8.h. Add a alternate implementation of AdjustAmountOfExternalAllocatedMemory and then use that from Node. PR-URL: https://github.com/nodejs/node/pull/24499 Reviewed-By: Anna Henningsen Reviewed-By: Yang Guo Reviewed-By: Myles Borins --- deps/v8/include/v8-version.h | 2 +- deps/v8/include/v8.h | 6 ++++++ deps/v8/src/api.cc | 34 ++++++++++++++++++++++++++++++++++ src/node_api.cc | 2 +- src/node_buffer.cc | 4 ++-- src/node_crypto.cc | 2 +- src/node_crypto.h | 7 ++++--- src/node_crypto_bio.h | 4 ++-- src/node_process.cc | 2 +- src/node_zlib.cc | 10 ++++++---- src/string_bytes.cc | 4 ++-- 11 files changed, 60 insertions(+), 17 deletions(-) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 73d98b3a9ba8f2..95cc3573a3f723 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 2 #define V8_BUILD_NUMBER 414 -#define V8_PATCH_LEVEL 71 +#define V8_PATCH_LEVEL 72 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index eaf1e5b5ca2485..c262a4822941d8 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -7207,6 +7207,12 @@ class V8_EXPORT Isolate { V8_INLINE int64_t AdjustAmountOfExternalAllocatedMemory(int64_t change_in_bytes); + /** + * This is a Node.js 8.x specific version of the function that uses + * CheckMemoryPressure. + */ + int64_t AdjustAmountOfExternalAllocatedMemoryCustom(int64_t change_in_bytes); + /** * Returns the number of phantom handles without callbacks that were reset * by the garbage collector since the last call to this function. diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index bc5848e939420a..ef8b6f858a7a8d 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -8879,6 +8879,40 @@ void Isolate::GetStackSample(const RegisterState& state, void** frames, sample_info->external_callback_entry = nullptr; } +int64_t Isolate::AdjustAmountOfExternalAllocatedMemoryCustom( + int64_t change_in_bytes) { + const int64_t kMemoryReducerActivationLimit = 1024 * 1024; + typedef internal::Internals I; + int64_t* external_memory = reinterpret_cast( + reinterpret_cast(this) + I::kExternalMemoryOffset); + int64_t* external_memory_limit = reinterpret_cast( + reinterpret_cast(this) + I::kExternalMemoryLimitOffset); + int64_t* external_memory_at_last_mc = + reinterpret_cast(reinterpret_cast(this) + + I::kExternalMemoryAtLastMarkCompactOffset); + const int64_t amount = *external_memory + change_in_bytes; + + *external_memory = amount; + + int64_t allocation_diff_since_last_mc = + *external_memory_at_last_mc - *external_memory; + allocation_diff_since_last_mc = allocation_diff_since_last_mc < 0 + ? -allocation_diff_since_last_mc + : allocation_diff_since_last_mc; + if (allocation_diff_since_last_mc > kMemoryReducerActivationLimit) { + CheckMemoryPressure(); + } + + if (change_in_bytes < 0) { + *external_memory_limit += change_in_bytes; + } + + if (change_in_bytes > 0 && amount > *external_memory_limit) { + ReportExternalAllocationLimitReached(); + } + return *external_memory; +} + size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() { i::Isolate* isolate = reinterpret_cast(this); size_t result = isolate->global_handles()->NumberOfPhantomHandleResets(); diff --git a/src/node_api.cc b/src/node_api.cc index 97ce7e5c9f05ef..61e9f6b4b00279 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -3326,7 +3326,7 @@ napi_status napi_adjust_external_memory(napi_env env, CHECK_ENV(env); CHECK_ARG(env, adjusted_value); - *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemory( + *adjusted_value = env->isolate->AdjustAmountOfExternalAllocatedMemoryCustom( change_in_bytes); return napi_clear_last_error(env); diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 3b0e453f83f591..6e3ff2cb124ed2 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -143,7 +143,7 @@ CallbackInfo::CallbackInfo(Isolate* isolate, persistent_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter); persistent_.SetWrapperClassId(BUFFER_ID); persistent_.MarkIndependent(); - isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this)); + isolate->AdjustAmountOfExternalAllocatedMemoryCustom(sizeof(*this)); } @@ -163,7 +163,7 @@ void CallbackInfo::WeakCallback( void CallbackInfo::WeakCallback(Isolate* isolate) { callback_(data_, hint_); int64_t change_in_bytes = -static_cast(sizeof(*this)); - isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); + isolate->AdjustAmountOfExternalAllocatedMemoryCustom(change_in_bytes); } diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 66ed992f9b0da5..c3779c07cccb74 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -2789,7 +2789,7 @@ void SSLWrap::DestroySSL() { return; SSL_free(ssl_); - env_->isolate()->AdjustAmountOfExternalAllocatedMemory(-kExternalSize); + env_->isolate()->AdjustAmountOfExternalAllocatedMemoryCustom(-kExternalSize); ssl_ = nullptr; } diff --git a/src/node_crypto.h b/src/node_crypto.h index cd8f17b11085c1..58f5b72405f2bc 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -168,7 +168,7 @@ class SecureContext : public BaseObject { cert_(nullptr), issuer_(nullptr) { MakeWeak(this); - env->isolate()->AdjustAmountOfExternalAllocatedMemory(kExternalSize); + env->isolate()->AdjustAmountOfExternalAllocatedMemoryCustom(kExternalSize); } void FreeCTXMem() { @@ -176,7 +176,8 @@ class SecureContext : public BaseObject { return; } - env()->isolate()->AdjustAmountOfExternalAllocatedMemory(-kExternalSize); + env()->isolate()->AdjustAmountOfExternalAllocatedMemoryCustom( + -kExternalSize); SSL_CTX_free(ctx_); if (cert_ != nullptr) X509_free(cert_); @@ -208,7 +209,7 @@ class SSLWrap { cert_cb_arg_(nullptr), cert_cb_running_(false) { ssl_ = SSL_new(sc->ctx_); - env_->isolate()->AdjustAmountOfExternalAllocatedMemory(kExternalSize); + env_->isolate()->AdjustAmountOfExternalAllocatedMemoryCustom(kExternalSize); CHECK_NE(ssl_, nullptr); } diff --git a/src/node_crypto_bio.h b/src/node_crypto_bio.h index 380a3a6b4c64f5..25138794207a23 100644 --- a/src/node_crypto_bio.h +++ b/src/node_crypto_bio.h @@ -135,14 +135,14 @@ class NodeBIO { next_(nullptr) { data_ = new char[len]; if (env_ != nullptr) - env_->isolate()->AdjustAmountOfExternalAllocatedMemory(len); + env_->isolate()->AdjustAmountOfExternalAllocatedMemoryCustom(len); } ~Buffer() { delete[] data_; if (env_ != nullptr) { const int64_t len = static_cast(len_); - env_->isolate()->AdjustAmountOfExternalAllocatedMemory(-len); + env_->isolate()->AdjustAmountOfExternalAllocatedMemoryCustom(-len); } } diff --git a/src/node_process.cc b/src/node_process.cc index f953f5fec3740a..5f6e34818d49c0 100644 --- a/src/node_process.cc +++ b/src/node_process.cc @@ -168,7 +168,7 @@ void MemoryUsage(const FunctionCallbackInfo& args) { fields[0] = rss; fields[1] = v8_heap_stats.total_heap_size(); fields[2] = v8_heap_stats.used_heap_size(); - fields[3] = isolate->AdjustAmountOfExternalAllocatedMemory(0); + fields[3] = isolate->AdjustAmountOfExternalAllocatedMemoryCustom(0); } // Most of the time, it's best to use `console.error` to write diff --git a/src/node_zlib.cc b/src/node_zlib.cc index eafdea4379d694..31201fbd36fd2b 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -109,12 +109,14 @@ class ZCtx : public AsyncWrap { if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) { (void)deflateEnd(&strm_); int64_t change_in_bytes = -static_cast(kDeflateContextSize); - env()->isolate()->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); + env()->isolate()->AdjustAmountOfExternalAllocatedMemoryCustom( + change_in_bytes); } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW || mode_ == UNZIP) { (void)inflateEnd(&strm_); int64_t change_in_bytes = -static_cast(kInflateContextSize); - env()->isolate()->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); + env()->isolate()->AdjustAmountOfExternalAllocatedMemoryCustom( + change_in_bytes); } mode_ = NONE; @@ -536,7 +538,7 @@ class ZCtx : public AsyncWrap { ctx->memLevel_, ctx->strategy_); ctx->env()->isolate() - ->AdjustAmountOfExternalAllocatedMemory(kDeflateContextSize); + ->AdjustAmountOfExternalAllocatedMemoryCustom(kDeflateContextSize); break; case INFLATE: case GUNZIP: @@ -544,7 +546,7 @@ class ZCtx : public AsyncWrap { case UNZIP: ctx->err_ = inflateInit2(&ctx->strm_, ctx->windowBits_); ctx->env()->isolate() - ->AdjustAmountOfExternalAllocatedMemory(kInflateContextSize); + ->AdjustAmountOfExternalAllocatedMemoryCustom(kInflateContextSize); break; default: UNREACHABLE(); diff --git a/src/string_bytes.cc b/src/string_bytes.cc index 2e41c1478c92fc..0ecb854a4e02a1 100644 --- a/src/string_bytes.cc +++ b/src/string_bytes.cc @@ -66,7 +66,7 @@ class ExternString: public ResourceType { public: ~ExternString() override { free(const_cast(data_)); - isolate()->AdjustAmountOfExternalAllocatedMemory(-byte_length()); + isolate()->AdjustAmountOfExternalAllocatedMemoryCustom(-byte_length()); } const TypeName* data() const override { @@ -122,7 +122,7 @@ class ExternString: public ResourceType { data, length); MaybeLocal str = NewExternal(isolate, h_str); - isolate->AdjustAmountOfExternalAllocatedMemory(h_str->byte_length()); + isolate->AdjustAmountOfExternalAllocatedMemoryCustom(h_str->byte_length()); if (str.IsEmpty()) { delete h_str;