Index: test/cctest/test-api.cc |
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
index da594881bf5c19284b62a96fb5b201a55060aa3e..fc74a42d1e2d99d4637570a3b2be706808c4ac24 100644 |
--- a/test/cctest/test-api.cc |
+++ b/test/cctest/test-api.cc |
@@ -7487,14 +7487,13 @@ struct FlagAndPersistent { |
}; |
-static void DisposeAndSetFlag( |
+static void SetFlag( |
const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) { |
- data.GetParameter()->handle.Reset(); |
data.GetParameter()->flag = true; |
} |
-THREADED_TEST(IndependentWeakHandle) { |
+static void IndependentWeakHandle(bool global_gc, bool interlinked) { |
v8::Isolate* iso = CcTest::isolate(); |
v8::HandleScope scope(iso); |
v8::Handle<Context> context = Context::New(iso); |
@@ -7502,26 +7501,115 @@ THREADED_TEST(IndependentWeakHandle) { |
FlagAndPersistent object_a, object_b; |
+ intptr_t big_heap_size; |
+ |
{ |
v8::HandleScope handle_scope(iso); |
- object_a.handle.Reset(iso, v8::Object::New(iso)); |
- object_b.handle.Reset(iso, v8::Object::New(iso)); |
+ Local<Object> a(v8::Object::New(iso)); |
+ Local<Object> b(v8::Object::New(iso)); |
+ object_a.handle.Reset(iso, a); |
+ object_b.handle.Reset(iso, b); |
+ if (interlinked) { |
+ a->Set(v8_str("x"), b); |
+ b->Set(v8_str("x"), a); |
+ } |
+ if (global_gc) { |
+ CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags); |
+ } else { |
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
+ } |
+ // We are relying on this creating a big flag array and reserving the space |
+ // up front. |
+ v8::Handle<Value> big_array = CompileRun("new Array(50000)"); |
+ a->Set(v8_str("y"), big_array); |
+ big_heap_size = CcTest::heap()->SizeOfObjects(); |
} |
object_a.flag = false; |
object_b.flag = false; |
- object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag); |
- object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag); |
+ object_a.handle.SetPhantom(&object_a, &SetFlag); |
+ object_b.handle.SetPhantom(&object_b, &SetFlag); |
CHECK(!object_b.handle.IsIndependent()); |
object_a.handle.MarkIndependent(); |
object_b.handle.MarkIndependent(); |
CHECK(object_b.handle.IsIndependent()); |
- CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
+ if (global_gc) { |
+ CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags); |
+ } else { |
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
+ } |
+ // A single GC should be enough to reclaim the memory, since we are using |
+ // phantom handles. |
+ CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 200000); |
+ CHECK(object_a.flag); |
+ CHECK(object_b.flag); |
+} |
+ |
+ |
+THREADED_TEST(IndependentWeakHandle) { |
+ IndependentWeakHandle(false, false); |
+ IndependentWeakHandle(false, true); |
+ IndependentWeakHandle(true, false); |
+ IndependentWeakHandle(true, true); |
+} |
+ |
+ |
+static void ResetUseValueAndSetFlag( |
+ const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) { |
+ // Blink will reset the handle, and then use the other handle, so they |
+ // can't use the same backing slot. |
+ data.GetParameter()->handle.Reset(); |
+ data.GetValue()->IsBoolean(); // Make sure the handle still works. |
+ data.GetParameter()->flag = true; |
+} |
+ |
+ |
+static void ResetWeakHandle(bool global_gc) { |
+ v8::Isolate* iso = CcTest::isolate(); |
+ v8::HandleScope scope(iso); |
+ v8::Handle<Context> context = Context::New(iso); |
+ Context::Scope context_scope(context); |
+ |
+ FlagAndPersistent object_a, object_b; |
+ |
+ { |
+ v8::HandleScope handle_scope(iso); |
+ Local<Object> a(v8::Object::New(iso)); |
+ Local<Object> b(v8::Object::New(iso)); |
+ object_a.handle.Reset(iso, a); |
+ object_b.handle.Reset(iso, b); |
+ if (global_gc) { |
+ CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags); |
+ } else { |
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
+ } |
+ } |
+ |
+ object_a.flag = false; |
+ object_b.flag = false; |
+ object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag); |
+ object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag); |
+ if (!global_gc) { |
+ object_a.handle.MarkIndependent(); |
+ object_b.handle.MarkIndependent(); |
+ CHECK(object_b.handle.IsIndependent()); |
+ } |
+ if (global_gc) { |
+ CcTest::heap()->CollectAllGarbage(TestHeap::Heap::kNoGCFlags); |
+ } else { |
+ CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
+ } |
CHECK(object_a.flag); |
CHECK(object_b.flag); |
} |
+THREADED_TEST(ResetWeakHandle) { |
+ ResetWeakHandle(false); |
+ ResetWeakHandle(true); |
+} |
+ |
+ |
static void InvokeScavenge() { |
CcTest::heap()->CollectGarbage(i::NEW_SPACE); |
} |