private List<Object[]> buildJVMExceptionTable() { List<Object[]> etEntries = new ArrayList<Object[]>(); for (BasicBlock b : linearizedBBList) { // We need handlers for: // - Unrescuable (handled by ensures), // - Throwable (handled by rescues) // in that order since Throwable < Unrescuable BasicBlock rBB = cfg().getRescuerBBFor(b); BasicBlock eBB = cfg().getEnsurerBBFor(b); if ((eBB != null) && (rBB == eBB || rBB == null)) { // 1. same rescue and ensure handler ==> just spit out one entry with a Throwable class // 2. only ensure handler ==> just spit out one entry with a Throwable class etEntries.add(new Object[] {b.getLabel(), eBB.getLabel(), Throwable.class}); } else if (rBB != null) { // Unrescuable comes before Throwable if (eBB != null) etEntries.add(new Object[] {b.getLabel(), eBB.getLabel(), Unrescuable.class}); etEntries.add(new Object[] {b.getLabel(), rBB.getLabel(), Throwable.class}); } } // SSS FIXME: This could be optimized by compressing entries for adjacent BBs that have // identical handlers // This could be optimized either during generation or as another pass over the table. But, if // the JVM // does that already, do we need to bother with it? return etEntries; }
private Instr[] prepareInstructionsForInterpretation() { checkRelinearization(); if (linearizedInstrArray != null) return linearizedInstrArray; // Already prepared try { buildLinearization(); // FIXME: compiler passes should have done this depends(linearization()); } catch (RuntimeException e) { LOG.error("Error linearizing cfg: ", e); CFG c = cfg(); LOG.error("\nGraph:\n" + c.toStringGraph()); LOG.error("\nInstructions:\n" + c.toStringInstrs()); throw e; } // Set up IPCs HashMap<Label, Integer> labelIPCMap = new HashMap<Label, Integer>(); List<Instr> newInstrs = new ArrayList<Instr>(); int ipc = 0; for (BasicBlock b : linearizedBBList) { labelIPCMap.put(b.getLabel(), ipc); List<Instr> bbInstrs = b.getInstrs(); int bbInstrsLength = bbInstrs.size(); for (int i = 0; i < bbInstrsLength; i++) { Instr instr = bbInstrs.get(i); if (instr instanceof Specializeable) { instr = ((Specializeable) instr).specializeForInterpretation(); bbInstrs.set(i, instr); } if (!(instr instanceof ReceiveSelfInstr)) { newInstrs.add(instr); ipc++; } } } // Set up label PCs setupLabelPCs(labelIPCMap); // Exit BB ipc cfg().getExitBB().getLabel().setTargetPC(ipc + 1); linearizedInstrArray = newInstrs.toArray(new Instr[newInstrs.size()]); return linearizedInstrArray; }
// SSS FIXME: Extremely inefficient public int getEnsurerPC(Instr excInstr) { depends(cfg()); for (BasicBlock b : linearizedBBList) { for (Instr i : b.getInstrs()) { if (i == excInstr) { BasicBlock ensurerBB = cfg.getEnsurerBBFor(b); return (ensurerBB == null) ? -1 : ensurerBB.getLabel().getTargetPC(); } } } // SSS FIXME: Cannot happen! Throw runtime exception LOG.error("Fell through looking for ensurer ipc for " + excInstr); return -1; }
/** Run any necessary passes to get the IR ready for compilation */ public Tuple<Instr[], Map<Integer, Label[]>> prepareForCompilation() { // Build CFG and run compiler passes, if necessary if (getCFG() == null) runCompilerPasses(); // Add this always since we dont re-JIT a previously // JIT-ted closure. But, check if there are other // smarts available to us and eliminate adding this // code to every closure there is. // // Add a global ensure block to catch uncaught breaks // and throw a LocalJumpError. if (this instanceof IRClosure && ((IRClosure) this).addGEBForUncaughtBreaks()) { this.relinearizeCFG = true; } try { buildLinearization(); // FIXME: compiler passes should have done this depends(linearization()); } catch (RuntimeException e) { LOG.error("Error linearizing cfg: ", e); CFG c = cfg(); LOG.error("\nGraph:\n" + c.toStringGraph()); LOG.error("\nInstructions:\n" + c.toStringInstrs()); throw e; } // Set up IPCs // FIXME: Would be nice to collapse duplicate labels; for now, using Label[] HashMap<Integer, Label[]> ipcLabelMap = new HashMap<Integer, Label[]>(); List<Instr> newInstrs = new ArrayList<Instr>(); int ipc = 0; for (BasicBlock b : linearizedBBList) { Label l = b.getLabel(); ipcLabelMap.put(ipc, catLabels(ipcLabelMap.get(ipc), l)); for (Instr i : b.getInstrs()) { if (!(i instanceof ReceiveSelfInstr)) { newInstrs.add(i); ipc++; } } } return new Tuple<Instr[], Map<Integer, Label[]>>( newInstrs.toArray(new Instr[newInstrs.size()]), ipcLabelMap); }
private void setupLabelPCs(HashMap<Label, Integer> labelIPCMap) { for (BasicBlock b : linearizedBBList) { Label l = b.getLabel(); l.setTargetPC(labelIPCMap.get(l)); } }