LCOV - code coverage report
Current view: top level - src/heap - store-buffer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 78 80 97.5 %
Date: 2017-10-20 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright 2011 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/heap/store-buffer.h"
       6             : 
       7             : #include <algorithm>
       8             : 
       9             : #include "src/base/macros.h"
      10             : #include "src/counters.h"
      11             : #include "src/heap/incremental-marking.h"
      12             : #include "src/isolate.h"
      13             : #include "src/objects-inl.h"
      14             : #include "src/v8.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19       54999 : StoreBuffer::StoreBuffer(Heap* heap)
      20       54999 :     : heap_(heap), top_(nullptr), current_(0), mode_(NOT_IN_GC) {
      21      164997 :   for (int i = 0; i < kStoreBuffers; i++) {
      22      109998 :     start_[i] = nullptr;
      23      109998 :     limit_[i] = nullptr;
      24      109998 :     lazy_top_[i] = nullptr;
      25             :   }
      26       54999 :   task_running_ = false;
      27       54999 :   insertion_callback = &InsertDuringRuntime;
      28       54999 :   deletion_callback = &DeleteDuringRuntime;
      29       54999 : }
      30             : 
      31       54999 : void StoreBuffer::SetUp() {
      32             :   // Allocate 3x the buffer size, so that we can start the new store buffer
      33             :   // aligned to 2x the size.  This lets us use a bit test to detect the end of
      34             :   // the area.
      35       54999 :   VirtualMemory reservation;
      36       54999 :   if (!AllocVirtualMemory(kStoreBufferSize * 3, heap_->GetRandomMmapAddr(),
      37       54999 :                           &reservation)) {
      38           0 :     V8::FatalProcessOutOfMemory("StoreBuffer::SetUp");
      39             :   }
      40       54999 :   uintptr_t start_as_int = reinterpret_cast<uintptr_t>(reservation.address());
      41             :   start_[0] =
      42       54999 :       reinterpret_cast<Address*>(::RoundUp(start_as_int, kStoreBufferSize));
      43       54999 :   limit_[0] = start_[0] + (kStoreBufferSize / kPointerSize);
      44       54999 :   start_[1] = limit_[0];
      45       54999 :   limit_[1] = start_[1] + (kStoreBufferSize / kPointerSize);
      46             : 
      47             :   Address* vm_limit = reinterpret_cast<Address*>(
      48             :       reinterpret_cast<char*>(reservation.address()) + reservation.size());
      49             : 
      50             :   USE(vm_limit);
      51             :   for (int i = 0; i < kStoreBuffers; i++) {
      52             :     DCHECK(reinterpret_cast<Address>(start_[i]) >= reservation.address());
      53             :     DCHECK(reinterpret_cast<Address>(limit_[i]) >= reservation.address());
      54             :     DCHECK(start_[i] <= vm_limit);
      55             :     DCHECK(limit_[i] <= vm_limit);
      56             :     DCHECK_EQ(0, reinterpret_cast<uintptr_t>(limit_[i]) & kStoreBufferMask);
      57             :   }
      58             : 
      59       54999 :   if (!reservation.Commit(reinterpret_cast<Address>(start_[0]),
      60             :                           kStoreBufferSize * kStoreBuffers,
      61       54999 :                           false)) {  // Not executable.
      62           0 :     V8::FatalProcessOutOfMemory("StoreBuffer::SetUp");
      63             :   }
      64       54999 :   current_ = 0;
      65       54999 :   top_ = start_[current_];
      66       54999 :   virtual_memory_.TakeControl(&reservation);
      67       54999 : }
      68             : 
      69             : 
      70       53365 : void StoreBuffer::TearDown() {
      71       53365 :   if (virtual_memory_.IsReserved()) virtual_memory_.Release();
      72       53365 :   top_ = nullptr;
      73      160095 :   for (int i = 0; i < kStoreBuffers; i++) {
      74      106730 :     start_[i] = nullptr;
      75      106730 :     limit_[i] = nullptr;
      76      106730 :     lazy_top_[i] = nullptr;
      77             :   }
      78       53365 : }
      79             : 
      80       85008 : int StoreBuffer::StoreBufferOverflow(Isolate* isolate) {
      81       85008 :   isolate->heap()->store_buffer()->FlipStoreBuffers();
      82       85008 :   isolate->counters()->store_buffer_overflows()->Increment();
      83             :   // Called by RecordWriteCodeStubAssembler, which doesnt accept void type
      84       85008 :   return 0;
      85             : }
      86             : 
      87       85008 : void StoreBuffer::FlipStoreBuffers() {
      88       85008 :   base::LockGuard<base::Mutex> guard(&mutex_);
      89       85008 :   int other = (current_ + 1) % kStoreBuffers;
      90       85008 :   MoveEntriesToRememberedSet(other);
      91       85008 :   lazy_top_[current_] = top_;
      92       85008 :   current_ = other;
      93       85008 :   top_ = start_[current_];
      94             : 
      95       85008 :   if (!task_running_ && FLAG_concurrent_store_buffer) {
      96       79556 :     task_running_ = true;
      97      159112 :     Task* task = new Task(heap_->isolate(), this);
      98       79556 :     V8::GetCurrentPlatform()->CallOnBackgroundThread(
      99       79556 :         task, v8::Platform::kShortRunningTask);
     100             :   }
     101       85008 : }
     102             : 
     103      337457 : void StoreBuffer::MoveEntriesToRememberedSet(int index) {
     104      674911 :   if (!lazy_top_[index]) return;
     105             :   DCHECK_GE(index, 0);
     106             :   DCHECK_LT(index, kStoreBuffers);
     107             :   Address last_inserted_addr = nullptr;
     108   202358378 :   for (Address* current = start_[index]; current < lazy_top_[index];
     109             :        current++) {
     110   202186928 :     Address addr = *current;
     111   202186928 :     Page* page = Page::FromAnyPointerAddress(heap_, addr);
     112   202186920 :     if (IsDeletionAddress(addr)) {
     113             :       last_inserted_addr = nullptr;
     114       30336 :       current++;
     115       30336 :       Address end = *current;
     116             :       DCHECK(!IsDeletionAddress(end));
     117             :       addr = UnmarkDeletionAddress(addr);
     118       30336 :       if (end) {
     119             :         RememberedSet<OLD_TO_NEW>::RemoveRange(page, addr, end,
     120       29766 :                                                SlotSet::PREFREE_EMPTY_BUCKETS);
     121             :       } else {
     122         570 :         RememberedSet<OLD_TO_NEW>::Remove(page, addr);
     123             :       }
     124             :     } else {
     125             :       DCHECK(!IsDeletionAddress(addr));
     126   202156584 :       if (addr != last_inserted_addr) {
     127   151737249 :         RememberedSet<OLD_TO_NEW>::Insert(page, addr);
     128             :         last_inserted_addr = addr;
     129             :       }
     130             :     }
     131             :   }
     132      171450 :   lazy_top_[index] = nullptr;
     133             : }
     134             : 
     135       86452 : void StoreBuffer::MoveAllEntriesToRememberedSet() {
     136       86452 :   base::LockGuard<base::Mutex> guard(&mutex_);
     137       86452 :   int other = (current_ + 1) % kStoreBuffers;
     138       86452 :   MoveEntriesToRememberedSet(other);
     139       86452 :   lazy_top_[current_] = top_;
     140       86452 :   MoveEntriesToRememberedSet(current_);
     141       86452 :   top_ = start_[current_];
     142       86452 : }
     143             : 
     144       79545 : void StoreBuffer::ConcurrentlyProcessStoreBuffer() {
     145       79545 :   base::LockGuard<base::Mutex> guard(&mutex_);
     146       79545 :   int other = (current_ + 1) % kStoreBuffers;
     147       79545 :   MoveEntriesToRememberedSet(other);
     148       79545 :   task_running_ = false;
     149       79545 : }
     150             : 
     151             : }  // namespace internal
     152             : }  // namespace v8

Generated by: LCOV version 1.10