您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

ShadowRange.java 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.bcel;
  13. import java.util.Iterator;
  14. import org.aspectj.apache.bcel.generic.Instruction;
  15. import org.aspectj.apache.bcel.generic.InstructionBranch;
  16. import org.aspectj.apache.bcel.generic.InstructionFactory;
  17. import org.aspectj.apache.bcel.generic.InstructionHandle;
  18. import org.aspectj.apache.bcel.generic.InstructionLV;
  19. import org.aspectj.apache.bcel.generic.InstructionList;
  20. import org.aspectj.apache.bcel.generic.InstructionSelect;
  21. import org.aspectj.apache.bcel.generic.InstructionTargeter;
  22. import org.aspectj.apache.bcel.generic.LocalVariableTag;
  23. import org.aspectj.apache.bcel.generic.RET;
  24. import org.aspectj.apache.bcel.generic.TargetLostException;
  25. import org.aspectj.weaver.BCException;
  26. import org.aspectj.weaver.IntMap;
  27. import org.aspectj.weaver.Shadow;
  28. final class ShadowRange extends Range {
  29. private BcelShadow shadow;
  30. // ---- initialization
  31. /**
  32. * After this constructor is called, this range is not well situated unless both {@link #associateWithTargets} and
  33. * {@link #associateWithShadow} are called.
  34. */
  35. public ShadowRange(InstructionList body) {
  36. super(body);
  37. }
  38. protected void associateWithTargets(InstructionHandle start, InstructionHandle end) {
  39. // assert body.contains(start) && body.contains(end);
  40. this.start = start;
  41. this.end = end;
  42. start.addTargeter(this);
  43. end.addTargeter(this);
  44. }
  45. public void associateWithShadow(BcelShadow shadow) {
  46. this.shadow = shadow;
  47. shadow.setRange(this);
  48. }
  49. // ----
  50. public Shadow.Kind getKind() {
  51. return shadow.getKind();
  52. }
  53. @Override
  54. public String toString() {
  55. return shadow.toString();
  56. }
  57. void extractInstructionsInto(LazyMethodGen freshMethod, IntMap remap, boolean addReturn) {
  58. LazyMethodGen.assertGoodBody(getBody(), toString());
  59. freshMethod.assertGoodBody();
  60. InstructionList freshBody = freshMethod.getBody();
  61. for (InstructionHandle oldIh = start.getNext(); oldIh != end; oldIh = oldIh.getNext()) {
  62. // first we copy the instruction itself.
  63. Instruction oldI = oldIh.getInstruction();
  64. Instruction freshI = (oldI == RANGEINSTRUCTION) ? oldI : Utility.copyInstruction(oldI);
  65. // Now we add it to the new instruction list.
  66. InstructionHandle freshIh;
  67. if (freshI instanceof InstructionBranch) {
  68. // If it's a targeting instruction,
  69. // update the target(s) to point to the new copy instead of the old copy.
  70. InstructionBranch oldBranch = (InstructionBranch) oldI;
  71. InstructionBranch freshBranch = (InstructionBranch) freshI;
  72. InstructionHandle oldTarget = oldBranch.getTarget();
  73. oldTarget.removeTargeter(oldBranch);
  74. oldTarget.addTargeter(freshBranch);
  75. if (freshBranch instanceof InstructionSelect) {
  76. InstructionSelect oldSelect = (InstructionSelect) oldI;
  77. InstructionSelect freshSelect = (InstructionSelect) freshI;
  78. InstructionHandle[] oldTargets = freshSelect.getTargets();
  79. for (int k = oldTargets.length - 1; k >= 0; k--) {
  80. oldTargets[k].removeTargeter(oldSelect);
  81. oldTargets[k].addTargeter(freshSelect);
  82. }
  83. }
  84. freshIh = freshBody.append(freshBranch);
  85. } else {
  86. freshIh = freshBody.append(freshI);
  87. }
  88. // if source comes before target:
  89. // source <--> target
  90. // --> [process: target.removeTargeter(source); target.addTargeter(sourcecopy)]
  91. // source ---------\
  92. // v
  93. // sourcecopy <--> target
  94. // --> [ process: sourcecopy.updateTarget(target, targetcopy) ]
  95. // source ----> target
  96. // sourcecopy <--> targetcopy
  97. // if target comes before source
  98. // target <--> source
  99. // --> [process: source.updateTarget(target, targetcopy) ]
  100. // target
  101. // targetcopy <--> source
  102. // --> [process: targetcopy.removeTargeter(source); targetcopy.addTargeter(sourcecopy)]
  103. // target source
  104. // v
  105. // targetcopy <--> sourcecopy
  106. // now deal with the old instruction's targeters. Update them all to point to us
  107. // instead of the old instruction. We use updateTarget to do this. One goal is
  108. // to make sure we remove all targeters from the old guy, so we can successfully
  109. // delete it.
  110. for (InstructionTargeter source : oldIh.getTargetersCopy()) {
  111. if (source instanceof LocalVariableTag) {
  112. Shadow.Kind kind = getKind();
  113. if (kind == Shadow.AdviceExecution || kind == Shadow.ConstructorExecution || kind == Shadow.MethodExecution
  114. || kind == Shadow.PreInitialization || kind == Shadow.Initialization
  115. || kind == Shadow.StaticInitialization) {
  116. LocalVariableTag sourceLocalVariableTag = (LocalVariableTag) source;
  117. if (sourceLocalVariableTag.getSlot() == 0) {
  118. // might be 'this' so should be renamed if being dumped in a static method 277616
  119. if (sourceLocalVariableTag.getName().equals("this")) {
  120. sourceLocalVariableTag.setName("ajc$this");
  121. }
  122. }
  123. // if we're extracting a whole block we can do this...
  124. source.updateTarget(oldIh, freshIh);
  125. } else {
  126. // XXX destroying local variable info
  127. // but only for a call or get join point, so no big deal
  128. source.updateTarget(oldIh, null);
  129. }
  130. } else if (source instanceof Range) {
  131. // exceptions and shadows are just moved
  132. ((Range) source).updateTarget(oldIh, freshIh, freshBody);
  133. } else {
  134. // line numbers can be shared,
  135. // branches will be copied along with us.
  136. source.updateTarget(oldIh, freshIh);
  137. }
  138. }
  139. // we're now done with the old instruction entirely, and will ignore them through
  140. // the rest of this loop. The only time we'll see them again is a second pass to
  141. // delete them.
  142. // now deal with local variable instructions. If this points to a remapped
  143. // frame location, update the instruction's index. If this doesn't,
  144. // do compaction/expansion: allocate a new local variable, and modify the remap
  145. // to handle it. XXX We're doing the safe thing and allocating ALL these local variables
  146. // as double-wides, in case the location is found to hold a double-wide later.
  147. if (freshI.isLocalVariableInstruction() || freshI instanceof RET) {
  148. // IndexedInstruction indexedI = (IndexedInstruction) freshI;
  149. int oldIndex = freshI.getIndex();
  150. int freshIndex;
  151. if (!remap.hasKey(oldIndex)) {
  152. freshIndex = freshMethod.allocateLocal(2);
  153. remap.put(oldIndex, freshIndex);
  154. } else {
  155. freshIndex = remap.get(oldIndex);
  156. }
  157. if (freshI instanceof RET) {
  158. freshI.setIndex(freshIndex);
  159. } else {
  160. freshI = ((InstructionLV) freshI).setIndexAndCopyIfNecessary(freshIndex);
  161. freshIh.setInstruction(freshI);
  162. }
  163. }
  164. // System.err.println("JUST COPIED: " +
  165. // oldIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool())
  166. // + " INTO " +
  167. // freshIh.getInstruction().toString(freshMethod.getEnclosingClass().getConstantPoolGen().getConstantPool()));
  168. }
  169. // now go through again and update variable slots that have been altered as a result
  170. // of remapping...
  171. for (InstructionHandle newIh = freshBody.getStart(); newIh != freshBody.getEnd(); newIh = newIh.getNext()) {
  172. for (InstructionTargeter source : newIh.getTargeters()) {
  173. if (source instanceof LocalVariableTag) {
  174. LocalVariableTag lvt = (LocalVariableTag) source;
  175. if (!lvt.isRemapped() && remap.hasKey(lvt.getSlot())) {
  176. lvt.updateSlot(remap.get(lvt.getSlot()));
  177. }
  178. }
  179. }
  180. }
  181. // we've now copied out all the instructions.
  182. // now delete the instructions... we've already taken care of the damn
  183. // targets, but since TargetLostException is checked, we have to do this stuff.
  184. try {
  185. for (InstructionHandle oldIh = start.getNext(); oldIh != end;) {
  186. InstructionHandle next = oldIh.getNext();
  187. body.delete(oldIh);
  188. oldIh = next;
  189. }
  190. } catch (TargetLostException e) {
  191. throw new BCException("shouldn't have gotten a target lost");
  192. }
  193. // now add the return, if one is warranted.
  194. InstructionHandle ret = null;
  195. if (addReturn) {
  196. // we really should pull this out somewhere...
  197. ret = freshBody.append(InstructionFactory.createReturn(freshMethod.getReturnType()));
  198. }
  199. // and remap all the old targeters of the end handle of the range to the return.
  200. for (InstructionTargeter t : end.getTargetersCopy()) {
  201. if (t == this) {
  202. continue;
  203. }
  204. if (!addReturn) {
  205. throw new BCException("range has target, but we aren't adding a return");
  206. } else {
  207. t.updateTarget(end, ret);
  208. }
  209. }
  210. LazyMethodGen.assertGoodBody(getBody(), toString());
  211. freshMethod.assertGoodBody();
  212. }
  213. public BcelShadow getShadow() {
  214. return shadow;
  215. }
  216. }