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

Generated by: LCOV version 1.10