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 5498bd704c213ca5deaa1bb6ce6600931f6480f8..400f25f5a71d4db6120899f47656f6c6b45a5569 100644 |
| --- a/runtime/vm/dart_api_impl_test.cc |
| +++ b/runtime/vm/dart_api_impl_test.cc |
| @@ -1207,6 +1207,28 @@ TEST_CASE(MalformedStringToUTF8) { |
| } |
| +// Helper class to ensure new gen GC is triggered without any side effects. |
| +// The normal call to CollectGarbage(Heap::kNew) could potentially trigger |
| +// an old gen collection if there is a promotion failure and this could |
| +// perturb the test. |
| +class GCTestHelper : public AllStatic { |
| + public: |
| + static void CollectNewSpace(Heap::ApiCallbacks api_callbacks) { |
| + bool invoke_api_callbacks = (api_callbacks == Heap::kInvokeApiCallbacks); |
| + Isolate::Current()->heap()->new_space()->Scavenge(invoke_api_callbacks); |
| + } |
| + |
| + static void WaitForFinalizationTasks() { |
| + Thread* thread = Thread::Current(); |
| + Heap* heap = thread->isolate()->heap(); |
| + MonitorLocker ml(heap->finalization_tasks_lock()); |
| + while (heap->finalization_tasks() > 0) { |
| + ml.WaitWithSafepointCheck(thread); |
| + } |
| + } |
| +}; |
| + |
| + |
| static void ExternalStringCallbackFinalizer(void* peer) { |
| *static_cast<int*>(peer) *= 2; |
| } |
| @@ -1243,9 +1265,11 @@ TEST_CASE(ExternalStringCallback) { |
| EXPECT_EQ(40, peer8); |
| EXPECT_EQ(41, peer16); |
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT_EQ(40, peer8); |
| EXPECT_EQ(41, peer16); |
| Isolate::Current()->heap()->CollectGarbage(Heap::kNew); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT_EQ(80, peer8); |
| EXPECT_EQ(82, peer16); |
| } |
| @@ -2382,13 +2406,47 @@ TEST_CASE(ExternalTypedDataCallback) { |
| TransitionNativeToVM transition(thread); |
| EXPECT(peer == 0); |
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT(peer == 0); |
| Isolate::Current()->heap()->CollectGarbage(Heap::kNew); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT(peer == 42); |
| } |
| } |
| +static void SlowFinalizer(void* isolate_callback_data, |
| + Dart_WeakPersistentHandle handle, |
| + void* peer) { |
| + OS::Sleep(50); |
|
siva
2016/06/22 04:43:29
I hope this sleep on every call won't cause timeou
rmacnak
2016/06/22 17:50:45
I like the monitor approach better. To make it wor
|
| + ++*reinterpret_cast<intptr_t*>(peer); |
| +} |
| + |
| + |
| +TEST_CASE(SlowFinalizer) { |
| + intptr_t peer = 0; |
| + for (intptr_t i = 0; i < 100; i++) { |
| + Dart_EnterScope(); |
| + Dart_Handle str1 = Dart_NewStringFromCString("Live fast"); |
| + Dart_NewWeakPersistentHandle(str1, &peer, 0, SlowFinalizer); |
| + Dart_Handle str2 = Dart_NewStringFromCString("Die young"); |
| + Dart_NewWeakPersistentHandle(str2, &peer, 0, SlowFinalizer); |
| + Dart_ExitScope(); |
| + |
| + { |
| + TransitionNativeToVM transition(thread); |
| + Isolate::Current()->heap()->CollectAllGarbage(); |
| + } |
| + } |
| + |
| + { |
| + TransitionNativeToVM transition(thread); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| + } |
| + ASSERT(peer == 200); |
| +} |
| + |
| + |
| static void CheckFloat32x4Data(Dart_Handle obj) { |
| void* raw_data = NULL; |
| intptr_t len; |
| @@ -2440,6 +2498,7 @@ TEST_CASE(Float32x4List) { |
| { |
| TransitionNativeToVM transition(thread); |
| Isolate::Current()->heap()->CollectGarbage(Heap::kNew); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT(peer == 42); |
| } |
| } |
| @@ -2602,19 +2661,6 @@ UNIT_TEST_CASE(AssignToPersistentHandle) { |
| } |
| -// Helper class to ensure new gen GC is triggered without any side effects. |
| -// The normal call to CollectGarbage(Heap::kNew) could potentially trigger |
| -// an old gen collection if there is a promotion failure and this could |
| -// perturb the test. |
| -class GCTestHelper : public AllStatic { |
| - public: |
| - static void CollectNewSpace(Heap::ApiCallbacks api_callbacks) { |
| - bool invoke_api_callbacks = (api_callbacks == Heap::kInvokeApiCallbacks); |
| - Isolate::Current()->heap()->new_space()->Scavenge(invoke_api_callbacks); |
| - } |
| -}; |
| - |
| - |
| static Dart_Handle AsHandle(Dart_PersistentHandle weak) { |
| return Dart_HandleFromPersistent(weak); |
| } |
| @@ -2729,6 +2775,7 @@ TEST_CASE(WeakPersistentHandle) { |
| TransitionNativeToVM transition(thread); |
| // Garbage collect new space again. |
| GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| } |
| { |
| @@ -2744,6 +2791,7 @@ TEST_CASE(WeakPersistentHandle) { |
| TransitionNativeToVM transition(thread); |
| // Garbage collect old space again. |
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| } |
| { |
| @@ -2788,6 +2836,7 @@ TEST_CASE(WeakPersistentHandleCallback) { |
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| EXPECT(peer == 0); |
| GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT(peer == 42); |
| } |
| } |
| @@ -2814,6 +2863,7 @@ TEST_CASE(WeakPersistentHandleNoCallback) { |
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| EXPECT(peer == 0); |
| GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT(peer == 0); |
| } |
| } |
| @@ -2874,6 +2924,7 @@ TEST_CASE(WeakPersistentHandleExternalAllocationSize) { |
| // Collect weakly referenced string, and promote strongly referenced string. |
| GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks); |
| GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT(heap->ExternalInWords(Heap::kNew) == 0); |
| EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak2ExternalSize / kWordSize); |
| } |
| @@ -2884,6 +2935,7 @@ TEST_CASE(WeakPersistentHandleExternalAllocationSize) { |
| { |
| TransitionNativeToVM transition(thread); |
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT(heap->ExternalInWords(Heap::kOld) == 0); |
| } |
| } |
| @@ -2929,6 +2981,7 @@ TEST_CASE(WeakPersistentHandleExternalAllocationSizeNewspaceGC) { |
| { |
| TransitionNativeToVM transition(thread); |
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| EXPECT(heap->ExternalInWords(Heap::kOld) == 0); |
| } |
| } |
| @@ -8707,6 +8760,7 @@ TEST_CASE(MakeExternalString) { |
| { |
| TransitionNativeToVM transition(thread); |
| Isolate::Current()->heap()->CollectAllGarbage(); |
| + GCTestHelper::WaitForFinalizationTasks(); |
| } |
| EXPECT_EQ(80, peer8); |
| EXPECT_EQ(82, peer16); |