| 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..d39e165391861bdb1ed2a4fab2d120bb64e96cac 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,65 @@ 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 Monitor* slow_finalizers_monitor = NULL;
|
| +static intptr_t slow_finalizers_waiting = 0;
|
| +
|
| +
|
| +static void SlowFinalizer(void* isolate_callback_data,
|
| + Dart_WeakPersistentHandle handle,
|
| + void* peer) {
|
| + {
|
| + MonitorLocker ml(slow_finalizers_monitor);
|
| + slow_finalizers_waiting++;
|
| + while (slow_finalizers_waiting < 10) {
|
| + ml.Wait();
|
| + }
|
| + ml.NotifyAll();
|
| + }
|
| +
|
| + intptr_t* count = reinterpret_cast<intptr_t*>(peer);
|
| + AtomicOperations::IncrementBy(count, 1);
|
| +}
|
| +
|
| +
|
| +TEST_CASE(SlowFinalizer) {
|
| + slow_finalizers_monitor = new Monitor();
|
| +
|
| + intptr_t count = 0;
|
| + for (intptr_t i = 0; i < 10; i++) {
|
| + Dart_EnterScope();
|
| + Dart_Handle str1 = Dart_NewStringFromCString("Live fast");
|
| + Dart_NewWeakPersistentHandle(str1, &count, 0, SlowFinalizer);
|
| + Dart_Handle str2 = Dart_NewStringFromCString("Die young");
|
| + Dart_NewWeakPersistentHandle(str2, &count, 0, SlowFinalizer);
|
| + Dart_ExitScope();
|
| +
|
| + {
|
| + TransitionNativeToVM transition(thread);
|
| + Isolate::Current()->heap()->CollectAllGarbage();
|
| + }
|
| + }
|
| +
|
| + {
|
| + TransitionNativeToVM transition(thread);
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| + }
|
| +
|
| + EXPECT_EQ(20, count);
|
| +
|
| + delete slow_finalizers_monitor;
|
| +}
|
| +
|
| +
|
| static void CheckFloat32x4Data(Dart_Handle obj) {
|
| void* raw_data = NULL;
|
| intptr_t len;
|
| @@ -2440,6 +2516,7 @@ TEST_CASE(Float32x4List) {
|
| {
|
| TransitionNativeToVM transition(thread);
|
| Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| EXPECT(peer == 42);
|
| }
|
| }
|
| @@ -2602,19 +2679,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 +2793,7 @@ TEST_CASE(WeakPersistentHandle) {
|
| TransitionNativeToVM transition(thread);
|
| // Garbage collect new space again.
|
| GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| }
|
|
|
| {
|
| @@ -2744,6 +2809,7 @@ TEST_CASE(WeakPersistentHandle) {
|
| TransitionNativeToVM transition(thread);
|
| // Garbage collect old space again.
|
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| }
|
|
|
| {
|
| @@ -2788,6 +2854,7 @@ TEST_CASE(WeakPersistentHandleCallback) {
|
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
| EXPECT(peer == 0);
|
| GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| EXPECT(peer == 42);
|
| }
|
| }
|
| @@ -2814,6 +2881,7 @@ TEST_CASE(WeakPersistentHandleNoCallback) {
|
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
| EXPECT(peer == 0);
|
| GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| EXPECT(peer == 0);
|
| }
|
| }
|
| @@ -2874,6 +2942,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 +2953,7 @@ TEST_CASE(WeakPersistentHandleExternalAllocationSize) {
|
| {
|
| TransitionNativeToVM transition(thread);
|
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
|
| }
|
| }
|
| @@ -2929,6 +2999,7 @@ TEST_CASE(WeakPersistentHandleExternalAllocationSizeNewspaceGC) {
|
| {
|
| TransitionNativeToVM transition(thread);
|
| Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
|
| }
|
| }
|
| @@ -8707,6 +8778,7 @@ TEST_CASE(MakeExternalString) {
|
| {
|
| TransitionNativeToVM transition(thread);
|
| Isolate::Current()->heap()->CollectAllGarbage();
|
| + GCTestHelper::WaitForFinalizationTasks();
|
| }
|
| EXPECT_EQ(80, peer8);
|
| EXPECT_EQ(82, peer16);
|
|
|