[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: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64855}
This commit is contained in:
Michael Starzinger 2019-11-08 11:32:43 +01:00 committed by Commit Bot
parent 2daa1138e3
commit bfe1328565
19 changed files with 20 additions and 173 deletions

View File

@ -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) \

View File

@ -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));

View File

@ -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.

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -1669,47 +1669,20 @@ 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);
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);
__ CallRuntimeStub(WasmCode::kWasmTraceMemory);
safepoint_table_builder_.DefineSafepoint(&asm_, Safepoint::kNoLazyDeopt);
__ DeallocateStackSlot(sizeof(MemoryTracingInfo));
}
Register AddMemoryMasking(Register index, uint32_t* offset,