Commit bfe13285 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Remove runtime call support from Liftoff.

This removes the support to emit runtime calls in Liftoff code and uses
WebAssembly runtime stubs instead. Calls to such stubs are smaller and
more efficient. They also use embedded builtins directly instead of the
on-heap {Code} object trampolines. This also removes the last use of a
runtime call that passes a dynamically loaded CEntry builtin from the
macro assembler.

R=clemensb@chromium.org

Change-Id: I9fa9f3b7a2b66cb76a677b70ce3cee49cb340f0f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1903443
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64855}
parent 2daa1138
......@@ -949,6 +949,7 @@ namespace internal {
TFC(WasmStackOverflow, NoContext) \
TFC(WasmThrow, WasmThrow) \
TFC(WasmRethrow, WasmThrow) \
TFS(WasmTraceMemory, kMemoryTracingInfo) \
TFS(ThrowWasmTrapUnreachable) \
TFS(ThrowWasmTrapMemOutOfBounds) \
TFS(ThrowWasmTrapUnalignedAccess) \
......@@ -1263,6 +1264,7 @@ namespace internal {
V(WasmStackOverflow) \
V(WasmThrow) \
V(WasmRethrow) \
V(WasmTraceMemory) \
V(AllocateHeapNumber) \
V(ArgumentsAdaptorTrampoline) \
V(BigIntToI32Pair) \
......
......@@ -61,6 +61,13 @@ TF_BUILTIN(WasmRethrow, WasmBuiltinsAssembler) {
TailCallRuntime(Runtime::kReThrow, context, exception);
}
TF_BUILTIN(WasmTraceMemory, WasmBuiltinsAssembler) {
TNode<Object> info = UncheckedParameter(Descriptor::kMemoryTracingInfo);
TNode<Object> instance = LoadInstanceFromFrame();
TNode<Object> context = LoadContextFromInstance(instance);
TailCallRuntime(Runtime::kWasmTraceMemory, context, info);
}
TF_BUILTIN(WasmAtomicNotify, WasmBuiltinsAssembler) {
TNode<Uint32T> address =
UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
......
......@@ -1826,19 +1826,6 @@ void TurboAssembler::TruncateDoubleToI(Isolate* isolate, Zone* zone,
bind(&done);
}
void TurboAssembler::CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
// TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code
// smarter.
mov(r0, Operand(f->nargs));
Move(r1, ExternalReference::Create(f));
DCHECK(!AreAliased(centry, r0, r1));
CallCodeObject(centry);
}
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
SaveFPRegsMode save_doubles) {
// All parameters are on the stack. r0 has the return value after call.
......
......@@ -287,10 +287,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
void LoadRootRelative(Register destination, int32_t offset) override;
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
// builtin for the target runtime function and uses an indirect call.
void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
// Jump, Call, and Ret pseudo instructions implementing inter-working.
void Call(Register target, Condition cond = al);
void Call(Address target, RelocInfo::Mode rmode, Condition cond = al,
......
......@@ -1618,19 +1618,6 @@ void TurboAssembler::AssertPositiveOrZero(Register value) {
}
}
void TurboAssembler::CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
// TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code
// smarter.
Mov(x0, f->nargs);
Mov(x1, ExternalReference::Create(f));
DCHECK(!AreAliased(centry, x0, x1));
CallCodeObject(centry);
}
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
SaveFPRegsMode save_doubles) {
// All arguments must be on the stack before this function is called.
......
......@@ -560,10 +560,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
inline void Isb();
inline void Csdb();
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
// builtin for the target runtime function and uses an indirect call.
void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
// Removes current frame and its arguments from the stack preserving
// the arguments and a return address pushed to the stack for the next call.
// Both |callee_args_count| and |caller_args_count| do not include
......
......@@ -980,20 +980,6 @@ void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
Call(code, RelocInfo::CODE_TARGET);
}
void TurboAssembler::CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
// TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code
// smarter.
Move(kRuntimeCallArgCountRegister, Immediate(f->nargs));
Move(kRuntimeCallFunctionRegister, Immediate(ExternalReference::Create(f)));
DCHECK(!AreAliased(centry, kRuntimeCallArgCountRegister,
kRuntimeCallFunctionRegister));
CallCodeObject(centry);
}
void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
// ----------- S t a t e -------------
// -- esp[0] : return address
......
......@@ -111,10 +111,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void CallForDeoptimization(Address target, int deopt_id);
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
// builtin for the target runtime function and uses an indirect call.
void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
// Jump the register contains a smi.
inline void JumpIfSmi(Register value, Label* smi_label,
Label::Distance distance = Label::kFar) {
......
......@@ -4566,19 +4566,6 @@ void TurboAssembler::MulOverflow(Register dst, Register left,
}
}
void TurboAssembler::CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
// TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code
// smarter.
PrepareCEntryArgs(f->nargs);
PrepareCEntryFunction(ExternalReference::Create(f));
DCHECK(!AreAliased(centry, a0, a1));
Call(centry, Code::kHeaderSize - kHeapObjectTag);
}
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
SaveFPRegsMode save_doubles) {
// All parameters are on the stack. v0 has the return value after call.
......
......@@ -504,10 +504,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
Label* condition_met);
#undef COND_ARGS
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
// builtin for the target runtime function and uses an indirect call.
void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
// Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32.
// Exits with 'result' holding the answer.
......
......@@ -4881,20 +4881,6 @@ void TurboAssembler::MulOverflow(Register dst, Register left,
xor_(overflow, overflow, scratch);
}
void TurboAssembler::CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
// TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code
// smarter.
PrepareCEntryArgs(f->nargs);
PrepareCEntryFunction(ExternalReference::Create(f));
DCHECK(!AreAliased(centry, a0, a1));
Daddu(centry, centry, Operand(Code::kHeaderSize - kHeapObjectTag));
Call(centry);
}
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
SaveFPRegsMode save_doubles) {
// All parameters are on the stack. v0 has the return value after call.
......
......@@ -527,10 +527,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
Label* condition_met);
#undef COND_ARGS
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
// builtin for the target runtime function and uses an indirect call.
void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
// Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32.
// Exits with 'result' holding the answer.
......
......@@ -1573,19 +1573,6 @@ void TurboAssembler::TryInlineTruncateDoubleToI(Register result,
beq(done);
}
void TurboAssembler::CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
// TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code
// smarter.
mov(r3, Operand(f->nargs));
Move(r4, ExternalReference::Create(f));
DCHECK(!AreAliased(centry, r3, r4));
CallCodeObject(centry);
}
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
SaveFPRegsMode save_doubles) {
// All parameters are on the stack. r3 has the return value after call.
......
......@@ -361,10 +361,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
int num_double_arguments,
bool has_function_descriptor = true);
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
// builtin for the target runtime function and uses an indirect call.
void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
void MovFromFloatParameter(DoubleRegister dst);
void MovFromFloatResult(DoubleRegister dst);
......
......@@ -1518,15 +1518,6 @@ void TurboAssembler::TryInlineTruncateDoubleToI(Register result,
beq(done);
}
void TurboAssembler::CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
mov(r2, Operand(f->nargs));
Move(r3, ExternalReference::Create(f));
DCHECK(!AreAliased(centry, r2, r3));
CallCodeObject(centry);
}
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
SaveFPRegsMode save_doubles) {
// All parameters are on the stack. r2 has the return value after call.
......
......@@ -811,10 +811,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
// ---------------------------------------------------------------------------
// Runtime calls
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
// builtin for the target runtime function and uses an indirect call.
void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
// Before calling a C-function from generated code, align arguments on stack.
// After aligning the frame, non-register arguments must be stored in
// sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
......
......@@ -590,20 +590,6 @@ void TurboAssembler::Abort(AbortReason reason) {
int3();
}
void TurboAssembler::CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
// TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code
// smarter.
Set(rax, f->nargs);
LoadAddress(rbx, ExternalReference::Create(f));
DCHECK(!AreAliased(centry, rax, rbx));
DCHECK(centry == rcx);
CallCodeObject(centry);
}
void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
SaveFPRegsMode save_doubles) {
// If the expected number of arguments of the runtime function is
......
......@@ -494,10 +494,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
Register caller_args_count, Register scratch0,
Register scratch1);
// Call a runtime routine. This expects {centry} to contain a fitting CEntry
// builtin for the target runtime function and uses an indirect call.
void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
void InitializeRootRegister() {
ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
Move(kRootRegister, isolate_root);
......
......@@ -1669,49 +1669,22 @@ class LiftoffCompiler {
__ Store(info.gp(), no_reg, offsetof(MemoryTracingInfo, mem_rep), address,
StoreType::kI32Store8, pinned);
WasmTraceMemoryDescriptor 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(position), false);
__ CallRuntimeStub(WasmCode::kWasmTraceMemory);
safepoint_table_builder_.DefineSafepoint(&asm_, Safepoint::kNoLazyDeopt);
Register args[] = {info.gp()};
GenerateRuntimeCall(Runtime::kWasmTraceMemory, arraysize(args), args);
__ DeallocateStackSlot(sizeof(MemoryTracingInfo));
}
void GenerateRuntimeCall(Runtime::FunctionId runtime_function, int num_args,
Register* args) {
// Currently, only one argument is supported. More arguments require some
// caution for the parallel register moves (reuse StackTransferRecipe).
DCHECK_EQ(1, num_args);
#ifdef DEBUG
auto call_descriptor = compiler::Linkage::GetRuntimeCallDescriptor(
compilation_zone_, runtime_function, num_args,
compiler::Operator::kNoProperties, compiler::CallDescriptor::kNoFlags);
constexpr size_t kInputShift = 1; // Input 0 is the call target.
compiler::LinkageLocation param_loc =
call_descriptor->GetInputLocation(kInputShift);
// Runtime calls take their arguments on the stack.
DCHECK(param_loc.IsCallerFrameSlot());
#endif
LiftoffStackSlots stack_slots(&asm_);
stack_slots.Add(LiftoffAssembler::VarState(LiftoffAssembler::kWasmIntPtr,
LiftoffRegister(args[0])));
stack_slots.Construct();
// Set context to "no context" for the runtime call.
__ TurboAssembler::Move(kContextRegister,
Smi::FromInt(Context::kNoContext));
Register centry = kJavaScriptCallCodeStartRegister;
LOAD_INSTANCE_FIELD(centry, IsolateRoot, kSystemPointerSize);
// All cache registers are spilled and there are no register arguments.
LiftoffRegList pinned;
auto centry_id =
Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit;
__ LoadTaggedPointer(centry, centry, no_reg,
IsolateData::builtin_slot_offset(centry_id), pinned);
__ CallRuntimeWithCEntry(runtime_function, centry);
safepoint_table_builder_.DefineSafepoint(&asm_, Safepoint::kNoLazyDeopt);
}
Register AddMemoryMasking(Register index, uint32_t* offset,
LiftoffRegList* pinned) {
if (!FLAG_untrusted_code_mitigations || env_->use_trap_handler) {
......
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