LCOV - code coverage report
Current view: top level - src/heap - store-buffer.h (source / functions) Hit Total Coverage
Test: app.info Lines: 12 12 100.0 %
Date: 2019-02-19 Functions: 2 3 66.7 %

          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             : #ifndef V8_HEAP_STORE_BUFFER_H_
       6             : #define V8_HEAP_STORE_BUFFER_H_
       7             : 
       8             : #include "src/allocation.h"
       9             : #include "src/base/logging.h"
      10             : #include "src/base/platform/platform.h"
      11             : #include "src/cancelable-task.h"
      12             : #include "src/globals.h"
      13             : #include "src/heap/gc-tracer.h"
      14             : #include "src/heap/remembered-set.h"
      15             : #include "src/heap/slot-set.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : // Intermediate buffer that accumulates old-to-new stores from the generated
      21             : // code. Moreover, it stores invalid old-to-new slots with two entries.
      22             : // The first is a tagged address of the start of the invalid range, the second
      23             : // one is the end address of the invalid range or null if there is just one slot
      24             : // that needs to be removed from the remembered set. On buffer overflow the
      25             : // slots are moved to the remembered set.
      26             : // Store buffer entries are always full pointers.
      27       61034 : class StoreBuffer {
      28             :  public:
      29             :   enum StoreBufferMode { IN_GC, NOT_IN_GC };
      30             : 
      31             :   static const int kStoreBuffers = 2;
      32             :   static const int kStoreBufferSize =
      33             :       Max(static_cast<int>(kMinExpectedOSPageSize / kStoreBuffers),
      34             :           1 << (11 + kSystemPointerSizeLog2));
      35             :   static const int kStoreBufferMask = kStoreBufferSize - 1;
      36             :   static const intptr_t kDeletionTag = 1;
      37             : 
      38             :   V8_EXPORT_PRIVATE static int StoreBufferOverflow(Isolate* isolate);
      39             : 
      40             :   static void DeleteDuringGarbageCollection(StoreBuffer* store_buffer,
      41             :                                             Address start, Address end);
      42             :   static void InsertDuringGarbageCollection(StoreBuffer* store_buffer,
      43             :                                             Address slot);
      44             : 
      45             :   static void DeleteDuringRuntime(StoreBuffer* store_buffer, Address start,
      46             :                                   Address end);
      47             :   static void InsertDuringRuntime(StoreBuffer* store_buffer, Address slot);
      48             : 
      49             :   explicit StoreBuffer(Heap* heap);
      50             :   void SetUp();
      51             :   void TearDown();
      52             : 
      53             :   // Used to add entries from generated code.
      54             :   inline Address* top_address() { return reinterpret_cast<Address*>(&top_); }
      55             : 
      56             :   // Moves entries from a specific store buffer to the remembered set. This
      57             :   // method takes a lock.
      58             :   void MoveEntriesToRememberedSet(int index);
      59             : 
      60             :   // This method ensures that all used store buffer entries are transferred to
      61             :   // the remembered set.
      62             :   void MoveAllEntriesToRememberedSet();
      63             : 
      64             :   inline bool IsDeletionAddress(Address address) const {
      65   181759381 :     return address & kDeletionTag;
      66             :   }
      67             : 
      68             :   inline Address MarkDeletionAddress(Address address) {
      69       17151 :     return address | kDeletionTag;
      70             :   }
      71             : 
      72             :   inline Address UnmarkDeletionAddress(Address address) {
      73       12149 :     return address & ~kDeletionTag;
      74             :   }
      75             : 
      76             :   inline void InsertDeletionIntoStoreBuffer(Address start, Address end);
      77             :   inline void InsertIntoStoreBuffer(Address slot);
      78             : 
      79             :   void InsertEntry(Address slot) {
      80             :     // Insertions coming from the GC are directly inserted into the remembered
      81             :     // set. Insertions coming from the runtime are added to the store buffer to
      82             :     // allow concurrent processing.
      83   111939470 :     insertion_callback(this, slot);
      84             :   }
      85             : 
      86             :   // If we only want to delete a single slot, end should be set to null which
      87             :   // will be written into the second field. When processing the store buffer
      88             :   // the more efficient Remove method will be called in this case.
      89             :   void DeleteEntry(Address start, Address end = kNullAddress) {
      90             :     // Deletions coming from the GC are directly deleted from the remembered
      91             :     // set. Deletions coming from the runtime are added to the store buffer
      92             :     // to allow concurrent processing.
      93       35016 :     deletion_callback(this, start, end);
      94             :   }
      95             : 
      96             :   void SetMode(StoreBufferMode mode);
      97             : 
      98             :   // Used by the concurrent processing thread to transfer entries from the
      99             :   // store buffer to the remembered set.
     100             :   void ConcurrentlyProcessStoreBuffer();
     101             : 
     102             :   bool Empty() {
     103             :     for (int i = 0; i < kStoreBuffers; i++) {
     104             :       if (lazy_top_[i]) {
     105             :         return false;
     106             :       }
     107             :     }
     108             :     return top_ == start_[current_];
     109             :   }
     110             : 
     111             :   Heap* heap() { return heap_; }
     112             : 
     113             :  private:
     114             :   // There are two store buffers. If one store buffer fills up, the main thread
     115             :   // publishes the top pointer of the store buffer that needs processing in its
     116             :   // global lazy_top_ field. After that it start the concurrent processing
     117             :   // thread. The concurrent processing thread uses the pointer in lazy_top_.
     118             :   // It will grab the given mutex and transfer its entries to the remembered
     119             :   // set. If the concurrent thread does not make progress, the main thread will
     120             :   // perform the work.
     121             :   // Important: there is an ordering constrained. The store buffer with the
     122             :   // older entries has to be processed first.
     123             :   class Task : public CancelableTask {
     124             :    public:
     125             :     Task(Isolate* isolate, StoreBuffer* store_buffer)
     126             :         : CancelableTask(isolate),
     127             :           store_buffer_(store_buffer),
     128      133668 :           tracer_(isolate->heap()->tracer()) {}
     129      133668 :     ~Task() override = default;
     130             : 
     131             :    private:
     132       66791 :     void RunInternal() override {
     133      267164 :       TRACE_BACKGROUND_GC(tracer_,
     134             :                           GCTracer::BackgroundScope::BACKGROUND_STORE_BUFFER);
     135      133582 :       store_buffer_->ConcurrentlyProcessStoreBuffer();
     136       66791 :     }
     137             :     StoreBuffer* store_buffer_;
     138             :     GCTracer* tracer_;
     139             :     DISALLOW_COPY_AND_ASSIGN(Task);
     140             :   };
     141             : 
     142             :   StoreBufferMode mode() const { return mode_; }
     143             : 
     144             :   void FlipStoreBuffers();
     145             : 
     146             :   Heap* heap_;
     147             : 
     148             :   Address* top_;
     149             : 
     150             :   // The start and the limit of the buffer that contains store slots
     151             :   // added from the generated code. We have two chunks of store buffers.
     152             :   // Whenever one fills up, we notify a concurrent processing thread and
     153             :   // use the other empty one in the meantime.
     154             :   Address* start_[kStoreBuffers];
     155             :   Address* limit_[kStoreBuffers];
     156             : 
     157             :   // At most one lazy_top_ pointer is set at any time.
     158             :   Address* lazy_top_[kStoreBuffers];
     159             :   base::Mutex mutex_;
     160             : 
     161             :   // We only want to have at most one concurrent processing tas running.
     162             :   bool task_running_;
     163             : 
     164             :   // Points to the current buffer in use.
     165             :   int current_;
     166             : 
     167             :   // During GC, entries are directly added to the remembered set without
     168             :   // going through the store buffer. This is signaled by a special
     169             :   // IN_GC mode.
     170             :   StoreBufferMode mode_;
     171             : 
     172             :   VirtualMemory virtual_memory_;
     173             : 
     174             :   // Callbacks are more efficient than reading out the gc state for every
     175             :   // store buffer operation.
     176             :   void (*insertion_callback)(StoreBuffer*, Address);
     177             :   void (*deletion_callback)(StoreBuffer*, Address, Address);
     178             : };
     179             : 
     180             : }  // namespace internal
     181             : }  // namespace v8
     182             : 
     183             : #endif  // V8_HEAP_STORE_BUFFER_H_

Generated by: LCOV version 1.10