Example #1
0
RegisterSet RegisterSet::allFPRs()
{
    RegisterSet result;
    for (MacroAssembler::FPRegisterID reg = MacroAssembler::firstFPRegister(); reg <= MacroAssembler::lastFPRegister(); reg = static_cast<MacroAssembler::FPRegisterID>(reg + 1))
        result.set(reg);
    return result;
}
void reportUsedRegisters(Code& code)
{
    PhaseScope phaseScope(code, "reportUsedRegisters");

    // FIXME: We should tell liveness to only track Regs.
    // https://bugs.webkit.org/show_bug.cgi?id=150751
    Liveness<Tmp> liveness(code);

    for (BasicBlock* block : code) {
        Liveness<Tmp>::LocalCalc localCalc(liveness, block);

        for (unsigned instIndex = block->size(); instIndex--;) {
            Inst& inst = block->at(instIndex);
            if (inst.hasSpecial()) {
                RegisterSet registerSet;
                for (Tmp tmp : localCalc.live()) {
                    if (tmp.isReg())
                        registerSet.set(tmp.reg());
                }
                inst.reportUsedRegisters(registerSet);
            }
            localCalc.execute(instIndex);
        }
    }
}
void
MacroAssembler::PushRegsInMask(RegisterSet set, FloatRegisterSet simdSet)
{
    FloatRegisterSet doubleSet(FloatRegisterSet::Subtract(set.fpus(), simdSet));
    MOZ_ASSERT_IF(simdSet.empty(), doubleSet == set.fpus());
    unsigned numSimd = simdSet.size();
    unsigned numDouble = doubleSet.size();
    int32_t diffF = numDouble * sizeof(double) + numSimd * Simd128DataSize;
    int32_t diffG = set.gprs().size() * sizeof(intptr_t);

    // 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);
        Push(*iter);
    }
    MOZ_ASSERT(diffG == 0);

    reserveStack(diffF);
    for (FloatRegisterBackwardIterator iter(doubleSet); iter.more(); iter++) {
        diffF -= sizeof(double);
        numDouble -= 1;
        storeDouble(*iter, Address(StackPointer, diffF));
    }
    MOZ_ASSERT(numDouble == 0);
    for (FloatRegisterBackwardIterator iter(simdSet); iter.more(); iter++) {
        diffF -= Simd128DataSize;
        numSimd -= 1;
        // XXX how to choose the right move type?
        storeUnalignedInt32x4(*iter, Address(StackPointer, diffF));
    }
    MOZ_ASSERT(numSimd == 0);
    MOZ_ASSERT(diffF == 0);
}
Example #4
0
RegisterSet RegisterSet::allRegisters()
{
    RegisterSet result;
    result.merge(allGPRs());
    result.merge(allFPRs());
    return result;
}
bool HexagonRegisterAliasInfo::covers(const RegisterSet &RRs, RegisterRef RR,
      const DataFlowGraph &DFG) const {
  if (RRs.count(RR))
    return true;

  // The exact reference RR is not in the set.

  if (TargetRegisterInfo::isVirtualRegister(RR.Reg)) {
    // Check if the there are references in RRs of the same register,
    // with both covering subregisters.
    bool HasLo = RRs.count({RR.Reg, Hexagon::subreg_loreg});
    bool HasHi = RRs.count({RR.Reg, Hexagon::subreg_hireg});
    if (HasLo && HasHi)
      return true;
  }

  if (TargetRegisterInfo::isPhysicalRegister(RR.Reg)) {
    // Check if both covering subregisters are present with full
    // lane masks.
    unsigned Lo = TRI.getSubReg(RR.Reg, Hexagon::subreg_loreg);
    unsigned Hi = TRI.getSubReg(RR.Reg, Hexagon::subreg_hireg);
    if (RRs.count({Lo, 0}) && RRs.count({Hi, 0}))
      return true;
  }

  return RegisterAliasInfo::covers(RRs, RR, DFG);
}
RegisterSet RegisterSet::stackRegisters()
{
    RegisterSet result;
    result.set(MacroAssembler::stackPointerRegister);
    result.set(MacroAssembler::framePointerRegister);
    return result;
}
    CCallHelpers::JumpList generateImpl(AccessGenerationState& state, const RegisterSet& usedRegistersBySnippet, CCallHelpers& jit, std::index_sequence<ArgumentsIndex...>)
    {
        CCallHelpers::JumpList exceptions;
        // We spill (1) the used registers by IC and (2) the used registers by Snippet.
        AccessGenerationState::SpillState spillState = state.preserveLiveRegistersToStackForCall(usedRegistersBySnippet);

        jit.store32(
            CCallHelpers::TrustedImm32(state.callSiteIndexForExceptionHandlingOrOriginal().bits()),
            CCallHelpers::tagFor(static_cast<VirtualRegister>(CallFrameSlot::argumentCount)));

        jit.makeSpaceOnStackForCCall();

        jit.setupArguments<FunctionType>(std::get<ArgumentsIndex>(m_arguments)...);

        CCallHelpers::Call operationCall = jit.call(OperationPtrTag);
        auto function = m_function;
        jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
            linkBuffer.link(operationCall, FunctionPtr<OperationPtrTag>(function));
        });

        jit.setupResults(m_result);
        jit.reclaimSpaceOnStackForCCall();

        CCallHelpers::Jump noException = jit.emitExceptionCheck(state.m_vm, CCallHelpers::InvertedExceptionCheck);

        state.restoreLiveRegistersFromStackForCallWithThrownException(spillState);
        exceptions.append(jit.jump());

        noException.link(&jit);
        RegisterSet dontRestore;
        dontRestore.set(m_result);
        state.restoreLiveRegistersFromStackForCall(spillState, dontRestore);

        return exceptions;
    }
void ScratchRegisterAllocator::preserveUsedRegistersToScratchBufferForCall(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR)
{
    RegisterSet usedRegisters = usedRegistersForCall();
    if (!usedRegisters.numberOfSetRegisters())
        return;
    
    unsigned count = 0;
    for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
        if (usedRegisters.get(reg)) {
            jit.storePtr(reg, static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + count);
            count++;
        }
        if (GPRInfo::toIndex(reg) != GPRInfo::InvalidIndex
            && scratchGPR == InvalidGPRReg
            && !m_lockedRegisters.get(reg) && !m_scratchRegisters.get(reg))
            scratchGPR = reg;
    }
    RELEASE_ASSERT(scratchGPR != InvalidGPRReg);
    for (FPRReg reg = MacroAssembler::firstFPRegister(); reg <= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg)) {
        if (usedRegisters.get(reg)) {
            jit.move(MacroAssembler::TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + count), scratchGPR);
            count++;
            jit.storeDouble(reg, scratchGPR);
        }
    }
    RELEASE_ASSERT(count * sizeof(JSValue) == desiredScratchBufferSizeForCall());
    
    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratchGPR);
    jit.storePtr(MacroAssembler::TrustedImmPtr(static_cast<size_t>(count * sizeof(JSValue))), scratchGPR);
}
void HexagonExpandCondsets::postprocessUndefImplicitUses(MachineBasicBlock &B) {
  // Implicit uses that are "undef" are only meaningful (outside of the
  // internals of this pass) when the instruction defines a subregister,
  // and the implicit-undef use applies to the defined register. In such
  // cases, the proper way to record the information in the IR is to mark
  // the definition as "undef", which will be interpreted as "read-undef".
  typedef SmallSet<unsigned,2> RegisterSet;
  for (MachineBasicBlock::iterator I = B.begin(), E = B.end(); I != E; ++I) {
    MachineInstr *MI = &*I;
    RegisterSet Undefs;
    for (unsigned i = MI->getNumOperands(); i > 0; --i) {
      MachineOperand &MO = MI->getOperand(i-1);
      if (MO.isReg() && MO.isUse() && MO.isImplicit() && MO.isUndef()) {
        MI->RemoveOperand(i-1);
        Undefs.insert(MO.getReg());
      }
    }
    for (auto &Op : MI->operands()) {
      if (!Op.isReg() || !Op.isDef() || !Op.getSubReg())
        continue;
      if (Undefs.count(Op.getReg()))
        Op.setIsUndef(true);
    }
  }
}
unsigned ScratchRegisterAllocator::preserveRegistersToStackForCall(MacroAssembler& jit, const RegisterSet& usedRegisters, unsigned extraBytesAtTopOfStack)
{
    RELEASE_ASSERT(extraBytesAtTopOfStack % sizeof(void*) == 0);
    if (!usedRegisters.numberOfSetRegisters())
        return 0;
    
    unsigned stackOffset = (usedRegisters.numberOfSetRegisters()) * sizeof(EncodedJSValue);
    stackOffset += extraBytesAtTopOfStack;
    stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), stackOffset);
    jit.subPtr(
        MacroAssembler::TrustedImm32(stackOffset),
        MacroAssembler::stackPointerRegister);

    unsigned count = 0;
    for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
        if (usedRegisters.get(reg)) {
            jit.storePtr(reg, MacroAssembler::Address(MacroAssembler::stackPointerRegister, extraBytesAtTopOfStack + (count * sizeof(EncodedJSValue))));
            count++;
        }
    }
    for (FPRReg reg = MacroAssembler::firstFPRegister(); reg <= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg)) {
        if (usedRegisters.get(reg)) {
            jit.storeDouble(reg, MacroAssembler::Address(MacroAssembler::stackPointerRegister, extraBytesAtTopOfStack + (count * sizeof(EncodedJSValue))));
            count++;
        }
    }

    RELEASE_ASSERT(count == usedRegisters.numberOfSetRegisters());

    return stackOffset;
}
void ScratchRegisterAllocator::restoreUsedRegistersFromScratchBufferForCall(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR)
{
    RegisterSet usedRegisters = usedRegistersForCall();
    if (!usedRegisters.numberOfSetRegisters())
        return;
    
    if (scratchGPR == InvalidGPRReg) {
        // Find a scratch register.
        for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
            if (m_lockedRegisters.getGPRByIndex(i) || m_scratchRegisters.getGPRByIndex(i))
                continue;
            scratchGPR = GPRInfo::toRegister(i);
            break;
        }
    }
    RELEASE_ASSERT(scratchGPR != InvalidGPRReg);
    
    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratchGPR);
    jit.storePtr(MacroAssembler::TrustedImmPtr(0), scratchGPR);

    // Restore double registers first.
    unsigned count = usedRegisters.numberOfSetGPRs();
    for (FPRReg reg = MacroAssembler::firstFPRegister(); reg <= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg)) {
        if (usedRegisters.get(reg)) {
            jit.move(MacroAssembler::TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++)), scratchGPR);
            jit.loadDouble(scratchGPR, reg);
        }
    }
        
    count = 0;
    for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
        if (usedRegisters.get(reg))
            jit.loadPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++), reg);
    }
}
Example #12
0
void CallFrameShuffleData::setupCalleeSaveRegisters(CodeBlock* codeBlock)
{
    RegisterSet calleeSaveRegisters { RegisterSet::vmCalleeSaveRegisters() };
    RegisterAtOffsetList* registerSaveLocations = codeBlock->calleeSaveRegisters();

    for (size_t i = 0; i < registerSaveLocations->size(); ++i) {
        RegisterAtOffset entry { registerSaveLocations->at(i) };
        if (!calleeSaveRegisters.get(entry.reg()))
            continue;

        VirtualRegister saveSlot { entry.offsetAsIndex() };
        registers[entry.reg()]
            = ValueRecovery::displacedInJSStack(saveSlot, DataFormatJS);
    }

    for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
        if (!calleeSaveRegisters.get(reg))
            continue;

        if (registers[reg])
            continue;

        registers[reg] = ValueRecovery::inRegister(reg, DataFormatJS);
    }
}
Example #13
0
RegisterSet RegisterSet::webAssemblyCalleeSaveRegisters()
{
    RegisterSet result;
#if CPU(X86)
#elif CPU(X86_64)
#if !OS(WINDOWS)
    ASSERT(GPRInfo::regCS3 == GPRInfo::tagTypeNumberRegister);
    ASSERT(GPRInfo::regCS4 == GPRInfo::tagMaskRegister);
    result.set(GPRInfo::regCS3);
    result.set(GPRInfo::regCS4);
#else
    ASSERT(GPRInfo::regCS5 == GPRInfo::tagTypeNumberRegister);
    ASSERT(GPRInfo::regCS6 == GPRInfo::tagMaskRegister);
    result.set(GPRInfo::regCS5);
    result.set(GPRInfo::regCS6);
#endif
#elif CPU(ARM_THUMB2)
#elif CPU(ARM_TRADITIONAL)
#elif CPU(ARM64)
    ASSERT(GPRInfo::regCS8 == GPRInfo::tagTypeNumberRegister);
    ASSERT(GPRInfo::regCS9 == GPRInfo::tagMaskRegister);
    result.set(GPRInfo::regCS8);
    result.set(GPRInfo::regCS9);
#elif CPU(MIPS)
#elif CPU(SH4)
#else
    UNREACHABLE_FOR_PLATFORM();
#endif
    return result;
}
Example #14
0
HexagonBlockRanges::RegisterSet HexagonBlockRanges::getLiveIns(
      const MachineBasicBlock &B) {
  RegisterSet LiveIns;
  for (auto I : B.liveins())
    if (!Reserved[I.PhysReg])
      LiveIns.insert({I.PhysReg, 0});
  return LiveIns;
}
Example #15
0
RegisterSet RegisterSet::volatileRegistersForJSCall()
{
    RegisterSet volatileRegisters = allRegisters();
    volatileRegisters.exclude(RegisterSet::stackRegisters());
    volatileRegisters.exclude(RegisterSet::reservedHardwareRegisters());
    volatileRegisters.exclude(RegisterSet::vmCalleeSaveRegisters());
    return volatileRegisters;
}
SlowPathCallContext::SlowPathCallContext(
    RegisterSet usedRegisters, CCallHelpers& jit, unsigned numArgs, GPRReg returnRegister)
    : m_jit(jit)
    , m_numArgs(numArgs)
    , m_returnRegister(returnRegister)
{
    // We don't care that you're using callee-save, stack, or hardware registers.
    usedRegisters.exclude(RegisterSet::stackRegisters());
    usedRegisters.exclude(RegisterSet::reservedHardwareRegisters());
    usedRegisters.exclude(RegisterSet::calleeSaveRegisters());
        
    // The return register doesn't need to be saved.
    if (m_returnRegister != InvalidGPRReg)
        usedRegisters.clear(m_returnRegister);
        
    size_t stackBytesNeededForReturnAddress = wordSize;
        
    m_offsetToSavingArea =
        (std::max(m_numArgs, NUMBER_OF_ARGUMENT_REGISTERS) - NUMBER_OF_ARGUMENT_REGISTERS) * wordSize;
        
    for (unsigned i = std::min(NUMBER_OF_ARGUMENT_REGISTERS, numArgs); i--;)
        m_argumentRegisters.set(GPRInfo::toArgumentRegister(i));
    m_callingConventionRegisters.merge(m_argumentRegisters);
    if (returnRegister != InvalidGPRReg)
        m_callingConventionRegisters.set(GPRInfo::returnValueGPR);
    m_callingConventionRegisters.filter(usedRegisters);
        
    unsigned numberOfCallingConventionRegisters =
        m_callingConventionRegisters.numberOfSetRegisters();
        
    size_t offsetToThunkSavingArea =
        m_offsetToSavingArea +
        numberOfCallingConventionRegisters * wordSize;
        
    m_stackBytesNeeded =
        offsetToThunkSavingArea +
        stackBytesNeededForReturnAddress +
        (usedRegisters.numberOfSetRegisters() - numberOfCallingConventionRegisters) * wordSize;
        
    m_stackBytesNeeded = (m_stackBytesNeeded + stackAlignmentBytes() - 1) & ~(stackAlignmentBytes() - 1);
        
    m_jit.subPtr(CCallHelpers::TrustedImm32(m_stackBytesNeeded), CCallHelpers::stackPointerRegister);

    m_thunkSaveSet = usedRegisters;
        
    // This relies on all calling convention registers also being temp registers.
    unsigned stackIndex = 0;
    for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
        GPRReg reg = GPRInfo::toRegister(i);
        if (!m_callingConventionRegisters.get(reg))
            continue;
        m_jit.storePtr(reg, CCallHelpers::Address(CCallHelpers::stackPointerRegister, m_offsetToSavingArea + (stackIndex++) * wordSize));
        m_thunkSaveSet.clear(reg);
    }
        
    m_offset = offsetToThunkSavingArea;
}
Example #17
0
RegisterSet registersToPreserve()
{
    RegisterSet calleeSaves = RegisterSet::calleeSaveRegisters();
    
    // No need to preserve FP since that always gets preserved anyway.
    calleeSaves.clear(GPRInfo::callFrameRegister);
    
    return calleeSaves;
}
    void assignColors()
    {
        ASSERT(m_simplifyWorklist.isEmpty());
        ASSERT(m_worklistMoves.isEmpty());
        ASSERT(m_freezeWorklist.isEmpty());
        ASSERT(m_spillWorklist.isEmpty());

        // Reclaim as much memory as possible.
        m_interferenceEdges.clear();
        m_degrees.clear();
        m_moveList.clear();
        m_worklistMoves.clear();
        m_simplifyWorklist.clear();
        m_spillWorklist.clear();
        m_freezeWorklist.clear();

        // Try to color the Tmp on the stack.
        m_coloredTmp.resize(m_adjacencyList.size());

        while (!m_selectStack.isEmpty()) {
            unsigned tmpIndex = m_selectStack.takeLast();
            ASSERT(!isPrecolored(tmpIndex));
            ASSERT(!m_coloredTmp[tmpIndex]);

            RegisterSet coloredRegisters;
            for (IndexType adjacentTmpIndex : m_adjacencyList[tmpIndex]) {
                IndexType aliasTmpIndex = getAlias(adjacentTmpIndex);
                Reg reg = m_coloredTmp[aliasTmpIndex];

                ASSERT(!isPrecolored(aliasTmpIndex) || (isPrecolored(aliasTmpIndex) && reg));

                if (reg)
                    coloredRegisters.set(reg);
            }

            bool colorAssigned = false;
            for (Reg reg : m_regsInPriorityOrder) {
                if (!coloredRegisters.get(reg)) {
                    m_coloredTmp[tmpIndex] = reg;
                    colorAssigned = true;
                    break;
                }
            }

            if (!colorAssigned)
                m_spilledTmps.append(tmpIndex);
        }
        m_selectStack.clear();

        if (m_spilledTmps.isEmpty())
            m_coalescedTmpsAtSpill.clear();
        else
            m_coloredTmp.clear();
    }
RegisterSet RegisterSet::specialRegisters()
{
    RegisterSet result;
    result.merge(stackRegisters());
    result.set(GPRInfo::callFrameRegister);
#if USE(JSVALUE64)
    result.set(GPRInfo::tagTypeNumberRegister);
    result.set(GPRInfo::tagMaskRegister);
#endif
    return result;
}
Example #20
0
RegisterSet LivenessInfo::getLiveRegisters()
{
	RegisterSet reg;
	for(int i=0;i<noRegisters;i++)
	{
		if(isAllocatableRegister(i))
		{
			if(liveOut[i]==BIT_ON)
				reg.push_back(i);
		}
	}
	return reg;
}
Example #21
0
RegisterSet* RegisterSet::copy() {
    RegisterSet* rscopy = new RegisterSet(size());
    for (unsigned i = 0; i < size(); ++i) {
        if (at(i) == 0) { continue; }

        if (isflagged(i, (REFERENCE | BOUND))) {
            rscopy->set(i, at(i));
        } else {
            rscopy->set(i, at(i)->copy());
        }
        rscopy->setmask(i, getmask(i));
    }
    return rscopy;
}
Example #22
0
void
MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
{
    int32_t diffG = set.gprs().size() * sizeof(intptr_t);
    int32_t diffF = set.fpus().size() * sizeof(double);
    const int32_t reservedG = diffG;
    const int32_t reservedF = diffF;

    for (FloatRegisterBackwardIterator iter(set.fpus()); iter.more(); iter++) {
        diffF -= sizeof(double);
        if (!ignore.has(*iter))
            loadDouble(Address(StackPointer, diffF), *iter);
    }
    freeStack(reservedF);
    JS_ASSERT(diffF == 0);

    // On x86, use pop to pop the integer registers, if we're not going to
    // ignore any slots, as it's fast on modern hardware and it's a small
    // instruction.
    if (ignore.empty(false)) {
        for (GeneralRegisterForwardIterator iter(set.gprs()); iter.more(); iter++) {
            diffG -= sizeof(intptr_t);
            Pop(*iter);
        }
    } else {
        for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
            diffG -= sizeof(intptr_t);
            if (!ignore.has(*iter))
                loadPtr(Address(StackPointer, diffG), *iter);
        }
        freeStack(reservedG);
    }
    JS_ASSERT(diffG == 0);
}
Example #23
0
const Vector<GPRReg>& gprsInPriorityOrder()
{
    static Vector<GPRReg>* result;
    static std::once_flag once;
    std::call_once(
        once,
        [] {
            result = new Vector<GPRReg>();
            RegisterSet all = RegisterSet::allGPRs();
            all.exclude(RegisterSet::stackRegisters());
            all.exclude(RegisterSet::reservedHardwareRegisters());
            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
            all.forEach(
                [&] (Reg reg) {
                    if (!calleeSave.get(reg))
                        result->append(reg.gpr());
                });
            all.forEach(
                [&] (Reg reg) {
                    if (calleeSave.get(reg))
                        result->append(reg.gpr());
                });
        });
    return *result;
}
Example #24
0
void
MacroAssembler::printf(const char *output)
{
    RegisterSet regs = RegisterSet::Volatile();
    PushRegsInMask(regs);

    Register temp = regs.takeGeneral();

    setupUnalignedABICall(1, temp);
    movePtr(ImmWord(output), temp);
    passABIArg(temp);
    callWithABI(JS_FUNC_TO_DATA_PTR(void *, printf0_));

    PopRegsInMask(RegisterSet::Volatile());
}
RegisterSet RegisterSet::calleeSaveRegisters()
{
    RegisterSet result;
#if CPU(X86_64)
    result.set(X86Registers::ebx);
    result.set(X86Registers::ebp);
    result.set(X86Registers::r10);
    result.set(X86Registers::r12);
    result.set(X86Registers::r13);
    result.set(X86Registers::r14);
    result.set(X86Registers::r15);
#else
    UNREACHABLE_FOR_PLATFORM();
#endif
    return result;
}
void
MacroAssembler::PushRegsInMask(RegisterSet set)
{
    size_t diff = set.gprs().size() * STACK_SLOT_SIZE +
                  set.fpus().size() * sizeof(double);

    reserveStack(diff);

    for (GeneralRegisterIterator iter(set.gprs()); iter.more(); iter++) {
        diff -= STACK_SLOT_SIZE;
        storePtr(*iter, Address(StackPointer, diff));
    }
    for (FloatRegisterIterator iter(set.fpus()); iter.more(); iter++) {
        diff -= sizeof(double);
        storeDouble(*iter, Address(StackPointer, diff));
    }
}
Example #27
0
RegisterSet RegisterSet::macroScratchRegisters()
{
#if CPU(X86_64)
    return RegisterSet(MacroAssembler::s_scratchRegister);
#elif CPU(ARM64)
    return RegisterSet(MacroAssembler::dataTempRegister, MacroAssembler::memoryTempRegister);
#elif CPU(MIPS)
    RegisterSet result;
    result.set(MacroAssembler::immTempRegister);
    result.set(MacroAssembler::dataTempRegister);
    result.set(MacroAssembler::addrTempRegister);
    result.set(MacroAssembler::cmpTempRegister);
    return result;
#else
    return RegisterSet();
#endif
}
Example #28
0
static void registerClobberCheck(AssemblyHelpers& jit, RegisterSet dontClobber)
{
    if (!Options::clobberAllRegsInFTLICSlowPath())
        return;
    
    RegisterSet clobber = RegisterSet::allRegisters();
    clobber.exclude(RegisterSet::reservedHardwareRegisters());
    clobber.exclude(RegisterSet::stackRegisters());
    clobber.exclude(RegisterSet::calleeSaveRegisters());
    clobber.exclude(dontClobber);
    
    GPRReg someGPR;
    for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
        if (!clobber.get(reg) || !reg.isGPR())
            continue;
        
        jit.move(AssemblyHelpers::TrustedImm32(0x1337beef), reg.gpr());
        someGPR = reg.gpr();
    }
    
    for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
        if (!clobber.get(reg) || !reg.isFPR())
            continue;
        
        jit.move64ToDouble(someGPR, reg.fpr());
    }
}
Example #29
0
void
MacroAssembler::PushRegsInMask(RegisterSet set)
{
    int32_t diffF = set.fpus().size() * sizeof(double);
    int32_t diffG = set.gprs().size() * STACK_SLOT_SIZE;

#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
    // 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 -= STACK_SLOT_SIZE;
        Push(*iter);
    }
#elif defined(JS_CPU_ARM)
    if (set.gprs().size() > 1) {
        adjustFrame(diffG);
        startDataTransferM(IsStore, StackPointer, DB, WriteBack);
        for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
            diffG -= STACK_SLOT_SIZE;
            transferReg(*iter);
        }
        finishDataTransfer();
    } else {
        reserveStack(diffG);
        for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
            diffG -= STACK_SLOT_SIZE;
            storePtr(*iter, Address(StackPointer, diffG));
        }
    }
#else
    reserveStack(diffG);
    for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
        diffG -= STACK_SLOT_SIZE;
        storePtr(*iter, Address(StackPointer, diffG));
    }
#endif
    JS_ASSERT(diffG == 0);

#ifdef JS_CPU_ARM
    adjustFrame(diffF);
    diffF += transferMultipleByRuns(set.fpus(), IsStore, StackPointer, DB);
#else
    reserveStack(diffF);
    for (FloatRegisterBackwardIterator iter(set.fpus()); iter.more(); iter++) {
        diffF -= sizeof(double);
        storeDouble(*iter, Address(StackPointer, diffF));
    }
#endif
    JS_ASSERT(diffF == 0);
}
void ScratchRegisterAllocator::restoreRegistersFromStackForCall(MacroAssembler& jit, const RegisterSet& usedRegisters, const RegisterSet& ignore, unsigned numberOfStackBytesUsedForRegisterPreservation, unsigned extraBytesAtTopOfStack)
{
    RELEASE_ASSERT(extraBytesAtTopOfStack % sizeof(void*) == 0);
    if (!usedRegisters.numberOfSetRegisters()) {
        RELEASE_ASSERT(numberOfStackBytesUsedForRegisterPreservation == 0);
        return;
    }

    unsigned count = 0;
    for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
        if (usedRegisters.get(reg)) {
            if (!ignore.get(reg))
                jit.loadPtr(MacroAssembler::Address(MacroAssembler::stackPointerRegister, extraBytesAtTopOfStack + (sizeof(EncodedJSValue) * count)), reg);
            count++;
        }
    }
    for (FPRReg reg = MacroAssembler::firstFPRegister(); reg <= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg)) {
        if (usedRegisters.get(reg)) {
            if (!ignore.get(reg))
                jit.loadDouble(MacroAssembler::Address(MacroAssembler::stackPointerRegister, extraBytesAtTopOfStack + (sizeof(EncodedJSValue) * count)), reg);
            count++;
        }
    }

    unsigned stackOffset = (usedRegisters.numberOfSetRegisters()) * sizeof(EncodedJSValue);
    stackOffset += extraBytesAtTopOfStack;
    stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), stackOffset);

    RELEASE_ASSERT(count == usedRegisters.numberOfSetRegisters());
    RELEASE_ASSERT(stackOffset == numberOfStackBytesUsedForRegisterPreservation);

    jit.addPtr(
        MacroAssembler::TrustedImm32(stackOffset),
        MacroAssembler::stackPointerRegister);
}