Search in sources :

Example 1 with GCIRMapElement

use of org.jikesrvm.compilers.opt.ir.GCIRMapElement in project JikesRVM by JikesRVM.

the class UpdateGCMaps1 method perform.

/**
 *  Iterate over the IR-based GC map collection and for each entry
 *  replace the symbolic reg with the real reg or spill it was allocated
 *  @param ir the IR
 */
@Override
public void perform(IR ir) {
    RegisterAllocatorState regAllocState = ir.MIRInfo.regAllocState;
    for (GCIRMapElement GCelement : ir.MIRInfo.gcIRMap) {
        if (LinearScan.GC_DEBUG) {
            VM.sysWrite("GCelement " + GCelement);
        }
        for (RegSpillListElement elem : GCelement.regSpillList()) {
            Register symbolic = elem.getSymbolicReg();
            if (LinearScan.GC_DEBUG) {
                VM.sysWriteln("get location for " + symbolic);
            }
            if (symbolic.isAllocated()) {
                Register ra = regAllocState.getMapping(symbolic);
                elem.setRealReg(ra);
                if (LinearScan.GC_DEBUG) {
                    VM.sysWriteln(ra.toString());
                }
            } else if (symbolic.isSpilled()) {
                int spill = ir.MIRInfo.regAllocState.getSpill(symbolic);
                elem.setSpill(spill);
                if (LinearScan.GC_DEBUG) {
                    VM.sysWriteln(Integer.toString(spill));
                }
            } else {
                OptimizingCompilerException.UNREACHABLE("LinearScan", "register not alive:", symbolic.toString());
            }
        }
    }
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) GCIRMapElement(org.jikesrvm.compilers.opt.ir.GCIRMapElement) RegSpillListElement(org.jikesrvm.compilers.opt.ir.RegSpillListElement)

Example 2 with GCIRMapElement

use of org.jikesrvm.compilers.opt.ir.GCIRMapElement in project JikesRVM by JikesRVM.

the class UpdateGCMaps2 method perform.

/**
 *  @param ir the IR
 */
@Override
public void perform(IR ir) {
    GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
    ScratchMap scratchMap = ir.stackManager.getScratchMap();
    RegisterAllocatorState regAllocState = ir.MIRInfo.regAllocState;
    if (LinearScan.GC_DEBUG) {
        System.out.println("SCRATCH MAP:");
        System.out.println();
        System.out.println(scratchMap);
    }
    if (scratchMap.isEmpty())
        return;
    // Walk over each instruction that has a GC point.
    for (GCIRMapElement GCelement : ir.MIRInfo.gcIRMap) {
        // new elements to add to the gc map
        HashSet<RegSpillListElement> newElements = new HashSet<RegSpillListElement>();
        Instruction GCinst = GCelement.getInstruction();
        int dfn = regAllocState.getDFN(GCinst);
        if (LinearScan.GC_DEBUG) {
            VM.sysWrite("GCelement at " + dfn + " , " + GCelement);
        }
        // a set of elements to delete from the GC Map
        HashSet<RegSpillListElement> toDelete = new HashSet<RegSpillListElement>(3);
        // For each element in the GC Map ...
        for (RegSpillListElement elem : GCelement.regSpillList()) {
            if (LinearScan.GC_DEBUG) {
                VM.sysWriteln("Update " + elem);
            }
            if (elem.isSpill()) {
                // check if the spilled value currently is cached in a scratch
                // register
                Register r = elem.getSymbolicReg();
                Register scratch = scratchMap.getScratch(r, dfn);
                if (scratch != null) {
                    if (LinearScan.GC_DEBUG) {
                        VM.sysWriteln("cached in scratch register " + scratch);
                    }
                    // we will add a new element noting that the scratch register
                    // also must be including in the GC map
                    RegSpillListElement newElem = new RegSpillListElement(r);
                    newElem.setRealReg(scratch);
                    newElements.add(newElem);
                    // valid value
                    if (scratchMap.isDirty(GCinst, r)) {
                        toDelete.add(elem);
                    }
                }
            } else {
                // check if the physical register is currently spilled.
                int n = elem.getRealRegNumber();
                Register r = phys.get(n);
                if (scratchMap.isScratch(r, dfn)) {
                    // spilled.
                    if (LinearScan.GC_DEBUG) {
                        VM.sysWriteln("CHANGE to spill location " + regAllocState.getSpill(r));
                    }
                    elem.setSpill(regAllocState.getSpill(r));
                }
            }
        }
        // delete all obsolete elements
        for (RegSpillListElement deadElem : toDelete) {
            GCelement.deleteRegSpillElement(deadElem);
        }
        // add each new Element to the gc map
        for (RegSpillListElement newElem : newElements) {
            GCelement.addRegSpillElement(newElem);
        }
    }
}
Also used : GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) Register(org.jikesrvm.compilers.opt.ir.Register) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) GCIRMapElement(org.jikesrvm.compilers.opt.ir.GCIRMapElement) RegSpillListElement(org.jikesrvm.compilers.opt.ir.RegSpillListElement) HashSet(java.util.HashSet)

Example 3 with GCIRMapElement

use of org.jikesrvm.compilers.opt.ir.GCIRMapElement in project JikesRVM by JikesRVM.

the class OptMachineCodeMap method generateMCInformation.

// //////////////////////////////////////////
// Create the map (at compile time)
// //////////////////////////////////////////
/**
 *  This method walks the IR map, and for each entry it creates
 *  the machine code mapping information for the entry.
 *  It is called during the compilation of the method, not at GC time.
 *  @param irMap  the irmap to translate from
 *  @param DUMP_MAPS dump while we work
 *  @param mcOffsets machine code offset information
 *  @return the machine code map
 */
private static OptMachineCodeMap generateMCInformation(GCIRMap irMap, boolean DUMP_MAPS, MachineCodeOffsets mcOffsets) {
    CallSiteTree inliningMap = new CallSiteTree();
    int numEntries = 0;
    // construct and encode the inlining information for those entries.
    for (GCIRMapElement irMapElem : irMap) {
        numEntries++;
        Instruction instr = irMapElem.getInstruction();
        if (instr.position() == null && instr.getBytecodeIndex() != INSTRUMENTATION_BCI) {
            if ((VM.BuildForIA32 && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.conforms(instr) && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.hasMethod(instr)) || (VM.BuildForPowerPC && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.conforms(instr) && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.hasMethod(instr))) {
                throw new OptimizingCompilerException("position required for all call instructions " + instr);
            }
        } else {
            inliningMap.addLocation(instr.position());
        }
    }
    // if no entries, then we are done.
    if (numEntries == 0)
        return emptyMachineCodeMap;
    int[] inlineEncoding = OptEncodedCallSiteTree.getEncoding(inliningMap);
    // (2) Encode the primary machine code mapping information and the GCMaps.
    OptGCMap gcMapBuilder = new OptGCMap();
    int[] tmpMC = new int[numEntries * SIZEOF_HUGE_ENTRY];
    int lastMCInfoEntry = 0;
    for (GCIRMapElement irMapElem : irMap) {
        Instruction instr = irMapElem.getInstruction();
        if (DUMP_MAPS)
            VM.sysWrite("IR Map for " + instr + "\n\t" + irMapElem);
        // retrieve the machine code offset (in bytes) from the instruction,
        ensureCorrectMapConstruction(mcOffsets, instr);
        int mco = mcOffsets.getMachineCodeOffset(instr);
        if (mco < 0) {
            VM.sysWrite("Negative machine code MCOffset found:" + mco);
            Instruction i = irMapElem.getInstruction();
            int machineCodeOffsetForI = mcOffsets.getMachineCodeOffset(i);
            VM.sysWriteln(i.getBytecodeIndex() + ", " + i + ", " + machineCodeOffsetForI);
            throw new OptimizingCompilerException("Negative machine code MCOffset found");
        }
        // create GC map and get GCI
        int gci = gcMapBuilder.generateGCMapEntry(irMapElem);
        // get bci information
        int bci = instr.getBytecodeIndex();
        if (bci < 0) {
            if ((bci == UNKNOWN_BCI) && ((VM.BuildForIA32 && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.conforms(instr) && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.hasMethod(instr)) || (VM.BuildForPowerPC && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.conforms(instr) && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.hasMethod(instr)))) {
                throw new OptimizingCompilerException("valid bytecode index required for all calls " + instr);
            }
            bci = -1;
        }
        // get index into inline encoding
        int iei = -1;
        if (instr.position() != null) {
            iei = inliningMap.find(instr.position()).encodedOffset;
        }
        // set the call info
        int cm = 0;
        if ((VM.BuildForIA32 && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.conforms(instr)) || (VM.BuildForPowerPC && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.conforms(instr))) {
            MethodOperand mo;
            if (VM.BuildForIA32) {
                mo = org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.getMethod(instr);
            } else {
                if (VM.VerifyAssertions)
                    VM._assert(VM.BuildForPowerPC);
                mo = org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.getMethod(instr);
            }
            if (mo != null && mo.isGuardedInlineOffBranch()) {
                cm = IS_GUARDED_CALL;
            } else {
                cm = IS_UNGUARDED_CALL;
            }
        }
        // Encode this entry into MCInformation
        if (bci < INVALID_BCI && iei < INVALID_IEI && gci < INVALID_GCI && mco < (OFFSET_MASK >>> OFFSET_SHIFT)) {
            // use a small entry
            if (bci == -1)
                bci = INVALID_BCI;
            if (iei == -1)
                iei = INVALID_IEI;
            if (gci == -1)
                gci = INVALID_GCI;
            if (VM.VerifyAssertions) {
                VM._assert((cm & (CALL_MASK >>> CALL_SHIFT)) == cm);
                VM._assert((bci & (BCI_MASK >>> BCI_SHIFT)) == bci);
                VM._assert((iei & (IEI_MASK >>> IEI_SHIFT)) == iei);
                VM._assert((gci & (GCI_MASK >>> GCI_SHIFT)) == gci);
                VM._assert((mco & (OFFSET_MASK >>> OFFSET_SHIFT)) == mco);
            }
            int t = START_OF_ENTRY;
            t |= (cm << CALL_SHIFT);
            t |= (bci << BCI_SHIFT);
            t |= (iei << IEI_SHIFT);
            t |= (gci << GCI_SHIFT);
            t |= (mco << OFFSET_SHIFT);
            tmpMC[lastMCInfoEntry++] = t;
        } else if (bci < BIG_INVALID_BCI && iei < BIG_INVALID_IEI && gci < BIG_INVALID_GCI && mco < (BIG_OFFSET_MASK >>> BIG_OFFSET_SHIFT)) {
            // use a big entry
            if (bci == -1)
                bci = BIG_INVALID_BCI;
            if (iei == -1)
                iei = BIG_INVALID_IEI;
            if (gci == -1)
                gci = BIG_INVALID_GCI;
            if (VM.VerifyAssertions) {
                VM._assert((cm & (BIG_CALL_MASK >>> BIG_CALL_SHIFT)) == cm);
                VM._assert((bci & (BIG_BCI_MASK >>> BIG_BCI_SHIFT)) == bci);
                VM._assert((iei & (BIG_IEI_MASK >>> BIG_IEI_SHIFT)) == iei);
                VM._assert((gci & (BIG_GCI_MASK >>> BIG_GCI_SHIFT)) == gci);
                VM._assert((mco & (BIG_OFFSET_MASK >>> BIG_OFFSET_SHIFT)) == mco);
            }
            int startIdx = lastMCInfoEntry;
            tmpMC[startIdx] = START_OF_BIG_ENTRY;
            tmpMC[startIdx + BIG_CALL_IDX_ADJ] |= (cm << BIG_CALL_SHIFT);
            tmpMC[startIdx + BIG_BCI_IDX_ADJ] |= (bci << BIG_BCI_SHIFT);
            tmpMC[startIdx + BIG_OFFSET_IDX_ADJ] |= (mco << BIG_OFFSET_SHIFT);
            tmpMC[startIdx + BIG_GCI_IDX_ADJ] |= (gci << BIG_GCI_SHIFT);
            tmpMC[startIdx + BIG_IEI_IDX_ADJ] |= (iei << BIG_IEI_SHIFT);
            lastMCInfoEntry += SIZEOF_BIG_ENTRY;
        } else {
            // use a huge entry
            if (bci == -1)
                bci = HUGE_INVALID_BCI;
            if (iei == -1)
                iei = HUGE_INVALID_IEI;
            if (gci == -1)
                gci = HUGE_INVALID_GCI;
            if (VM.VerifyAssertions) {
                VM._assert((cm & (HUGE_CALL_MASK >>> HUGE_CALL_SHIFT)) == cm);
                VM._assert((bci & (HUGE_BCI_MASK >>> HUGE_BCI_SHIFT)) == bci);
                VM._assert((iei & (HUGE_IEI_MASK >>> HUGE_IEI_SHIFT)) == iei);
                VM._assert((gci & (HUGE_GCI_MASK >>> HUGE_GCI_SHIFT)) == gci);
                VM._assert((mco & (HUGE_OFFSET_MASK >>> HUGE_OFFSET_SHIFT)) == mco);
            }
            int startIdx = lastMCInfoEntry;
            tmpMC[startIdx] = START_OF_HUGE_ENTRY;
            tmpMC[startIdx + HUGE_CALL_IDX_ADJ] |= (cm << HUGE_CALL_SHIFT);
            tmpMC[startIdx + HUGE_BCI_IDX_ADJ] |= (bci << HUGE_BCI_SHIFT);
            tmpMC[startIdx + HUGE_OFFSET_IDX_ADJ] |= (mco << HUGE_OFFSET_SHIFT);
            tmpMC[startIdx + HUGE_GCI_IDX_ADJ] |= (gci << HUGE_GCI_SHIFT);
            tmpMC[startIdx + HUGE_IEI_IDX_ADJ] |= (iei << HUGE_IEI_SHIFT);
            lastMCInfoEntry += SIZEOF_HUGE_ENTRY;
        }
    }
    int[] mcInformation = new int[lastMCInfoEntry];
    System.arraycopy(tmpMC, 0, mcInformation, 0, mcInformation.length);
    int[] gcMaps = gcMapBuilder.finish();
    return new OptMachineCodeMap(mcInformation, gcMaps, inlineEncoding);
}
Also used : CallSiteTree(org.jikesrvm.compilers.opt.inlining.CallSiteTree) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) GCIRMapElement(org.jikesrvm.compilers.opt.ir.GCIRMapElement) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand)

Aggregations

GCIRMapElement (org.jikesrvm.compilers.opt.ir.GCIRMapElement)3 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)2 RegSpillListElement (org.jikesrvm.compilers.opt.ir.RegSpillListElement)2 Register (org.jikesrvm.compilers.opt.ir.Register)2 HashSet (java.util.HashSet)1 OptimizingCompilerException (org.jikesrvm.compilers.opt.OptimizingCompilerException)1 CallSiteTree (org.jikesrvm.compilers.opt.inlining.CallSiteTree)1 GenericPhysicalRegisterSet (org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet)1 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)1