[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:
parent
a9b7830d3a
commit
171d94111a
@ -22,6 +22,7 @@ extern runtime WasmStackGuard(Context): JSAny;
|
|||||||
extern runtime ThrowWasmStackOverflow(Context): JSAny;
|
extern runtime ThrowWasmStackOverflow(Context): JSAny;
|
||||||
extern runtime WasmTraceMemory(Context, Smi): JSAny;
|
extern runtime WasmTraceMemory(Context, Smi): JSAny;
|
||||||
extern runtime WasmTraceEnter(Context): JSAny;
|
extern runtime WasmTraceEnter(Context): JSAny;
|
||||||
|
extern runtime WasmTraceExit(Context, Smi): JSAny;
|
||||||
extern runtime WasmAtomicNotify(
|
extern runtime WasmAtomicNotify(
|
||||||
Context, WasmInstanceObject, Number, Number): Smi;
|
Context, WasmInstanceObject, Number, Number): Smi;
|
||||||
extern runtime WasmI32AtomicWait(
|
extern runtime WasmI32AtomicWait(
|
||||||
@ -215,6 +216,10 @@ builtin WasmTraceEnter(): JSAny {
|
|||||||
tail runtime::WasmTraceEnter(LoadContextFromFrame());
|
tail runtime::WasmTraceEnter(LoadContextFromFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builtin WasmTraceExit(info: Smi): JSAny {
|
||||||
|
tail runtime::WasmTraceExit(LoadContextFromFrame(), info);
|
||||||
|
}
|
||||||
|
|
||||||
builtin WasmAllocateJSArray(implicit context: Context)(size: Smi): JSArray {
|
builtin WasmAllocateJSArray(implicit context: Context)(size: Smi): JSArray {
|
||||||
const map: Map = GetFastPackedElementsJSArrayMap();
|
const map: Map = GetFastPackedElementsJSArrayMap();
|
||||||
return AllocateJSArray(ElementsKind::PACKED_ELEMENTS, map, size, size);
|
return AllocateJSArray(ElementsKind::PACKED_ELEMENTS, map, size, size);
|
||||||
|
@ -950,11 +950,65 @@ RUNTIME_FUNCTION(Runtime_TraceExit) {
|
|||||||
RUNTIME_FUNCTION(Runtime_WasmTraceEnter) {
|
RUNTIME_FUNCTION(Runtime_WasmTraceEnter) {
|
||||||
SealHandleScope shs(isolate);
|
SealHandleScope shs(isolate);
|
||||||
DCHECK_EQ(0, args.length());
|
DCHECK_EQ(0, args.length());
|
||||||
// TODO(10559): Print more useful info here.
|
// TODO(10559): Print function name and indentation.
|
||||||
PrintF("Enter function\n");
|
PrintF("Enter function\n");
|
||||||
return ReadOnlyRoots(isolate).undefined_value();
|
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) {
|
RUNTIME_FUNCTION(Runtime_HaveSameMap) {
|
||||||
SealHandleScope shs(isolate);
|
SealHandleScope shs(isolate);
|
||||||
DCHECK_EQ(2, args.length());
|
DCHECK_EQ(2, args.length());
|
||||||
|
@ -543,6 +543,7 @@ namespace internal {
|
|||||||
F(WasmTierUpFunction, 2, 1) \
|
F(WasmTierUpFunction, 2, 1) \
|
||||||
F(WasmTierUpModule, 1, 1) \
|
F(WasmTierUpModule, 1, 1) \
|
||||||
F(WasmTraceEnter, 0, 1) \
|
F(WasmTraceEnter, 0, 1) \
|
||||||
|
F(WasmTraceExit, 1, 1) \
|
||||||
F(WasmTraceMemory, 1, 1) \
|
F(WasmTraceMemory, 1, 1) \
|
||||||
I(DeoptimizeNow, 0, 1)
|
I(DeoptimizeNow, 0, 1)
|
||||||
|
|
||||||
|
@ -284,6 +284,8 @@ class LiftoffAssembler : public TurboAssembler {
|
|||||||
explicit LiftoffAssembler(std::unique_ptr<AssemblerBuffer>);
|
explicit LiftoffAssembler(std::unique_ptr<AssemblerBuffer>);
|
||||||
~LiftoffAssembler() override;
|
~LiftoffAssembler() override;
|
||||||
|
|
||||||
|
LiftoffRegister LoadToRegister(VarState slot, LiftoffRegList pinned);
|
||||||
|
|
||||||
LiftoffRegister PopToRegister(LiftoffRegList pinned = {});
|
LiftoffRegister PopToRegister(LiftoffRegList pinned = {});
|
||||||
|
|
||||||
// Returns the register which holds the value of stack slot {index}. If the
|
// Returns the register which holds the value of stack slot {index}. If the
|
||||||
@ -1138,7 +1140,6 @@ class LiftoffAssembler : public TurboAssembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LiftoffRegister LoadToRegister(VarState slot, LiftoffRegList pinned);
|
|
||||||
LiftoffRegister LoadI64HalfIntoRegister(VarState slot, RegPairHalf half);
|
LiftoffRegister LoadI64HalfIntoRegister(VarState slot, RegPairHalf half);
|
||||||
|
|
||||||
uint32_t num_locals_ = 0;
|
uint32_t num_locals_ = 0;
|
||||||
|
@ -1545,7 +1545,45 @@ class LiftoffCompiler {
|
|||||||
__ cache_state()->stack_state.pop_back();
|
__ 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) {
|
void ReturnImpl(FullDecoder* decoder) {
|
||||||
|
if (FLAG_trace_wasm) TraceFunctionExit(decoder);
|
||||||
size_t num_returns = decoder->sig_->return_count();
|
size_t num_returns = decoder->sig_->return_count();
|
||||||
if (num_returns > 0) __ MoveToReturnLocations(decoder->sig_, descriptor_);
|
if (num_returns > 0) __ MoveToReturnLocations(decoder->sig_, descriptor_);
|
||||||
DEBUG_CODE_COMMENT("leave frame");
|
DEBUG_CODE_COMMENT("leave frame");
|
||||||
|
@ -72,6 +72,7 @@ struct WasmModule;
|
|||||||
V(WasmThrow) \
|
V(WasmThrow) \
|
||||||
V(WasmRethrow) \
|
V(WasmRethrow) \
|
||||||
V(WasmTraceEnter) \
|
V(WasmTraceEnter) \
|
||||||
|
V(WasmTraceExit) \
|
||||||
V(WasmTraceMemory) \
|
V(WasmTraceMemory) \
|
||||||
V(ArgumentsAdaptorTrampoline) \
|
V(ArgumentsAdaptorTrampoline) \
|
||||||
V(BigIntToI32Pair) \
|
V(BigIntToI32Pair) \
|
||||||
|
@ -8,11 +8,28 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
|
|||||||
|
|
||||||
let builder = new WasmModuleBuilder();
|
let builder = new WasmModuleBuilder();
|
||||||
let kRet23Function = builder.addFunction('ret_23', kSig_i_v)
|
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()
|
.exportFunc()
|
||||||
.index;
|
.index;
|
||||||
builder.addFunction('main', kSig_v_v)
|
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');
|
.exportAs('main');
|
||||||
|
|
||||||
let instance = builder.instantiate();
|
let instance = builder.instantiate();
|
||||||
|
@ -1,2 +1,10 @@
|
|||||||
Enter function
|
Enter function
|
||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user