blob: 8fa0b245216b6d4b028cfd21ba91c43b9fa4060e [file] [log] [blame]
// 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_INL_H_
#define V8_OBJECTS_BYTECODE_ARRAY_INL_H_
#include "src/common/ptr-compr-inl.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/interpreter/bytecode-register.h"
#include "src/objects/bytecode-array.h"
#include "src/objects/fixed-array-inl.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
CAST_ACCESSOR(BytecodeArray)
OBJECT_CONSTRUCTORS_IMPL(BytecodeArray, ExposedTrustedObject)
SMI_ACCESSORS(BytecodeArray, length, kLengthOffset)
RELEASE_ACQUIRE_SMI_ACCESSORS(BytecodeArray, length, kLengthOffset)
PROTECTED_POINTER_ACCESSORS(BytecodeArray, handler_table, TrustedByteArray,
kHandlerTableOffset)
PROTECTED_POINTER_ACCESSORS(BytecodeArray, constant_pool, TrustedFixedArray,
kConstantPoolOffset)
ACCESSORS(BytecodeArray, wrapper, Tagged<BytecodeWrapper>, kWrapperOffset)
RELEASE_ACQUIRE_PROTECTED_POINTER_ACCESSORS(BytecodeArray,
source_position_table,
TrustedByteArray,
kSourcePositionTableOffset)
uint8_t BytecodeArray::get(int index) const {
DCHECK(index >= 0 && index < length());
return ReadField<uint8_t>(kHeaderSize + index * kCharSize);
}
void BytecodeArray::set(int index, uint8_t value) {
DCHECK(index >= 0 && index < length());
WriteField<uint8_t>(kHeaderSize + index * kCharSize, value);
}
void BytecodeArray::set_frame_size(int32_t frame_size) {
DCHECK_GE(frame_size, 0);
DCHECK(IsAligned(frame_size, kSystemPointerSize));
WriteField<int32_t>(kFrameSizeOffset, frame_size);
}
int32_t BytecodeArray::frame_size() const {
return ReadField<int32_t>(kFrameSizeOffset);
}
int BytecodeArray::register_count() const {
return static_cast<int>(frame_size()) / kSystemPointerSize;
}
void BytecodeArray::set_parameter_count(int32_t number_of_parameters) {
DCHECK_GE(number_of_parameters, 0);
// Parameter count is stored as the size on stack of the parameters to allow
// it to be used directly by generated code.
WriteField<int32_t>(kParameterSizeOffset,
(number_of_parameters << kSystemPointerSizeLog2));
}
interpreter::Register BytecodeArray::incoming_new_target_or_generator_register()
const {
int32_t register_operand =
ReadField<int32_t>(kIncomingNewTargetOrGeneratorRegisterOffset);
if (register_operand == 0) {
return interpreter::Register::invalid_value();
} else {
return interpreter::Register::FromOperand(register_operand);
}
}
void BytecodeArray::set_incoming_new_target_or_generator_register(
interpreter::Register incoming_new_target_or_generator_register) {
if (!incoming_new_target_or_generator_register.is_valid()) {
WriteField<int32_t>(kIncomingNewTargetOrGeneratorRegisterOffset, 0);
} else {
DCHECK(incoming_new_target_or_generator_register.index() <
register_count());
DCHECK_NE(0, incoming_new_target_or_generator_register.ToOperand());
WriteField<int32_t>(kIncomingNewTargetOrGeneratorRegisterOffset,
incoming_new_target_or_generator_register.ToOperand());
}
}
int32_t BytecodeArray::parameter_count() const {
// Parameter count is stored as the size on stack of the parameters to allow
// it to be used directly by generated code.
return ReadField<int32_t>(kParameterSizeOffset) >> kSystemPointerSizeLog2;
}
void BytecodeArray::clear_padding() {
int data_size = kHeaderSize + length();
memset(reinterpret_cast<void*>(address() + data_size), 0,
SizeFor(length()) - data_size);
}
Address BytecodeArray::GetFirstBytecodeAddress() {
return ptr() - kHeapObjectTag + kHeaderSize;
}
bool BytecodeArray::HasSourcePositionTable() const {
return has_source_position_table(kAcquireLoad);
}
DEF_GETTER(BytecodeArray, SourcePositionTable, Tagged<TrustedByteArray>) {
// WARNING: This function may be called from a background thread, hence
// changes to how it accesses the heap can easily lead to bugs.
Tagged<Object> maybe_table = raw_source_position_table(kAcquireLoad);
if (IsTrustedByteArray(maybe_table))
return TrustedByteArray::cast(maybe_table);
DCHECK_EQ(maybe_table, Smi::zero());
return GetIsolateFromWritableObject(*this)
->heap()
->empty_trusted_byte_array();
}
void BytecodeArray::SetSourcePositionsFailedToCollect() {
TaggedField<Object>::Release_Store(*this, kSourcePositionTableOffset,
Smi::zero());
}
DEF_GETTER(BytecodeArray, raw_constant_pool, Tagged<Object>) {
Tagged<Object> value = RawProtectedPointerField(kConstantPoolOffset).load();
// This field might be 0 during deserialization.
DCHECK(value == Smi::zero() || IsTrustedFixedArray(value));
return value;
}
DEF_GETTER(BytecodeArray, raw_handler_table, Tagged<Object>) {
Tagged<Object> value = RawProtectedPointerField(kHandlerTableOffset).load();
// This field might be 0 during deserialization.
DCHECK(value == Smi::zero() || IsTrustedByteArray(value));
return value;
}
DEF_ACQUIRE_GETTER(BytecodeArray, raw_source_position_table, Tagged<Object>) {
Tagged<Object> value =
RawProtectedPointerField(kSourcePositionTableOffset).Acquire_Load();
// This field might be 0 during deserialization or if source positions have
// not been (successfully) collected.
DCHECK(value == Smi::zero() || IsTrustedByteArray(value));
return value;
}
int BytecodeArray::BytecodeArraySize() const { return SizeFor(this->length()); }
DEF_GETTER(BytecodeArray, SizeIncludingMetadata, int) {
int size = BytecodeArraySize();
Tagged<Object> maybe_constant_pool = raw_constant_pool(cage_base);
if (IsTrustedFixedArray(maybe_constant_pool)) {
size += TrustedFixedArray::cast(maybe_constant_pool)->Size(cage_base);
} else {
DCHECK_EQ(maybe_constant_pool, Smi::zero());
}
Tagged<Object> maybe_handler_table = raw_handler_table(cage_base);
if (IsTrustedByteArray(maybe_handler_table)) {
size += TrustedByteArray::cast(maybe_handler_table)->AllocatedSize();
} else {
DCHECK_EQ(maybe_handler_table, Smi::zero());
}
Tagged<Object> maybe_table = raw_source_position_table(kAcquireLoad);
if (IsByteArray(maybe_table)) {
size += ByteArray::cast(maybe_table)->AllocatedSize();
}
return size;
}
CAST_ACCESSOR(BytecodeWrapper)
OBJECT_CONSTRUCTORS_IMPL(BytecodeWrapper, Struct)
TRUSTED_POINTER_ACCESSORS(BytecodeWrapper, bytecode, BytecodeArray,
kBytecodeOffset, kBytecodeArrayIndirectPointerTag)
void BytecodeWrapper::clear_padding() {
WriteField<int32_t>(kPadding1Offset, 0);
WriteField<int32_t>(kPadding2Offset, 0);
}
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_BYTECODE_ARRAY_INL_H_