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 f6380aa8119c1b7115945363c739bf5edab5c1de..b19b4fcf2c4a76ee50da47c6e3cc930722c5e9d1 100644 |
| --- a/runtime/vm/dart_api_impl_test.cc |
| +++ b/runtime/vm/dart_api_impl_test.cc |
| @@ -1646,6 +1646,171 @@ TEST_CASE(ImplicitReferences) { |
| EXPECT(Dart_IsNull(weak3)); |
| } |
| + |
| +static int global_prologue_callback_status = 0; |
| + |
| + |
| +static void PrologueCallbackTimes2() { |
| + global_prologue_callback_status *= 2; |
| +} |
| + |
| + |
| +static void PrologueCallbackTimes3() { |
| + global_prologue_callback_status *= 3; |
| +} |
| + |
| + |
| +static int global_epilogue_callback_status = 0; |
| + |
| + |
| +static void EpilogueCallbackTimes4() { |
| + global_epilogue_callback_status *= 4; |
|
turnidge
2012/03/07 00:25:16
How about relatively prime numbers? 4 -> 5, 5 ->
cshapiro
2012/03/07 03:06:10
I think I avoid this case by separating the value
|
| +} |
| + |
| + |
| +static void EpilogueCallbackTimes5() { |
| + global_epilogue_callback_status *= 5; |
| +} |
| + |
| + |
| +TEST_CASE(GarbageCollectionCallbacks) { |
|
turnidge
2012/03/07 00:25:16
Consider splitting into a few smaller tests.
I li
cshapiro
2012/03/07 03:06:10
Done.
|
| + // Add a prologue callback. |
| + EXPECT_VALID(Dart_NewGcPrologueCallback(&PrologueCallbackTimes2)); |
| + |
| + // Add the same prologue callback again. This is an error. |
| + EXPECT(Dart_IsError(Dart_NewGcPrologueCallback(&PrologueCallbackTimes2))); |
| + |
| + // Garbage collect new space. This should not invoke the prologue |
| + // callback. No status values should change. |
| + global_prologue_callback_status = 3; |
| + global_epilogue_callback_status = 7; |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kNew); |
| + EXPECT_EQ(3, global_prologue_callback_status); |
| + EXPECT_EQ(7, global_epilogue_callback_status); |
| + |
| + // Garbage collect old space. This should invoke the prologue |
| + // callback. The prologue status value should change. |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(6, global_prologue_callback_status); |
| + EXPECT_EQ(7, global_epilogue_callback_status); |
| + |
| + // Garbage collect old space again. Callbacks are persistent so the |
| + // prolog status value should change again. |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(12, global_prologue_callback_status); |
| + EXPECT_EQ(7, global_epilogue_callback_status); |
| + |
| + // Add an GC epilogue callback. |
| + EXPECT_VALID(Dart_NewGcEpilogueCallback(&EpilogueCallbackTimes4)); |
| + |
| + // Add the same epilogue callback again. This is an error. |
| + EXPECT(Dart_IsError(Dart_NewGcEpilogueCallback(&EpilogueCallbackTimes4))); |
| + |
| + // Garbage collect new space. This should not invoke the prologue |
| + // or the epilogue callback. No status values should change. |
| + global_prologue_callback_status = 3; |
| + global_epilogue_callback_status = 7; |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kNew); |
| + EXPECT_EQ(3, global_prologue_callback_status); |
| + EXPECT_EQ(7, global_epilogue_callback_status); |
| + |
| + // Garbage collect old space. This should invoke the prologue and |
| + // the epilogue callbacks. The prologue and epilogue status values |
| + // should change. |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(6, global_prologue_callback_status); |
| + EXPECT_EQ(28, global_epilogue_callback_status); |
| + |
| + // Garbage collect old space again. Callbacks are persistent so the |
| + // prologue and epilogue status values should change again. |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(12, global_prologue_callback_status); |
| + EXPECT_EQ(112, global_epilogue_callback_status); |
| + |
| + // Add another GC prologue callback. |
| + EXPECT_VALID(Dart_NewGcPrologueCallback(&PrologueCallbackTimes3)); |
| + |
| + // Garbage collect old space. This should invoke both prologue |
| + // callbacks and the epilogue callback. The prologue and epilogue |
| + // status values should change. |
| + global_prologue_callback_status = 3; |
| + global_epilogue_callback_status = 7; |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(18, global_prologue_callback_status); |
| + EXPECT_EQ(28, global_epilogue_callback_status); |
| + |
| + // Add another GC epilogue callback. |
| + EXPECT_VALID(Dart_NewGcEpilogueCallback(&EpilogueCallbackTimes5)); |
| + |
| + // Garbage collect old space. This should invoke both prologue |
| + // callbacks and both epilogue callbacks. The prologue and epilogue |
| + // status values should change. |
| + global_prologue_callback_status = 3; |
| + global_epilogue_callback_status = 7; |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(18, global_prologue_callback_status); |
| + EXPECT_EQ(140, global_epilogue_callback_status); |
| + |
| + // Remove an epilogue callback. |
| + EXPECT_VALID(Dart_DeleteGcEpilogueCallback(&EpilogueCallbackTimes4)); |
| + |
| + // Garbage collect old space. This should invoke both prologue |
| + // callbacks and the remaining epilogue callback. The prologue and |
| + // epilogue status values should change. |
| + global_prologue_callback_status = 3; |
| + global_epilogue_callback_status = 7; |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(18, global_prologue_callback_status); |
| + EXPECT_EQ(35, global_epilogue_callback_status); |
| + |
| + // Try removing the epilogue callback again. This is an error. |
| + EXPECT(Dart_IsError(Dart_DeleteGcEpilogueCallback(&EpilogueCallbackTimes4))); |
| + |
| + // Remove the remaining epilogue callback. |
| + EXPECT_VALID(Dart_DeleteGcEpilogueCallback(&EpilogueCallbackTimes5)); |
| + |
| + // Try removing the remaining epilogue callback again. This is an |
| + // error. |
| + EXPECT(Dart_IsError(Dart_DeleteGcEpilogueCallback(&EpilogueCallbackTimes5))); |
| + |
| + // Garbage collect old space. This should invoke both prologue |
| + // callbacks. The prologue status value should change. |
| + global_prologue_callback_status = 3; |
| + global_epilogue_callback_status = 7; |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(18, global_prologue_callback_status); |
| + EXPECT_EQ(7, global_epilogue_callback_status); |
| + |
| + // Remove a prologue callback. |
| + EXPECT_VALID(Dart_DeleteGcPrologueCallback(&PrologueCallbackTimes3)); |
| + |
| + // Try removing the prologue callback again. This is an error. |
| + EXPECT(Dart_IsError(Dart_DeleteGcPrologueCallback(&PrologueCallbackTimes3))); |
| + |
| + // Garbage collect old space. This should invoke the remaining |
| + // prologue callback. The prologue status value should change. |
| + global_prologue_callback_status = 3; |
| + global_epilogue_callback_status = 7; |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(6, global_prologue_callback_status); |
| + EXPECT_EQ(7, global_epilogue_callback_status); |
| + |
| + // Remove the remaining prologue callback. |
| + EXPECT_VALID(Dart_DeleteGcPrologueCallback(&PrologueCallbackTimes2)); |
| + |
| + // Try removing the remaining prologue callback again. This is an |
| + // error. |
| + EXPECT(Dart_IsError(Dart_DeleteGcPrologueCallback(&PrologueCallbackTimes2))); |
| + |
| + // Garbage collect old space. No callbacks should be invoked. No |
| + // status values should change. |
| + global_prologue_callback_status = 3; |
| + global_epilogue_callback_status = 7; |
| + Isolate::Current()->heap()->CollectGarbage(Heap::kOld); |
| + EXPECT_EQ(3, global_prologue_callback_status); |
| + EXPECT_EQ(7, global_epilogue_callback_status); |
| +} |
| + |
| #endif |