Commit 957d872b authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[deoptimizer] Refactor translation opcodes and array builder

The final CL of this chain, this extracts translation opcodes into the
TranslationOpcode class, and merges logic for TranslationArray
creation into TranslationArrayBuilder.

Drive-by: Pull TranslationArray printing logic into
translation-state.cc.

Bug: v8:11332
Change-Id: Ia4bbb6cdd15ea3318dfb9b7edb6eb881530dda54
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2642254
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72278}
parent 107629d1
......@@ -2644,8 +2644,7 @@ v8_source_set("v8_base_without_compiler") {
"src/deoptimizer/translated-state.h",
"src/deoptimizer/translation-array.cc",
"src/deoptimizer/translation-array.h",
"src/deoptimizer/translations.cc",
"src/deoptimizer/translations.h",
"src/deoptimizer/translation-opcode.h",
"src/diagnostics/basic-block-profiler.cc",
"src/diagnostics/basic-block-profiler.h",
"src/diagnostics/code-tracer.h",
......
This diff is collapsed.
......@@ -394,16 +394,14 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler {
OutputFrameStateCombine state_combine);
void BuildTranslationForFrameStateDescriptor(
FrameStateDescriptor* descriptor, InstructionOperandIterator* iter,
Translation* translation, OutputFrameStateCombine state_combine);
OutputFrameStateCombine state_combine);
void TranslateStateValueDescriptor(StateValueDescriptor* desc,
StateValueList* nested,
Translation* translation,
InstructionOperandIterator* iter);
void TranslateFrameStateDescriptorOperands(FrameStateDescriptor* desc,
InstructionOperandIterator* iter,
Translation* translation);
void AddTranslationForOperand(Translation* translation, Instruction* instr,
InstructionOperand* op, MachineType type);
InstructionOperandIterator* iter);
void AddTranslationForOperand(Instruction* instr, InstructionOperand* op,
MachineType type);
void MarkLazyDeoptSite();
void PrepareForDeoptimizationExits(ZoneDeque<DeoptimizationExit*>* exits);
......@@ -444,7 +442,7 @@ class V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler {
ZoneDeque<DeoptimizationExit*> deoptimization_exits_;
ZoneDeque<DeoptimizationLiteral> deoptimization_literals_;
size_t inlined_function_count_ = 0;
TranslationBuffer translations_;
TranslationArrayBuilder translations_;
int handler_table_offset_ = 0;
int last_lazy_deopt_pc_ = 0;
......
......@@ -7,7 +7,7 @@
#include <vector>
#include "src/deoptimizer/translations.h"
#include "src/deoptimizer/translated-state.h"
namespace v8 {
namespace internal {
......
......@@ -7,10 +7,11 @@
#include <vector>
#include "src/builtins/builtins.h"
#include "src/codegen/source-position.h"
#include "src/deoptimizer/deoptimize-reason.h"
#include "src/deoptimizer/frame-description.h"
#include "src/deoptimizer/translations.h"
#include "src/deoptimizer/translated-state.h"
#include "src/diagnostics/code-tracer.h"
#include "src/objects/js-function.h"
......
This diff is collapsed.
......@@ -8,6 +8,7 @@
#include <stack>
#include <vector>
#include "src/deoptimizer/translation-array.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/heap-object.h"
#include "src/objects/shared-function-info.h"
......@@ -19,7 +20,14 @@ namespace internal {
class RegisterValues;
class TranslatedState;
class TranslationArrayIterator;
// TODO(jgruber): This duplicates decoding logic already present in
// TranslatedState/TranslatedFrame. Deduplicate into one class, e.g. by basing
// printing off TranslatedFrame.
void TranslationArrayPrintSingleFrame(std::ostream& os,
TranslationArray translation_array,
int translation_index,
FixedArray literal_array);
// The Translated{Value,Frame,State} class hierarchy are a set of utility
// functions to work with the combination of translations (built from a
......
......@@ -35,5 +35,235 @@ bool TranslationArrayIterator::HasNext() const {
return index_ < buffer_.length();
}
void TranslationArrayBuilder::Add(int32_t value) {
// This wouldn't handle kMinInt correctly if it ever encountered it.
DCHECK_NE(value, kMinInt);
// Encode the sign bit in the least significant bit.
bool is_negative = (value < 0);
uint32_t bits = (static_cast<uint32_t>(is_negative ? -value : value) << 1) |
static_cast<uint32_t>(is_negative);
// Encode the individual bytes using the least significant bit of
// each byte to indicate whether or not more bytes follow.
do {
uint32_t next = bits >> 7;
contents_.push_back(((bits << 1) & 0xFF) | (next != 0));
bits = next;
} while (bits != 0);
}
Handle<TranslationArray> TranslationArrayBuilder::ToTranslationArray(
Factory* factory) {
Handle<TranslationArray> result =
factory->NewByteArray(Size(), AllocationType::kOld);
contents_.CopyTo(result->GetDataStartAddress());
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);
}
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::BeginArgumentsAdaptorFrame(int literal_id,
unsigned height) {
auto opcode = TranslationOpcode::ARGUMENTS_ADAPTOR_FRAME;
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
......@@ -5,13 +5,19 @@
#ifndef V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_
#define V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_
#include "src/codegen/register-arch.h"
#include "src/deoptimizer/translation-opcode.h"
#include "src/objects/fixed-array.h"
#include "src/wasm/value-type.h"
#include "src/zone/zone-chunk-list.h"
namespace v8 {
namespace internal {
class Factory;
// The TranslationArray is the on-heap representation of translations created
// during code generation in a (zone-allocated) TranslationBuffer. The
// during code generation in a (zone-allocated) TranslationArrayBuilder. The
// translation array specifies how to transform an optimized frame back into
// one or more unoptimized frames.
// TODO(jgruber): Consider a real type instead of this type alias.
......@@ -34,6 +40,73 @@ class TranslationArrayIterator {
int index_;
};
class TranslationArrayBuilder {
public:
explicit TranslationArrayBuilder(Zone* zone) : contents_(zone), zone_(zone) {}
int Size() const { return static_cast<int>(contents_.size()); }
Handle<TranslationArray> ToTranslationArray(Factory* factory);
int BeginTranslation(int frame_count, int jsframe_count,
int update_feedback_count) {
int start_index = Size();
auto opcode = TranslationOpcode::BEGIN;
Add(opcode);
Add(frame_count);
Add(jsframe_count);
Add(update_feedback_count);
DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3);
return start_index;
}
void BeginInterpretedFrame(BytecodeOffset bytecode_offset, int literal_id,
unsigned height, int return_value_offset,
int return_value_count);
void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
void BeginConstructStubFrame(BytecodeOffset bailout_id, int literal_id,
unsigned height);
void BeginBuiltinContinuationFrame(BytecodeOffset bailout_id, int literal_id,
unsigned height);
void BeginJSToWasmBuiltinContinuationFrame(
BytecodeOffset bailout_id, int literal_id, unsigned height,
base::Optional<wasm::ValueType::Kind> return_type);
void BeginJavaScriptBuiltinContinuationFrame(BytecodeOffset bailout_id,
int literal_id, unsigned height);
void BeginJavaScriptBuiltinContinuationWithCatchFrame(
BytecodeOffset bailout_id, int literal_id, unsigned height);
void ArgumentsElements(CreateArgumentsType type);
void ArgumentsLength();
void BeginCapturedObject(int length);
void AddUpdateFeedback(int vector_literal, int slot);
void DuplicateObject(int object_index);
void StoreRegister(Register reg);
void StoreInt32Register(Register reg);
void StoreInt64Register(Register reg);
void StoreUint32Register(Register reg);
void StoreBoolRegister(Register reg);
void StoreFloatRegister(FloatRegister reg);
void StoreDoubleRegister(DoubleRegister reg);
void StoreStackSlot(int index);
void StoreInt32StackSlot(int index);
void StoreInt64StackSlot(int index);
void StoreUint32StackSlot(int index);
void StoreBoolStackSlot(int index);
void StoreFloatStackSlot(int index);
void StoreDoubleStackSlot(int index);
void StoreLiteral(int literal_id);
void StoreJSFrameFunction();
private:
void Add(int32_t value);
void Add(TranslationOpcode opcode) { Add(static_cast<int32_t>(opcode)); }
Zone* zone() const { return zone_; }
ZoneChunkList<uint8_t> contents_;
Zone* const zone_;
};
} // namespace internal
} // namespace v8
......
// 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.
#ifndef V8_DEOPTIMIZER_TRANSLATION_OPCODE_H_
#define V8_DEOPTIMIZER_TRANSLATION_OPCODE_H_
namespace v8 {
namespace internal {
// V(name, operand_count)
#define TRANSLATION_OPCODE_LIST(V) \
V(ARGUMENTS_ADAPTOR_FRAME, 2) \
V(ARGUMENTS_ELEMENTS, 1) \
V(ARGUMENTS_LENGTH, 0) \
V(BEGIN, 3) \
V(BOOL_REGISTER, 1) \
V(BOOL_STACK_SLOT, 1) \
V(BUILTIN_CONTINUATION_FRAME, 3) \
V(CAPTURED_OBJECT, 1) \
V(CONSTRUCT_STUB_FRAME, 3) \
V(DOUBLE_REGISTER, 1) \
V(DOUBLE_STACK_SLOT, 1) \
V(DUPLICATED_OBJECT, 1) \
V(FLOAT_REGISTER, 1) \
V(FLOAT_STACK_SLOT, 1) \
V(INT32_REGISTER, 1) \
V(INT32_STACK_SLOT, 1) \
V(INT64_REGISTER, 1) \
V(INT64_STACK_SLOT, 1) \
V(INTERPRETED_FRAME, 5) \
V(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME, 3) \
V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME, 3) \
V(LITERAL, 1) \
V(REGISTER, 1) \
V(STACK_SLOT, 1) \
V(UINT32_REGISTER, 1) \
V(UINT32_STACK_SLOT, 1) \
V(UPDATE_FEEDBACK, 2)
enum class TranslationOpcode {
#define CASE(name, ...) name,
TRANSLATION_OPCODE_LIST(CASE)
#undef CASE
};
constexpr TranslationOpcode TranslationOpcodeFromInt(int i) {
return static_cast<TranslationOpcode>(i);
}
inline int TranslationOpcodeOperandCount(TranslationOpcode o) {
#define CASE(name, operand_count) operand_count,
static const int counts[] = {TRANSLATION_OPCODE_LIST(CASE)};
#undef CASE
return counts[static_cast<int>(o)];
}
inline const char* TranslationOpcodeToString(TranslationOpcode o) {
#define CASE(name, ...) #name,
static const char* const names[] = {TRANSLATION_OPCODE_LIST(CASE)};
#undef CASE
return names[static_cast<int>(o)];
}
#undef TRANSLATION_OPCODE_LIST
} // namespace internal
} // namespace v8
#endif // V8_DEOPTIMIZER_TRANSLATION_OPCODE_H_
// 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/translations.h"
#include "src/execution/frames.h"
#include "src/execution/isolate.h"
#include "src/heap/factory.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/oddball.h"
namespace v8 {
namespace internal {
void TranslationBuffer::Add(int32_t value) {
// This wouldn't handle kMinInt correctly if it ever encountered it.
DCHECK_NE(value, kMinInt);
// Encode the sign bit in the least significant bit.
bool is_negative = (value < 0);
uint32_t bits = (static_cast<uint32_t>(is_negative ? -value : value) << 1) |
static_cast<uint32_t>(is_negative);
// Encode the individual bytes using the least significant bit of
// each byte to indicate whether or not more bytes follow.
do {
uint32_t next = bits >> 7;
contents_.push_back(((bits << 1) & 0xFF) | (next != 0));
bits = next;
} while (bits != 0);
}
Handle<ByteArray> TranslationBuffer::CreateByteArray(Factory* factory) {
Handle<ByteArray> result =
factory->NewByteArray(CurrentIndex(), AllocationType::kOld);
contents_.CopyTo(result->GetDataStartAddress());
return result;
}
void Translation::BeginBuiltinContinuationFrame(BytecodeOffset bytecode_offset,
int literal_id,
unsigned height) {
buffer_->Add(BUILTIN_CONTINUATION_FRAME);
buffer_->Add(bytecode_offset.ToInt());
buffer_->Add(literal_id);
buffer_->Add(height);
}
void Translation::BeginJavaScriptBuiltinContinuationFrame(
BytecodeOffset bytecode_offset, int literal_id, unsigned height) {
buffer_->Add(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME);
buffer_->Add(bytecode_offset.ToInt());
buffer_->Add(literal_id);
buffer_->Add(height);
}
void Translation::BeginJavaScriptBuiltinContinuationWithCatchFrame(
BytecodeOffset bytecode_offset, int literal_id, unsigned height) {
buffer_->Add(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME);
buffer_->Add(bytecode_offset.ToInt());
buffer_->Add(literal_id);
buffer_->Add(height);
}
void Translation::BeginConstructStubFrame(BytecodeOffset bytecode_offset,
int literal_id, unsigned height) {
buffer_->Add(CONSTRUCT_STUB_FRAME);
buffer_->Add(bytecode_offset.ToInt());
buffer_->Add(literal_id);
buffer_->Add(height);
}
void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
buffer_->Add(ARGUMENTS_ADAPTOR_FRAME);
buffer_->Add(literal_id);
buffer_->Add(height);
}
void Translation::BeginInterpretedFrame(BytecodeOffset bytecode_offset,
int literal_id, unsigned height,
int return_value_offset,
int return_value_count) {
buffer_->Add(INTERPRETED_FRAME);
buffer_->Add(bytecode_offset.ToInt());
buffer_->Add(literal_id);
buffer_->Add(height);
buffer_->Add(return_value_offset);
buffer_->Add(return_value_count);
}
void Translation::ArgumentsElements(CreateArgumentsType type) {
buffer_->Add(ARGUMENTS_ELEMENTS);
buffer_->Add(static_cast<uint8_t>(type));
}
void Translation::ArgumentsLength() { buffer_->Add(ARGUMENTS_LENGTH); }
void Translation::BeginCapturedObject(int length) {
buffer_->Add(CAPTURED_OBJECT);
buffer_->Add(length);
}
void Translation::DuplicateObject(int object_index) {
buffer_->Add(DUPLICATED_OBJECT);
buffer_->Add(object_index);
}
void Translation::StoreRegister(Register reg) {
buffer_->Add(REGISTER);
buffer_->Add(reg.code());
}
void Translation::StoreInt32Register(Register reg) {
buffer_->Add(INT32_REGISTER);
buffer_->Add(reg.code());
}
void Translation::StoreInt64Register(Register reg) {
buffer_->Add(INT64_REGISTER);
buffer_->Add(reg.code());
}
void Translation::StoreUint32Register(Register reg) {
buffer_->Add(UINT32_REGISTER);
buffer_->Add(reg.code());
}
void Translation::StoreBoolRegister(Register reg) {
buffer_->Add(BOOL_REGISTER);
buffer_->Add(reg.code());
}
void Translation::StoreFloatRegister(FloatRegister reg) {
buffer_->Add(FLOAT_REGISTER);
buffer_->Add(reg.code());
}
void Translation::StoreDoubleRegister(DoubleRegister reg) {
buffer_->Add(DOUBLE_REGISTER);
buffer_->Add(reg.code());
}
void Translation::StoreStackSlot(int index) {
buffer_->Add(STACK_SLOT);
buffer_->Add(index);
}
void Translation::StoreInt32StackSlot(int index) {
buffer_->Add(INT32_STACK_SLOT);
buffer_->Add(index);
}
void Translation::StoreInt64StackSlot(int index) {
buffer_->Add(INT64_STACK_SLOT);
buffer_->Add(index);
}
void Translation::StoreUint32StackSlot(int index) {
buffer_->Add(UINT32_STACK_SLOT);
buffer_->Add(index);
}
void Translation::StoreBoolStackSlot(int index) {
buffer_->Add(BOOL_STACK_SLOT);
buffer_->Add(index);
}
void Translation::StoreFloatStackSlot(int index) {
buffer_->Add(FLOAT_STACK_SLOT);
buffer_->Add(index);
}
void Translation::StoreDoubleStackSlot(int index) {
buffer_->Add(DOUBLE_STACK_SLOT);
buffer_->Add(index);
}
void Translation::StoreLiteral(int literal_id) {
buffer_->Add(LITERAL);
buffer_->Add(literal_id);
}
void Translation::AddUpdateFeedback(int vector_literal, int slot) {
buffer_->Add(UPDATE_FEEDBACK);
buffer_->Add(vector_literal);
buffer_->Add(slot);
}
void Translation::StoreJSFrameFunction() {
StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
StandardFrameConstants::kFunctionOffset) /
kSystemPointerSize);
}
int Translation::NumberOfOperandsFor(Opcode opcode) {
switch (opcode) {
case ARGUMENTS_LENGTH:
return 0;
case DUPLICATED_OBJECT:
case ARGUMENTS_ELEMENTS:
case CAPTURED_OBJECT:
case REGISTER:
case INT32_REGISTER:
case INT64_REGISTER:
case UINT32_REGISTER:
case BOOL_REGISTER:
case FLOAT_REGISTER:
case DOUBLE_REGISTER:
case STACK_SLOT:
case INT32_STACK_SLOT:
case INT64_STACK_SLOT:
case UINT32_STACK_SLOT:
case BOOL_STACK_SLOT:
case FLOAT_STACK_SLOT:
case DOUBLE_STACK_SLOT:
case LITERAL:
return 1;
case ARGUMENTS_ADAPTOR_FRAME:
case UPDATE_FEEDBACK:
return 2;
case BEGIN:
case CONSTRUCT_STUB_FRAME:
case BUILTIN_CONTINUATION_FRAME:
case JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME:
return 3;
case INTERPRETED_FRAME:
return 5;
}
FATAL("Unexpected translation type");
return -1;
}
#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
const char* Translation::StringFor(Opcode opcode) {
#define TRANSLATION_OPCODE_CASE(item) \
case item: \
return #item;
switch (opcode) { TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE) }
#undef TRANSLATION_OPCODE_CASE
UNREACHABLE();
}
#endif
} // namespace internal
} // namespace v8
// 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.
#ifndef V8_DEOPTIMIZER_TRANSLATIONS_H_
#define V8_DEOPTIMIZER_TRANSLATIONS_H_
#include <stack>
#include <vector>
#include "src/builtins/builtins.h"
#include "src/codegen/register-arch.h"
#include "src/deoptimizer/translated-state.h"
#include "src/objects/fixed-array.h"
#include "src/wasm/value-type.h"
#include "src/zone/zone-chunk-list.h"
namespace v8 {
namespace internal {
class Factory;
class TranslationBuffer {
public:
explicit TranslationBuffer(Zone* zone) : contents_(zone) {}
int CurrentIndex() const { return static_cast<int>(contents_.size()); }
void Add(int32_t value);
Handle<ByteArray> CreateByteArray(Factory* factory);
private:
ZoneChunkList<uint8_t> contents_;
};
#define TRANSLATION_OPCODE_LIST(V) \
V(BEGIN) \
V(INTERPRETED_FRAME) \
V(BUILTIN_CONTINUATION_FRAME) \
V(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME) \
V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) \
V(CONSTRUCT_STUB_FRAME) \
V(ARGUMENTS_ADAPTOR_FRAME) \
V(DUPLICATED_OBJECT) \
V(ARGUMENTS_ELEMENTS) \
V(ARGUMENTS_LENGTH) \
V(CAPTURED_OBJECT) \
V(REGISTER) \
V(INT32_REGISTER) \
V(INT64_REGISTER) \
V(UINT32_REGISTER) \
V(BOOL_REGISTER) \
V(FLOAT_REGISTER) \
V(DOUBLE_REGISTER) \
V(STACK_SLOT) \
V(INT32_STACK_SLOT) \
V(INT64_STACK_SLOT) \
V(UINT32_STACK_SLOT) \
V(BOOL_STACK_SLOT) \
V(FLOAT_STACK_SLOT) \
V(DOUBLE_STACK_SLOT) \
V(LITERAL) \
V(UPDATE_FEEDBACK)
class Translation {
public:
#define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
enum Opcode {
TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM) LAST = LITERAL
};
#undef DECLARE_TRANSLATION_OPCODE_ENUM
Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
int update_feedback_count, Zone* zone)
: buffer_(buffer), index_(buffer->CurrentIndex()), zone_(zone) {
buffer_->Add(BEGIN);
buffer_->Add(frame_count);
buffer_->Add(jsframe_count);
buffer_->Add(update_feedback_count);
}
int index() const { return index_; }
// Commands.
void BeginInterpretedFrame(BytecodeOffset bytecode_offset, int literal_id,
unsigned height, int return_value_offset,
int return_value_count);
void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
void BeginConstructStubFrame(BytecodeOffset bailout_id, int literal_id,
unsigned height);
void BeginBuiltinContinuationFrame(BytecodeOffset bailout_id, int literal_id,
unsigned height);
void BeginJavaScriptBuiltinContinuationFrame(BytecodeOffset bailout_id,
int literal_id, unsigned height);
void BeginJavaScriptBuiltinContinuationWithCatchFrame(
BytecodeOffset bailout_id, int literal_id, unsigned height);
void ArgumentsElements(CreateArgumentsType type);
void ArgumentsLength();
void BeginCapturedObject(int length);
void AddUpdateFeedback(int vector_literal, int slot);
void DuplicateObject(int object_index);
void StoreRegister(Register reg);
void StoreInt32Register(Register reg);
void StoreInt64Register(Register reg);
void StoreUint32Register(Register reg);
void StoreBoolRegister(Register reg);
void StoreFloatRegister(FloatRegister reg);
void StoreDoubleRegister(DoubleRegister reg);
void StoreStackSlot(int index);
void StoreInt32StackSlot(int index);
void StoreInt64StackSlot(int index);
void StoreUint32StackSlot(int index);
void StoreBoolStackSlot(int index);
void StoreFloatStackSlot(int index);
void StoreDoubleStackSlot(int index);
void StoreLiteral(int literal_id);
void StoreJSFrameFunction();
Zone* zone() const { return zone_; }
static int NumberOfOperandsFor(Opcode opcode);
#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
static const char* StringFor(Opcode opcode);
#endif
private:
TranslationBuffer* buffer_;
int index_;
Zone* zone_;
};
} // namespace internal
} // namespace v8
#endif // V8_DEOPTIMIZER_TRANSLATIONS_H_
......@@ -1644,8 +1644,8 @@ void OptimizedFrame::GetFunctions(
TranslationArrayIterator it(data.TranslationByteArray(),
data.TranslationIndex(deopt_index).value());
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
DCHECK_EQ(Translation::BEGIN, opcode);
TranslationOpcode opcode = TranslationOpcodeFromInt(it.Next());
DCHECK_EQ(TranslationOpcode::BEGIN, opcode);
it.Next(); // Skip frame count.
int jsframe_count = it.Next();
it.Next(); // Skip update feedback count.
......@@ -1653,11 +1653,11 @@ void OptimizedFrame::GetFunctions(
// We insert the frames in reverse order because the frames
// in the deoptimization translation are ordered bottom-to-top.
while (jsframe_count != 0) {
opcode = static_cast<Translation::Opcode>(it.Next());
if (opcode == Translation::INTERPRETED_FRAME ||
opcode == Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME ||
opcode ==
Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) {
opcode = TranslationOpcodeFromInt(it.Next());
if (opcode == TranslationOpcode::INTERPRETED_FRAME ||
opcode == TranslationOpcode::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME ||
opcode == TranslationOpcode::
JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) {
it.Next(); // Skip bailout id.
jsframe_count--;
......@@ -1666,10 +1666,10 @@ void OptimizedFrame::GetFunctions(
functions->push_back(SharedFunctionInfo::cast(shared));
// Skip over remaining operands to advance to the next opcode.
it.Skip(Translation::NumberOfOperandsFor(opcode) - 2);
it.Skip(TranslationOpcodeOperandCount(opcode) - 2);
} else {
// Skip over operands to advance to the next opcode.
it.Skip(Translation::NumberOfOperandsFor(opcode));
it.Skip(TranslationOpcodeOperandCount(opcode));
}
}
}
......
......@@ -441,7 +441,6 @@ void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) { // NOLINT
return;
}
disasm::NameConverter converter;
int const inlined_function_count = InlinedFunctionCount().value();
os << "Inlined functions (count = " << inlined_function_count << ")\n";
for (int id = 0; id < inlined_function_count; ++id) {
......@@ -467,203 +466,9 @@ void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) { // NOLINT
continue;
}
// Print details of the frame translation.
int translation_index = TranslationIndex(i).value();
TranslationArrayIterator iterator(TranslationByteArray(),
translation_index);
Translation::Opcode opcode =
static_cast<Translation::Opcode>(iterator.Next());
DCHECK(Translation::BEGIN == opcode);
int frame_count = iterator.Next();
int jsframe_count = iterator.Next();
int update_feedback_count = iterator.Next();
os << " " << Translation::StringFor(opcode)
<< " {frame count=" << frame_count
<< ", js frame count=" << jsframe_count
<< ", update_feedback_count=" << update_feedback_count << "}\n";
while (iterator.HasNext() &&
Translation::BEGIN !=
(opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
os << std::setw(31) << " " << Translation::StringFor(opcode) << " ";
switch (opcode) {
case Translation::BEGIN:
UNREACHABLE();
break;
case Translation::INTERPRETED_FRAME: {
int bytecode_offset = iterator.Next();
int shared_info_id = iterator.Next();
unsigned height = iterator.Next();
int return_value_offset = iterator.Next();
int return_value_count = iterator.Next();
Object shared_info = LiteralArray().get(shared_info_id);
os << "{bytecode_offset=" << bytecode_offset << ", function="
<< SharedFunctionInfo::cast(shared_info).DebugNameCStr().get()
<< ", height=" << height << ", retval=@" << return_value_offset
<< "(#" << return_value_count << ")}";
break;
}
case Translation::CONSTRUCT_STUB_FRAME: {
int bailout_id = iterator.Next();
int shared_info_id = iterator.Next();
Object shared_info = LiteralArray().get(shared_info_id);
unsigned height = iterator.Next();
os << "{bailout_id=" << bailout_id << ", function="
<< SharedFunctionInfo::cast(shared_info).DebugNameCStr().get()
<< ", height=" << height << "}";
break;
}
case Translation::BUILTIN_CONTINUATION_FRAME:
case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME: {
int bailout_id = iterator.Next();
int shared_info_id = iterator.Next();
Object shared_info = LiteralArray().get(shared_info_id);
unsigned height = iterator.Next();
os << "{bailout_id=" << bailout_id << ", function="
<< SharedFunctionInfo::cast(shared_info).DebugNameCStr().get()
<< ", height=" << height << "}";
break;
}
case Translation::ARGUMENTS_ADAPTOR_FRAME: {
int shared_info_id = iterator.Next();
Object shared_info = LiteralArray().get(shared_info_id);
unsigned height = iterator.Next();
os << "{function="
<< SharedFunctionInfo::cast(shared_info).DebugNameCStr().get()
<< ", height=" << height << "}";
break;
}
case Translation::REGISTER: {
int reg_code = iterator.Next();
os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
break;
}
case Translation::INT32_REGISTER: {
int reg_code = iterator.Next();
os << "{input=" << converter.NameOfCPURegister(reg_code)
<< " (int32)}";
break;
}
case Translation::INT64_REGISTER: {
int reg_code = iterator.Next();
os << "{input=" << converter.NameOfCPURegister(reg_code)
<< " (int64)}";
break;
}
case Translation::UINT32_REGISTER: {
int reg_code = iterator.Next();
os << "{input=" << converter.NameOfCPURegister(reg_code)
<< " (uint32)}";
break;
}
case Translation::BOOL_REGISTER: {
int reg_code = iterator.Next();
os << "{input=" << converter.NameOfCPURegister(reg_code)
<< " (bool)}";
break;
}
case Translation::FLOAT_REGISTER: {
int reg_code = iterator.Next();
os << "{input=" << FloatRegister::from_code(reg_code) << "}";
break;
}
case Translation::DOUBLE_REGISTER: {
int reg_code = iterator.Next();
os << "{input=" << DoubleRegister::from_code(reg_code) << "}";
break;
}
case Translation::STACK_SLOT: {
int input_slot_index = iterator.Next();
os << "{input=" << input_slot_index << "}";
break;
}
case Translation::INT32_STACK_SLOT: {
int input_slot_index = iterator.Next();
os << "{input=" << input_slot_index << " (int32)}";
break;
}
case Translation::INT64_STACK_SLOT: {
int input_slot_index = iterator.Next();
os << "{input=" << input_slot_index << " (int64)}";
break;
}
case Translation::UINT32_STACK_SLOT: {
int input_slot_index = iterator.Next();
os << "{input=" << input_slot_index << " (uint32)}";
break;
}
case Translation::BOOL_STACK_SLOT: {
int input_slot_index = iterator.Next();
os << "{input=" << input_slot_index << " (bool)}";
break;
}
case Translation::FLOAT_STACK_SLOT:
case Translation::DOUBLE_STACK_SLOT: {
int input_slot_index = iterator.Next();
os << "{input=" << input_slot_index << "}";
break;
}
case Translation::LITERAL: {
int literal_index = iterator.Next();
Object literal_value = LiteralArray().get(literal_index);
os << "{literal_id=" << literal_index << " (" << Brief(literal_value)
<< ")}";
break;
}
case Translation::DUPLICATED_OBJECT: {
int object_index = iterator.Next();
os << "{object_index=" << object_index << "}";
break;
}
case Translation::ARGUMENTS_ELEMENTS: {
CreateArgumentsType arguments_type =
static_cast<CreateArgumentsType>(iterator.Next());
os << "{arguments_type=" << arguments_type << "}";
break;
}
case Translation::ARGUMENTS_LENGTH: {
os << "{arguments_length}";
break;
}
case Translation::CAPTURED_OBJECT: {
int args_length = iterator.Next();
os << "{length=" << args_length << "}";
break;
}
case Translation::UPDATE_FEEDBACK: {
int literal_index = iterator.Next();
FeedbackSlot slot(iterator.Next());
os << "{feedback={vector_index=" << literal_index << ", slot=" << slot
<< "}}";
break;
}
}
os << "\n";
}
TranslationArrayPrintSingleFrame(os, TranslationByteArray(),
TranslationIndex(i).value(),
LiteralArray());
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment