blob: 5f900accc63cfe91f50bfe8d783487e2d04b6cf7 [file] [edit]
// Copyright 2021 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.
#include "src/deoptimizer/translation-array.h"
#include "src/base/vlq.h"
#include "src/deoptimizer/translated-state.h"
#include "src/objects/fixed-array-inl.h"
#include "third_party/zlib/google/compression_utils_portable.h"
namespace v8 {
namespace internal {
namespace {
// Constants describing compressed TranslationArray layout. Only relevant if
// --turbo-compress-translation-arrays is enabled.
constexpr int kUncompressedSizeOffset = 0;
constexpr int kUncompressedSizeSize = kInt32Size;
constexpr int kCompressedDataOffset =
kUncompressedSizeOffset + kUncompressedSizeSize;
constexpr int kTranslationArrayElementSize = kInt32Size;
} // namespace
TranslationArrayIterator::TranslationArrayIterator(TranslationArray buffer,
int index)
: buffer_(buffer), index_(index) {
if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) {
const int size = buffer_.get_int(kUncompressedSizeOffset);
uncompressed_contents_.insert(uncompressed_contents_.begin(), size, 0);
uLongf uncompressed_size = size * kTranslationArrayElementSize;
CHECK_EQ(zlib_internal::UncompressHelper(
zlib_internal::ZRAW,
base::bit_cast<Bytef*>(uncompressed_contents_.data()),
&uncompressed_size,
buffer_.GetDataStartAddress() + kCompressedDataOffset,
buffer_.DataSize()),
Z_OK);
DCHECK(index >= 0 && index < size);
} else {
DCHECK(index >= 0 && index < buffer.length());
}
}
int32_t TranslationArrayIterator::Next() {
if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) {
return uncompressed_contents_[index_++];
} else {
int32_t value = base::VLQDecode(buffer_.GetDataStartAddress(), &index_);
DCHECK_LE(index_, buffer_.length());
return value;
}
}
bool TranslationArrayIterator::HasNext() const {
if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) {
return index_ < static_cast<int>(uncompressed_contents_.size());
} else {
return index_ < buffer_.length();
}
}
void TranslationArrayBuilder::Add(int32_t value) {
if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) {
contents_for_compression_.push_back(value);
} else {
base::VLQEncode(&contents_, value);
}
}
Handle<TranslationArray> TranslationArrayBuilder::ToTranslationArray(
Factory* factory) {
if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) {
const int input_size = SizeInBytes();
uLongf compressed_data_size = compressBound(input_size);
ZoneVector<byte> compressed_data(compressed_data_size, zone());
CHECK_EQ(
zlib_internal::CompressHelper(
zlib_internal::ZRAW, compressed_data.data(), &compressed_data_size,
base::bit_cast<const Bytef*>(contents_for_compression_.data()),
input_size, Z_DEFAULT_COMPRESSION, nullptr, nullptr),
Z_OK);
const int translation_array_size =
static_cast<int>(compressed_data_size) + kUncompressedSizeSize;
Handle<TranslationArray> result =
factory->NewByteArray(translation_array_size, AllocationType::kOld);
result->set_int(kUncompressedSizeOffset, Size());
std::memcpy(result->GetDataStartAddress() + kCompressedDataOffset,
compressed_data.data(), compressed_data_size);
return result;
} else {
Handle<TranslationArray> result =
factory->NewByteArray(SizeInBytes(), AllocationType::kOld);
memcpy(result->GetDataStartAddress(), contents_.data(),
contents_.size() * sizeof(uint8_t));
return result;
}
}
void TranslationArrayBuilder::BeginBuiltinContinuationFrame(
BytecodeOffset bytecode_offset, int literal_id, unsigned height) {
auto opcode = TranslationOpcode::BUILTIN_CONTINUATION_FRAME;
Add(opcode);
Add(bytecode_offset.ToInt());
Add(literal_id);
Add(height);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3);
}
#if V8_ENABLE_WEBASSEMBLY
void TranslationArrayBuilder::BeginJSToWasmBuiltinContinuationFrame(
BytecodeOffset bytecode_offset, int literal_id, unsigned height,
base::Optional<wasm::ValueKind> return_kind) {
auto opcode = TranslationOpcode::JS_TO_WASM_BUILTIN_CONTINUATION_FRAME;
Add(opcode);
Add(bytecode_offset.ToInt());
Add(literal_id);
Add(height);
Add(return_kind ? static_cast<int>(return_kind.value()) : kNoWasmReturnKind);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 4);
}
#endif // V8_ENABLE_WEBASSEMBLY
void TranslationArrayBuilder::BeginJavaScriptBuiltinContinuationFrame(
BytecodeOffset bytecode_offset, int literal_id, unsigned height) {
auto opcode = TranslationOpcode::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME;
Add(opcode);
Add(bytecode_offset.ToInt());
Add(literal_id);
Add(height);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3);
}
void TranslationArrayBuilder::BeginJavaScriptBuiltinContinuationWithCatchFrame(
BytecodeOffset bytecode_offset, int literal_id, unsigned height) {
auto opcode =
TranslationOpcode::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME;
Add(opcode);
Add(bytecode_offset.ToInt());
Add(literal_id);
Add(height);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3);
}
void TranslationArrayBuilder::BeginConstructStubFrame(
BytecodeOffset bytecode_offset, int literal_id, unsigned height) {
auto opcode = TranslationOpcode::CONSTRUCT_STUB_FRAME;
Add(opcode);
Add(bytecode_offset.ToInt());
Add(literal_id);
Add(height);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3);
}
void TranslationArrayBuilder::BeginInlinedExtraArguments(int literal_id,
unsigned height) {
auto opcode = TranslationOpcode::INLINED_EXTRA_ARGUMENTS;
Add(opcode);
Add(literal_id);
Add(height);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 2);
}
void TranslationArrayBuilder::BeginInterpretedFrame(
BytecodeOffset bytecode_offset, int literal_id, unsigned height,
int return_value_offset, int return_value_count) {
auto opcode = TranslationOpcode::INTERPRETED_FRAME;
Add(opcode);
Add(bytecode_offset.ToInt());
Add(literal_id);
Add(height);
Add(return_value_offset);
Add(return_value_count);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 5);
}
void TranslationArrayBuilder::ArgumentsElements(CreateArgumentsType type) {
auto opcode = TranslationOpcode::ARGUMENTS_ELEMENTS;
Add(opcode);
Add(static_cast<uint8_t>(type));
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::ArgumentsLength() {
auto opcode = TranslationOpcode::ARGUMENTS_LENGTH;
Add(opcode);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 0);
}
void TranslationArrayBuilder::BeginCapturedObject(int length) {
auto opcode = TranslationOpcode::CAPTURED_OBJECT;
Add(opcode);
Add(length);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::DuplicateObject(int object_index) {
auto opcode = TranslationOpcode::DUPLICATED_OBJECT;
Add(opcode);
Add(object_index);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreRegister(Register reg) {
auto opcode = TranslationOpcode::REGISTER;
Add(opcode);
Add(reg.code());
}
void TranslationArrayBuilder::StoreInt32Register(Register reg) {
auto opcode = TranslationOpcode::INT32_REGISTER;
Add(opcode);
Add(reg.code());
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreInt64Register(Register reg) {
auto opcode = TranslationOpcode::INT64_REGISTER;
Add(opcode);
Add(reg.code());
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreUint32Register(Register reg) {
auto opcode = TranslationOpcode::UINT32_REGISTER;
Add(opcode);
Add(reg.code());
}
void TranslationArrayBuilder::StoreBoolRegister(Register reg) {
auto opcode = TranslationOpcode::BOOL_REGISTER;
Add(opcode);
Add(reg.code());
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreFloatRegister(FloatRegister reg) {
auto opcode = TranslationOpcode::FLOAT_REGISTER;
Add(opcode);
Add(reg.code());
}
void TranslationArrayBuilder::StoreDoubleRegister(DoubleRegister reg) {
auto opcode = TranslationOpcode::DOUBLE_REGISTER;
Add(opcode);
Add(reg.code());
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreStackSlot(int index) {
auto opcode = TranslationOpcode::STACK_SLOT;
Add(opcode);
Add(index);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreInt32StackSlot(int index) {
auto opcode = TranslationOpcode::INT32_STACK_SLOT;
Add(opcode);
Add(index);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreInt64StackSlot(int index) {
auto opcode = TranslationOpcode::INT64_STACK_SLOT;
Add(opcode);
Add(index);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreUint32StackSlot(int index) {
auto opcode = TranslationOpcode::UINT32_STACK_SLOT;
Add(opcode);
Add(index);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreBoolStackSlot(int index) {
auto opcode = TranslationOpcode::BOOL_STACK_SLOT;
Add(opcode);
Add(index);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreFloatStackSlot(int index) {
auto opcode = TranslationOpcode::FLOAT_STACK_SLOT;
Add(opcode);
Add(index);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreDoubleStackSlot(int index) {
auto opcode = TranslationOpcode::DOUBLE_STACK_SLOT;
Add(opcode);
Add(index);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::StoreLiteral(int literal_id) {
auto opcode = TranslationOpcode::LITERAL;
Add(opcode);
Add(literal_id);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1);
}
void TranslationArrayBuilder::AddUpdateFeedback(int vector_literal, int slot) {
auto opcode = TranslationOpcode::UPDATE_FEEDBACK;
Add(opcode);
Add(vector_literal);
Add(slot);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 2);
}
void TranslationArrayBuilder::StoreJSFrameFunction() {
StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
StandardFrameConstants::kFunctionOffset) /
kSystemPointerSize);
}
} // namespace internal
} // namespace v8