blob: 2546b616968a5dea7c1c7f5f44b76372eac7d005 [file]
// Copyright 2023 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_OBJECTS_BYTECODE_ARRAY_H_
#define V8_OBJECTS_BYTECODE_ARRAY_H_
#include "src/objects/struct.h"
#include "src/objects/trusted-object.h"
#include "src/objects/trusted-pointer.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
class BytecodeWrapper;
namespace interpreter {
class Register;
} // namespace interpreter
// BytecodeArray represents a sequence of interpreter bytecodes.
V8_OBJECT class BytecodeArray : public ExposedTrustedObject {
public:
// The length of this bytecode array, in bytes.
inline int length() const;
inline int length(AcquireLoadTag tag) const;
inline void set_length(int value);
inline void set_length(int value, ReleaseStoreTag tag);
// The handler table contains offsets of exception handlers.
DECL_PROTECTED_POINTER_ACCESSORS(handler_table, TrustedByteArray)
DECL_PROTECTED_POINTER_ACCESSORS(constant_pool, TrustedFixedArray)
// The BytecodeWrapper for this BytecodeArray. When the sandbox is enabled,
// the BytecodeArray lives in trusted space outside of the sandbox, but the
// wrapper object lives inside the main heap and therefore inside the
// sandbox. As such, the wrapper object can be used in cases where a
// BytecodeArray needs to be referenced alongside other tagged pointer
// references (so for example inside a FixedArray).
inline Tagged<BytecodeWrapper> wrapper() const;
inline void set_wrapper(Tagged<BytecodeWrapper> value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Source position table. Can contain:
// * Smi::zero() (initial value, or if an error occurred while explicitly
// collecting source positions for pre-existing bytecode).
// * empty_trusted_byte_array (for bytecode generated for functions that will
// never have source positions, e.g. native functions).
// * TrustedByteArray (if source positions were collected for the bytecode)
DECL_RELEASE_ACQUIRE_PROTECTED_POINTER_ACCESSORS(source_position_table,
TrustedByteArray)
DECL_INT32_ACCESSORS(frame_size)
inline int32_t max_frame_size() const;
static constexpr int SizeFor(int length) {
return OBJECT_POINTER_ALIGN(kHeaderSize + length);
}
inline uint8_t get(int index) const;
inline void set(int index, uint8_t value);
inline Address GetFirstBytecodeAddress();
// Note: The register count is derived from frame_size.
inline int register_count() const;
// Note: the parameter count includes the implicit 'this' receiver.
inline uint16_t parameter_count() const;
inline uint16_t parameter_count_without_receiver() const;
inline void set_parameter_count(uint16_t number_of_parameters);
inline uint16_t max_arguments() const;
inline void set_max_arguments(uint16_t max_arguments);
inline interpreter::Register incoming_new_target_or_generator_register()
const;
inline void set_incoming_new_target_or_generator_register(
interpreter::Register incoming_new_target_or_generator_register);
inline bool HasSourcePositionTable() const;
int SourcePosition(int offset) const;
int SourceStatementPosition(int offset) const;
// If source positions have not been collected or an exception has been thrown
// this will return the empty_trusted_byte_array.
inline Tagged<TrustedByteArray> SourcePositionTable() const;
// Raw accessors to access these fields during code cache deserialization.
inline Tagged<Union<Smi, TrustedFixedArray>> raw_constant_pool() const;
inline Tagged<Union<Smi, TrustedByteArray>> raw_handler_table() const;
// This accessor can also be used when it's not guaranteed that a source
// position table exists, for example because it hasn't been collected. In
// that case, Smi::zero() will be returned.
inline Tagged<Object> raw_source_position_table(AcquireLoadTag) const;
// Indicates that an attempt was made to collect source positions, but that it
// failed, most likely due to stack exhaustion. When in this state
// |SourcePositionTable| will return an empty byte array.
inline void SetSourcePositionsFailedToCollect();
inline int BytecodeArraySize() const;
// Returns the size of bytecode and its metadata. This includes the size of
// bytecode, constant pool, source position table, and handler table.
inline int SizeIncludingMetadata() const;
DECL_PRINTER(BytecodeArray)
DECL_VERIFIER(BytecodeArray)
V8_EXPORT_PRIVATE void PrintJson(std::ostream& os);
V8_EXPORT_PRIVATE void Disassemble(std::ostream& os);
V8_EXPORT_PRIVATE static void Disassemble(Handle<BytecodeArray> handle,
std::ostream& os);
void CopyBytecodesTo(Tagged<BytecodeArray> to);
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic.
inline void clear_padding();
class BodyDescriptor;
static const int kHeaderSize;
static const int kBytesOffset;
// Maximal memory consumption for a single BytecodeArray.
static const int kMaxSize = 512 * MB;
// Maximal length of a single BytecodeArray.
static const int kMaxLength;
private:
friend class BytecodeVerifier;
friend class NoOpBytecodeVerifier;
// Mark this BytecodeArray as successfully verified. Must only be called by
// the BytecodeVerifier after successful verification.
// Under the hood, this will "publish" the BytecodeArray, making it
// accessible to the sandbox. As such, (only) after this step the
// BytecodeArray can be executed in the interpreter.
inline void MarkVerified(IsolateForSandbox isolate);
public:
TaggedMember<Smi> length_;
TaggedMember<BytecodeWrapper> wrapper_;
ProtectedTaggedMember<TrustedByteArray> source_position_table_;
ProtectedTaggedMember<TrustedByteArray> handler_table_;
ProtectedTaggedMember<TrustedFixedArray> constant_pool_;
int32_t frame_size_;
uint16_t parameter_size_;
uint16_t max_arguments_;
int32_t incoming_new_target_or_generator_register_;
#if TAGGED_SIZE_8_BYTES
uint32_t optional_padding_;
#endif
FLEXIBLE_ARRAY_MEMBER(uint8_t, bytes);
} V8_OBJECT_END;
inline constexpr int BytecodeArray::kHeaderSize =
OFFSET_OF_DATA_START(BytecodeArray);
inline constexpr int BytecodeArray::kBytesOffset =
OFFSET_OF_DATA_START(BytecodeArray);
inline constexpr int BytecodeArray::kMaxLength =
BytecodeArray::kMaxSize - BytecodeArray::kHeaderSize;
// A BytecodeWrapper wraps a BytecodeArray but lives inside the sandbox. This
// can be useful for example when a reference to a BytecodeArray needs to be
// stored along other tagged pointers inside an array or similar datastructure.
V8_OBJECT class BytecodeWrapper : public Struct {
public:
DECL_TRUSTED_POINTER_ACCESSORS(bytecode, BytecodeArray)
DECL_PRINTER(BytecodeWrapper)
DECL_VERIFIER(BytecodeWrapper)
class BodyDescriptor;
public:
TrustedPointerMember<BytecodeArray, kBytecodeArrayIndirectPointerTag>
bytecode_;
} V8_OBJECT_END;
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_BYTECODE_ARRAY_H_