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); }
// Create the initial free list. // It must be called after computePreColoringHint, because the order of // caller-saved regs depends on pre-coloring hints. void LinearScan::initFreeList() { // reserve extra regs for testing purpose. for (int i = kNumX64Regs - 1; i >= 0; i--) { if (!m_regs[i].m_reserved) { pushFreeReg(&m_regs[i]); } } }
void LinearScan::freeReg(RegState* reg) { pushFreeReg(reg); // The <tmp> shouldn't be reused any more. SSATmp* tmp = reg->m_ssaTmp; int32 slotId = tmp->getSpillSlot(); if (slotId != -1) { m_slots[slotId].m_latestTmp = NULL; } reg->m_ssaTmp = NULL; }