Commit edef7f13 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[api,global-handle] Introduce TracedGlobal::SetFinalizationCallback

Introduce a way to set a custom finalization callback that can be used
to signal and set up destruction of embedder memory.

Bug: chromium:923361
Change-Id: Ifc62ebd534aba3b02511c74b59161ec3edc0ee0d
Reviewed-on: https://chromium-review.googlesource.com/c/1452447
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59381}
parent 8408dbaf
...@@ -941,6 +941,19 @@ class V8_EXPORT TracedGlobal { ...@@ -941,6 +941,19 @@ class V8_EXPORT TracedGlobal {
*/ */
V8_INLINE uint16_t WrapperClassId() const; V8_INLINE uint16_t WrapperClassId() const;
/**
* Adds a finalization callback to the handle. The type of this callback is
* similar to WeakCallbackType::kInternalFields, i.e., it will pass the
* parameter and the first two internal fields of the object.
*
* The callback is then supposed to reset the handle in the callback. No
* further V8 API may be called in this callback. In case additional work
* involving V8 needs to be done, a second callback can be scheduled using
* WeakCallbackInfo<void>::SetSecondPassCallback.
*/
V8_INLINE void SetFinalizationCallback(
void* parameter, WeakCallbackInfo<void>::Callback callback);
private: private:
V8_INLINE static T* New(Isolate* isolate, T* that, T** slot); V8_INLINE static T* New(Isolate* isolate, T* that, T** slot);
...@@ -8681,6 +8694,9 @@ class V8_EXPORT V8 { ...@@ -8681,6 +8694,9 @@ class V8_EXPORT V8 {
WeakCallbackType type); WeakCallbackType type);
static void MakeWeak(internal::Address** location_addr); static void MakeWeak(internal::Address** location_addr);
static void* ClearWeak(internal::Address* location); static void* ClearWeak(internal::Address* location);
static void SetFinalizationCallbackTraced(
internal::Address* location, void* parameter,
WeakCallbackInfo<void>::Callback callback);
static void AnnotateStrongRetainer(internal::Address* location, static void AnnotateStrongRetainer(internal::Address* location,
const char* label); const char* label);
static Value* Eternalize(Isolate* isolate, Value* handle); static Value* Eternalize(Isolate* isolate, Value* handle);
...@@ -9858,6 +9874,13 @@ uint16_t TracedGlobal<T>::WrapperClassId() const { ...@@ -9858,6 +9874,13 @@ uint16_t TracedGlobal<T>::WrapperClassId() const {
return *reinterpret_cast<uint16_t*>(addr); return *reinterpret_cast<uint16_t*>(addr);
} }
template <class T>
void TracedGlobal<T>::SetFinalizationCallback(
void* parameter, typename WeakCallbackInfo<void>::Callback callback) {
V8::SetFinalizationCallbackTraced(
reinterpret_cast<internal::Address*>(this->val_), parameter, callback);
}
template <typename T> template <typename T>
ReturnValue<T>::ReturnValue(internal::Address* slot) : value_(slot) {} ReturnValue<T>::ReturnValue(internal::Address* slot) : value_(slot) {}
......
...@@ -1074,6 +1074,13 @@ void V8::DisposeTracedGlobal(internal::Address* location) { ...@@ -1074,6 +1074,13 @@ void V8::DisposeTracedGlobal(internal::Address* location) {
i::GlobalHandles::DestroyTraced(location); i::GlobalHandles::DestroyTraced(location);
} }
void V8::SetFinalizationCallbackTraced(
internal::Address* location, void* parameter,
WeakCallbackInfo<void>::Callback callback) {
i::GlobalHandles::SetFinalizationCallbackForTraced(location, parameter,
callback);
}
Value* V8::Eternalize(Isolate* v8_isolate, Value* value) { Value* V8::Eternalize(Isolate* v8_isolate, Value* value) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
i::Object object = *Utils::OpenHandle(value); i::Object object = *Utils::OpenHandle(value);
......
This diff is collapsed.
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_GLOBAL_HANDLES_H_ #define V8_GLOBAL_HANDLES_H_
#include <type_traits> #include <type_traits>
#include <utility>
#include <vector> #include <vector>
#include "include/v8.h" #include "include/v8.h"
...@@ -43,17 +44,16 @@ class GlobalHandles final { ...@@ -43,17 +44,16 @@ class GlobalHandles final {
template <class NodeType> template <class NodeType>
class NodeBlock; class NodeBlock;
// Move a global handle. //
static void MoveGlobal(Address** from, Address** to); // API for regular handles.
static void MoveTracedGlobal(Address** from, Address** to); //
// Destroy a global handle. static void MoveGlobal(Address** from, Address** to);
static void Destroy(Address* location);
static void DestroyTraced(Address* location);
// Copy a global handle.
static Handle<Object> CopyGlobal(Address* location); static Handle<Object> CopyGlobal(Address* location);
static void Destroy(Address* location);
// Make the global handle weak and set the callback parameter for the // Make the global handle weak and set the callback parameter for the
// handle. When the garbage collector recognizes that only weak global // handle. When the garbage collector recognizes that only weak global
// handles point to an object the callback function is invoked (for each // handles point to an object the callback function is invoked (for each
...@@ -66,7 +66,6 @@ class GlobalHandles final { ...@@ -66,7 +66,6 @@ class GlobalHandles final {
static void MakeWeak(Address* location, void* parameter, static void MakeWeak(Address* location, void* parameter,
WeakCallbackInfo<void>::Callback weak_callback, WeakCallbackInfo<void>::Callback weak_callback,
v8::WeakCallbackType type); v8::WeakCallbackType type);
static void MakeWeak(Address** location_addr); static void MakeWeak(Address** location_addr);
static void AnnotateStrongRetainer(Address* location, const char* label); static void AnnotateStrongRetainer(Address* location, const char* label);
...@@ -80,6 +79,16 @@ class GlobalHandles final { ...@@ -80,6 +79,16 @@ class GlobalHandles final {
// Tells whether global handle is weak. // Tells whether global handle is weak.
static bool IsWeak(Address* location); static bool IsWeak(Address* location);
//
// API for traced handles.
//
static void MoveTracedGlobal(Address** from, Address** to);
static void DestroyTraced(Address* location);
static void SetFinalizationCallbackForTraced(
Address* location, void* parameter,
WeakCallbackInfo<void>::Callback callback);
explicit GlobalHandles(Isolate* isolate); explicit GlobalHandles(Isolate* isolate);
~GlobalHandles(); ~GlobalHandles();
...@@ -195,6 +204,10 @@ class GlobalHandles final { ...@@ -195,6 +204,10 @@ class GlobalHandles final {
size_t PostScavengeProcessing(unsigned post_processing_count); size_t PostScavengeProcessing(unsigned post_processing_count);
size_t PostMarkSweepProcessing(unsigned post_processing_count); size_t PostMarkSweepProcessing(unsigned post_processing_count);
template <typename T>
size_t InvokeFirstPassWeakCallbacks(
std::vector<std::pair<T*, PendingPhantomCallback>>* pending);
template <typename T> template <typename T>
void UpdateAndCompactListOfNewSpaceNode(std::vector<T*>* node_list); void UpdateAndCompactListOfNewSpaceNode(std::vector<T*>* node_list);
void UpdateListOfNewSpaceNodes(); void UpdateListOfNewSpaceNodes();
...@@ -216,7 +229,10 @@ class GlobalHandles final { ...@@ -216,7 +229,10 @@ class GlobalHandles final {
size_t handles_count_ = 0; size_t handles_count_ = 0;
size_t number_of_phantom_handle_resets_ = 0; size_t number_of_phantom_handle_resets_ = 0;
std::vector<PendingPhantomCallback> pending_phantom_callbacks_; std::vector<std::pair<Node*, PendingPhantomCallback>>
regular_pending_phantom_callbacks_;
std::vector<std::pair<TracedNode*, PendingPhantomCallback>>
traced_pending_phantom_callbacks_;
std::vector<PendingPhantomCallback> second_pass_callbacks_; std::vector<PendingPhantomCallback> second_pass_callbacks_;
bool second_pass_callbacks_task_posted_ = false; bool second_pass_callbacks_task_posted_ = false;
...@@ -229,22 +245,23 @@ class GlobalHandles final { ...@@ -229,22 +245,23 @@ class GlobalHandles final {
class GlobalHandles::PendingPhantomCallback final { class GlobalHandles::PendingPhantomCallback final {
public: public:
typedef v8::WeakCallbackInfo<void> Data; typedef v8::WeakCallbackInfo<void> Data;
enum InvocationType { kFirstPass, kSecondPass };
PendingPhantomCallback( PendingPhantomCallback(
Node* node, Data::Callback callback, void* parameter, Data::Callback callback, void* parameter,
void* embedder_fields[v8::kEmbedderFieldsInWeakCallback]) void* embedder_fields[v8::kEmbedderFieldsInWeakCallback])
: node_(node), callback_(callback), parameter_(parameter) { : callback_(callback), parameter_(parameter) {
for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) { for (int i = 0; i < v8::kEmbedderFieldsInWeakCallback; ++i) {
embedder_fields_[i] = embedder_fields[i]; embedder_fields_[i] = embedder_fields[i];
} }
} }
void Invoke(Isolate* isolate); void Invoke(Isolate* isolate, InvocationType type);
Node* node() const { return node_; }
Data::Callback callback() const { return callback_; } Data::Callback callback() const { return callback_; }
private: private:
Node* node_;
Data::Callback callback_; Data::Callback callback_;
void* parameter_; void* parameter_;
void* embedder_fields_[v8::kEmbedderFieldsInWeakCallback]; void* embedder_fields_[v8::kEmbedderFieldsInWeakCallback];
......
...@@ -488,6 +488,63 @@ TEST(TracedGlobalIteration) { ...@@ -488,6 +488,63 @@ TEST(TracedGlobalIteration) {
CHECK_EQ(1, visitor.count()); CHECK_EQ(1, visitor.count());
} }
namespace {
void FinalizationCallback(const WeakCallbackInfo<void>& data) {
v8::TracedGlobal<v8::Object>* traced =
reinterpret_cast<v8::TracedGlobal<v8::Object>*>(data.GetParameter());
CHECK_EQ(reinterpret_cast<void*>(0x4), data.GetInternalField(0));
CHECK_EQ(reinterpret_cast<void*>(0x8), data.GetInternalField(1));
traced->Reset();
}
} // namespace
TEST(TracedGlobalSetFinalizationCallbackScavenge) {
ManualGCScope manual_gc;
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
TestEmbedderHeapTracer tracer;
tracer.ConsiderTracedGlobalAsRoot(false);
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
v8::TracedGlobal<v8::Object> traced;
ConstructJSApiObject(isolate, isolate->GetCurrentContext(), &traced);
CHECK(!traced.IsEmpty());
{
v8::HandleScope scope(isolate);
auto local = traced.Get(isolate);
local->SetAlignedPointerInInternalField(0, reinterpret_cast<void*>(0x4));
local->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(0x8));
}
traced.SetFinalizationCallback(&traced, FinalizationCallback);
heap::InvokeScavenge();
CHECK(traced.IsEmpty());
}
TEST(TracedGlobalSetFinalizationCallbackMarkSweep) {
ManualGCScope manual_gc;
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
TestEmbedderHeapTracer tracer;
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
v8::TracedGlobal<v8::Object> traced;
ConstructJSApiObject(isolate, isolate->GetCurrentContext(), &traced);
CHECK(!traced.IsEmpty());
{
v8::HandleScope scope(isolate);
auto local = traced.Get(isolate);
local->SetAlignedPointerInInternalField(0, reinterpret_cast<void*>(0x4));
local->SetAlignedPointerInInternalField(1, reinterpret_cast<void*>(0x8));
}
traced.SetFinalizationCallback(&traced, FinalizationCallback);
heap::InvokeMarkSweep();
CHECK(traced.IsEmpty());
}
} // namespace heap } // namespace heap
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment