From ff74931107598f017efc11e265c13f716dd9eab7 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Wed, 8 Apr 2015 11:10:12 +0200 Subject: [PATCH] smalloc: do not track external memory The memory that was allocated outside of the `smalloc.cc` should not be tracked using `AdjustAmountOfExternalAllocatedMemory`. There are no potential issues except triggering V8's GC way too often. In fact, `heap.js` is creating a buffer out of the pointer, and since it doesn't know the size of the pointer - it just creates the maximum possible `Buffer` instance with a no-op free callback and no hint. PR-URL: https://github.com/iojs/io.js/pull/1375 Reviewed-By: Ben Noordhuis --- src/smalloc.cc | 59 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/src/smalloc.cc b/src/smalloc.cc index 57ea97f2aca20e..1ac92ecb76bbfe 100644 --- a/src/smalloc.cc +++ b/src/smalloc.cc @@ -48,8 +48,14 @@ using v8::kExternalUint8Array; class CallbackInfo { public: + enum Ownership { + kInternal, + kExternal + }; + static inline void Free(char* data, void* hint); static inline CallbackInfo* New(Isolate* isolate, + Ownership ownership, Handle object, FreeCallback callback, void* hint = 0); @@ -59,10 +65,12 @@ class CallbackInfo { static void WeakCallback(const WeakCallbackData&); inline void WeakCallback(Isolate* isolate, Local object); inline CallbackInfo(Isolate* isolate, + Ownership ownership, Handle object, FreeCallback callback, void* hint); ~CallbackInfo(); + const Ownership ownership_; Persistent persistent_; FreeCallback const callback_; void* const hint_; @@ -76,10 +84,11 @@ void CallbackInfo::Free(char* data, void*) { CallbackInfo* CallbackInfo::New(Isolate* isolate, + CallbackInfo::Ownership ownership, Handle object, FreeCallback callback, void* hint) { - return new CallbackInfo(isolate, object, callback, hint); + return new CallbackInfo(isolate, ownership, object, callback, hint); } @@ -94,15 +103,18 @@ Persistent* CallbackInfo::persistent() { CallbackInfo::CallbackInfo(Isolate* isolate, + CallbackInfo::Ownership ownership, Handle object, FreeCallback callback, void* hint) - : persistent_(isolate, object), + : ownership_(ownership), + persistent_(isolate, object), callback_(callback), hint_(hint) { persistent_.SetWeak(this, WeakCallback); persistent_.SetWrapperClassId(ALLOC_ID); persistent_.MarkIndependent(); + isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this)); } @@ -129,9 +141,11 @@ void CallbackInfo::WeakCallback(Isolate* isolate, Local object) { array_length *= array_size; } object->SetIndexedPropertiesToExternalArrayData(nullptr, array_type, 0); - int64_t change_in_bytes = -static_cast(array_length + sizeof(*this)); - isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); callback_(static_cast(array_data), hint_); + int64_t change_in_bytes = -static_cast(sizeof(*this)); + if (ownership_ == kInternal) + change_in_bytes -= static_cast(array_length); + isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); delete this; } @@ -333,7 +347,10 @@ void Alloc(Environment* env, env->isolate()->AdjustAmountOfExternalAllocatedMemory(length); size_t size = length / ExternalArraySize(type); obj->SetIndexedPropertiesToExternalArrayData(data, type, size); - CallbackInfo::New(env->isolate(), obj, CallbackInfo::Free); + CallbackInfo::New(env->isolate(), + CallbackInfo::kInternal, + obj, + CallbackInfo::Free); } @@ -381,6 +398,25 @@ void AllocDispose(Environment* env, Handle obj) { } +static void Alloc(Environment* env, + CallbackInfo::Ownership ownership, + Handle obj, + char* data, + size_t length, + FreeCallback fn, + void* hint, + enum ExternalArrayType type) { + CHECK_EQ(false, obj->HasIndexedPropertiesInExternalArrayData()); + Isolate* isolate = env->isolate(); + HandleScope handle_scope(isolate); + env->set_using_smalloc_alloc_cb(true); + CallbackInfo* info = CallbackInfo::New(isolate, ownership, obj, fn, hint); + obj->SetHiddenValue(env->smalloc_p_string(), External::New(isolate, info)); + size_t size = length / ExternalArraySize(type); + obj->SetIndexedPropertiesToExternalArrayData(data, type, size); +} + + void Alloc(Environment* env, Handle obj, size_t length, @@ -404,7 +440,8 @@ void Alloc(Environment* env, UNREACHABLE(); } - Alloc(env, obj, data, length, fn, hint, type); + env->isolate()->AdjustAmountOfExternalAllocatedMemory(length); + Alloc(env, CallbackInfo::kInternal, obj, data, length, fn, hint, type); } @@ -415,15 +452,7 @@ void Alloc(Environment* env, FreeCallback fn, void* hint, enum ExternalArrayType type) { - CHECK_EQ(false, obj->HasIndexedPropertiesInExternalArrayData()); - Isolate* isolate = env->isolate(); - HandleScope handle_scope(isolate); - env->set_using_smalloc_alloc_cb(true); - CallbackInfo* info = CallbackInfo::New(isolate, obj, fn, hint); - obj->SetHiddenValue(env->smalloc_p_string(), External::New(isolate, info)); - isolate->AdjustAmountOfExternalAllocatedMemory(length + sizeof(*info)); - size_t size = length / ExternalArraySize(type); - obj->SetIndexedPropertiesToExternalArrayData(data, type, size); + Alloc(env, CallbackInfo::kExternal, obj, data, length, fn, hint, type); }