LCOV - code coverage report
Current view: top level - test/cctest/heap - test-invalidated-slots.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 201 201 100.0 %
Date: 2019-01-20 Functions: 15 15 100.0 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <stdlib.h>
       6             : 
       7             : #include "src/v8.h"
       8             : 
       9             : #include "src/heap/heap-inl.h"
      10             : #include "src/heap/heap.h"
      11             : #include "src/heap/invalidated-slots-inl.h"
      12             : #include "src/heap/invalidated-slots.h"
      13             : #include "test/cctest/cctest.h"
      14             : #include "test/cctest/heap/heap-tester.h"
      15             : #include "test/cctest/heap/heap-utils.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : namespace heap {
      20             : 
      21          30 : Page* HeapTester::AllocateByteArraysOnPage(
      22          30 :     Heap* heap, std::vector<ByteArray>* byte_arrays) {
      23          30 :   PauseAllocationObserversScope pause_observers(heap);
      24             :   const int kLength = 256 - ByteArray::kHeaderSize;
      25             :   const int kSize = ByteArray::SizeFor(kLength);
      26             :   CHECK_EQ(kSize, 256);
      27             :   Isolate* isolate = heap->isolate();
      28             :   PagedSpace* old_space = heap->old_space();
      29             :   Page* page;
      30             :   // Fill a page with byte arrays.
      31             :   {
      32             :     AlwaysAllocateScope always_allocate(isolate);
      33          30 :     heap::SimulateFullSpace(old_space);
      34          30 :     ByteArray byte_array;
      35          30 :     CHECK(AllocateByteArrayForTest(heap, kLength, TENURED).To(&byte_array));
      36          30 :     byte_arrays->push_back(byte_array);
      37             :     page = Page::FromHeapObject(byte_array);
      38          60 :     size_t n = page->area_size() / kSize;
      39       61380 :     for (size_t i = 1; i < n; i++) {
      40       61350 :       CHECK(AllocateByteArrayForTest(heap, kLength, TENURED).To(&byte_array));
      41       61350 :       byte_arrays->push_back(byte_array);
      42       61350 :       CHECK_EQ(page, Page::FromHeapObject(byte_array));
      43             :     }
      44             :   }
      45          30 :   CHECK_NULL(page->invalidated_slots());
      46          30 :   return page;
      47             : }
      48             : 
      49       28342 : HEAP_TEST(InvalidatedSlotsNoInvalidatedRanges) {
      50           5 :   CcTest::InitializeVM();
      51           5 :   Heap* heap = CcTest::heap();
      52             :   std::vector<ByteArray> byte_arrays;
      53           5 :   Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
      54           5 :   InvalidatedSlotsFilter filter(page);
      55       10240 :   for (ByteArray byte_array : byte_arrays) {
      56       10230 :     Address start = byte_array->address() + ByteArray::kHeaderSize;
      57       10230 :     Address end = byte_array->address() + byte_array->Size();
      58      317130 :     for (Address addr = start; addr < end; addr += kTaggedSize) {
      59      306900 :       CHECK(filter.IsValid(addr));
      60             :     }
      61             :   }
      62           5 : }
      63             : 
      64       28342 : HEAP_TEST(InvalidatedSlotsSomeInvalidatedRanges) {
      65           5 :   CcTest::InitializeVM();
      66           5 :   Heap* heap = CcTest::heap();
      67             :   std::vector<ByteArray> byte_arrays;
      68           5 :   Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
      69             :   // Register every second byte arrays as invalidated.
      70       10240 :   for (size_t i = 0; i < byte_arrays.size(); i += 2) {
      71        5115 :     page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
      72       10230 :                                              byte_arrays[i]->Size());
      73             :   }
      74           5 :   InvalidatedSlotsFilter filter(page);
      75       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
      76       10230 :     ByteArray byte_array = byte_arrays[i];
      77       10230 :     Address start = byte_array->address() + ByteArray::kHeaderSize;
      78       10230 :     Address end = byte_array->address() + byte_array->Size();
      79      317130 :     for (Address addr = start; addr < end; addr += kTaggedSize) {
      80      306900 :       if (i % 2 == 0) {
      81      153450 :         CHECK(!filter.IsValid(addr));
      82             :       } else {
      83      153450 :         CHECK(filter.IsValid(addr));
      84             :       }
      85             :     }
      86             :   }
      87           5 : }
      88             : 
      89       28342 : HEAP_TEST(InvalidatedSlotsAllInvalidatedRanges) {
      90           5 :   CcTest::InitializeVM();
      91           5 :   Heap* heap = CcTest::heap();
      92             :   std::vector<ByteArray> byte_arrays;
      93           5 :   Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
      94             :   // Register the all byte arrays as invalidated.
      95       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
      96       10230 :     page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
      97       20460 :                                              byte_arrays[i]->Size());
      98             :   }
      99           5 :   InvalidatedSlotsFilter filter(page);
     100       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
     101       10230 :     ByteArray byte_array = byte_arrays[i];
     102       10230 :     Address start = byte_array->address() + ByteArray::kHeaderSize;
     103       10230 :     Address end = byte_array->address() + byte_array->Size();
     104      317130 :     for (Address addr = start; addr < end; addr += kTaggedSize) {
     105      306900 :       CHECK(!filter.IsValid(addr));
     106             :     }
     107             :   }
     108           5 : }
     109             : 
     110       28342 : HEAP_TEST(InvalidatedSlotsAfterTrimming) {
     111             :   ManualGCScope manual_gc_scope;
     112           5 :   CcTest::InitializeVM();
     113           5 :   Heap* heap = CcTest::heap();
     114             :   std::vector<ByteArray> byte_arrays;
     115           5 :   Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
     116             :   // Register the all byte arrays as invalidated.
     117       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
     118       10230 :     page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
     119       20460 :                                              byte_arrays[i]->Size());
     120             :   }
     121             :   // Trim byte arrays and check that the slots outside the byte arrays are
     122             :   // considered invalid if the old space page was swept.
     123           5 :   InvalidatedSlotsFilter filter(page);
     124       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
     125       10230 :     ByteArray byte_array = byte_arrays[i];
     126       10230 :     Address start = byte_array->address() + ByteArray::kHeaderSize;
     127       10230 :     Address end = byte_array->address() + byte_array->Size();
     128       10230 :     heap->RightTrimFixedArray(byte_array, byte_array->length());
     129      317130 :     for (Address addr = start; addr < end; addr += kTaggedSize) {
     130      306900 :       CHECK_EQ(filter.IsValid(addr), page->SweepingDone());
     131             :     }
     132             :   }
     133           5 : }
     134             : 
     135       28342 : HEAP_TEST(InvalidatedSlotsEvacuationCandidate) {
     136             :   ManualGCScope manual_gc_scope;
     137           5 :   CcTest::InitializeVM();
     138           5 :   Heap* heap = CcTest::heap();
     139             :   std::vector<ByteArray> byte_arrays;
     140           5 :   Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
     141           5 :   page->MarkEvacuationCandidate();
     142             :   // Register the all byte arrays as invalidated.
     143             :   // This should be no-op because the page is marked as evacuation
     144             :   // candidate.
     145       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
     146       10230 :     page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
     147       20460 :                                              byte_arrays[i]->Size());
     148             :   }
     149             :   // All slots must still be valid.
     150           5 :   InvalidatedSlotsFilter filter(page);
     151       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
     152       10230 :     ByteArray byte_array = byte_arrays[i];
     153       10230 :     Address start = byte_array->address() + ByteArray::kHeaderSize;
     154       10230 :     Address end = byte_array->address() + byte_array->Size();
     155      317130 :     for (Address addr = start; addr < end; addr += kTaggedSize) {
     156      306900 :       CHECK(filter.IsValid(addr));
     157             :     }
     158             :   }
     159           5 : }
     160             : 
     161       28342 : HEAP_TEST(InvalidatedSlotsResetObjectRegression) {
     162           5 :   CcTest::InitializeVM();
     163           5 :   Heap* heap = CcTest::heap();
     164             :   std::vector<ByteArray> byte_arrays;
     165           5 :   Page* page = AllocateByteArraysOnPage(heap, &byte_arrays);
     166             :   // Ensure that the first array has smaller size then the rest.
     167          10 :   heap->RightTrimFixedArray(byte_arrays[0], byte_arrays[0]->length() - 8);
     168             :   // Register the all byte arrays as invalidated.
     169       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
     170       10230 :     page->RegisterObjectWithInvalidatedSlots(byte_arrays[i],
     171       20460 :                                              byte_arrays[i]->Size());
     172             :   }
     173             :   // All slots must still be invalid.
     174           5 :   InvalidatedSlotsFilter filter(page);
     175       20470 :   for (size_t i = 0; i < byte_arrays.size(); i++) {
     176       10230 :     ByteArray byte_array = byte_arrays[i];
     177       10230 :     Address start = byte_array->address() + ByteArray::kHeaderSize;
     178       10230 :     Address end = byte_array->address() + byte_array->Size();
     179      316985 :     for (Address addr = start; addr < end; addr += kTaggedSize) {
     180      306755 :       CHECK(!filter.IsValid(addr));
     181             :     }
     182             :   }
     183           5 : }
     184             : 
     185          55 : Handle<FixedArray> AllocateArrayOnFreshPage(Isolate* isolate,
     186             :                                             PagedSpace* old_space, int length) {
     187             :   AlwaysAllocateScope always_allocate(isolate);
     188          55 :   heap::SimulateFullSpace(old_space);
     189         110 :   return isolate->factory()->NewFixedArray(length, TENURED);
     190             : }
     191             : 
     192          20 : Handle<FixedArray> AllocateArrayOnEvacuationCandidate(Isolate* isolate,
     193             :                                                       PagedSpace* old_space,
     194             :                                                       int length) {
     195             :   Handle<FixedArray> object =
     196          20 :       AllocateArrayOnFreshPage(isolate, old_space, length);
     197          20 :   heap::ForceEvacuationCandidate(Page::FromHeapObject(*object));
     198          20 :   return object;
     199             : }
     200             : 
     201       28342 : HEAP_TEST(InvalidatedSlotsRightTrimFixedArray) {
     202           5 :   FLAG_manual_evacuation_candidates_selection = true;
     203           5 :   FLAG_parallel_compaction = false;
     204             :   ManualGCScope manual_gc_scope;
     205           5 :   CcTest::InitializeVM();
     206             :   Isolate* isolate = CcTest::i_isolate();
     207             :   Factory* factory = isolate->factory();
     208          10 :   Heap* heap = CcTest::heap();
     209             :   HandleScope scope(isolate);
     210             :   PagedSpace* old_space = heap->old_space();
     211             :   // Allocate a dummy page to be swept be the sweeper during evacuation.
     212           5 :   AllocateArrayOnFreshPage(isolate, old_space, 1);
     213             :   Handle<FixedArray> evacuated =
     214           5 :       AllocateArrayOnEvacuationCandidate(isolate, old_space, 1);
     215           5 :   Handle<FixedArray> trimmed = AllocateArrayOnFreshPage(isolate, old_space, 10);
     216           5 :   heap::SimulateIncrementalMarking(heap);
     217         100 :   for (int i = 1; i < trimmed->length(); i++) {
     218          90 :     trimmed->set(i, *evacuated);
     219             :   }
     220             :   {
     221             :     HandleScope scope(isolate);
     222           5 :     Handle<HeapObject> dead = factory->NewFixedArray(1);
     223         100 :     for (int i = 1; i < trimmed->length(); i++) {
     224          90 :       trimmed->set(i, *dead);
     225             :     }
     226          10 :     heap->RightTrimFixedArray(*trimmed, trimmed->length() - 1);
     227             :   }
     228           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     229           5 :   CcTest::CollectGarbage(i::OLD_SPACE);
     230           5 : }
     231             : 
     232       28342 : HEAP_TEST(InvalidatedSlotsRightTrimLargeFixedArray) {
     233           5 :   FLAG_manual_evacuation_candidates_selection = true;
     234           5 :   FLAG_parallel_compaction = false;
     235             :   ManualGCScope manual_gc_scope;
     236           5 :   CcTest::InitializeVM();
     237             :   Isolate* isolate = CcTest::i_isolate();
     238             :   Factory* factory = isolate->factory();
     239          10 :   Heap* heap = CcTest::heap();
     240             :   HandleScope scope(isolate);
     241             :   PagedSpace* old_space = heap->old_space();
     242             :   // Allocate a dummy page to be swept be the sweeper during evacuation.
     243           5 :   AllocateArrayOnFreshPage(isolate, old_space, 1);
     244             :   Handle<FixedArray> evacuated =
     245           5 :       AllocateArrayOnEvacuationCandidate(isolate, old_space, 1);
     246             :   Handle<FixedArray> trimmed;
     247             :   {
     248             :     AlwaysAllocateScope always_allocate(isolate);
     249             :     trimmed = factory->NewFixedArray(
     250           5 :         kMaxRegularHeapObjectSize / kTaggedSize + 100, TENURED);
     251             :     DCHECK(MemoryChunk::FromHeapObject(*trimmed)->InLargeObjectSpace());
     252             :   }
     253           5 :   heap::SimulateIncrementalMarking(heap);
     254      634920 :   for (int i = 1; i < trimmed->length(); i++) {
     255      634910 :     trimmed->set(i, *evacuated);
     256             :   }
     257             :   {
     258             :     HandleScope scope(isolate);
     259           5 :     Handle<HeapObject> dead = factory->NewFixedArray(1);
     260      634920 :     for (int i = 1; i < trimmed->length(); i++) {
     261      634910 :       trimmed->set(i, *dead);
     262             :     }
     263          10 :     heap->RightTrimFixedArray(*trimmed, trimmed->length() - 1);
     264             :   }
     265           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     266           5 :   CcTest::CollectGarbage(i::OLD_SPACE);
     267           5 : }
     268             : 
     269       28342 : HEAP_TEST(InvalidatedSlotsLeftTrimFixedArray) {
     270           5 :   FLAG_manual_evacuation_candidates_selection = true;
     271           5 :   FLAG_parallel_compaction = false;
     272             :   ManualGCScope manual_gc_scope;
     273           5 :   CcTest::InitializeVM();
     274             :   Isolate* isolate = CcTest::i_isolate();
     275             :   Factory* factory = isolate->factory();
     276          10 :   Heap* heap = CcTest::heap();
     277             :   HandleScope scope(isolate);
     278             :   PagedSpace* old_space = heap->old_space();
     279             :   // Allocate a dummy page to be swept be the sweeper during evacuation.
     280           5 :   AllocateArrayOnFreshPage(isolate, old_space, 1);
     281             :   Handle<FixedArray> evacuated =
     282           5 :       AllocateArrayOnEvacuationCandidate(isolate, old_space, 1);
     283           5 :   Handle<FixedArray> trimmed = AllocateArrayOnFreshPage(isolate, old_space, 10);
     284           5 :   heap::SimulateIncrementalMarking(heap);
     285         105 :   for (int i = 0; i + 1 < trimmed->length(); i++) {
     286          90 :     trimmed->set(i, *evacuated);
     287             :   }
     288             :   {
     289             :     HandleScope scope(isolate);
     290           5 :     Handle<HeapObject> dead = factory->NewFixedArray(1);
     291         100 :     for (int i = 1; i < trimmed->length(); i++) {
     292          90 :       trimmed->set(i, *dead);
     293             :     }
     294          10 :     heap->LeftTrimFixedArray(*trimmed, trimmed->length() - 1);
     295             :   }
     296           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     297           5 :   CcTest::CollectGarbage(i::OLD_SPACE);
     298           5 : }
     299             : 
     300       28342 : HEAP_TEST(InvalidatedSlotsFastToSlow) {
     301           5 :   FLAG_manual_evacuation_candidates_selection = true;
     302           5 :   FLAG_parallel_compaction = false;
     303             :   ManualGCScope manual_gc_scope;
     304           5 :   CcTest::InitializeVM();
     305             :   Isolate* isolate = CcTest::i_isolate();
     306             :   Factory* factory = isolate->factory();
     307           5 :   Heap* heap = CcTest::heap();
     308             :   PagedSpace* old_space = heap->old_space();
     309             : 
     310             :   HandleScope scope(isolate);
     311             : 
     312           5 :   Handle<String> name = factory->InternalizeUtf8String("TestObject");
     313           5 :   Handle<String> prop_name1 = factory->InternalizeUtf8String("prop1");
     314           5 :   Handle<String> prop_name2 = factory->InternalizeUtf8String("prop2");
     315           5 :   Handle<String> prop_name3 = factory->InternalizeUtf8String("prop3");
     316             :   // Allocate a dummy page to be swept be the sweeper during evacuation.
     317           5 :   AllocateArrayOnFreshPage(isolate, old_space, 1);
     318             :   Handle<FixedArray> evacuated =
     319           5 :       AllocateArrayOnEvacuationCandidate(isolate, old_space, 1);
     320             :   // Allocate a dummy page to ensure that the JSObject is allocated on
     321             :   // a fresh page.
     322           5 :   AllocateArrayOnFreshPage(isolate, old_space, 1);
     323             :   Handle<JSObject> obj;
     324             :   {
     325             :     AlwaysAllocateScope always_allocate(isolate);
     326           5 :     Handle<JSFunction> function = factory->NewFunctionForTest(name);
     327          10 :     function->shared()->set_expected_nof_properties(3);
     328           5 :     obj = factory->NewJSObject(function, TENURED);
     329             :   }
     330             :   // Start incremental marking.
     331           5 :   heap::SimulateIncrementalMarking(heap);
     332             :   // Set properties to point to the evacuation candidate.
     333             :   Object::SetProperty(isolate, obj, prop_name1, evacuated,
     334           5 :                       LanguageMode::kSloppy)
     335          10 :       .Check();
     336             :   Object::SetProperty(isolate, obj, prop_name2, evacuated,
     337           5 :                       LanguageMode::kSloppy)
     338          10 :       .Check();
     339             :   Object::SetProperty(isolate, obj, prop_name3, evacuated,
     340           5 :                       LanguageMode::kSloppy)
     341          10 :       .Check();
     342             : 
     343             :   {
     344             :     HandleScope scope(isolate);
     345           5 :     Handle<HeapObject> dead = factory->NewFixedArray(1);
     346           5 :     Object::SetProperty(isolate, obj, prop_name1, dead, LanguageMode::kSloppy)
     347          10 :         .Check();
     348           5 :     Object::SetProperty(isolate, obj, prop_name2, dead, LanguageMode::kSloppy)
     349          10 :         .Check();
     350           5 :     Object::SetProperty(isolate, obj, prop_name3, dead, LanguageMode::kSloppy)
     351          10 :         .Check();
     352             :     Handle<Map> map(obj->map(), isolate);
     353             :     Handle<Map> normalized_map =
     354           5 :         Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, "testing");
     355           5 :     JSObject::MigrateToMap(obj, normalized_map);
     356             :   }
     357           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     358           5 :   CcTest::CollectGarbage(i::OLD_SPACE);
     359           5 : }
     360             : 
     361             : }  // namespace heap
     362             : }  // namespace internal
     363       85011 : }  // namespace v8

Generated by: LCOV version 1.10