Index: test/cctest/test-identity-map.cc |
diff --git a/test/cctest/test-identity-map.cc b/test/cctest/test-identity-map.cc |
index 6254bbfc6c988a623fe2633a72934feddf5d8c72..648508cbd17d060af613c513800ed1c658483efe 100644 |
--- a/test/cctest/test-identity-map.cc |
+++ b/test/cctest/test-identity-map.cc |
@@ -336,5 +336,85 @@ TEST(ExplicitGC) { |
} |
} |
+ |
+TEST(CanonicalHandleScope) { |
+ Isolate* isolate = CcTest::i_isolate(); |
+ Heap* heap = CcTest::heap(); |
+ HandleScope outer(isolate); |
+ CanonicalHandleScope outer_canonical(isolate); |
+ |
+ // Deduplicate smi handles. |
+ List<Handle<Object> > smi_handles; |
+ for (int i = 0; i < 100; i++) { |
+ smi_handles.Add(Handle<Object>(Smi::FromInt(i), isolate)); |
+ } |
+ Object** next_handle = isolate->handle_scope_data()->next; |
+ for (int i = 0; i < 100; i++) { |
+ Handle<Object> new_smi = Handle<Object>(Smi::FromInt(i), isolate); |
+ Handle<Object> old_smi = smi_handles[i]; |
+ CHECK_EQ(new_smi.location(), old_smi.location()); |
+ } |
+ // Check that no new handles have been allocated. |
+ CHECK_EQ(next_handle, isolate->handle_scope_data()->next); |
+ |
+ // Deduplicate root list items. |
+ Handle<String> empty_string(heap->empty_string()); |
+ Handle<Map> free_space_map(heap->free_space_map()); |
+ Handle<Symbol> uninitialized_symbol(heap->uninitialized_symbol()); |
+ CHECK_EQ(isolate->factory()->empty_string().location(), |
+ empty_string.location()); |
+ CHECK_EQ(isolate->factory()->free_space_map().location(), |
+ free_space_map.location()); |
+ CHECK_EQ(isolate->factory()->uninitialized_symbol().location(), |
+ uninitialized_symbol.location()); |
+ // Check that no new handles have been allocated. |
+ CHECK_EQ(next_handle, isolate->handle_scope_data()->next); |
+ |
+ // Test ordinary heap objects. |
+ Handle<HeapNumber> number1 = isolate->factory()->NewHeapNumber(3.3); |
+ Handle<String> string1 = |
+ isolate->factory()->NewStringFromAsciiChecked("test"); |
+ next_handle = isolate->handle_scope_data()->next; |
+ Handle<HeapNumber> number2(*number1); |
+ Handle<String> string2(*string1); |
+ CHECK_EQ(number1.location(), number2.location()); |
+ CHECK_EQ(string1.location(), string2.location()); |
+ heap->CollectAllGarbage(); |
+ Handle<HeapNumber> number3(*number2); |
+ Handle<String> string3(*string2); |
+ CHECK_EQ(number1.location(), number3.location()); |
+ CHECK_EQ(string1.location(), string3.location()); |
+ // Check that no new handles have been allocated. |
+ CHECK_EQ(next_handle, isolate->handle_scope_data()->next); |
+ |
+ // Inner handle scope do not create canonical handles. |
+ { |
+ HandleScope inner(isolate); |
+ Handle<HeapNumber> number4(*number1); |
+ Handle<String> string4(*string1); |
+ CHECK_NE(number1.location(), number4.location()); |
+ CHECK_NE(string1.location(), string4.location()); |
+ |
+ // Nested canonical scope does not conflict with outer canonical scope, |
+ // but does not canonicalize across scopes. |
+ CanonicalHandleScope inner_canonical(isolate); |
+ Handle<HeapNumber> number5(*number4); |
+ Handle<String> string5(*string4); |
+ CHECK_NE(number4.location(), number5.location()); |
+ CHECK_NE(string4.location(), string5.location()); |
+ CHECK_NE(number1.location(), number5.location()); |
+ CHECK_NE(string1.location(), string5.location()); |
+ |
+ Handle<HeapNumber> number6(*number1); |
+ Handle<String> string6(*string1); |
+ CHECK_NE(number4.location(), number6.location()); |
+ CHECK_NE(string4.location(), string6.location()); |
+ CHECK_NE(number1.location(), number6.location()); |
+ CHECK_NE(string1.location(), string6.location()); |
+ CHECK_EQ(number5.location(), number6.location()); |
+ CHECK_EQ(string5.location(), string6.location()); |
+ } |
+} |
+ |
} // namespace internal |
} // namespace v8 |