LCOV - code coverage report
Current view: top level - src/heap - array-buffer-tracker.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 68 69 98.6 %
Date: 2017-04-26 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright 2015 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/array-buffer-tracker.h"
       6             : #include "src/heap/array-buffer-tracker-inl.h"
       7             : #include "src/heap/heap.h"
       8             : 
       9             : namespace v8 {
      10             : namespace internal {
      11             : 
      12      185716 : LocalArrayBufferTracker::~LocalArrayBufferTracker() {
      13      185716 :   CHECK(array_buffers_.empty());
      14      185724 : }
      15             : 
      16             : template <LocalArrayBufferTracker::FreeMode free_mode>
      17      152164 : void LocalArrayBufferTracker::Free() {
      18             :   size_t freed_memory = 0;
      19      338438 :   for (TrackingData::iterator it = array_buffers_.begin();
      20             :        it != array_buffers_.end();) {
      21       34110 :     JSArrayBuffer* buffer = reinterpret_cast<JSArrayBuffer*>(it->first);
      22             :     // TODO(mlippautz): Create a dependency on the collector to avoid getting
      23             :     // the marking state out of thin air.
      24        6476 :     if ((free_mode == kFreeAll) ||
      25             :         ObjectMarking::IsWhite(buffer, MarkingState::Internal(buffer))) {
      26       29650 :       const size_t len = it->second;
      27       88950 :       heap_->isolate()->array_buffer_allocator()->Free(buffer->backing_store(),
      28       29650 :                                                        len);
      29       29650 :       freed_memory += len;
      30             :       it = array_buffers_.erase(it);
      31             :     } else {
      32             :       ++it;
      33             :     }
      34             :   }
      35      152164 :   if (freed_memory > 0) {
      36             :     heap_->update_external_memory_concurrently_freed(
      37        2964 :         static_cast<intptr_t>(freed_memory));
      38             :   }
      39      152164 : }
      40             : 
      41             : template <typename Callback>
      42      253312 : void LocalArrayBufferTracker::Process(Callback callback) {
      43      253312 :   JSArrayBuffer* new_buffer = nullptr;
      44             :   size_t freed_memory = 0;
      45      624567 :   for (TrackingData::iterator it = array_buffers_.begin();
      46             :        it != array_buffers_.end();) {
      47      117943 :     const CallbackResult result = callback(it->first, &new_buffer);
      48      117937 :     if (result == kKeepEntry) {
      49             :       ++it;
      50      117942 :     } else if (result == kUpdateEntry) {
      51             :       DCHECK_NOT_NULL(new_buffer);
      52       19804 :       Page* target_page = Page::FromAddress(new_buffer->address());
      53             :       // We need to lock the target page because we cannot guarantee
      54             :       // exclusive access to new space pages.
      55       34110 :       if (target_page->InNewSpace()) target_page->mutex()->Lock();
      56             :       LocalArrayBufferTracker* tracker = target_page->local_tracker();
      57       19804 :       if (tracker == nullptr) {
      58        1094 :         target_page->AllocateLocalTracker();
      59             :         tracker = target_page->local_tracker();
      60             :       }
      61             :       DCHECK_NOT_NULL(tracker);
      62       19804 :       tracker->Add(new_buffer, it->second);
      63       33016 :       if (target_page->InNewSpace()) target_page->mutex()->Unlock();
      64             :       it = array_buffers_.erase(it);
      65       98138 :     } else if (result == kRemoveEntry) {
      66       98138 :       const size_t len = it->second;
      67      294414 :       heap_->isolate()->array_buffer_allocator()->Free(
      68       98138 :           it->first->backing_store(), len);
      69       98140 :       freed_memory += len;
      70             :       it = array_buffers_.erase(it);
      71             :     } else {
      72           0 :       UNREACHABLE();
      73             :     }
      74             :   }
      75      253312 :   if (freed_memory > 0) {
      76             :     heap_->update_external_memory_concurrently_freed(
      77        3257 :         static_cast<intptr_t>(freed_memory));
      78             :   }
      79      253312 : }
      80             : 
      81      138378 : void ArrayBufferTracker::FreeDeadInNewSpace(Heap* heap) {
      82             :   DCHECK_EQ(heap->gc_state(), Heap::HeapState::SCAVENGE);
      83      435953 :   for (Page* page : PageRange(heap->new_space()->FromSpaceStart(),
      84      138378 :                               heap->new_space()->FromSpaceEnd())) {
      85             :     bool empty = ProcessBuffers(page, kUpdateForwardedRemoveOthers);
      86      183382 :     CHECK(empty);
      87             :   }
      88       69189 :   heap->account_external_memory_concurrently_freed();
      89       69189 : }
      90             : 
      91      480060 : void ArrayBufferTracker::FreeDead(Page* page) {
      92             :   // Callers need to ensure having the page lock.
      93      480060 :   LocalArrayBufferTracker* tracker = page->local_tracker();
      94      960120 :   if (tracker == nullptr) return;
      95             :   DCHECK(!page->SweepingDone());
      96        4864 :   tracker->Free<LocalArrayBufferTracker::kFreeDead>();
      97        4864 :   if (tracker->IsEmpty()) {
      98        1394 :     page->ReleaseLocalTracker();
      99             :   }
     100             : }
     101             : 
     102      630479 : void ArrayBufferTracker::FreeAll(Page* page) {
     103      630479 :   LocalArrayBufferTracker* tracker = page->local_tracker();
     104     1260958 :   if (tracker == nullptr) return;
     105      147300 :   tracker->Free<LocalArrayBufferTracker::kFreeAll>();
     106      147300 :   if (tracker->IsEmpty()) {
     107      147300 :     page->ReleaseLocalTracker();
     108             :   }
     109             : }
     110             : 
     111       79674 : bool ArrayBufferTracker::ProcessBuffers(Page* page, ProcessingMode mode) {
     112      263056 :   LocalArrayBufferTracker* tracker = page->local_tracker();
     113      263056 :   if (tracker == nullptr) return true;
     114             : 
     115             :   DCHECK(page->SweepingDone());
     116             :   tracker->Process(
     117      117944 :       [mode](JSArrayBuffer* old_buffer, JSArrayBuffer** new_buffer) {
     118             :         MapWord map_word = old_buffer->map_word();
     119      117944 :         if (map_word.IsForwardingAddress()) {
     120       19804 :           *new_buffer = JSArrayBuffer::cast(map_word.ToForwardingAddress());
     121       19804 :           return LocalArrayBufferTracker::kUpdateEntry;
     122             :         }
     123       98140 :         return mode == kUpdateForwardedKeepOthers
     124             :                    ? LocalArrayBufferTracker::kKeepEntry
     125       98140 :                    : LocalArrayBufferTracker::kRemoveEntry;
     126      253312 :       });
     127       70205 :   return tracker->IsEmpty();
     128             : }
     129             : 
     130         244 : bool ArrayBufferTracker::IsTracked(JSArrayBuffer* buffer) {
     131         244 :   Page* page = Page::FromAddress(buffer->address());
     132             :   {
     133         488 :     base::LockGuard<base::RecursiveMutex> guard(page->mutex());
     134             :     LocalArrayBufferTracker* tracker = page->local_tracker();
     135         244 :     if (tracker == nullptr) return false;
     136         216 :     return tracker->IsTracked(buffer);
     137             :   }
     138             : }
     139             : 
     140             : }  // namespace internal
     141             : }  // namespace v8

Generated by: LCOV version 1.10