From b4ad15be5fc33a6f716d96a654c160ecf533cc88 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 8 Sep 2017 15:36:50 +0200 Subject: [PATCH] deps: cherry-pick 9b21865822243 from V8 upstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: [api] Add optional data pointer to GC callbacks This can be useful when there may be multiple callbacks attached by code that's not directly tied to a single isolate, e.g. working on a per-context basis. This also allows rephrasing the global non-isolate APIs in terms of this new API, rather than working around it inside `src/heap`. TBR=hpayer@chromium.org Bug: Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng Change-Id: I2e490ec40d1a34ea812f25f41ef9741d2116d965 Reviewed-on: https://chromium-review.googlesource.com/647548 Reviewed-by: Yang Guo Reviewed-by: Adam Klein Commit-Queue: Yang Guo Cr-Commit-Position: refs/heads/master@{#47923} PR-URL: https://github.com/nodejs/node/pull/15391 Reviewed-By: James M Snell Reviewed-By: Michaƫl Zasso --- deps/v8/include/v8.h | 9 +++++ deps/v8/src/api.cc | 65 +++++++++++++++++++++--------- deps/v8/src/heap/heap.cc | 71 ++++++++++++++------------------- deps/v8/src/heap/heap.h | 34 ++++++++-------- deps/v8/test/cctest/test-api.cc | 59 +++++++++++++++++++++++++++ 5 files changed, 162 insertions(+), 76 deletions(-) diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 6bf0e1d7bf9bff..931dd9a6280c29 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -7169,6 +7169,8 @@ class V8_EXPORT Isolate { typedef void (*GCCallback)(Isolate* isolate, GCType type, GCCallbackFlags flags); + typedef void (*GCCallbackWithData)(Isolate* isolate, GCType type, + GCCallbackFlags flags, void* data); /** * Enables the host application to receive a notification before a @@ -7179,6 +7181,8 @@ class V8_EXPORT Isolate { * not possible to register the same callback function two times with * different GCType filters. */ + void AddGCPrologueCallback(GCCallbackWithData callback, void* data = nullptr, + GCType gc_type_filter = kGCTypeAll); void AddGCPrologueCallback(GCCallback callback, GCType gc_type_filter = kGCTypeAll); @@ -7186,6 +7190,7 @@ class V8_EXPORT Isolate { * This function removes callback which was installed by * AddGCPrologueCallback function. */ + void RemoveGCPrologueCallback(GCCallbackWithData, void* data = nullptr); void RemoveGCPrologueCallback(GCCallback callback); /** @@ -7202,6 +7207,8 @@ class V8_EXPORT Isolate { * not possible to register the same callback function two times with * different GCType filters. */ + void AddGCEpilogueCallback(GCCallbackWithData callback, void* data = nullptr, + GCType gc_type_filter = kGCTypeAll); void AddGCEpilogueCallback(GCCallback callback, GCType gc_type_filter = kGCTypeAll); @@ -7209,6 +7216,8 @@ class V8_EXPORT Isolate { * This function removes callback which was installed by * AddGCEpilogueCallback function. */ + void RemoveGCEpilogueCallback(GCCallbackWithData callback, + void* data = nullptr); void RemoveGCEpilogueCallback(GCCallback callback); typedef size_t (*GetExternallyAllocatedMemoryInBytesCallback)(); diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 4792a3e7ac38ba..2220e41b6cffe7 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -8338,41 +8338,70 @@ v8::Local Isolate::ThrowException(v8::Local value) { return v8::Undefined(reinterpret_cast(isolate)); } -void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) { +void Isolate::AddGCPrologueCallback(GCCallbackWithData callback, void* data, + GCType gc_type) { i::Isolate* isolate = reinterpret_cast(this); - isolate->heap()->AddGCPrologueCallback(callback, gc_type); + isolate->heap()->AddGCPrologueCallback(callback, gc_type, data); } - -void Isolate::RemoveGCPrologueCallback(GCCallback callback) { +void Isolate::RemoveGCPrologueCallback(GCCallbackWithData callback, + void* data) { i::Isolate* isolate = reinterpret_cast(this); - isolate->heap()->RemoveGCPrologueCallback(callback); + isolate->heap()->RemoveGCPrologueCallback(callback, data); } +void Isolate::AddGCEpilogueCallback(GCCallbackWithData callback, void* data, + GCType gc_type) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->heap()->AddGCEpilogueCallback(callback, gc_type, data); +} -void Isolate::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) { +void Isolate::RemoveGCEpilogueCallback(GCCallbackWithData callback, + void* data) { i::Isolate* isolate = reinterpret_cast(this); - isolate->heap()->AddGCEpilogueCallback(callback, gc_type); + isolate->heap()->RemoveGCEpilogueCallback(callback, data); } +static void CallGCCallbackWithoutData(Isolate* isolate, GCType type, + GCCallbackFlags flags, void* data) { + reinterpret_cast(data)(isolate, type, flags); +} -void Isolate::RemoveGCEpilogueCallback(GCCallback callback) { - i::Isolate* isolate = reinterpret_cast(this); - isolate->heap()->RemoveGCEpilogueCallback(callback); +void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) { + void* data = reinterpret_cast(callback); + AddGCPrologueCallback(CallGCCallbackWithoutData, data, gc_type); } +void Isolate::RemoveGCPrologueCallback(GCCallback callback) { + void* data = reinterpret_cast(callback); + RemoveGCPrologueCallback(CallGCCallbackWithoutData, data); +} -void V8::AddGCPrologueCallback(GCCallback callback, GCType gc_type) { - i::Isolate* isolate = i::Isolate::Current(); - isolate->heap()->AddGCPrologueCallback( - reinterpret_cast(callback), gc_type, false); +void Isolate::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) { + void* data = reinterpret_cast(callback); + AddGCEpilogueCallback(CallGCCallbackWithoutData, data, gc_type); +} + +void Isolate::RemoveGCEpilogueCallback(GCCallback callback) { + void* data = reinterpret_cast(callback); + RemoveGCEpilogueCallback(CallGCCallbackWithoutData, data); } +static void CallGCCallbackWithoutIsolate(Isolate* isolate, GCType type, + GCCallbackFlags flags, void* data) { + reinterpret_cast(data)(type, flags); +} -void V8::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) { - i::Isolate* isolate = i::Isolate::Current(); - isolate->heap()->AddGCEpilogueCallback( - reinterpret_cast(callback), gc_type, false); +void V8::AddGCPrologueCallback(v8::GCCallback callback, GCType gc_type) { + void* data = reinterpret_cast(callback); + Isolate::GetCurrent()->AddGCPrologueCallback(CallGCCallbackWithoutIsolate, + data, gc_type); +} + +void V8::AddGCEpilogueCallback(v8::GCCallback callback, GCType gc_type) { + void* data = reinterpret_cast(callback); + Isolate::GetCurrent()->AddGCEpilogueCallback(CallGCCallbackWithoutIsolate, + data, gc_type); } void Isolate::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) { diff --git a/deps/v8/src/heap/heap.cc b/deps/v8/src/heap/heap.cc index c391683844d3bb..b168c3104c7666 100644 --- a/deps/v8/src/heap/heap.cc +++ b/deps/v8/src/heap/heap.cc @@ -57,15 +57,16 @@ namespace v8 { namespace internal { -bool Heap::GCCallbackPair::operator==(const Heap::GCCallbackPair& other) const { - return other.callback == callback; +bool Heap::GCCallbackTuple::operator==( + const Heap::GCCallbackTuple& other) const { + return other.callback == callback && other.data == data; } -Heap::GCCallbackPair& Heap::GCCallbackPair::operator=( - const Heap::GCCallbackPair& other) { +Heap::GCCallbackTuple& Heap::GCCallbackTuple::operator=( + const Heap::GCCallbackTuple& other) { callback = other.callback; gc_type = other.gc_type; - pass_isolate = other.pass_isolate; + data = other.data; return *this; } @@ -1513,35 +1514,21 @@ bool Heap::PerformGarbageCollection( void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { RuntimeCallTimerScope runtime_timer(isolate(), &RuntimeCallStats::GCPrologueCallback); - for (const GCCallbackPair& info : gc_prologue_callbacks_) { + for (const GCCallbackTuple& info : gc_prologue_callbacks_) { if (gc_type & info.gc_type) { - if (!info.pass_isolate) { - v8::GCCallback callback = - reinterpret_cast(info.callback); - callback(gc_type, flags); - } else { - v8::Isolate* isolate = reinterpret_cast(this->isolate()); - info.callback(isolate, gc_type, flags); - } + v8::Isolate* isolate = reinterpret_cast(this->isolate()); + info.callback(isolate, gc_type, flags, info.data); } } } - -void Heap::CallGCEpilogueCallbacks(GCType gc_type, - GCCallbackFlags gc_callback_flags) { +void Heap::CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags) { RuntimeCallTimerScope runtime_timer(isolate(), &RuntimeCallStats::GCEpilogueCallback); - for (const GCCallbackPair& info : gc_epilogue_callbacks_) { + for (const GCCallbackTuple& info : gc_epilogue_callbacks_) { if (gc_type & info.gc_type) { - if (!info.pass_isolate) { - v8::GCCallback callback = - reinterpret_cast(info.callback); - callback(gc_type, gc_callback_flags); - } else { - v8::Isolate* isolate = reinterpret_cast(this->isolate()); - info.callback(isolate, gc_type, gc_callback_flags); - } + v8::Isolate* isolate = reinterpret_cast(this->isolate()); + info.callback(isolate, gc_type, flags, info.data); } } } @@ -5963,21 +5950,21 @@ void Heap::TearDown() { memory_allocator_ = nullptr; } - -void Heap::AddGCPrologueCallback(v8::Isolate::GCCallback callback, - GCType gc_type, bool pass_isolate) { +void Heap::AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback, + GCType gc_type, void* data) { DCHECK_NOT_NULL(callback); DCHECK(gc_prologue_callbacks_.end() == std::find(gc_prologue_callbacks_.begin(), gc_prologue_callbacks_.end(), - GCCallbackPair(callback, gc_type, pass_isolate))); - gc_prologue_callbacks_.emplace_back(callback, gc_type, pass_isolate); + GCCallbackTuple(callback, gc_type, data))); + gc_prologue_callbacks_.emplace_back(callback, gc_type, data); } - -void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallback callback) { +void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallbackWithData callback, + void* data) { DCHECK_NOT_NULL(callback); for (size_t i = 0; i < gc_prologue_callbacks_.size(); i++) { - if (gc_prologue_callbacks_[i].callback == callback) { + if (gc_prologue_callbacks_[i].callback == callback && + gc_prologue_callbacks_[i].data == data) { gc_prologue_callbacks_[i] = gc_prologue_callbacks_.back(); gc_prologue_callbacks_.pop_back(); return; @@ -5986,21 +5973,21 @@ void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallback callback) { UNREACHABLE(); } - -void Heap::AddGCEpilogueCallback(v8::Isolate::GCCallback callback, - GCType gc_type, bool pass_isolate) { +void Heap::AddGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback, + GCType gc_type, void* data) { DCHECK_NOT_NULL(callback); DCHECK(gc_epilogue_callbacks_.end() == std::find(gc_epilogue_callbacks_.begin(), gc_epilogue_callbacks_.end(), - GCCallbackPair(callback, gc_type, pass_isolate))); - gc_epilogue_callbacks_.emplace_back(callback, gc_type, pass_isolate); + GCCallbackTuple(callback, gc_type, data))); + gc_epilogue_callbacks_.emplace_back(callback, gc_type, data); } - -void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback) { +void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback, + void* data) { DCHECK_NOT_NULL(callback); for (size_t i = 0; i < gc_epilogue_callbacks_.size(); i++) { - if (gc_epilogue_callbacks_[i].callback == callback) { + if (gc_epilogue_callbacks_[i].callback == callback && + gc_epilogue_callbacks_[i].data == data) { gc_epilogue_callbacks_[i] = gc_epilogue_callbacks_.back(); gc_epilogue_callbacks_.pop_back(); return; diff --git a/deps/v8/src/heap/heap.h b/deps/v8/src/heap/heap.h index 44ef96b064597f..2ea58d886b5eac 100644 --- a/deps/v8/src/heap/heap.h +++ b/deps/v8/src/heap/heap.h @@ -1414,13 +1414,15 @@ class Heap { // Prologue/epilogue callback methods.======================================== // =========================================================================== - void AddGCPrologueCallback(v8::Isolate::GCCallback callback, - GCType gc_type_filter, bool pass_isolate = true); - void RemoveGCPrologueCallback(v8::Isolate::GCCallback callback); + void AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback, + GCType gc_type_filter, void* data); + void RemoveGCPrologueCallback(v8::Isolate::GCCallbackWithData callback, + void* data); - void AddGCEpilogueCallback(v8::Isolate::GCCallback callback, - GCType gc_type_filter, bool pass_isolate = true); - void RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback); + void AddGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback, + GCType gc_type_filter, void* data); + void RemoveGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback, + void* data); void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags); void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags); @@ -1580,17 +1582,17 @@ class Heap { RootListIndex index; }; - struct GCCallbackPair { - GCCallbackPair(v8::Isolate::GCCallback callback, GCType gc_type, - bool pass_isolate) - : callback(callback), gc_type(gc_type), pass_isolate(pass_isolate) {} + struct GCCallbackTuple { + GCCallbackTuple(v8::Isolate::GCCallbackWithData callback, GCType gc_type, + void* data) + : callback(callback), gc_type(gc_type), data(data) {} - bool operator==(const GCCallbackPair& other) const; - GCCallbackPair& operator=(const GCCallbackPair& other); + bool operator==(const GCCallbackTuple& other) const; + GCCallbackTuple& operator=(const GCCallbackTuple& other); - v8::Isolate::GCCallback callback; + v8::Isolate::GCCallbackWithData callback; GCType gc_type; - bool pass_isolate; + void* data; }; typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap, @@ -2254,8 +2256,8 @@ class Heap { Object* encountered_transition_arrays_; - std::vector gc_epilogue_callbacks_; - std::vector gc_prologue_callbacks_; + std::vector gc_epilogue_callbacks_; + std::vector gc_prologue_callbacks_; GetExternallyAllocatedMemoryInBytesCallback external_memory_callback_; diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index aa4cba5a602d89..06ce7c565e112a 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -19592,6 +19592,19 @@ void EpilogueCallbackSecond(v8::Isolate* isolate, ++epilogue_call_count_second; } +void PrologueCallbackNew(v8::Isolate* isolate, v8::GCType, + v8::GCCallbackFlags flags, void* data) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); + CHECK_EQ(gc_callbacks_isolate, isolate); + ++*static_cast(data); +} + +void EpilogueCallbackNew(v8::Isolate* isolate, v8::GCType, + v8::GCCallbackFlags flags, void* data) { + CHECK_EQ(flags, v8::kNoGCCallbackFlags); + CHECK_EQ(gc_callbacks_isolate, isolate); + ++*static_cast(data); +} void PrologueCallbackAlloc(v8::Isolate* isolate, v8::GCType, @@ -19666,6 +19679,52 @@ TEST(GCCallbacksOld) { CHECK_EQ(2, epilogue_call_count_second); } +TEST(GCCallbacksWithData) { + LocalContext context; + + gc_callbacks_isolate = context->GetIsolate(); + int prologue1 = 0; + int epilogue1 = 0; + int prologue2 = 0; + int epilogue2 = 0; + + context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue1); + context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue1); + CHECK_EQ(0, prologue1); + CHECK_EQ(0, epilogue1); + CHECK_EQ(0, prologue2); + CHECK_EQ(0, epilogue2); + CcTest::CollectAllGarbage(); + CHECK_EQ(1, prologue1); + CHECK_EQ(1, epilogue1); + CHECK_EQ(0, prologue2); + CHECK_EQ(0, epilogue2); + context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue2); + context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue2); + CcTest::CollectAllGarbage(); + CHECK_EQ(2, prologue1); + CHECK_EQ(2, epilogue1); + CHECK_EQ(1, prologue2); + CHECK_EQ(1, epilogue2); + context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew, + &prologue1); + context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew, + &epilogue1); + CcTest::CollectAllGarbage(); + CHECK_EQ(2, prologue1); + CHECK_EQ(2, epilogue1); + CHECK_EQ(2, prologue2); + CHECK_EQ(2, epilogue2); + context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew, + &prologue2); + context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew, + &epilogue2); + CcTest::CollectAllGarbage(); + CHECK_EQ(2, prologue1); + CHECK_EQ(2, epilogue1); + CHECK_EQ(2, prologue2); + CHECK_EQ(2, epilogue2); +} TEST(GCCallbacks) { LocalContext context;