/** @return complete, i.e., deep copy of this list */ public InstructionList copy() { Map<InstructionHandle, InstructionHandle> map = new HashMap<InstructionHandle, InstructionHandle>(); InstructionList il = new InstructionList(); /* Pass 1: Make copies of all instructions, append them to the new list * and associate old instruction references with the new ones, i.e., * a 1:1 mapping. */ for (InstructionHandle ih = start; ih != null; ih = ih.next) { Instruction i = ih.instruction; Instruction c = i.copy(); // Use clone for shallow copy if (c instanceof BranchInstruction) { map.put(ih, il.append((BranchInstruction) c)); } else { map.put(ih, il.append(c)); } } /* Pass 2: Update branch targets. */ InstructionHandle ih = start; InstructionHandle ch = il.start; while (ih != null) { Instruction i = ih.instruction; Instruction c = ch.instruction; if (i instanceof BranchInstruction) { BranchInstruction bi = (BranchInstruction) i; BranchInstruction bc = (BranchInstruction) c; InstructionHandle itarget = bi.getTarget(); // old target // New target is in hash map bc.setTarget(map.get(itarget)); if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH InstructionHandle[] itargets = ((Select) bi).getTargets(); InstructionHandle[] ctargets = ((Select) bc).getTargets(); for (int j = 0; j < itargets.length; j++) { // Update all targets ctargets[j] = map.get(itargets[j]); } } } ih = ih.next; ch = ch.next; } return il; }
/** * Redirect all references from old_target to new_target, i.e., update targets of branch * instructions. * * @param old_target the old target instruction handle * @param new_target the new target instruction handle */ public void redirectBranches(InstructionHandle old_target, InstructionHandle new_target) { for (InstructionHandle ih = start; ih != null; ih = ih.next) { Instruction i = ih.getInstruction(); if (i instanceof BranchInstruction) { BranchInstruction b = (BranchInstruction) i; InstructionHandle target = b.getTarget(); if (target == old_target) { b.setTarget(new_target); } if (b instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH InstructionHandle[] targets = ((Select) b).getTargets(); for (int j = 0; j < targets.length; j++) { if (targets[j] == old_target) { ((Select) b).setTarget(j, new_target); } } } } } }