Reland "[api,heap] Remove deprecated Persistent APIs"
Removes APIs:
- MarkIndependent
- IsIndependent
- MarkActive
- RegisterExternalReference
All weak persistent handles are now treated as independent. Users of
traced handles should already use v8::EmbedderHeapTracer.
This reverts commit 49954eb56f
.
Bug: chromium:923361
Change-Id: I0b9fcd678964331f926f6b725f70eb64268ca33f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1578462
Auto-Submit: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60971}
This commit is contained in:
parent
65a6dae92e
commit
4214933c6b
@ -165,8 +165,6 @@ class Internals {
|
|||||||
static const int kNodeStateMask = 0x7;
|
static const int kNodeStateMask = 0x7;
|
||||||
static const int kNodeStateIsWeakValue = 2;
|
static const int kNodeStateIsWeakValue = 2;
|
||||||
static const int kNodeStateIsPendingValue = 3;
|
static const int kNodeStateIsPendingValue = 3;
|
||||||
static const int kNodeIsIndependentShift = 3;
|
|
||||||
static const int kNodeIsActiveShift = 4;
|
|
||||||
|
|
||||||
static const int kFirstNonstringType = 0x40;
|
static const int kFirstNonstringType = 0x40;
|
||||||
static const int kOddballType = 0x43;
|
static const int kOddballType = 0x43;
|
||||||
|
@ -194,14 +194,6 @@ class PersistentValueMapBase {
|
|||||||
return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
|
return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Call V8::RegisterExternallyReferencedObject with the map value for given
|
|
||||||
* key.
|
|
||||||
*/
|
|
||||||
V8_DEPRECATED(
|
|
||||||
"Used TracedGlobal and EmbedderHeapTracer::RegisterEmbedderReference",
|
|
||||||
inline void RegisterExternallyReferencedObject(K& key));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return value for key and remove it from the map.
|
* Return value for key and remove it from the map.
|
||||||
*/
|
*/
|
||||||
@ -352,16 +344,6 @@ class PersistentValueMapBase {
|
|||||||
const char* label_;
|
const char* label_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename K, typename V, typename Traits>
|
|
||||||
inline void
|
|
||||||
PersistentValueMapBase<K, V, Traits>::RegisterExternallyReferencedObject(
|
|
||||||
K& key) {
|
|
||||||
assert(Contains(key));
|
|
||||||
V8::RegisterExternallyReferencedObject(
|
|
||||||
reinterpret_cast<internal::Address*>(FromVal(Traits::Get(&impl_, key))),
|
|
||||||
reinterpret_cast<internal::Isolate*>(GetIsolate()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename K, typename V, typename Traits>
|
template <typename K, typename V, typename Traits>
|
||||||
class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
|
class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
|
||||||
public:
|
public:
|
||||||
|
68
include/v8.h
68
include/v8.h
@ -545,38 +545,6 @@ template <class T> class PersistentBase {
|
|||||||
*/
|
*/
|
||||||
V8_INLINE void AnnotateStrongRetainer(const char* label);
|
V8_INLINE void AnnotateStrongRetainer(const char* label);
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows the embedder to tell the v8 garbage collector that a certain object
|
|
||||||
* is alive. Only allowed when the embedder is asked to trace its heap by
|
|
||||||
* EmbedderHeapTracer.
|
|
||||||
*/
|
|
||||||
V8_DEPRECATED(
|
|
||||||
"Used TracedGlobal and EmbedderHeapTracer::RegisterEmbedderReference",
|
|
||||||
V8_INLINE void RegisterExternalReference(Isolate* isolate) const);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the reference to this object independent. Garbage collector is free
|
|
||||||
* to ignore any object groups containing this object. Weak callback for an
|
|
||||||
* independent handle should not assume that it will be preceded by a global
|
|
||||||
* GC prologue callback or followed by a global GC epilogue callback.
|
|
||||||
*/
|
|
||||||
V8_DEPRECATED(
|
|
||||||
"Weak objects are always considered independent. "
|
|
||||||
"Use TracedGlobal when trying to use EmbedderHeapTracer. "
|
|
||||||
"Use a strong handle when trying to keep an object alive.",
|
|
||||||
V8_INLINE void MarkIndependent());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the reference to this object as active. The scavenge garbage
|
|
||||||
* collection should not reclaim the objects marked as active, even if the
|
|
||||||
* object held by the handle is otherwise unreachable.
|
|
||||||
*
|
|
||||||
* This bit is cleared after the each garbage collection pass.
|
|
||||||
*/
|
|
||||||
V8_DEPRECATED("Use TracedGlobal.", V8_INLINE void MarkActive());
|
|
||||||
|
|
||||||
V8_DEPRECATED("See MarkIndependent.", V8_INLINE bool IsIndependent() const);
|
|
||||||
|
|
||||||
/** Returns true if the handle's reference is weak. */
|
/** Returns true if the handle's reference is weak. */
|
||||||
V8_INLINE bool IsWeak() const;
|
V8_INLINE bool IsWeak() const;
|
||||||
|
|
||||||
@ -8839,9 +8807,6 @@ class V8_EXPORT V8 {
|
|||||||
const char* label);
|
const char* label);
|
||||||
static Value* Eternalize(Isolate* isolate, Value* handle);
|
static Value* Eternalize(Isolate* isolate, Value* handle);
|
||||||
|
|
||||||
static void RegisterExternallyReferencedObject(internal::Address* location,
|
|
||||||
internal::Isolate* isolate);
|
|
||||||
|
|
||||||
template <class K, class V, class T>
|
template <class K, class V, class T>
|
||||||
friend class PersistentValueMapBase;
|
friend class PersistentValueMapBase;
|
||||||
|
|
||||||
@ -9788,14 +9753,6 @@ void Persistent<T, M>::Copy(const Persistent<S, M2>& that) {
|
|||||||
M::Copy(that, this);
|
M::Copy(that, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
bool PersistentBase<T>::IsIndependent() const {
|
|
||||||
typedef internal::Internals I;
|
|
||||||
if (this->IsEmpty()) return false;
|
|
||||||
return I::GetNodeFlag(reinterpret_cast<internal::Address*>(this->val_),
|
|
||||||
I::kNodeIsIndependentShift);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
bool PersistentBase<T>::IsWeak() const {
|
bool PersistentBase<T>::IsWeak() const {
|
||||||
typedef internal::Internals I;
|
typedef internal::Internals I;
|
||||||
@ -9862,31 +9819,6 @@ void PersistentBase<T>::AnnotateStrongRetainer(const char* label) {
|
|||||||
label);
|
label);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void PersistentBase<T>::RegisterExternalReference(Isolate* isolate) const {
|
|
||||||
if (IsEmpty()) return;
|
|
||||||
V8::RegisterExternallyReferencedObject(
|
|
||||||
reinterpret_cast<internal::Address*>(this->val_),
|
|
||||||
reinterpret_cast<internal::Isolate*>(isolate));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void PersistentBase<T>::MarkIndependent() {
|
|
||||||
typedef internal::Internals I;
|
|
||||||
if (this->IsEmpty()) return;
|
|
||||||
I::UpdateNodeFlag(reinterpret_cast<internal::Address*>(this->val_), true,
|
|
||||||
I::kNodeIsIndependentShift);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void PersistentBase<T>::MarkActive() {
|
|
||||||
typedef internal::Internals I;
|
|
||||||
if (this->IsEmpty()) return;
|
|
||||||
I::UpdateNodeFlag(reinterpret_cast<internal::Address*>(this->val_), true,
|
|
||||||
I::kNodeIsActiveShift);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void PersistentBase<T>::SetWrapperClassId(uint16_t class_id) {
|
void PersistentBase<T>::SetWrapperClassId(uint16_t class_id) {
|
||||||
typedef internal::Internals I;
|
typedef internal::Internals I;
|
||||||
|
@ -1037,11 +1037,6 @@ void V8::MoveTracedGlobalReference(internal::Address** from,
|
|||||||
i::GlobalHandles::MoveTracedGlobal(from, to);
|
i::GlobalHandles::MoveTracedGlobal(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V8::RegisterExternallyReferencedObject(i::Address* location,
|
|
||||||
i::Isolate* isolate) {
|
|
||||||
isolate->heap()->RegisterExternallyReferencedObject(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
void V8::MakeWeak(i::Address* location, void* parameter,
|
void V8::MakeWeak(i::Address* location, void* parameter,
|
||||||
WeakCallbackInfo<void>::Callback weak_callback,
|
WeakCallbackInfo<void>::Callback weak_callback,
|
||||||
WeakCallbackType type) {
|
WeakCallbackType type) {
|
||||||
|
@ -379,10 +379,6 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
|
|||||||
Internals::kNodeStateMask);
|
Internals::kNodeStateMask);
|
||||||
STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue);
|
STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue);
|
||||||
STATIC_ASSERT(PENDING == Internals::kNodeStateIsPendingValue);
|
STATIC_ASSERT(PENDING == Internals::kNodeStateIsPendingValue);
|
||||||
STATIC_ASSERT(static_cast<int>(IsIndependent::kShift) ==
|
|
||||||
Internals::kNodeIsIndependentShift);
|
|
||||||
STATIC_ASSERT(static_cast<int>(IsActive::kShift) ==
|
|
||||||
Internals::kNodeIsActiveShift);
|
|
||||||
set_in_young_list(false);
|
set_in_young_list(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,16 +402,6 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
|
|||||||
flags_ = NodeState::update(flags_, state);
|
flags_ = NodeState::update(flags_, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_independent() { return IsIndependent::decode(flags_); }
|
|
||||||
void set_independent(bool v) { flags_ = IsIndependent::update(flags_, v); }
|
|
||||||
|
|
||||||
bool is_active() {
|
|
||||||
return IsActive::decode(flags_);
|
|
||||||
}
|
|
||||||
void set_active(bool v) {
|
|
||||||
flags_ = IsActive::update(flags_, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_in_young_list() const { return IsInYoungList::decode(flags_); }
|
bool is_in_young_list() const { return IsInYoungList::decode(flags_); }
|
||||||
void set_in_young_list(bool v) { flags_ = IsInYoungList::update(flags_, v); }
|
void set_in_young_list(bool v) { flags_ = IsInYoungList::update(flags_, v); }
|
||||||
|
|
||||||
@ -562,7 +548,6 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
|
|||||||
// This method invokes a finalizer. Updating the method name would require
|
// This method invokes a finalizer. Updating the method name would require
|
||||||
// adjusting CFI blacklist as weak_callback_ is invoked on the wrong type.
|
// adjusting CFI blacklist as weak_callback_ is invoked on the wrong type.
|
||||||
CHECK(IsPendingFinalizer());
|
CHECK(IsPendingFinalizer());
|
||||||
CHECK(!is_active());
|
|
||||||
set_state(NEAR_DEATH);
|
set_state(NEAR_DEATH);
|
||||||
// Check that we are not passing a finalized external string to
|
// Check that we are not passing a finalized external string to
|
||||||
// the callback.
|
// the callback.
|
||||||
@ -593,24 +578,17 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
|
|||||||
private:
|
private:
|
||||||
// Fields that are not used for managing node memory.
|
// Fields that are not used for managing node memory.
|
||||||
void ClearImplFields() {
|
void ClearImplFields() {
|
||||||
set_independent(false);
|
|
||||||
set_active(false);
|
|
||||||
weak_callback_ = nullptr;
|
weak_callback_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckImplFieldsAreCleared() {
|
void CheckImplFieldsAreCleared() {
|
||||||
DCHECK(!is_independent());
|
|
||||||
DCHECK(!is_active());
|
|
||||||
DCHECK_EQ(nullptr, weak_callback_);
|
DCHECK_EQ(nullptr, weak_callback_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This stores three flags (independent, partially_dependent and
|
// This stores three flags (independent, partially_dependent and
|
||||||
// in_young_list) and a State.
|
// in_young_list) and a State.
|
||||||
class NodeState : public BitField8<State, 0, 3> {};
|
class NodeState : public BitField8<State, 0, 3> {};
|
||||||
class IsIndependent : public BitField8<bool, NodeState::kNext, 1> {};
|
class IsInYoungList : public BitField8<bool, NodeState::kNext, 1> {};
|
||||||
// The following two fields are mutually exclusive
|
|
||||||
class IsActive : public BitField8<bool, IsIndependent::kNext, 1> {};
|
|
||||||
class IsInYoungList : public BitField8<bool, IsActive::kNext, 1> {};
|
|
||||||
class NodeWeaknessType
|
class NodeWeaknessType
|
||||||
: public BitField8<WeaknessType, IsInYoungList::kNext, 2> {};
|
: public BitField8<WeaknessType, IsInYoungList::kNext, 2> {};
|
||||||
|
|
||||||
@ -873,12 +851,6 @@ void GlobalHandles::IterateWeakRootsIdentifyFinalizers(
|
|||||||
|
|
||||||
void GlobalHandles::IdentifyWeakUnmodifiedObjects(
|
void GlobalHandles::IdentifyWeakUnmodifiedObjects(
|
||||||
WeakSlotCallback is_unmodified) {
|
WeakSlotCallback is_unmodified) {
|
||||||
for (Node* node : young_nodes_) {
|
|
||||||
if (node->IsWeak() && !is_unmodified(node->location())) {
|
|
||||||
node->set_active(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalEmbedderHeapTracer* const tracer =
|
LocalEmbedderHeapTracer* const tracer =
|
||||||
isolate()->heap()->local_embedder_heap_tracer();
|
isolate()->heap()->local_embedder_heap_tracer();
|
||||||
for (TracedNode* node : traced_young_nodes_) {
|
for (TracedNode* node : traced_young_nodes_) {
|
||||||
@ -895,9 +867,7 @@ void GlobalHandles::IdentifyWeakUnmodifiedObjects(
|
|||||||
|
|
||||||
void GlobalHandles::IterateYoungStrongAndDependentRoots(RootVisitor* v) {
|
void GlobalHandles::IterateYoungStrongAndDependentRoots(RootVisitor* v) {
|
||||||
for (Node* node : young_nodes_) {
|
for (Node* node : young_nodes_) {
|
||||||
if (node->IsStrongRetainer() ||
|
if (node->IsStrongRetainer()) {
|
||||||
(node->IsWeakRetainer() && !node->is_independent() &&
|
|
||||||
node->is_active())) {
|
|
||||||
v->VisitRootPointer(Root::kGlobalHandles, node->label(),
|
v->VisitRootPointer(Root::kGlobalHandles, node->label(),
|
||||||
node->location());
|
node->location());
|
||||||
}
|
}
|
||||||
@ -913,8 +883,7 @@ void GlobalHandles::MarkYoungWeakUnmodifiedObjectsPending(
|
|||||||
WeakSlotCallbackWithHeap is_dead) {
|
WeakSlotCallbackWithHeap is_dead) {
|
||||||
for (Node* node : young_nodes_) {
|
for (Node* node : young_nodes_) {
|
||||||
DCHECK(node->is_in_young_list());
|
DCHECK(node->is_in_young_list());
|
||||||
if ((node->is_independent() || !node->is_active()) && node->IsWeak() &&
|
if (node->IsWeak() && is_dead(isolate_->heap(), node->location())) {
|
||||||
is_dead(isolate_->heap(), node->location())) {
|
|
||||||
if (!node->IsPhantomCallback() && !node->IsPhantomResetHandle()) {
|
if (!node->IsPhantomCallback() && !node->IsPhantomResetHandle()) {
|
||||||
node->MarkPending();
|
node->MarkPending();
|
||||||
}
|
}
|
||||||
@ -926,8 +895,7 @@ void GlobalHandles::IterateYoungWeakUnmodifiedRootsForFinalizers(
|
|||||||
RootVisitor* v) {
|
RootVisitor* v) {
|
||||||
for (Node* node : young_nodes_) {
|
for (Node* node : young_nodes_) {
|
||||||
DCHECK(node->is_in_young_list());
|
DCHECK(node->is_in_young_list());
|
||||||
if ((node->is_independent() || !node->is_active()) &&
|
if (node->IsWeakRetainer() && (node->state() == Node::PENDING)) {
|
||||||
node->IsWeakRetainer() && (node->state() == Node::PENDING)) {
|
|
||||||
DCHECK(!node->IsPhantomCallback());
|
DCHECK(!node->IsPhantomCallback());
|
||||||
DCHECK(!node->IsPhantomResetHandle());
|
DCHECK(!node->IsPhantomResetHandle());
|
||||||
// Finalizers need to survive.
|
// Finalizers need to survive.
|
||||||
@ -941,8 +909,7 @@ void GlobalHandles::IterateYoungWeakUnmodifiedRootsForPhantomHandles(
|
|||||||
RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle) {
|
RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle) {
|
||||||
for (Node* node : young_nodes_) {
|
for (Node* node : young_nodes_) {
|
||||||
DCHECK(node->is_in_young_list());
|
DCHECK(node->is_in_young_list());
|
||||||
if ((node->is_independent() || !node->is_active()) &&
|
if (node->IsWeakRetainer() && (node->state() != Node::PENDING)) {
|
||||||
node->IsWeakRetainer() && (node->state() != Node::PENDING)) {
|
|
||||||
if (should_reset_handle(isolate_->heap(), node->location())) {
|
if (should_reset_handle(isolate_->heap(), node->location())) {
|
||||||
DCHECK(node->IsPhantomResetHandle() || node->IsPhantomCallback());
|
DCHECK(node->IsPhantomResetHandle() || node->IsPhantomCallback());
|
||||||
if (node->IsPhantomResetHandle()) {
|
if (node->IsPhantomResetHandle()) {
|
||||||
@ -1008,9 +975,6 @@ size_t GlobalHandles::PostScavengeProcessing(unsigned post_processing_count) {
|
|||||||
// Filter free nodes.
|
// Filter free nodes.
|
||||||
if (!node->IsRetainer()) continue;
|
if (!node->IsRetainer()) continue;
|
||||||
|
|
||||||
// Reset active state for all affected nodes.
|
|
||||||
node->set_active(false);
|
|
||||||
|
|
||||||
if (node->IsPending()) {
|
if (node->IsPending()) {
|
||||||
DCHECK(node->has_callback());
|
DCHECK(node->has_callback());
|
||||||
DCHECK(node->IsPendingFinalizer());
|
DCHECK(node->IsPendingFinalizer());
|
||||||
@ -1029,9 +993,6 @@ size_t GlobalHandles::PostMarkSweepProcessing(unsigned post_processing_count) {
|
|||||||
// Filter free nodes.
|
// Filter free nodes.
|
||||||
if (!node->IsRetainer()) continue;
|
if (!node->IsRetainer()) continue;
|
||||||
|
|
||||||
// Reset active state for all affected nodes.
|
|
||||||
node->set_active(false);
|
|
||||||
|
|
||||||
if (node->IsPending()) {
|
if (node->IsPending()) {
|
||||||
DCHECK(node->has_callback());
|
DCHECK(node->has_callback());
|
||||||
DCHECK(node->IsPendingFinalizer());
|
DCHECK(node->IsPendingFinalizer());
|
||||||
|
@ -97,16 +97,6 @@ void SamplingHeapProfiler::SampleObject(Address soon_object, size_t size) {
|
|||||||
base::make_unique<Sample>(size, node, loc, this, next_sample_id());
|
base::make_unique<Sample>(size, node, loc, this, next_sample_id());
|
||||||
sample->global.SetWeak(sample.get(), OnWeakCallback,
|
sample->global.SetWeak(sample.get(), OnWeakCallback,
|
||||||
WeakCallbackType::kParameter);
|
WeakCallbackType::kParameter);
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
|
||||||
#endif
|
|
||||||
// MarkIndependent is marked deprecated but we still rely on it here
|
|
||||||
// temporarily.
|
|
||||||
sample->global.MarkIndependent();
|
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
samples_.emplace(sample.get(), std::move(sample));
|
samples_.emplace(sample.get(), std::move(sample));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,22 @@ namespace v8 {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
namespace heap {
|
namespace heap {
|
||||||
|
|
||||||
|
class TemporaryEmbedderHeapTracerScope {
|
||||||
|
public:
|
||||||
|
TemporaryEmbedderHeapTracerScope(v8::Isolate* isolate,
|
||||||
|
v8::EmbedderHeapTracer* tracer)
|
||||||
|
: isolate_(isolate) {
|
||||||
|
isolate_->SetEmbedderHeapTracer(tracer);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TemporaryEmbedderHeapTracerScope() {
|
||||||
|
isolate_->SetEmbedderHeapTracer(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
v8::Isolate* const isolate_;
|
||||||
|
};
|
||||||
|
|
||||||
void SealCurrentObjects(Heap* heap);
|
void SealCurrentObjects(Heap* heap);
|
||||||
|
|
||||||
int FixedArrayLenFromSize(int size);
|
int FixedArrayLenFromSize(int size);
|
||||||
|
@ -103,22 +103,6 @@ class TestEmbedderHeapTracer final : public v8::EmbedderHeapTracer {
|
|||||||
v8::Global<v8::Array> array_;
|
v8::Global<v8::Array> array_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TemporaryEmbedderHeapTracerScope {
|
|
||||||
public:
|
|
||||||
TemporaryEmbedderHeapTracerScope(v8::Isolate* isolate,
|
|
||||||
EmbedderHeapTracer* tracer)
|
|
||||||
: isolate_(isolate) {
|
|
||||||
isolate_->SetEmbedderHeapTracer(tracer);
|
|
||||||
}
|
|
||||||
|
|
||||||
~TemporaryEmbedderHeapTracerScope() {
|
|
||||||
isolate_->SetEmbedderHeapTracer(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
v8::Isolate* const isolate_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(V8RegisteringEmbedderReference) {
|
TEST(V8RegisteringEmbedderReference) {
|
||||||
@ -128,7 +112,7 @@ TEST(V8RegisteringEmbedderReference) {
|
|||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
@ -148,7 +132,7 @@ TEST(EmbedderRegisteringV8Reference) {
|
|||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
@ -181,7 +165,7 @@ TEST(TracingInRevivedSubgraph) {
|
|||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
@ -209,7 +193,7 @@ TEST(TracingInEphemerons) {
|
|||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
@ -240,7 +224,7 @@ TEST(FinalizeTracingIsNoopWhenNotMarking) {
|
|||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
Isolate* i_isolate = CcTest::i_isolate();
|
Isolate* i_isolate = CcTest::i_isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
|
|
||||||
// Finalize a potentially running garbage collection.
|
// Finalize a potentially running garbage collection.
|
||||||
i_isolate->heap()->CollectGarbage(OLD_SPACE,
|
i_isolate->heap()->CollectGarbage(OLD_SPACE,
|
||||||
@ -259,7 +243,7 @@ TEST(FinalizeTracingWhenMarking) {
|
|||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
Isolate* i_isolate = CcTest::i_isolate();
|
Isolate* i_isolate = CcTest::i_isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
|
|
||||||
// Finalize a potentially running garbage collection.
|
// Finalize a potentially running garbage collection.
|
||||||
i_isolate->heap()->CollectGarbage(OLD_SPACE,
|
i_isolate->heap()->CollectGarbage(OLD_SPACE,
|
||||||
@ -284,7 +268,7 @@ TEST(GarbageCollectionForTesting) {
|
|||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
Isolate* i_isolate = CcTest::i_isolate();
|
Isolate* i_isolate = CcTest::i_isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
|
|
||||||
int saved_gc_counter = i_isolate->heap()->gc_count();
|
int saved_gc_counter = i_isolate->heap()->gc_count();
|
||||||
tracer.GarbageCollectionForTesting(EmbedderHeapTracer::kUnknown);
|
tracer.GarbageCollectionForTesting(EmbedderHeapTracer::kUnknown);
|
||||||
@ -414,7 +398,7 @@ TEST(TracedGlobalToUnmodifiedJSObjectSurvivesScavengeWhenExcludedFromRoots) {
|
|||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
tracer.ConsiderTracedGlobalAsRoot(false);
|
tracer.ConsiderTracedGlobalAsRoot(false);
|
||||||
TracedGlobalTest(
|
TracedGlobalTest(
|
||||||
CcTest::isolate(), ConstructJSObject,
|
CcTest::isolate(), ConstructJSObject,
|
||||||
@ -427,7 +411,7 @@ TEST(TracedGlobalToUnmodifiedJSApiObjectSurvivesScavengePerDefault) {
|
|||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
tracer.ConsiderTracedGlobalAsRoot(true);
|
tracer.ConsiderTracedGlobalAsRoot(true);
|
||||||
TracedGlobalTest(
|
TracedGlobalTest(
|
||||||
CcTest::isolate(), ConstructJSApiObject,
|
CcTest::isolate(), ConstructJSApiObject,
|
||||||
@ -440,7 +424,7 @@ TEST(TracedGlobalToUnmodifiedJSApiObjectDiesOnScavengeWhenExcludedFromRoots) {
|
|||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
tracer.ConsiderTracedGlobalAsRoot(false);
|
tracer.ConsiderTracedGlobalAsRoot(false);
|
||||||
TracedGlobalTest(
|
TracedGlobalTest(
|
||||||
CcTest::isolate(), ConstructJSApiObject,
|
CcTest::isolate(), ConstructJSApiObject,
|
||||||
@ -454,7 +438,7 @@ TEST(TracedGlobalWrapperClassId) {
|
|||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
|
|
||||||
v8::TracedGlobal<v8::Object> traced;
|
v8::TracedGlobal<v8::Object> traced;
|
||||||
ConstructJSObject(isolate, isolate->GetCurrentContext(), &traced);
|
ConstructJSObject(isolate, isolate->GetCurrentContext(), &traced);
|
||||||
@ -489,7 +473,7 @@ TEST(TracedGlobalIteration) {
|
|||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
|
|
||||||
v8::TracedGlobal<v8::Object> traced;
|
v8::TracedGlobal<v8::Object> traced;
|
||||||
ConstructJSObject(isolate, isolate->GetCurrentContext(), &traced);
|
ConstructJSObject(isolate, isolate->GetCurrentContext(), &traced);
|
||||||
@ -522,7 +506,7 @@ TEST(TracedGlobalSetFinalizationCallbackScavenge) {
|
|||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
tracer.ConsiderTracedGlobalAsRoot(false);
|
tracer.ConsiderTracedGlobalAsRoot(false);
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
|
|
||||||
v8::TracedGlobal<v8::Object> traced;
|
v8::TracedGlobal<v8::Object> traced;
|
||||||
ConstructJSApiObject(isolate, isolate->GetCurrentContext(), &traced);
|
ConstructJSApiObject(isolate, isolate->GetCurrentContext(), &traced);
|
||||||
@ -544,7 +528,7 @@ TEST(TracedGlobalSetFinalizationCallbackMarkSweep) {
|
|||||||
v8::Isolate* isolate = CcTest::isolate();
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
TestEmbedderHeapTracer tracer;
|
TestEmbedderHeapTracer tracer;
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
|
|
||||||
v8::TracedGlobal<v8::Object> traced;
|
v8::TracedGlobal<v8::Object> traced;
|
||||||
ConstructJSApiObject(isolate, isolate->GetCurrentContext(), &traced);
|
ConstructJSApiObject(isolate, isolate->GetCurrentContext(), &traced);
|
||||||
@ -574,7 +558,7 @@ TEST(TracePrologueCallingIntoV8WriteBarrier) {
|
|||||||
}
|
}
|
||||||
TestEmbedderHeapTracer tracer(TracePrologueBehavior::kCallV8WriteBarrier,
|
TestEmbedderHeapTracer tracer(TracePrologueBehavior::kCallV8WriteBarrier,
|
||||||
std::move(global));
|
std::move(global));
|
||||||
TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
SimulateIncrementalMarking(CcTest::i_isolate()->heap());
|
SimulateIncrementalMarking(CcTest::i_isolate()->heap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,44 +500,6 @@ static void TestWeakGlobalHandleCallback(
|
|||||||
p->first->Reset();
|
p->first->Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(WeakGlobalHandlesScavenge) {
|
|
||||||
FLAG_stress_compaction = false;
|
|
||||||
FLAG_stress_incremental_marking = false;
|
|
||||||
CcTest::InitializeVM();
|
|
||||||
Isolate* isolate = CcTest::i_isolate();
|
|
||||||
Factory* factory = isolate->factory();
|
|
||||||
GlobalHandles* global_handles = isolate->global_handles();
|
|
||||||
|
|
||||||
WeakPointerCleared = false;
|
|
||||||
|
|
||||||
Handle<Object> h1;
|
|
||||||
Handle<Object> h2;
|
|
||||||
|
|
||||||
{
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
|
|
||||||
Handle<Object> i = factory->NewStringFromStaticChars("fisk");
|
|
||||||
Handle<Object> u = factory->NewNumber(1.12344);
|
|
||||||
|
|
||||||
h1 = global_handles->Create(*i);
|
|
||||||
h2 = global_handles->Create(*u);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234);
|
|
||||||
GlobalHandles::MakeWeak(
|
|
||||||
h2.location(), reinterpret_cast<void*>(&handle_and_id),
|
|
||||||
&TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter);
|
|
||||||
|
|
||||||
// Scavenge treats weak pointers as normal roots.
|
|
||||||
CcTest::CollectGarbage(NEW_SPACE);
|
|
||||||
CHECK((*h1)->IsString());
|
|
||||||
CHECK((*h2)->IsHeapNumber());
|
|
||||||
CHECK(!WeakPointerCleared);
|
|
||||||
GlobalHandles::Destroy(h1.location());
|
|
||||||
GlobalHandles::Destroy(h2.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WeakGlobalUnmodifiedApiHandlesScavenge) {
|
TEST(WeakGlobalUnmodifiedApiHandlesScavenge) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
Isolate* isolate = CcTest::i_isolate();
|
Isolate* isolate = CcTest::i_isolate();
|
||||||
@ -576,84 +538,6 @@ TEST(WeakGlobalUnmodifiedApiHandlesScavenge) {
|
|||||||
GlobalHandles::Destroy(h1.location());
|
GlobalHandles::Destroy(h1.location());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WeakGlobalApiHandleModifiedMapScavenge) {
|
|
||||||
CcTest::InitializeVM();
|
|
||||||
Isolate* isolate = CcTest::i_isolate();
|
|
||||||
LocalContext context;
|
|
||||||
GlobalHandles* global_handles = isolate->global_handles();
|
|
||||||
|
|
||||||
WeakPointerCleared = false;
|
|
||||||
|
|
||||||
Handle<Object> h1;
|
|
||||||
|
|
||||||
{
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
|
|
||||||
// Create an API object which does not have the same map as constructor.
|
|
||||||
auto function_template = FunctionTemplate::New(context->GetIsolate());
|
|
||||||
auto instance_t = function_template->InstanceTemplate();
|
|
||||||
instance_t->Set(v8::String::NewFromUtf8(context->GetIsolate(), "a",
|
|
||||||
NewStringType::kNormal)
|
|
||||||
.ToLocalChecked(),
|
|
||||||
v8::Number::New(context->GetIsolate(), 10));
|
|
||||||
auto function =
|
|
||||||
function_template->GetFunction(context.local()).ToLocalChecked();
|
|
||||||
auto i = function->NewInstance(context.local()).ToLocalChecked();
|
|
||||||
|
|
||||||
h1 = global_handles->Create(*(reinterpret_cast<internal::Address*>(*i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Handle<Object>*, int> handle_and_id(&h1, 1234);
|
|
||||||
GlobalHandles::MakeWeak(
|
|
||||||
h1.location(), reinterpret_cast<void*>(&handle_and_id),
|
|
||||||
&TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter);
|
|
||||||
|
|
||||||
CcTest::CollectGarbage(NEW_SPACE);
|
|
||||||
CHECK(!WeakPointerCleared);
|
|
||||||
GlobalHandles::Destroy(h1.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WeakGlobalApiHandleWithElementsScavenge) {
|
|
||||||
CcTest::InitializeVM();
|
|
||||||
Isolate* isolate = CcTest::i_isolate();
|
|
||||||
LocalContext context;
|
|
||||||
GlobalHandles* global_handles = isolate->global_handles();
|
|
||||||
|
|
||||||
WeakPointerCleared = false;
|
|
||||||
|
|
||||||
Handle<Object> h1;
|
|
||||||
|
|
||||||
{
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
|
|
||||||
// Create an API object which has elements.
|
|
||||||
auto function_template = FunctionTemplate::New(context->GetIsolate());
|
|
||||||
auto instance_t = function_template->InstanceTemplate();
|
|
||||||
instance_t->Set(v8::String::NewFromUtf8(context->GetIsolate(), "1",
|
|
||||||
NewStringType::kNormal)
|
|
||||||
.ToLocalChecked(),
|
|
||||||
v8::Number::New(context->GetIsolate(), 10));
|
|
||||||
instance_t->Set(v8::String::NewFromUtf8(context->GetIsolate(), "2",
|
|
||||||
NewStringType::kNormal)
|
|
||||||
.ToLocalChecked(),
|
|
||||||
v8::Number::New(context->GetIsolate(), 10));
|
|
||||||
auto function =
|
|
||||||
function_template->GetFunction(context.local()).ToLocalChecked();
|
|
||||||
auto i = function->NewInstance(context.local()).ToLocalChecked();
|
|
||||||
|
|
||||||
h1 = global_handles->Create(*(reinterpret_cast<internal::Address*>(*i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Handle<Object>*, int> handle_and_id(&h1, 1234);
|
|
||||||
GlobalHandles::MakeWeak(
|
|
||||||
h1.location(), reinterpret_cast<void*>(&handle_and_id),
|
|
||||||
&TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter);
|
|
||||||
|
|
||||||
CcTest::CollectGarbage(NEW_SPACE);
|
|
||||||
CHECK(!WeakPointerCleared);
|
|
||||||
GlobalHandles::Destroy(h1.location());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WeakGlobalHandlesMark) {
|
TEST(WeakGlobalHandlesMark) {
|
||||||
FLAG_stress_incremental_marking = false;
|
FLAG_stress_incremental_marking = false;
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
@ -703,9 +587,7 @@ TEST(DeleteWeakGlobalHandle) {
|
|||||||
GlobalHandles* global_handles = isolate->global_handles();
|
GlobalHandles* global_handles = isolate->global_handles();
|
||||||
|
|
||||||
WeakPointerCleared = false;
|
WeakPointerCleared = false;
|
||||||
|
|
||||||
Handle<Object> h;
|
Handle<Object> h;
|
||||||
|
|
||||||
{
|
{
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
|
|
||||||
@ -717,15 +599,8 @@ TEST(DeleteWeakGlobalHandle) {
|
|||||||
GlobalHandles::MakeWeak(h.location(), reinterpret_cast<void*>(&handle_and_id),
|
GlobalHandles::MakeWeak(h.location(), reinterpret_cast<void*>(&handle_and_id),
|
||||||
&TestWeakGlobalHandleCallback,
|
&TestWeakGlobalHandleCallback,
|
||||||
v8::WeakCallbackType::kParameter);
|
v8::WeakCallbackType::kParameter);
|
||||||
|
|
||||||
// Scanvenge does not recognize weak reference.
|
|
||||||
CcTest::CollectGarbage(NEW_SPACE);
|
|
||||||
|
|
||||||
CHECK(!WeakPointerCleared);
|
CHECK(!WeakPointerCleared);
|
||||||
|
|
||||||
// Mark-compact treats weak reference properly.
|
|
||||||
CcTest::CollectGarbage(OLD_SPACE);
|
CcTest::CollectGarbage(OLD_SPACE);
|
||||||
|
|
||||||
CHECK(WeakPointerCleared);
|
CHECK(WeakPointerCleared);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7956,18 +7956,6 @@ static void IndependentWeakHandle(bool global_gc, bool interlinked) {
|
|||||||
v8::WeakCallbackType::kParameter);
|
v8::WeakCallbackType::kParameter);
|
||||||
object_b.handle.SetWeak(&object_b, &SetFlag,
|
object_b.handle.SetWeak(&object_b, &SetFlag,
|
||||||
v8::WeakCallbackType::kParameter);
|
v8::WeakCallbackType::kParameter);
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
|
||||||
#endif
|
|
||||||
// MarkIndependent is marked deprecated but we still rely on it temporarily.
|
|
||||||
CHECK(!object_b.handle.IsIndependent());
|
|
||||||
object_a.handle.MarkIndependent();
|
|
||||||
object_b.handle.MarkIndependent();
|
|
||||||
CHECK(object_b.handle.IsIndependent());
|
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
if (global_gc) {
|
if (global_gc) {
|
||||||
CcTest::CollectAllGarbage();
|
CcTest::CollectAllGarbage();
|
||||||
} else {
|
} else {
|
||||||
@ -8118,19 +8106,6 @@ void v8::internal::heap::HeapTester::ResetWeakHandle(bool global_gc) {
|
|||||||
v8::WeakCallbackType::kParameter);
|
v8::WeakCallbackType::kParameter);
|
||||||
object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
|
object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
|
||||||
v8::WeakCallbackType::kParameter);
|
v8::WeakCallbackType::kParameter);
|
||||||
if (!global_gc) {
|
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
|
||||||
#endif
|
|
||||||
// MarkIndependent is marked deprecated but we still rely on it temporarily.
|
|
||||||
object_a.handle.MarkIndependent();
|
|
||||||
object_b.handle.MarkIndependent();
|
|
||||||
CHECK(object_b.handle.IsIndependent());
|
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (global_gc) {
|
if (global_gc) {
|
||||||
CcTest::PreciseCollectAllGarbage();
|
CcTest::PreciseCollectAllGarbage();
|
||||||
} else {
|
} else {
|
||||||
@ -8198,16 +8173,6 @@ THREADED_TEST(GCFromWeakCallbacks) {
|
|||||||
object.flag = false;
|
object.flag = false;
|
||||||
object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
|
object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
|
||||||
v8::WeakCallbackType::kParameter);
|
v8::WeakCallbackType::kParameter);
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
|
||||||
#endif
|
|
||||||
// MarkIndependent is marked deprecated but we still rely on it
|
|
||||||
// temporarily.
|
|
||||||
object.handle.MarkIndependent();
|
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
invoke_gc[outer_gc]();
|
invoke_gc[outer_gc]();
|
||||||
EmptyMessageQueues(isolate);
|
EmptyMessageQueues(isolate);
|
||||||
CHECK(object.flag);
|
CHECK(object.flag);
|
||||||
|
@ -39,6 +39,25 @@ namespace internal {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
// Empty v8::EmbedderHeapTracer that never keeps objects alive on Scavenge. See
|
||||||
|
// |IsRootForNonTracingGC|.
|
||||||
|
class NonRootingEmbedderHeapTracer final : public v8::EmbedderHeapTracer {
|
||||||
|
public:
|
||||||
|
NonRootingEmbedderHeapTracer() = default;
|
||||||
|
|
||||||
|
void RegisterV8References(
|
||||||
|
const std::vector<std::pair<void*, void*>>& embedder_fields) final {}
|
||||||
|
bool AdvanceTracing(double deadline_in_ms) final { return true; }
|
||||||
|
bool IsTracingDone() final { return true; }
|
||||||
|
void TracePrologue() final {}
|
||||||
|
void TraceEpilogue() final {}
|
||||||
|
void EnterFinalPause(EmbedderStackState) final {}
|
||||||
|
|
||||||
|
bool IsRootForNonTracingGC(const v8::TracedGlobal<v8::Value>& handle) final {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void InvokeScavenge() { CcTest::CollectGarbage(i::NEW_SPACE); }
|
void InvokeScavenge() { CcTest::CollectGarbage(i::NEW_SPACE); }
|
||||||
|
|
||||||
void InvokeMarkSweep() { CcTest::CollectAllGarbage(); }
|
void InvokeMarkSweep() { CcTest::CollectAllGarbage(); }
|
||||||
@ -47,23 +66,23 @@ void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
|||||||
info.GetReturnValue().Set(v8_num(0));
|
info.GetReturnValue().Set(v8_num(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FlagAndPersistent {
|
struct FlagAndGlobal {
|
||||||
bool flag;
|
bool flag;
|
||||||
v8::Global<v8::Object> handle;
|
v8::Global<v8::Object> handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ResetHandleAndSetFlag(
|
struct TracedGlobalWrapper {
|
||||||
const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
v8::TracedGlobal<v8::Object> handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ResetHandleAndSetFlag(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
||||||
data.GetParameter()->handle.Reset();
|
data.GetParameter()->handle.Reset();
|
||||||
data.GetParameter()->flag = true;
|
data.GetParameter()->flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
using ConstructFunction = void (*)(v8::Isolate* isolate,
|
template <typename HandleContainer>
|
||||||
v8::Local<v8::Context> context,
|
|
||||||
FlagAndPersistent* flag_and_persistent);
|
|
||||||
|
|
||||||
void ConstructJSObject(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
void ConstructJSObject(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
||||||
FlagAndPersistent* flag_and_persistent) {
|
HandleContainer* flag_and_persistent) {
|
||||||
v8::HandleScope handle_scope(isolate);
|
v8::HandleScope handle_scope(isolate);
|
||||||
v8::Local<v8::Object> object(v8::Object::New(isolate));
|
v8::Local<v8::Object> object(v8::Object::New(isolate));
|
||||||
CHECK(!object.IsEmpty());
|
CHECK(!object.IsEmpty());
|
||||||
@ -79,8 +98,9 @@ void ConstructJSObject(v8::Isolate* isolate, v8::Global<v8::Object>* global) {
|
|||||||
CHECK(!global->IsEmpty());
|
CHECK(!global->IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename HandleContainer>
|
||||||
void ConstructJSApiObject(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
void ConstructJSApiObject(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
||||||
FlagAndPersistent* flag_and_persistent) {
|
HandleContainer* flag_and_persistent) {
|
||||||
v8::HandleScope handle_scope(isolate);
|
v8::HandleScope handle_scope(isolate);
|
||||||
v8::Local<v8::FunctionTemplate> fun =
|
v8::Local<v8::FunctionTemplate> fun =
|
||||||
v8::FunctionTemplate::New(isolate, SimpleCallback);
|
v8::FunctionTemplate::New(isolate, SimpleCallback);
|
||||||
@ -95,7 +115,8 @@ void ConstructJSApiObject(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
|||||||
|
|
||||||
enum class SurvivalMode { kSurvives, kDies };
|
enum class SurvivalMode { kSurvives, kDies };
|
||||||
|
|
||||||
template <typename ModifierFunction, typename GCFunction>
|
template <typename ConstructFunction, typename ModifierFunction,
|
||||||
|
typename GCFunction>
|
||||||
void WeakHandleTest(v8::Isolate* isolate, ConstructFunction construct_function,
|
void WeakHandleTest(v8::Isolate* isolate, ConstructFunction construct_function,
|
||||||
ModifierFunction modifier_function, GCFunction gc_function,
|
ModifierFunction modifier_function, GCFunction gc_function,
|
||||||
SurvivalMode survives) {
|
SurvivalMode survives) {
|
||||||
@ -103,7 +124,7 @@ void WeakHandleTest(v8::Isolate* isolate, ConstructFunction construct_function,
|
|||||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
|
|
||||||
FlagAndPersistent fp;
|
FlagAndGlobal fp;
|
||||||
construct_function(isolate, context, &fp);
|
construct_function(isolate, context, &fp);
|
||||||
CHECK(heap::InYoungGeneration(isolate, fp.handle));
|
CHECK(heap::InYoungGeneration(isolate, fp.handle));
|
||||||
fp.handle.SetWeak(&fp, &ResetHandleAndSetFlag,
|
fp.handle.SetWeak(&fp, &ResetHandleAndSetFlag,
|
||||||
@ -115,6 +136,28 @@ void WeakHandleTest(v8::Isolate* isolate, ConstructFunction construct_function,
|
|||||||
CHECK_IMPLIES(survives == SurvivalMode::kDies, fp.flag);
|
CHECK_IMPLIES(survives == SurvivalMode::kDies, fp.flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ConstructFunction, typename ModifierFunction,
|
||||||
|
typename GCFunction>
|
||||||
|
void TracedGlobalTest(v8::Isolate* isolate,
|
||||||
|
ConstructFunction construct_function,
|
||||||
|
ModifierFunction modifier_function,
|
||||||
|
GCFunction gc_function, SurvivalMode survives) {
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||||
|
v8::Context::Scope context_scope(context);
|
||||||
|
|
||||||
|
NonRootingEmbedderHeapTracer tracer;
|
||||||
|
heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
||||||
|
|
||||||
|
TracedGlobalWrapper fp;
|
||||||
|
construct_function(isolate, context, &fp);
|
||||||
|
CHECK(heap::InYoungGeneration(isolate, fp.handle));
|
||||||
|
modifier_function(&fp);
|
||||||
|
gc_function();
|
||||||
|
CHECK_IMPLIES(survives == SurvivalMode::kSurvives, !fp.handle.IsEmpty());
|
||||||
|
CHECK_IMPLIES(survives == SurvivalMode::kDies, fp.handle.IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
void ResurrectingFinalizer(
|
void ResurrectingFinalizer(
|
||||||
const v8::WeakCallbackInfo<v8::Global<v8::Object>>& data) {
|
const v8::WeakCallbackInfo<v8::Global<v8::Object>>& data) {
|
||||||
data.GetParameter()->ClearWeak();
|
data.GetParameter()->ClearWeak();
|
||||||
@ -277,25 +320,36 @@ TEST(PhatomHandlesWithoutCallbacks) {
|
|||||||
CHECK_EQ(0u, isolate->NumberOfPhantomHandleResetsSinceLastCall());
|
CHECK_EQ(0u, isolate->NumberOfPhantomHandleResetsSinceLastCall());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WeakHandleToUnmodifiedJSObjectSurvivesScavenge) {
|
TEST(WeakHandleToUnmodifiedJSObjectDiesOnScavenge) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
WeakHandleTest(
|
||||||
CcTest::isolate(), &ConstructJSObject, [](FlagAndPersistent* fp) {},
|
CcTest::isolate(), &ConstructJSObject<FlagAndGlobal>,
|
||||||
[]() { InvokeScavenge(); }, SurvivalMode::kSurvives);
|
[](FlagAndGlobal* fp) {}, []() { InvokeScavenge(); },
|
||||||
|
SurvivalMode::kDies);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TracedGlobalToUnmodifiedJSObjectSurvivesScavenge) {
|
||||||
|
ManualGCScope manual_gc;
|
||||||
|
CcTest::InitializeVM();
|
||||||
|
TracedGlobalTest(
|
||||||
|
CcTest::isolate(), &ConstructJSObject<TracedGlobalWrapper>,
|
||||||
|
[](TracedGlobalWrapper* fp) {}, []() { InvokeScavenge(); },
|
||||||
|
SurvivalMode::kSurvives);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WeakHandleToUnmodifiedJSObjectDiesOnMarkCompact) {
|
TEST(WeakHandleToUnmodifiedJSObjectDiesOnMarkCompact) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
WeakHandleTest(
|
||||||
CcTest::isolate(), &ConstructJSObject, [](FlagAndPersistent* fp) {},
|
CcTest::isolate(), &ConstructJSObject<FlagAndGlobal>,
|
||||||
[]() { InvokeMarkSweep(); }, SurvivalMode::kDies);
|
[](FlagAndGlobal* fp) {}, []() { InvokeMarkSweep(); },
|
||||||
|
SurvivalMode::kDies);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WeakHandleToUnmodifiedJSObjectSurvivesMarkCompactWhenInHandle) {
|
TEST(WeakHandleToUnmodifiedJSObjectSurvivesMarkCompactWhenInHandle) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
WeakHandleTest(
|
||||||
CcTest::isolate(), &ConstructJSObject,
|
CcTest::isolate(), &ConstructJSObject<FlagAndGlobal>,
|
||||||
[](FlagAndPersistent* fp) {
|
[](FlagAndGlobal* fp) {
|
||||||
v8::Local<v8::Object> handle =
|
v8::Local<v8::Object> handle =
|
||||||
v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
||||||
USE(handle);
|
USE(handle);
|
||||||
@ -306,19 +360,30 @@ TEST(WeakHandleToUnmodifiedJSObjectSurvivesMarkCompactWhenInHandle) {
|
|||||||
TEST(WeakHandleToUnmodifiedJSApiObjectDiesOnScavenge) {
|
TEST(WeakHandleToUnmodifiedJSApiObjectDiesOnScavenge) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
WeakHandleTest(
|
||||||
CcTest::isolate(), &ConstructJSApiObject, [](FlagAndPersistent* fp) {},
|
CcTest::isolate(), &ConstructJSApiObject<FlagAndGlobal>,
|
||||||
[]() { InvokeScavenge(); }, SurvivalMode::kDies);
|
[](FlagAndGlobal* fp) {}, []() { InvokeScavenge(); },
|
||||||
|
SurvivalMode::kDies);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WeakHandleToJSApiObjectWithIdentityHashSurvivesScavenge) {
|
TEST(TracedGlobalToUnmodifiedJSApiObjectDiesOnScavenge) {
|
||||||
|
ManualGCScope manual_gc;
|
||||||
|
CcTest::InitializeVM();
|
||||||
|
TracedGlobalTest(
|
||||||
|
CcTest::isolate(), &ConstructJSApiObject<TracedGlobalWrapper>,
|
||||||
|
[](TracedGlobalWrapper* fp) {}, []() { InvokeScavenge(); },
|
||||||
|
SurvivalMode::kDies);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TracedGlobalToJSApiObjectWithIdentityHashSurvivesScavenge) {
|
||||||
|
ManualGCScope manual_gc;
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
Isolate* i_isolate = CcTest::i_isolate();
|
Isolate* i_isolate = CcTest::i_isolate();
|
||||||
HandleScope scope(i_isolate);
|
HandleScope scope(i_isolate);
|
||||||
Handle<JSWeakMap> weakmap = i_isolate->factory()->NewJSWeakMap();
|
Handle<JSWeakMap> weakmap = i_isolate->factory()->NewJSWeakMap();
|
||||||
|
|
||||||
WeakHandleTest(
|
TracedGlobalTest(
|
||||||
CcTest::isolate(), &ConstructJSApiObject,
|
CcTest::isolate(), &ConstructJSApiObject<TracedGlobalWrapper>,
|
||||||
[&weakmap, i_isolate](FlagAndPersistent* fp) {
|
[&weakmap, i_isolate](TracedGlobalWrapper* fp) {
|
||||||
v8::HandleScope scope(CcTest::isolate());
|
v8::HandleScope scope(CcTest::isolate());
|
||||||
Handle<JSReceiver> key =
|
Handle<JSReceiver> key =
|
||||||
Utils::OpenHandle(*fp->handle.Get(CcTest::isolate()));
|
Utils::OpenHandle(*fp->handle.Get(CcTest::isolate()));
|
||||||
@ -332,8 +397,8 @@ TEST(WeakHandleToJSApiObjectWithIdentityHashSurvivesScavenge) {
|
|||||||
TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesScavengeWhenInHandle) {
|
TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesScavengeWhenInHandle) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
WeakHandleTest(
|
||||||
CcTest::isolate(), &ConstructJSApiObject,
|
CcTest::isolate(), &ConstructJSApiObject<FlagAndGlobal>,
|
||||||
[](FlagAndPersistent* fp) {
|
[](FlagAndGlobal* fp) {
|
||||||
v8::Local<v8::Object> handle =
|
v8::Local<v8::Object> handle =
|
||||||
v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
||||||
USE(handle);
|
USE(handle);
|
||||||
@ -344,15 +409,16 @@ TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesScavengeWhenInHandle) {
|
|||||||
TEST(WeakHandleToUnmodifiedJSApiObjectDiesOnMarkCompact) {
|
TEST(WeakHandleToUnmodifiedJSApiObjectDiesOnMarkCompact) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
WeakHandleTest(
|
||||||
CcTest::isolate(), &ConstructJSApiObject, [](FlagAndPersistent* fp) {},
|
CcTest::isolate(), &ConstructJSApiObject<FlagAndGlobal>,
|
||||||
[]() { InvokeMarkSweep(); }, SurvivalMode::kDies);
|
[](FlagAndGlobal* fp) {}, []() { InvokeMarkSweep(); },
|
||||||
|
SurvivalMode::kDies);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesMarkCompactWhenInHandle) {
|
TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesMarkCompactWhenInHandle) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
WeakHandleTest(
|
||||||
CcTest::isolate(), &ConstructJSApiObject,
|
CcTest::isolate(), &ConstructJSApiObject<FlagAndGlobal>,
|
||||||
[](FlagAndPersistent* fp) {
|
[](FlagAndGlobal* fp) {
|
||||||
v8::Local<v8::Object> handle =
|
v8::Local<v8::Object> handle =
|
||||||
v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
||||||
USE(handle);
|
USE(handle);
|
||||||
@ -360,58 +426,57 @@ TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesMarkCompactWhenInHandle) {
|
|||||||
[]() { InvokeMarkSweep(); }, SurvivalMode::kSurvives);
|
[]() { InvokeMarkSweep(); }, SurvivalMode::kSurvives);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WeakHandleToActiveUnmodifiedJSApiObjectSurvivesScavenge) {
|
TEST(TracedGlobalToJSApiObjectWithModifiedMapSurvivesScavenge) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
CcTest::isolate(), &ConstructJSApiObject,
|
LocalContext context;
|
||||||
[](FlagAndPersistent* fp) {
|
|
||||||
#if __clang__
|
TracedGlobal<v8::Object> handle;
|
||||||
#pragma clang diagnostic push
|
{
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
v8::HandleScope scope(isolate);
|
||||||
#endif
|
// Create an API object which does not have the same map as constructor.
|
||||||
fp->handle.MarkActive();
|
auto function_template = FunctionTemplate::New(isolate);
|
||||||
#if __clang__
|
auto instance_t = function_template->InstanceTemplate();
|
||||||
#pragma clang diagnostic pop
|
instance_t->Set(
|
||||||
#endif
|
v8::String::NewFromUtf8(isolate, "a", NewStringType::kNormal)
|
||||||
},
|
.ToLocalChecked(),
|
||||||
[]() { InvokeScavenge(); }, SurvivalMode::kSurvives);
|
v8::Number::New(isolate, 10));
|
||||||
|
auto function =
|
||||||
|
function_template->GetFunction(context.local()).ToLocalChecked();
|
||||||
|
auto i = function->NewInstance(context.local()).ToLocalChecked();
|
||||||
|
handle.Reset(isolate, i);
|
||||||
|
}
|
||||||
|
InvokeScavenge();
|
||||||
|
CHECK(!handle.IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WeakHandleToActiveUnmodifiedJSApiObjectDiesOnMarkCompact) {
|
TEST(TracedGlobalTOJsApiObjectWithElementsSurvivesScavenge) {
|
||||||
CcTest::InitializeVM();
|
CcTest::InitializeVM();
|
||||||
WeakHandleTest(
|
v8::Isolate* isolate = CcTest::isolate();
|
||||||
CcTest::isolate(), &ConstructJSApiObject,
|
LocalContext context;
|
||||||
[](FlagAndPersistent* fp) {
|
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
|
||||||
#endif
|
|
||||||
fp->handle.MarkActive();
|
|
||||||
#if __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
},
|
|
||||||
[]() { InvokeMarkSweep(); }, SurvivalMode::kDies);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(WeakHandleToActiveUnmodifiedJSApiObjectSurvivesMarkCompactWhenInHandle) {
|
TracedGlobal<v8::Object> handle;
|
||||||
CcTest::InitializeVM();
|
{
|
||||||
WeakHandleTest(
|
v8::HandleScope scope(isolate);
|
||||||
CcTest::isolate(), &ConstructJSApiObject,
|
|
||||||
[](FlagAndPersistent* fp) {
|
// Create an API object which has elements.
|
||||||
#if __clang__
|
auto function_template = FunctionTemplate::New(isolate);
|
||||||
#pragma clang diagnostic push
|
auto instance_t = function_template->InstanceTemplate();
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
instance_t->Set(
|
||||||
#endif
|
v8::String::NewFromUtf8(isolate, "1", NewStringType::kNormal)
|
||||||
fp->handle.MarkActive();
|
.ToLocalChecked(),
|
||||||
#if __clang__
|
v8::Number::New(isolate, 10));
|
||||||
#pragma clang diagnostic pop
|
instance_t->Set(
|
||||||
#endif
|
v8::String::NewFromUtf8(isolate, "2", NewStringType::kNormal)
|
||||||
v8::Local<v8::Object> handle =
|
.ToLocalChecked(),
|
||||||
v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
v8::Number::New(isolate, 10));
|
||||||
USE(handle);
|
auto function =
|
||||||
},
|
function_template->GetFunction(context.local()).ToLocalChecked();
|
||||||
[]() { InvokeMarkSweep(); }, SurvivalMode::kSurvives);
|
auto i = function->NewInstance(context.local()).ToLocalChecked();
|
||||||
|
handle.Reset(isolate, i);
|
||||||
|
}
|
||||||
|
InvokeScavenge();
|
||||||
|
CHECK(!handle.IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FinalizerOnUnmodifiedJSApiObjectDoesNotCrash) {
|
TEST(FinalizerOnUnmodifiedJSApiObjectDoesNotCrash) {
|
||||||
@ -422,8 +487,7 @@ TEST(FinalizerOnUnmodifiedJSApiObjectDoesNotCrash) {
|
|||||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
|
|
||||||
FlagAndPersistent fp;
|
FlagAndGlobal fp;
|
||||||
// Could use a regular object and MarkIndependent too.
|
|
||||||
ConstructJSApiObject(isolate, context, &fp);
|
ConstructJSApiObject(isolate, context, &fp);
|
||||||
fp.handle.SetWeak(&fp, &ResetHandleAndSetFlag,
|
fp.handle.SetWeak(&fp, &ResetHandleAndSetFlag,
|
||||||
v8::WeakCallbackType::kFinalizer);
|
v8::WeakCallbackType::kFinalizer);
|
||||||
@ -495,22 +559,22 @@ TEST(FinalizerDiesAndKeepsPhantomAliveOnMarkCompact) {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void ForceScavenge2(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
void ForceScavenge2(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
||||||
data.GetParameter()->flag = true;
|
data.GetParameter()->flag = true;
|
||||||
InvokeScavenge();
|
InvokeScavenge();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForceScavenge1(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
void ForceScavenge1(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
||||||
data.GetParameter()->handle.Reset();
|
data.GetParameter()->handle.Reset();
|
||||||
data.SetSecondPassCallback(ForceScavenge2);
|
data.SetSecondPassCallback(ForceScavenge2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForceMarkSweep2(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
void ForceMarkSweep2(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
||||||
data.GetParameter()->flag = true;
|
data.GetParameter()->flag = true;
|
||||||
InvokeMarkSweep();
|
InvokeMarkSweep();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForceMarkSweep1(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
void ForceMarkSweep1(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
||||||
data.GetParameter()->handle.Reset();
|
data.GetParameter()->handle.Reset();
|
||||||
data.SetSecondPassCallback(ForceMarkSweep2);
|
data.SetSecondPassCallback(ForceMarkSweep2);
|
||||||
}
|
}
|
||||||
@ -525,7 +589,7 @@ TEST(GCFromWeakCallbacks) {
|
|||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
|
|
||||||
static const int kNumberOfGCTypes = 2;
|
static const int kNumberOfGCTypes = 2;
|
||||||
typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
|
typedef v8::WeakCallbackInfo<FlagAndGlobal>::Callback Callback;
|
||||||
Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
|
Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
|
||||||
&ForceMarkSweep1};
|
&ForceMarkSweep1};
|
||||||
|
|
||||||
@ -534,7 +598,7 @@ TEST(GCFromWeakCallbacks) {
|
|||||||
|
|
||||||
for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
|
for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
|
||||||
for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
|
for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
|
||||||
FlagAndPersistent fp;
|
FlagAndGlobal fp;
|
||||||
ConstructJSApiObject(isolate, context, &fp);
|
ConstructJSApiObject(isolate, context, &fp);
|
||||||
CHECK(heap::InYoungGeneration(isolate, fp.handle));
|
CHECK(heap::InYoungGeneration(isolate, fp.handle));
|
||||||
fp.flag = false;
|
fp.flag = false;
|
||||||
@ -549,11 +613,11 @@ TEST(GCFromWeakCallbacks) {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void SecondPassCallback(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
void SecondPassCallback(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
||||||
data.GetParameter()->flag = true;
|
data.GetParameter()->flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FirstPassCallback(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
void FirstPassCallback(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
||||||
data.GetParameter()->handle.Reset();
|
data.GetParameter()->handle.Reset();
|
||||||
data.SetSecondPassCallback(SecondPassCallback);
|
data.SetSecondPassCallback(SecondPassCallback);
|
||||||
}
|
}
|
||||||
@ -566,7 +630,7 @@ TEST(SecondPassPhantomCallbacks) {
|
|||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
FlagAndPersistent fp;
|
FlagAndGlobal fp;
|
||||||
ConstructJSApiObject(isolate, context, &fp);
|
ConstructJSApiObject(isolate, context, &fp);
|
||||||
fp.flag = false;
|
fp.flag = false;
|
||||||
fp.handle.SetWeak(&fp, FirstPassCallback, v8::WeakCallbackType::kParameter);
|
fp.handle.SetWeak(&fp, FirstPassCallback, v8::WeakCallbackType::kParameter);
|
||||||
|
Loading…
Reference in New Issue
Block a user