void LinearScan::spill(SSATmp* tmp) { if (RuntimeOption::EvalDumpIR > 4) { std::cout << "--- spilling "; tmp->print(std::cout); std::cout << "\n"; } // If we're spilling, we better actually have registers allocated. ASSERT(tmp->numAllocatedRegs() > 0); ASSERT(tmp->numAllocatedRegs() == tmp->numNeededRegs()); // Free the registers used by <tmp>. // Need call freeReg and modify <m_allocatedRegs>. for (std::list<RegState*>::iterator it = m_allocatedRegs.begin(); it != m_allocatedRegs.end(); ) { std::list<RegState*>::iterator next = it; ++next; RegState* reg = *it; if (reg->m_ssaTmp == tmp) { freeReg(reg); m_allocatedRegs.erase(it); } it = next; } if (tmp->getSpillSlot() == -1) { // <tmp> hasn't been spilled before. // We need to create a new spill slot for it. uint32 slotId = createSpillSlot(tmp); // createSpillSlot sets the latest reloaded value of slotId to tmp. // Here, we need reset this value because tmp is spilled and no longer // synced with memory. m_slots[slotId].m_latestTmp = NULL; } }
void LinearScan::allocRegToTmp(SSATmp* ssaTmp, uint32_t index) { bool preferCallerSaved = true; if (RuntimeOption::EvalHHIREnableCalleeSavedOpt) { // Prefer caller-saved registers iff <ssaTmp> doesn't span native. preferCallerSaved = (ssaTmp->getLastUseId() <= getNextNativeId()); } RegState* reg = NULL; if (!preferCallerSaved) { reg = getFreeReg(false); if (reg->isCallerSaved()) { // If we are out of callee-saved registers, fall into the logic of // assigning a caller-saved register. pushFreeReg(reg); // getFreeReg pins the reg. Need restore it here. reg->m_pinned = false; reg = NULL; } } if (reg == NULL && RuntimeOption::EvalHHIREnablePreColoring) { // Pre-colors ssaTmp if it's used as an argument of next native. // Search for the original tmp instead of <ssaTmp> itself, because // the pre-coloring hint is not aware of reloaded tmps. RegNumber targetRegNo = m_preColoringHint.getPreColoringReg(getOrigTmp(ssaTmp), index); if (targetRegNo != reg::noreg) { reg = getReg(&m_regs[int(targetRegNo)]); } } if (reg == NULL && RuntimeOption::EvalHHIREnablePreColoring && ssaTmp->getInstruction()->isNative()) { // Pre-colors ssaTmp if it's the return value of a native. ASSERT(index == 0); reg = getReg(&m_regs[int(rax)]); } if (reg == NULL) { // No pre-coloring for this tmp. // Pick a regular caller-saved reg. reg = getFreeReg(true); } ASSERT(reg); if (!preferCallerSaved && reg->isCallerSaved()) { // ssaTmp spans native, but we failed to find a free callee-saved reg. // We eagerly add a spill ssaTmp, and update ssaTmp's live range // to end with next native, because we know we have to spill it at // the next native. // Setting the last use ID to the next native is conservative. // Setting it to the last use before the next native would be more precise, // but that would be more expensive to compute. if (ssaTmp->getSpillSlot() == -1) { createSpillSlot(ssaTmp); } ssaTmp->setLastUseId(getNextNativeId()); } allocRegToTmp(reg, ssaTmp, index); }