Unify phantom and internal fields weak handle callbacks
R=dcarney@chromium.org BUG= Review URL: https://codereview.chromium.org/842153004 Cr-Commit-Position: refs/heads/master@{#26022}
This commit is contained in:
parent
a4124b3bfc
commit
7db1759b65
106
include/v8.h
106
include/v8.h
@ -137,15 +137,18 @@ class PropertyCallbackArguments;
|
||||
class FunctionCallbackArguments;
|
||||
class GlobalHandles;
|
||||
|
||||
template <typename T>
|
||||
class CallbackData {
|
||||
public:
|
||||
V8_INLINE v8::Isolate* GetIsolate() const { return isolate_; }
|
||||
|
||||
protected:
|
||||
explicit CallbackData(v8::Isolate* isolate) : isolate_(isolate) {}
|
||||
explicit CallbackData(v8::Isolate* isolate, T* parameter)
|
||||
: isolate_(isolate), parameter_(parameter) {}
|
||||
V8_INLINE T* GetParameter() const { return parameter_; }
|
||||
|
||||
private:
|
||||
v8::Isolate* isolate_;
|
||||
T* parameter_;
|
||||
};
|
||||
}
|
||||
|
||||
@ -425,23 +428,28 @@ template <class T> class Eternal {
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class PhantomCallbackData : public internal::CallbackData {
|
||||
template <typename T, typename U = void, typename V = void>
|
||||
class PhantomCallbackData : public internal::CallbackData<T> {
|
||||
public:
|
||||
typedef void (*Callback)(const PhantomCallbackData<T>& data);
|
||||
typedef void (*Callback)(const PhantomCallbackData<T, U, V>& data);
|
||||
|
||||
V8_INLINE T* GetParameter() const { return parameter_; }
|
||||
V8_INLINE U* GetInternalField1() const { return internal_field1_; }
|
||||
V8_INLINE V* GetInternalField2() const { return internal_field2_; }
|
||||
|
||||
PhantomCallbackData<T>(Isolate* isolate, T* parameter)
|
||||
: internal::CallbackData(isolate), parameter_(parameter) {}
|
||||
PhantomCallbackData(Isolate* isolate, T* parameter, U* internal_field1,
|
||||
V* internal_field2)
|
||||
: internal::CallbackData<T>(isolate, parameter),
|
||||
internal_field1_(internal_field1),
|
||||
internal_field2_(internal_field2) {}
|
||||
|
||||
private:
|
||||
T* parameter_;
|
||||
U* internal_field1_;
|
||||
V* internal_field2_;
|
||||
};
|
||||
|
||||
|
||||
template <class T, class P>
|
||||
class WeakCallbackData : public PhantomCallbackData<P> {
|
||||
class WeakCallbackData : public internal::CallbackData<P> {
|
||||
public:
|
||||
typedef void (*Callback)(const WeakCallbackData<T, P>& data);
|
||||
|
||||
@ -450,31 +458,11 @@ class WeakCallbackData : public PhantomCallbackData<P> {
|
||||
private:
|
||||
friend class internal::GlobalHandles;
|
||||
WeakCallbackData(Isolate* isolate, P* parameter, Local<T> handle)
|
||||
: PhantomCallbackData<P>(isolate, parameter), handle_(handle) {}
|
||||
: internal::CallbackData<P>(isolate, parameter), handle_(handle) {}
|
||||
Local<T> handle_;
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
class InternalFieldsCallbackData : public internal::CallbackData {
|
||||
public:
|
||||
typedef void (*Callback)(const InternalFieldsCallbackData<T, U>& data);
|
||||
|
||||
InternalFieldsCallbackData(Isolate* isolate, T* internalField1,
|
||||
U* internalField2)
|
||||
: internal::CallbackData(isolate),
|
||||
internal_field1_(internalField1),
|
||||
internal_field2_(internalField2) {}
|
||||
|
||||
V8_INLINE T* GetInternalField1() const { return internal_field1_; }
|
||||
V8_INLINE U* GetInternalField2() const { return internal_field2_; }
|
||||
|
||||
private:
|
||||
T* internal_field1_;
|
||||
U* internal_field2_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An object reference that is independent of any handle scope. Where
|
||||
* a Local handle only lives as long as the HandleScope in which it was
|
||||
@ -562,13 +550,17 @@ template <class T> class PersistentBase {
|
||||
// specify a parameter for the callback or the location of two internal
|
||||
// fields in the dying object.
|
||||
template <typename P>
|
||||
V8_INLINE void SetPhantom(P* parameter,
|
||||
typename PhantomCallbackData<P>::Callback callback);
|
||||
|
||||
V8_INLINE void SetPhantom(
|
||||
P* parameter,
|
||||
typename PhantomCallbackData<P, void, void>::Callback callback);
|
||||
template <typename P, typename Q>
|
||||
V8_INLINE void SetPhantom(
|
||||
void (*callback)(const InternalFieldsCallbackData<P, Q>&),
|
||||
int internal_field_index1, int internal_field_index2);
|
||||
P* parameter, int internal_field_index1,
|
||||
typename PhantomCallbackData<P, Q, void>::Callback callback);
|
||||
template <typename P, typename Q, typename R>
|
||||
V8_INLINE void SetPhantom(
|
||||
P* parameter, int internal_field_index1, int internal_field_index2,
|
||||
typename PhantomCallbackData<P, Q, R>::Callback callback);
|
||||
|
||||
template<typename P>
|
||||
V8_INLINE P* ClearWeak();
|
||||
@ -5595,13 +5587,13 @@ class V8_EXPORT V8 {
|
||||
typedef WeakCallbackData<Value, void>::Callback WeakCallback;
|
||||
static void MakeWeak(internal::Object** global_handle, void* data,
|
||||
WeakCallback weak_callback);
|
||||
static void MakePhantom(internal::Object** global_handle, void* data,
|
||||
PhantomCallbackData<void>::Callback weak_callback);
|
||||
static void MakePhantom(
|
||||
internal::Object** global_handle,
|
||||
InternalFieldsCallbackData<void, void>::Callback weak_callback,
|
||||
internal::Object** global_handle, void* data,
|
||||
// Must be 0 or kNoInternalFieldIndex.
|
||||
int internal_field_index1,
|
||||
int internal_field_index2 = Object::kNoInternalFieldIndex);
|
||||
// Must be 1 or kNoInternalFieldIndex.
|
||||
int internal_field_index2,
|
||||
PhantomCallbackData<void, void, void>::Callback weak_callback);
|
||||
static void* ClearWeak(internal::Object** global_handle);
|
||||
static void Eternalize(Isolate* isolate,
|
||||
Value* handle,
|
||||
@ -6489,22 +6481,36 @@ void PersistentBase<T>::SetWeak(
|
||||
template <class T>
|
||||
template <typename P>
|
||||
void PersistentBase<T>::SetPhantom(
|
||||
P* parameter, typename PhantomCallbackData<P>::Callback callback) {
|
||||
typedef typename PhantomCallbackData<void>::Callback Callback;
|
||||
P* parameter,
|
||||
typename PhantomCallbackData<P, void, void>::Callback callback) {
|
||||
typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
|
||||
V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
|
||||
Object::kNoInternalFieldIndex, Object::kNoInternalFieldIndex,
|
||||
reinterpret_cast<Callback>(callback));
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
template <typename U, typename V>
|
||||
template <typename P, typename Q>
|
||||
void PersistentBase<T>::SetPhantom(
|
||||
void (*callback)(const InternalFieldsCallbackData<U, V>&),
|
||||
int internal_field_index1, int internal_field_index2) {
|
||||
typedef typename InternalFieldsCallbackData<void, void>::Callback Callback;
|
||||
V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_),
|
||||
reinterpret_cast<Callback>(callback), internal_field_index1,
|
||||
internal_field_index2);
|
||||
P* parameter, int internal_field_index1,
|
||||
typename PhantomCallbackData<P, Q, void>::Callback callback) {
|
||||
typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
|
||||
V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
|
||||
internal_field_index1, Object::kNoInternalFieldIndex,
|
||||
reinterpret_cast<Callback>(callback));
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
template <typename P, typename Q, typename R>
|
||||
void PersistentBase<T>::SetPhantom(
|
||||
P* parameter, int internal_field_index1, int internal_field_index2,
|
||||
typename PhantomCallbackData<P, Q, R>::Callback callback) {
|
||||
typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
|
||||
V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
|
||||
internal_field_index1, internal_field_index2,
|
||||
reinterpret_cast<Callback>(callback));
|
||||
}
|
||||
|
||||
|
||||
|
26
src/api.cc
26
src/api.cc
@ -408,18 +408,22 @@ void V8::MakeWeak(i::Object** object, void* parameter,
|
||||
}
|
||||
|
||||
|
||||
void V8::MakePhantom(i::Object** object, void* parameter,
|
||||
PhantomCallbackData<void>::Callback weak_callback) {
|
||||
i::GlobalHandles::MakePhantom(object, parameter, weak_callback);
|
||||
}
|
||||
|
||||
|
||||
void V8::MakePhantom(
|
||||
i::Object** object,
|
||||
InternalFieldsCallbackData<void, void>::Callback weak_callback,
|
||||
int internal_field_index1, int internal_field_index2) {
|
||||
i::GlobalHandles::MakePhantom(object, weak_callback, internal_field_index1,
|
||||
internal_field_index2);
|
||||
i::Object** object, void* parameter, int internal_field_index1,
|
||||
int internal_field_index2,
|
||||
PhantomCallbackData<void, void, void>::Callback weak_callback) {
|
||||
if (internal_field_index1 == 0) {
|
||||
if (internal_field_index2 == 1) {
|
||||
i::GlobalHandles::MakePhantom(object, parameter, 2, weak_callback);
|
||||
} else {
|
||||
DCHECK_EQ(internal_field_index2, Object::kNoInternalFieldIndex);
|
||||
i::GlobalHandles::MakePhantom(object, parameter, 1, weak_callback);
|
||||
}
|
||||
} else {
|
||||
DCHECK_EQ(internal_field_index1, Object::kNoInternalFieldIndex);
|
||||
DCHECK_EQ(internal_field_index2, Object::kNoInternalFieldIndex);
|
||||
i::GlobalHandles::MakePhantom(object, parameter, 0, weak_callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -716,7 +716,7 @@ DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
|
||||
debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info));
|
||||
typedef PhantomCallbackData<void>::Callback Callback;
|
||||
GlobalHandles::MakePhantom(
|
||||
reinterpret_cast<Object**>(debug_info_.location()), this,
|
||||
reinterpret_cast<Object**>(debug_info_.location()), this, 0,
|
||||
reinterpret_cast<Callback>(Debug::HandlePhantomDebugInfo));
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,6 @@ class GlobalHandles::Node {
|
||||
// Callback parameter accessors.
|
||||
void set_parameter(void* parameter) {
|
||||
DCHECK(IsInUse());
|
||||
DCHECK(weakness_type() == NORMAL_WEAK || weakness_type() == PHANTOM_WEAK);
|
||||
parameter_or_next_free_.parameter = parameter;
|
||||
}
|
||||
void* parameter() const {
|
||||
@ -211,30 +210,6 @@ class GlobalHandles::Node {
|
||||
return parameter_or_next_free_.parameter;
|
||||
}
|
||||
|
||||
void set_internal_fields(int internal_field_index1,
|
||||
int internal_field_index2) {
|
||||
DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
|
||||
// These are stored in an int16_t.
|
||||
DCHECK(internal_field_index1 < 1 << 16);
|
||||
DCHECK(internal_field_index1 >= -(1 << 16));
|
||||
DCHECK(internal_field_index2 < 1 << 16);
|
||||
DCHECK(internal_field_index2 >= -(1 << 16));
|
||||
parameter_or_next_free_.internal_field_indeces.internal_field1 =
|
||||
static_cast<int16_t>(internal_field_index1);
|
||||
parameter_or_next_free_.internal_field_indeces.internal_field2 =
|
||||
static_cast<int16_t>(internal_field_index2);
|
||||
}
|
||||
|
||||
int internal_field1() const {
|
||||
DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
|
||||
return parameter_or_next_free_.internal_field_indeces.internal_field1;
|
||||
}
|
||||
|
||||
int internal_field2() const {
|
||||
DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
|
||||
return parameter_or_next_free_.internal_field_indeces.internal_field2;
|
||||
}
|
||||
|
||||
// Accessors for next free node in the free list.
|
||||
Node* next_free() {
|
||||
DCHECK(state() == FREE);
|
||||
@ -255,23 +230,22 @@ class GlobalHandles::Node {
|
||||
weak_callback_ = weak_callback;
|
||||
}
|
||||
|
||||
void MakePhantom(void* parameter,
|
||||
PhantomCallbackData<void>::Callback phantom_callback,
|
||||
int16_t internal_field_index1,
|
||||
int16_t internal_field_index2) {
|
||||
void MakePhantom(void* parameter, int number_of_internal_fields,
|
||||
PhantomCallbackData<void>::Callback phantom_callback) {
|
||||
DCHECK(number_of_internal_fields >= 0);
|
||||
DCHECK(number_of_internal_fields <= 2);
|
||||
DCHECK(phantom_callback != NULL);
|
||||
DCHECK(IsInUse());
|
||||
CHECK(object_ != NULL);
|
||||
set_state(WEAK);
|
||||
if (parameter == NULL) {
|
||||
set_weakness_type(INTERNAL_FIELDS_WEAK);
|
||||
set_internal_fields(internal_field_index1, internal_field_index2);
|
||||
if (number_of_internal_fields == 0) {
|
||||
set_weakness_type(PHANTOM_WEAK_0_INTERNAL_FIELDS);
|
||||
} else if (number_of_internal_fields == 1) {
|
||||
set_weakness_type(PHANTOM_WEAK_1_INTERNAL_FIELDS);
|
||||
} else {
|
||||
DCHECK(internal_field_index1 == v8::Object::kNoInternalFieldIndex);
|
||||
DCHECK(internal_field_index2 == v8::Object::kNoInternalFieldIndex);
|
||||
set_weakness_type(PHANTOM_WEAK);
|
||||
set_parameter(parameter);
|
||||
set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS);
|
||||
}
|
||||
set_parameter(parameter);
|
||||
weak_callback_ = reinterpret_cast<WeakCallback>(phantom_callback);
|
||||
}
|
||||
|
||||
@ -284,63 +258,51 @@ class GlobalHandles::Node {
|
||||
}
|
||||
|
||||
void CollectPhantomCallbackData(
|
||||
Isolate* isolate, List<PendingPhantomCallback>* pending_phantom_callbacks,
|
||||
List<PendingInternalFieldsCallback>* pending_internal_fields_callbacks) {
|
||||
if (state() != Node::PENDING) return;
|
||||
bool do_release = true;
|
||||
Isolate* isolate,
|
||||
List<PendingPhantomCallback>* pending_phantom_callbacks) {
|
||||
if (state() != PENDING) return;
|
||||
if (weak_callback_ != NULL) {
|
||||
if (weakness_type() == NORMAL_WEAK) return;
|
||||
|
||||
v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate);
|
||||
|
||||
if (weakness_type() == PHANTOM_WEAK) {
|
||||
// Phantom weak pointer case. Zap with harmless value.
|
||||
DCHECK(*location() == Smi::FromInt(0));
|
||||
typedef PhantomCallbackData<void> Data;
|
||||
DCHECK(weakness_type() == PHANTOM_WEAK_0_INTERNAL_FIELDS ||
|
||||
weakness_type() == PHANTOM_WEAK_1_INTERNAL_FIELDS ||
|
||||
weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
|
||||
|
||||
Data data(api_isolate, parameter());
|
||||
Data::Callback callback =
|
||||
reinterpret_cast<Data::Callback>(weak_callback_);
|
||||
|
||||
pending_phantom_callbacks->Add(
|
||||
PendingPhantomCallback(this, data, callback));
|
||||
|
||||
// Postpone the release of the handle. The embedder can't use the
|
||||
// handle (it's zapped), but it may be using the location, and we
|
||||
// don't want to confuse things by reusing that.
|
||||
do_release = false;
|
||||
} else {
|
||||
DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
|
||||
typedef InternalFieldsCallbackData<void, void> Data;
|
||||
|
||||
// Phantom weak pointer case, passing internal fields instead of
|
||||
// parameter. Don't use a handle here during GC, because it will
|
||||
// create a handle pointing to a dying object, which can confuse
|
||||
// the next GC.
|
||||
Object* internal_field0 = nullptr;
|
||||
Object* internal_field1 = nullptr;
|
||||
if (weakness_type() != PHANTOM_WEAK_0_INTERNAL_FIELDS) {
|
||||
JSObject* jsobject = reinterpret_cast<JSObject*>(object());
|
||||
DCHECK(jsobject->IsJSObject());
|
||||
Data data(api_isolate, jsobject->GetInternalField(internal_field1()),
|
||||
jsobject->GetInternalField(internal_field2()));
|
||||
Data::Callback callback =
|
||||
reinterpret_cast<Data::Callback>(weak_callback_);
|
||||
|
||||
// In the future, we want to delay the callback. In that case we will
|
||||
// zap when we queue up, to stop the C++ side accessing the dead V8
|
||||
// object, but we will call Release only after the callback (allowing
|
||||
// the node to be reused).
|
||||
pending_internal_fields_callbacks->Add(
|
||||
PendingInternalFieldsCallback(data, callback));
|
||||
DCHECK(jsobject->GetInternalFieldCount() >= 1);
|
||||
internal_field0 = jsobject->GetInternalField(0);
|
||||
if (weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS) {
|
||||
DCHECK(jsobject->GetInternalFieldCount() >= 2);
|
||||
internal_field1 = jsobject->GetInternalField(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Zap with harmless value.
|
||||
*location() = Smi::FromInt(0);
|
||||
typedef PhantomCallbackData<void, void, void> Data;
|
||||
|
||||
if (!internal_field0->IsSmi()) internal_field0 = nullptr;
|
||||
if (!internal_field1->IsSmi()) internal_field1 = nullptr;
|
||||
|
||||
Data data(api_isolate, parameter(), internal_field0, internal_field1);
|
||||
Data::Callback callback =
|
||||
reinterpret_cast<Data::Callback>(weak_callback_);
|
||||
|
||||
pending_phantom_callbacks->Add(
|
||||
PendingPhantomCallback(this, data, callback));
|
||||
DCHECK(IsInUse());
|
||||
set_state(NEAR_DEATH);
|
||||
}
|
||||
// TODO(erikcorry): At the moment the callbacks are not postponed much,
|
||||
// but if we really postpone them until after the mutator has run, we
|
||||
// need to divide things up, so that an early callback clears the handle,
|
||||
// while a later one destroys the objects involved, possibley triggering
|
||||
// some work when decremented ref counts hit zero.
|
||||
if (do_release) Release();
|
||||
}
|
||||
|
||||
bool PostGarbageCollectionProcessing(Isolate* isolate) {
|
||||
// Handles only weak handles (not phantom) that are dying.
|
||||
if (state() != Node::PENDING) return false;
|
||||
if (weak_callback_ == NULL) {
|
||||
Release();
|
||||
@ -354,11 +316,11 @@ class GlobalHandles::Node {
|
||||
ExternalOneByteString::cast(object_)->resource() != NULL);
|
||||
DCHECK(!object_->IsExternalTwoByteString() ||
|
||||
ExternalTwoByteString::cast(object_)->resource() != NULL);
|
||||
if (weakness_type() != NORMAL_WEAK) return false;
|
||||
|
||||
// Leaving V8.
|
||||
VMState<EXTERNAL> vmstate(isolate);
|
||||
HandleScope handle_scope(isolate);
|
||||
if (weakness_type() == PHANTOM_WEAK) return false;
|
||||
DCHECK(weakness_type() == NORMAL_WEAK);
|
||||
Object** object = location();
|
||||
Handle<Object> handle(*object, isolate);
|
||||
v8::WeakCallbackData<v8::Value, void> data(
|
||||
@ -410,10 +372,6 @@ class GlobalHandles::Node {
|
||||
// the free list link.
|
||||
union {
|
||||
void* parameter;
|
||||
struct {
|
||||
int16_t internal_field1;
|
||||
int16_t internal_field2;
|
||||
} internal_field_indeces;
|
||||
Node* next_free;
|
||||
} parameter_or_next_free_;
|
||||
|
||||
@ -604,32 +562,21 @@ void GlobalHandles::MakeWeak(Object** location, void* parameter,
|
||||
}
|
||||
|
||||
|
||||
typedef PhantomCallbackData<void>::Callback GenericCallback;
|
||||
|
||||
|
||||
void GlobalHandles::MakePhantom(
|
||||
Object** location,
|
||||
v8::InternalFieldsCallbackData<void, void>::Callback phantom_callback,
|
||||
int16_t internal_field_index1, int16_t internal_field_index2) {
|
||||
Node::FromLocation(location)
|
||||
->MakePhantom(NULL, reinterpret_cast<GenericCallback>(phantom_callback),
|
||||
internal_field_index1, internal_field_index2);
|
||||
}
|
||||
typedef PhantomCallbackData<void, void, void>::Callback GenericCallback;
|
||||
|
||||
|
||||
void GlobalHandles::MakePhantom(Object** location, void* parameter,
|
||||
int number_of_internal_fields,
|
||||
GenericCallback phantom_callback) {
|
||||
Node::FromLocation(location)->MakePhantom(parameter, phantom_callback,
|
||||
v8::Object::kNoInternalFieldIndex,
|
||||
v8::Object::kNoInternalFieldIndex);
|
||||
Node::FromLocation(location)
|
||||
->MakePhantom(parameter, number_of_internal_fields, phantom_callback);
|
||||
}
|
||||
|
||||
|
||||
void GlobalHandles::CollectPhantomCallbackData() {
|
||||
for (NodeIterator it(this); !it.done(); it.Advance()) {
|
||||
Node* node = it.node();
|
||||
node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_,
|
||||
&pending_internal_fields_callbacks_);
|
||||
node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -668,22 +615,22 @@ void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
|
||||
for (NodeIterator it(this); !it.done(); it.Advance()) {
|
||||
Node* node = it.node();
|
||||
if (node->IsWeakRetainer()) {
|
||||
// Weakness type can be normal, phantom or internal fields.
|
||||
// For normal weakness we mark through the handle so that
|
||||
// the object and things reachable from it are available
|
||||
// to the callback.
|
||||
// In the case of phantom we can zap the object handle now
|
||||
// and we won't need it, so we don't need to mark through it.
|
||||
// Weakness type can be normal or phantom, with or without internal
|
||||
// fields). For normal weakness we mark through the handle so that the
|
||||
// object and things reachable from it are available to the callback.
|
||||
//
|
||||
// In the case of phantom with no internal fields, we can zap the object
|
||||
// handle now and we won't need it, so we don't need to mark through it.
|
||||
// In the internal fields case we will need the internal
|
||||
// fields, so we can't zap the handle, but we don't need to
|
||||
// mark through it, because it will die in this GC round.
|
||||
// fields, so we can't zap the handle.
|
||||
if (node->state() == Node::PENDING) {
|
||||
if (node->weakness_type() == PHANTOM_WEAK) {
|
||||
if (node->weakness_type() == PHANTOM_WEAK_0_INTERNAL_FIELDS) {
|
||||
*(node->location()) = Smi::FromInt(0);
|
||||
} else if (node->weakness_type() == NORMAL_WEAK) {
|
||||
v->VisitPointer(node->location());
|
||||
} else {
|
||||
DCHECK(node->weakness_type() == INTERNAL_FIELDS_WEAK);
|
||||
DCHECK(node->weakness_type() == PHANTOM_WEAK_1_INTERNAL_FIELDS ||
|
||||
node->weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
|
||||
}
|
||||
} else {
|
||||
// Node is not pending, so that means the object survived. We still
|
||||
@ -736,12 +683,13 @@ void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) {
|
||||
DCHECK(node->is_in_new_space_list());
|
||||
if ((node->is_independent() || node->is_partially_dependent()) &&
|
||||
node->IsWeakRetainer()) {
|
||||
if (node->weakness_type() == PHANTOM_WEAK) {
|
||||
if (node->weakness_type() == PHANTOM_WEAK_0_INTERNAL_FIELDS) {
|
||||
*(node->location()) = Smi::FromInt(0);
|
||||
} else if (node->weakness_type() == NORMAL_WEAK) {
|
||||
v->VisitPointer(node->location());
|
||||
} else {
|
||||
DCHECK(node->weakness_type() == INTERNAL_FIELDS_WEAK);
|
||||
DCHECK(node->weakness_type() == PHANTOM_WEAK_1_INTERNAL_FIELDS ||
|
||||
node->weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
|
||||
// For this case we only need to trace if it's alive: The tracing of
|
||||
// something that is already alive is just to get the pointer updated
|
||||
// to the new location of the object).
|
||||
@ -886,13 +834,9 @@ int GlobalHandles::DispatchPendingPhantomCallbacks() {
|
||||
int freed_nodes = 0;
|
||||
while (pending_phantom_callbacks_.length() != 0) {
|
||||
PendingPhantomCallback callback = pending_phantom_callbacks_.RemoveLast();
|
||||
DCHECK(callback.node()->IsInUse());
|
||||
callback.invoke();
|
||||
freed_nodes++;
|
||||
}
|
||||
while (pending_internal_fields_callbacks_.length() != 0) {
|
||||
PendingInternalFieldsCallback callback =
|
||||
pending_internal_fields_callbacks_.RemoveLast();
|
||||
callback.invoke();
|
||||
DCHECK(!callback.node()->IsInUse());
|
||||
freed_nodes++;
|
||||
}
|
||||
return freed_nodes;
|
||||
|
@ -98,9 +98,15 @@ struct ObjectGroupRetainerInfo {
|
||||
|
||||
|
||||
enum WeaknessType {
|
||||
NORMAL_WEAK, // Embedder gets a handle to the dying object.
|
||||
PHANTOM_WEAK, // Embedder gets the parameter they passed in earlier.
|
||||
INTERNAL_FIELDS_WEAK // Embedder gets 2 internal fields from dying object.
|
||||
NORMAL_WEAK, // Embedder gets a handle to the dying object.
|
||||
// In the following cases, the embedder gets the parameter they passed in
|
||||
// earlier, and the 0, 1 or 2 first internal fields. Note that the internal
|
||||
// fields must contain aligned non-V8 pointers. Getting pointers to V8
|
||||
// objects through this interface would be GC unsafe so in that case the
|
||||
// embedder gets a null pointer instead.
|
||||
PHANTOM_WEAK_0_INTERNAL_FIELDS,
|
||||
PHANTOM_WEAK_1_INTERNAL_FIELDS,
|
||||
PHANTOM_WEAK_2_INTERNAL_FIELDS
|
||||
};
|
||||
|
||||
|
||||
@ -139,14 +145,9 @@ class GlobalHandles {
|
||||
|
||||
// It would be nice to template this one, but it's really hard to get
|
||||
// the template instantiator to work right if you do.
|
||||
static void MakePhantom(Object** location, void* parameter,
|
||||
PhantomCallbackData<void>::Callback weak_callback);
|
||||
|
||||
static void MakePhantom(
|
||||
Object** location,
|
||||
v8::InternalFieldsCallbackData<void, void>::Callback weak_callback,
|
||||
int16_t internal_field_index1,
|
||||
int16_t internal_field_index2 = v8::Object::kNoInternalFieldIndex);
|
||||
Object** location, void* parameter, int number_of_internal_fields,
|
||||
PhantomCallbackData<void, void, void>::Callback weak_callback);
|
||||
|
||||
void RecordStats(HeapStats* stats);
|
||||
|
||||
@ -302,7 +303,6 @@ class GlobalHandles {
|
||||
class NodeBlock;
|
||||
class NodeIterator;
|
||||
class PendingPhantomCallback;
|
||||
class PendingInternalFieldsCallback;
|
||||
|
||||
Isolate* isolate_;
|
||||
|
||||
@ -336,7 +336,6 @@ class GlobalHandles {
|
||||
List<ObjectGroupConnection> implicit_ref_connections_;
|
||||
|
||||
List<PendingPhantomCallback> pending_phantom_callbacks_;
|
||||
List<PendingInternalFieldsCallback> pending_internal_fields_callbacks_;
|
||||
|
||||
friend class Isolate;
|
||||
|
||||
@ -346,7 +345,7 @@ class GlobalHandles {
|
||||
|
||||
class GlobalHandles::PendingPhantomCallback {
|
||||
public:
|
||||
typedef PhantomCallbackData<void> Data;
|
||||
typedef PhantomCallbackData<void, void, void> Data;
|
||||
PendingPhantomCallback(Node* node, Data data, Data::Callback callback)
|
||||
: node_(node), data_(data), callback_(callback) {}
|
||||
|
||||
@ -361,20 +360,6 @@ class GlobalHandles::PendingPhantomCallback {
|
||||
};
|
||||
|
||||
|
||||
class GlobalHandles::PendingInternalFieldsCallback {
|
||||
public:
|
||||
typedef InternalFieldsCallbackData<void, void> Data;
|
||||
PendingInternalFieldsCallback(Data data, Data::Callback callback)
|
||||
: data_(data), callback_(callback) {}
|
||||
|
||||
void invoke() { callback_(data_); }
|
||||
|
||||
private:
|
||||
Data data_;
|
||||
Data::Callback callback_;
|
||||
};
|
||||
|
||||
|
||||
class EternalHandles {
|
||||
public:
|
||||
enum SingletonHandle {
|
||||
|
@ -7796,8 +7796,10 @@ class Trivial2 {
|
||||
};
|
||||
|
||||
|
||||
void CheckInternalFields(
|
||||
const v8::InternalFieldsCallbackData<Trivial, Trivial2>& data) {
|
||||
void CheckInternalFields(const v8::PhantomCallbackData<
|
||||
v8::Persistent<v8::Object>, Trivial, Trivial2>& data) {
|
||||
v8::Persistent<v8::Object>* handle = data.GetParameter();
|
||||
handle->Reset();
|
||||
Trivial* t1 = data.GetInternalField1();
|
||||
Trivial2* t2 = data.GetInternalField2();
|
||||
CHECK_EQ(42, t1->x());
|
||||
@ -7835,7 +7837,8 @@ void InternalFieldCallback(bool global_gc) {
|
||||
reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
|
||||
CHECK_EQ(103, t2->x());
|
||||
|
||||
handle.SetPhantom(CheckInternalFields, 0, 1);
|
||||
handle.SetPhantom<v8::Persistent<v8::Object>, Trivial, Trivial2>(
|
||||
&handle, 0, 1, CheckInternalFields);
|
||||
if (!global_gc) {
|
||||
handle.MarkIndependent();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user