* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.ajdt.internal.compiler.ast;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.ResolvedMemberImpl;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.patterns.IfPointcut;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-//import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ResolvedMemberImpl;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.patterns.IfPointcut;
public class IfMethodDeclaration extends AjMethodDeclaration {
IfPointcut ifPointcut;
super(compilationResult);
this.ifPointcut = ifPointcut;
}
-
- public void parseStatements(
- Parser parser,
- CompilationUnitDeclaration unit) {
+
+ public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
// do nothing, we're already fully parsed
}
-
+
protected int generateInfoAttributes(ClassFile classFile) {
return classFile.generateMethodInfoAttribute(binding, false, AstUtil.getAjSyntheticAttribute());
}
-
+
+ // private static class TrueFalseVisitor extends astvi
public void resolveStatements() {
super.resolveStatements();
if (binding != null) {
ThisJoinPointVisitor tjp = new ThisJoinPointVisitor(this);
ifPointcut.extraParameterFlags |= tjp.removeUnusedExtraArguments();
-
- //XXX this is where we should remove unavailable args if we're in a cflow
+
+ // Check for FALSE or TRUE constant reference
+ if (statements != null && statements.length == 1 && statements[0] instanceof ReturnStatement) {
+ if (tjp.hasConstantReference) {
+ if (tjp.constantReferenceValue == true) {
+ ifPointcut.setAlways(true);
+ } else {
+ ifPointcut.setAlways(false);
+ }
+ return;
+ }
+ }
+
+ // XXX this is where we should remove unavailable args if we're in a cflow
EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(scope);
- ifPointcut.testMethod = new ResolvedMemberImpl(
- Member.METHOD,
- factory.fromBinding(binding.declaringClass),
- this.modifiers, ResolvedType.BOOLEAN,
- new String(this.selector),
- factory.fromBindings(this.binding.parameters));
- }
+ ifPointcut.testMethod = new ResolvedMemberImpl(Member.METHOD, factory.fromBinding(binding.declaringClass),
+ this.modifiers, ResolvedType.BOOLEAN, new String(this.selector), factory.fromBindings(this.binding.parameters));
+ }
}
}
* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.ajdt.internal.compiler.ast;
-import org.aspectj.weaver.Advice;
import org.aspectj.bridge.context.CompilationAndWeavingContext;
import org.aspectj.bridge.context.ContextToken;
import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
+import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.aspectj.weaver.Advice;
/**
- * Takes a method that already has the three extra parameters
- * thisJoinPointStaticPart, thisJoinPoint and thisEnclosingJoinPointStaticPart
+ * Takes a method that already has the three extra parameters thisJoinPointStaticPart, thisJoinPoint and
+ * thisEnclosingJoinPointStaticPart
*/
public class ThisJoinPointVisitor extends ASTVisitor {
boolean needsStatic = false;
boolean needsStaticEnclosing = false;
boolean hasEffectivelyStaticRef = false;
+ boolean hasConstantReference = false;
+ boolean constantReferenceValue = false; // only has valid value when hasConstantReference is true
LocalVariableBinding thisJoinPointDec;
LocalVariableBinding thisJoinPointStaticPartDec;
LocalVariableBinding thisEnclosingJoinPointStaticPartDec;
-
+
LocalVariableBinding thisJoinPointDecLocal;
LocalVariableBinding thisJoinPointStaticPartDecLocal;
LocalVariableBinding thisEnclosingJoinPointStaticPartDecLocal;
boolean replaceEffectivelyStaticRefs = false;
-
+
AbstractMethodDeclaration method;
ThisJoinPointVisitor(AbstractMethodDeclaration method) {
this.method = method;
int index = method.arguments.length - 3;
-
+
thisJoinPointStaticPartDecLocal = method.scope.locals[index];
thisJoinPointStaticPartDec = method.arguments[index++].binding;
thisJoinPointDecLocal = method.scope.locals[index];
// walk my body to see what is needed
method.traverse(this, (ClassScope) null);
- //??? add support for option to disable this optimization
- //System.err.println("walked: " + method);
- //System.err.println("check: "+ hasEffectivelyStaticRef + ", " + needsDynamic);
+ // ??? add support for option to disable this optimization
+ // System.err.println("walked: " + method);
+ // System.err.println("check: "+ hasEffectivelyStaticRef + ", " + needsDynamic);
if (hasEffectivelyStaticRef && !needsDynamic) {
// replace effectively static refs with thisJoinPointStaticPart
replaceEffectivelyStaticRefs = true;
needsStatic = true;
method.traverse(this, (ClassScope) null);
}
- //System.err.println("done: " + method);
+ // System.err.println("done: " + method);
}
boolean isRef(NameReference ref, Binding binding) {
- //System.err.println("check ref: " + ref + " is " + System.identityHashCode(ref));
+ // System.err.println("check ref: " + ref + " is " + System.identityHashCode(ref));
return ref.binding == binding;
}
boolean isRef(Expression expr, Binding binding) {
- return expr != null
- && expr instanceof NameReference
- && isRef((NameReference) expr, binding);
+ return expr != null && expr instanceof NameReference && isRef((NameReference) expr, binding);
}
public void endVisit(SingleNameReference ref, BlockScope scope) {
needsStatic = true;
} else if (isRef(ref, thisEnclosingJoinPointStaticPartDec)) {
needsStaticEnclosing = true;
+ } else if (ref.constant != null && ref.constant != Constant.NotAConstant) {
+ if (ref.constant instanceof BooleanConstant) {
+ hasConstantReference = true;
+ constantReferenceValue = ((BooleanConstant) ref.constant).booleanValue();
+ }
}
}
boolean canTreatAsStatic(String id) {
- return id.equals("toString")
- || id.equals("toShortString")
- || id.equals("toLongString")
- || id.equals("getKind")
- || id.equals("getSignature")
- || id.equals("getSourceLocation");
- //TODO: This is a good optimization, but requires more work than the above
- // we have to replace a call with a direct reference, not just a different call
- //|| id.equals("getStaticPart");
+ return id.equals("toString") || id.equals("toShortString") || id.equals("toLongString") || id.equals("getKind")
+ || id.equals("getSignature") || id.equals("getSourceLocation");
+ // TODO: This is a good optimization, but requires more work than the above
+ // we have to replace a call with a direct reference, not just a different call
+ // || id.equals("getStaticPart");
}
- // boolean canTreatAsStatic(VarExpr varExpr) {
- // ASTObject parent = varExpr.getParent();
- // if (parent instanceof CallExpr) {
- // Method calledMethod = ((CallExpr)parent).getMethod();
- // return canTreatAsStatic(calledMethod);
+ // boolean canTreatAsStatic(VarExpr varExpr) {
+ // ASTObject parent = varExpr.getParent();
+ // if (parent instanceof CallExpr) {
+ // Method calledMethod = ((CallExpr)parent).getMethod();
+ // return canTreatAsStatic(calledMethod);
//
- // //??? should add a case here to catch
- // //??? tjp.getEnclosingExecutionJoinPoint().STATIC_METHOD()
- // } else if (parent instanceof BinopExpr) {
- // BinopExpr binop = (BinopExpr)parent;
- // if (binop.getType().isEquivalent(this.getTypeManager().getStringType())) {
- // return true;
- // } else {
- // return false;
- // }
- // } else {
- // return false;
- // }
- // }
+ // //??? should add a case here to catch
+ // //??? tjp.getEnclosingExecutionJoinPoint().STATIC_METHOD()
+ // } else if (parent instanceof BinopExpr) {
+ // BinopExpr binop = (BinopExpr)parent;
+ // if (binop.getType().isEquivalent(this.getTypeManager().getStringType())) {
+ // return true;
+ // } else {
+ // return false;
+ // }
+ // } else {
+ // return false;
+ // }
+ // }
boolean inBlockThatCantRun = false;
public boolean visit(MessageSend call, BlockScope scope) {
- ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.OPTIMIZING_THIS_JOIN_POINT_CALLS, call.selector);
+ ContextToken tok = CompilationAndWeavingContext.enteringPhase(
+ CompilationAndWeavingContext.OPTIMIZING_THIS_JOIN_POINT_CALLS, call.selector);
Expression receiver = call.receiver;
if (isRef(receiver, thisJoinPointDec)) {
if (canTreatAsStatic(new String(call.selector))) {
if (replaceEffectivelyStaticRefs) {
replaceEffectivelyStaticRef(call);
} else {
- //System.err.println("has static reg");
+ // System.err.println("has static reg");
hasEffectivelyStaticRef = true;
if (call.arguments != null) {
int argumentsLength = call.arguments.length;
private void replaceEffectivelyStaticRef(MessageSend call) {
NameReference receiver = (NameReference) call.receiver;
-
+
// Don't continue if the call binding is null, as we are going to report an error about this line of code!
- if (call.binding==null) return;
-
- //System.err.println("replace static ref: " + receiver + " is " + System.identityHashCode(receiver));
- receiver.binding = thisJoinPointStaticPartDecLocal; //thisJoinPointStaticPartDec;
+ if (call.binding == null)
+ return;
+
+ // System.err.println("replace static ref: " + receiver + " is " + System.identityHashCode(receiver));
+ receiver.binding = thisJoinPointStaticPartDecLocal; // thisJoinPointStaticPartDec;
receiver.codegenBinding = thisJoinPointStaticPartDecLocal;
-
- ReferenceBinding thisJoinPointStaticPartType =
- (ReferenceBinding)thisJoinPointStaticPartDec.type;
-
- receiver.actualReceiverType =
- receiver.resolvedType = thisJoinPointStaticPartType;
-
+
+ ReferenceBinding thisJoinPointStaticPartType = (ReferenceBinding) thisJoinPointStaticPartDec.type;
+
+ receiver.actualReceiverType = receiver.resolvedType = thisJoinPointStaticPartType;
+
call.setActualReceiverType(thisJoinPointStaticPartType);
AstUtil.replaceMethodBinding(call, getEquivalentStaticBinding(call.binding));
}
-
+
private MethodBinding getEquivalentStaticBinding(MethodBinding template) {
- ReferenceBinding b = (ReferenceBinding)thisJoinPointStaticPartDec.type;
- return b.getExactMethod(template.selector, template.parameters,null);
+ ReferenceBinding b = (ReferenceBinding) thisJoinPointStaticPartDec.type;
+ return b.getExactMethod(template.selector, template.parameters, null);
}
public int removeUnusedExtraArguments() {
int extraArgumentFlags = 0;
-
+
this.computeJoinPointParams();
MethodBinding binding = method.binding;
-
-
+
int index = binding.parameters.length - 3;
if (needsStaticEnclosing) {
extraArgumentFlags |= Advice.ThisEnclosingJoinPointStaticPart;
} else {
- removeParameter(index+2);
+ removeParameter(index + 2);
}
-
+
if (needsDynamic) {
extraArgumentFlags |= Advice.ThisJoinPoint;
} else {
- removeParameter(index+1);
+ removeParameter(index + 1);
}
-
+
if (needsStatic) {
extraArgumentFlags |= Advice.ThisJoinPointStaticPart;
} else {
- removeParameter(index+0);
+ removeParameter(index + 0);
}
-
+
return extraArgumentFlags;
}
private void removeParameter(int indexToRemove) {
-// TypeBinding[] parameters = method.binding.parameters;
+ // TypeBinding[] parameters = method.binding.parameters;
method.scope.locals = removeLocalBinding(indexToRemove, method.scope.locals);
method.scope.localIndex -= 1;
method.binding.parameters = removeParameter(indexToRemove, method.binding.parameters);
}
-
private static TypeBinding[] removeParameter(int index, TypeBinding[] bindings) {
int len = bindings.length;
- TypeBinding[] ret = new TypeBinding[len-1];
+ TypeBinding[] ret = new TypeBinding[len - 1];
System.arraycopy(bindings, 0, ret, 0, index);
- System.arraycopy(bindings, index+1, ret, index, len-index-1);
+ System.arraycopy(bindings, index + 1, ret, index, len - index - 1);
return ret;
}
private static LocalVariableBinding[] removeLocalBinding(int index, LocalVariableBinding[] bindings) {
int len = bindings.length;
- //??? for performance we should do this in-place
- LocalVariableBinding[] ret = new LocalVariableBinding[len-1];
+ // ??? for performance we should do this in-place
+ LocalVariableBinding[] ret = new LocalVariableBinding[len - 1];
System.arraycopy(bindings, 0, ret, 0, index);
- System.arraycopy(bindings, index+1, ret, index, len-index-1);
+ System.arraycopy(bindings, index + 1, ret, index, len - index - 1);
return ret;
}
-
}