Commit 5d287754 authored by Nico Hartmann's avatar Nico Hartmann Committed by V8 LUCI CQ

[deoptimizer][turbofan] Provide id of deoptimizing node in trace

When running d8 with --trace-deopt, any deopt will contain the id of
the node that caused this deopt. These ids also show up in the
deoptimization data table of when using --print-opt-code.

Change-Id: I412ca7a4ff20427100fa63101d78ee3846569a8e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3024144Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76220}
parent c88de19f
......@@ -1077,8 +1077,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
// Record the emission of a constant pool.
//
......
......@@ -4373,9 +4373,11 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data,
(rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) ||
(rmode == RelocInfo::DEOPT_INLINING_ID) ||
(rmode == RelocInfo::DEOPT_REASON) || (rmode == RelocInfo::DEOPT_ID) ||
(rmode == RelocInfo::LITERAL_CONSTANT)) {
(rmode == RelocInfo::LITERAL_CONSTANT) ||
(rmode == RelocInfo::DEOPT_NODE_ID)) {
// Adjust code for new modes.
DCHECK(RelocInfo::IsDeoptReason(rmode) || RelocInfo::IsDeoptId(rmode) ||
RelocInfo::IsDeoptNodeId(rmode) ||
RelocInfo::IsDeoptPosition(rmode) ||
RelocInfo::IsInternalReference(rmode) ||
RelocInfo::IsDataEmbeddedObject(rmode) ||
......
......@@ -349,8 +349,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
int buffer_space() const;
......
......@@ -295,13 +295,16 @@ HeapObjectRequest::HeapObjectRequest(const StringConstantBase* string,
// Platform specific but identical code for all the platforms.
void Assembler::RecordDeoptReason(DeoptimizeReason reason,
void Assembler::RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::DEOPT_SCRIPT_OFFSET, position.ScriptOffset());
RecordRelocInfo(RelocInfo::DEOPT_INLINING_ID, position.InliningId());
RecordRelocInfo(RelocInfo::DEOPT_REASON, static_cast<int>(reason));
RecordRelocInfo(RelocInfo::DEOPT_ID, id);
#ifdef DEBUG
RecordRelocInfo(RelocInfo::DEOPT_NODE_ID, node_id);
#endif // DEBUG
}
void Assembler::DataAlign(int m) {
......
......@@ -192,7 +192,8 @@ class ConstantPoolKey {
rmode_ != RelocInfo::VENEER_POOL &&
rmode_ != RelocInfo::DEOPT_SCRIPT_OFFSET &&
rmode_ != RelocInfo::DEOPT_INLINING_ID &&
rmode_ != RelocInfo::DEOPT_REASON && rmode_ != RelocInfo::DEOPT_ID);
rmode_ != RelocInfo::DEOPT_REASON && rmode_ != RelocInfo::DEOPT_ID &&
rmode_ != RelocInfo::DEOPT_NODE_ID);
// CODE_TARGETs can be shared because they aren't patched anymore,
// and we make sure we emit only one reloc info for them (thus delta
// patching) will apply the delta only once. At the moment, we do not dedup
......
......@@ -1803,8 +1803,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
// Writes a single byte or word of data in the code stream. Used for
// inline tables, e.g., jump-tables.
......
......@@ -1414,8 +1414,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
static int RelocateInternalReference(RelocInfo::Mode rmode, Address pc,
intptr_t pc_delta);
......
......@@ -1477,8 +1477,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
static int RelocateInternalReference(RelocInfo::Mode rmode, Address pc,
intptr_t pc_delta);
......
......@@ -1189,8 +1189,8 @@ class Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
// Writes a single byte or word of data in the code stream. Used
// for inline tables, e.g., jump-tables.
......
......@@ -157,7 +157,8 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) {
WriteShortData(rinfo->data());
} else if (RelocInfo::IsConstPool(rmode) ||
RelocInfo::IsVeneerPool(rmode) || RelocInfo::IsDeoptId(rmode) ||
RelocInfo::IsDeoptPosition(rmode)) {
RelocInfo::IsDeoptPosition(rmode) ||
RelocInfo::IsDeoptNodeId(rmode)) {
WriteIntData(static_cast<int>(rinfo->data()));
}
}
......@@ -244,7 +245,8 @@ void RelocIterator::next() {
} else if (RelocInfo::IsConstPool(rmode) ||
RelocInfo::IsVeneerPool(rmode) ||
RelocInfo::IsDeoptId(rmode) ||
RelocInfo::IsDeoptPosition(rmode)) {
RelocInfo::IsDeoptPosition(rmode) ||
RelocInfo::IsDeoptNodeId(rmode)) {
if (SetMode(rmode)) {
AdvanceReadInt();
return;
......@@ -424,6 +426,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
return "deopt index";
case LITERAL_CONSTANT:
return "literal constant";
case DEOPT_NODE_ID:
return "deopt node id";
case CONST_POOL:
return "constant pool";
case VENEER_POOL:
......@@ -528,6 +532,7 @@ void RelocInfo::Verify(Isolate* isolate) {
case DEOPT_REASON:
case DEOPT_ID:
case LITERAL_CONSTANT:
case DEOPT_NODE_ID:
case CONST_POOL:
case VENEER_POOL:
case WASM_CALL:
......
......@@ -88,6 +88,8 @@ class RelocInfo {
DEOPT_INLINING_ID, // Deoptimization source position.
DEOPT_REASON, // Deoptimization reason index.
DEOPT_ID, // Deoptimization inlining id.
DEOPT_NODE_ID, // Id of the node that caused deoptimization. This
// information is only recorded in debug builds.
LITERAL_CONSTANT, // An constant embedded in the instruction stream.
......@@ -174,6 +176,9 @@ class RelocInfo {
static constexpr bool IsLiteralConstant(Mode mode) {
return mode == LITERAL_CONSTANT;
}
static constexpr bool IsDeoptNodeId(Mode mode) {
return mode == DEOPT_NODE_ID;
}
static constexpr bool IsExternalReference(Mode mode) {
return mode == EXTERNAL_REFERENCE;
}
......
......@@ -837,8 +837,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
static int RelocateInternalReference(RelocInfo::Mode rmode, Address pc,
intptr_t pc_delta);
......
......@@ -1314,8 +1314,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
// Writes a single byte or word of data in the code stream. Used
// for inline tables, e.g., jump-tables.
......
......@@ -1864,8 +1864,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
// Record a deoptimization reason that can be used by a log or cpu profiler.
// Use --trace-deopt to enable.
void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
int id);
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
SourcePosition position, int id);
// Writes a single word of data in the code stream.
// Used for inline tables, e.g., jump-tables.
......
......@@ -189,7 +189,8 @@ class DeoptimizationExit : public ZoneObject {
public:
explicit DeoptimizationExit(SourcePosition pos, BytecodeOffset bailout_id,
int translation_id, int pc_offset,
DeoptimizeKind kind, DeoptimizeReason reason)
DeoptimizeKind kind, DeoptimizeReason reason,
NodeId node_id)
: deoptimization_id_(kNoDeoptIndex),
pos_(pos),
bailout_id_(bailout_id),
......@@ -197,6 +198,7 @@ class DeoptimizationExit : public ZoneObject {
pc_offset_(pc_offset),
kind_(kind),
reason_(reason),
node_id_(node_id),
immediate_args_(nullptr),
emitted_(false) {}
......@@ -220,6 +222,7 @@ class DeoptimizationExit : public ZoneObject {
int pc_offset() const { return pc_offset_; }
DeoptimizeKind kind() const { return kind_; }
DeoptimizeReason reason() const { return reason_; }
NodeId node_id() const { return node_id_; }
const ZoneVector<ImmediateOperand*>* immediate_args() const {
return immediate_args_;
}
......@@ -243,6 +246,7 @@ class DeoptimizationExit : public ZoneObject {
const int pc_offset_;
const DeoptimizeKind kind_;
const DeoptimizeReason reason_;
const NodeId node_id_;
ZoneVector<ImmediateOperand*>* immediate_args_;
bool emitted_;
};
......
......@@ -221,8 +221,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
&jump_deoptimization_entry_labels_[static_cast<int>(deopt_kind)];
}
if (info()->source_positions()) {
tasm()->RecordDeoptReason(deoptimization_reason, exit->pos(),
deoptimization_id);
tasm()->RecordDeoptReason(deoptimization_reason, exit->node_id(),
exit->pos(), deoptimization_id);
}
if (deopt_kind == DeoptimizeKind::kLazy) {
......@@ -1059,6 +1059,9 @@ Handle<DeoptimizationData> CodeGenerator::GenerateDeoptimizationData() {
data->SetTranslationIndex(
i, Smi::FromInt(deoptimization_exit->translation_id()));
data->SetPc(i, Smi::FromInt(deoptimization_exit->pc_offset()));
#ifdef DEBUG
data->SetNodeId(i, Smi::FromInt(deoptimization_exit->node_id()));
#endif // DEBUG
}
return data;
......@@ -1246,8 +1249,12 @@ DeoptimizationExit* CodeGenerator::BuildTranslation(
DeoptimizationExit* const exit = zone()->New<DeoptimizationExit>(
current_source_position_, descriptor->bailout_id(), translation_index,
pc_offset, entry.kind(), entry.reason());
pc_offset, entry.kind(), entry.reason(),
#ifdef DEBUG
entry.node_id());
#else // DEBUG
0);
#endif // DEBUG
if (!Deoptimizer::kSupportsFixedDeoptExitSizes) {
exit->set_deoptimization_id(next_deoptimization_id_++);
}
......
......@@ -873,7 +873,7 @@ Instruction* InstructionSelector::EmitWithContinuation(
opcode |= DeoptImmedArgsCountField::encode(immediate_args_count) |
DeoptFrameStateOffsetField::encode(static_cast<int>(input_count));
AppendDeoptimizeArguments(&continuation_inputs_, cont->kind(),
cont->reason(), cont->feedback(),
cont->reason(), cont->node_id(), cont->feedback(),
FrameState{cont->frame_state()});
} else if (cont->IsSet()) {
continuation_outputs_.push_back(g.DefineAsRegister(cont->result()));
......@@ -906,13 +906,13 @@ Instruction* InstructionSelector::EmitWithContinuation(
void InstructionSelector::AppendDeoptimizeArguments(
InstructionOperandVector* args, DeoptimizeKind kind,
DeoptimizeReason reason, FeedbackSource const& feedback,
DeoptimizeReason reason, NodeId node_id, FeedbackSource const& feedback,
FrameState frame_state) {
OperandGenerator g(this);
FrameStateDescriptor* const descriptor = GetFrameStateDescriptor(frame_state);
DCHECK_NE(DeoptimizeKind::kLazy, kind);
int const state_id =
sequence()->AddDeoptimizationEntry(descriptor, kind, reason, feedback);
int const state_id = sequence()->AddDeoptimizationEntry(
descriptor, kind, reason, node_id, feedback);
args->push_back(g.TempImmediate(state_id));
StateObjectDeduplicator deduplicator(instruction_zone());
AddInputsToFrameStateDescriptor(descriptor, frame_state, &g, &deduplicator,
......@@ -1112,7 +1112,7 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
int const state_id = sequence()->AddDeoptimizationEntry(
buffer->frame_state_descriptor, DeoptimizeKind::kLazy,
DeoptimizeReason::kUnknown, FeedbackSource());
DeoptimizeReason::kUnknown, call->id(), FeedbackSource());
buffer->instruction_args.push_back(g.TempImmediate(state_id));
StateObjectDeduplicator deduplicator(instruction_zone());
......@@ -1362,7 +1362,7 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
case BasicBlock::kDeoptimize: {
DeoptimizeParameters p = DeoptimizeParametersOf(input->op());
FrameState value{input->InputAt(0)};
VisitDeoptimize(p.kind(), p.reason(), p.feedback(), value);
VisitDeoptimize(p.kind(), p.reason(), input->id(), p.feedback(), value);
break;
}
case BasicBlock::kThrow:
......@@ -3119,11 +3119,13 @@ void InstructionSelector::VisitDeoptimizeIf(Node* node) {
DeoptimizeParameters p = DeoptimizeParametersOf(node->op());
if (NeedsPoisoning(p.is_safety_check())) {
FlagsContinuation cont = FlagsContinuation::ForDeoptimizeAndPoison(
kNotEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1));
kNotEqual, p.kind(), p.reason(), node->id(), p.feedback(),
node->InputAt(1));
VisitWordCompareZero(node, node->InputAt(0), &cont);
} else {
FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
kNotEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1));
kNotEqual, p.kind(), p.reason(), node->id(), p.feedback(),
node->InputAt(1));
VisitWordCompareZero(node, node->InputAt(0), &cont);
}
}
......@@ -3132,11 +3134,13 @@ void InstructionSelector::VisitDeoptimizeUnless(Node* node) {
DeoptimizeParameters p = DeoptimizeParametersOf(node->op());
if (NeedsPoisoning(p.is_safety_check())) {
FlagsContinuation cont = FlagsContinuation::ForDeoptimizeAndPoison(
kEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1));
kEqual, p.kind(), p.reason(), node->id(), p.feedback(),
node->InputAt(1));
VisitWordCompareZero(node, node->InputAt(0), &cont);
} else {
FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
kEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1));
kEqual, p.kind(), p.reason(), node->id(), p.feedback(),
node->InputAt(1));
VisitWordCompareZero(node, node->InputAt(0), &cont);
}
}
......@@ -3184,12 +3188,12 @@ void InstructionSelector::VisitDynamicCheckMapsWithDeoptUnless(Node* node) {
if (NeedsPoisoning(IsSafetyCheck::kCriticalSafetyCheck)) {
FlagsContinuation cont = FlagsContinuation::ForDeoptimizeAndPoison(
kEqual, p.kind(), p.reason(), p.feedback(), n.frame_state(),
kEqual, p.kind(), p.reason(), node->id(), p.feedback(), n.frame_state(),
dynamic_check_args.data(), static_cast<int>(dynamic_check_args.size()));
VisitWordCompareZero(node, n.condition(), &cont);
} else {
FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
kEqual, p.kind(), p.reason(), p.feedback(), n.frame_state(),
kEqual, p.kind(), p.reason(), node->id(), p.feedback(), n.frame_state(),
dynamic_check_args.data(), static_cast<int>(dynamic_check_args.size()));
VisitWordCompareZero(node, n.condition(), &cont);
}
......@@ -3214,10 +3218,12 @@ void InstructionSelector::EmitIdentity(Node* node) {
void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind,
DeoptimizeReason reason,
NodeId node_id,
FeedbackSource const& feedback,
FrameState frame_state) {
InstructionOperandVector args(instruction_zone());
AppendDeoptimizeArguments(&args, kind, reason, feedback, frame_state);
AppendDeoptimizeArguments(&args, kind, reason, node_id, feedback,
frame_state);
Emit(kArchDeoptimize, 0, nullptr, args.size(), &args.front(), 0, nullptr);
}
......
......@@ -64,20 +64,20 @@ class FlagsContinuation final {
// Creates a new flags continuation for an eager deoptimization exit.
static FlagsContinuation ForDeoptimize(
FlagsCondition condition, DeoptimizeKind kind, DeoptimizeReason reason,
FeedbackSource const& feedback, Node* frame_state,
NodeId node_id, FeedbackSource const& feedback, Node* frame_state,
InstructionOperand* extra_args = nullptr, int extra_args_count = 0) {
return FlagsContinuation(kFlags_deoptimize, condition, kind, reason,
feedback, frame_state, extra_args,
node_id, feedback, frame_state, extra_args,
extra_args_count);
}
// Creates a new flags continuation for an eager deoptimization exit.
static FlagsContinuation ForDeoptimizeAndPoison(
FlagsCondition condition, DeoptimizeKind kind, DeoptimizeReason reason,
FeedbackSource const& feedback, Node* frame_state,
NodeId node_id, FeedbackSource const& feedback, Node* frame_state,
InstructionOperand* extra_args = nullptr, int extra_args_count = 0) {
return FlagsContinuation(kFlags_deoptimize_and_poison, condition, kind,
reason, feedback, frame_state, extra_args,
reason, node_id, feedback, frame_state, extra_args,
extra_args_count);
}
......@@ -123,6 +123,10 @@ class FlagsContinuation final {
DCHECK(IsDeoptimize());
return reason_;
}
NodeId node_id() const {
DCHECK(IsDeoptimize());
return node_id_;
}
FeedbackSource const& feedback() const {
DCHECK(IsDeoptimize());
return feedback_;
......@@ -229,12 +233,14 @@ class FlagsContinuation final {
FlagsContinuation(FlagsMode mode, FlagsCondition condition,
DeoptimizeKind kind, DeoptimizeReason reason,
FeedbackSource const& feedback, Node* frame_state,
InstructionOperand* extra_args, int extra_args_count)
NodeId node_id, FeedbackSource const& feedback,
Node* frame_state, InstructionOperand* extra_args,
int extra_args_count)
: mode_(mode),
condition_(condition),
kind_(kind),
reason_(reason),
node_id_(node_id),
feedback_(feedback),
frame_state_or_result_(frame_state),
extra_args_(extra_args),
......@@ -274,6 +280,7 @@ class FlagsContinuation final {
FlagsCondition condition_;
DeoptimizeKind kind_; // Only valid if mode_ == kFlags_deoptimize*
DeoptimizeReason reason_; // Only valid if mode_ == kFlags_deoptimize*
NodeId node_id_; // Only valid if mode_ == kFlags_deoptimize*
FeedbackSource feedback_; // Only valid if mode_ == kFlags_deoptimize*
Node* frame_state_or_result_; // Only valid if mode_ == kFlags_deoptimize*
// or mode_ == kFlags_set.
......@@ -524,7 +531,7 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
void AppendDeoptimizeArguments(InstructionOperandVector* args,
DeoptimizeKind kind, DeoptimizeReason reason,
FeedbackSource const& feedback,
NodeId node_id, FeedbackSource const& feedback,
FrameState frame_state);
void EmitTableSwitch(const SwitchInfo& sw,
......@@ -660,7 +667,8 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch);
void VisitSwitch(Node* node, const SwitchInfo& sw);
void VisitDeoptimize(DeoptimizeKind kind, DeoptimizeReason reason,
FeedbackSource const& feedback, FrameState frame_state);
NodeId node_id, FeedbackSource const& feedback,
FrameState frame_state);
void VisitSelect(Node* node);
void VisitReturn(Node* ret);
void VisitThrow(Node* node);
......
......@@ -953,10 +953,10 @@ void InstructionSequence::MarkAsRepresentation(MachineRepresentation rep,
int InstructionSequence::AddDeoptimizationEntry(
FrameStateDescriptor* descriptor, DeoptimizeKind kind,
DeoptimizeReason reason, FeedbackSource const& feedback) {
DeoptimizeReason reason, NodeId node_id, FeedbackSource const& feedback) {
int deoptimization_id = static_cast<int>(deoptimization_entries_.size());
deoptimization_entries_.push_back(
DeoptimizationEntry(descriptor, kind, reason, feedback));
DeoptimizationEntry(descriptor, kind, reason, node_id, feedback));
return deoptimization_id;
}
......
......@@ -1449,24 +1449,35 @@ class JSToWasmFrameStateDescriptor : public FrameStateDescriptor {
// frame state descriptor that we have to go back to.
class DeoptimizationEntry final {
public:
DeoptimizationEntry() = default;
DeoptimizationEntry(FrameStateDescriptor* descriptor, DeoptimizeKind kind,
DeoptimizeReason reason, FeedbackSource const& feedback)
DeoptimizeReason reason, NodeId node_id,
FeedbackSource const& feedback)
: descriptor_(descriptor),
kind_(kind),
reason_(reason),
feedback_(feedback) {}
#ifdef DEBUG
node_id_(node_id),
#endif // DEBUG
feedback_(feedback) {
USE(node_id);
}
FrameStateDescriptor* descriptor() const { return descriptor_; }
DeoptimizeKind kind() const { return kind_; }
DeoptimizeReason reason() const { return reason_; }
#ifdef DEBUG
NodeId node_id() const { return node_id_; }
#endif // DEBUG
FeedbackSource const& feedback() const { return feedback_; }
private:
FrameStateDescriptor* descriptor_ = nullptr;
DeoptimizeKind kind_ = DeoptimizeKind::kEager;
DeoptimizeReason reason_ = DeoptimizeReason::kUnknown;
FeedbackSource feedback_ = FeedbackSource();
FrameStateDescriptor* const descriptor_;
const DeoptimizeKind kind_;
const DeoptimizeReason reason_;
#ifdef DEBUG
const NodeId node_id_;
#endif // DEBUG
const FeedbackSource feedback_;
};
using DeoptimizationVector = ZoneVector<DeoptimizationEntry>;
......@@ -1775,7 +1786,7 @@ class V8_EXPORT_PRIVATE InstructionSequence final
int AddDeoptimizationEntry(FrameStateDescriptor* descriptor,
DeoptimizeKind kind, DeoptimizeReason reason,
FeedbackSource const& feedback);
NodeId node_id, FeedbackSource const& feedback);
DeoptimizationEntry const& GetDeoptimizationEntry(int deoptimization_id);
int GetDeoptimizationEntryCount() const {
return static_cast<int>(deoptimization_entries_.size());
......
......@@ -745,11 +745,19 @@ void Deoptimizer::TraceDeoptBegin(int optimization_id,
PrintF(file, "%s", CodeKindToString(compiled_code_.kind()));
}
PrintF(file,
", opt id %d, bytecode offset %d, deopt exit %d, FP to SP delta %d, "
", opt id %d, "
#ifdef DEBUG
"node id %d, "
#endif // DEBUG
"bytecode offset %d, deopt exit %d, FP to SP "
"delta %d, "
"caller SP " V8PRIxPTR_FMT ", pc " V8PRIxPTR_FMT "]\n",
optimization_id, bytecode_offset.ToInt(), deopt_exit_index_,
fp_to_sp_delta_, caller_frame_top_,
PointerAuthentication::StripPAC(from_));
optimization_id,
#ifdef DEBUG
info.node_id,
#endif // DEBUG
bytecode_offset.ToInt(), deopt_exit_index_, fp_to_sp_delta_,
caller_frame_top_, PointerAuthentication::StripPAC(from_));
if (verbose_tracing_enabled() && deopt_kind_ != DeoptimizeKind::kLazy) {
PrintF(file, " ;;; deoptimize at ");
OFStream outstr(file);
......@@ -2067,11 +2075,13 @@ Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code code, Address pc) {
CHECK(code.InstructionStart() <= pc && pc <= code.InstructionEnd());
SourcePosition last_position = SourcePosition::Unknown();
DeoptimizeReason last_reason = DeoptimizeReason::kUnknown;
uint32_t last_node_id = 0;
int last_deopt_id = kNoDeoptimizationId;
int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
RelocInfo::ModeMask(RelocInfo::DEOPT_ID) |
RelocInfo::ModeMask(RelocInfo::DEOPT_SCRIPT_OFFSET) |
RelocInfo::ModeMask(RelocInfo::DEOPT_INLINING_ID);
RelocInfo::ModeMask(RelocInfo::DEOPT_INLINING_ID) |
RelocInfo::ModeMask(RelocInfo::DEOPT_NODE_ID);
for (RelocIterator it(code, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
if (info->pc() >= pc) break;
......@@ -2085,9 +2095,11 @@ Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code code, Address pc) {
last_deopt_id = static_cast<int>(info->data());
} else if (info->rmode() == RelocInfo::DEOPT_REASON) {
last_reason = static_cast<DeoptimizeReason>(info->data());
} else if (info->rmode() == RelocInfo::DEOPT_NODE_ID) {
last_node_id = static_cast<uint32_t>(info->data());
}
}
return DeoptInfo(last_position, last_reason, last_deopt_id);
return DeoptInfo(last_position, last_reason, last_node_id, last_deopt_id);
}
// static
......
......@@ -31,11 +31,15 @@ class Deoptimizer : public Malloced {
public:
struct DeoptInfo {
DeoptInfo(SourcePosition position, DeoptimizeReason deopt_reason,
int deopt_id)
: position(position), deopt_reason(deopt_reason), deopt_id(deopt_id) {}
uint32_t node_id, int deopt_id)
: position(position),
deopt_reason(deopt_reason),
node_id(node_id),
deopt_id(deopt_id) {}
const SourcePosition position;
const DeoptimizeReason deopt_reason;
const uint32_t node_id;
const int deopt_id;
};
......
......@@ -224,6 +224,13 @@ static void PrintRelocInfo(std::ostringstream& out, Isolate* isolate,
<< "'";
} else if (rmode == RelocInfo::DEOPT_ID) {
out << " ;; debug: deopt index " << static_cast<int>(relocinfo->data());
} else if (rmode == RelocInfo::DEOPT_NODE_ID) {
#ifdef DEBUG
out << " ;; debug: deopt node id "
<< static_cast<uint32_t>(relocinfo->data());
#else // DEBUG
UNREACHABLE();
#endif // DEBUG
} else if (RelocInfo::IsEmbeddedObjectMode(rmode)) {
HeapStringAllocator allocator;
StringStream accumulator(&allocator);
......
......@@ -1004,6 +1004,9 @@ DEFINE_DEOPT_ELEMENT_ACCESSORS(LazyDeoptCount, Smi)
DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi)
DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi)
#ifdef DEBUG
DEFINE_DEOPT_ENTRY_ACCESSORS(NodeId, Smi)
#endif // DEBUG
BytecodeOffset DeoptimizationData::GetBytecodeOffset(int i) {
return BytecodeOffset(BytecodeOffsetRaw(i).value());
......
......@@ -460,13 +460,21 @@ void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) {
int deopt_count = DeoptCount();
os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
if (0 != deopt_count) {
#ifdef DEBUG
os << " index bytecode-offset node-id pc";
#else // DEBUG
os << " index bytecode-offset pc";
#endif // DEBUG
if (FLAG_print_code_verbose) os << " commands";
os << "\n";
}
for (int i = 0; i < deopt_count; i++) {
os << std::setw(6) << i << " " << std::setw(15)
<< GetBytecodeOffset(i).ToInt() << " " << std::setw(4);
<< GetBytecodeOffset(i).ToInt() << " "
#ifdef DEBUG
<< std::setw(7) << NodeId(i).value() << " "
#endif // DEBUG
<< std::setw(4);
print_pc(os, Pc(i).value());
os << std::setw(2);
......
......@@ -966,7 +966,12 @@ class DeoptimizationData : public FixedArray {
static const int kBytecodeOffsetRawOffset = 0;
static const int kTranslationIndexOffset = 1;
static const int kPcOffset = 2;
#ifdef DEBUG
static const int kNodeIdOffset = 3;
static const int kDeoptEntrySize = 4;
#else // DEBUG
static const int kDeoptEntrySize = 3;
#endif // DEBUG
// Simple element accessors.
#define DECL_ELEMENT_ACCESSORS(name, type) \
......@@ -995,6 +1000,9 @@ class DeoptimizationData : public FixedArray {
DECL_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
DECL_ENTRY_ACCESSORS(TranslationIndex, Smi)
DECL_ENTRY_ACCESSORS(Pc, Smi)
#ifdef DEBUG
DECL_ENTRY_ACCESSORS(NodeId, Smi)
#endif // DEBUG
#undef DECL_ENTRY_ACCESSORS
......
......@@ -77,8 +77,8 @@ TEST(DeoptInMiddleOfBasicBlock) {
Node* node = Node::New(zone, 0, nullptr, 0, nullptr, false);
FeedbackSource feedback;
FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
kEqual, DeoptimizeKind::kEager, DeoptimizeReason::kUnknown, feedback,
node);
kEqual, DeoptimizeKind::kEager, DeoptimizeReason::kUnknown, node->id(),
feedback, node);
jmp_opcode = cont.Encode(jmp_opcode);
Instruction* jmp_inst = Instruction::New(zone, jmp_opcode);
tester.CheckIsDeopt(jmp_inst);
......
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