Commit 171d9411 authored by Arnaud Robin's avatar Arnaud Robin Committed by Commit Bot

[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/+/2225024Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Arnaud Robin <arobin@google.com>
Cr-Commit-Position: refs/heads/master@{#68143}
parent a9b7830d
......@@ -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);
......
......@@ -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());
......
......@@ -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)
......
......@@ -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;
......
......@@ -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");
......
......@@ -72,6 +72,7 @@ struct WasmModule;
V(WasmThrow) \
V(WasmRethrow) \
V(WasmTraceEnter) \
V(WasmTraceExit) \
V(WasmTraceMemory) \
V(ArgumentsAdaptorTrampoline) \
V(BigIntToI32Pair) \
......
......@@ -8,11 +8,28 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
let builder = new WasmModuleBuilder();
let kRet23Function = builder.addFunction('ret_23', kSig_i_v)
.addBody([kExprI32Const, 23])
.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();
......
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
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