Bug 1897153 - [wasm-jspi] Add support for arm32. r=rhunt

Depends on D217426

Differential Revision: https://phabricator.services.mozilla.com/D211924
This commit is contained in:
Yury Delendik 2024-07-26 02:31:30 +00:00
parent 47b6082608
commit 0589ea4ef5
6 changed files with 77 additions and 21 deletions

View File

@ -810,9 +810,9 @@ def default_wasm_jspi(
return
if simulator:
return simulator[0] == "arm64"
return simulator[0] == "arm64" or simulator[0] == "arm"
if target.cpu in ("x86_64", "x86", "aarch64"):
if target.cpu in ("x86_64", "x86", "aarch64", "arm"):
return True
@ -845,13 +845,13 @@ def wasm_jspi(value, jit_enabled, simulator, gc, tail_calls, no_experimental, ta
if not tail_calls:
die("--enable-wasm-jspi requires --enable-wasm-tail-calls")
if simulator and (simulator[0] != "arm64"):
die("--enable-wasm-jspi is only supported for arm64 simulator")
if simulator and not (simulator[0] == "arm64" or simulator[0] == "arm"):
die("--enable-wasm-jspi is only supported for arm64/arm simulators")
if target.cpu in ("x86_64", "x86", "aarch64"):
if target.cpu in ("x86_64", "x86", "aarch64", "arm"):
return True
die("--enable-wasm-jspi only possible when targeting the x86_64/x86/arm64 jits")
die("--enable-wasm-jspi only possible when targeting the x86_64/x86/arm64/arm jits")
set_config("ENABLE_WASM_JSPI", wasm_jspi)

View File

@ -81,11 +81,12 @@
const stacks = disableSingleStepProfiling();
WasmHelpers.assertEqImpreciseStacks(stacks,
["", ">", "2,>", "<,2,>", "2,>", "<,2,>", "#ref.func function,2,>",
"<,2,>", "2,>", "<,2,>", "#update suspender state util,2,>",
"<,2,>", "2,>", "3,2,>", "4,3,2,>", "<,4,3,2,>", "4,3,2,>", "3,2,>",
"<,3,2,>", "SetPromisingPromiseResults,3,2,>", "<,3,2,>", "3,2,>", "2,>",
"<,2,>", "#update suspender state util,2,>", "<,2,>", "2,>", ">", ""]
["", ">", "1,>", "<,1,>", "CreateSuspender,1,>", "<,1,>", "1,>", "<,1,>",
"CreatePromisingPromise,1,>", "<,1,>", "1,>", "<,1,>", "#ref.func function,1,>",
"<,1,>", "1,>", "<,1,>", "#update suspender state util,1,>", "<,1,>", "1,>",
"2,1,>", "4,2,1,>", "<,4,2,1,>", "4,2,1,>", "2,1,>", "<,2,1,>",
"SetPromisingPromiseResults,2,1,>", "<,2,1,>", "2,1,>", "1,>", "<,1,>",
"#update suspender state util,1,>", "<,1,>", "1,>", ">", ""]
);
disableGeckoProfiling();

View File

@ -9512,6 +9512,8 @@ void CodeGenerator::visitWasmStackSwitchToSuspendable(
const Register ScratchReg1 = ABINonArgReg3;
# elif defined(JS_CODEGEN_X64)
const Register ScratchReg1 = ScratchReg;
# elif defined(JS_CODEGEN_ARM)
const Register ScratchReg1 = ABINonArgReturnVolatileReg;
# else
# error "NYI: scratch register"
# endif
@ -9600,8 +9602,8 @@ void CodeGenerator::visitWasmStackSwitchToSuspendable(
// WASM_FUNC_UNCHECKED_ENTRY_SLOT extended slot.
size_t uncheckedEntrySlotOffset = FunctionExtended::offsetOfExtendedSlot(
FunctionExtended::WASM_FUNC_UNCHECKED_ENTRY_SLOT);
masm.loadPtr(Address(FnReg, uncheckedEntrySlotOffset), ScratchReg1);
masm.jump(ScratchReg1);
masm.loadPtr(Address(FnReg, uncheckedEntrySlotOffset), ScratchReg2);
masm.jump(ScratchReg2);
// About to use valid FramePointer -- restore framePushed.
masm.setFramePushed(framePushed);
@ -9652,6 +9654,8 @@ void CodeGenerator::visitWasmStackSwitchToMain(LWasmStackSwitchToMain* lir) {
const Register ScratchReg1 = ABINonArgReg3;
# elif defined(JS_CODEGEN_X64)
const Register ScratchReg1 = ScratchReg;
# elif defined(JS_CODEGEN_ARM)
const Register ScratchReg1 = ABINonArgReturnVolatileReg;
# else
# error "NYI: scratch register"
# endif
@ -9769,8 +9773,8 @@ void CodeGenerator::visitWasmStackSwitchToMain(LWasmStackSwitchToMain* lir) {
// WASM_FUNC_UNCHECKED_ENTRY_SLOT extended slot.
size_t uncheckedEntrySlotOffset = FunctionExtended::offsetOfExtendedSlot(
FunctionExtended::WASM_FUNC_UNCHECKED_ENTRY_SLOT);
masm.loadPtr(Address(FnReg, uncheckedEntrySlotOffset), ScratchReg1);
masm.jump(ScratchReg1);
masm.loadPtr(Address(FnReg, uncheckedEntrySlotOffset), ScratchReg2);
masm.jump(ScratchReg2);
// About to use valid FramePointer -- restore framePushed.
masm.setFramePushed(framePushed);
@ -9820,6 +9824,8 @@ void CodeGenerator::visitWasmStackContinueOnSuspendable(
const Register ScratchReg1 = ABINonArgReg2;
# elif defined(JS_CODEGEN_X64)
const Register ScratchReg1 = ScratchReg;
# elif defined(JS_CODEGEN_ARM)
const Register ScratchReg1 = ABINonArgReturnVolatileReg;
# else
# error "NYI: scratch register"
# endif
@ -9854,8 +9860,8 @@ void CodeGenerator::visitWasmStackContinueOnSuspendable(
Address(ScratchReg1, wasm::Frame::callerFPOffset()));
// Adjust exit frame RA.
masm.mov(&returnCallsite, ScratchReg2);
masm.storePtr(ScratchReg2,
Address(ScratchReg1, wasm::Frame::returnAddressOffset()));
// Adjust exit frame caller instance slot.

View File

@ -2218,11 +2218,11 @@ void Assembler::bind(Label* label, BufferOffset boff) {
return;
}
BufferOffset dest = boff.assigned() ? boff : nextOffset();
if (label->used()) {
bool more;
// If our caller didn't give us an explicit target to bind to then we
// want to bind to the location of the next instruction.
BufferOffset dest = boff.assigned() ? boff : nextOffset();
BufferOffset b(label);
do {
BufferOffset next;
@ -2242,7 +2242,7 @@ void Assembler::bind(Label* label, BufferOffset boff) {
b = next;
} while (more);
}
label->bind(nextOffset().getOffset());
label->bind(dest.getOffset());
MOZ_ASSERT(!oom());
}

View File

@ -19,6 +19,7 @@
#include "wasm/WasmPI.h"
#include "builtin/Promise.h"
#include "jit/arm/Simulator-arm.h"
#include "jit/MIRGenerator.h"
#include "js/CallAndConstruct.h"
#include "vm/Iteration.h"
@ -102,6 +103,22 @@ void SuspenderObjectData::switchSimulatorToSuspendable() {
}
# endif
# ifdef JS_SIMULATOR_ARM
void SuspenderObjectData::switchSimulatorToMain() {
suspendableSP_ = (void*)Simulator::Current()->get_register(Simulator::sp);
suspendableFP_ = (void*)Simulator::Current()->get_register(Simulator::fp);
Simulator::Current()->set_register(Simulator::sp, (int)mainSP_);
Simulator::Current()->set_register(Simulator::fp, (int)mainFP_);
}
void SuspenderObjectData::switchSimulatorToSuspendable() {
mainSP_ = (void*)Simulator::Current()->get_register(Simulator::sp);
mainFP_ = (void*)Simulator::Current()->get_register(Simulator::fp);
Simulator::Current()->set_register(Simulator::sp, (int)suspendableSP_);
Simulator::Current()->set_register(Simulator::fp, (int)suspendableFP_);
}
# endif
// Slots that used in various JSFunctionExtended below.
const size_t SUSPENDER_SLOT = 0;
const size_t WRAPPED_FN_SLOT = 1;
@ -422,7 +439,7 @@ bool CallImportOnMainThread(JSContext* cx, Instance* instance,
suspender->setSuspended(cx);
# ifdef JS_SIMULATOR
# ifdef JS_SIMULATOR_ARM64
# if defined(JS_SIMULATOR_ARM64) || defined(JS_SIMULATOR_ARM)
// The simulator is using its own stack, however switching is needed for
// virtual registers.
stacks->switchSimulatorToMain();
@ -593,11 +610,43 @@ bool CallImportOnMainThread(JSContext* cx, Instance* instance,
: CALLER_SAVED_REGS)
INLINED_ASM(12, 16, 20, 24);
# elif defined(__arm__)
# define INLINED_ASM(MAIN_FP, MAIN_SP, SUSPENDABLE_FP, SUSPENDABLE_SP) \
CHECK_OFFSETS(MAIN_FP, MAIN_SP, SUSPENDABLE_FP, SUSPENDABLE_SP); \
asm("\n mov r0, %1" \
"\n mov r1, sp" \
"\n str r11, [r0, #" #SUSPENDABLE_FP "]" \
"\n str r1, [r0, #" #SUSPENDABLE_SP "]" \
\
"\n ldr r11, [r0, #" #MAIN_FP "]" \
"\n ldr r1, [r0, #" #MAIN_SP "]" \
"\n mov sp, r1" \
\
"\n str r0, [sp, #-8]! " \
\
"\n mov r0, %3" \
"\n blx %2" \
\
"\n ldr r2, [sp], #8 " \
\
"\n mov r1, sp" \
"\n str r11, [r2, #" #MAIN_FP "]" \
"\n str r1, [r2, #" #MAIN_SP "]" \
\
"\n ldr r11, [r2, #" #SUSPENDABLE_FP "]" \
"\n ldr r1, [r2, #" #SUSPENDABLE_SP "]" \
"\n mov sp, r1" \
"\n mov %0, r0" \
: "=r"(res) \
: "r"(stacks), "r"(CallImportData::Call), "r"(&data) \
: "r0", "r1", "r2")
INLINED_ASM(12, 16, 20, 24);
# else
MOZ_CRASH("Not supported for this platform");
# endif
// clang-format on
# endif
# endif // JS_SIMULATOR
bool ok = res;
suspender->setActive(cx);

View File

@ -179,7 +179,7 @@ class SuspenderObjectData
void restoreTIBStackFields();
#endif
#if defined(JS_SIMULATOR_ARM64)
#if defined(JS_SIMULATOR_ARM64) || defined(JS_SIMULATOR_ARM)
void switchSimulatorToMain();
void switchSimulatorToSuspendable();
#endif