Index: test/cctest/test-api.cc |
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
index a4dcc545b64f6a2874a8099c0843c273d5040592..0fb12af930b0483791cfb1c274939b1e57db5ac5 100644 |
--- a/test/cctest/test-api.cc |
+++ b/test/cctest/test-api.cc |
@@ -2543,6 +2543,97 @@ THREADED_TEST(ApiObjectGroupsCycle) { |
} |
+THREADED_TEST(ApiObjectGroupsCycleForScavenger) { |
+ HandleScope scope; |
+ LocalContext env; |
+ |
+ WeakCallCounter counter(1234); |
+ |
+ Persistent<Object> g1s1; |
+ Persistent<Object> g1s2; |
+ Persistent<Object> g2s1; |
+ Persistent<Object> g2s2; |
+ Persistent<Object> g3s1; |
+ Persistent<Object> g3s2; |
+ |
+ { |
+ HandleScope scope; |
+ g1s1 = Persistent<Object>::New(Object::New()); |
+ g1s2 = Persistent<Object>::New(Object::New()); |
+ g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
+ g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
+ |
+ g2s1 = Persistent<Object>::New(Object::New()); |
+ g2s2 = Persistent<Object>::New(Object::New()); |
+ g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
+ g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
+ |
+ g3s1 = Persistent<Object>::New(Object::New()); |
+ g3s2 = Persistent<Object>::New(Object::New()); |
+ g3s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
+ g3s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
+ } |
+ |
+ // Make a root. |
+ Persistent<Object> root = Persistent<Object>::New(g1s1); |
+ root.MarkPartiallyDependent(); |
+ |
+ // Connect groups. We're building the following cycle: |
+ // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other |
+ // groups. |
+ { |
+ g1s1.MarkPartiallyDependent(); |
+ g1s2.MarkPartiallyDependent(); |
+ g2s1.MarkPartiallyDependent(); |
+ g2s2.MarkPartiallyDependent(); |
+ g3s1.MarkPartiallyDependent(); |
+ g3s2.MarkPartiallyDependent(); |
+ Persistent<Value> g1_objects[] = { g1s1, g1s2 }; |
+ Persistent<Value> g2_objects[] = { g2s1, g2s2 }; |
+ Persistent<Value> g3_objects[] = { g3s1, g3s2 }; |
+ V8::AddObjectGroup(g1_objects, 2); |
+ g1s1->Set(v8_str("x"), g2s1); |
+ V8::AddObjectGroup(g2_objects, 2); |
+ g2s1->Set(v8_str("x"), g3s1); |
+ V8::AddObjectGroup(g3_objects, 2); |
+ g3s1->Set(v8_str("x"), g1s1); |
+ } |
+ |
+ HEAP->CollectGarbage(i::NEW_SPACE); |
+ |
+ // All objects should be alive. |
+ CHECK_EQ(0, counter.NumberOfWeakCalls()); |
+ |
+ // Weaken the root. |
+ root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
+ root.MarkPartiallyDependent(); |
+ |
+ // Groups are deleted, rebuild groups. |
+ { |
+ g1s1.MarkPartiallyDependent(); |
+ g1s2.MarkPartiallyDependent(); |
+ g2s1.MarkPartiallyDependent(); |
+ g2s2.MarkPartiallyDependent(); |
+ g3s1.MarkPartiallyDependent(); |
+ g3s2.MarkPartiallyDependent(); |
+ Persistent<Value> g1_objects[] = { g1s1, g1s2 }; |
+ Persistent<Value> g2_objects[] = { g2s1, g2s2 }; |
+ Persistent<Value> g3_objects[] = { g3s1, g3s2 }; |
+ V8::AddObjectGroup(g1_objects, 2); |
+ g1s1->Set(v8_str("x"), g2s1); |
+ V8::AddObjectGroup(g2_objects, 2); |
+ g2s1->Set(v8_str("x"), g3s1); |
+ V8::AddObjectGroup(g3_objects, 2); |
+ g3s1->Set(v8_str("x"), g1s1); |
+ } |
+ |
+ HEAP->CollectGarbage(i::NEW_SPACE); |
+ |
+ // All objects should be gone. 7 global handles in total. |
+ CHECK_EQ(7, counter.NumberOfWeakCalls()); |
+} |
+ |
+ |
THREADED_TEST(ScriptException) { |
v8::HandleScope scope; |
LocalContext env; |