author | Jan de Mooij <jdemooij@mozilla.com> |
Thu, 22 Dec 2016 09:25:47 +0100 | |
changeset 374279 | ca40a39ca612747899dabfafdd236d701497ea2c |
parent 374278 | db73f66731afcb4b99e5a41e8a68a7e0e6047d7e |
child 374280 | bce06174a133a988bd9ff24fc44701cf4c75b6d9 |
push id | 1419 |
push user | jlund@mozilla.com |
push date | Mon, 10 Apr 2017 20:44:07 +0000 |
treeherder | mozilla-release@5e6801b73ef6 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | nbp |
bugs | 1322093 |
milestone | 53.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -418,16 +418,22 @@ class MacroAssembler : public MacroAssem public: // =============================================================== // Stack manipulation functions. void PushRegsInMask(LiveRegisterSet set) DEFINED_ON(arm, arm64, mips32, mips64, x86_shared); void PushRegsInMask(LiveGeneralRegisterSet set); + // Like PushRegsInMask, but instead of pushing the registers, store them to + // |dest|. |dest| should point to the end of the reserved space, so the + // first register will be stored at |dest.offset - sizeof(register)|. + void storeRegsInMask(LiveRegisterSet set, Address dest, Register scratch) + DEFINED_ON(arm, arm64, x86_shared); + void PopRegsInMask(LiveRegisterSet set); void PopRegsInMask(LiveGeneralRegisterSet set); void PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) DEFINED_ON(arm, arm64, mips32, mips64, x86_shared); void Push(const Operand op) DEFINED_ON(x86_shared); void Push(Register reg) PER_SHARED_ARCH; void Push(Register reg1, Register reg2, Register reg3, Register reg4) DEFINED_ON(arm64);
--- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -4839,16 +4839,53 @@ MacroAssembler::PushRegsInMask(LiveRegis MOZ_ASSERT(diffG == 0); adjustFrame(diffF); diffF += transferMultipleByRuns(set.fpus(), IsStore, StackPointer, DB); MOZ_ASSERT(diffF == 0); } void +MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register scratch) +{ + MOZ_ASSERT(!set.has(scratch)); + + int32_t diffF = set.fpus().getPushSizeInBytes(); + int32_t diffG = set.gprs().size() * sizeof(intptr_t); + + MOZ_ASSERT(dest.offset >= diffF + diffG); + + if (set.gprs().size() > 1) { + computeEffectiveAddress(dest, scratch); + + startDataTransferM(IsStore, scratch, DB, WriteBack); + for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) { + diffG -= sizeof(intptr_t); + dest.offset -= sizeof(intptr_t); + transferReg(*iter); + } + finishDataTransfer(); + } else { + for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) { + diffG -= sizeof(intptr_t); + dest.offset -= sizeof(intptr_t); + storePtr(*iter, dest); + } + } + MOZ_ASSERT(diffG == 0); + + if (diffF > 0) { + computeEffectiveAddress(dest, scratch); + diffF += transferMultipleByRuns(set.fpus(), IsStore, scratch, DB); + } + + MOZ_ASSERT(diffF == 0); +} + +void MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) { int32_t diffG = set.gprs().size() * sizeof(intptr_t); int32_t diffF = set.fpus().getPushSizeInBytes(); const int32_t reservedG = diffG; const int32_t reservedF = diffF; // ARM can load multiple registers at once, but only if we want back all
--- a/js/src/jit/arm64/MacroAssembler-arm64.cpp +++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp @@ -351,16 +351,22 @@ MacroAssembler::PushRegsInMask(LiveRegis ++iter; adjustFrame(8); } vixl::MacroAssembler::Push(src[0], src[1], src[2], src[3]); } } void +MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register scratch) +{ + MOZ_CRASH("NYI: storeRegsInMask"); +} + +void MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) { // The offset of the data from the stack pointer. uint32_t offset = 0; for (FloatRegisterIterator iter(set.fpus().reduceSetForPush()); iter.more(); ) { vixl::CPURegister dest[2] = { vixl::NoCPUReg, vixl::NoCPUReg }; uint32_t nextOffset = offset;
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp +++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp @@ -457,16 +457,59 @@ MacroAssembler::PushRegsInMask(LiveRegis MOZ_ASSERT(numFpu == 0); // x64 padding to keep the stack aligned on uintptr_t. Keep in sync with // GetPushBytesInSize. diffF -= diffF % sizeof(uintptr_t); MOZ_ASSERT(diffF == 0); } void +MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register scratch) +{ + // We don't use |scratch| here, but assert this for other platforms. + MOZ_ASSERT(!set.has(scratch)); + + FloatRegisterSet fpuSet(set.fpus().reduceSetForPush()); + unsigned numFpu = fpuSet.size(); + int32_t diffF = fpuSet.getPushSizeInBytes(); + int32_t diffG = set.gprs().size() * sizeof(intptr_t); + + MOZ_ASSERT(dest.offset >= diffG + diffF); + + // On x86, always use push to push the integer registers, as it's fast + // on modern hardware and it's a small instruction. + for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) { + diffG -= sizeof(intptr_t); + dest.offset -= sizeof(intptr_t); + storePtr(*iter, dest); + } + MOZ_ASSERT(diffG == 0); + + for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); ++iter) { + FloatRegister reg = *iter; + diffF -= reg.size(); + numFpu -= 1; + dest.offset -= reg.size(); + if (reg.isDouble()) + storeDouble(reg, dest); + else if (reg.isSingle()) + storeFloat32(reg, dest); + else if (reg.isSimd128()) + storeUnalignedSimd128Float(reg, dest); + else + MOZ_CRASH("Unknown register type."); + } + MOZ_ASSERT(numFpu == 0); + // x64 padding to keep the stack aligned on uintptr_t. Keep in sync with + // GetPushBytesInSize. + diffF -= diffF % sizeof(uintptr_t); + MOZ_ASSERT(diffF == 0); +} + +void MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) { FloatRegisterSet fpuSet(set.fpus().reduceSetForPush()); unsigned numFpu = fpuSet.size(); int32_t diffG = set.gprs().size() * sizeof(intptr_t); int32_t diffF = fpuSet.getPushSizeInBytes(); const int32_t reservedG = diffG; const int32_t reservedF = diffF;