LCOV - code coverage report
Current view: top level - src/snapshot - default-deserializer-allocator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 70 87 80.5 %
Date: 2017-10-20 Functions: 11 13 84.6 %

          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/default-deserializer-allocator.h"
       6             : 
       7             : #include "src/heap/heap-inl.h"
       8             : #include "src/snapshot/builtin-deserializer.h"
       9             : #include "src/snapshot/deserializer.h"
      10             : #include "src/snapshot/startup-deserializer.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15      138819 : DefaultDeserializerAllocator::DefaultDeserializerAllocator(
      16             :     Deserializer<DefaultDeserializerAllocator>* deserializer)
      17      971733 :     : deserializer_(deserializer) {}
      18             : 
      19             : // We know the space requirements before deserialization and can
      20             : // pre-allocate that reserved space. During deserialization, all we need
      21             : // to do is to bump up the pointer for each space in the reserved
      22             : // space. This is also used for fixing back references.
      23             : // We may have to split up the pre-allocation into several chunks
      24             : // because it would not fit onto a single page. We do not have to keep
      25             : // track of when to move to the next chunk. An opcode will signal this.
      26             : // Since multiple large objects cannot be folded into one large object
      27             : // space allocation, we have to do an actual allocation when deserializing
      28             : // each large object. Instead of tracking offset for back references, we
      29             : // reference large objects by index.
      30   443044876 : Address DefaultDeserializerAllocator::AllocateRaw(AllocationSpace space,
      31             :                                                   int size) {
      32   443044876 :   if (space == LO_SPACE) {
      33             :     AlwaysAllocateScope scope(isolate());
      34          40 :     LargeObjectSpace* lo_space = isolate()->heap()->lo_space();
      35             :     // TODO(jgruber): May be cleaner to pass in executability as an argument.
      36             :     Executability exec =
      37          40 :         static_cast<Executability>(deserializer_->source()->Get());
      38          40 :     AllocationResult result = lo_space->AllocateRaw(size, exec);
      39          40 :     HeapObject* obj = result.ToObjectChecked();
      40          40 :     deserialized_large_objects_.push_back(obj);
      41          40 :     return obj->address();
      42   443044836 :   } else if (space == MAP_SPACE) {
      43             :     DCHECK_EQ(Map::kSize, size);
      44    58437734 :     return allocated_maps_[next_map_index_++];
      45             :   } else {
      46             :     DCHECK_LT(space, kNumberOfPreallocatedSpaces);
      47   413825969 :     Address address = high_water_[space];
      48             :     DCHECK_NOT_NULL(address);
      49   413825969 :     high_water_[space] += size;
      50             : #ifdef DEBUG
      51             :     // Assert that the current reserved chunk is still big enough.
      52             :     const Heap::Reservation& reservation = reservations_[space];
      53             :     int chunk_index = current_chunk_[space];
      54             :     DCHECK_LE(high_water_[space], reservation[chunk_index].end);
      55             : #endif
      56   413825969 :     if (space == CODE_SPACE) SkipList::Update(address, size);
      57   413827415 :     return address;
      58             :   }
      59             : }
      60             : 
      61   443043252 : Address DefaultDeserializerAllocator::Allocate(AllocationSpace space,
      62             :                                                int size) {
      63             :   Address address;
      64             :   HeapObject* obj;
      65             : 
      66   443043252 :   if (next_alignment_ != kWordAligned) {
      67           0 :     const int reserved = size + Heap::GetMaximumFillToAlign(next_alignment_);
      68           0 :     address = AllocateRaw(space, reserved);
      69           0 :     obj = HeapObject::FromAddress(address);
      70             :     // If one of the following assertions fails, then we are deserializing an
      71             :     // aligned object when the filler maps have not been deserialized yet.
      72             :     // We require filler maps as padding to align the object.
      73           0 :     Heap* heap = isolate()->heap();
      74             :     DCHECK(heap->free_space_map()->IsMap());
      75             :     DCHECK(heap->one_pointer_filler_map()->IsMap());
      76             :     DCHECK(heap->two_pointer_filler_map()->IsMap());
      77           0 :     obj = heap->AlignWithFiller(obj, size, reserved, next_alignment_);
      78             :     address = obj->address();
      79           0 :     next_alignment_ = kWordAligned;
      80           0 :     return address;
      81             :   } else {
      82   443043252 :     return AllocateRaw(space, size);
      83             :   }
      84             : }
      85             : 
      86          55 : void DefaultDeserializerAllocator::MoveToNextChunk(AllocationSpace space) {
      87             :   DCHECK_LT(space, kNumberOfPreallocatedSpaces);
      88          55 :   uint32_t chunk_index = current_chunk_[space];
      89         165 :   const Heap::Reservation& reservation = reservations_[space];
      90             :   // Make sure the current chunk is indeed exhausted.
      91         110 :   CHECK_EQ(reservation[chunk_index].end, high_water_[space]);
      92             :   // Move to next reserved chunk.
      93          55 :   chunk_index = ++current_chunk_[space];
      94          55 :   CHECK_LT(chunk_index, reservation.size());
      95          55 :   high_water_[space] = reservation[chunk_index].start;
      96          55 : }
      97             : 
      98    18272643 : HeapObject* DefaultDeserializerAllocator::GetMap(uint32_t index) {
      99             :   DCHECK_LT(index, next_map_index_);
     100    36545286 :   return HeapObject::FromAddress(allocated_maps_[index]);
     101             : }
     102             : 
     103           5 : HeapObject* DefaultDeserializerAllocator::GetLargeObject(uint32_t index) {
     104             :   DCHECK_LT(index, deserialized_large_objects_.size());
     105          10 :   return deserialized_large_objects_[index];
     106             : }
     107             : 
     108   243483453 : HeapObject* DefaultDeserializerAllocator::GetObject(AllocationSpace space,
     109             :                                                     uint32_t chunk_index,
     110             :                                                     uint32_t chunk_offset) {
     111             :   DCHECK_LT(space, kNumberOfPreallocatedSpaces);
     112             :   DCHECK_LE(chunk_index, current_chunk_[space]);
     113   486966906 :   Address address = reservations_[space][chunk_index].start + chunk_offset;
     114   243483453 :   if (next_alignment_ != kWordAligned) {
     115           0 :     int padding = Heap::GetFillToAlign(address, next_alignment_);
     116           0 :     next_alignment_ = kWordAligned;
     117             :     DCHECK(padding == 0 || HeapObject::FromAddress(address)->IsFiller());
     118           0 :     address += padding;
     119             :   }
     120   243483453 :   return HeapObject::FromAddress(address);
     121             : }
     122             : 
     123      138819 : void DefaultDeserializerAllocator::DecodeReservation(
     124             :     Vector<const SerializedData::Reservation> res) {
     125             :   DCHECK_EQ(0, reservations_[NEW_SPACE].size());
     126             :   STATIC_ASSERT(NEW_SPACE == 0);
     127             :   int current_space = NEW_SPACE;
     128      832969 :   for (auto& r : res) {
     129     1388300 :     reservations_[current_space].push_back({r.chunk_size(), NULL, NULL});
     130      694150 :     if (r.is_last()) current_space++;
     131             :   }
     132             :   DCHECK_EQ(kNumberOfSpaces, current_space);
     133      416457 :   for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0;
     134      138819 : }
     135             : 
     136       83851 : bool DefaultDeserializerAllocator::ReserveSpace() {
     137             : #ifdef DEBUG
     138             :   for (int i = NEW_SPACE; i < kNumberOfSpaces; ++i) {
     139             :     DCHECK_GT(reservations_[i].size(), 0);
     140             :   }
     141             : #endif  // DEBUG
     142             :   DCHECK(allocated_maps_.empty());
     143      167702 :   if (!isolate()->heap()->ReserveSpace(reservations_, &allocated_maps_)) {
     144             :     return false;
     145             :   }
     146      251553 :   for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
     147      251553 :     high_water_[i] = reservations_[i][0].start;
     148             :   }
     149             :   return true;
     150             : }
     151             : 
     152             : // static
     153       54968 : bool DefaultDeserializerAllocator::ReserveSpace(
     154             :     StartupDeserializer* startup_deserializer,
     155             :     BuiltinDeserializer* builtin_deserializer) {
     156             :   const int first_space = NEW_SPACE;
     157             :   const int last_space = SerializerDeserializer::kNumberOfSpaces;
     158       54968 :   Isolate* isolate = startup_deserializer->isolate();
     159             : 
     160             :   // Create a set of merged reservations to reserve space in one go.
     161             :   // The BuiltinDeserializer's reservations are ignored, since our actual
     162             :   // requirements vary based on whether lazy deserialization is enabled.
     163             :   // Instead, we manually determine the required code-space.
     164             : 
     165      329808 :   Heap::Reservation merged_reservations[kNumberOfSpaces];
     166      274840 :   for (int i = first_space; i < last_space; i++) {
     167      274840 :     merged_reservations[i] =
     168      274840 :         startup_deserializer->allocator()->reservations_[i];
     169             :   }
     170             : 
     171             :   Heap::Reservation builtin_reservations =
     172       54968 :       builtin_deserializer->allocator()->CreateReservationsForEagerBuiltins();
     173             :   DCHECK(!builtin_reservations.empty());
     174             : 
     175    25051062 :   for (const auto& c : builtin_reservations) {
     176    24941117 :     merged_reservations[CODE_SPACE].push_back(c);
     177             :   }
     178             : 
     179       54968 :   if (!isolate->heap()->ReserveSpace(
     180             :           merged_reservations,
     181       54968 :           &startup_deserializer->allocator()->allocated_maps_)) {
     182             :     return false;
     183             :   }
     184             : 
     185             :   DisallowHeapAllocation no_allocation;
     186             : 
     187             :   // Distribute the successful allocations between both deserializers.
     188             :   // There's nothing to be done here except for code space.
     189             : 
     190             :   {
     191             :     const int num_builtin_reservations =
     192      109936 :         static_cast<int>(builtin_reservations.size());
     193    24995948 :     for (int i = num_builtin_reservations - 1; i >= 0; i--) {
     194             :       const auto& c = merged_reservations[CODE_SPACE].back();
     195             :       DCHECK_EQ(c.size, builtin_reservations[i].size);
     196             :       DCHECK_EQ(c.size, c.end - c.start);
     197    49881960 :       builtin_reservations[i].start = c.start;
     198    24940980 :       builtin_reservations[i].end = c.end;
     199             :       merged_reservations[CODE_SPACE].pop_back();
     200             :     }
     201             : 
     202             :     builtin_deserializer->allocator()->InitializeBuiltinsTable(
     203       54968 :         builtin_reservations);
     204             :   }
     205             : 
     206             :   // Write back startup reservations.
     207             : 
     208      329808 :   for (int i = first_space; i < last_space; i++) {
     209             :     startup_deserializer->allocator()->reservations_[i].swap(
     210      274840 :         merged_reservations[i]);
     211             :   }
     212             : 
     213      164904 :   for (int i = first_space; i < kNumberOfPreallocatedSpaces; i++) {
     214             :     startup_deserializer->allocator()->high_water_[i] =
     215      164904 :         startup_deserializer->allocator()->reservations_[i][0].start;
     216             :   }
     217             : 
     218      329808 :   return true;
     219             : }
     220             : 
     221           0 : bool DefaultDeserializerAllocator::ReservationsAreFullyUsed() const {
     222           0 :   for (int space = 0; space < kNumberOfPreallocatedSpaces; space++) {
     223           0 :     const uint32_t chunk_index = current_chunk_[space];
     224           0 :     if (reservations_[space].size() != chunk_index + 1) {
     225             :       return false;
     226             :     }
     227           0 :     if (reservations_[space][chunk_index].end != high_water_[space]) {
     228             :       return false;
     229             :     }
     230             :   }
     231           0 :   return (allocated_maps_.size() == next_map_index_);
     232             : }
     233             : 
     234       83851 : void DefaultDeserializerAllocator::
     235             :     RegisterDeserializedObjectsForBlackAllocation() {
     236             :   isolate()->heap()->RegisterDeserializedObjectsForBlackAllocation(
     237      167702 :       reservations_, deserialized_large_objects_, allocated_maps_);
     238       83851 : }
     239             : 
     240           0 : Isolate* DefaultDeserializerAllocator::isolate() const {
     241      167782 :   return deserializer_->isolate();
     242             : }
     243             : 
     244             : }  // namespace internal
     245             : }  // namespace v8

Generated by: LCOV version 1.10