LCOV - code coverage report
Current view: top level - src/heap - local-allocator.h (source / functions) Hit Total Coverage
Test: app.info Lines: 57 60 95.0 %
Date: 2017-10-20 Functions: 11 11 100.0 %

          Line data    Source code
       1             : // Copyright 2017 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_LOCAL_ALLOCATOR_H_
       6             : #define V8_HEAP_LOCAL_ALLOCATOR_H_
       7             : 
       8             : #include "src/globals.h"
       9             : #include "src/heap/heap.h"
      10             : #include "src/heap/spaces.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : // Allocator encapsulating thread-local allocation. Assumes that all other
      16             : // allocations also go through LocalAllocator.
      17      200936 : class LocalAllocator {
      18             :  public:
      19             :   static const int kLabSize = 32 * KB;
      20             :   static const int kMaxLabObjectSize = 8 * KB;
      21             : 
      22      200936 :   explicit LocalAllocator(Heap* heap)
      23             :       : heap_(heap),
      24             :         new_space_(heap->new_space()),
      25             :         compaction_spaces_(heap),
      26             :         new_space_lab_(LocalAllocationBuffer::InvalidBuffer()),
      27      301404 :         lab_allocation_will_fail_(false) {}
      28             : 
      29             :   // Needs to be called from the main thread to finalize this LocalAllocator.
      30      100468 :   void Finalize() {
      31      200936 :     heap_->old_space()->MergeCompactionSpace(compaction_spaces_.Get(OLD_SPACE));
      32      100468 :     heap_->code_space()->MergeCompactionSpace(
      33      200936 :         compaction_spaces_.Get(CODE_SPACE));
      34             :     // Give back remaining LAB space if this LocalAllocator's new space LAB
      35             :     // sits right next to new space allocation top.
      36      100468 :     const AllocationInfo info = new_space_lab_.Close();
      37      100468 :     const Address top = new_space_->top();
      38      100468 :     if (info.limit() != nullptr && info.limit() == top) {
      39             :       DCHECK_NOT_NULL(info.top());
      40       56045 :       *new_space_->allocation_top_address() = info.top();
      41             :     }
      42      100468 :   }
      43             : 
      44   136360982 :   AllocationResult Allocate(AllocationSpace space, int object_size,
      45             :                             AllocationAlignment alignment) {
      46   136360982 :     switch (space) {
      47             :       case NEW_SPACE:
      48    77849066 :         return AllocateInNewSpace(object_size, alignment);
      49             :       case OLD_SPACE:
      50    58510723 :         return compaction_spaces_.Get(OLD_SPACE)->AllocateRaw(object_size,
      51    58520190 :                                                               alignment);
      52             :       case CODE_SPACE:
      53        1193 :         return compaction_spaces_.Get(CODE_SPACE)
      54        1193 :             ->AllocateRaw(object_size, alignment);
      55             :       default:
      56           0 :         UNREACHABLE();
      57             :         break;
      58             :     }
      59             :   }
      60             : 
      61     1178817 :   void FreeLast(AllocationSpace space, HeapObject* object, int object_size) {
      62     1178817 :     switch (space) {
      63             :       case NEW_SPACE:
      64      549469 :         FreeLastInNewSpace(object, object_size);
      65      549178 :         return;
      66             :       case OLD_SPACE:
      67      629348 :         FreeLastInOldSpace(object, object_size);
      68      629081 :         return;
      69             :       default:
      70             :         // Only new and old space supported.
      71           0 :         UNREACHABLE();
      72             :         break;
      73             :     }
      74             :   }
      75             : 
      76      145631 :   void AnnounceLockedPage(MemoryChunk* chunk) {
      77      145631 :     const AllocationSpace space = chunk->owner()->identity();
      78             :     // There are no allocations on large object and map space and hence we
      79             :     // cannot announce that we locked a page there.
      80      291259 :     if (space == LO_SPACE || space == MAP_SPACE) return;
      81             : 
      82             :     DCHECK(space != NEW_SPACE);
      83      107371 :     compaction_spaces_.Get(space)->AnnounceLockedPage(
      84             :         reinterpret_cast<Page*>(chunk));
      85             :   }
      86             : 
      87             :  private:
      88    77856790 :   AllocationResult AllocateInNewSpace(int object_size,
      89             :                                       AllocationAlignment alignment) {
      90    77856790 :     if (object_size > kMaxLabObjectSize) {
      91      272289 :       return new_space_->AllocateRawSynchronized(object_size, alignment);
      92             :     }
      93    77584501 :     return AllocateInLAB(object_size, alignment);
      94             :   }
      95             : 
      96      639557 :   inline bool NewLocalAllocationBuffer() {
      97      639557 :     if (lab_allocation_will_fail_) return false;
      98      186061 :     LocalAllocationBuffer saved_lab_ = new_space_lab_;
      99             :     AllocationResult result =
     100      186055 :         new_space_->AllocateRawSynchronized(kLabSize, kWordAligned);
     101      372164 :     new_space_lab_ = LocalAllocationBuffer::FromResult(heap_, result, kLabSize);
     102      186079 :     if (new_space_lab_.IsValid()) {
     103             :       new_space_lab_.TryMerge(&saved_lab_);
     104             :       return true;
     105             :     }
     106         206 :     new_space_lab_ = saved_lab_;
     107         206 :     lab_allocation_will_fail_ = true;
     108         206 :     return false;
     109             :   }
     110             : 
     111    77595139 :   AllocationResult AllocateInLAB(int object_size,
     112             :                                  AllocationAlignment alignment) {
     113             :     AllocationResult allocation;
     114    77595139 :     if (!new_space_lab_.IsValid() && !NewLocalAllocationBuffer()) {
     115             :       return AllocationResult::Retry(OLD_SPACE);
     116             :     }
     117    77593495 :     allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
     118    77588099 :     if (allocation.IsRetry()) {
     119      568584 :       if (!NewLocalAllocationBuffer()) {
     120             :         return AllocationResult::Retry(OLD_SPACE);
     121             :       } else {
     122      116540 :         allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
     123      116540 :         CHECK(!allocation.IsRetry());
     124             :       }
     125             :     }
     126    77136055 :     return allocation;
     127             :   }
     128             : 
     129      549481 :   void FreeLastInNewSpace(HeapObject* object, int object_size) {
     130      549481 :     if (!new_space_lab_.TryFreeLast(object, object_size)) {
     131             :       // We couldn't free the last object so we have to write a proper filler.
     132             :       heap_->CreateFillerObjectAt(object->address(), object_size,
     133          12 :                                   ClearRecordedSlots::kNo);
     134             :     }
     135      549481 :   }
     136             : 
     137      629356 :   void FreeLastInOldSpace(HeapObject* object, int object_size) {
     138     1258693 :     if (!compaction_spaces_.Get(OLD_SPACE)->TryFreeLast(object, object_size)) {
     139             :       // We couldn't free the last object so we have to write a proper filler.
     140             :       heap_->CreateFillerObjectAt(object->address(), object_size,
     141           0 :                                   ClearRecordedSlots::kNo);
     142             :     }
     143      629337 :   }
     144             : 
     145             :   Heap* const heap_;
     146             :   NewSpace* const new_space_;
     147             :   CompactionSpaceCollection compaction_spaces_;
     148             :   LocalAllocationBuffer new_space_lab_;
     149             :   bool lab_allocation_will_fail_;
     150             : };
     151             : 
     152             : }  // namespace internal
     153             : }  // namespace v8
     154             : 
     155             : #endif  // V8_HEAP_LOCAL_ALLOCATOR_H_

Generated by: LCOV version 1.10