Home | History | Annotate | Download | only in snapshot
      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_SNAPSHOT_BUILTIN_DESERIALIZER_ALLOCATOR_H_
      6 #define V8_SNAPSHOT_BUILTIN_DESERIALIZER_ALLOCATOR_H_
      7 
      8 #include <unordered_set>
      9 
     10 #include "src/globals.h"
     11 #include "src/heap/heap.h"
     12 #include "src/interpreter/interpreter.h"
     13 #include "src/snapshot/serializer-common.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 
     18 template <class AllocatorT>
     19 class Deserializer;
     20 
     21 class BuiltinDeserializer;
     22 class BuiltinSnapshotUtils;
     23 
     24 class BuiltinDeserializerAllocator final {
     25   using BSU = BuiltinSnapshotUtils;
     26   using Bytecode = interpreter::Bytecode;
     27   using OperandScale = interpreter::OperandScale;
     28 
     29  public:
     30   BuiltinDeserializerAllocator(
     31       Deserializer<BuiltinDeserializerAllocator>* deserializer);
     32 
     33   ~BuiltinDeserializerAllocator();
     34 
     35   // ------- Allocation Methods -------
     36   // Methods related to memory allocation during deserialization.
     37 
     38   // Allocation works differently here than in other deserializers. Instead of
     39   // a statically-known memory area determined at serialization-time, our
     40   // memory requirements here are determined at runtime. Another major
     41   // difference is that we create builtin Code objects up-front (before
     42   // deserialization) in order to avoid having to patch builtin references
     43   // later on. See also the kBuiltin case in deserializer.cc.
     44   //
     45   // There are three ways that we use to reserve / allocate space. In all
     46   // cases, required objects are requested from the GC prior to
     47   // deserialization. 1. pre-allocated builtin code objects are written into
     48   // the builtins table (this is to make deserialization of builtin references
     49   // easier). Pre-allocated handler code objects are 2. stored in the
     50   // {handler_allocations_} vector (at eager-deserialization time) and 3.
     51   // stored in {handler_allocation_} (at lazy-deserialization time).
     52   //
     53   // Allocate simply returns the pre-allocated object prepared by
     54   // InitializeFromReservations.
     55   Address Allocate(AllocationSpace space, int size);
     56 
     57   void MoveToNextChunk(AllocationSpace space) { UNREACHABLE(); }
     58   void SetAlignment(AllocationAlignment alignment) { UNREACHABLE(); }
     59 
     60   void set_next_reference_is_weak(bool next_reference_is_weak) {
     61     next_reference_is_weak_ = next_reference_is_weak;
     62   }
     63 
     64   bool GetAndClearNextReferenceIsWeak() {
     65     bool saved = next_reference_is_weak_;
     66     next_reference_is_weak_ = false;
     67     return saved;
     68   }
     69 
     70 #ifdef DEBUG
     71   bool next_reference_is_weak() const { return next_reference_is_weak_; }
     72 #endif
     73 
     74   HeapObject* GetMap(uint32_t index) { UNREACHABLE(); }
     75   HeapObject* GetLargeObject(uint32_t index) { UNREACHABLE(); }
     76   HeapObject* GetObject(AllocationSpace space, uint32_t chunk_index,
     77                         uint32_t chunk_offset) {
     78     UNREACHABLE();
     79   }
     80 
     81   // ------- Reservation Methods -------
     82   // Methods related to memory reservations (prior to deserialization).
     83 
     84   // Builtin deserialization does not bake reservations into the snapshot, hence
     85   // this is a nop.
     86   void DecodeReservation(std::vector<SerializedData::Reservation> res) {}
     87 
     88   // These methods are used to pre-allocate builtin objects prior to
     89   // deserialization.
     90   // TODO(jgruber): Refactor reservation/allocation logic in deserializers to
     91   // make this less messy.
     92   Heap::Reservation CreateReservationsForEagerBuiltinsAndHandlers();
     93   void InitializeFromReservations(const Heap::Reservation& reservation);
     94 
     95   // Creates reservations and initializes the builtins table in preparation for
     96   // lazily deserializing a single builtin.
     97   void ReserveAndInitializeBuiltinsTableForBuiltin(int builtin_id);
     98 
     99   // Pre-allocates a code object preparation for lazily deserializing a single
    100   // handler.
    101   void ReserveForHandler(Bytecode bytecode, OperandScale operand_scale);
    102 
    103 #ifdef DEBUG
    104   bool ReservationsAreFullyUsed() const;
    105 #endif
    106 
    107  private:
    108   Isolate* isolate() const;
    109   BuiltinDeserializer* deserializer() const;
    110 
    111   // Used after memory allocation prior to isolate initialization, to register
    112   // the newly created object in code space and add it to the builtins table.
    113   void InitializeBuiltinFromReservation(const Heap::Chunk& chunk,
    114                                         int builtin_id);
    115 
    116   // As above, but for interpreter bytecode handlers.
    117   void InitializeHandlerFromReservation(
    118       const Heap::Chunk& chunk, interpreter::Bytecode bytecode,
    119       interpreter::OperandScale operand_scale);
    120 
    121 #ifdef DEBUG
    122   void RegisterCodeObjectReservation(int code_object_id);
    123   void RegisterCodeObjectAllocation(int code_object_id);
    124   std::unordered_set<int> unused_reservations_;
    125 #endif
    126 
    127  private:
    128   // The current deserializer. Note that this always points to a
    129   // BuiltinDeserializer instance, but we can't perform the cast during
    130   // construction since that makes vtable-based checks fail.
    131   Deserializer<BuiltinDeserializerAllocator>* const deserializer_;
    132 
    133   // Stores allocated space for bytecode handlers during eager deserialization.
    134   std::vector<Address>* handler_allocations_ = nullptr;
    135 
    136   // Stores the allocated space for a single handler during lazy
    137   // deserialization.
    138   Address handler_allocation_ = kNullAddress;
    139 
    140   bool next_reference_is_weak_ = false;
    141 
    142   DISALLOW_COPY_AND_ASSIGN(BuiltinDeserializerAllocator)
    143 };
    144 
    145 }  // namespace internal
    146 }  // namespace v8
    147 
    148 #endif  // V8_SNAPSHOT_BUILTIN_DESERIALIZER_ALLOCATOR_H_
    149