blob: 0e156f75a096f40083750b26e887b92e50929b85 [file] [log] [blame]
// Copyright 2020 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_SERIALIZER_DESERIALIZER_H_
#define V8_SNAPSHOT_SERIALIZER_DESERIALIZER_H_
#include "src/common/assert-scope.h"
#include "src/objects/visitors.h"
#include "src/snapshot/references.h"
namespace v8 {
namespace internal {
class CallHandlerInfo;
class Isolate;
// The Serializer/Deserializer class is a common superclass for Serializer and
// Deserializer which is used to store common constants and methods used by
// both.
class SerializerDeserializer : public RootVisitor {
public:
static void Iterate(Isolate* isolate, RootVisitor* visitor);
protected:
static bool CanBeDeferred(HeapObject o);
void RestoreExternalReferenceRedirector(Isolate* isolate,
Handle<AccessorInfo> accessor_info);
void RestoreExternalReferenceRedirector(
Isolate* isolate, Handle<CallHandlerInfo> call_handler_info);
// clang-format off
#define UNUSED_SERIALIZER_BYTE_CODES(V) \
/* Free range 0x1c..0x1f */ \
V(0x1c) V(0x1d) V(0x1e) V(0x1f) \
/* Free range 0x20..0x2f */ \
V(0x20) V(0x21) V(0x22) V(0x23) V(0x24) V(0x25) V(0x26) V(0x27) \
V(0x28) V(0x29) V(0x2a) V(0x2b) V(0x2c) V(0x2d) V(0x2e) V(0x2f) \
/* Free range 0x30..0x3f */ \
V(0x30) V(0x31) V(0x32) V(0x33) V(0x34) V(0x35) V(0x36) V(0x37) \
V(0x38) V(0x39) V(0x3a) V(0x3b) V(0x3c) V(0x3d) V(0x3e) V(0x3f) \
/* Free range 0x97..0x9f */ \
V(0x98) V(0x99) V(0x9a) V(0x9b) V(0x9c) V(0x9d) V(0x9e) V(0x9f) \
/* Free range 0xa0..0xaf */ \
V(0xa0) V(0xa1) V(0xa2) V(0xa3) V(0xa4) V(0xa5) V(0xa6) V(0xa7) \
V(0xa8) V(0xa9) V(0xaa) V(0xab) V(0xac) V(0xad) V(0xae) V(0xaf) \
/* Free range 0xb0..0xbf */ \
V(0xb0) V(0xb1) V(0xb2) V(0xb3) V(0xb4) V(0xb5) V(0xb6) V(0xb7) \
V(0xb8) V(0xb9) V(0xba) V(0xbb) V(0xbc) V(0xbd) V(0xbe) V(0xbf) \
/* Free range 0xc0..0xcf */ \
V(0xc0) V(0xc1) V(0xc2) V(0xc3) V(0xc4) V(0xc5) V(0xc6) V(0xc7) \
V(0xc8) V(0xc9) V(0xca) V(0xcb) V(0xcc) V(0xcd) V(0xce) V(0xcf) \
/* Free range 0xd0..0xdf */ \
V(0xd0) V(0xd1) V(0xd2) V(0xd3) V(0xd4) V(0xd5) V(0xd6) V(0xd7) \
V(0xd8) V(0xd9) V(0xda) V(0xdb) V(0xdc) V(0xdd) V(0xde) V(0xdf) \
/* Free range 0xe0..0xef */ \
V(0xe0) V(0xe1) V(0xe2) V(0xe3) V(0xe4) V(0xe5) V(0xe6) V(0xe7) \
V(0xe8) V(0xe9) V(0xea) V(0xeb) V(0xec) V(0xed) V(0xee) V(0xef) \
/* Free range 0xf0..0xff */ \
V(0xf0) V(0xf1) V(0xf2) V(0xf3) V(0xf4) V(0xf5) V(0xf6) V(0xf7) \
V(0xf8) V(0xf9) V(0xfa) V(0xfb) V(0xfc) V(0xfd) V(0xfe) V(0xff)
// clang-format on
// The static assert below will trigger when the number of preallocated spaces
// changed. If that happens, update the kNewObject and kBackref bytecode
// ranges in the comments below.
STATIC_ASSERT(4 == kNumberOfSnapshotSpaces);
// First 32 root array items.
static const int kRootArrayConstantsCount = 0x20;
// 32 common raw data lengths.
static const int kFixedRawDataCount = 0x20;
// 16 repeats lengths.
static const int kFixedRepeatCount = 0x10;
// 8 hot (recently seen or back-referenced) objects with optional skip.
static const int kHotObjectCount = 8;
enum Bytecode : byte {
//
// ---------- byte code range 0x00..0x1b ----------
//
// 0x00..0x03 Allocate new object, in specified space.
kNewObject = 0x00,
// Reference to previously allocated object.
kBackref = 0x04,
// Reference to an object in the read only heap.
kReadOnlyHeapRef,
// Object in the startup object cache.
kStartupObjectCache,
// Root array item.
kRootArray,
// Object provided in the attached list.
kAttachedReference,
// Object in the read-only object cache.
kReadOnlyObjectCache,
// Do nothing, used for padding.
kNop,
// A tag emitted at strategic points in the snapshot to delineate sections.
// If the deserializer does not find these at the expected moments then it
// is an indication that the snapshot and the VM do not fit together.
// Examine the build process for architecture, version or configuration
// mismatches.
kSynchronize,
// Repeats of variable length.
kVariableRepeat,
// Used for embedder-allocated backing stores for TypedArrays.
kOffHeapBackingStore,
// Used for embedder-provided serialization data for embedder fields.
kEmbedderFieldsData,
// Raw data of variable length.
kVariableRawData,
// Used to encode external references provided through the API.
kApiReference,
// External reference referenced by id.
kExternalReference,
// Same as two bytecodes above but for serializing sandboxed external
// pointer values.
// TODO(v8:10391): Remove them once all ExternalPointer usages are
// sandbox-ready.
kSandboxedApiReference,
kSandboxedExternalReference,
// Internal reference of a code objects in code stream.
kInternalReference,
// In-place weak references.
kClearedWeakReference,
kWeakPrefix,
// Encodes an off-heap instruction stream target.
kOffHeapTarget,
// Registers the current slot as a "pending" forward reference, to be later
// filled by a corresponding resolution bytecode.
kRegisterPendingForwardRef,
// Resolves an existing "pending" forward reference to point to the current
// object.
kResolvePendingForwardRef,
// Special construction bytecode for the metamap. In theory we could re-use
// forward-references for this, but then the forward reference would be
// registered during object map deserialization, before the object is
// allocated, so there wouldn't be a allocated object whose map field we can
// register as the pending field. We could either hack around this, or
// simply introduce this new bytecode.
kNewMetaMap,
// Special construction bytecode for Code object bodies, which have a more
// complex deserialization ordering and RelocInfo processing.
kCodeBody,
//
// ---------- byte code range 0x40..0x7f ----------
//
// 0x40..0x5f
kRootArrayConstants = 0x40,
// 0x60..0x7f
kFixedRawData = 0x60,
//
// ---------- byte code range 0x80..0x9f ----------
//
// 0x80..0x8f
kFixedRepeat = 0x80,
// 0x90..0x97
kHotObject = 0x90,
};
// Helper class for encoding and decoding a value into and from a bytecode.
//
// The value is encoded by allocating an entire bytecode range, and encoding
// the value as an index in that range, starting at kMinValue; thus the range
// of values
// [kMinValue, kMinValue + 1, ... , kMaxValue]
// is encoded as
// [kBytecode, kBytecode + 1, ... , kBytecode + (N - 1)]
// where N is the number of values, i.e. kMaxValue - kMinValue + 1.
template <Bytecode kBytecode, int kMinValue, int kMaxValue,
typename TValue = int>
struct BytecodeValueEncoder {
STATIC_ASSERT((kBytecode + kMaxValue - kMinValue) <= kMaxUInt8);
static constexpr bool IsEncodable(TValue value) {
return base::IsInRange(static_cast<int>(value), kMinValue, kMaxValue);
}
static constexpr byte Encode(TValue value) {
CONSTEXPR_DCHECK(IsEncodable(value));
return static_cast<byte>(kBytecode + static_cast<int>(value) - kMinValue);
}
static constexpr TValue Decode(byte bytecode) {
CONSTEXPR_DCHECK(base::IsInRange(bytecode,
Encode(static_cast<TValue>(kMinValue)),
Encode(static_cast<TValue>(kMaxValue))));
return static_cast<TValue>(bytecode - kBytecode + kMinValue);
}
};
template <Bytecode bytecode>
using SpaceEncoder =
BytecodeValueEncoder<bytecode, 0, kNumberOfSnapshotSpaces - 1,
SnapshotSpace>;
using NewObject = SpaceEncoder<kNewObject>;
//
// Some other constants.
//
// Sentinel after a new object to indicate that double alignment is needed.
static const int kDoubleAlignmentSentinel = 0;
// Raw data size encoding helpers.
static const int kFirstEncodableFixedRawDataSize = 1;
static const int kLastEncodableFixedRawDataSize =
kFirstEncodableFixedRawDataSize + kFixedRawDataCount - 1;
using FixedRawDataWithSize =
BytecodeValueEncoder<kFixedRawData, kFirstEncodableFixedRawDataSize,
kLastEncodableFixedRawDataSize>;
// Repeat count encoding helpers.
static const int kFirstEncodableRepeatCount = 2;
static const int kLastEncodableFixedRepeatCount =
kFirstEncodableRepeatCount + kFixedRepeatCount - 1;
static const int kFirstEncodableVariableRepeatCount =
kLastEncodableFixedRepeatCount + 1;
using FixedRepeatWithCount =
BytecodeValueEncoder<kFixedRepeat, kFirstEncodableRepeatCount,
kLastEncodableFixedRepeatCount>;
// Encodes/decodes repeat count into a serialized variable repeat count
// value.
struct VariableRepeatCount {
static constexpr bool IsEncodable(int repeat_count) {
return repeat_count >= kFirstEncodableVariableRepeatCount;
}
static constexpr int Encode(int repeat_count) {
CONSTEXPR_DCHECK(IsEncodable(repeat_count));
return repeat_count - kFirstEncodableVariableRepeatCount;
}
static constexpr int Decode(int value) {
return value + kFirstEncodableVariableRepeatCount;
}
};
using RootArrayConstant =
BytecodeValueEncoder<kRootArrayConstants, 0, kRootArrayConstantsCount - 1,
RootIndex>;
using HotObject = BytecodeValueEncoder<kHotObject, 0, kHotObjectCount - 1>;
// This backing store reference value represents nullptr values during
// serialization/deserialization.
static const uint32_t kNullRefSentinel = 0;
};
} // namespace internal
} // namespace v8
#endif // V8_SNAPSHOT_SERIALIZER_DESERIALIZER_H_