#ifndef V8_DEOPTIMIZER_FRAME_DESCRIPTION_H_
#define V8_DEOPTIMIZER_FRAME_DESCRIPTION_H_
#include "src/base/memory.h"
#include "src/base/platform/memory.h"
#include "src/codegen/register.h"
#include "src/common/simd128.h"
#include "src/execution/frame-constants.h"
#include "src/utils/boxed-float.h"
namespace v8 {
namespace internal {
class RegisterValues {
public:
intptr_t GetRegister(unsigned n) const {
V8_ASSUME(n < arraysize(registers_));
return registers_[n];
}
Float32 GetFloatRegister(unsigned n) const;
Float64 GetDoubleRegister(unsigned n) const;
void SetDoubleRegister(unsigned n, Float64 value);
Simd128 GetSimd128Register(unsigned n) const {
V8_ASSUME(n < arraysize(simd128_registers_));
return simd128_registers_[n];
}
void SetRegister(unsigned n, intptr_t value) {
V8_ASSUME(n < arraysize(registers_));
registers_[n] = value;
}
void SetSimd128Register(unsigned n, Simd128 value) {
V8_ASSUME(n < arraysize(simd128_registers_));
simd128_registers_[n] = value;
}
intptr_t registers_[Register::kNumRegisters];
static_assert(sizeof(Simd128) == kSimd128Size, "size mismatch");
#if defined(V8_TARGET_ARCH_RISCV64) || defined(V8_TARGET_ARCH_RISCV32)
Float64 double_registers_[DoubleRegister::kNumRegisters];
Simd128 simd128_registers_[Simd128Register::kNumRegisters];
#else
Simd128 simd128_registers_[Simd128Register::kNumRegisters];
#endif
};
class FrameDescription {
public:
static FrameDescription* Create(uint32_t frame_size, int parameter_count,
Isolate* isolate) {
return new (frame_size)
FrameDescription(frame_size, parameter_count, isolate);
}
void operator delete(void* description) { base::Free(description); }
uint32_t GetFrameSize() const {
USE(frame_content_);
DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
return static_cast<uint32_t>(frame_size_);
}
intptr_t GetFrameSlot(unsigned offset) {
return *GetFrameSlotPointer(offset);
}
unsigned GetLastArgumentSlotOffset(bool pad_arguments = true) {
int parameter_slots = parameter_count();
if (pad_arguments) {
parameter_slots = AddArgumentPaddingSlots(parameter_slots);
}
return GetFrameSize() - parameter_slots * kSystemPointerSize;
}
Address GetFramePointerAddress() {
const bool pad_arguments_bottom_frame = false;
int fp_offset = GetLastArgumentSlotOffset(pad_arguments_bottom_frame) -
StandardFrameConstants::kCallerSPOffset;
return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
}
RegisterValues* GetRegisterValues() { return ®ister_values_; }
void SetFrameSlot(unsigned offset, intptr_t value) {
*GetFrameSlotPointer(offset) = value;
}
void SetLiftoffFrameSlot32(unsigned offset, int32_t value) {
base::WriteUnalignedValue(
reinterpret_cast<char*>(GetFrameSlotPointer(offset)), value);
}
void SetLiftoffFrameSlot64(unsigned offset, int64_t value) {
base::WriteUnalignedValue(
reinterpret_cast<char*>(GetFrameSlotPointer(offset)), value);
}
void SetLiftoffFrameSlotPointer(unsigned offset, intptr_t value) {
if constexpr (Is64()) {
SetLiftoffFrameSlot64(offset, value);
} else {
SetLiftoffFrameSlot32(offset, value);
}
}
void SetCallerPc(unsigned offset, intptr_t value);
void SetCallerFp(unsigned offset, intptr_t value);
void SetCallerConstantPool(unsigned offset, intptr_t value);
intptr_t GetRegister(unsigned n) const {
return register_values_.GetRegister(n);
}
Float64 GetDoubleRegister(unsigned n) const {
return register_values_.GetDoubleRegister(n);
}
Float32 GetFloatRegister(unsigned n) const {
return register_values_.GetFloatRegister(n);
}
void SetRegister(unsigned n, intptr_t value) {
register_values_.SetRegister(n, value);
}
void SetDoubleRegister(unsigned n, Float64 value) {
register_values_.SetDoubleRegister(n, value);
}
void SetSimd128Register(unsigned n, Simd128 value) {
register_values_.SetSimd128Register(n, value);
}
intptr_t GetTop() const { return top_; }
void SetTop(intptr_t top) { top_ = top; }
intptr_t GetPc() const { return pc_; }
void SetPc(intptr_t pc);
intptr_t GetFp() const { return fp_; }
void SetFp(intptr_t frame_pointer) { fp_ = frame_pointer; }
intptr_t GetConstantPool() const { return constant_pool_; }
void SetConstantPool(intptr_t constant_pool) {
constant_pool_ = constant_pool;
}
bool HasCallerPc() const { return caller_pc_ != 0; }
intptr_t GetCallerPc() const { return caller_pc_; }
void SetContinuation(intptr_t pc) { continuation_ = pc; }
intptr_t GetContinuation() const { return continuation_; }
int parameter_count() { return parameter_count_; }
static int registers_offset() {
return offsetof(FrameDescription, register_values_.registers_);
}
#if defined(V8_TARGET_ARCH_RISCV64) || defined(V8_TARGET_ARCH_RISCV32)
static constexpr int double_registers_offset() {
return offsetof(FrameDescription, register_values_.double_registers_);
}
#endif
static constexpr int simd128_registers_offset() {
return offsetof(FrameDescription, register_values_.simd128_registers_);
}
static int frame_size_offset() {
return offsetof(FrameDescription, frame_size_);
}
static int pc_offset() { return offsetof(FrameDescription, pc_); }
static int continuation_offset() {
return offsetof(FrameDescription, continuation_);
}
static int frame_content_offset() {
return offsetof(FrameDescription, frame_content_);
}
private:
FrameDescription(uint32_t frame_size, int parameter_count, Isolate* isolate)
: frame_size_(frame_size),
parameter_count_(parameter_count),
top_(kZapUint32),
pc_(kZapUint32),
fp_(kZapUint32),
constant_pool_(kZapUint32),
isolate_(isolate) {
USE(isolate_);
for (int r = 0; r < Register::kNumRegisters; r++) {
#if defined(V8_OS_WIN) && defined(V8_TARGET_ARCH_ARM64)
const int kPlatformRegister = 18;
if (r != kPlatformRegister) {
SetRegister(r, kZapUint32);
}
#else
SetRegister(r, kZapUint32);
#endif
}
for (unsigned o = 0; o < frame_size; o += kSystemPointerSize) {
SetFrameSlot(o, kZapUint32);
}
}
void* operator new(size_t size, uint32_t frame_size) {
return base::Malloc(size + frame_size - kSystemPointerSize);
}
static const uint32_t kZapUint32 = 0xbeeddead;
uintptr_t frame_size_;
int parameter_count_;
RegisterValues register_values_;
intptr_t top_;
intptr_t pc_;
intptr_t fp_;
intptr_t constant_pool_;
intptr_t caller_pc_ = 0;
Isolate* isolate_;
intptr_t continuation_;
intptr_t frame_content_[1];
intptr_t* GetFrameSlotPointer(unsigned offset) {
DCHECK(offset < frame_size_);
return reinterpret_cast<intptr_t*>(reinterpret_cast<Address>(this) +
frame_content_offset() + offset);
}
};
}
}
#endif