Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

ThisJoinPointVisitor.java 8.9KB

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