LCOV - code coverage report
Current view: top level - test/cctest/heap - test-weak-references.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 372 374 99.5 %
Date: 2019-02-19 Functions: 21 21 100.0 %

          Line data    Source code
       1             : // Copyright 2018 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 "src/api-inl.h"
       6             : #include "src/assembler-inl.h"
       7             : #include "src/heap/factory.h"
       8             : #include "src/heap/heap-inl.h"
       9             : #include "src/isolate.h"
      10             : #include "src/objects/smi.h"
      11             : #include "test/cctest/cctest.h"
      12             : #include "test/cctest/heap/heap-tester.h"
      13             : #include "test/cctest/heap/heap-utils.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : namespace heap {
      18             : 
      19          40 : Handle<FeedbackVector> CreateFeedbackVectorForTest(
      20             :     v8::Isolate* isolate, Factory* factory,
      21             :     PretenureFlag pretenure_flag = NOT_TENURED) {
      22             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
      23             :   v8::Local<v8::Script> script =
      24             :       v8::Script::Compile(isolate->GetCurrentContext(),
      25             :                           v8::String::NewFromUtf8(isolate, "function foo() {}",
      26             :                                                   v8::NewStringType::kNormal)
      27          80 :                               .ToLocalChecked())
      28          40 :           .ToLocalChecked();
      29             :   Handle<Object> obj = v8::Utils::OpenHandle(*script);
      30             :   Handle<SharedFunctionInfo> shared_function =
      31          80 :       Handle<SharedFunctionInfo>(JSFunction::cast(*obj)->shared(), i_isolate);
      32             :   Handle<FeedbackVector> fv =
      33          40 :       factory->NewFeedbackVector(shared_function, pretenure_flag);
      34          40 :   return fv;
      35             : }
      36             : 
      37       25879 : TEST(WeakReferencesBasic) {
      38           4 :   CcTest::InitializeVM();
      39             :   Isolate* isolate = CcTest::i_isolate();
      40             :   Factory* factory = isolate->factory();
      41             :   HandleScope outer_scope(isolate);
      42             : 
      43             :   Handle<FeedbackVector> fv =
      44           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory);
      45           4 :   CHECK(Heap::InYoungGeneration(*fv));
      46             : 
      47           4 :   MaybeObject code_object = fv->optimized_code_weak_or_smi();
      48           4 :   CHECK(code_object->IsSmi());
      49           4 :   CcTest::CollectAllGarbage();
      50           4 :   CHECK(Heap::InYoungGeneration(*fv));
      51           8 :   CHECK_EQ(code_object, fv->optimized_code_weak_or_smi());
      52             : 
      53             :   {
      54             :     HandleScope inner_scope(isolate);
      55             : 
      56             :     // Create a new Code.
      57          16 :     Assembler assm(AssemblerOptions{});
      58           4 :     assm.nop();  // supported on all architectures
      59           4 :     CodeDesc desc;
      60             :     assm.GetCode(isolate, &desc);
      61             :     Handle<Code> code =
      62           8 :         isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
      63           8 :     CHECK(code->IsCode());
      64             : 
      65           8 :     fv->set_optimized_code_weak_or_smi(HeapObjectReference::Weak(*code));
      66           4 :     HeapObject code_heap_object;
      67           4 :     CHECK(fv->optimized_code_weak_or_smi()->GetHeapObjectIfWeak(
      68             :         &code_heap_object));
      69           8 :     CHECK_EQ(*code, code_heap_object);
      70             : 
      71           4 :     CcTest::CollectAllGarbage();
      72             : 
      73           4 :     CHECK(fv->optimized_code_weak_or_smi()->GetHeapObjectIfWeak(
      74             :         &code_heap_object));
      75           8 :     CHECK_EQ(*code, code_heap_object);
      76             :   }  // code will go out of scope.
      77             : 
      78           4 :   CcTest::CollectAllGarbage();
      79           4 :   CHECK(fv->optimized_code_weak_or_smi()->IsCleared());
      80           4 : }
      81             : 
      82       25879 : TEST(WeakReferencesOldToOld) {
      83             :   // Like WeakReferencesBasic, but the updated weak slot is in the old space,
      84             :   // and referring to an old space object.
      85             :   ManualGCScope manual_gc_scope;
      86           4 :   FLAG_manual_evacuation_candidates_selection = true;
      87           4 :   CcTest::InitializeVM();
      88             :   Isolate* isolate = CcTest::i_isolate();
      89             :   Factory* factory = isolate->factory();
      90          12 :   Heap* heap = isolate->heap();
      91             : 
      92             :   HandleScope outer_scope(isolate);
      93             :   Handle<FeedbackVector> fv =
      94           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory, TENURED);
      95           4 :   CHECK(heap->InOldSpace(*fv));
      96             : 
      97             :   // Create a new FixedArray which the FeedbackVector will point to.
      98           4 :   Handle<FixedArray> fixed_array = factory->NewFixedArray(1, TENURED);
      99           4 :   CHECK(heap->InOldSpace(*fixed_array));
     100           8 :   fv->set_optimized_code_weak_or_smi(HeapObjectReference::Weak(*fixed_array));
     101             : 
     102             :   Page* page_before_gc = Page::FromHeapObject(*fixed_array);
     103           4 :   heap::ForceEvacuationCandidate(page_before_gc);
     104           4 :   CcTest::CollectAllGarbage();
     105           4 :   CHECK(heap->InOldSpace(*fixed_array));
     106             : 
     107           4 :   HeapObject heap_object;
     108           4 :   CHECK(fv->optimized_code_weak_or_smi()->GetHeapObjectIfWeak(&heap_object));
     109           8 :   CHECK_EQ(heap_object, *fixed_array);
     110           4 : }
     111             : 
     112       25879 : TEST(WeakReferencesOldToNew) {
     113             :   // Like WeakReferencesBasic, but the updated weak slot is in the old space,
     114             :   // and referring to an new space object.
     115           4 :   CcTest::InitializeVM();
     116             :   Isolate* isolate = CcTest::i_isolate();
     117             :   Factory* factory = isolate->factory();
     118           4 :   Heap* heap = isolate->heap();
     119             : 
     120             :   HandleScope outer_scope(isolate);
     121             :   Handle<FeedbackVector> fv =
     122           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory, TENURED);
     123           4 :   CHECK(heap->InOldSpace(*fv));
     124             : 
     125             :   // Create a new FixedArray which the FeedbackVector will point to.
     126           4 :   Handle<FixedArray> fixed_array = factory->NewFixedArray(1);
     127           4 :   CHECK(Heap::InYoungGeneration(*fixed_array));
     128           8 :   fv->set_optimized_code_weak_or_smi(HeapObjectReference::Weak(*fixed_array));
     129             : 
     130           4 :   CcTest::CollectAllGarbage();
     131             : 
     132           4 :   HeapObject heap_object;
     133           4 :   CHECK(fv->optimized_code_weak_or_smi()->GetHeapObjectIfWeak(&heap_object));
     134           8 :   CHECK_EQ(heap_object, *fixed_array);
     135           4 : }
     136             : 
     137       25879 : TEST(WeakReferencesOldToNewScavenged) {
     138             :   // Like WeakReferencesBasic, but the updated weak slot is in the old space,
     139             :   // and referring to an new space object, which is then scavenged.
     140           4 :   CcTest::InitializeVM();
     141             :   Isolate* isolate = CcTest::i_isolate();
     142             :   Factory* factory = isolate->factory();
     143           4 :   Heap* heap = isolate->heap();
     144             : 
     145             :   HandleScope outer_scope(isolate);
     146             :   Handle<FeedbackVector> fv =
     147           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory, TENURED);
     148           4 :   CHECK(heap->InOldSpace(*fv));
     149             : 
     150             :   // Create a new FixedArray which the FeedbackVector will point to.
     151           4 :   Handle<FixedArray> fixed_array = factory->NewFixedArray(1);
     152           4 :   CHECK(Heap::InYoungGeneration(*fixed_array));
     153           8 :   fv->set_optimized_code_weak_or_smi(HeapObjectReference::Weak(*fixed_array));
     154             : 
     155           4 :   CcTest::CollectGarbage(NEW_SPACE);
     156             : 
     157           4 :   HeapObject heap_object;
     158           4 :   CHECK(fv->optimized_code_weak_or_smi()->GetHeapObjectIfWeak(&heap_object));
     159           8 :   CHECK_EQ(heap_object, *fixed_array);
     160           4 : }
     161             : 
     162       25879 : TEST(WeakReferencesOldToCleared) {
     163             :   // Like WeakReferencesBasic, but the updated weak slot is in the old space,
     164             :   // and is cleared.
     165             :   ManualGCScope manual_gc_scope;
     166           4 :   FLAG_manual_evacuation_candidates_selection = true;
     167           4 :   CcTest::InitializeVM();
     168             :   Isolate* isolate = CcTest::i_isolate();
     169             :   Factory* factory = isolate->factory();
     170           4 :   Heap* heap = isolate->heap();
     171             : 
     172             :   HandleScope outer_scope(isolate);
     173             :   Handle<FeedbackVector> fv =
     174           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory, TENURED);
     175           4 :   CHECK(heap->InOldSpace(*fv));
     176             :   fv->set_optimized_code_weak_or_smi(
     177           8 :       HeapObjectReference::ClearedValue(isolate));
     178             : 
     179           4 :   CcTest::CollectAllGarbage();
     180           4 :   CHECK(fv->optimized_code_weak_or_smi()->IsCleared());
     181           4 : }
     182             : 
     183       25879 : TEST(ObjectMovesBeforeClearingWeakField) {
     184           4 :   if (!FLAG_incremental_marking) {
     185           0 :     return;
     186             :   }
     187             :   ManualGCScope manual_gc_scope;
     188           4 :   CcTest::InitializeVM();
     189             :   Isolate* isolate = CcTest::i_isolate();
     190             :   Factory* factory = isolate->factory();
     191           4 :   Heap* heap = isolate->heap();
     192             : 
     193             :   HandleScope outer_scope(isolate);
     194             :   Handle<FeedbackVector> fv =
     195           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory);
     196           4 :   CHECK(Heap::InYoungGeneration(*fv));
     197           4 :   FeedbackVector fv_location = *fv;
     198             :   {
     199             :     HandleScope inner_scope(isolate);
     200             :     // Create a new FixedArray which the FeedbackVector will point to.
     201           4 :     Handle<FixedArray> fixed_array = factory->NewFixedArray(1);
     202           4 :     CHECK(Heap::InYoungGeneration(*fixed_array));
     203           8 :     fv->set_optimized_code_weak_or_smi(HeapObjectReference::Weak(*fixed_array));
     204             :     // inner_scope will go out of scope, so when marking the next time,
     205             :     // *fixed_array will stay white.
     206             :   }
     207             : 
     208             :   // Do marking steps; this will store *fv into the list for later processing
     209             :   // (since it points to a white object).
     210           4 :   SimulateIncrementalMarking(heap, true);
     211             : 
     212             :   // Scavenger will move *fv.
     213           4 :   CcTest::CollectGarbage(NEW_SPACE);
     214           4 :   FeedbackVector new_fv_location = *fv;
     215           4 :   CHECK_NE(fv_location, new_fv_location);
     216           4 :   CHECK(fv->optimized_code_weak_or_smi()->IsWeak());
     217             : 
     218             :   // Now we try to clear *fv.
     219           4 :   CcTest::CollectAllGarbage();
     220           4 :   CHECK(fv->optimized_code_weak_or_smi()->IsCleared());
     221             : }
     222             : 
     223       25879 : TEST(ObjectWithWeakFieldDies) {
     224           4 :   if (!FLAG_incremental_marking) {
     225           4 :     return;
     226             :   }
     227             :   ManualGCScope manual_gc_scope;
     228           4 :   CcTest::InitializeVM();
     229             :   Isolate* isolate = CcTest::i_isolate();
     230             :   Factory* factory = isolate->factory();
     231           4 :   Heap* heap = isolate->heap();
     232             : 
     233             :   {
     234             :     HandleScope outer_scope(isolate);
     235             :     Handle<FeedbackVector> fv =
     236           4 :         CreateFeedbackVectorForTest(CcTest::isolate(), factory);
     237           4 :     CHECK(Heap::InYoungGeneration(*fv));
     238             :     {
     239             :       HandleScope inner_scope(isolate);
     240             :       // Create a new FixedArray which the FeedbackVector will point to.
     241           4 :       Handle<FixedArray> fixed_array = factory->NewFixedArray(1);
     242           4 :       CHECK(Heap::InYoungGeneration(*fixed_array));
     243             :       fv->set_optimized_code_weak_or_smi(
     244           8 :           HeapObjectReference::Weak(*fixed_array));
     245             :       // inner_scope will go out of scope, so when marking the next time,
     246             :       // *fixed_array will stay white.
     247             :     }
     248             : 
     249             :     // Do marking steps; this will store *fv into the list for later processing
     250             :     // (since it points to a white object).
     251           4 :     SimulateIncrementalMarking(heap, true);
     252             :   }  // outer_scope goes out of scope
     253             : 
     254             :   // fv will die
     255           4 :   CcTest::CollectGarbage(NEW_SPACE);
     256             : 
     257             :   // This used to crash when processing the dead weak reference.
     258           4 :   CcTest::CollectAllGarbage();
     259             : }
     260             : 
     261       25879 : TEST(ObjectWithWeakReferencePromoted) {
     262           4 :   CcTest::InitializeVM();
     263             :   Isolate* isolate = CcTest::i_isolate();
     264             :   Factory* factory = isolate->factory();
     265           8 :   Heap* heap = isolate->heap();
     266             : 
     267             :   HandleScope outer_scope(isolate);
     268             :   Handle<FeedbackVector> fv =
     269           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory);
     270           4 :   CHECK(Heap::InYoungGeneration(*fv));
     271             : 
     272             :   // Create a new FixedArray which the FeedbackVector will point to.
     273           4 :   Handle<FixedArray> fixed_array = factory->NewFixedArray(1);
     274           4 :   CHECK(Heap::InYoungGeneration(*fixed_array));
     275           8 :   fv->set_optimized_code_weak_or_smi(HeapObjectReference::Weak(*fixed_array));
     276             : 
     277           4 :   CcTest::CollectGarbage(NEW_SPACE);
     278           4 :   CcTest::CollectGarbage(NEW_SPACE);
     279           4 :   CHECK(heap->InOldSpace(*fv));
     280           4 :   CHECK(heap->InOldSpace(*fixed_array));
     281             : 
     282           4 :   HeapObject heap_object;
     283           4 :   CHECK(fv->optimized_code_weak_or_smi()->GetHeapObjectIfWeak(&heap_object));
     284           8 :   CHECK_EQ(heap_object, *fixed_array);
     285           4 : }
     286             : 
     287       25879 : TEST(ObjectWithClearedWeakReferencePromoted) {
     288           4 :   CcTest::InitializeVM();
     289             :   Isolate* isolate = CcTest::i_isolate();
     290             :   Factory* factory = isolate->factory();
     291           4 :   Heap* heap = isolate->heap();
     292             : 
     293             :   HandleScope outer_scope(isolate);
     294             :   Handle<FeedbackVector> fv =
     295           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory);
     296           4 :   CHECK(Heap::InYoungGeneration(*fv));
     297             : 
     298             :   fv->set_optimized_code_weak_or_smi(
     299           8 :       HeapObjectReference::ClearedValue(isolate));
     300             : 
     301           4 :   CcTest::CollectGarbage(NEW_SPACE);
     302           4 :   CHECK(Heap::InYoungGeneration(*fv));
     303           4 :   CHECK(fv->optimized_code_weak_or_smi()->IsCleared());
     304             : 
     305           4 :   CcTest::CollectGarbage(NEW_SPACE);
     306           4 :   CHECK(heap->InOldSpace(*fv));
     307           4 :   CHECK(fv->optimized_code_weak_or_smi()->IsCleared());
     308             : 
     309           4 :   CcTest::CollectAllGarbage();
     310           4 :   CHECK(fv->optimized_code_weak_or_smi()->IsCleared());
     311           4 : }
     312             : 
     313       25879 : TEST(WeakReferenceWriteBarrier) {
     314           4 :   if (!FLAG_incremental_marking) {
     315           4 :     return;
     316             :   }
     317             : 
     318             :   ManualGCScope manual_gc_scope;
     319           4 :   CcTest::InitializeVM();
     320             :   Isolate* isolate = CcTest::i_isolate();
     321             :   Factory* factory = isolate->factory();
     322           4 :   Heap* heap = isolate->heap();
     323             : 
     324             :   HandleScope outer_scope(isolate);
     325             :   Handle<FeedbackVector> fv =
     326           4 :       CreateFeedbackVectorForTest(CcTest::isolate(), factory);
     327           4 :   CHECK(Heap::InYoungGeneration(*fv));
     328             : 
     329             :   {
     330             :     HandleScope inner_scope(isolate);
     331             : 
     332             :     // Create a new FixedArray which the FeedbackVector will point to.
     333           4 :     Handle<FixedArray> fixed_array1 = factory->NewFixedArray(1);
     334           4 :     CHECK(Heap::InYoungGeneration(*fixed_array1));
     335             :     fv->set_optimized_code_weak_or_smi(
     336           8 :         HeapObjectReference::Weak(*fixed_array1));
     337             : 
     338           4 :     SimulateIncrementalMarking(heap, true);
     339             : 
     340           4 :     Handle<FixedArray> fixed_array2 = factory->NewFixedArray(1);
     341           4 :     CHECK(Heap::InYoungGeneration(*fixed_array2));
     342             :     // This write will trigger the write barrier.
     343             :     fv->set_optimized_code_weak_or_smi(
     344           8 :         HeapObjectReference::Weak(*fixed_array2));
     345             :   }
     346             : 
     347           4 :   CcTest::CollectAllGarbage();
     348             : 
     349             :   // Check that the write barrier treated the weak reference as strong.
     350           4 :   CHECK(fv->optimized_code_weak_or_smi()->IsWeak());
     351             : }
     352             : 
     353       25880 : TEST(EmptyWeakArray) {
     354           5 :   CcTest::InitializeVM();
     355             :   Isolate* isolate = CcTest::i_isolate();
     356             :   Factory* factory = isolate->factory();
     357             :   HandleScope outer_scope(isolate);
     358             : 
     359             :   Handle<WeakFixedArray> array = factory->empty_weak_fixed_array();
     360          10 :   CHECK(array->IsWeakFixedArray());
     361          10 :   CHECK(!array->IsFixedArray());
     362           5 :   CHECK_EQ(array->length(), 0);
     363           5 : }
     364             : 
     365       25880 : TEST(WeakArraysBasic) {
     366             :   ManualGCScope manual_gc_scope;
     367           5 :   CcTest::InitializeVM();
     368             :   Isolate* isolate = CcTest::i_isolate();
     369             :   Factory* factory = isolate->factory();
     370          10 :   Heap* heap = isolate->heap();
     371             :   HandleScope outer_scope(isolate);
     372             : 
     373             :   const int length = 4;
     374           5 :   Handle<WeakFixedArray> array = factory->NewWeakFixedArray(length);
     375          10 :   CHECK(array->IsWeakFixedArray());
     376          10 :   CHECK(!array->IsFixedArray());
     377           5 :   CHECK_EQ(array->length(), length);
     378           5 :   CHECK(Heap::InYoungGeneration(*array));
     379             : 
     380          20 :   for (int i = 0; i < length; ++i) {
     381          20 :     HeapObject heap_object;
     382          20 :     CHECK(array->Get(i)->GetHeapObjectIfStrong(&heap_object));
     383          40 :     CHECK_EQ(heap_object, ReadOnlyRoots(heap).undefined_value());
     384             :   }
     385             : 
     386             :   Handle<HeapObject> saved;
     387             :   {
     388             :     HandleScope inner_scope(isolate);
     389           5 :     Handle<FixedArray> index0 = factory->NewFixedArray(1);
     390             :     index0->set(0, Smi::FromInt(2016));
     391           5 :     Handle<FixedArray> index1 = factory->NewFixedArray(1);
     392             :     index1->set(0, Smi::FromInt(2017));
     393             : 
     394           5 :     Handle<FixedArray> index2 = factory->NewFixedArray(1);
     395             :     index2->set(0, Smi::FromInt(2018));
     396           5 :     Handle<FixedArray> index3 = factory->NewFixedArray(1);
     397             :     index3->set(0, Smi::FromInt(2019));
     398             : 
     399          10 :     array->Set(0, HeapObjectReference::Weak(*index0));
     400          10 :     array->Set(1, HeapObjectReference::Weak(*index1));
     401          10 :     array->Set(2, HeapObjectReference::Strong(*index2));
     402          10 :     array->Set(3, HeapObjectReference::Weak(*index3));
     403           5 :     saved = inner_scope.CloseAndEscape(index1);
     404             :   }  // inner_scope goes out of scope.
     405             : 
     406             :   // The references are only cleared by the mark-compact (scavenger treats weak
     407             :   // references as strong). Thus we need to GC until the array reaches old
     408             :   // space.
     409             : 
     410             :   // TODO(marja): update this when/if we do handle weak references in the new
     411             :   // space.
     412           5 :   CcTest::CollectGarbage(NEW_SPACE);
     413           5 :   HeapObject heap_object;
     414           5 :   CHECK(array->Get(0)->GetHeapObjectIfWeak(&heap_object));
     415           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2016);
     416           5 :   CHECK(array->Get(1)->GetHeapObjectIfWeak(&heap_object));
     417           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2017);
     418           5 :   CHECK(array->Get(2)->GetHeapObjectIfStrong(&heap_object));
     419           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2018);
     420           5 :   CHECK(array->Get(3)->GetHeapObjectIfWeak(&heap_object));
     421           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2019);
     422             : 
     423           5 :   CcTest::CollectAllGarbage();
     424           5 :   CHECK(heap->InOldSpace(*array));
     425          10 :   CHECK(array->Get(0)->IsCleared());
     426           5 :   CHECK(array->Get(1)->GetHeapObjectIfWeak(&heap_object));
     427           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2017);
     428           5 :   CHECK(array->Get(2)->GetHeapObjectIfStrong(&heap_object));
     429           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2018);
     430          10 :   CHECK(array->Get(3)->IsCleared());
     431           5 : }
     432             : 
     433       25880 : TEST(WeakArrayListBasic) {
     434             :   ManualGCScope manual_gc_scope;
     435           5 :   CcTest::InitializeVM();
     436             :   Isolate* isolate = CcTest::i_isolate();
     437             :   Factory* factory = isolate->factory();
     438          10 :   Heap* heap = isolate->heap();
     439             :   HandleScope outer_scope(isolate);
     440             : 
     441             :   Handle<WeakArrayList> array(ReadOnlyRoots(heap).empty_weak_array_list(),
     442             :                               isolate);
     443          10 :   CHECK(array->IsWeakArrayList());
     444          10 :   CHECK(!array->IsFixedArray());
     445          10 :   CHECK(!array->IsWeakFixedArray());
     446           5 :   CHECK_EQ(array->length(), 0);
     447             : 
     448           5 :   Handle<FixedArray> index2 = factory->NewFixedArray(1);
     449             :   index2->set(0, Smi::FromInt(2017));
     450             : 
     451             :   Handle<HeapObject> saved;
     452             :   {
     453             :     HandleScope inner_scope(isolate);
     454           5 :     Handle<FixedArray> index0 = factory->NewFixedArray(1);
     455             :     index0->set(0, Smi::FromInt(2016));
     456           5 :     Handle<FixedArray> index4 = factory->NewFixedArray(1);
     457             :     index4->set(0, Smi::FromInt(2018));
     458           5 :     Handle<FixedArray> index6 = factory->NewFixedArray(1);
     459             :     index6->set(0, Smi::FromInt(2019));
     460             : 
     461             :     array = WeakArrayList::AddToEnd(isolate, array,
     462           5 :                                     MaybeObjectHandle::Weak(index0));
     463             :     array = WeakArrayList::AddToEnd(
     464           5 :         isolate, array, MaybeObjectHandle(Smi::FromInt(1), isolate));
     465           5 :     CHECK_EQ(array->length(), 2);
     466             : 
     467             :     array = WeakArrayList::AddToEnd(isolate, array,
     468           5 :                                     MaybeObjectHandle::Weak(index2));
     469             :     array = WeakArrayList::AddToEnd(
     470           5 :         isolate, array, MaybeObjectHandle(Smi::FromInt(3), isolate));
     471           5 :     CHECK_EQ(array->length(), 4);
     472             : 
     473             :     array = WeakArrayList::AddToEnd(isolate, array,
     474           5 :                                     MaybeObjectHandle::Weak(index4));
     475             :     array = WeakArrayList::AddToEnd(
     476           5 :         isolate, array, MaybeObjectHandle(Smi::FromInt(5), isolate));
     477           5 :     CHECK_EQ(array->length(), 6);
     478             : 
     479             :     array = WeakArrayList::AddToEnd(isolate, array,
     480           5 :                                     MaybeObjectHandle::Weak(index6));
     481             :     array = WeakArrayList::AddToEnd(
     482           5 :         isolate, array, MaybeObjectHandle(Smi::FromInt(7), isolate));
     483           5 :     CHECK_EQ(array->length(), 8);
     484             : 
     485           5 :     CHECK(Heap::InYoungGeneration(*array));
     486             : 
     487          15 :     CHECK_EQ(array->Get(0), HeapObjectReference::Weak(*index0));
     488          10 :     CHECK_EQ(array->Get(1).ToSmi().value(), 1);
     489             : 
     490          15 :     CHECK_EQ(array->Get(2), HeapObjectReference::Weak(*index2));
     491          10 :     CHECK_EQ(array->Get(3).ToSmi().value(), 3);
     492             : 
     493          15 :     CHECK_EQ(array->Get(4), HeapObjectReference::Weak(*index4));
     494          10 :     CHECK_EQ(array->Get(5).ToSmi().value(), 5);
     495             : 
     496          15 :     CHECK_EQ(array->Get(6), HeapObjectReference::Weak(*index6));
     497           5 :     array = inner_scope.CloseAndEscape(array);
     498             :   }  // inner_scope goes out of scope.
     499             : 
     500             :   // The references are only cleared by the mark-compact (scavenger treats weak
     501             :   // references as strong). Thus we need to GC until the array reaches old
     502             :   // space.
     503             : 
     504             :   // TODO(marja): update this when/if we do handle weak references in the new
     505             :   // space.
     506           5 :   CcTest::CollectGarbage(NEW_SPACE);
     507           5 :   HeapObject heap_object;
     508           5 :   CHECK_EQ(array->length(), 8);
     509           5 :   CHECK(array->Get(0)->GetHeapObjectIfWeak(&heap_object));
     510           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2016);
     511          10 :   CHECK_EQ(array->Get(1).ToSmi().value(), 1);
     512             : 
     513           5 :   CHECK(array->Get(2)->GetHeapObjectIfWeak(&heap_object));
     514           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2017);
     515          10 :   CHECK_EQ(array->Get(3).ToSmi().value(), 3);
     516             : 
     517           5 :   CHECK(array->Get(4)->GetHeapObjectIfWeak(&heap_object));
     518           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2018);
     519          10 :   CHECK_EQ(array->Get(5).ToSmi().value(), 5);
     520             : 
     521           5 :   CHECK(array->Get(6)->GetHeapObjectIfWeak(&heap_object));
     522           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2019);
     523          10 :   CHECK_EQ(array->Get(7).ToSmi().value(), 7);
     524             : 
     525           5 :   CcTest::CollectAllGarbage();
     526           5 :   CHECK(heap->InOldSpace(*array));
     527           5 :   CHECK_EQ(array->length(), 8);
     528          10 :   CHECK(array->Get(0)->IsCleared());
     529          10 :   CHECK_EQ(array->Get(1).ToSmi().value(), 1);
     530             : 
     531           5 :   CHECK(array->Get(2)->GetHeapObjectIfWeak(&heap_object));
     532           5 :   CHECK_EQ(Smi::cast(FixedArray::cast(heap_object)->get(0))->value(), 2017);
     533          10 :   CHECK_EQ(array->Get(3).ToSmi().value(), 3);
     534             : 
     535          10 :   CHECK(array->Get(4)->IsCleared());
     536          10 :   CHECK_EQ(array->Get(5).ToSmi().value(), 5);
     537             : 
     538          10 :   CHECK(array->Get(6)->IsCleared());
     539          10 :   CHECK_EQ(array->Get(7).ToSmi().value(), 7);
     540           5 : }
     541             : 
     542       25880 : TEST(WeakArrayListRemove) {
     543             :   ManualGCScope manual_gc_scope;
     544           5 :   CcTest::InitializeVM();
     545             :   Isolate* isolate = CcTest::i_isolate();
     546             :   Factory* factory = isolate->factory();
     547           5 :   Heap* heap = isolate->heap();
     548             :   HandleScope outer_scope(isolate);
     549             : 
     550             :   Handle<WeakArrayList> array(ReadOnlyRoots(heap).empty_weak_array_list(),
     551             :                               isolate);
     552             : 
     553           5 :   Handle<FixedArray> elem0 = factory->NewFixedArray(1);
     554           5 :   Handle<FixedArray> elem1 = factory->NewFixedArray(1);
     555           5 :   Handle<FixedArray> elem2 = factory->NewFixedArray(1);
     556             : 
     557             :   array =
     558           5 :       WeakArrayList::AddToEnd(isolate, array, MaybeObjectHandle::Weak(elem0));
     559             :   array =
     560           5 :       WeakArrayList::AddToEnd(isolate, array, MaybeObjectHandle::Weak(elem1));
     561             :   array =
     562           5 :       WeakArrayList::AddToEnd(isolate, array, MaybeObjectHandle::Weak(elem2));
     563             : 
     564           5 :   CHECK_EQ(array->length(), 3);
     565          15 :   CHECK_EQ(array->Get(0), HeapObjectReference::Weak(*elem0));
     566          15 :   CHECK_EQ(array->Get(1), HeapObjectReference::Weak(*elem1));
     567          15 :   CHECK_EQ(array->Get(2), HeapObjectReference::Weak(*elem2));
     568             : 
     569          10 :   CHECK(array->RemoveOne(MaybeObjectHandle::Weak(elem1)));
     570             : 
     571           5 :   CHECK_EQ(array->length(), 2);
     572          15 :   CHECK_EQ(array->Get(0), HeapObjectReference::Weak(*elem0));
     573          15 :   CHECK_EQ(array->Get(1), HeapObjectReference::Weak(*elem2));
     574             : 
     575          10 :   CHECK(!array->RemoveOne(MaybeObjectHandle::Weak(elem1)));
     576             : 
     577           5 :   CHECK_EQ(array->length(), 2);
     578          15 :   CHECK_EQ(array->Get(0), HeapObjectReference::Weak(*elem0));
     579          15 :   CHECK_EQ(array->Get(1), HeapObjectReference::Weak(*elem2));
     580             : 
     581          10 :   CHECK(array->RemoveOne(MaybeObjectHandle::Weak(elem0)));
     582             : 
     583           5 :   CHECK_EQ(array->length(), 1);
     584          15 :   CHECK_EQ(array->Get(0), HeapObjectReference::Weak(*elem2));
     585             : 
     586          10 :   CHECK(array->RemoveOne(MaybeObjectHandle::Weak(elem2)));
     587             : 
     588           5 :   CHECK_EQ(array->length(), 0);
     589           5 : }
     590             : 
     591       25880 : TEST(Regress7768) {
     592           5 :   i::FLAG_allow_natives_syntax = true;
     593           5 :   i::FLAG_turbo_inlining = false;
     594           5 :   if (!FLAG_incremental_marking) {
     595           0 :     return;
     596             :   }
     597             :   ManualGCScope manual_gc_scope;
     598           5 :   CcTest::InitializeVM();
     599          10 :   LocalContext context;
     600             :   Isolate* isolate = CcTest::i_isolate();
     601           5 :   Heap* heap = isolate->heap();
     602             :   HandleScope outer_scope(isolate);
     603             :   // Create an optimized code which will contain a weak reference to another
     604             :   // function ("f"). The weak reference is the only reference to the function.
     605             :   CompileRun(
     606             :       "function myfunc(f) { f(); } "
     607             :       "(function wrapper() { "
     608             :       "   function f() {}; myfunc(f); myfunc(f); "
     609             :       "   %OptimizeFunctionOnNextCall(myfunc); myfunc(f); "
     610             :       "   %ClearFunctionFeedback(wrapper);"
     611             :       "})(); "
     612             :       "%ClearFunctionFeedback(myfunc);");
     613             : 
     614             :   // Do marking steps; this will store the objects pointed by myfunc for later
     615             :   // processing.
     616           5 :   SimulateIncrementalMarking(heap, true);
     617             : 
     618             :   // Deoptimize the code; now the pointers inside it will be replaced with
     619             :   // undefined, and the weak_objects_in_code is the only place pointing to the
     620             :   // function f.
     621             :   CompileRun("%DeoptimizeFunction(myfunc);");
     622             : 
     623             :   // The object pointed to by the weak reference won't be scavenged.
     624           5 :   CcTest::CollectGarbage(NEW_SPACE);
     625             : 
     626             :   // Make sure the memory where it's stored is invalidated, so that we'll crash
     627             :   // if we try to access it.
     628           5 :   HeapTester::UncommitFromSpace(heap);
     629             : 
     630             :   // This used to crash when processing the dead weak reference.
     631           5 :   CcTest::CollectAllGarbage();
     632             : }
     633             : 
     634       25880 : TEST(PrototypeUsersBasic) {
     635           5 :   CcTest::InitializeVM();
     636           5 :   LocalContext context;
     637             :   Isolate* isolate = CcTest::i_isolate();
     638             :   Factory* factory = isolate->factory();
     639           5 :   Heap* heap = isolate->heap();
     640             :   HandleScope outer_scope(isolate);
     641             : 
     642             :   Handle<WeakArrayList> array(ReadOnlyRoots(heap).empty_weak_array_list(),
     643             :                               isolate);
     644             : 
     645             :   // Add some objects into the array.
     646           5 :   int index = -1;
     647             :   {
     648           5 :     Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     649           5 :     array = PrototypeUsers::Add(isolate, array, map, &index);
     650          10 :     CHECK_EQ(array->length(), index + 1);
     651             :   }
     652           5 :   CHECK_EQ(index, 1);
     653             : 
     654             :   int empty_index = index;
     655           5 :   PrototypeUsers::MarkSlotEmpty(*array, empty_index);
     656             : 
     657             :   // Even though we have an empty slot, we still add to the end.
     658           5 :   int last_index = index;
     659             :   int old_capacity = array->capacity();
     660          20 :   while (!array->IsFull()) {
     661          10 :     Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     662          10 :     array = PrototypeUsers::Add(isolate, array, map, &index);
     663          10 :     CHECK_EQ(index, last_index + 1);
     664          20 :     CHECK_EQ(array->length(), index + 1);
     665          10 :     last_index = index;
     666             :   }
     667             : 
     668             :   // The next addition will fill the empty slot.
     669             :   {
     670           5 :     Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     671           5 :     array = PrototypeUsers::Add(isolate, array, map, &index);
     672             :   }
     673           5 :   CHECK_EQ(index, empty_index);
     674             : 
     675             :   // The next addition will make the arrow grow again.
     676             :   {
     677           5 :     Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     678           5 :     array = PrototypeUsers::Add(isolate, array, map, &index);
     679          10 :     CHECK_EQ(array->length(), index + 1);
     680           5 :     last_index = index;
     681             :   }
     682           5 :   CHECK_GT(array->capacity(), old_capacity);
     683             : 
     684             :   // Make multiple slots empty.
     685             :   int empty_index1 = 1;
     686             :   int empty_index2 = 2;
     687           5 :   PrototypeUsers::MarkSlotEmpty(*array, empty_index1);
     688           5 :   PrototypeUsers::MarkSlotEmpty(*array, empty_index2);
     689             : 
     690             :   // Fill the array (still adding to the end)
     691             :   old_capacity = array->capacity();
     692          20 :   while (!array->IsFull()) {
     693          10 :     Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     694          10 :     array = PrototypeUsers::Add(isolate, array, map, &index);
     695          10 :     CHECK_EQ(index, last_index + 1);
     696          20 :     CHECK_EQ(array->length(), index + 1);
     697          10 :     last_index = index;
     698             :   }
     699             : 
     700             :   // Make sure we use the empty slots in (reverse) order.
     701             :   {
     702           5 :     Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     703           5 :     array = PrototypeUsers::Add(isolate, array, map, &index);
     704             :   }
     705           5 :   CHECK_EQ(index, empty_index2);
     706             : 
     707             :   {
     708           5 :     Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     709           5 :     array = PrototypeUsers::Add(isolate, array, map, &index);
     710             :   }
     711          10 :   CHECK_EQ(index, empty_index1);
     712           5 : }
     713             : 
     714             : namespace {
     715             : 
     716             : HeapObject saved_heap_object;
     717             : 
     718           5 : static void TestCompactCallback(HeapObject value, int old_index,
     719             :                                 int new_index) {
     720           5 :   saved_heap_object = value;
     721           5 :   CHECK_EQ(old_index, 2);
     722           5 :   CHECK_EQ(new_index, 1);
     723           5 : }
     724             : 
     725             : }  // namespace
     726             : 
     727       25880 : TEST(PrototypeUsersCompacted) {
     728             :   ManualGCScope manual_gc_scope;
     729           5 :   CcTest::InitializeVM();
     730          10 :   LocalContext context;
     731             :   Isolate* isolate = CcTest::i_isolate();
     732             :   Factory* factory = isolate->factory();
     733           5 :   Heap* heap = isolate->heap();
     734             :   HandleScope outer_scope(isolate);
     735             : 
     736             :   Handle<WeakArrayList> array(ReadOnlyRoots(heap).empty_weak_array_list(),
     737             :                               isolate);
     738             : 
     739             :   // Add some objects into the array.
     740           5 :   int index = -1;
     741             :   Handle<Map> map_cleared_by_user =
     742           5 :       factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     743           5 :   array = PrototypeUsers::Add(isolate, array, map_cleared_by_user, &index);
     744           5 :   CHECK_EQ(index, 1);
     745           5 :   Handle<Map> live_map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     746           5 :   array = PrototypeUsers::Add(isolate, array, live_map, &index);
     747           5 :   CHECK_EQ(index, 2);
     748             :   {
     749             :     HandleScope inner_scope(isolate);
     750             :     Handle<Map> soon_dead_map =
     751           5 :         factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     752           5 :     array = PrototypeUsers::Add(isolate, array, soon_dead_map, &index);
     753           5 :     CHECK_EQ(index, 3);
     754             : 
     755           5 :     array = inner_scope.CloseAndEscape(array);
     756             :   }
     757             : 
     758           5 :   PrototypeUsers::MarkSlotEmpty(*array, 1);
     759           5 :   CcTest::CollectAllGarbage();
     760          10 :   CHECK(array->Get(3)->IsCleared());
     761             : 
     762           5 :   CHECK_EQ(array->length(), 3 + PrototypeUsers::kFirstIndex);
     763             :   WeakArrayList new_array =
     764           5 :       PrototypeUsers::Compact(array, heap, TestCompactCallback);
     765           5 :   CHECK_EQ(new_array->length(), 1 + PrototypeUsers::kFirstIndex);
     766          10 :   CHECK_EQ(saved_heap_object, *live_map);
     767           5 : }
     768             : 
     769             : }  // namespace heap
     770             : }  // namespace internal
     771       77625 : }  // namespace v8

Generated by: LCOV version 1.10