You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Range.java 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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 Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.bcel;
  13. import java.util.Map;
  14. import org.aspectj.apache.bcel.generic.IMPDEP1;
  15. import org.aspectj.apache.bcel.generic.Instruction;
  16. import org.aspectj.apache.bcel.generic.InstructionHandle;
  17. import org.aspectj.apache.bcel.generic.InstructionList;
  18. import org.aspectj.apache.bcel.generic.InstructionTargeter;
  19. import org.aspectj.weaver.BCException;
  20. abstract class Range implements InstructionTargeter {
  21. protected InstructionList body;
  22. protected InstructionHandle start;
  23. protected InstructionHandle end;
  24. // ---- initialization
  25. protected Range(InstructionList il) {
  26. this.body = il;
  27. }
  28. // ----
  29. final InstructionList getBody() {
  30. return body;
  31. }
  32. final InstructionHandle getStart() {
  33. return start;
  34. }
  35. final InstructionHandle getEnd() {
  36. return end;
  37. }
  38. // ----
  39. boolean isEmpty() {
  40. InstructionHandle ih = start;
  41. //System.err.println(" looking for " + end);
  42. while (ih != end) {
  43. //System.err.println(" ih " + ih);
  44. if (! Range.isRangeHandle(ih)) return false;
  45. ih = ih.getNext();
  46. }
  47. return true;
  48. }
  49. static InstructionHandle getRealStart(InstructionHandle ih) {
  50. while (Range.isRangeHandle(ih)) {
  51. ih = ih.getNext();
  52. }
  53. return ih;
  54. }
  55. InstructionHandle getRealStart() {
  56. return getRealStart(start);
  57. }
  58. static InstructionHandle getRealEnd(InstructionHandle ih) {
  59. while (Range.isRangeHandle(ih)) {
  60. ih = ih.getPrev();
  61. }
  62. return ih;
  63. }
  64. InstructionHandle getRealEnd() {
  65. return getRealEnd(end);
  66. }
  67. InstructionHandle getRealNext() {
  68. return getRealStart(end);
  69. }
  70. static InstructionHandle getRealPrev(InstructionHandle ih) {
  71. InstructionHandle ret = ih.getPrev();
  72. while (isRangeHandle(ret)) {
  73. ret = ret.getPrev();
  74. }
  75. return ret;
  76. }
  77. // ----
  78. InstructionHandle insert(Instruction i, Where where) {
  79. InstructionList il = new InstructionList();
  80. InstructionHandle ret = il.insert(i);
  81. insert(il, where);
  82. return ret;
  83. }
  84. void insert(InstructionList freshIl, Where where) {
  85. InstructionHandle h;
  86. if (where == InsideBefore || where == OutsideBefore) {
  87. h = getStart();
  88. } else {
  89. h = getEnd();
  90. }
  91. if (where == InsideBefore || where == OutsideAfter) {
  92. body.append(h, freshIl);
  93. } else {
  94. InstructionHandle newStart = body.insert(h, freshIl);
  95. if (where == OutsideBefore) {
  96. // XXX this is slow. There's a better design than this. We should
  97. // never have to retarget branches apart from the creation of ranges.
  98. // basically, we should never weave OutsideBefore.
  99. BcelShadow.retargetAllBranches(h, newStart);
  100. }
  101. }
  102. }
  103. InstructionHandle append(Instruction i) {
  104. return insert(i, InsideAfter);
  105. }
  106. void append(InstructionList i) {
  107. insert(i, InsideAfter);
  108. }
  109. static InstructionHandle remap(InstructionHandle h, Map m) {
  110. return (InstructionHandle) m.get(h);
  111. }
  112. private static void setLineNumberFromNext(InstructionHandle ih) {
  113. int lineNumber = Utility.getSourceLine(ih.getNext());
  114. if (lineNumber != -1) {
  115. Utility.setSourceLine(ih, lineNumber);
  116. }
  117. }
  118. static InstructionHandle genStart(InstructionList body) {
  119. InstructionHandle ih = body.insert(Range.RANGEINSTRUCTION);
  120. setLineNumberFromNext(ih);
  121. return ih;
  122. }
  123. static InstructionHandle genEnd(InstructionList body) {
  124. return body.append(Range.RANGEINSTRUCTION);
  125. }
  126. static InstructionHandle genStart(InstructionList body, InstructionHandle ih) {
  127. if (ih == null) return genStart(body);
  128. InstructionHandle freshIh = body.insert(ih, Range.RANGEINSTRUCTION);
  129. setLineNumberFromNext(freshIh);
  130. return freshIh;
  131. }
  132. static InstructionHandle genEnd(InstructionList body, InstructionHandle ih) {
  133. if (ih == null) return genEnd(body);
  134. return body.append(ih, Range.RANGEINSTRUCTION);
  135. }
  136. // -----
  137. public boolean containsTarget(InstructionHandle ih) {
  138. return false;
  139. }
  140. public final void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
  141. throw new RuntimeException("Ranges must be updated with an enclosing instructionList");
  142. }
  143. protected void updateTarget(
  144. InstructionHandle old_ih,
  145. InstructionHandle new_ih,
  146. InstructionList new_il)
  147. {
  148. old_ih.removeTargeter(this);
  149. if (new_ih != null)
  150. new_ih.addTargeter(this);
  151. body = new_il;
  152. if (old_ih == start) {
  153. start = new_ih;
  154. }
  155. if (old_ih == end) {
  156. end = new_ih;
  157. }
  158. }
  159. public static final boolean isRangeHandle(InstructionHandle ih) {
  160. if (ih == null) return false;
  161. return ih.getInstruction() == Range.RANGEINSTRUCTION;
  162. }
  163. protected static final Range getRange(InstructionHandle ih) {
  164. // assert isRangeHandle(ih)
  165. Range ret = null;
  166. InstructionTargeter[] targeters = ih.getTargeters();
  167. for (int i = targeters.length - 1; i >= 0; i--) {
  168. if (targeters[i] instanceof Range) {
  169. Range r = (Range) targeters[i];
  170. if (r.getStart() != ih && r.getEnd() != ih) continue;
  171. if (ret != null) throw new BCException("multiple ranges on same range handle: " + ret + ", " + targeters[i]);
  172. ret = (Range) targeters[i];
  173. }
  174. }
  175. if (ret == null) throw new BCException("shouldn't happen");
  176. return ret;
  177. }
  178. // ----
  179. static final Where InsideBefore = new Where("insideBefore");
  180. static final Where InsideAfter = new Where("insideAfter");
  181. static final Where OutsideBefore = new Where("outsideBefore");
  182. static final Where OutsideAfter = new Where("outsideAfter");
  183. // ---- constants
  184. // note that this is STUPIDLY copied by Instruction.copy(), so don't do that.
  185. public static final Instruction RANGEINSTRUCTION = new IMPDEP1();
  186. // ----
  187. static class Where {
  188. private String name;
  189. public Where(String name) { this.name = name; }
  190. public String toString() { return name; }
  191. }
  192. }