[api] Mark functions related to object grouping as DEPRECATE_SOON

Embedders should use the EmbedderHeapTracer API.

BUG=v8:5828

Review-Url: https://codereview.chromium.org/2628893003
Cr-Commit-Position: refs/heads/master@{#42269}
This commit is contained in:
mlippautz 2017-01-12 06:02:21 -08:00 committed by Commit bot
parent 9cd0de73dc
commit e00eae9e89
4 changed files with 12 additions and 455 deletions

View File

@ -6779,8 +6779,10 @@ class V8_EXPORT Isolate {
* garbage collection types it is sufficient to provide object groups
* for partially dependent handles only.
*/
template<typename T> void SetObjectGroupId(const Persistent<T>& object,
UniqueId id);
template <typename T>
V8_DEPRECATE_SOON("Use EmbedderHeapTracer",
void SetObjectGroupId(const Persistent<T>& object,
UniqueId id));
/**
* Allows the host application to declare implicit references from an object
@ -6789,8 +6791,10 @@ class V8_EXPORT Isolate {
* are removed. It is intended to be used in the before-garbage-collection
* callback function.
*/
template<typename T> void SetReferenceFromGroup(UniqueId id,
const Persistent<T>& child);
template <typename T>
V8_DEPRECATE_SOON("Use EmbedderHeapTracer",
void SetReferenceFromGroup(UniqueId id,
const Persistent<T>& child));
/**
* Allows the host application to declare implicit references from an object
@ -6798,8 +6802,10 @@ class V8_EXPORT Isolate {
* too. After each garbage collection, all implicit references are removed. It
* is intended to be used in the before-garbage-collection callback function.
*/
template<typename T, typename S>
void SetReference(const Persistent<T>& parent, const Persistent<S>& child);
template <typename T, typename S>
V8_DEPRECATE_SOON("Use EmbedderHeapTracer",
void SetReference(const Persistent<T>& parent,
const Persistent<S>& child));
typedef void (*GCCallback)(Isolate* isolate, GCType type,
GCCallbackFlags flags);

View File

@ -6200,44 +6200,6 @@ TEST(SharedFunctionInfoIterator) {
CHECK_EQ(0, sfi_count);
}
template <typename T>
static UniqueId MakeUniqueId(const Persistent<T>& p) {
return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
}
TEST(Regress519319) {
if (!FLAG_incremental_marking) return;
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
Heap* heap = CcTest::heap();
LocalContext context;
v8::Persistent<Value> parent;
v8::Persistent<Value> child;
parent.Reset(isolate, v8::Object::New(isolate));
child.Reset(isolate, v8::Object::New(isolate));
heap::SimulateFullSpace(heap->old_space());
CcTest::CollectGarbage(OLD_SPACE);
{
UniqueId id = MakeUniqueId(parent);
isolate->SetObjectGroupId(parent, id);
isolate->SetReferenceFromGroup(id, child);
}
// The CollectGarbage call above starts sweeper threads.
// The crash will happen if the following two functions
// are called before sweeping finishes.
heap->StartIncrementalMarking(i::Heap::kNoGCFlags,
i::GarbageCollectionReason::kTesting);
heap->FinalizeIncrementalMarkingIfComplete(
i::GarbageCollectionReason::kTesting);
}
HEAP_TEST(Regress587004) {
FLAG_concurrent_sweeping = false;
#ifdef VERIFY_HEAP

View File

@ -4483,335 +4483,6 @@ static void WeakPointerCallback(
data.GetParameter()->handle.Reset();
}
template <typename T>
static UniqueId MakeUniqueId(const Persistent<T>& p) {
return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
}
THREADED_TEST(ApiObjectGroups) {
LocalContext env;
v8::Isolate* iso = env->GetIsolate();
HandleScope scope(iso);
WeakCallCounter counter(1234);
WeakCallCounterAndPersistent<Value> g1s1(&counter);
WeakCallCounterAndPersistent<Value> g1s2(&counter);
WeakCallCounterAndPersistent<Value> g1c1(&counter);
WeakCallCounterAndPersistent<Value> g2s1(&counter);
WeakCallCounterAndPersistent<Value> g2s2(&counter);
WeakCallCounterAndPersistent<Value> g2c1(&counter);
{
HandleScope scope(iso);
g1s1.handle.Reset(iso, Object::New(iso));
g1s2.handle.Reset(iso, Object::New(iso));
g1c1.handle.Reset(iso, Object::New(iso));
g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2s1.handle.Reset(iso, Object::New(iso));
g2s2.handle.Reset(iso, Object::New(iso));
g2c1.handle.Reset(iso, Object::New(iso));
g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
}
WeakCallCounterAndPersistent<Value> root(&counter);
root.handle.Reset(iso, g1s1.handle); // make a root.
// Connect group 1 and 2, make a cycle.
{
HandleScope scope(iso);
CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle))
.FromJust());
CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle))
.FromJust());
}
{
UniqueId id1 = MakeUniqueId(g1s1.handle);
UniqueId id2 = MakeUniqueId(g2s2.handle);
iso->SetObjectGroupId(g1s1.handle, id1);
iso->SetObjectGroupId(g1s2.handle, id1);
iso->SetReferenceFromGroup(id1, g1c1.handle);
iso->SetObjectGroupId(g2s1.handle, id2);
iso->SetObjectGroupId(g2s2.handle, id2);
iso->SetReferenceFromGroup(id2, g2c1.handle);
}
// Do a single full GC, ensure incremental marking is stopped.
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
// All object should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
// Weaken the root.
root.handle.SetWeak(&root, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
// But make children strong roots---all the objects (except for children)
// should be collectable now.
g1c1.handle.ClearWeak();
g2c1.handle.ClearWeak();
// Groups are deleted, rebuild groups.
{
UniqueId id1 = MakeUniqueId(g1s1.handle);
UniqueId id2 = MakeUniqueId(g2s2.handle);
iso->SetObjectGroupId(g1s1.handle, id1);
iso->SetObjectGroupId(g1s2.handle, id1);
iso->SetReferenceFromGroup(id1, g1c1.handle);
iso->SetObjectGroupId(g2s1.handle, id2);
iso->SetObjectGroupId(g2s2.handle, id2);
iso->SetReferenceFromGroup(id2, g2c1.handle);
}
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
// All objects should be gone. 5 global handles in total.
CHECK_EQ(5, counter.NumberOfWeakCalls());
// And now make children weak again and collect them.
g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
CHECK_EQ(7, counter.NumberOfWeakCalls());
}
THREADED_TEST(ApiObjectGroupsForSubtypes) {
LocalContext env;
v8::Isolate* iso = env->GetIsolate();
HandleScope scope(iso);
WeakCallCounter counter(1234);
WeakCallCounterAndPersistent<Object> g1s1(&counter);
WeakCallCounterAndPersistent<String> g1s2(&counter);
WeakCallCounterAndPersistent<String> g1c1(&counter);
WeakCallCounterAndPersistent<Object> g2s1(&counter);
WeakCallCounterAndPersistent<String> g2s2(&counter);
WeakCallCounterAndPersistent<String> g2c1(&counter);
{
HandleScope scope(iso);
g1s1.handle.Reset(iso, Object::New(iso));
g1s2.handle.Reset(iso, v8_str("foo1"));
g1c1.handle.Reset(iso, v8_str("foo2"));
g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2s1.handle.Reset(iso, Object::New(iso));
g2s2.handle.Reset(iso, v8_str("foo3"));
g2c1.handle.Reset(iso, v8_str("foo4"));
g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
}
WeakCallCounterAndPersistent<Value> root(&counter);
root.handle.Reset(iso, g1s1.handle); // make a root.
// Connect group 1 and 2, make a cycle.
{
HandleScope scope(iso);
CHECK(Local<Object>::New(iso, g1s1.handle)
->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle))
.FromJust());
CHECK(Local<Object>::New(iso, g2s1.handle)
->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle))
.FromJust());
}
{
UniqueId id1 = MakeUniqueId(g1s1.handle);
UniqueId id2 = MakeUniqueId(g2s2.handle);
iso->SetObjectGroupId(g1s1.handle, id1);
iso->SetObjectGroupId(g1s2.handle, id1);
iso->SetReference(g1s1.handle, g1c1.handle);
iso->SetObjectGroupId(g2s1.handle, id2);
iso->SetObjectGroupId(g2s2.handle, id2);
iso->SetReferenceFromGroup(id2, g2c1.handle);
}
// Do a single full GC, ensure incremental marking is stopped.
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
// All object should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
// Weaken the root.
root.handle.SetWeak(&root, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
// But make children strong roots---all the objects (except for children)
// should be collectable now.
g1c1.handle.ClearWeak();
g2c1.handle.ClearWeak();
// Groups are deleted, rebuild groups.
{
UniqueId id1 = MakeUniqueId(g1s1.handle);
UniqueId id2 = MakeUniqueId(g2s2.handle);
iso->SetObjectGroupId(g1s1.handle, id1);
iso->SetObjectGroupId(g1s2.handle, id1);
iso->SetReference(g1s1.handle, g1c1.handle);
iso->SetObjectGroupId(g2s1.handle, id2);
iso->SetObjectGroupId(g2s2.handle, id2);
iso->SetReferenceFromGroup(id2, g2c1.handle);
}
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
// All objects should be gone. 5 global handles in total.
CHECK_EQ(5, counter.NumberOfWeakCalls());
// And now make children weak again and collect them.
g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
CHECK_EQ(7, counter.NumberOfWeakCalls());
}
THREADED_TEST(ApiObjectGroupsCycle) {
LocalContext env;
v8::Isolate* iso = env->GetIsolate();
HandleScope scope(iso);
WeakCallCounter counter(1234);
WeakCallCounterAndPersistent<Value> g1s1(&counter);
WeakCallCounterAndPersistent<Value> g1s2(&counter);
WeakCallCounterAndPersistent<Value> g2s1(&counter);
WeakCallCounterAndPersistent<Value> g2s2(&counter);
WeakCallCounterAndPersistent<Value> g3s1(&counter);
WeakCallCounterAndPersistent<Value> g3s2(&counter);
WeakCallCounterAndPersistent<Value> g4s1(&counter);
WeakCallCounterAndPersistent<Value> g4s2(&counter);
{
HandleScope scope(iso);
g1s1.handle.Reset(iso, Object::New(iso));
g1s2.handle.Reset(iso, Object::New(iso));
g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
CHECK(g1s1.handle.IsWeak());
CHECK(g1s2.handle.IsWeak());
g2s1.handle.Reset(iso, Object::New(iso));
g2s2.handle.Reset(iso, Object::New(iso));
g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
CHECK(g2s1.handle.IsWeak());
CHECK(g2s2.handle.IsWeak());
g3s1.handle.Reset(iso, Object::New(iso));
g3s2.handle.Reset(iso, Object::New(iso));
g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
CHECK(g3s1.handle.IsWeak());
CHECK(g3s2.handle.IsWeak());
g4s1.handle.Reset(iso, Object::New(iso));
g4s2.handle.Reset(iso, Object::New(iso));
g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
CHECK(g4s1.handle.IsWeak());
CHECK(g4s2.handle.IsWeak());
}
WeakCallCounterAndPersistent<Value> root(&counter);
root.handle.Reset(iso, g1s1.handle); // make a root.
// Connect groups. We're building the following cycle:
// G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
// groups.
{
UniqueId id1 = MakeUniqueId(g1s1.handle);
UniqueId id2 = MakeUniqueId(g2s1.handle);
UniqueId id3 = MakeUniqueId(g3s1.handle);
UniqueId id4 = MakeUniqueId(g4s1.handle);
iso->SetObjectGroupId(g1s1.handle, id1);
iso->SetObjectGroupId(g1s2.handle, id1);
iso->SetReferenceFromGroup(id1, g2s1.handle);
iso->SetObjectGroupId(g2s1.handle, id2);
iso->SetObjectGroupId(g2s2.handle, id2);
iso->SetReferenceFromGroup(id2, g3s1.handle);
iso->SetObjectGroupId(g3s1.handle, id3);
iso->SetObjectGroupId(g3s2.handle, id3);
iso->SetReferenceFromGroup(id3, g4s1.handle);
iso->SetObjectGroupId(g4s1.handle, id4);
iso->SetObjectGroupId(g4s2.handle, id4);
iso->SetReferenceFromGroup(id4, g1s1.handle);
}
// Do a single full GC
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
// All object should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
// Weaken the root.
root.handle.SetWeak(&root, &WeakPointerCallback,
v8::WeakCallbackType::kParameter);
// Groups are deleted, rebuild groups.
{
UniqueId id1 = MakeUniqueId(g1s1.handle);
UniqueId id2 = MakeUniqueId(g2s1.handle);
UniqueId id3 = MakeUniqueId(g3s1.handle);
UniqueId id4 = MakeUniqueId(g4s1.handle);
iso->SetObjectGroupId(g1s1.handle, id1);
iso->SetObjectGroupId(g1s2.handle, id1);
iso->SetReferenceFromGroup(id1, g2s1.handle);
iso->SetObjectGroupId(g2s1.handle, id2);
iso->SetObjectGroupId(g2s2.handle, id2);
iso->SetReferenceFromGroup(id2, g3s1.handle);
iso->SetObjectGroupId(g3s1.handle, id3);
iso->SetObjectGroupId(g3s2.handle, id3);
iso->SetReferenceFromGroup(id3, g4s1.handle);
iso->SetObjectGroupId(g4s1.handle, id4);
iso->SetObjectGroupId(g4s2.handle, id4);
iso->SetReferenceFromGroup(id4, g1s1.handle);
}
CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask);
// All objects should be gone. 9 global handles in total.
CHECK_EQ(9, counter.NumberOfWeakCalls());
}
THREADED_TEST(ScriptException) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());

View File

@ -1570,88 +1570,6 @@ TEST(HeapSnapshotRetainedObjectInfo) {
CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "native"));
}
class GraphWithImplicitRefs {
public:
static const int kObjectsCount = 4;
explicit GraphWithImplicitRefs(LocalContext* env) {
CHECK(!instance_);
instance_ = this;
isolate_ = (*env)->GetIsolate();
for (int i = 0; i < kObjectsCount; i++) {
objects_[i].Reset(isolate_, v8::Object::New(isolate_));
}
(*env)
->Global()
->Set(isolate_->GetCurrentContext(), v8_str("root_object"),
v8::Local<v8::Value>::New(isolate_, objects_[0]))
.FromJust();
}
~GraphWithImplicitRefs() {
instance_ = NULL;
}
static void gcPrologue(v8::Isolate* isolate, v8::GCType type,
v8::GCCallbackFlags flags) {
instance_->AddImplicitReferences();
}
private:
void AddImplicitReferences() {
// 0 -> 1
isolate_->SetObjectGroupId(objects_[0],
v8::UniqueId(1));
isolate_->SetReferenceFromGroup(
v8::UniqueId(1), objects_[1]);
// Adding two more references: 1 -> 2, 1 -> 3
isolate_->SetReference(objects_[1].As<v8::Object>(),
objects_[2]);
isolate_->SetReference(objects_[1].As<v8::Object>(),
objects_[3]);
}
v8::Persistent<v8::Value> objects_[kObjectsCount];
static GraphWithImplicitRefs* instance_;
v8::Isolate* isolate_;
};
GraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL;
TEST(HeapSnapshotImplicitReferences) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
GraphWithImplicitRefs graph(&env);
env->GetIsolate()->AddGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue);
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
CHECK(ValidateSnapshot(snapshot));
const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot);
const v8::HeapGraphNode* obj0 = GetProperty(
global_object, v8::HeapGraphEdge::kProperty, "root_object");
CHECK(obj0);
CHECK_EQ(v8::HeapGraphNode::kObject, obj0->GetType());
const v8::HeapGraphNode* obj1 = GetProperty(
obj0, v8::HeapGraphEdge::kInternal, "native");
CHECK(obj1);
int implicit_targets_count = 0;
for (int i = 0, count = obj1->GetChildrenCount(); i < count; ++i) {
const v8::HeapGraphEdge* prop = obj1->GetChild(i);
v8::String::Utf8Value prop_name(prop->GetName());
if (prop->GetType() == v8::HeapGraphEdge::kInternal &&
strcmp("native", *prop_name) == 0) {
++implicit_targets_count;
}
}
CHECK_EQ(2, implicit_targets_count);
env->GetIsolate()->RemoveGCPrologueCallback(
&GraphWithImplicitRefs::gcPrologue);
}
TEST(DeleteAllHeapSnapshots) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());