LCOV - code coverage report
Current view: top level - src/snapshot - deserializer-allocator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 46 60 76.7 %
Date: 2019-04-17 Functions: 10 11 90.9 %

          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             : #include "src/snapshot/deserializer-allocator.h"
       6             : 
       7             : #include "src/heap/heap-inl.h"  // crbug.com/v8/8499
       8             : 
       9             : namespace v8 {
      10             : namespace internal {
      11             : 
      12             : // We know the space requirements before deserialization and can
      13             : // pre-allocate that reserved space. During deserialization, all we need
      14             : // to do is to bump up the pointer for each space in the reserved
      15             : // space. This is also used for fixing back references.
      16             : // We may have to split up the pre-allocation into several chunks
      17             : // because it would not fit onto a single page. We do not have to keep
      18             : // track of when to move to the next chunk. An opcode will signal this.
      19             : // Since multiple large objects cannot be folded into one large object
      20             : // space allocation, we have to do an actual allocation when deserializing
      21             : // each large object. Instead of tracking offset for back references, we
      22             : // reference large objects by index.
      23   441589221 : Address DeserializerAllocator::AllocateRaw(AllocationSpace space, int size) {
      24   441589221 :   if (space == LO_SPACE) {
      25          60 :     AlwaysAllocateScope scope(heap_);
      26             :     // Note that we currently do not support deserialization of large code
      27             :     // objects.
      28          60 :     LargeObjectSpace* lo_space = heap_->lo_space();
      29          60 :     AllocationResult result = lo_space->AllocateRaw(size);
      30          60 :     HeapObject obj = result.ToObjectChecked();
      31          60 :     deserialized_large_objects_.push_back(obj);
      32             :     return obj->address();
      33   441589161 :   } else if (space == MAP_SPACE) {
      34             :     DCHECK_EQ(Map::kSize, size);
      35    45897908 :     return allocated_maps_[next_map_index_++];
      36             :   } else {
      37             :     DCHECK_LT(space, kNumberOfPreallocatedSpaces);
      38   418640207 :     Address address = high_water_[space];
      39             :     DCHECK_NE(address, kNullAddress);
      40   418640207 :     high_water_[space] += size;
      41             : #ifdef DEBUG
      42             :     // Assert that the current reserved chunk is still big enough.
      43             :     const Heap::Reservation& reservation = reservations_[space];
      44             :     int chunk_index = current_chunk_[space];
      45             :     DCHECK_LE(high_water_[space], reservation[chunk_index].end);
      46             : #endif
      47   418640207 :     if (space == CODE_SPACE) SkipList::Update(address, size);
      48             :     return address;
      49             :   }
      50             : }
      51             : 
      52   441585799 : Address DeserializerAllocator::Allocate(AllocationSpace space, int size) {
      53             :   Address address;
      54             :   HeapObject obj;
      55             : 
      56   441585799 :   if (next_alignment_ != kWordAligned) {
      57           0 :     const int reserved = size + Heap::GetMaximumFillToAlign(next_alignment_);
      58           0 :     address = AllocateRaw(space, reserved);
      59             :     obj = HeapObject::FromAddress(address);
      60             :     // If one of the following assertions fails, then we are deserializing an
      61             :     // aligned object when the filler maps have not been deserialized yet.
      62             :     // We require filler maps as padding to align the object.
      63             :     DCHECK(ReadOnlyRoots(heap_).free_space_map()->IsMap());
      64             :     DCHECK(ReadOnlyRoots(heap_).one_pointer_filler_map()->IsMap());
      65             :     DCHECK(ReadOnlyRoots(heap_).two_pointer_filler_map()->IsMap());
      66           0 :     obj = heap_->AlignWithFiller(obj, size, reserved, next_alignment_);
      67             :     address = obj->address();
      68           0 :     next_alignment_ = kWordAligned;
      69           0 :     return address;
      70             :   } else {
      71   441585799 :     return AllocateRaw(space, size);
      72             :   }
      73             : }
      74             : 
      75     2295440 : void DeserializerAllocator::MoveToNextChunk(AllocationSpace space) {
      76             :   DCHECK_LT(space, kNumberOfPreallocatedSpaces);
      77     2295440 :   uint32_t chunk_index = current_chunk_[space];
      78     2295440 :   const Heap::Reservation& reservation = reservations_[space];
      79             :   // Make sure the current chunk is indeed exhausted.
      80     4590880 :   CHECK_EQ(reservation[chunk_index].end, high_water_[space]);
      81             :   // Move to next reserved chunk.
      82     2295440 :   chunk_index = ++current_chunk_[space];
      83     2295440 :   CHECK_LT(chunk_index, reservation.size());
      84     2295440 :   high_water_[space] = reservation[chunk_index].start;
      85     2295440 : }
      86             : 
      87    12378409 : HeapObject DeserializerAllocator::GetMap(uint32_t index) {
      88             :   DCHECK_LT(index, next_map_index_);
      89    37135227 :   return HeapObject::FromAddress(allocated_maps_[index]);
      90             : }
      91             : 
      92          10 : HeapObject DeserializerAllocator::GetLargeObject(uint32_t index) {
      93             :   DCHECK_LT(index, deserialized_large_objects_.size());
      94          20 :   return deserialized_large_objects_[index];
      95             : }
      96             : 
      97   175213426 : HeapObject DeserializerAllocator::GetObject(AllocationSpace space,
      98             :                                             uint32_t chunk_index,
      99             :                                             uint32_t chunk_offset) {
     100             :   DCHECK_LT(space, kNumberOfPreallocatedSpaces);
     101             :   DCHECK_LE(chunk_index, current_chunk_[space]);
     102   350426852 :   Address address = reservations_[space][chunk_index].start + chunk_offset;
     103   175213426 :   if (next_alignment_ != kWordAligned) {
     104           0 :     int padding = Heap::GetFillToAlign(address, next_alignment_);
     105           0 :     next_alignment_ = kWordAligned;
     106             :     DCHECK(padding == 0 || HeapObject::FromAddress(address)->IsFiller());
     107           0 :     address += padding;
     108             :   }
     109   175213426 :   return HeapObject::FromAddress(address);
     110             : }
     111             : 
     112      216608 : void DeserializerAllocator::DecodeReservation(
     113             :     const std::vector<SerializedData::Reservation>& res) {
     114             :   DCHECK_EQ(0, reservations_[FIRST_SPACE].size());
     115             :   int current_space = FIRST_SPACE;
     116     3811663 :   for (auto& r : res) {
     117     7190109 :     reservations_[current_space].push_back(
     118             :         {r.chunk_size(), kNullAddress, kNullAddress});
     119     3595055 :     if (r.is_last()) current_space++;
     120             :   }
     121             :   DCHECK_EQ(kNumberOfSpaces, current_space);
     122     1083045 :   for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0;
     123      216609 : }
     124             : 
     125      216611 : bool DeserializerAllocator::ReserveSpace() {
     126             : #ifdef DEBUG
     127             :   for (int i = FIRST_SPACE; i < kNumberOfSpaces; ++i) {
     128             :     DCHECK_GT(reservations_[i].size(), 0);
     129             :   }
     130             : #endif  // DEBUG
     131             :   DCHECK(allocated_maps_.empty());
     132      216611 :   if (!heap_->ReserveSpace(reservations_, &allocated_maps_)) {
     133             :     return false;
     134             :   }
     135     1949500 :   for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
     136      866444 :     high_water_[i] = reservations_[i][0].start;
     137             :   }
     138             :   return true;
     139             : }
     140             : 
     141           0 : bool DeserializerAllocator::ReservationsAreFullyUsed() const {
     142           0 :   for (int space = 0; space < kNumberOfPreallocatedSpaces; space++) {
     143           0 :     const uint32_t chunk_index = current_chunk_[space];
     144           0 :     if (reservations_[space].size() != chunk_index + 1) {
     145             :       return false;
     146             :     }
     147           0 :     if (reservations_[space][chunk_index].end != high_water_[space]) {
     148             :       return false;
     149             :     }
     150             :   }
     151           0 :   return (allocated_maps_.size() == next_map_index_);
     152             : }
     153             : 
     154       91871 : void DeserializerAllocator::RegisterDeserializedObjectsForBlackAllocation() {
     155       91871 :   heap_->RegisterDeserializedObjectsForBlackAllocation(
     156       91871 :       reservations_, deserialized_large_objects_, allocated_maps_);
     157       91872 : }
     158             : 
     159             : }  // namespace internal
     160      122004 : }  // namespace v8

Generated by: LCOV version 1.10