|
@@ -1,1159 +0,0 @@
|
|
|
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
-From: Jeremy Apthorp <[email protected]>
|
|
|
-Date: Mon, 29 Apr 2019 13:52:07 -0700
|
|
|
-Subject: Revert "Reland "[api,heap] Remove deprecated Persistent APIs""
|
|
|
-
|
|
|
-This reverts commit 4214933c6bb4d1815f07a40eaf008cb1e37ef217.
|
|
|
-
|
|
|
-diff --git a/include/v8-internal.h b/include/v8-internal.h
|
|
|
-index ef13006d1379290053ec00f70433c9bdaaa1daff..fe2ce67e0df04e58502d73ca5ac81a86ee001494 100644
|
|
|
---- a/include/v8-internal.h
|
|
|
-+++ b/include/v8-internal.h
|
|
|
-@@ -174,6 +174,8 @@ class Internals {
|
|
|
- static const int kNodeStateMask = 0x7;
|
|
|
- static const int kNodeStateIsWeakValue = 2;
|
|
|
- static const int kNodeStateIsPendingValue = 3;
|
|
|
-+ static const int kNodeIsIndependentShift = 3;
|
|
|
-+ static const int kNodeIsActiveShift = 4;
|
|
|
-
|
|
|
- static const int kFirstNonstringType = 0x40;
|
|
|
- static const int kOddballType = 0x43;
|
|
|
-diff --git a/include/v8-util.h b/include/v8-util.h
|
|
|
-index 29d813e4274d16939b77e5e1d13f097c5e08b0af..24962607076f780105365700d5aff10336eb1dac 100644
|
|
|
---- a/include/v8-util.h
|
|
|
-+++ b/include/v8-util.h
|
|
|
-@@ -194,6 +194,14 @@ class PersistentValueMapBase {
|
|
|
- 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.
|
|
|
- */
|
|
|
-@@ -344,6 +352,16 @@ class PersistentValueMapBase {
|
|
|
- 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>
|
|
|
- class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
|
|
|
- public:
|
|
|
-diff --git a/include/v8.h b/include/v8.h
|
|
|
-index cb9da12b88bca393ea814a226da82ecae857d343..011495aafd67337b7e0251e571ee2d79bdcfedb3 100644
|
|
|
---- a/include/v8.h
|
|
|
-+++ b/include/v8.h
|
|
|
-@@ -544,6 +544,38 @@ template <class T> class PersistentBase {
|
|
|
- */
|
|
|
- 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. */
|
|
|
- V8_INLINE bool IsWeak() const;
|
|
|
-
|
|
|
-@@ -8847,6 +8879,9 @@ class V8_EXPORT V8 {
|
|
|
- const char* label);
|
|
|
- static Value* Eternalize(Isolate* isolate, Value* handle);
|
|
|
-
|
|
|
-+ static void RegisterExternallyReferencedObject(internal::Address* location,
|
|
|
-+ internal::Isolate* isolate);
|
|
|
-+
|
|
|
- template <class K, class V, class T>
|
|
|
- friend class PersistentValueMapBase;
|
|
|
-
|
|
|
-@@ -9793,6 +9828,14 @@ void Persistent<T, M>::Copy(const Persistent<S, M2>& that) {
|
|
|
- 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>
|
|
|
- bool PersistentBase<T>::IsWeak() const {
|
|
|
- typedef internal::Internals I;
|
|
|
-@@ -9859,6 +9902,31 @@ void PersistentBase<T>::AnnotateStrongRetainer(const char* 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>
|
|
|
- void PersistentBase<T>::SetWrapperClassId(uint16_t class_id) {
|
|
|
- typedef internal::Internals I;
|
|
|
-diff --git a/src/api/api.cc b/src/api/api.cc
|
|
|
-index efaa78cd42945c0a9176a53d59364f488648418a..0964a815793f3347e5326817e56e75cd851cea4d 100644
|
|
|
---- a/src/api/api.cc
|
|
|
-+++ b/src/api/api.cc
|
|
|
-@@ -1044,6 +1044,11 @@ void V8::MoveTracedGlobalReference(internal::Address** from,
|
|
|
- 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,
|
|
|
- WeakCallbackInfo<void>::Callback weak_callback,
|
|
|
- WeakCallbackType type) {
|
|
|
-diff --git a/src/global-handles.cc b/src/global-handles.cc
|
|
|
-index ab6172836d38ad53b8b4f5d8d3cac5740ddd6788..b647cc6d55089e1c1835c0b7fd24bf84b3995ab4 100644
|
|
|
---- a/src/global-handles.cc
|
|
|
-+++ b/src/global-handles.cc
|
|
|
-@@ -380,6 +380,10 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
|
|
|
- Internals::kNodeStateMask);
|
|
|
- STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue);
|
|
|
- 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);
|
|
|
- }
|
|
|
-
|
|
|
-@@ -403,6 +407,16 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
|
|
|
- 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_); }
|
|
|
- void set_in_young_list(bool v) { flags_ = IsInYoungList::update(flags_, v); }
|
|
|
-
|
|
|
-@@ -549,6 +563,7 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
|
|
|
- // This method invokes a finalizer. Updating the method name would require
|
|
|
- // adjusting CFI blacklist as weak_callback_ is invoked on the wrong type.
|
|
|
- CHECK(IsPendingFinalizer());
|
|
|
-+ CHECK(!is_active());
|
|
|
- set_state(NEAR_DEATH);
|
|
|
- // Check that we are not passing a finalized external string to
|
|
|
- // the callback.
|
|
|
-@@ -579,17 +594,24 @@ class GlobalHandles::Node final : public NodeBase<GlobalHandles::Node> {
|
|
|
- private:
|
|
|
- // Fields that are not used for managing node memory.
|
|
|
- void ClearImplFields() {
|
|
|
-+ set_independent(false);
|
|
|
-+ set_active(false);
|
|
|
- weak_callback_ = nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- void CheckImplFieldsAreCleared() {
|
|
|
-+ DCHECK(!is_independent());
|
|
|
-+ DCHECK(!is_active());
|
|
|
- DCHECK_EQ(nullptr, weak_callback_);
|
|
|
- }
|
|
|
-
|
|
|
- // This stores three flags (independent, partially_dependent and
|
|
|
- // in_young_list) and a State.
|
|
|
- class NodeState : public BitField8<State, 0, 3> {};
|
|
|
-- class IsInYoungList : public BitField8<bool, NodeState::kNext, 1> {};
|
|
|
-+ class IsIndependent : 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
|
|
|
- : public BitField8<WeaknessType, IsInYoungList::kNext, 2> {};
|
|
|
-
|
|
|
-@@ -852,6 +874,12 @@ void GlobalHandles::IterateWeakRootsIdentifyFinalizers(
|
|
|
-
|
|
|
- void GlobalHandles::IdentifyWeakUnmodifiedObjects(
|
|
|
- WeakSlotCallback is_unmodified) {
|
|
|
-+ for (Node* node : young_nodes_) {
|
|
|
-+ if (node->IsWeak() && !is_unmodified(node->location())) {
|
|
|
-+ node->set_active(true);
|
|
|
-+ }
|
|
|
-+ }
|
|
|
-+
|
|
|
- LocalEmbedderHeapTracer* const tracer =
|
|
|
- isolate()->heap()->local_embedder_heap_tracer();
|
|
|
- for (TracedNode* node : traced_young_nodes_) {
|
|
|
-@@ -868,7 +896,9 @@ void GlobalHandles::IdentifyWeakUnmodifiedObjects(
|
|
|
-
|
|
|
- void GlobalHandles::IterateYoungStrongAndDependentRoots(RootVisitor* v) {
|
|
|
- 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(),
|
|
|
- node->location());
|
|
|
- }
|
|
|
-@@ -884,7 +914,8 @@ void GlobalHandles::MarkYoungWeakUnmodifiedObjectsPending(
|
|
|
- WeakSlotCallbackWithHeap is_dead) {
|
|
|
- for (Node* node : young_nodes_) {
|
|
|
- DCHECK(node->is_in_young_list());
|
|
|
-- if (node->IsWeak() && is_dead(isolate_->heap(), node->location())) {
|
|
|
-+ if ((node->is_independent() || !node->is_active()) && node->IsWeak() &&
|
|
|
-+ is_dead(isolate_->heap(), node->location())) {
|
|
|
- if (!node->IsPhantomCallback() && !node->IsPhantomResetHandle()) {
|
|
|
- node->MarkPending();
|
|
|
- }
|
|
|
-@@ -896,7 +927,8 @@ void GlobalHandles::IterateYoungWeakUnmodifiedRootsForFinalizers(
|
|
|
- RootVisitor* v) {
|
|
|
- for (Node* node : young_nodes_) {
|
|
|
- DCHECK(node->is_in_young_list());
|
|
|
-- if (node->IsWeakRetainer() && (node->state() == Node::PENDING)) {
|
|
|
-+ if ((node->is_independent() || !node->is_active()) &&
|
|
|
-+ node->IsWeakRetainer() && (node->state() == Node::PENDING)) {
|
|
|
- DCHECK(!node->IsPhantomCallback());
|
|
|
- DCHECK(!node->IsPhantomResetHandle());
|
|
|
- // Finalizers need to survive.
|
|
|
-@@ -910,7 +942,8 @@ void GlobalHandles::IterateYoungWeakUnmodifiedRootsForPhantomHandles(
|
|
|
- RootVisitor* v, WeakSlotCallbackWithHeap should_reset_handle) {
|
|
|
- for (Node* node : young_nodes_) {
|
|
|
- DCHECK(node->is_in_young_list());
|
|
|
-- if (node->IsWeakRetainer() && (node->state() != Node::PENDING)) {
|
|
|
-+ if ((node->is_independent() || !node->is_active()) &&
|
|
|
-+ node->IsWeakRetainer() && (node->state() != Node::PENDING)) {
|
|
|
- if (should_reset_handle(isolate_->heap(), node->location())) {
|
|
|
- DCHECK(node->IsPhantomResetHandle() || node->IsPhantomCallback());
|
|
|
- if (node->IsPhantomResetHandle()) {
|
|
|
-@@ -985,6 +1018,9 @@ size_t GlobalHandles::PostScavengeProcessing(unsigned post_processing_count) {
|
|
|
- // Filter free nodes.
|
|
|
- if (!node->IsRetainer()) continue;
|
|
|
-
|
|
|
-+ // Reset active state for all affected nodes.
|
|
|
-+ node->set_active(false);
|
|
|
-+
|
|
|
- if (node->IsPending()) {
|
|
|
- DCHECK(node->has_callback());
|
|
|
- DCHECK(node->IsPendingFinalizer());
|
|
|
-@@ -1003,6 +1039,9 @@ size_t GlobalHandles::PostMarkSweepProcessing(unsigned post_processing_count) {
|
|
|
- // Filter free nodes.
|
|
|
- if (!node->IsRetainer()) continue;
|
|
|
-
|
|
|
-+ // Reset active state for all affected nodes.
|
|
|
-+ node->set_active(false);
|
|
|
-+
|
|
|
- if (node->IsPending()) {
|
|
|
- DCHECK(node->has_callback());
|
|
|
- DCHECK(node->IsPendingFinalizer());
|
|
|
-diff --git a/src/profiler/sampling-heap-profiler.cc b/src/profiler/sampling-heap-profiler.cc
|
|
|
-index 2b22e673d7cfb4601a31f3d687eb5b3ba69be6c4..cd79b398b482ca31dcad8477d99a8b9a9644640c 100644
|
|
|
---- a/src/profiler/sampling-heap-profiler.cc
|
|
|
-+++ b/src/profiler/sampling-heap-profiler.cc
|
|
|
-@@ -92,6 +92,16 @@ void SamplingHeapProfiler::SampleObject(Address soon_object, size_t size) {
|
|
|
- base::make_unique<Sample>(size, node, loc, this, next_sample_id());
|
|
|
- sample->global.SetWeak(sample.get(), OnWeakCallback,
|
|
|
- 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));
|
|
|
- }
|
|
|
-
|
|
|
-diff --git a/test/cctest/heap/heap-utils.h b/test/cctest/heap/heap-utils.h
|
|
|
-index dfd4094913e84d3f04daea5896b34fd21107295b..375c2aeb13320cdc4faa3cdacaa71ac4e0db1896 100644
|
|
|
---- a/test/cctest/heap/heap-utils.h
|
|
|
-+++ b/test/cctest/heap/heap-utils.h
|
|
|
-@@ -12,22 +12,6 @@ namespace v8 {
|
|
|
- namespace internal {
|
|
|
- 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);
|
|
|
-
|
|
|
- int FixedArrayLenFromSize(int size);
|
|
|
-diff --git a/test/cctest/heap/test-embedder-tracing.cc b/test/cctest/heap/test-embedder-tracing.cc
|
|
|
-index 022d605aff3b2eafa07be9075c1ff1645baecbfb..aa76386a22f234bb133e54a853e40b30d91e0b88 100644
|
|
|
---- a/test/cctest/heap/test-embedder-tracing.cc
|
|
|
-+++ b/test/cctest/heap/test-embedder-tracing.cc
|
|
|
-@@ -103,6 +103,22 @@ class TestEmbedderHeapTracer final : public v8::EmbedderHeapTracer {
|
|
|
- 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
|
|
|
-
|
|
|
- TEST(V8RegisteringEmbedderReference) {
|
|
|
-@@ -112,7 +128,7 @@ TEST(V8RegisteringEmbedderReference) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- v8::Local<v8::Context> context = v8::Context::New(isolate);
|
|
|
- v8::Context::Scope context_scope(context);
|
|
|
-@@ -132,7 +148,7 @@ TEST(EmbedderRegisteringV8Reference) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- v8::Local<v8::Context> context = v8::Context::New(isolate);
|
|
|
- v8::Context::Scope context_scope(context);
|
|
|
-@@ -165,7 +181,7 @@ TEST(TracingInRevivedSubgraph) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- v8::Local<v8::Context> context = v8::Context::New(isolate);
|
|
|
- v8::Context::Scope context_scope(context);
|
|
|
-@@ -193,7 +209,7 @@ TEST(TracingInEphemerons) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- v8::Local<v8::Context> context = v8::Context::New(isolate);
|
|
|
- v8::Context::Scope context_scope(context);
|
|
|
-@@ -224,7 +240,7 @@ TEST(FinalizeTracingIsNoopWhenNotMarking) {
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- Isolate* i_isolate = CcTest::i_isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-
|
|
|
- // Finalize a potentially running garbage collection.
|
|
|
- i_isolate->heap()->CollectGarbage(OLD_SPACE,
|
|
|
-@@ -243,7 +259,7 @@ TEST(FinalizeTracingWhenMarking) {
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- Isolate* i_isolate = CcTest::i_isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-
|
|
|
- // Finalize a potentially running garbage collection.
|
|
|
- i_isolate->heap()->CollectGarbage(OLD_SPACE,
|
|
|
-@@ -268,7 +284,7 @@ TEST(GarbageCollectionForTesting) {
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- Isolate* i_isolate = CcTest::i_isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-
|
|
|
- int saved_gc_counter = i_isolate->heap()->gc_count();
|
|
|
- tracer.GarbageCollectionForTesting(EmbedderHeapTracer::kUnknown);
|
|
|
-@@ -398,7 +414,7 @@ TEST(TracedGlobalToUnmodifiedJSObjectSurvivesScavengeWhenExcludedFromRoots) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
- tracer.ConsiderTracedGlobalAsRoot(false);
|
|
|
- TracedGlobalTest(
|
|
|
- CcTest::isolate(), ConstructJSObject,
|
|
|
-@@ -411,7 +427,7 @@ TEST(TracedGlobalToUnmodifiedJSApiObjectSurvivesScavengePerDefault) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
- tracer.ConsiderTracedGlobalAsRoot(true);
|
|
|
- TracedGlobalTest(
|
|
|
- CcTest::isolate(), ConstructJSApiObject,
|
|
|
-@@ -424,7 +440,7 @@ TEST(TracedGlobalToUnmodifiedJSApiObjectDiesOnScavengeWhenExcludedFromRoots) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
- tracer.ConsiderTracedGlobalAsRoot(false);
|
|
|
- TracedGlobalTest(
|
|
|
- CcTest::isolate(), ConstructJSApiObject,
|
|
|
-@@ -438,7 +454,7 @@ TEST(TracedGlobalWrapperClassId) {
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-
|
|
|
- v8::TracedGlobal<v8::Object> traced;
|
|
|
- ConstructJSObject(isolate, isolate->GetCurrentContext(), &traced);
|
|
|
-@@ -473,7 +489,7 @@ TEST(TracedGlobalIteration) {
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-
|
|
|
- v8::TracedGlobal<v8::Object> traced;
|
|
|
- ConstructJSObject(isolate, isolate->GetCurrentContext(), &traced);
|
|
|
-@@ -506,7 +522,7 @@ TEST(TracedGlobalSetFinalizationCallbackScavenge) {
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
- tracer.ConsiderTracedGlobalAsRoot(false);
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-
|
|
|
- v8::TracedGlobal<v8::Object> traced;
|
|
|
- ConstructJSApiObject(isolate, isolate->GetCurrentContext(), &traced);
|
|
|
-@@ -528,7 +544,7 @@ TEST(TracedGlobalSetFinalizationCallbackMarkSweep) {
|
|
|
- v8::Isolate* isolate = CcTest::isolate();
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- TestEmbedderHeapTracer tracer;
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-
|
|
|
- v8::TracedGlobal<v8::Object> traced;
|
|
|
- ConstructJSApiObject(isolate, isolate->GetCurrentContext(), &traced);
|
|
|
-@@ -558,7 +574,7 @@ TEST(TracePrologueCallingIntoV8WriteBarrier) {
|
|
|
- }
|
|
|
- TestEmbedderHeapTracer tracer(TracePrologueBehavior::kCallV8WriteBarrier,
|
|
|
- std::move(global));
|
|
|
-- heap::TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
-+ TemporaryEmbedderHeapTracerScope tracer_scope(isolate, &tracer);
|
|
|
- SimulateIncrementalMarking(CcTest::i_isolate()->heap());
|
|
|
- }
|
|
|
-
|
|
|
-diff --git a/test/cctest/heap/test-heap.cc b/test/cctest/heap/test-heap.cc
|
|
|
-index 951c249c0ab909bef84e28221f682389c58d7b11..faad45cb4c11360487d97b04bdde0dce71d9e3cd 100644
|
|
|
---- a/test/cctest/heap/test-heap.cc
|
|
|
-+++ b/test/cctest/heap/test-heap.cc
|
|
|
-@@ -496,6 +496,44 @@ static void TestWeakGlobalHandleCallback(
|
|
|
- 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) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- Isolate* isolate = CcTest::i_isolate();
|
|
|
-@@ -534,6 +572,84 @@ TEST(WeakGlobalUnmodifiedApiHandlesScavenge) {
|
|
|
- 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) {
|
|
|
- FLAG_stress_incremental_marking = false;
|
|
|
- CcTest::InitializeVM();
|
|
|
-@@ -583,7 +699,9 @@ TEST(DeleteWeakGlobalHandle) {
|
|
|
- GlobalHandles* global_handles = isolate->global_handles();
|
|
|
-
|
|
|
- WeakPointerCleared = false;
|
|
|
-+
|
|
|
- Handle<Object> h;
|
|
|
-+
|
|
|
- {
|
|
|
- HandleScope scope(isolate);
|
|
|
-
|
|
|
-@@ -595,8 +713,15 @@ TEST(DeleteWeakGlobalHandle) {
|
|
|
- GlobalHandles::MakeWeak(h.location(), reinterpret_cast<void*>(&handle_and_id),
|
|
|
- &TestWeakGlobalHandleCallback,
|
|
|
- v8::WeakCallbackType::kParameter);
|
|
|
-+
|
|
|
-+ // Scanvenge does not recognize weak reference.
|
|
|
-+ CcTest::CollectGarbage(NEW_SPACE);
|
|
|
-+
|
|
|
- CHECK(!WeakPointerCleared);
|
|
|
-+
|
|
|
-+ // Mark-compact treats weak reference properly.
|
|
|
- CcTest::CollectGarbage(OLD_SPACE);
|
|
|
-+
|
|
|
- CHECK(WeakPointerCleared);
|
|
|
- }
|
|
|
-
|
|
|
-diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
|
|
|
-index 2118f34f1025125b746291af8830ddefd8b45c81..af2026ed86b43d35998e1ce0e760b1622af1a8b5 100644
|
|
|
---- a/test/cctest/test-api.cc
|
|
|
-+++ b/test/cctest/test-api.cc
|
|
|
-@@ -8089,6 +8089,18 @@ static void IndependentWeakHandle(bool global_gc, bool interlinked) {
|
|
|
- v8::WeakCallbackType::kParameter);
|
|
|
- object_b.handle.SetWeak(&object_b, &SetFlag,
|
|
|
- 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) {
|
|
|
- CcTest::CollectAllGarbage();
|
|
|
- } else {
|
|
|
-@@ -8239,6 +8251,19 @@ void v8::internal::heap::HeapTester::ResetWeakHandle(bool global_gc) {
|
|
|
- v8::WeakCallbackType::kParameter);
|
|
|
- object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
|
|
|
- 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) {
|
|
|
- CcTest::PreciseCollectAllGarbage();
|
|
|
- } else {
|
|
|
-@@ -8306,6 +8331,16 @@ THREADED_TEST(GCFromWeakCallbacks) {
|
|
|
- object.flag = false;
|
|
|
- object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
|
|
|
- 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]();
|
|
|
- EmptyMessageQueues(isolate);
|
|
|
- CHECK(object.flag);
|
|
|
-diff --git a/test/cctest/test-global-handles.cc b/test/cctest/test-global-handles.cc
|
|
|
-index 3cf57b04b2fc9bfa2450d06954b179707527d68d..f2b9bb4cc5fe5f3ce62db3577e63c9ab7ed51609 100644
|
|
|
---- a/test/cctest/test-global-handles.cc
|
|
|
-+++ b/test/cctest/test-global-handles.cc
|
|
|
-@@ -39,25 +39,6 @@ namespace internal {
|
|
|
-
|
|
|
- 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 InvokeMarkSweep() { CcTest::CollectAllGarbage(); }
|
|
|
-@@ -66,23 +47,23 @@ void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
|
|
- info.GetReturnValue().Set(v8_num(0));
|
|
|
- }
|
|
|
-
|
|
|
--struct FlagAndGlobal {
|
|
|
-+struct FlagAndPersistent {
|
|
|
- bool flag;
|
|
|
- v8::Global<v8::Object> handle;
|
|
|
- };
|
|
|
-
|
|
|
--struct TracedGlobalWrapper {
|
|
|
-- v8::TracedGlobal<v8::Object> handle;
|
|
|
--};
|
|
|
--
|
|
|
--void ResetHandleAndSetFlag(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
|
|
-+void ResetHandleAndSetFlag(
|
|
|
-+ const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
|
|
- data.GetParameter()->handle.Reset();
|
|
|
- data.GetParameter()->flag = true;
|
|
|
- }
|
|
|
-
|
|
|
--template <typename HandleContainer>
|
|
|
-+using ConstructFunction = void (*)(v8::Isolate* isolate,
|
|
|
-+ v8::Local<v8::Context> context,
|
|
|
-+ FlagAndPersistent* flag_and_persistent);
|
|
|
-+
|
|
|
- void ConstructJSObject(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
|
|
-- HandleContainer* flag_and_persistent) {
|
|
|
-+ FlagAndPersistent* flag_and_persistent) {
|
|
|
- v8::HandleScope handle_scope(isolate);
|
|
|
- v8::Local<v8::Object> object(v8::Object::New(isolate));
|
|
|
- CHECK(!object.IsEmpty());
|
|
|
-@@ -98,9 +79,8 @@ void ConstructJSObject(v8::Isolate* isolate, v8::Global<v8::Object>* global) {
|
|
|
- CHECK(!global->IsEmpty());
|
|
|
- }
|
|
|
-
|
|
|
--template <typename HandleContainer>
|
|
|
- void ConstructJSApiObject(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
|
|
-- HandleContainer* flag_and_persistent) {
|
|
|
-+ FlagAndPersistent* flag_and_persistent) {
|
|
|
- v8::HandleScope handle_scope(isolate);
|
|
|
- v8::Local<v8::FunctionTemplate> fun =
|
|
|
- v8::FunctionTemplate::New(isolate, SimpleCallback);
|
|
|
-@@ -115,8 +95,7 @@ void ConstructJSApiObject(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
|
|
-
|
|
|
- enum class SurvivalMode { kSurvives, kDies };
|
|
|
-
|
|
|
--template <typename ConstructFunction, typename ModifierFunction,
|
|
|
-- typename GCFunction>
|
|
|
-+template <typename ModifierFunction, typename GCFunction>
|
|
|
- void WeakHandleTest(v8::Isolate* isolate, ConstructFunction construct_function,
|
|
|
- ModifierFunction modifier_function, GCFunction gc_function,
|
|
|
- SurvivalMode survives) {
|
|
|
-@@ -124,7 +103,7 @@ void WeakHandleTest(v8::Isolate* isolate, ConstructFunction construct_function,
|
|
|
- v8::Local<v8::Context> context = v8::Context::New(isolate);
|
|
|
- v8::Context::Scope context_scope(context);
|
|
|
-
|
|
|
-- FlagAndGlobal fp;
|
|
|
-+ FlagAndPersistent fp;
|
|
|
- construct_function(isolate, context, &fp);
|
|
|
- CHECK(heap::InYoungGeneration(isolate, fp.handle));
|
|
|
- fp.handle.SetWeak(&fp, &ResetHandleAndSetFlag,
|
|
|
-@@ -136,28 +115,6 @@ void WeakHandleTest(v8::Isolate* isolate, ConstructFunction construct_function,
|
|
|
- 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(
|
|
|
- const v8::WeakCallbackInfo<v8::Global<v8::Object>>& data) {
|
|
|
- data.GetParameter()->ClearWeak();
|
|
|
-@@ -320,36 +277,25 @@ TEST(PhatomHandlesWithoutCallbacks) {
|
|
|
- CHECK_EQ(0u, isolate->NumberOfPhantomHandleResetsSinceLastCall());
|
|
|
- }
|
|
|
-
|
|
|
--TEST(WeakHandleToUnmodifiedJSObjectDiesOnScavenge) {
|
|
|
-+TEST(WeakHandleToUnmodifiedJSObjectSurvivesScavenge) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- WeakHandleTest(
|
|
|
-- CcTest::isolate(), &ConstructJSObject<FlagAndGlobal>,
|
|
|
-- [](FlagAndGlobal* fp) {}, []() { InvokeScavenge(); },
|
|
|
-- SurvivalMode::kDies);
|
|
|
--}
|
|
|
--
|
|
|
--TEST(TracedGlobalToUnmodifiedJSObjectSurvivesScavenge) {
|
|
|
-- ManualGCScope manual_gc;
|
|
|
-- CcTest::InitializeVM();
|
|
|
-- TracedGlobalTest(
|
|
|
-- CcTest::isolate(), &ConstructJSObject<TracedGlobalWrapper>,
|
|
|
-- [](TracedGlobalWrapper* fp) {}, []() { InvokeScavenge(); },
|
|
|
-- SurvivalMode::kSurvives);
|
|
|
-+ CcTest::isolate(), &ConstructJSObject, [](FlagAndPersistent* fp) {},
|
|
|
-+ []() { InvokeScavenge(); }, SurvivalMode::kSurvives);
|
|
|
- }
|
|
|
-
|
|
|
- TEST(WeakHandleToUnmodifiedJSObjectDiesOnMarkCompact) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- WeakHandleTest(
|
|
|
-- CcTest::isolate(), &ConstructJSObject<FlagAndGlobal>,
|
|
|
-- [](FlagAndGlobal* fp) {}, []() { InvokeMarkSweep(); },
|
|
|
-- SurvivalMode::kDies);
|
|
|
-+ CcTest::isolate(), &ConstructJSObject, [](FlagAndPersistent* fp) {},
|
|
|
-+ []() { InvokeMarkSweep(); }, SurvivalMode::kDies);
|
|
|
- }
|
|
|
-
|
|
|
- TEST(WeakHandleToUnmodifiedJSObjectSurvivesMarkCompactWhenInHandle) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- WeakHandleTest(
|
|
|
-- CcTest::isolate(), &ConstructJSObject<FlagAndGlobal>,
|
|
|
-- [](FlagAndGlobal* fp) {
|
|
|
-+ CcTest::isolate(), &ConstructJSObject,
|
|
|
-+ [](FlagAndPersistent* fp) {
|
|
|
- v8::Local<v8::Object> handle =
|
|
|
- v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
|
|
- USE(handle);
|
|
|
-@@ -360,30 +306,19 @@ TEST(WeakHandleToUnmodifiedJSObjectSurvivesMarkCompactWhenInHandle) {
|
|
|
- TEST(WeakHandleToUnmodifiedJSApiObjectDiesOnScavenge) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- WeakHandleTest(
|
|
|
-- CcTest::isolate(), &ConstructJSApiObject<FlagAndGlobal>,
|
|
|
-- [](FlagAndGlobal* fp) {}, []() { InvokeScavenge(); },
|
|
|
-- SurvivalMode::kDies);
|
|
|
--}
|
|
|
--
|
|
|
--TEST(TracedGlobalToUnmodifiedJSApiObjectDiesOnScavenge) {
|
|
|
-- ManualGCScope manual_gc;
|
|
|
-- CcTest::InitializeVM();
|
|
|
-- TracedGlobalTest(
|
|
|
-- CcTest::isolate(), &ConstructJSApiObject<TracedGlobalWrapper>,
|
|
|
-- [](TracedGlobalWrapper* fp) {}, []() { InvokeScavenge(); },
|
|
|
-- SurvivalMode::kDies);
|
|
|
-+ CcTest::isolate(), &ConstructJSApiObject, [](FlagAndPersistent* fp) {},
|
|
|
-+ []() { InvokeScavenge(); }, SurvivalMode::kDies);
|
|
|
- }
|
|
|
-
|
|
|
--TEST(TracedGlobalToJSApiObjectWithIdentityHashSurvivesScavenge) {
|
|
|
-- ManualGCScope manual_gc;
|
|
|
-+TEST(WeakHandleToJSApiObjectWithIdentityHashSurvivesScavenge) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- Isolate* i_isolate = CcTest::i_isolate();
|
|
|
- HandleScope scope(i_isolate);
|
|
|
- Handle<JSWeakMap> weakmap = i_isolate->factory()->NewJSWeakMap();
|
|
|
-
|
|
|
-- TracedGlobalTest(
|
|
|
-- CcTest::isolate(), &ConstructJSApiObject<TracedGlobalWrapper>,
|
|
|
-- [&weakmap, i_isolate](TracedGlobalWrapper* fp) {
|
|
|
-+ WeakHandleTest(
|
|
|
-+ CcTest::isolate(), &ConstructJSApiObject,
|
|
|
-+ [&weakmap, i_isolate](FlagAndPersistent* fp) {
|
|
|
- v8::HandleScope scope(CcTest::isolate());
|
|
|
- Handle<JSReceiver> key =
|
|
|
- Utils::OpenHandle(*fp->handle.Get(CcTest::isolate()));
|
|
|
-@@ -397,8 +332,8 @@ TEST(TracedGlobalToJSApiObjectWithIdentityHashSurvivesScavenge) {
|
|
|
- TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesScavengeWhenInHandle) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- WeakHandleTest(
|
|
|
-- CcTest::isolate(), &ConstructJSApiObject<FlagAndGlobal>,
|
|
|
-- [](FlagAndGlobal* fp) {
|
|
|
-+ CcTest::isolate(), &ConstructJSApiObject,
|
|
|
-+ [](FlagAndPersistent* fp) {
|
|
|
- v8::Local<v8::Object> handle =
|
|
|
- v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
|
|
- USE(handle);
|
|
|
-@@ -409,16 +344,15 @@ TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesScavengeWhenInHandle) {
|
|
|
- TEST(WeakHandleToUnmodifiedJSApiObjectDiesOnMarkCompact) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- WeakHandleTest(
|
|
|
-- CcTest::isolate(), &ConstructJSApiObject<FlagAndGlobal>,
|
|
|
-- [](FlagAndGlobal* fp) {}, []() { InvokeMarkSweep(); },
|
|
|
-- SurvivalMode::kDies);
|
|
|
-+ CcTest::isolate(), &ConstructJSApiObject, [](FlagAndPersistent* fp) {},
|
|
|
-+ []() { InvokeMarkSweep(); }, SurvivalMode::kDies);
|
|
|
- }
|
|
|
-
|
|
|
- TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesMarkCompactWhenInHandle) {
|
|
|
- CcTest::InitializeVM();
|
|
|
- WeakHandleTest(
|
|
|
-- CcTest::isolate(), &ConstructJSApiObject<FlagAndGlobal>,
|
|
|
-- [](FlagAndGlobal* fp) {
|
|
|
-+ CcTest::isolate(), &ConstructJSApiObject,
|
|
|
-+ [](FlagAndPersistent* fp) {
|
|
|
- v8::Local<v8::Object> handle =
|
|
|
- v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
|
|
- USE(handle);
|
|
|
-@@ -426,57 +360,58 @@ TEST(WeakHandleToUnmodifiedJSApiObjectSurvivesMarkCompactWhenInHandle) {
|
|
|
- []() { InvokeMarkSweep(); }, SurvivalMode::kSurvives);
|
|
|
- }
|
|
|
-
|
|
|
--TEST(TracedGlobalToJSApiObjectWithModifiedMapSurvivesScavenge) {
|
|
|
-+TEST(WeakHandleToActiveUnmodifiedJSApiObjectSurvivesScavenge) {
|
|
|
- CcTest::InitializeVM();
|
|
|
-- v8::Isolate* isolate = CcTest::isolate();
|
|
|
-- LocalContext context;
|
|
|
--
|
|
|
-- TracedGlobal<v8::Object> handle;
|
|
|
-- {
|
|
|
-- v8::HandleScope scope(isolate);
|
|
|
-- // Create an API object which does not have the same map as constructor.
|
|
|
-- auto function_template = FunctionTemplate::New(isolate);
|
|
|
-- auto instance_t = function_template->InstanceTemplate();
|
|
|
-- instance_t->Set(
|
|
|
-- v8::String::NewFromUtf8(isolate, "a", NewStringType::kNormal)
|
|
|
-- .ToLocalChecked(),
|
|
|
-- 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());
|
|
|
-+ WeakHandleTest(
|
|
|
-+ CcTest::isolate(), &ConstructJSApiObject,
|
|
|
-+ [](FlagAndPersistent* fp) {
|
|
|
-+#if __clang__
|
|
|
-+#pragma clang diagnostic push
|
|
|
-+#pragma clang diagnostic ignored "-Wdeprecated"
|
|
|
-+#endif
|
|
|
-+ fp->handle.MarkActive();
|
|
|
-+#if __clang__
|
|
|
-+#pragma clang diagnostic pop
|
|
|
-+#endif
|
|
|
-+ },
|
|
|
-+ []() { InvokeScavenge(); }, SurvivalMode::kSurvives);
|
|
|
- }
|
|
|
-
|
|
|
--TEST(TracedGlobalTOJsApiObjectWithElementsSurvivesScavenge) {
|
|
|
-+TEST(WeakHandleToActiveUnmodifiedJSApiObjectDiesOnMarkCompact) {
|
|
|
- CcTest::InitializeVM();
|
|
|
-- v8::Isolate* isolate = CcTest::isolate();
|
|
|
-- LocalContext context;
|
|
|
--
|
|
|
-- TracedGlobal<v8::Object> handle;
|
|
|
-- {
|
|
|
-- v8::HandleScope scope(isolate);
|
|
|
-+ WeakHandleTest(
|
|
|
-+ CcTest::isolate(), &ConstructJSApiObject,
|
|
|
-+ [](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);
|
|
|
-+}
|
|
|
-
|
|
|
-- // Create an API object which has elements.
|
|
|
-- auto function_template = FunctionTemplate::New(isolate);
|
|
|
-- auto instance_t = function_template->InstanceTemplate();
|
|
|
-- instance_t->Set(
|
|
|
-- v8::String::NewFromUtf8(isolate, "1", NewStringType::kNormal)
|
|
|
-- .ToLocalChecked(),
|
|
|
-- v8::Number::New(isolate, 10));
|
|
|
-- instance_t->Set(
|
|
|
-- v8::String::NewFromUtf8(isolate, "2", NewStringType::kNormal)
|
|
|
-- .ToLocalChecked(),
|
|
|
-- 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(WeakHandleToActiveUnmodifiedJSApiObjectSurvivesMarkCompactWhenInHandle) {
|
|
|
-+ CcTest::InitializeVM();
|
|
|
-+ WeakHandleTest(
|
|
|
-+ CcTest::isolate(), &ConstructJSApiObject,
|
|
|
-+ [](FlagAndPersistent* fp) {
|
|
|
-+#if __clang__
|
|
|
-+#pragma clang diagnostic push
|
|
|
-+#pragma clang diagnostic ignored "-Wdeprecated"
|
|
|
-+#endif
|
|
|
-+ fp->handle.MarkActive();
|
|
|
-+#if __clang__
|
|
|
-+#pragma clang diagnostic pop
|
|
|
-+#endif
|
|
|
-+ v8::Local<v8::Object> handle =
|
|
|
-+ v8::Local<v8::Object>::New(CcTest::isolate(), fp->handle);
|
|
|
-+ USE(handle);
|
|
|
-+ },
|
|
|
-+ []() { InvokeMarkSweep(); }, SurvivalMode::kSurvives);
|
|
|
- }
|
|
|
-
|
|
|
- TEST(FinalizerOnUnmodifiedJSApiObjectDoesNotCrash) {
|
|
|
-@@ -487,7 +422,8 @@ TEST(FinalizerOnUnmodifiedJSApiObjectDoesNotCrash) {
|
|
|
- v8::Local<v8::Context> context = v8::Context::New(isolate);
|
|
|
- v8::Context::Scope context_scope(context);
|
|
|
-
|
|
|
-- FlagAndGlobal fp;
|
|
|
-+ FlagAndPersistent fp;
|
|
|
-+ // Could use a regular object and MarkIndependent too.
|
|
|
- ConstructJSApiObject(isolate, context, &fp);
|
|
|
- fp.handle.SetWeak(&fp, &ResetHandleAndSetFlag,
|
|
|
- v8::WeakCallbackType::kFinalizer);
|
|
|
-@@ -559,22 +495,22 @@ TEST(FinalizerDiesAndKeepsPhantomAliveOnMarkCompact) {
|
|
|
-
|
|
|
- namespace {
|
|
|
-
|
|
|
--void ForceScavenge2(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
|
|
-+void ForceScavenge2(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
|
|
- data.GetParameter()->flag = true;
|
|
|
- InvokeScavenge();
|
|
|
- }
|
|
|
-
|
|
|
--void ForceScavenge1(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
|
|
-+void ForceScavenge1(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
|
|
- data.GetParameter()->handle.Reset();
|
|
|
- data.SetSecondPassCallback(ForceScavenge2);
|
|
|
- }
|
|
|
-
|
|
|
--void ForceMarkSweep2(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
|
|
-+void ForceMarkSweep2(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
|
|
- data.GetParameter()->flag = true;
|
|
|
- InvokeMarkSweep();
|
|
|
- }
|
|
|
-
|
|
|
--void ForceMarkSweep1(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
|
|
-+void ForceMarkSweep1(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
|
|
- data.GetParameter()->handle.Reset();
|
|
|
- data.SetSecondPassCallback(ForceMarkSweep2);
|
|
|
- }
|
|
|
-@@ -589,7 +525,7 @@ TEST(GCFromWeakCallbacks) {
|
|
|
- v8::Context::Scope context_scope(context);
|
|
|
-
|
|
|
- static const int kNumberOfGCTypes = 2;
|
|
|
-- typedef v8::WeakCallbackInfo<FlagAndGlobal>::Callback Callback;
|
|
|
-+ typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
|
|
|
- Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
|
|
|
- &ForceMarkSweep1};
|
|
|
-
|
|
|
-@@ -598,7 +534,7 @@ TEST(GCFromWeakCallbacks) {
|
|
|
-
|
|
|
- for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
|
|
|
- for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
|
|
|
-- FlagAndGlobal fp;
|
|
|
-+ FlagAndPersistent fp;
|
|
|
- ConstructJSApiObject(isolate, context, &fp);
|
|
|
- CHECK(heap::InYoungGeneration(isolate, fp.handle));
|
|
|
- fp.flag = false;
|
|
|
-@@ -613,11 +549,11 @@ TEST(GCFromWeakCallbacks) {
|
|
|
-
|
|
|
- namespace {
|
|
|
-
|
|
|
--void SecondPassCallback(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
|
|
-+void SecondPassCallback(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
|
|
- data.GetParameter()->flag = true;
|
|
|
- }
|
|
|
-
|
|
|
--void FirstPassCallback(const v8::WeakCallbackInfo<FlagAndGlobal>& data) {
|
|
|
-+void FirstPassCallback(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
|
|
|
- data.GetParameter()->handle.Reset();
|
|
|
- data.SetSecondPassCallback(SecondPassCallback);
|
|
|
- }
|
|
|
-@@ -630,7 +566,7 @@ TEST(SecondPassPhantomCallbacks) {
|
|
|
- v8::HandleScope scope(isolate);
|
|
|
- v8::Local<v8::Context> context = v8::Context::New(isolate);
|
|
|
- v8::Context::Scope context_scope(context);
|
|
|
-- FlagAndGlobal fp;
|
|
|
-+ FlagAndPersistent fp;
|
|
|
- ConstructJSApiObject(isolate, context, &fp);
|
|
|
- fp.flag = false;
|
|
|
- fp.handle.SetWeak(&fp, FirstPassCallback, v8::WeakCallbackType::kParameter);
|