Bug 1488515 - avoid wasm hardfp -> softfp transition twice on Android. r=bbouvier

The baseline compiler should always call builtins assuming the hardfp
calling convention on ARM, but it would actually take the native
calling convention on the device into account and sometimes use the
softfp convention.

The reason the baseline compiler should always use hardfp is that the
builtin thunks already convert hardfp->softfp along the call path and
softfp->hardfp along the return path, if this is necessary, to allow
wasm to call builtins using the hardfp convention always.

It is possible that the situation was different when the baseline
compiler was written and that the bug is the result of subsequent
changes to the thunk layer, but this is not known precisely.

There's a driveby fix here to simplify the logic around determining
hardfp vs softfp for the system ABI; UseHardFpABI() is now always
available and does the right thing, we don't need the #ifdef nest we
had previously.

--HG--
extra : rebase_source : 5b82e0d25cad05f9064e859282dd9d886da1e672
extra : amend_source : 13b9627ddda0127c7e34fe6b01f3d252f5bfba42
This commit is contained in:
Lars T Hansen 2018-11-07 15:12:56 +01:00
Родитель ad2fed0601
Коммит ca61507f1a
2 изменённых файлов: 35 добавлений и 8 удалений

Просмотреть файл

@ -0,0 +1,20 @@
// Bug 1488515 - ABI issues on Android because both the baseline compiler and
// the builtin thunks converted between hardFP and softFP.
var prog = wasmEvalText(
`(module
(func $f64div (export "test") (param $a f64) (param $b f64) (result f64)
(local $dummy0 i32)
(local $dummy1 i32)
(local $dummy2 i32)
(local $dummy3 i32)
(local $dummy4 i32)
(local $x f64)
(local $y f64)
(local $z f64)
(set_local $x (get_local $a))
(set_local $y (get_local $b))
(set_local $z (f64.floor (f64.div (get_local $x) (get_local $y))))
(get_local $z)))`);
assertEq(prog.exports.test(16096, 32), 503);

Просмотреть файл

@ -167,9 +167,15 @@ using ZeroOnOverflow = bool;
class BaseStackFrame;
// Two flags, useABI and interModule, control how calls are made.
//
// UseABI::Wasm implies that the Tls/Heap/Global registers are nonvolatile,
// except when InterModule::True is also set, when they are volatile.
//
// UseABI::Builtin implies that the Tls/Heap/Global registers are volatile.
// In this case, we require InterModule::False. The calling convention
// is otherwise like UseABI::Wasm.
//
// UseABI::System implies that the Tls/Heap/Global registers are volatile.
// Additionally, the parameter passing mechanism may be slightly different from
// the UseABI::Wasm convention.
@ -182,7 +188,7 @@ class BaseStackFrame;
// after the call (it will restore the Tls register from the save slot and load
// the other two from the Tls data).
enum class UseABI { Wasm, System };
enum class UseABI { Wasm, Builtin, System };
enum class InterModule { False = false, True = true };
#if defined(JS_CODEGEN_NONE)
@ -3642,22 +3648,23 @@ class BaseCompiler final : public BaseCompilerInterface
void beginCall(FunctionCall& call, UseABI useABI, InterModule interModule)
{
MOZ_ASSERT_IF(useABI == UseABI::Builtin, interModule == InterModule::False);
call.isInterModule = interModule == InterModule::True;
call.usesSystemAbi = useABI == UseABI::System;
if (call.usesSystemAbi) {
// Call-outs need to use the appropriate system ABI.
#if defined(JS_CODEGEN_ARM)
# if defined(JS_SIMULATOR_ARM)
call.hardFP = UseHardFpABI();
# elif defined(JS_CODEGEN_ARM_HARDFP)
call.hardFP = true;
# else
call.hardFP = false;
# endif
call.abi.setUseHardFp(call.hardFP);
#elif defined(JS_CODEGEN_MIPS32)
call.abi.enforceO32ABI();
#endif
} else {
#if defined(JS_CODEGEN_ARM)
MOZ_ASSERT(call.hardFP,
"All private ABIs pass FP arguments in registers");
#endif
}
@ -8261,7 +8268,7 @@ BaseCompiler::emitUnaryMathBuiltinCall(SymbolicAddress callee, ValType operandTy
size_t stackSpace = stackConsumed(numArgs);
FunctionCall baselineCall(lineOrBytecode);
beginCall(baselineCall, UseABI::System, InterModule::False);
beginCall(baselineCall, UseABI::Builtin, InterModule::False);
if (!emitCallArgs(signature, &baselineCall)) {
return false;