/** * Remove from instruction `prev' to instruction `next' both contained in this list. Throws * TargetLostException when one of the removed instruction handles is still being targeted. * * @param prev where to start deleting (predecessor, exclusive) * @param next where to end deleting (successor, exclusive) */ private void remove(InstructionHandle prev, InstructionHandle next) throws TargetLostException { InstructionHandle first, last; // First and last deleted instruction if ((prev == null) && (next == null)) { first = start; last = end; start = end = null; } else { if (prev == null) { // At start of list first = start; start = next; } else { first = prev.next; prev.next = next; } if (next == null) { // At end of list last = end; end = prev; } else { last = next.prev; next.prev = prev; } } first.prev = null; // Completely separated from rest of list last.next = null; List<InstructionHandle> target_vec = new ArrayList<InstructionHandle>(); for (InstructionHandle ih = first; ih != null; ih = ih.next) { ih.getInstruction().dispose(); // e.g. BranchInstructions release their targets } StringBuilder buf = new StringBuilder("{ "); for (InstructionHandle ih = first; ih != null; ih = next) { next = ih.next; length--; if (ih.hasTargeters()) { // Still got targeters? target_vec.add(ih); buf.append(ih.toString(true) + " "); ih.next = ih.prev = null; } else { ih.dispose(); } } buf.append("}"); if (!target_vec.isEmpty()) { InstructionHandle[] targeted = new InstructionHandle[target_vec.size()]; target_vec.toArray(targeted); throw new TargetLostException(targeted, buf.toString()); } }
/** * Replace instruction ih in list il with the instructions in new_il. If new_il is null, do * nothing */ protected static void replace_instructions( InstructionList il, InstructionHandle ih, InstructionList new_il) { if ((new_il == null) || new_il.isEmpty()) return; // If there is only one new instruction, just replace it in the handle if (new_il.getLength() == 1) { ih.setInstruction(new_il.getEnd().getInstruction()); return; } // Get the start and end instruction of the new instructions InstructionHandle new_end = new_il.getEnd(); InstructionHandle new_start = il.insert(ih, new_il); // Move all of the branches from the old instruction to the new start il.redirectBranches(ih, new_start); // Move other targets to the new instuctions. if (ih.hasTargeters()) { for (InstructionTargeter it : ih.getTargeters()) { if (it instanceof LineNumberGen) { it.updateTarget(ih, new_start); } else if (it instanceof LocalVariableGen) { it.updateTarget(ih, new_end); } else if (it instanceof CodeExceptionGen) { CodeExceptionGen exc = (CodeExceptionGen) it; if (exc.getStartPC() == ih) exc.updateTarget(ih, new_start); else if (exc.getEndPC() == ih) exc.updateTarget(ih, new_end); else if (exc.getHandlerPC() == ih) exc.setHandlerPC(new_start); else System.out.printf("Malformed CodeException: %s%n", exc); } else { System.out.printf("unexpected target %s%n", it); } } } // Remove the old handle. There should be no targeters left to it. try { il.delete(ih); } catch (Exception e) { throw new Error("Can't delete instruction", e); } }