[wasm] Add return value to the tracing of function calls

Added return value display when tracing function calls in wasm.
The new types handled are I32, I64, F32 and F64.
Only single return value is handled.

R=clemensb@chromium.org

Bug: v8:10559
Change-Id: I726d08fcfdc8bf2c3e43a25ec1932412ff74387b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2225024
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Commit-Queue: Arnaud Robin <arobin@google.com>
Cr-Commit-Position: refs/heads/master@{#68143}
This commit is contained in:
Arnaud Robin 2020-06-03 15:38:42 +02:00 committed by Commit Bot
parent a9b7830d3a
commit 171d94111a
8 changed files with 129 additions and 4 deletions

View File

@ -22,6 +22,7 @@ extern runtime WasmStackGuard(Context): JSAny;
extern runtime ThrowWasmStackOverflow(Context): JSAny;
extern runtime WasmTraceMemory(Context, Smi): JSAny;
extern runtime WasmTraceEnter(Context): JSAny;
extern runtime WasmTraceExit(Context, Smi): JSAny;
extern runtime WasmAtomicNotify(
Context, WasmInstanceObject, Number, Number): Smi;
extern runtime WasmI32AtomicWait(
@ -215,6 +216,10 @@ builtin WasmTraceEnter(): JSAny {
tail runtime::WasmTraceEnter(LoadContextFromFrame());
}
builtin WasmTraceExit(info: Smi): JSAny {
tail runtime::WasmTraceExit(LoadContextFromFrame(), info);
}
builtin WasmAllocateJSArray(implicit context: Context)(size: Smi): JSArray {
const map: Map = GetFastPackedElementsJSArrayMap();
return AllocateJSArray(ElementsKind::PACKED_ELEMENTS, map, size, size);

View File

@ -950,11 +950,65 @@ RUNTIME_FUNCTION(Runtime_TraceExit) {
RUNTIME_FUNCTION(Runtime_WasmTraceEnter) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
// TODO(10559): Print more useful info here.
// TODO(10559): Print function name and indentation.
PrintF("Enter function\n");
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_WasmTraceExit) {
HandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(Smi, value_addr_smi, 0);
// TODO(10559): Print function name and indentation.
PrintF("Exit function");
// Find the caller wasm frame.
wasm::WasmCodeRefScope wasm_code_ref_scope;
StackTraceFrameIterator it(isolate);
DCHECK(!it.done());
DCHECK(it.is_wasm());
WasmFrame* frame = WasmFrame::cast(it.frame());
int func_index = frame->function_index();
const wasm::FunctionSig* sig =
frame->wasm_instance().module()->functions[func_index].sig;
size_t num_returns = sig->return_count();
if (num_returns == 1) {
wasm::ValueType return_type = sig->GetReturn(0);
switch (return_type.kind()) {
case wasm::ValueType::kI32: {
int32_t value = ReadUnalignedValue<int32_t>(value_addr_smi.ptr());
PrintF(" -> %d\n", value);
break;
}
case wasm::ValueType::kI64: {
int64_t value = ReadUnalignedValue<int64_t>(value_addr_smi.ptr());
PrintF(" -> %" PRId64 "\n", value);
break;
}
case wasm::ValueType::kF32: {
float_t value = ReadUnalignedValue<float_t>(value_addr_smi.ptr());
PrintF(" -> %f\n", value);
break;
}
case wasm::ValueType::kF64: {
double_t value = ReadUnalignedValue<double_t>(value_addr_smi.ptr());
PrintF(" -> %f\n", value);
break;
}
default:
PrintF(" -> Unsupported type\n");
break;
}
} else {
// TODO(wasm) Handle multiple return values.
PrintF("\n");
}
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_HaveSameMap) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());

View File

@ -543,6 +543,7 @@ namespace internal {
F(WasmTierUpFunction, 2, 1) \
F(WasmTierUpModule, 1, 1) \
F(WasmTraceEnter, 0, 1) \
F(WasmTraceExit, 1, 1) \
F(WasmTraceMemory, 1, 1) \
I(DeoptimizeNow, 0, 1)

View File

@ -284,6 +284,8 @@ class LiftoffAssembler : public TurboAssembler {
explicit LiftoffAssembler(std::unique_ptr<AssemblerBuffer>);
~LiftoffAssembler() override;
LiftoffRegister LoadToRegister(VarState slot, LiftoffRegList pinned);
LiftoffRegister PopToRegister(LiftoffRegList pinned = {});
// Returns the register which holds the value of stack slot {index}. If the
@ -1138,7 +1140,6 @@ class LiftoffAssembler : public TurboAssembler {
}
private:
LiftoffRegister LoadToRegister(VarState slot, LiftoffRegList pinned);
LiftoffRegister LoadI64HalfIntoRegister(VarState slot, RegPairHalf half);
uint32_t num_locals_ = 0;

View File

@ -1545,7 +1545,45 @@ class LiftoffCompiler {
__ cache_state()->stack_state.pop_back();
}
void TraceFunctionExit(FullDecoder* decoder) {
DEBUG_CODE_COMMENT("trace function exit");
// Before making the runtime call, spill all cache registers.
__ SpillAllRegisters();
LiftoffRegList pinned;
// Get a register to hold the stack slot for the return value.
LiftoffRegister info = pinned.set(__ GetUnusedRegister(kGpReg, pinned));
__ AllocateStackSlot(info.gp(), sizeof(int64_t));
// Store the return value if there is exactly one. Multiple return values
// are not handled yet.
size_t num_returns = decoder->sig_->return_count();
if (num_returns == 1) {
ValueType return_type = decoder->sig_->GetReturn(0);
LiftoffRegister return_reg =
__ LoadToRegister(__ cache_state()->stack_state.back(), pinned);
__ Store(info.gp(), no_reg, 0, return_reg,
StoreType::ForValueType(return_type), pinned);
}
// Put the parameter in its place.
WasmTraceExitDescriptor descriptor;
DCHECK_EQ(0, descriptor.GetStackParameterCount());
DCHECK_EQ(1, descriptor.GetRegisterParameterCount());
Register param_reg = descriptor.GetRegisterParameter(0);
if (info.gp() != param_reg) {
__ Move(param_reg, info.gp(), LiftoffAssembler::kWasmIntPtr);
}
source_position_table_builder_.AddPosition(
__ pc_offset(), SourcePosition(decoder->position()), false);
__ CallRuntimeStub(WasmCode::kWasmTraceExit);
safepoint_table_builder_.DefineSafepoint(&asm_, Safepoint::kNoLazyDeopt);
__ DeallocateStackSlot(sizeof(int64_t));
}
void ReturnImpl(FullDecoder* decoder) {
if (FLAG_trace_wasm) TraceFunctionExit(decoder);
size_t num_returns = decoder->sig_->return_count();
if (num_returns > 0) __ MoveToReturnLocations(decoder->sig_, descriptor_);
DEBUG_CODE_COMMENT("leave frame");

View File

@ -72,6 +72,7 @@ struct WasmModule;
V(WasmThrow) \
V(WasmRethrow) \
V(WasmTraceEnter) \
V(WasmTraceExit) \
V(WasmTraceMemory) \
V(ArgumentsAdaptorTrampoline) \
V(BigIntToI32Pair) \

View File

@ -11,8 +11,25 @@ let kRet23Function = builder.addFunction('ret_23', kSig_i_v)
.addBody([kExprI32Const, 23])
.exportFunc()
.index;
let kRet57Function = builder.addFunction('ret_57', kSig_l_v)
.addBody([kExprI64Const, 57])
.exportFunc()
.index;
let kRet0Function = builder.addFunction('ret_0', kSig_f_v)
.addBody(wasmF32Const(0))
.exportFunc()
.index;
let kRet1Function = builder.addFunction('ret_1', kSig_d_v)
.addBody(wasmF64Const(1))
.exportFunc()
.index;
builder.addFunction('main', kSig_v_v)
.addBody([kExprCallFunction, kRet23Function, kExprDrop])
.addBody([
kExprCallFunction, kRet23Function, kExprDrop, // -
kExprCallFunction, kRet57Function, kExprDrop, // -
kExprCallFunction, kRet0Function, kExprDrop, // -
kExprCallFunction, kRet1Function, kExprDrop // -
])
.exportAs('main');
let instance = builder.instantiate();

View File

@ -1,2 +1,10 @@
Enter function
Enter function
Exit function -> 23
Enter function
Exit function -> 57
Enter function
Exit function -> 0.000000
Enter function
Exit function -> 1.000000
Exit function