Browse Source

deps: cherry-pick 9b21865822243 from V8 upstream

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 <yangguo@chromium.org>
    Reviewed-by: Adam Klein <adamk@chromium.org>
    Commit-Queue: Yang Guo <yangguo@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#47923}

PR-URL: https://github.com/nodejs/node/pull/15391
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
canary-base
Anna Henningsen 7 years ago
committed by James M Snell
parent
commit
8403d6b999
  1. 9
      deps/v8/include/v8.h
  2. 65
      deps/v8/src/api.cc
  3. 67
      deps/v8/src/heap/heap.cc
  4. 34
      deps/v8/src/heap/heap.h
  5. 59
      deps/v8/test/cctest/test-api.cc

9
deps/v8/include/v8.h

@ -7203,6 +7203,8 @@ class V8_EXPORT Isolate {
typedef void (*GCCallback)(Isolate* isolate, GCType type, typedef void (*GCCallback)(Isolate* isolate, GCType type,
GCCallbackFlags flags); GCCallbackFlags flags);
typedef void (*GCCallbackWithData)(Isolate* isolate, GCType type,
GCCallbackFlags flags, void* data);
/** /**
* Enables the host application to receive a notification before a * Enables the host application to receive a notification before a
@ -7213,6 +7215,8 @@ class V8_EXPORT Isolate {
* not possible to register the same callback function two times with * not possible to register the same callback function two times with
* different GCType filters. * different GCType filters.
*/ */
void AddGCPrologueCallback(GCCallbackWithData callback, void* data = nullptr,
GCType gc_type_filter = kGCTypeAll);
void AddGCPrologueCallback(GCCallback callback, void AddGCPrologueCallback(GCCallback callback,
GCType gc_type_filter = kGCTypeAll); GCType gc_type_filter = kGCTypeAll);
@ -7220,6 +7224,7 @@ class V8_EXPORT Isolate {
* This function removes callback which was installed by * This function removes callback which was installed by
* AddGCPrologueCallback function. * AddGCPrologueCallback function.
*/ */
void RemoveGCPrologueCallback(GCCallbackWithData, void* data = nullptr);
void RemoveGCPrologueCallback(GCCallback callback); void RemoveGCPrologueCallback(GCCallback callback);
/** /**
@ -7236,6 +7241,8 @@ class V8_EXPORT Isolate {
* not possible to register the same callback function two times with * not possible to register the same callback function two times with
* different GCType filters. * different GCType filters.
*/ */
void AddGCEpilogueCallback(GCCallbackWithData callback, void* data = nullptr,
GCType gc_type_filter = kGCTypeAll);
void AddGCEpilogueCallback(GCCallback callback, void AddGCEpilogueCallback(GCCallback callback,
GCType gc_type_filter = kGCTypeAll); GCType gc_type_filter = kGCTypeAll);
@ -7243,6 +7250,8 @@ class V8_EXPORT Isolate {
* This function removes callback which was installed by * This function removes callback which was installed by
* AddGCEpilogueCallback function. * AddGCEpilogueCallback function.
*/ */
void RemoveGCEpilogueCallback(GCCallbackWithData callback,
void* data = nullptr);
void RemoveGCEpilogueCallback(GCCallback callback); void RemoveGCEpilogueCallback(GCCallback callback);
typedef size_t (*GetExternallyAllocatedMemoryInBytesCallback)(); typedef size_t (*GetExternallyAllocatedMemoryInBytesCallback)();

65
deps/v8/src/api.cc

@ -8341,41 +8341,70 @@ v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
} }
void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) { void Isolate::AddGCPrologueCallback(GCCallbackWithData callback, void* data,
GCType gc_type) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->heap()->AddGCPrologueCallback(callback, gc_type); isolate->heap()->AddGCPrologueCallback(callback, gc_type, data);
} }
void Isolate::RemoveGCPrologueCallback(GCCallbackWithData callback,
void Isolate::RemoveGCPrologueCallback(GCCallback callback) { void* data) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(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<i::Isolate*>(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<i::Isolate*>(this); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(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<Isolate::GCCallback>(data)(isolate, type, flags);
}
void Isolate::RemoveGCEpilogueCallback(GCCallback callback) { void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); void* data = reinterpret_cast<void*>(callback);
isolate->heap()->RemoveGCEpilogueCallback(callback); AddGCPrologueCallback(CallGCCallbackWithoutData, data, gc_type);
} }
void Isolate::RemoveGCPrologueCallback(GCCallback callback) {
void* data = reinterpret_cast<void*>(callback);
RemoveGCPrologueCallback(CallGCCallbackWithoutData, data);
}
void V8::AddGCPrologueCallback(GCCallback callback, GCType gc_type) { void Isolate::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) {
i::Isolate* isolate = i::Isolate::Current(); void* data = reinterpret_cast<void*>(callback);
isolate->heap()->AddGCPrologueCallback( AddGCEpilogueCallback(CallGCCallbackWithoutData, data, gc_type);
reinterpret_cast<v8::Isolate::GCCallback>(callback), gc_type, false); }
void Isolate::RemoveGCEpilogueCallback(GCCallback callback) {
void* data = reinterpret_cast<void*>(callback);
RemoveGCEpilogueCallback(CallGCCallbackWithoutData, data);
} }
static void CallGCCallbackWithoutIsolate(Isolate* isolate, GCType type,
GCCallbackFlags flags, void* data) {
reinterpret_cast<v8::GCCallback>(data)(type, flags);
}
void V8::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) { void V8::AddGCPrologueCallback(v8::GCCallback callback, GCType gc_type) {
i::Isolate* isolate = i::Isolate::Current(); void* data = reinterpret_cast<void*>(callback);
isolate->heap()->AddGCEpilogueCallback( Isolate::GetCurrent()->AddGCPrologueCallback(CallGCCallbackWithoutIsolate,
reinterpret_cast<v8::Isolate::GCCallback>(callback), gc_type, false); data, gc_type);
}
void V8::AddGCEpilogueCallback(v8::GCCallback callback, GCType gc_type) {
void* data = reinterpret_cast<void*>(callback);
Isolate::GetCurrent()->AddGCEpilogueCallback(CallGCCallbackWithoutIsolate,
data, gc_type);
} }
void Isolate::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) { void Isolate::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {

67
deps/v8/src/heap/heap.cc

@ -57,15 +57,16 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
bool Heap::GCCallbackPair::operator==(const Heap::GCCallbackPair& other) const { bool Heap::GCCallbackTuple::operator==(
return other.callback == callback; const Heap::GCCallbackTuple& other) const {
return other.callback == callback && other.data == data;
} }
Heap::GCCallbackPair& Heap::GCCallbackPair::operator=( Heap::GCCallbackTuple& Heap::GCCallbackTuple::operator=(
const Heap::GCCallbackPair& other) { const Heap::GCCallbackTuple& other) {
callback = other.callback; callback = other.callback;
gc_type = other.gc_type; gc_type = other.gc_type;
pass_isolate = other.pass_isolate; data = other.data;
return *this; return *this;
} }
@ -1513,35 +1514,21 @@ bool Heap::PerformGarbageCollection(
void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) {
RuntimeCallTimerScope runtime_timer(isolate(), RuntimeCallTimerScope runtime_timer(isolate(),
&RuntimeCallStats::GCPrologueCallback); &RuntimeCallStats::GCPrologueCallback);
for (const GCCallbackPair& info : gc_prologue_callbacks_) { for (const GCCallbackTuple& info : gc_prologue_callbacks_) {
if (gc_type & info.gc_type) { if (gc_type & info.gc_type) {
if (!info.pass_isolate) {
v8::GCCallback callback =
reinterpret_cast<v8::GCCallback>(info.callback);
callback(gc_type, flags);
} else {
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate()); v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
info.callback(isolate, gc_type, flags); info.callback(isolate, gc_type, flags, info.data);
}
} }
} }
} }
void Heap::CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags) {
void Heap::CallGCEpilogueCallbacks(GCType gc_type,
GCCallbackFlags gc_callback_flags) {
RuntimeCallTimerScope runtime_timer(isolate(), RuntimeCallTimerScope runtime_timer(isolate(),
&RuntimeCallStats::GCEpilogueCallback); &RuntimeCallStats::GCEpilogueCallback);
for (const GCCallbackPair& info : gc_epilogue_callbacks_) { for (const GCCallbackTuple& info : gc_epilogue_callbacks_) {
if (gc_type & info.gc_type) { if (gc_type & info.gc_type) {
if (!info.pass_isolate) {
v8::GCCallback callback =
reinterpret_cast<v8::GCCallback>(info.callback);
callback(gc_type, gc_callback_flags);
} else {
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate()); v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
info.callback(isolate, gc_type, gc_callback_flags); info.callback(isolate, gc_type, flags, info.data);
}
} }
} }
} }
@ -5973,21 +5960,21 @@ void Heap::TearDown() {
memory_allocator_ = nullptr; memory_allocator_ = nullptr;
} }
void Heap::AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
void Heap::AddGCPrologueCallback(v8::Isolate::GCCallback callback, GCType gc_type, void* data) {
GCType gc_type, bool pass_isolate) {
DCHECK_NOT_NULL(callback); DCHECK_NOT_NULL(callback);
DCHECK(gc_prologue_callbacks_.end() == DCHECK(gc_prologue_callbacks_.end() ==
std::find(gc_prologue_callbacks_.begin(), gc_prologue_callbacks_.end(), std::find(gc_prologue_callbacks_.begin(), gc_prologue_callbacks_.end(),
GCCallbackPair(callback, gc_type, pass_isolate))); GCCallbackTuple(callback, gc_type, data)));
gc_prologue_callbacks_.emplace_back(callback, gc_type, pass_isolate); gc_prologue_callbacks_.emplace_back(callback, gc_type, data);
} }
void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallback callback) { void* data) {
DCHECK_NOT_NULL(callback); DCHECK_NOT_NULL(callback);
for (size_t i = 0; i < gc_prologue_callbacks_.size(); i++) { 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_[i] = gc_prologue_callbacks_.back();
gc_prologue_callbacks_.pop_back(); gc_prologue_callbacks_.pop_back();
return; return;
@ -5996,21 +5983,21 @@ void Heap::RemoveGCPrologueCallback(v8::Isolate::GCCallback callback) {
UNREACHABLE(); UNREACHABLE();
} }
void Heap::AddGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
void Heap::AddGCEpilogueCallback(v8::Isolate::GCCallback callback, GCType gc_type, void* data) {
GCType gc_type, bool pass_isolate) {
DCHECK_NOT_NULL(callback); DCHECK_NOT_NULL(callback);
DCHECK(gc_epilogue_callbacks_.end() == DCHECK(gc_epilogue_callbacks_.end() ==
std::find(gc_epilogue_callbacks_.begin(), gc_epilogue_callbacks_.end(), std::find(gc_epilogue_callbacks_.begin(), gc_epilogue_callbacks_.end(),
GCCallbackPair(callback, gc_type, pass_isolate))); GCCallbackTuple(callback, gc_type, data)));
gc_epilogue_callbacks_.emplace_back(callback, gc_type, pass_isolate); gc_epilogue_callbacks_.emplace_back(callback, gc_type, data);
} }
void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback) { void* data) {
DCHECK_NOT_NULL(callback); DCHECK_NOT_NULL(callback);
for (size_t i = 0; i < gc_epilogue_callbacks_.size(); i++) { 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_[i] = gc_epilogue_callbacks_.back();
gc_epilogue_callbacks_.pop_back(); gc_epilogue_callbacks_.pop_back();
return; return;

34
deps/v8/src/heap/heap.h

@ -1422,13 +1422,15 @@ class Heap {
// Prologue/epilogue callback methods.======================================== // Prologue/epilogue callback methods.========================================
// =========================================================================== // ===========================================================================
void AddGCPrologueCallback(v8::Isolate::GCCallback callback, void AddGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
GCType gc_type_filter, bool pass_isolate = true); GCType gc_type_filter, void* data);
void RemoveGCPrologueCallback(v8::Isolate::GCCallback callback); void RemoveGCPrologueCallback(v8::Isolate::GCCallbackWithData callback,
void* data);
void AddGCEpilogueCallback(v8::Isolate::GCCallback callback, void AddGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
GCType gc_type_filter, bool pass_isolate = true); GCType gc_type_filter, void* data);
void RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback); void RemoveGCEpilogueCallback(v8::Isolate::GCCallbackWithData callback,
void* data);
void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags); void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags);
void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags); void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags);
@ -1588,17 +1590,17 @@ class Heap {
RootListIndex index; RootListIndex index;
}; };
struct GCCallbackPair { struct GCCallbackTuple {
GCCallbackPair(v8::Isolate::GCCallback callback, GCType gc_type, GCCallbackTuple(v8::Isolate::GCCallbackWithData callback, GCType gc_type,
bool pass_isolate) void* data)
: callback(callback), gc_type(gc_type), pass_isolate(pass_isolate) {} : callback(callback), gc_type(gc_type), data(data) {}
bool operator==(const GCCallbackPair& other) const; bool operator==(const GCCallbackTuple& other) const;
GCCallbackPair& operator=(const GCCallbackPair& other); GCCallbackTuple& operator=(const GCCallbackTuple& other);
v8::Isolate::GCCallback callback; v8::Isolate::GCCallbackWithData callback;
GCType gc_type; GCType gc_type;
bool pass_isolate; void* data;
}; };
typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap, typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap,
@ -2262,8 +2264,8 @@ class Heap {
Object* encountered_transition_arrays_; Object* encountered_transition_arrays_;
std::vector<GCCallbackPair> gc_epilogue_callbacks_; std::vector<GCCallbackTuple> gc_epilogue_callbacks_;
std::vector<GCCallbackPair> gc_prologue_callbacks_; std::vector<GCCallbackTuple> gc_prologue_callbacks_;
GetExternallyAllocatedMemoryInBytesCallback external_memory_callback_; GetExternallyAllocatedMemoryInBytesCallback external_memory_callback_;

59
deps/v8/test/cctest/test-api.cc

@ -19626,6 +19626,19 @@ void EpilogueCallbackSecond(v8::Isolate* isolate,
++epilogue_call_count_second; ++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<int*>(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<int*>(data);
}
void PrologueCallbackAlloc(v8::Isolate* isolate, void PrologueCallbackAlloc(v8::Isolate* isolate,
v8::GCType, v8::GCType,
@ -19700,6 +19713,52 @@ TEST(GCCallbacksOld) {
CHECK_EQ(2, epilogue_call_count_second); 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) { TEST(GCCallbacks) {
LocalContext context; LocalContext context;

Loading…
Cancel
Save