[wasm] Refactor decoder tracing
Move more logic into the {TraceLine} class. In release builds, this class will not do anything. Since there is no code after the switch in {DecodeOp} any more after this CL, we can apply tail-call optimization (via explicit returns in C++), which will save an additional call in some cases. R=thibaudm@chromium.org Bug: v8:10576 Change-Id: Ie11ec550ab33d0c03a27375f34576e3a75dcf6ad Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2254021 Reviewed-by: Thibaud Michaud <thibaudm@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#68515}
This commit is contained in:
parent
5ce53d3666
commit
98a9c44be9
@ -1989,11 +1989,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
class TraceLine {
|
class TraceLine {
|
||||||
public:
|
public:
|
||||||
static constexpr int kMaxLen = 512;
|
explicit TraceLine(WasmFullDecoder* decoder) : decoder_(decoder) {}
|
||||||
|
|
||||||
~TraceLine() {
|
~TraceLine() {
|
||||||
if (!FLAG_trace_wasm_decoder) return;
|
if (!FLAG_trace_wasm_decoder) return;
|
||||||
|
AppendStackState();
|
||||||
PrintF("%.*s\n", len_, buffer_);
|
PrintF("%.*s\n", len_, buffer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2011,9 +2014,87 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void AppendStackState() {
|
||||||
|
DCHECK(FLAG_trace_wasm_decoder);
|
||||||
|
Append(" ");
|
||||||
|
for (Control& c : decoder_->control_) {
|
||||||
|
switch (c.kind) {
|
||||||
|
case kControlIf:
|
||||||
|
Append("I");
|
||||||
|
break;
|
||||||
|
case kControlBlock:
|
||||||
|
Append("B");
|
||||||
|
break;
|
||||||
|
case kControlLoop:
|
||||||
|
Append("L");
|
||||||
|
break;
|
||||||
|
case kControlTry:
|
||||||
|
Append("T");
|
||||||
|
break;
|
||||||
|
case kControlIfElse:
|
||||||
|
case kControlTryCatch:
|
||||||
|
case kControlLet: // TODO(7748): Implement
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c.start_merge.arity) Append("%u-", c.start_merge.arity);
|
||||||
|
Append("%u", c.end_merge.arity);
|
||||||
|
if (!c.reachable()) Append("%c", c.unreachable() ? '*' : '#');
|
||||||
|
}
|
||||||
|
Append(" | ");
|
||||||
|
for (size_t i = 0; i < decoder_->stack_.size(); ++i) {
|
||||||
|
Value& val = decoder_->stack_[i];
|
||||||
|
WasmOpcode val_opcode = static_cast<WasmOpcode>(*val.pc);
|
||||||
|
if (WasmOpcodes::IsPrefixOpcode(val_opcode)) {
|
||||||
|
val_opcode =
|
||||||
|
decoder_->template read_prefixed_opcode<Decoder::kNoValidate>(
|
||||||
|
val.pc);
|
||||||
|
}
|
||||||
|
Append(" %c@%d:%s", val.type.short_name(),
|
||||||
|
static_cast<int>(val.pc - decoder_->start_),
|
||||||
|
WasmOpcodes::OpcodeName(val_opcode));
|
||||||
|
// If the decoder failed, don't try to decode the immediates, as this
|
||||||
|
// can trigger a DCHECK failure.
|
||||||
|
if (decoder_->failed()) continue;
|
||||||
|
switch (val_opcode) {
|
||||||
|
case kExprI32Const: {
|
||||||
|
ImmI32Immediate<Decoder::kNoValidate> imm(decoder_, val.pc);
|
||||||
|
Append("[%d]", imm.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kExprLocalGet:
|
||||||
|
case kExprLocalSet:
|
||||||
|
case kExprLocalTee: {
|
||||||
|
LocalIndexImmediate<Decoder::kNoValidate> imm(decoder_, val.pc);
|
||||||
|
Append("[%u]", imm.index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kExprGlobalGet:
|
||||||
|
case kExprGlobalSet: {
|
||||||
|
GlobalIndexImmediate<Decoder::kNoValidate> imm(decoder_, val.pc);
|
||||||
|
Append("[%u]", imm.index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr int kMaxLen = 512;
|
||||||
|
|
||||||
char buffer_[kMaxLen];
|
char buffer_[kMaxLen];
|
||||||
int len_ = 0;
|
int len_ = 0;
|
||||||
|
WasmFullDecoder* const decoder_;
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
class TraceLine {
|
||||||
|
public:
|
||||||
|
explicit TraceLine(WasmFullDecoder*) {}
|
||||||
|
|
||||||
|
PRINTF_FORMAT(2, 3)
|
||||||
|
void Append(const char* format, ...) {}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
// Helper to avoid calling member methods (which are more expensive to call
|
// Helper to avoid calling member methods (which are more expensive to call
|
||||||
// indirectly).
|
// indirectly).
|
||||||
@ -2024,16 +2105,11 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
|
|
||||||
template <WasmOpcode opcode>
|
template <WasmOpcode opcode>
|
||||||
int DecodeOp() {
|
int DecodeOp() {
|
||||||
#if DEBUG
|
TraceLine trace_msg(this);
|
||||||
TraceLine trace_msg;
|
|
||||||
#define TRACE_PART(...) trace_msg.Append(__VA_ARGS__)
|
|
||||||
if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
|
if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
|
||||||
TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
|
trace_msg.Append(TRACE_INST_FORMAT, startrel(this->pc_),
|
||||||
WasmOpcodes::OpcodeName(opcode));
|
WasmOpcodes::OpcodeName(opcode));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define TRACE_PART(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int len = 1;
|
int len = 1;
|
||||||
|
|
||||||
@ -2283,8 +2359,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// The result of the block is the return value.
|
// The result of the block is the return value.
|
||||||
TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_),
|
trace_msg.Append("\n" TRACE_INST_FORMAT, startrel(this->pc_),
|
||||||
"(implicit) return");
|
"(implicit) return");
|
||||||
DoReturn();
|
DoReturn();
|
||||||
control_.clear();
|
control_.clear();
|
||||||
break;
|
break;
|
||||||
@ -2744,8 +2820,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
} else if (full_opcode >= kExprMemoryInit) {
|
} else if (full_opcode >= kExprMemoryInit) {
|
||||||
CHECK_PROTOTYPE_OPCODE(bulk_memory);
|
CHECK_PROTOTYPE_OPCODE(bulk_memory);
|
||||||
}
|
}
|
||||||
TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
|
trace_msg.Append(TRACE_INST_FORMAT, startrel(this->pc_),
|
||||||
WasmOpcodes::OpcodeName(full_opcode));
|
WasmOpcodes::OpcodeName(full_opcode));
|
||||||
len += DecodeNumericOpcode(full_opcode);
|
len += DecodeNumericOpcode(full_opcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2757,8 +2833,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
if (!VALIDATE(this->ok())) break;
|
if (!VALIDATE(this->ok())) break;
|
||||||
len += length;
|
len += length;
|
||||||
|
|
||||||
TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
|
trace_msg.Append(TRACE_INST_FORMAT, startrel(this->pc_),
|
||||||
WasmOpcodes::OpcodeName(full_opcode));
|
WasmOpcodes::OpcodeName(full_opcode));
|
||||||
len += DecodeSimdOpcode(full_opcode, length);
|
len += DecodeSimdOpcode(full_opcode, length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2769,8 +2845,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
this->template read_u8<validate>(this->pc_ + 1, "atomic index");
|
this->template read_u8<validate>(this->pc_ + 1, "atomic index");
|
||||||
WasmOpcode full_opcode =
|
WasmOpcode full_opcode =
|
||||||
static_cast<WasmOpcode>(opcode << 8 | atomic_index);
|
static_cast<WasmOpcode>(opcode << 8 | atomic_index);
|
||||||
TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
|
trace_msg.Append(TRACE_INST_FORMAT, startrel(this->pc_),
|
||||||
WasmOpcodes::OpcodeName(full_opcode));
|
WasmOpcodes::OpcodeName(full_opcode));
|
||||||
len += DecodeAtomicOpcode(full_opcode);
|
len += DecodeAtomicOpcode(full_opcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2780,8 +2856,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
this->template read_u8<validate>(this->pc_ + 1, "gc index");
|
this->template read_u8<validate>(this->pc_ + 1, "gc index");
|
||||||
WasmOpcode full_opcode =
|
WasmOpcode full_opcode =
|
||||||
static_cast<WasmOpcode>(opcode << 8 | gc_index);
|
static_cast<WasmOpcode>(opcode << 8 | gc_index);
|
||||||
TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
|
trace_msg.Append(TRACE_INST_FORMAT, startrel(this->pc_),
|
||||||
WasmOpcodes::OpcodeName(full_opcode));
|
WasmOpcodes::OpcodeName(full_opcode));
|
||||||
len = DecodeGCOpcode(full_opcode);
|
len = DecodeGCOpcode(full_opcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2804,71 +2880,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (FLAG_trace_wasm_decoder) {
|
|
||||||
TRACE_PART(" ");
|
|
||||||
for (Control& c : control_) {
|
|
||||||
switch (c.kind) {
|
|
||||||
case kControlIf:
|
|
||||||
TRACE_PART("I");
|
|
||||||
break;
|
|
||||||
case kControlBlock:
|
|
||||||
TRACE_PART("B");
|
|
||||||
break;
|
|
||||||
case kControlLoop:
|
|
||||||
TRACE_PART("L");
|
|
||||||
break;
|
|
||||||
case kControlTry:
|
|
||||||
TRACE_PART("T");
|
|
||||||
break;
|
|
||||||
case kControlIfElse:
|
|
||||||
case kControlTryCatch:
|
|
||||||
case kControlLet: // TODO(7748): Implement
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity);
|
|
||||||
TRACE_PART("%u", c.end_merge.arity);
|
|
||||||
if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#');
|
|
||||||
}
|
|
||||||
TRACE_PART(" | ");
|
|
||||||
for (size_t i = 0; i < stack_.size(); ++i) {
|
|
||||||
Value& val = stack_[i];
|
|
||||||
WasmOpcode val_opcode = static_cast<WasmOpcode>(*val.pc);
|
|
||||||
if (WasmOpcodes::IsPrefixOpcode(val_opcode)) {
|
|
||||||
val_opcode =
|
|
||||||
this->template read_prefixed_opcode<Decoder::kNoValidate>(val.pc);
|
|
||||||
}
|
|
||||||
TRACE_PART(" %c@%d:%s", val.type.short_name(),
|
|
||||||
static_cast<int>(val.pc - this->start_),
|
|
||||||
WasmOpcodes::OpcodeName(val_opcode));
|
|
||||||
// If the decoder failed, don't try to decode the immediates, as this
|
|
||||||
// can trigger a DCHECK failure.
|
|
||||||
if (this->failed()) continue;
|
|
||||||
switch (val_opcode) {
|
|
||||||
case kExprI32Const: {
|
|
||||||
ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
|
|
||||||
TRACE_PART("[%d]", imm.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kExprLocalGet:
|
|
||||||
case kExprLocalSet:
|
|
||||||
case kExprLocalTee: {
|
|
||||||
LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
|
|
||||||
TRACE_PART("[%u]", imm.index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kExprGlobalGet:
|
|
||||||
case kExprGlobalSet: {
|
|
||||||
GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
|
|
||||||
TRACE_PART("[%u]", imm.index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user