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 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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.ajdt.internal.compiler.ast;
  13. import java.util.Arrays;
  14. import org.aspectj.weaver.*;
  15. import org.aspectj.weaver.ShadowMunger;
  16. import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
  17. import org.eclipse.jdt.internal.compiler.ast.*;
  18. import org.eclipse.jdt.internal.compiler.lookup.*;
  19. /**
  20. * Takes a method that already has the three extra parameters
  21. * thisJoinPointStaticPart, thisJoinPoint and thisEnclosingJoinPointStaticPart
  22. */
  23. public class ThisJoinPointVisitor extends AbstractSyntaxTreeVisitorAdapter {
  24. boolean needsDynamic = false;
  25. boolean needsStatic = false;
  26. boolean needsStaticEnclosing = false;
  27. boolean hasEffectivelyStaticRef = false;
  28. LocalVariableBinding thisJoinPointDec;
  29. LocalVariableBinding thisJoinPointStaticPartDec;
  30. LocalVariableBinding thisEnclosingJoinPointStaticPartDec;
  31. LocalVariableBinding thisJoinPointDecLocal;
  32. LocalVariableBinding thisJoinPointStaticPartDecLocal;
  33. LocalVariableBinding thisEnclosingJoinPointStaticPartDecLocal;
  34. boolean replaceEffectivelyStaticRefs = false;
  35. AbstractMethodDeclaration method;
  36. ThisJoinPointVisitor(AbstractMethodDeclaration method) {
  37. this.method = method;
  38. int index = method.arguments.length - 3;
  39. thisJoinPointStaticPartDecLocal = method.scope.locals[index];
  40. thisJoinPointStaticPartDec = method.arguments[index++].binding;
  41. thisJoinPointDecLocal = method.scope.locals[index];
  42. thisJoinPointDec = method.arguments[index++].binding;
  43. thisEnclosingJoinPointStaticPartDecLocal = method.scope.locals[index];
  44. thisEnclosingJoinPointStaticPartDec = method.arguments[index++].binding;
  45. }
  46. public void computeJoinPointParams() {
  47. // walk my body to see what is needed
  48. method.traverse(this, (ClassScope) null);
  49. //??? add support for option to disable this optimization
  50. //System.err.println("walked: " + method);
  51. //System.err.println("check: "+ hasEffectivelyStaticRef + ", " + needsDynamic);
  52. if (hasEffectivelyStaticRef && !needsDynamic) {
  53. // replace effectively static refs with thisJoinPointStaticPart
  54. replaceEffectivelyStaticRefs = true;
  55. needsStatic = true;
  56. method.traverse(this, (ClassScope) null);
  57. }
  58. //System.err.println("done: " + method);
  59. }
  60. boolean isRef(NameReference ref, Binding binding) {
  61. //System.err.println("check ref: " + ref + " is " + System.identityHashCode(ref));
  62. return ref.binding == binding;
  63. }
  64. boolean isRef(Expression expr, Binding binding) {
  65. return expr != null
  66. && expr instanceof NameReference
  67. && isRef((NameReference) expr, binding);
  68. }
  69. public void endVisit(SingleNameReference ref, BlockScope scope) {
  70. if (isRef(ref, thisJoinPointDec)) {
  71. needsDynamic = true;
  72. } else if (isRef(ref, thisJoinPointStaticPartDec)) {
  73. needsStatic = true;
  74. } else if (isRef(ref, thisEnclosingJoinPointStaticPartDec)) {
  75. needsStaticEnclosing = true;
  76. }
  77. }
  78. boolean canTreatAsStatic(String id) {
  79. return id.equals("toString")
  80. || id.equals("toShortString")
  81. || id.equals("toLongString")
  82. || id.equals("getKind")
  83. || id.equals("getSignature")
  84. || id.equals("getSourceLocation")
  85. || id.equals("getStaticPart");
  86. }
  87. // boolean canTreatAsStatic(VarExpr varExpr) {
  88. // ASTObject parent = varExpr.getParent();
  89. // if (parent instanceof CallExpr) {
  90. // Method calledMethod = ((CallExpr)parent).getMethod();
  91. // return canTreatAsStatic(calledMethod);
  92. //
  93. // //??? should add a case here to catch
  94. // //??? tjp.getEnclosingExecutionJoinPoint().STATIC_METHOD()
  95. // } else if (parent instanceof BinopExpr) {
  96. // BinopExpr binop = (BinopExpr)parent;
  97. // if (binop.getType().isEquivalent(this.getTypeManager().getStringType())) {
  98. // return true;
  99. // } else {
  100. // return false;
  101. // }
  102. // } else {
  103. // return false;
  104. // }
  105. // }
  106. boolean inBlockThatCantRun = false;
  107. public boolean visit(MessageSend call, BlockScope scope) {
  108. Expression receiver = call.receiver;
  109. if (isRef(receiver, thisJoinPointDec)) {
  110. if (canTreatAsStatic(new String(call.selector))) {
  111. if (replaceEffectivelyStaticRefs) {
  112. replaceEffectivelyStaticRef(call);
  113. } else {
  114. //System.err.println("has static reg");
  115. hasEffectivelyStaticRef = true;
  116. if (call.arguments != null) {
  117. int argumentsLength = call.arguments.length;
  118. for (int i = 0; i < argumentsLength; i++)
  119. call.arguments[i].traverse(this, scope);
  120. }
  121. return false;
  122. }
  123. }
  124. }
  125. return super.visit(call, scope);
  126. }
  127. private void replaceEffectivelyStaticRef(MessageSend call) {
  128. NameReference receiver = (NameReference) call.receiver;
  129. //System.err.println("replace static ref: " + receiver + " is " + System.identityHashCode(receiver));
  130. receiver.binding = thisJoinPointStaticPartDecLocal; //thisJoinPointStaticPartDec;
  131. receiver.codegenBinding = thisJoinPointStaticPartDecLocal;
  132. call.binding = call.codegenBinding = getEquivalentStaticBinding(call.binding);
  133. }
  134. private MethodBinding getEquivalentStaticBinding(MethodBinding template) {
  135. ReferenceBinding b = (ReferenceBinding)thisJoinPointStaticPartDec.type;
  136. return b.getExactMethod(template.selector, template.parameters);
  137. }
  138. public int removeUnusedExtraArguments() {
  139. int extraArgumentFlags = 0;
  140. this.computeJoinPointParams();
  141. MethodBinding binding = method.binding;
  142. int index = binding.parameters.length - 3;
  143. if (needsStaticEnclosing) {
  144. extraArgumentFlags |= Advice.ThisEnclosingJoinPointStaticPart;
  145. } else {
  146. removeParameter(index+2);
  147. }
  148. if (needsDynamic) {
  149. extraArgumentFlags |= Advice.ThisJoinPoint;
  150. } else {
  151. removeParameter(index+1);
  152. }
  153. if (needsStatic) {
  154. extraArgumentFlags |= Advice.ThisJoinPointStaticPart;
  155. } else {
  156. removeParameter(index+0);
  157. }
  158. return extraArgumentFlags;
  159. }
  160. private void removeParameter(int indexToRemove) {
  161. TypeBinding[] parameters = method.binding.parameters;
  162. method.scope.locals = removeLocalBinding(indexToRemove, method.scope.locals);
  163. method.binding.parameters = removeParameter(indexToRemove, method.binding.parameters);
  164. }
  165. private static TypeBinding[] removeParameter(int index, TypeBinding[] bindings) {
  166. int len = bindings.length;
  167. TypeBinding[] ret = new TypeBinding[len-1];
  168. System.arraycopy(bindings, 0, ret, 0, index);
  169. System.arraycopy(bindings, index+1, ret, index, len-index-1);
  170. return ret;
  171. }
  172. private static LocalVariableBinding[] removeLocalBinding(int index, LocalVariableBinding[] bindings) {
  173. int len = bindings.length;
  174. //??? for performance we should do this in-place
  175. LocalVariableBinding[] ret = new LocalVariableBinding[len-1];
  176. System.arraycopy(bindings, 0, ret, 0, index);
  177. System.arraycopy(bindings, index+1, ret, index, len-index-1);
  178. return ret;
  179. }
  180. }