Commit 49954eb5 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

Revert "[api,heap] Remove deprecated Persistent APIs"

This reverts commit 1ebf5f72.

Reason for revert: Breaks TSAN

Original change's description:
> [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.
> 
> Bug: chromium:923361
> Change-Id: Ic90a647fe2ce9db92197ad6560e4907290805592
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1578459
> Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#60953}

TBR=ulan@chromium.org,mlippautz@chromium.org

Change-Id: I8281daf30b67c1b71ef6e65d8f13a59230ba0334
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:923361
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1578900Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60954}
parent 1ebf5f72
......@@ -165,6 +165,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;
......
......@@ -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:
......
......@@ -545,6 +545,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;
......@@ -8807,6 +8839,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;
......@@ -9753,6 +9788,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;
......@@ -9819,6 +9862,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;
......
......@@ -1037,6 +1037,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) {
......
......@@ -379,6 +379,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);
}
......@@ -402,6 +406,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); }
......@@ -548,6 +562,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.
......@@ -578,17 +593,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> {};
......@@ -851,6 +873,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_) {
......@@ -867,7 +895,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());
}
......@@ -883,7 +913,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();
}
......@@ -895,7 +926,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.
......@@ -909,7 +941,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()) {
......@@ -975,6 +1008,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());
......@@ -993,6 +1029,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());
......
......@@ -97,6 +97,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));
}
......
......@@ -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);
......
......@@ -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());
}
......
......@@ -500,6 +500,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();
......@@ -538,6 +576,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();
......@@ -587,7 +703,9 @@ TEST(DeleteWeakGlobalHandle) {
GlobalHandles* global_handles = isolate->global_handles();
WeakPointerCleared = false;
Handle<Object> h;
{
HandleScope scope(isolate);
......@@ -599,8 +717,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);
}
......
......@@ -7956,6 +7956,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 {
......@@ -8106,6 +8118,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 {
......@@ -8173,6 +8198,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);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment