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

Generated by: LCOV version 1.10