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.

ProceedVisitor.java 8.0KB

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