LCOV - code coverage report
Current view: top level - src/heap - array-buffer-tracker.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 58 60 96.7 %
Date: 2017-10-20 Functions: 8 8 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             : #include "src/heap/spaces.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : 
      13      185433 : LocalArrayBufferTracker::~LocalArrayBufferTracker() {
      14      185433 :   CHECK(array_buffers_.empty());
      15      185435 : }
      16             : 
      17             : template <typename Callback>
      18      168410 : void LocalArrayBufferTracker::Process(Callback callback) {
      19      168410 :   JSArrayBuffer* new_buffer = nullptr;
      20             :   JSArrayBuffer* old_buffer = nullptr;
      21             :   size_t new_retained_size = 0;
      22             :   size_t moved_size = 0;
      23      543433 :   for (TrackingData::iterator it = array_buffers_.begin();
      24             :        it != array_buffers_.end();) {
      25      206614 :     old_buffer = reinterpret_cast<JSArrayBuffer*>(*it);
      26      206614 :     const CallbackResult result = callback(old_buffer, &new_buffer);
      27      206646 :     if (result == kKeepEntry) {
      28           0 :       new_retained_size += NumberToSize(old_buffer->byte_length());
      29             :       ++it;
      30      206646 :     } else if (result == kUpdateEntry) {
      31             :       DCHECK_NOT_NULL(new_buffer);
      32       22229 :       Page* target_page = Page::FromAddress(new_buffer->address());
      33             :       {
      34       45161 :         base::LockGuard<base::RecursiveMutex> guard(target_page->mutex());
      35             :         LocalArrayBufferTracker* tracker = target_page->local_tracker();
      36       22230 :         if (tracker == nullptr) {
      37         702 :           target_page->AllocateLocalTracker();
      38             :           tracker = target_page->local_tracker();
      39             :         }
      40             :         DCHECK_NOT_NULL(tracker);
      41       44460 :         const size_t size = NumberToSize(new_buffer->byte_length());
      42       22230 :         moved_size += size;
      43             :         tracker->Add(new_buffer, size);
      44             :       }
      45             :       it = array_buffers_.erase(it);
      46      184417 :     } else if (result == kRemoveEntry) {
      47             :       // Size of freed memory is computed to avoid looking at dead objects.
      48      184417 :       old_buffer->FreeBackingStore();
      49             :       it = array_buffers_.erase(it);
      50             :     } else {
      51           0 :       UNREACHABLE();
      52             :     }
      53             :   }
      54      168409 :   const size_t freed_memory = retained_size_ - new_retained_size - moved_size;
      55      168409 :   if (freed_memory > 0) {
      56             :     heap_->update_external_memory_concurrently_freed(
      57        2466 :         static_cast<intptr_t>(freed_memory));
      58             :   }
      59      168409 :   retained_size_ = new_retained_size;
      60      168409 : }
      61             : 
      62       59304 : void ArrayBufferTracker::FreeDeadInNewSpace(Heap* heap) {
      63             :   DCHECK_EQ(heap->gc_state(), Heap::HeapState::SCAVENGE);
      64      236556 :   for (Page* page : PageRange(heap->new_space()->FromSpaceStart(),
      65       59304 :                               heap->new_space()->FromSpaceEnd())) {
      66             :     bool empty = ProcessBuffers(page, kUpdateForwardedRemoveOthers);
      67      103452 :     CHECK(empty);
      68             :   }
      69       29652 :   heap->account_external_memory_concurrently_freed();
      70       29652 : }
      71             : 
      72          48 : size_t ArrayBufferTracker::RetainedInNewSpace(Heap* heap) {
      73             :   size_t retained_size = 0;
      74         120 :   for (Page* page : PageRange(heap->new_space()->ToSpaceStart(),
      75          48 :                               heap->new_space()->ToSpaceEnd())) {
      76          96 :     LocalArrayBufferTracker* tracker = page->local_tracker();
      77          48 :     if (tracker == nullptr) continue;
      78          48 :     retained_size += tracker->retained_size();
      79             :   }
      80          24 :   return retained_size;
      81             : }
      82             : 
      83      522232 : void ArrayBufferTracker::FreeAll(Page* page) {
      84      522232 :   LocalArrayBufferTracker* tracker = page->local_tracker();
      85     1044464 :   if (tracker == nullptr) return;
      86      147889 :   tracker->Free([](JSArrayBuffer* buffer) { return true; });
      87      147889 :   if (tracker->IsEmpty()) {
      88      147889 :     page->ReleaseLocalTracker();
      89             :   }
      90             : }
      91             : 
      92       67228 : bool ArrayBufferTracker::ProcessBuffers(Page* page, ProcessingMode mode) {
      93      170680 :   LocalArrayBufferTracker* tracker = page->local_tracker();
      94      170680 :   if (tracker == nullptr) return true;
      95             : 
      96             :   DCHECK(page->SweepingDone());
      97             :   tracker->Process(
      98      206591 :       [mode](JSArrayBuffer* old_buffer, JSArrayBuffer** new_buffer) {
      99             :         MapWord map_word = old_buffer->map_word();
     100      206591 :         if (map_word.IsForwardingAddress()) {
     101       22229 :           *new_buffer = JSArrayBuffer::cast(map_word.ToForwardingAddress());
     102       22229 :           return LocalArrayBufferTracker::kUpdateEntry;
     103             :         }
     104      184362 :         return mode == kUpdateForwardedKeepOthers
     105             :                    ? LocalArrayBufferTracker::kKeepEntry
     106      184362 :                    : LocalArrayBufferTracker::kRemoveEntry;
     107      168415 :       });
     108       67221 :   return tracker->IsEmpty();
     109             : }
     110             : 
     111         209 : bool ArrayBufferTracker::IsTracked(JSArrayBuffer* buffer) {
     112         209 :   Page* page = Page::FromAddress(buffer->address());
     113             :   {
     114         418 :     base::LockGuard<base::RecursiveMutex> guard(page->mutex());
     115             :     LocalArrayBufferTracker* tracker = page->local_tracker();
     116         209 :     if (tracker == nullptr) return false;
     117         185 :     return tracker->IsTracked(buffer);
     118             :   }
     119             : }
     120             : 
     121             : }  // namespace internal
     122             : }  // namespace v8

Generated by: LCOV version 1.10