From 9e2d6162c1084ab01d9ffa811835e0d505052745 Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Thu, 26 Feb 2015 12:18:23 +0100 Subject: [PATCH] Bug 1112164 part 6 - RegisterSets: takeAny should take one register and all aliases of it. r=mjrosenb --- js/src/asmjs/AsmJSValidate.cpp | 6 +++-- js/src/jit/BacktrackingAllocator.cpp | 4 ++-- js/src/jit/LinearScan.cpp | 4 ++-- js/src/jit/RegisterSets.h | 35 +++++++++++++++++++++------- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index 61cda85a3d30..56ed59b9cf48 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -8181,12 +8181,14 @@ StackDecrementForCall(MacroAssembler &masm, uint32_t alignment, const VectorT &a } #if defined(JS_CODEGEN_ARM) -// The ARM system ABI also includes d15 in the non volatile float registers. +// The ARM system ABI also includes d15 & s31 in the non volatile float registers. // Also exclude lr (a.k.a. r14) as we preserve it manually) static const RegisterSet NonVolatileRegs = RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask & ~(uint32_t(1) << Registers::lr)), - FloatRegisterSet(FloatRegisters::NonVolatileMask | (1ULL << FloatRegisters::d15))); + FloatRegisterSet(FloatRegisters::NonVolatileMask + | (1ULL << FloatRegisters::d15) + | (1ULL << FloatRegisters::s31))); #else static const RegisterSet NonVolatileRegs = RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask), diff --git a/js/src/jit/BacktrackingAllocator.cpp b/js/src/jit/BacktrackingAllocator.cpp index 0baaebb80335..1c2d3ee55c6e 100644 --- a/js/src/jit/BacktrackingAllocator.cpp +++ b/js/src/jit/BacktrackingAllocator.cpp @@ -17,11 +17,11 @@ BacktrackingAllocator::init() { RegisterSet remainingRegisters(allRegisters_); while (!remainingRegisters.empty(/* float = */ false)) { - AnyRegister reg = AnyRegister(remainingRegisters.takeGeneral()); + AnyRegister reg = AnyRegister(remainingRegisters.takeUnaliasedGeneral()); registers[reg.code()].allocatable = true; } while (!remainingRegisters.empty(/* float = */ true)) { - AnyRegister reg = AnyRegister(remainingRegisters.takeFloat()); + AnyRegister reg = AnyRegister(remainingRegisters.takeUnaliasedFloat()); registers[reg.code()].allocatable = true; } diff --git a/js/src/jit/LinearScan.cpp b/js/src/jit/LinearScan.cpp index 92fe761ea4ef..03aa25f99bf6 100644 --- a/js/src/jit/LinearScan.cpp +++ b/js/src/jit/LinearScan.cpp @@ -998,7 +998,7 @@ LinearScanAllocator::findBestFreeRegister(CodePosition *freeUntil) for (RegisterSet regs(allRegisters_); !regs.empty(needFloat); ) { // If the requested register is a FP, we may need to look at // all of the float32 and float64 registers. - AnyRegister reg = regs.takeAny(needFloat); + AnyRegister reg = regs.takeUnaliasedAny(needFloat); freeUntilPos[reg.code()] = CodePosition::MAX; } for (IntervalIterator i(active.begin()); i != active.end(); i++) { @@ -1126,7 +1126,7 @@ LinearScanAllocator::findBestBlockedRegister(CodePosition *nextUsed) CodePosition nextUsePos[AnyRegister::Total]; bool needFloat = vregs[current->vreg()].isFloatReg(); for (RegisterSet regs(allRegisters_); !regs.empty(needFloat); ) { - AnyRegister reg = regs.takeAny(needFloat); + AnyRegister reg = regs.takeUnaliasedAny(needFloat); nextUsePos[reg.code()] = CodePosition::MAX; } for (IntervalIterator i(active.begin()); i != active.end(); i++) { diff --git a/js/src/jit/RegisterSets.h b/js/src/jit/RegisterSets.h index 58d4e31ae63f..8183109712af 100644 --- a/js/src/jit/RegisterSets.h +++ b/js/src/jit/RegisterSets.h @@ -425,7 +425,7 @@ class TypedRegisterSet for (uint32_t a = 0; a < reg.numAliased(); a++) { T tmp; reg.aliased(a, &tmp); - bits_ &= ~(SetType(1) << tmp.code()); + takeUnchecked(tmp); } } void take(ValueOperand value) { @@ -488,12 +488,19 @@ class TypedRegisterSet T takeAny() { MOZ_ASSERT(!empty()); T reg = getAny(); - take(reg); + takeAllAliasedUnchecked(reg); + return reg; + } + T takeUnaliasedAny() { + // This variant is used by LinearScan for iterating over all registers. + MOZ_ASSERT(!empty()); + T reg = getAny(); + takeUnchecked(reg); return reg; } T takeAnyExcluding(T preclude) { T reg = getAnyExcluding(preclude); - take(reg); + takeAllAliasedUnchecked(reg); return reg; } ValueOperand takeAnyValue() { @@ -509,15 +516,20 @@ class TypedRegisterSet #endif } T takeFirst() { + // This function is used to implement a forward register set iterator. MOZ_ASSERT(!empty()); T reg = getFirst(); - take(reg); + // The iterator is used by PushRegsInMask which might be called with + // AllAlllocatableRegister mask. To avoid saving more than needed we + // should take aliased registers too. + takeAllAliasedUnchecked(reg); return reg; } T takeLast() { + // This function is used to implement a backward register set iterator. MOZ_ASSERT(!empty()); T reg = getLast(); - take(reg); + takeAllAliasedUnchecked(reg); return reg; } void clear() { @@ -646,9 +658,15 @@ class RegisterSet { FloatRegister takeFloat() { return fpu_.takeAny(); } + FloatRegister takeUnaliasedFloat() { + return fpu_.takeUnaliasedAny(); + } Register takeGeneral() { return gpr_.takeAny(); } + Register takeUnaliasedGeneral() { + return gpr_.takeUnaliasedAny(); + } ValueOperand takeValueOperand() { #if defined(JS_NUNBOX32) return ValueOperand(takeGeneral(), takeGeneral()); @@ -670,10 +688,11 @@ class RegisterSet { else gpr_.takeAllAliasedUnchecked(reg.gpr()); } - AnyRegister takeAny(bool isFloat) { + // This function is used by LinearScan to find a free register. + AnyRegister takeUnaliasedAny(bool isFloat) { if (isFloat) - return AnyRegister(takeFloat()); - return AnyRegister(takeGeneral()); + return AnyRegister(takeUnaliasedFloat()); + return AnyRegister(takeUnaliasedGeneral()); } void clear() { gpr_.clear();