Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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}
  • Loading branch information
addaleax committed Sep 13, 2017
commit c82d22e024611176356561785e1ede0cf325d86f
9 changes: 9 additions & 0 deletions deps/v8/include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -7203,6 +7203,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
Expand All @@ -7213,13 +7215,16 @@ 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);

/**
* This function removes callback which was installed by
* AddGCPrologueCallback function.
*/
void RemoveGCPrologueCallback(GCCallbackWithData, void* data = nullptr);
void RemoveGCPrologueCallback(GCCallback callback);

/**
Expand All @@ -7236,13 +7241,17 @@ 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);

/**
* 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)();
Expand Down
65 changes: 47 additions & 18 deletions deps/v8/src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8341,41 +8341,70 @@ v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
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);
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<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);
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) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->heap()->RemoveGCEpilogueCallback(callback);
void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) {
void* data = reinterpret_cast<void*>(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) {
i::Isolate* isolate = i::Isolate::Current();
isolate->heap()->AddGCPrologueCallback(
reinterpret_cast<v8::Isolate::GCCallback>(callback), gc_type, false);
void Isolate::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) {
void* data = reinterpret_cast<void*>(callback);
AddGCEpilogueCallback(CallGCCallbackWithoutData, data, gc_type);
}

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) {
i::Isolate* isolate = i::Isolate::Current();
isolate->heap()->AddGCEpilogueCallback(
reinterpret_cast<v8::Isolate::GCCallback>(callback), gc_type, false);
void V8::AddGCPrologueCallback(v8::GCCallback callback, GCType gc_type) {
void* data = reinterpret_cast<void*>(callback);
Isolate::GetCurrent()->AddGCPrologueCallback(CallGCCallbackWithoutIsolate,
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) {
Expand Down
71 changes: 29 additions & 42 deletions deps/v8/src/heap/heap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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<v8::GCCallback>(info.callback);
callback(gc_type, flags);
} else {
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
info.callback(isolate, gc_type, flags);
}
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(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<v8::GCCallback>(info.callback);
callback(gc_type, gc_callback_flags);
} else {
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
info.callback(isolate, gc_type, gc_callback_flags);
}
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
info.callback(isolate, gc_type, flags, info.data);
}
}
}
Expand Down Expand Up @@ -5973,21 +5960,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;
Expand All @@ -5996,21 +5983,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;
Expand Down
34 changes: 18 additions & 16 deletions deps/v8/src/heap/heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -1422,13 +1422,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);
Expand Down Expand Up @@ -1588,17 +1590,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,
Expand Down Expand Up @@ -2262,8 +2264,8 @@ class Heap {

Object* encountered_transition_arrays_;

std::vector<GCCallbackPair> gc_epilogue_callbacks_;
std::vector<GCCallbackPair> gc_prologue_callbacks_;
std::vector<GCCallbackTuple> gc_epilogue_callbacks_;
std::vector<GCCallbackTuple> gc_prologue_callbacks_;

GetExternallyAllocatedMemoryInBytesCallback external_memory_callback_;

Expand Down
59 changes: 59 additions & 0 deletions deps/v8/test/cctest/test-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19626,6 +19626,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<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,
v8::GCType,
Expand Down Expand Up @@ -19700,6 +19713,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;
Expand Down