* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver.bcel;
import java.util.Iterator;
final class ShadowRange extends Range {
- private BcelShadow shadow;
+ private BcelShadow shadow;
// ---- initialization
-
+
/**
- * After this constructor is called, this range is not well situated unless both
- * {@link #associateWithTargets} and {@link #associateWithShadow} are called.
+ * After this constructor is called, this range is not well situated unless both {@link #associateWithTargets} and
+ * {@link #associateWithShadow} are called.
*/
public ShadowRange(InstructionList body) {
super(body);
}
+
protected void associateWithTargets(InstructionHandle start, InstructionHandle end) {
// assert body.contains(start) && body.contains(end);
this.start = start;
this.end = end;
start.addTargeter(this);
end.addTargeter(this);
- }
+ }
+
public void associateWithShadow(BcelShadow shadow) {
this.shadow = shadow;
shadow.setRange(this);
}
-
+
// ----
- public Shadow.Kind getKind() {
- return shadow.getKind();
- }
-
- public String toString() {
- return shadow.toString();
- }
+ public Shadow.Kind getKind() {
+ return shadow.getKind();
+ }
- void extractInstructionsInto(LazyMethodGen freshMethod, IntMap remap, boolean addReturn) {
- LazyMethodGen.assertGoodBody(getBody(), toString());
- freshMethod.assertGoodBody();
- InstructionList freshBody = freshMethod.getBody();
+ public String toString() {
+ return shadow.toString();
+ }
- 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);
+ void extractInstructionsInto(LazyMethodGen freshMethod, IntMap remap, boolean addReturn) {
+ LazyMethodGen.assertGoodBody(getBody(), toString());
+ 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 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);
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
+ 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.
- InstructionTargeter[] sources = oldIh.getTargetersArray();
- if (sources != null) {
- for (int j = sources.length - 1; j >= 0; j--) {
- InstructionTargeter source = sources[j];
- 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) {
- // 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);
- }
- }
- }
+ InstructionTargeter[] sources = oldIh.getTargetersArray();
+ if (sources != null) {
+ for (int j = sources.length - 1; j >= 0; j--) {
+ InstructionTargeter source = sources[j];
+ 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
+ // 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,
+
+ // 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
+ // 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);
- }
- }
-// System.err.println("JUST COPIED: " + oldIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool())
-// + " INTO " + freshIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool()));
- }
-
- // now go through again and update variable slots that have been altered as a result
- // of remapping...
- for (InstructionHandle newIh = freshBody.getStart(); newIh != freshBody.getEnd(); newIh = newIh.getNext()) {
- Iterator tIter = newIh.getTargeters().iterator();
- while (tIter.hasNext()) {
- InstructionTargeter source = (InstructionTargeter)tIter.next();
- if (source instanceof LocalVariableTag) {
- LocalVariableTag lvt = (LocalVariableTag) source;
- if (!lvt.isRemapped() && remap.hasKey(lvt.getSlot())) {
- lvt.updateSlot(remap.get(lvt.getSlot()));
- }
- }
- }
- }
-
-
-
+ 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);
+ }
+ }
+ // System.err.println("JUST COPIED: " +
+ // oldIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool())
+ // + " INTO " +
+ // freshIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool()));
+ }
+
+ // now go through again and update variable slots that have been altered as a result
+ // of remapping...
+ for (InstructionHandle newIh = freshBody.getStart(); newIh != freshBody.getEnd(); newIh = newIh.getNext()) {
+ Iterator tIter = newIh.getTargeters().iterator();
+ while (tIter.hasNext()) {
+ InstructionTargeter source = (InstructionTargeter) tIter.next();
+ if (source instanceof LocalVariableTag) {
+ LocalVariableTag lvt = (LocalVariableTag) source;
+ if (!lvt.isRemapped() && remap.hasKey(lvt.getSlot())) {
+ lvt.updateSlot(remap.get(lvt.getSlot()));
+ }
+ }
+ }
+ }
// we've now copied out all the instructions.
- // now delete the instructions... we've already taken care of the damn
- // targets, but since TargetLostException is checked, we have to do this stuff.
- try {
- for (InstructionHandle oldIh = start.getNext(); oldIh != end; ) {
- InstructionHandle next = oldIh.getNext();
- body.delete(oldIh);
- oldIh = next;
- }
- } catch (TargetLostException e) {
- throw new BCException("shouldn't have gotten a target lost");
- }
-
- // now add the return, if one is warranted.
- InstructionHandle ret = null;
- if (addReturn) {
- // we really should pull this out somewhere...
- ret = freshBody.append(
- InstructionFactory.createReturn(freshMethod.getReturnType()));
- }
+ // now delete the instructions... we've already taken care of the damn
+ // targets, but since TargetLostException is checked, we have to do this stuff.
+ try {
+ for (InstructionHandle oldIh = start.getNext(); oldIh != end;) {
+ InstructionHandle next = oldIh.getNext();
+ body.delete(oldIh);
+ oldIh = next;
+ }
+ } catch (TargetLostException e) {
+ throw new BCException("shouldn't have gotten a target lost");
+ }
+
+ // now add the return, if one is warranted.
+ InstructionHandle ret = null;
+ if (addReturn) {
+ // we really should pull this out somewhere...
+ ret = freshBody.append(InstructionFactory.createReturn(freshMethod.getReturnType()));
+ }
// and remap all the old targeters of the end handle of the range to the return.
- InstructionTargeter[] ts = end.getTargetersArray();
- if (ts != null) { // shouldn't be the case, but let's test for paranoia
- for (int j = ts.length - 1; j >= 0; j--) {
- InstructionTargeter t = ts[j];
- if (t == this) continue;
- if (! addReturn) {
- throw new BCException("range has target, but we aren't adding a return");
- } else {
- t.updateTarget(end, ret);
- }
- }
- }
-
- LazyMethodGen.assertGoodBody(getBody(), toString());
- freshMethod.assertGoodBody();
- }
+ InstructionTargeter[] ts = end.getTargetersArray();
+ if (ts != null) { // shouldn't be the case, but let's test for paranoia
+ for (int j = ts.length - 1; j >= 0; j--) {
+ InstructionTargeter t = ts[j];
+ if (t == this)
+ continue;
+ if (!addReturn) {
+ throw new BCException("range has target, but we aren't adding a return");
+ } else {
+ t.updateTarget(end, ret);
+ }
+ }
+ }
+
+ LazyMethodGen.assertGoodBody(getBody(), toString());
+ freshMethod.assertGoodBody();
+ }
public BcelShadow getShadow() {
return shadow;
}
-
}