freshMethod.assertGoodBody();
InstructionList freshBody = freshMethod.getBody();
for (InstructionHandle oldIh = start.getNext(); oldIh != end; oldIh = oldIh.getNext()) {
// first we copy the instruction itself.
Instruction oldI = oldIh.getInstruction();
Instruction freshI = (oldI == RANGEINSTRUCTION) ? oldI : Utility.copyInstruction(oldI);
// Now we add it to the new instruction list.
InstructionHandle freshIh;
if (freshI instanceof InstructionBranch) {
// If it's a targeting instruction,
// update the target(s) to point to the new copy instead of the old copy.
InstructionBranch oldBranch = (InstructionBranch) oldI;
InstructionBranch freshBranch = (InstructionBranch) freshI;
InstructionHandle oldTarget = oldBranch.getTarget();
oldTarget.removeTargeter(oldBranch);
oldTarget.addTargeter(freshBranch);
if (freshBranch instanceof InstructionSelect) {
InstructionSelect oldSelect = (InstructionSelect) oldI;
InstructionSelect freshSelect = (InstructionSelect) freshI;
InstructionHandle[] oldTargets = freshSelect.getTargets();
for (int k = oldTargets.length - 1; k >= 0; k--) {
oldTargets[k].removeTargeter(oldSelect);
oldTargets[k].addTargeter(freshSelect);
}
}
freshIh = freshBody.append(freshBranch);
} else {
freshIh = freshBody.append(freshI);
}
// if source comes before target:
// source <--> target
// --> [process: target.removeTargeter(source); target.addTargeter(sourcecopy)]
// source ---------\
// v
// sourcecopy <--> target
// --> [ process: sourcecopy.updateTarget(target, targetcopy) ]
// source ----> target
// sourcecopy <--> targetcopy
// if target comes before source
// target <--> source
// --> [process: source.updateTarget(target, targetcopy) ]
// target
// targetcopy <--> source
// --> [process: targetcopy.removeTargeter(source); targetcopy.addTargeter(sourcecopy)]
// target source
// v
// targetcopy <--> sourcecopy
// now deal with the old instruction's targeters. Update them all to point to us
// instead of the old instruction. We use updateTarget to do this. One goal is
// to make sure we remove all targeters from the old guy, so we can successfully
// delete it.
for (InstructionTargeter source : oldIh.getTargetersCopy()) {
if (source instanceof LocalVariableTag) {
Shadow.Kind kind = getKind();
if (kind == Shadow.AdviceExecution || kind == Shadow.ConstructorExecution || kind == Shadow.MethodExecution
|| kind == Shadow.PreInitialization || kind == Shadow.Initialization
|| kind == Shadow.StaticInitialization) {
LocalVariableTag sourceLocalVariableTag = (LocalVariableTag) source;
if (sourceLocalVariableTag.getSlot() == 0) {
// might be 'this' so should be renamed if being dumped in a static method 277616
if (sourceLocalVariableTag.getName().equals("this")) {
sourceLocalVariableTag.setName("ajc$this");
}
}
// if we're extracting a whole block we can do this...
source.updateTarget(oldIh, freshIh);
} else {
// XXX destroying local variable info
// but only for a call or get join point, so no big deal
source.updateTarget(oldIh, null);
}
} else if (source instanceof Range) {
// exceptions and shadows are just moved
((Range) source).updateTarget(oldIh, freshIh, freshBody);
} else {
// line numbers can be shared,
// branches will be copied along with us.
source.updateTarget(oldIh, freshIh);
}
}
// we're now done with the old instruction entirely, and will ignore them through
// the rest of this loop. The only time we'll see them again is a second pass to
// delete them.
// now deal with local variable instructions. If this points to a remapped
// frame location, update the instruction's index. If this doesn't,
// do compaction/expansion: allocate a new local variable, and modify the remap
// to handle it. XXX We're doing the safe thing and allocating ALL these local variables
// as double-wides, in case the location is found to hold a double-wide later.
if (freshI.isLocalVariableInstruction() || freshI instanceof RET) {
// IndexedInstruction indexedI = (IndexedInstruction) freshI;
int oldIndex = freshI.getIndex();
int freshIndex;
if (!remap.hasKey(oldIndex)) {
freshIndex = freshMethod.allocateLocal(2);
remap.put(oldIndex, freshIndex);
} else {
freshIndex = remap.get(oldIndex);
}
if (freshI instanceof RET) {
freshI.setIndex(freshIndex);
} else {
freshI = ((InstructionLV) freshI).setIndexAndCopyIfNecessary(freshIndex);
freshIh.setInstruction(freshI);
}
}