--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -3087,26 +3087,24 @@ class BaseCompiler final : public BaseCo
loadI32(arg, RegI32(argLoc.gpr()));
}
break;
}
case ValType::I64: {
ABIArg argLoc = call.abi.next(MIRType::Int64);
if (argLoc.kind() == ABIArg::Stack) {
ScratchI32 scratch(*this);
-#if defined(JS_CODEGEN_X64)
+#ifdef JS_PUNBOX64
loadI64(arg, fromI32(scratch));
- masm.movq(scratch, Operand(masm.getStackPointer(), argLoc.offsetFromArgBase()));
-#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+ masm.storePtr(scratch, Address(masm.getStackPointer(), argLoc.offsetFromArgBase()));
+#else
loadI64Low(arg, scratch);
masm.store32(scratch, LowWord(Address(masm.getStackPointer(), argLoc.offsetFromArgBase())));
loadI64High(arg, scratch);
masm.store32(scratch, HighWord(Address(masm.getStackPointer(), argLoc.offsetFromArgBase())));
-#else
- MOZ_CRASH("BaseCompiler platform hook: passArg I64");
#endif
} else {
loadI64(arg, RegI64(argLoc.gpr64()));
}
break;
}
case ValType::F64: {
ABIArg argLoc = call.abi.next(MIRType::Double);
@@ -3495,47 +3493,49 @@ class BaseCompiler final : public BaseCo
*r1 = widenI32(specific_ecx);
*r1 = popI64ToSpecific(*r1);
*r0 = popI64();
#else
pop2xI64(r0, r1);
#endif
}
- bool rotate64NeedsTemp() const {
+ RegI32 needRotate64Temp() {
#if defined(JS_CODEGEN_X86)
- return true;
+ return needI32();
+#elif defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM)
+ return RegI32::Invalid();
#else
- return false;
+ MOZ_CRASH("BaseCompiler platform hook: needRotate64Temp");
#endif
}
void maskShiftCount32(RegI32 r) {
#if defined(JS_CODEGEN_ARM)
masm.and32(Imm32(31), r);
#endif
}
- bool popcnt32NeedsTemp() const {
+ RegI32 needPopcnt32Temp() {
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
- return !AssemblerX86Shared::HasPOPCNT();
+ return AssemblerX86Shared::HasPOPCNT() ? RegI32::Invalid() : needI32();
#elif defined(JS_CODEGEN_ARM)
- return true;
+ return needI32();
#else
- MOZ_CRASH("BaseCompiler platform hook: popcnt32NeedsTemp");
-#endif
- }
-
- bool popcnt64NeedsTemp() const {
+ MOZ_CRASH("BaseCompiler platform hook: needPopcnt32Temp");
+#endif
+ }
+
+ RegI32 needPopcnt64Temp() {
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
- return !AssemblerX86Shared::HasPOPCNT();
+ return AssemblerX86Shared::HasPOPCNT() ? RegI32::Invalid() : needI32();
#elif defined(JS_CODEGEN_ARM)
- return true;
+ return needI32();
#else
- MOZ_CRASH("BaseCompiler platform hook: popcnt64NeedsTemp");
+ MOZ_CRASH("BaseCompiler platform hook: needPopcnt64Temp");
#endif
}
RegI64 popI32ForSignExtendI64() {
#if defined(JS_CODEGEN_X86)
need2xI32(specific_edx, specific_eax);
RegI32 r0 = popI32ToSpecific(specific_eax);
RegI64 x0 = specific_edx_eax;
@@ -3714,24 +3714,25 @@ class BaseCompiler final : public BaseCo
# else
MOZ_CRASH("BaseCompiler platform hook: truncateF64ToI64");
# endif
return true;
}
#endif // RABALDR_FLOAT_TO_I64_CALLOUT
#ifndef RABALDR_I64_TO_FLOAT_CALLOUT
- bool convertI64ToFloatNeedsTemp(ValType to, bool isUnsigned) const {
+ RegI32 needConvertI64ToFloatTemp(ValType to, bool isUnsigned) {
# if defined(JS_CODEGEN_X86)
- return isUnsigned &&
- ((to == ValType::F64 && AssemblerX86Shared::HasSSE3()) ||
- to == ValType::F32);
+ bool needs = isUnsigned &&
+ ((to == ValType::F64 && AssemblerX86Shared::HasSSE3()) ||
+ to == ValType::F32);
# else
- return isUnsigned;
+ bool needs = isUnsigned;
# endif
+ return needs ? needI32() : RegI32::Invalid();
}
void convertI64ToF32(RegI64 src, bool isUnsigned, RegF32 dest, RegI32 temp) {
# if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
if (isUnsigned)
masm.convertUInt64ToFloat32(src, dest, temp);
else
masm.convertInt64ToFloat32(src, dest);
@@ -4037,21 +4038,22 @@ class BaseCompiler final : public BaseCo
}
#else
MOZ_CRASH("BaseCompiler platform hook: load");
#endif
return true;
}
- void needStoreTemps(const MemoryAccessDesc& access, ValType srcType, RegI32* tmp) {
+ RegI32 needStoreTemp(const MemoryAccessDesc& access, ValType srcType) {
#if defined(JS_CODEGEN_ARM)
if (IsUnaligned(access) && srcType != ValType::I32)
- *tmp = needI32();
-#endif
+ return needI32();
+#endif
+ return RegI32::Invalid();
}
// ptr and src must not be the same register.
// This may destroy ptr and src.
MOZ_MUST_USE bool store(MemoryAccessDesc* access, AccessCheck* check, RegI32 tls, RegI32 ptr,
AnyReg src, RegI32 tmp)
{
prepareMemoryAccess(access, check, tls, ptr);
@@ -4180,30 +4182,32 @@ class BaseCompiler final : public BaseCo
freeI32(specific_ecx);
#elif defined(JS_CODEGEN_ARM)
freeI64(rv);
#else
MOZ_CRASH("BaseCompiler porting interface: xchg64");
#endif
}
- void needAtomicRMWTemps(AtomicOp op, MemoryAccessDesc* access, RegI32* tmp) {
+ RegI32 needAtomicRMWTemp(AtomicOp op, MemoryAccessDesc* access) {
+ RegI32 tmp;
#if defined(JS_CODEGEN_X86)
// Handled specially in atomicRMW
if (access->byteSize() == 1)
- return;
+ return tmp;
#endif
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
if (op != AtomicFetchAddOp && op != AtomicFetchSubOp)
- *tmp = needI32();
+ tmp = needI32();
#elif defined(JS_CODEGEN_ARM)
- *tmp = needI32();
+ tmp = needI32();
#else
MOZ_CRASH("BaseCompiler platform hook: atomicRMWTemps");
#endif
+ return tmp;
}
void
atomicRMW(AtomicOp op, MemoryAccessDesc* access, AccessCheck* check, RegI32 tls, RegI32 ptr,
RegI32 rv, RegI32 rd, RegI32 tmp)
{
prepareMemoryAccess(access, check, tls, ptr);
ATOMIC_PTR(srcAddr, access, tls, ptr);
@@ -4253,27 +4257,29 @@ class BaseCompiler final : public BaseCo
break;
}
default: {
MOZ_CRASH("Bad type for atomic operation");
}
}
}
- void needAtomicRMW64Temps(AtomicOp op, RegI64* tmp) {
+ RegI64 needAtomicRMW64Temp(AtomicOp op) {
+ RegI64 tmp;
#if defined(JS_CODEGEN_X86)
MOZ_CRASH("Do not call on x86");
#elif defined(JS_CODEGEN_X64)
if (op != AtomicFetchAddOp && op != AtomicFetchSubOp)
- *tmp = needI64();
+ tmp = needI64();
#elif defined(JS_CODEGEN_ARM)
- *tmp = needI64Pair();
+ tmp = needI64Pair();
#else
MOZ_CRASH("BaseCompiler platform hook: atomicRMW64Temps");
#endif
+ return tmp;
}
// On x86, T is Address. On other platforms, it is Register64.
// U is BaseIndex or Address.
template <typename T, typename U>
void
atomicRMW64(AtomicOp op, T value, const U& srcAddr, Register64 tmp, Register64 rd) {
switch (op) {
@@ -5497,19 +5503,17 @@ BaseCompiler::emitRotrI32()
}
void
BaseCompiler::emitRotrI64()
{
int64_t c;
if (popConstI64(&c)) {
RegI64 r = popI64();
- RegI32 temp;
- if (rotate64NeedsTemp())
- temp = needI32();
+ RegI32 temp = needRotate64Temp();
masm.rotateRight64(Imm32(c & 63), r, r, temp);
maybeFreeI32(temp);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rotateRight64(lowPart(r1), r0, r0, maybeHighPart(r1));
freeI64(r1);
@@ -5535,19 +5539,17 @@ BaseCompiler::emitRotlI32()
}
void
BaseCompiler::emitRotlI64()
{
int64_t c;
if (popConstI64(&c)) {
RegI64 r = popI64();
- RegI32 temp;
- if (rotate64NeedsTemp())
- temp = needI32();
+ RegI32 temp = needRotate64Temp();
masm.rotateLeft64(Imm32(c & 63), r, r, temp);
maybeFreeI32(temp);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rotateLeft64(lowPart(r1), r0, r0, maybeHighPart(r1));
freeI64(r1);
@@ -5612,37 +5614,29 @@ BaseCompiler::emitCtzI64()
maybeClearHighPart(r0);
pushI64(r0);
}
void
BaseCompiler::emitPopcntI32()
{
RegI32 r0 = popI32();
- if (popcnt32NeedsTemp()) {
- RegI32 tmp = needI32();
- masm.popcnt32(r0, r0, tmp);
- freeI32(tmp);
- } else {
- masm.popcnt32(r0, r0, RegI32::Invalid());
- }
+ RegI32 tmp = needPopcnt32Temp();
+ masm.popcnt32(r0, r0, tmp);
+ maybeFreeI32(tmp);
pushI32(r0);
}
void
BaseCompiler::emitPopcntI64()
{
RegI64 r0 = popI64();
- if (popcnt64NeedsTemp()) {
- RegI32 tmp = needI32();
- masm.popcnt64(r0, r0, tmp);
- freeI32(tmp);
- } else {
- masm.popcnt64(r0, r0, RegI32::Invalid());
- }
+ RegI32 tmp = needPopcnt64Temp();
+ masm.popcnt64(r0, r0, tmp);
+ maybeFreeI32(tmp);
pushI64(r0);
}
void
BaseCompiler::emitAbsF32()
{
RegF32 r0 = popF32();
masm.absFloat32(r0, r0);
@@ -5885,19 +5879,17 @@ BaseCompiler::emitConvertI64ToF32()
pushF32(f0);
}
void
BaseCompiler::emitConvertU64ToF32()
{
RegI64 r0 = popI64();
RegF32 f0 = needF32();
- RegI32 temp;
- if (convertI64ToFloatNeedsTemp(ValType::F32, IsUnsigned(true)))
- temp = needI32();
+ RegI32 temp = needConvertI64ToFloatTemp(ValType::F32, IsUnsigned(true));
convertI64ToF32(r0, IsUnsigned(true), f0, temp);
maybeFreeI32(temp);
freeI64(r0);
pushF32(f0);
}
#endif
void
@@ -5941,19 +5933,17 @@ BaseCompiler::emitConvertI64ToF64()
pushF64(d0);
}
void
BaseCompiler::emitConvertU64ToF64()
{
RegI64 r0 = popI64();
RegF64 d0 = needF64();
- RegI32 temp;
- if (convertI64ToFloatNeedsTemp(ValType::F64, IsUnsigned(true)))
- temp = needI32();
+ RegI32 temp = needConvertI64ToFloatTemp(ValType::F64, IsUnsigned(true));
convertI64ToF64(r0, IsUnsigned(true), d0, temp);
maybeFreeI32(temp);
freeI64(r0);
pushF64(d0);
}
#endif // RABALDR_I64_TO_FLOAT_CALLOUT
void
@@ -7352,18 +7342,18 @@ BaseCompiler::emitLoad(ValType type, Sca
return loadCommon(&access, type);
}
bool
BaseCompiler::storeCommon(MemoryAccessDesc* access, ValType resultType)
{
AccessCheck check;
- RegI32 tls, tmp;
- needStoreTemps(*access, resultType, &tmp);
+ RegI32 tls;
+ RegI32 tmp = needStoreTemp(*access, resultType);
switch (resultType) {
case ValType::I32: {
RegI32 rv = popI32();
RegI32 rp = popMemoryAccess(access, &check);
tls = maybeLoadTlsForAccess(check);
if (!store(access, &check, tls, rp, AnyReg(rv), tmp))
return false;
@@ -7860,18 +7850,17 @@ BaseCompiler::emitAtomicRMW(ValType type
RegI32 rv = narrowing ? popI64ToI32() : popI32();
RegI32 rp = popMemoryAccess(&access, &check);
RegI32 output = needI32();
#else
RegI32 rv, rp, output;
MOZ_CRASH("BaseCompiler porting interface: atomic rmw");
#endif
RegI32 tls = maybeLoadTlsForAccess(check);
- RegI32 tmp;
- needAtomicRMWTemps(op, &access, &tmp);
+ RegI32 tmp = needAtomicRMWTemp(op, &access);
atomicRMW(op, &access, &check, tls, rp, rv, output, tmp);
maybeFreeI32(tls);
maybeFreeI32(tmp);
freeI32(rp);
if (rv != output)
freeI32(rv);
@@ -7943,18 +7932,17 @@ BaseCompiler::emitAtomicRMW(ValType type
RegI64 rd = needI64Pair();
# else
RegI64 rv, rd;
RegI32 rp;
MOZ_CRASH("BaseCompiler porting interface: 64-bit atomic RMW");
# endif
RegI32 tls = maybeLoadTlsForAccess(check);
- RegI64 tmp;
- needAtomicRMW64Temps(op, &tmp);
+ RegI64 tmp = needAtomicRMW64Temp(op);
prepareMemoryAccess(&access, &check, tls, rp);
ATOMIC_PTR(srcAddr, &access, tls, rp);
atomicRMW64(op, rv, srcAddr, tmp, rd);
pushI64(rd);