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.

ThisJoinPointVisitor.java 9.9KB

21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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.ajdt.internal.compiler.ast;
  13. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  14. import org.aspectj.bridge.context.ContextToken;
  15. import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
  16. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
  17. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
  18. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
  19. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NameReference;
  20. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
  21. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
  22. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
  23. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
  24. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
  25. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  26. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
  27. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
  28. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  30. import org.aspectj.weaver.Advice;
  31. /**
  32. * Takes a method that already has the three extra parameters thisJoinPointStaticPart, thisJoinPoint and
  33. * thisEnclosingJoinPointStaticPart
  34. */
  35. public class ThisJoinPointVisitor extends ASTVisitor {
  36. boolean needsDynamic = false;
  37. boolean needsStatic = false;
  38. boolean needsStaticEnclosing = false;
  39. boolean needsThisAspectInstance = false;
  40. boolean hasEffectivelyStaticRef = false;
  41. boolean hasConstantReference = false;
  42. boolean constantReferenceValue = false; // only has valid value when hasConstantReference is true
  43. LocalVariableBinding thisJoinPointDec;
  44. LocalVariableBinding thisJoinPointStaticPartDec;
  45. LocalVariableBinding thisEnclosingJoinPointStaticPartDec;
  46. LocalVariableBinding thisAspectInstanceDec;
  47. LocalVariableBinding thisJoinPointDecLocal;
  48. LocalVariableBinding thisJoinPointStaticPartDecLocal;
  49. LocalVariableBinding thisEnclosingJoinPointStaticPartDecLocal;
  50. LocalVariableBinding thisAspectInstanceDecLocal;
  51. boolean replaceEffectivelyStaticRefs = false;
  52. boolean isIf = true;
  53. AbstractMethodDeclaration method;
  54. ThisJoinPointVisitor(AbstractMethodDeclaration method) {
  55. this.method = method;
  56. if (method instanceof AdviceDeclaration) {
  57. isIf = false;
  58. }
  59. int index = method.arguments.length - 3 - (isIf ? 1 : 0);
  60. thisJoinPointStaticPartDecLocal = method.scope.locals[index];
  61. thisJoinPointStaticPartDec = method.arguments[index++].binding;
  62. thisJoinPointDecLocal = method.scope.locals[index];
  63. thisJoinPointDec = method.arguments[index++].binding;
  64. thisEnclosingJoinPointStaticPartDecLocal = method.scope.locals[index];
  65. thisEnclosingJoinPointStaticPartDec = method.arguments[index++].binding;
  66. if (isIf) {
  67. thisAspectInstanceDecLocal = method.scope.locals[index];
  68. thisAspectInstanceDec = method.arguments[index++].binding;
  69. }
  70. }
  71. public void computeJoinPointParams() {
  72. // walk my body to see what is needed
  73. method.traverse(this, (ClassScope) null);
  74. // ??? add support for option to disable this optimization
  75. // System.err.println("walked: " + method);
  76. // System.err.println("check: "+ hasEffectivelyStaticRef + ", " + needsDynamic);
  77. if (hasEffectivelyStaticRef && !needsDynamic) {
  78. // replace effectively static refs with thisJoinPointStaticPart
  79. replaceEffectivelyStaticRefs = true;
  80. needsStatic = true;
  81. method.traverse(this, (ClassScope) null);
  82. }
  83. // System.err.println("done: " + method);
  84. }
  85. boolean isRef(NameReference ref, Binding binding) {
  86. // System.err.println("check ref: " + ref + " is " + System.identityHashCode(ref));
  87. return ref.binding == binding;
  88. }
  89. boolean isRef(Expression expr, Binding binding) {
  90. return expr != null && expr instanceof NameReference && isRef((NameReference) expr, binding);
  91. }
  92. public void endVisit(SingleNameReference ref, BlockScope scope) {
  93. if (isRef(ref, thisJoinPointDec)) {
  94. needsDynamic = true;
  95. } else if (isRef(ref, thisJoinPointStaticPartDec)) {
  96. needsStatic = true;
  97. } else if (isRef(ref, thisEnclosingJoinPointStaticPartDec)) {
  98. needsStaticEnclosing = true;
  99. } else if (isIf && isRef(ref, thisAspectInstanceDec)) {
  100. needsThisAspectInstance = true;
  101. } else if (ref.constant != null && ref.constant != Constant.NotAConstant) {
  102. if (ref.constant instanceof BooleanConstant) {
  103. hasConstantReference = true;
  104. constantReferenceValue = ((BooleanConstant) ref.constant).booleanValue();
  105. }
  106. }
  107. }
  108. boolean canTreatAsStatic(String id) {
  109. return id.equals("toString") || id.equals("toShortString") || id.equals("toLongString") || id.equals("getKind")
  110. || id.equals("getSignature") || id.equals("getSourceLocation");
  111. // TODO: This is a good optimization, but requires more work than the above
  112. // we have to replace a call with a direct reference, not just a different call
  113. // || id.equals("getStaticPart");
  114. }
  115. // boolean canTreatAsStatic(VarExpr varExpr) {
  116. // ASTObject parent = varExpr.getParent();
  117. // if (parent instanceof CallExpr) {
  118. // Method calledMethod = ((CallExpr)parent).getMethod();
  119. // return canTreatAsStatic(calledMethod);
  120. //
  121. // //??? should add a case here to catch
  122. // //??? tjp.getEnclosingExecutionJoinPoint().STATIC_METHOD()
  123. // } else if (parent instanceof BinopExpr) {
  124. // BinopExpr binop = (BinopExpr)parent;
  125. // if (binop.getType().isEquivalent(this.getTypeManager().getStringType())) {
  126. // return true;
  127. // } else {
  128. // return false;
  129. // }
  130. // } else {
  131. // return false;
  132. // }
  133. // }
  134. boolean inBlockThatCantRun = false;
  135. public boolean visit(MessageSend call, BlockScope scope) {
  136. ContextToken tok = CompilationAndWeavingContext.enteringPhase(
  137. CompilationAndWeavingContext.OPTIMIZING_THIS_JOIN_POINT_CALLS, call.selector);
  138. Expression receiver = call.receiver;
  139. if (isRef(receiver, thisJoinPointDec)) {
  140. if (canTreatAsStatic(new String(call.selector))) {
  141. if (replaceEffectivelyStaticRefs) {
  142. replaceEffectivelyStaticRef(call);
  143. } else {
  144. // System.err.println("has static reg");
  145. hasEffectivelyStaticRef = true;
  146. if (call.arguments != null) {
  147. int argumentsLength = call.arguments.length;
  148. for (int i = 0; i < argumentsLength; i++)
  149. call.arguments[i].traverse(this, scope);
  150. }
  151. CompilationAndWeavingContext.leavingPhase(tok);
  152. return false;
  153. }
  154. }
  155. }
  156. boolean ret = super.visit(call, scope);
  157. CompilationAndWeavingContext.leavingPhase(tok);
  158. return ret;
  159. }
  160. private void replaceEffectivelyStaticRef(MessageSend call) {
  161. NameReference receiver = (NameReference) call.receiver;
  162. // Don't continue if the call binding is null, as we are going to report an error about this line of code!
  163. if (call.binding == null)
  164. return;
  165. // System.err.println("replace static ref: " + receiver + " is " + System.identityHashCode(receiver));
  166. receiver.binding = thisJoinPointStaticPartDecLocal; // thisJoinPointStaticPartDec;
  167. // receiver.codegenBinding = thisJoinPointStaticPartDecLocal;
  168. ReferenceBinding thisJoinPointStaticPartType = (ReferenceBinding) thisJoinPointStaticPartDec.type;
  169. receiver.actualReceiverType = receiver.resolvedType = thisJoinPointStaticPartType;
  170. call.setActualReceiverType(thisJoinPointStaticPartType);
  171. AstUtil.replaceMethodBinding(call, getEquivalentStaticBinding(call.binding));
  172. }
  173. private MethodBinding getEquivalentStaticBinding(MethodBinding template) {
  174. ReferenceBinding b = (ReferenceBinding) thisJoinPointStaticPartDec.type;
  175. return b.getExactMethod(template.selector, template.parameters, null);
  176. }
  177. public int removeUnusedExtraArguments() {
  178. int extraArgumentFlags = 0;
  179. this.computeJoinPointParams();
  180. MethodBinding binding = method.binding;
  181. int index = binding.parameters.length - 3 - (isIf ? 1 : 0);
  182. if (isIf) {
  183. if (needsThisAspectInstance) {
  184. extraArgumentFlags |= Advice.ThisAspectInstance;
  185. } else {
  186. removeParameter(index + 3);
  187. }
  188. }
  189. if (needsStaticEnclosing) {
  190. extraArgumentFlags |= Advice.ThisEnclosingJoinPointStaticPart;
  191. } else {
  192. removeParameter(index + 2);
  193. }
  194. if (needsDynamic) {
  195. extraArgumentFlags |= Advice.ThisJoinPoint;
  196. } else {
  197. removeParameter(index + 1);
  198. }
  199. if (needsStatic) {
  200. extraArgumentFlags |= Advice.ThisJoinPointStaticPart;
  201. } else {
  202. removeParameter(index + 0);
  203. }
  204. return extraArgumentFlags;
  205. }
  206. public boolean usedThisAspectInstance() {
  207. return needsThisAspectInstance;
  208. }
  209. private void removeParameter(int indexToRemove) {
  210. // TypeBinding[] parameters = method.binding.parameters;
  211. method.scope.locals = removeLocalBinding(indexToRemove, method.scope.locals);
  212. method.scope.localIndex -= 1;
  213. method.binding.parameters = removeParameter(indexToRemove, method.binding.parameters);
  214. }
  215. private static TypeBinding[] removeParameter(int index, TypeBinding[] bindings) {
  216. int len = bindings.length;
  217. TypeBinding[] ret = new TypeBinding[len - 1];
  218. System.arraycopy(bindings, 0, ret, 0, index);
  219. System.arraycopy(bindings, index + 1, ret, index, len - index - 1);
  220. return ret;
  221. }
  222. private static LocalVariableBinding[] removeLocalBinding(int index, LocalVariableBinding[] bindings) {
  223. int len = bindings.length;
  224. // ??? for performance we should do this in-place
  225. LocalVariableBinding[] ret = new LocalVariableBinding[len - 1];
  226. System.arraycopy(bindings, 0, ret, 0, index);
  227. System.arraycopy(bindings, index + 1, ret, index, len - index - 1);
  228. return ret;
  229. }
  230. }