blob: eb04b54025a888297c3452881a1e4d872d359878 [file] [log] [blame]
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_SNAPSHOT_BUILTIN_DESERIALIZER_ALLOCATOR_H_
#define V8_SNAPSHOT_BUILTIN_DESERIALIZER_ALLOCATOR_H_
#include <unordered_set>
#include "src/globals.h"
#include "src/heap/heap.h"
#include "src/interpreter/interpreter.h"
#include "src/snapshot/serializer-common.h"
namespace v8 {
namespace internal {
template <class AllocatorT>
class Deserializer;
class BuiltinDeserializer;
class BuiltinSnapshotUtils;
class BuiltinDeserializerAllocator final {
using BSU = BuiltinSnapshotUtils;
using Bytecode = interpreter::Bytecode;
using OperandScale = interpreter::OperandScale;
public:
BuiltinDeserializerAllocator(
Deserializer<BuiltinDeserializerAllocator>* deserializer);
~BuiltinDeserializerAllocator();
// ------- Allocation Methods -------
// Methods related to memory allocation during deserialization.
// Allocation works differently here than in other deserializers. Instead of
// a statically-known memory area determined at serialization-time, our
// memory requirements here are determined at runtime. Another major
// difference is that we create builtin Code objects up-front (before
// deserialization) in order to avoid having to patch builtin references
// later on. See also the kBuiltin case in deserializer.cc.
//
// There are three ways that we use to reserve / allocate space. In all
// cases, required objects are requested from the GC prior to
// deserialization. 1. pre-allocated builtin code objects are written into
// the builtins table (this is to make deserialization of builtin references
// easier). Pre-allocated handler code objects are 2. stored in the
// {handler_allocations_} vector (at eager-deserialization time) and 3.
// stored in {handler_allocation_} (at lazy-deserialization time).
//
// Allocate simply returns the pre-allocated object prepared by
// InitializeFromReservations.
Address Allocate(AllocationSpace space, int size);
void MoveToNextChunk(AllocationSpace space) { UNREACHABLE(); }
void SetAlignment(AllocationAlignment alignment) { UNREACHABLE(); }
HeapObject* GetMap(uint32_t index) { UNREACHABLE(); }
HeapObject* GetLargeObject(uint32_t index) { UNREACHABLE(); }
HeapObject* GetObject(AllocationSpace space, uint32_t chunk_index,
uint32_t chunk_offset) {
UNREACHABLE();
}
// ------- Reservation Methods -------
// Methods related to memory reservations (prior to deserialization).
// Builtin deserialization does not bake reservations into the snapshot, hence
// this is a nop.
void DecodeReservation(std::vector<SerializedData::Reservation> res) {}
// These methods are used to pre-allocate builtin objects prior to
// deserialization.
// TODO(jgruber): Refactor reservation/allocation logic in deserializers to
// make this less messy.
Heap::Reservation CreateReservationsForEagerBuiltinsAndHandlers();
void InitializeFromReservations(const Heap::Reservation& reservation);
// Creates reservations and initializes the builtins table in preparation for
// lazily deserializing a single builtin.
void ReserveAndInitializeBuiltinsTableForBuiltin(int builtin_id);
// Pre-allocates a code object preparation for lazily deserializing a single
// handler.
void ReserveForHandler(Bytecode bytecode, OperandScale operand_scale);
#ifdef DEBUG
bool ReservationsAreFullyUsed() const;
#endif
private:
Isolate* isolate() const;
BuiltinDeserializer* deserializer() const;
// Used after memory allocation prior to isolate initialization, to register
// the newly created object in code space and add it to the builtins table.
void InitializeBuiltinFromReservation(const Heap::Chunk& chunk,
int builtin_id);
// As above, but for interpreter bytecode handlers.
void InitializeHandlerFromReservation(
const Heap::Chunk& chunk, interpreter::Bytecode bytecode,
interpreter::OperandScale operand_scale);
#ifdef DEBUG
void RegisterCodeObjectReservation(int code_object_id);
void RegisterCodeObjectAllocation(int code_object_id);
std::unordered_set<int> unused_reservations_;
#endif
private:
// The current deserializer. Note that this always points to a
// BuiltinDeserializer instance, but we can't perform the cast during
// construction since that makes vtable-based checks fail.
Deserializer<BuiltinDeserializerAllocator>* const deserializer_;
// Stores allocated space for bytecode handlers during eager deserialization.
std::vector<Address>* handler_allocations_ = nullptr;
// Stores the allocated space for a single handler during lazy
// deserialization.
Address handler_allocation_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(BuiltinDeserializerAllocator)
};
} // namespace internal
} // namespace v8
#endif // V8_SNAPSHOT_BUILTIN_DESERIALIZER_ALLOCATOR_H_