Chromium Code Reviews| Index: runtime/vm/dart_api_impl_test.cc |
| diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc |
| index aedc4874e4e46c97530035de0c62cc3fac8b4da6..c1aa039a9eb02441b0f37ac8e3a4f7d30156c391 100644 |
| --- a/runtime/vm/dart_api_impl_test.cc |
| +++ b/runtime/vm/dart_api_impl_test.cc |
| @@ -1371,6 +1371,278 @@ TEST_CASE(WeakPersistentHandleCallback) { |
| Dart_DeletePersistentHandle(weak_ref); |
| } |
| + |
| +TEST_CASE(ObjectGroups) { |
| + Dart_Handle strong = Dart_Null(); |
| + EXPECT(Dart_IsNull(strong)); |
| + |
| + Dart_Handle weak1 = Dart_Null(); |
| + EXPECT(Dart_IsNull(weak1)); |
| + |
| + Dart_Handle weak2 = Dart_Null(); |
| + EXPECT(Dart_IsNull(weak2)); |
| + |
| + Dart_Handle weak3 = Dart_Null(); |
| + EXPECT(Dart_IsNull(weak3)); |
| + |
| + Dart_Handle weak4 = Dart_Null(); |
| + EXPECT(Dart_IsNull(weak4)); |
| + |
| + Dart_EnterScope(); |
| + { |
| + DARTSCOPE(Isolate::Current()); |
| + String& str = String::Handle(); |
| + |
| + str ^= String::New("strongly reachable", Heap::kOld); |
| + strong = Dart_NewPersistentHandle(Api::NewLocalHandle(str)); |
| + EXPECT_VALID(strong); |
| + EXPECT(!Dart_IsNull(strong)); |
| + |
| + str ^= String::New("weakly reachable 1", Heap::kOld); |
| + weak1 = Dart_NewWeakPersistentHandle(Api::NewLocalHandle(str), NULL, NULL); |
| + EXPECT_VALID(weak1); |
| + EXPECT(!Dart_IsNull(weak1)); |
| + |
| + str ^= String::New("weakly reachable 2", Heap::kOld); |
| + weak2 = Dart_NewWeakPersistentHandle(Api::NewLocalHandle(str), NULL, NULL); |
| + EXPECT_VALID(weak2); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + |
| + str ^= String::New("weakly reachable 3", Heap::kOld); |
| + weak3 = Dart_NewWeakPersistentHandle(Api::NewLocalHandle(str), NULL, NULL); |
| + EXPECT_VALID(weak3); |
| + EXPECT(!Dart_IsNull(weak3)); |
| + |
| + str ^= String::New("weakly reachable 4", Heap::kOld); |
| + weak4 = Dart_NewWeakPersistentHandle(Api::NewLocalHandle(str), NULL, NULL); |
| + EXPECT_VALID(weak4); |
| + EXPECT(!Dart_IsNull(weak4)); |
| + } |
| + Dart_ExitScope(); |
| + |
| + EXPECT_VALID(strong); |
| + |
| + EXPECT_VALID(weak1); |
| + EXPECT_VALID(weak2); |
| + EXPECT_VALID(weak3); |
| + EXPECT_VALID(weak4); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kNew); |
| + |
| + // New space collection should not affect old space objects |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + EXPECT(!Dart_IsNull(weak3)); |
| + EXPECT(!Dart_IsNull(weak4)); |
| + |
| + { |
| + Dart_Handle array1[] = { weak1, strong }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1), |
| + array1, ARRAY_SIZE(array1))); |
| + |
| + Dart_Handle array2[] = { weak2, weak1 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2), |
| + array2, ARRAY_SIZE(array2))); |
| + |
| + Dart_Handle array3[] = { weak3, weak2 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array3, ARRAY_SIZE(array3), |
| + array3, ARRAY_SIZE(array3))); |
| + |
| + Dart_Handle array4[] = { weak4, weak3 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array4, ARRAY_SIZE(array4), |
| + array4, ARRAY_SIZE(array4))); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + } |
| + |
| + // All weak references should be preserved. |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + EXPECT(!Dart_IsNull(weak3)); |
| + EXPECT(!Dart_IsNull(weak4)); |
| + |
| + { |
| + Dart_Handle array1[] = { weak1, strong }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1), |
| + array1, ARRAY_SIZE(array1))); |
| + |
| + Dart_Handle array2[] = { weak2, weak1 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2), |
| + array2, ARRAY_SIZE(array2))); |
| + |
| + Dart_Handle array3[] = { weak2 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array3, ARRAY_SIZE(array3), |
| + array3, ARRAY_SIZE(array3))); |
| + |
| + // Strong reference to weak3 to retain weak3 and weak4. |
| + Dart_Handle weak3_strong_ref = Dart_NewPersistentHandle(weak3); |
| + EXPECT_VALID(weak3_strong_ref); |
| + |
| + Dart_Handle array4[] = { weak4, weak3 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array4, ARRAY_SIZE(array4), |
| + array4, ARRAY_SIZE(array4))); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + |
| + // Delete strong reference to weak3. |
| + Dart_DeletePersistentHandle(weak3_strong_ref); |
| + } |
| + |
| + // All weak references should be preserved. |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + EXPECT(!Dart_IsNull(weak3)); |
| + EXPECT(!Dart_IsNull(weak4)); |
| + |
| + { |
| + Dart_Handle array1[] = { weak1, strong }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1), |
| + array1, ARRAY_SIZE(array1))); |
| + |
| + Dart_Handle array2[] = { weak2, weak1 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2), |
| + array2, ARRAY_SIZE(array2))); |
| + |
| + Dart_Handle array3[] = { weak2 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array3, ARRAY_SIZE(array3), |
| + array3, ARRAY_SIZE(array3))); |
| + |
| + Dart_Handle array4[] = { weak4, weak3 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array4, ARRAY_SIZE(array4), |
| + array4, ARRAY_SIZE(array4))); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + } |
| + |
| + // Only weak1 and weak2 should be preserved. |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + EXPECT(Dart_IsNull(weak3)); |
| + EXPECT(Dart_IsNull(weak4)); |
| + |
| + { |
| + Dart_Handle array1[] = { weak1, strong }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1), |
| + array1, ARRAY_SIZE(array1))); |
| + |
| + Dart_Handle array2[] = { weak2, weak3 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2), |
| + array2, ARRAY_SIZE(array2))); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + } |
| + |
| + // Only weak1 should be preserved, weak3 should not preserve weak2. |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT(Dart_IsNull(weak2)); |
| + EXPECT(Dart_IsNull(weak3)); |
| + EXPECT(Dart_IsNull(weak4)); |
|
siva
2012/03/02 18:30:33
weak3 and weak4 were already NULL before this test
cshapiro
2012/03/03 00:03:23
Yes, weak3 and weak4 were null before the GC on li
|
| + |
| + { |
| + Dart_Handle array1[] = { strong, weak2, weak3, weak4 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array1, ARRAY_SIZE(array1), |
| + array1, ARRAY_SIZE(array1))); |
| + |
| + Dart_Handle array2[] = { weak1 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(array2, ARRAY_SIZE(array2), |
| + array2, ARRAY_SIZE(array2))); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + } |
| + |
| + // No weak references should be preserved. |
|
siva
2012/03/02 18:30:33
Why should weak2, weak3 and weak4 not be preserved
cshapiro
2012/03/03 00:03:23
The are still null so they should remain null.
|
| + EXPECT(Dart_IsNull(weak1)); |
| + EXPECT(Dart_IsNull(weak2)); |
| + EXPECT(Dart_IsNull(weak3)); |
| + EXPECT(Dart_IsNull(weak4)); |
|
siva
2012/03/02 18:30:33
I am little confused here, weak3, weak4, weak2 wer
cshapiro
2012/03/03 00:03:23
Let me add some comments and see if that makes the
|
| +} |
| + |
| + |
| +TEST_CASE(ImplicitReferences) { |
| + Dart_Handle strong = Dart_Null(); |
| + EXPECT(Dart_IsNull(strong)); |
| + |
| + Dart_Handle weak1 = Dart_Null(); |
| + EXPECT(Dart_IsNull(weak1)); |
| + |
| + Dart_Handle weak2 = Dart_Null(); |
| + EXPECT(Dart_IsNull(weak2)); |
| + |
| + Dart_Handle weak3 = Dart_Null(); |
| + EXPECT(Dart_IsNull(weak3)); |
| + |
| + |
| + Dart_EnterScope(); |
| + { |
| + DARTSCOPE(Isolate::Current()); |
| + String& str = String::Handle(); |
| + |
| + str ^= String::New("strongly reachable", Heap::kOld); |
| + strong = Dart_NewPersistentHandle(Api::NewLocalHandle(str)); |
| + EXPECT(!Dart_IsNull(strong)); |
| + EXPECT_VALID(strong); |
| + |
| + str ^= String::New("weakly reachable 1", Heap::kOld); |
| + weak1 = Dart_NewWeakPersistentHandle(Api::NewLocalHandle(str), NULL, NULL); |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT_VALID(weak1); |
| + |
| + str ^= String::New("weakly reachable 2", Heap::kOld); |
| + weak2 = Dart_NewWeakPersistentHandle(Api::NewLocalHandle(str), NULL, NULL); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + EXPECT_VALID(weak2); |
| + |
| + str ^= String::New("weakly reachable 3", Heap::kOld); |
| + weak3 = Dart_NewWeakPersistentHandle(Api::NewLocalHandle(str), NULL, NULL); |
| + EXPECT(!Dart_IsNull(weak3)); |
| + EXPECT_VALID(weak3); |
| + } |
| + Dart_ExitScope(); |
| + |
| + EXPECT_VALID(strong); |
| + |
| + EXPECT_VALID(weak1); |
| + EXPECT_VALID(weak2); |
| + EXPECT_VALID(weak3); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kNew); |
| + |
| + // New space collection should not affect old space objects |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + EXPECT(!Dart_IsNull(weak3)); |
| + |
| + // A strongly referenced key should preserve all the values. |
| + { |
| + Dart_Handle keys[] = { strong }; |
| + Dart_Handle values[] = { weak1, weak2, weak3 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(keys, ARRAY_SIZE(keys), |
| + values, ARRAY_SIZE(values))); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + } |
| + |
| + // All weak references should be preserved. |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + EXPECT(!Dart_IsNull(weak3)); |
| + |
| + // Key membership does not imply a strong reference. |
| + { |
| + Dart_Handle keys[] = { strong, weak3 }; |
| + Dart_Handle values[] = { weak1, weak2 }; |
| + EXPECT_VALID(Dart_NewWeakReferenceSet(keys, ARRAY_SIZE(keys), |
| + values, ARRAY_SIZE(values))); |
| + |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + } |
| + |
| + // All weak references except weak3 should be preserved. |
| + EXPECT(!Dart_IsNull(weak1)); |
| + EXPECT(!Dart_IsNull(weak2)); |
| + EXPECT(Dart_IsNull(weak3)); |
| +} |
| + |
| #endif |