private void updateUnboxedVarsInfo( Instr i, UnboxState state, Variable dst, boolean hasRescuer, boolean isDFBarrier) { HashSet<Variable> varsToBox = new HashSet<Variable>(); // Special treatment for instructions that can raise exceptions if (i.canRaiseException()) { if (hasRescuer) { // If we are going to be rescued, // box all unboxed dirty vars before we execute the instr. state.unboxedDirtyVars.clear(); } else { // We are going to exit if an exception is raised. // So, only need to bother with dirty live local vars for closures if (problem.getScope() instanceof IRClosure) { markLocalVariables(varsToBox, state.unboxedDirtyVars); } } } if (isDFBarrier) { // All dirty unboxed local vars will get reboxed. markLocalVariables(varsToBox, state.unboxedDirtyVars); // We have to re-unbox local variables as necessary since we don't // know how they are going to change once we get past this instruction. List<Variable> lvs = new ArrayList<Variable>(); markLocalVariables(lvs, state.unboxedVars.keySet()); state.unboxedVars.keySet().removeAll(lvs); } // Update set of unboxed dirty vars state.unboxedDirtyVars.removeAll(varsToBox); // FIXME: Also global variables .. see LVA / StoreLocalVar analysis. // B_TRUE and B_FALSE have unboxed forms and their operands // needn't get boxed back. Operation op = i.getOperation(); if (op != Operation.B_TRUE && op != Operation.B_FALSE) { // Vars used by this instruction that only exist in unboxed form // will have to get boxed before it is executed state.unboxedDirtyVars.removeAll(i.getUsedVariables()); } // If the instruction writes into 'dst', it will be in boxed form. if (dst != null) { state.unboxedVars.remove(dst); state.unboxedDirtyVars.remove(dst); } }
private void boxRequiredVars( Instr i, UnboxState state, Map<Variable, TemporaryLocalVariable> unboxMap, Variable dst, boolean hasRescuer, boolean isDFBarrier, List<Instr> newInstrs) { // Special treatment for instructions that can raise exceptions boolean isClosure = problem.getScope() instanceof IRClosure; HashSet<Variable> varsToBox = new HashSet<Variable>(); if (i.canRaiseException()) { if (hasRescuer) { // If we are going to be rescued, // box all unboxed dirty vars before we execute the instr varsToBox.addAll(state.unboxedDirtyVars); } else if (isClosure) { // We are going to exit if an exception is raised. // So, only need to bother with dirty live local vars for closures markLocalVariables(varsToBox, state.unboxedDirtyVars); } } if (isClosure && (i instanceof ReturnInstr || i instanceof BreakInstr)) { markLocalVariables(varsToBox, state.unboxedDirtyVars); } if (isDFBarrier) { // All dirty unboxed (local) vars will get reboxed. markLocalVariables(varsToBox, state.unboxedDirtyVars); // We have to re-unbox local variables as necessary since we don't // know how they are going to change once we get past this instruction. List<Variable> lvs = new ArrayList<Variable>(); markLocalVariables(lvs, state.unboxedVars.keySet()); state.unboxedVars.keySet().removeAll(lvs); } // B_TRUE and B_FALSE have unboxed forms and their operands // needn't get boxed back. Operation op = i.getOperation(); boolean isBranch = op == Operation.B_TRUE || op == Operation.B_FALSE; if (!isBranch) { // Vars used by this instruction that only exist in unboxed form // will have to get boxed before it is executed for (Variable v : i.getUsedVariables()) { if (state.unboxedDirtyVars.contains(v)) { varsToBox.add(v); } } } // Add boxing instrs. for (Variable v : varsToBox) { boxVar(state, state.unboxedVars.get(v), unboxMap, v, newInstrs); } // Add 'i' itself if (isBranch) { OneOperandBranchInstr bi = (OneOperandBranchInstr) i; Operand a = bi.getArg1(); Operand ua = getUnboxedOperand(state, unboxMap, a); if (ua == a) { newInstrs.add(i); } else if (op == Operation.B_TRUE) { newInstrs.add(new BTrueInstr(Operation.B_TRUE, ua, bi.getJumpTarget())); } else { newInstrs.add(new BFalseInstr(Operation.B_FALSE, ua, bi.getJumpTarget())); } } else { newInstrs.add(i); } // If the instruction writes into 'dst', it will be in boxed form. if (dst != null) { state.unboxedVars.remove(dst); state.unboxedDirtyVars.remove(dst); } }