Index: test/cctest/test-spaces.cc |
diff --git a/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc |
index 16d1e8a762c0981254784b350273d6ac347a85c3..21f7438cec7909ba313b02d01a84e7938ff72150 100644 |
--- a/test/cctest/test-spaces.cc |
+++ b/test/cctest/test-spaces.cc |
@@ -645,3 +645,110 @@ UNINITIALIZED_TEST(NewSpaceGrowsToTargetCapacity) { |
} |
isolate->Dispose(); |
} |
+ |
+ |
+static HeapObject* AllocateUnaligned(NewSpace* space, int size) { |
+ AllocationResult allocation = space->AllocateRawUnaligned(size); |
+ CHECK(!allocation.IsRetry()); |
+ HeapObject* filler = NULL; |
+ CHECK(allocation.To(&filler)); |
+ space->heap()->CreateFillerObjectAt(filler->address(), size); |
+ return filler; |
+} |
+ |
+ |
+static void observer1(int bytes_allocated, void* arg) { |
+ int* counter = static_cast<int*>(arg); |
+ (*counter)++; |
+} |
+ |
+ |
+static void observer2(int bytes_allocated, void* arg) { |
+ int* counter = static_cast<int*>(arg); |
+ (*counter)++; |
+} |
+ |
+ |
+UNINITIALIZED_TEST(InlineAllocationObserver) { |
+ v8::Isolate::CreateParams create_params; |
+ create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); |
+ v8::Isolate* isolate = v8::Isolate::New(create_params); |
+ { |
+ v8::Isolate::Scope isolate_scope(isolate); |
+ v8::HandleScope handle_scope(isolate); |
+ v8::Context::New(isolate)->Enter(); |
+ |
+ Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate); |
+ |
+ NewSpace* new_space = i_isolate->heap()->new_space(); |
+ |
+ int counter1 = 0; |
+ new_space->AddInlineAllocationObserver(128, observer1, &counter1); |
+ |
+ // The observer should not get notified until we have allocated a 128 bytes. |
+ AllocateUnaligned(new_space, 64); |
+ CHECK_EQ(counter1, 0); |
+ |
+ // The observer should get notified when have allocated precisely 128 bytes. |
+ AllocateUnaligned(new_space, 64); |
+ CHECK_EQ(counter1, 1); |
+ |
+ // Another 128 bytes should get another notification. |
+ AllocateUnaligned(new_space, 128); |
+ CHECK_EQ(counter1, 2); |
+ |
+ // Allocating a large object should get only one notification. |
+ AllocateUnaligned(new_space, 1024); |
+ CHECK_EQ(counter1, 3); |
+ |
+ // Allocating another 2048 bytes in small objects should get 16 |
+ // notifications. |
+ for (int i = 0; i < 64; ++i) { |
+ AllocateUnaligned(new_space, 32); |
+ } |
+ CHECK_EQ(counter1, 19); |
+ |
+ // Multiple observers should work. |
+ int counter2 = 0; |
+ new_space->AddInlineAllocationObserver(96, observer2, &counter2); |
+ |
+ AllocateUnaligned(new_space, 2048); |
+ CHECK_EQ(counter1, 20); |
+ CHECK_EQ(counter2, 1); |
+ |
+ AllocateUnaligned(new_space, 96); |
+ CHECK_EQ(counter1, 20); |
+ CHECK_EQ(counter2, 2); |
+ |
+ // Callback should stop getting called after an observer is removed. |
+ new_space->RemoveInlineAllocationObserver(observer1); |
+ |
+ AllocateUnaligned(new_space, 384); |
+ CHECK_EQ(counter1, 20); // no more notifications. |
+ CHECK_EQ(counter2, 3); // this one is still active. |
+ |
+ // The same function pointer can be added multiple times. |
+ int counter3 = 0; |
+ new_space->AddInlineAllocationObserver(32, observer2, &counter3); |
+ |
+ // Both counter2, and counter3 should be getting updated now. |
+ AllocateUnaligned(new_space, 128); |
+ CHECK_EQ(counter1, 20); |
+ CHECK_EQ(counter2, 4); |
+ CHECK_EQ(counter3, 1); |
+ |
+ // Removing an duplicated observer removes it in the order of addition. |
+ new_space->RemoveInlineAllocationObserver(observer2); |
+ AllocateUnaligned(new_space, 128); |
+ CHECK_EQ(counter1, 20); |
+ CHECK_EQ(counter2, 4); |
+ CHECK_EQ(counter3, 2); // this one should still get updated. |
+ |
+ // Should be able to remove the second instance of observer2. |
+ new_space->RemoveInlineAllocationObserver(observer2); |
+ CHECK_EQ(counter1, 20); |
+ CHECK_EQ(counter2, 4); |
+ CHECK_EQ(counter3, 2); |
+ } |
+ isolate->Dispose(); |
+} |