buildConfig.setNoWeave(true);
} else if (arg.equals("-XserializableAspects")) {
buildConfig.setXserializableAspects(true);
+ } else if (arg.equals("-XnoInline")) {
+ buildConfig.setXnoInline(true);
} else if (arg.equals("-Xlintfile")) {
if (args.size() > nextArgIndex) {
File lintSpecFile = makeFile(((ConfigParser.Arg)args.get(nextArgIndex)).getValue());
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.ajdt.internal.compiler.ast;
+
+import java.util.Arrays;
+
+import org.aspectj.ajdt.internal.compiler.lookup.*;
+import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedHandler;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ShadowMunger;
+import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Takes a method that already has the three extra parameters
+ * thisJoinPointStaticPart, thisJoinPoint and thisEnclosingJoinPointStaticPart
+ */
+
+public class AccessForInlineVisitor extends AbstractSyntaxTreeVisitorAdapter {
+ PrivilegedHandler handler;
+ EclipseWorld world;
+ public AccessForInlineVisitor(EclipseWorld world, PrivilegedHandler handler) {
+ this.world = world;
+ this.handler = handler;
+ }
+
+ public void endVisit(SingleNameReference ref, BlockScope scope) {
+ if (ref.binding instanceof FieldBinding) {
+ FieldBinding fieldBinding = (FieldBinding)ref.binding;
+ makePublic(fieldBinding.declaringClass);
+ if (isPublic(fieldBinding)) return;
+ ref.binding = handler.getPrivilegedAccessField(fieldBinding);
+ }
+ }
+
+ public void endVisit(QualifiedNameReference ref, BlockScope scope) {
+ if (ref.binding instanceof FieldBinding) {
+ FieldBinding fieldBinding = (FieldBinding)ref.binding;
+ makePublic(fieldBinding.declaringClass);
+ if (isPublic(fieldBinding)) return;
+ ref.binding = handler.getPrivilegedAccessField(fieldBinding);
+ }
+ }
+
+ public void endVisit(FieldReference ref, BlockScope scope) {
+ if (ref.binding instanceof FieldBinding) {
+ FieldBinding fieldBinding = (FieldBinding)ref.binding;
+ makePublic(fieldBinding.declaringClass);
+ if (isPublic(fieldBinding)) return;
+ ref.binding = handler.getPrivilegedAccessField(fieldBinding);
+ }
+ }
+ public void endVisit(MessageSend send, BlockScope scope) {
+ if (send instanceof Proceed) return;
+ if (send.binding == null) return;
+ if (isPublic(send.binding)) return;
+ makePublic(send.binding.declaringClass);
+ send.binding = send.codegenBinding = handler.getPrivilegedAccessMethod(send.binding);
+ }
+ public void endVisit(AllocationExpression send, BlockScope scope) {
+ if (send.binding == null) return;
+ if (isPublic(send.binding)) return;
+ makePublic(send.binding.declaringClass);
+ send.binding = handler.getPrivilegedAccessMethod(send.binding);
+ }
+ public void endVisit(
+ QualifiedTypeReference ref,
+ BlockScope scope)
+ {
+ makePublic(ref.binding);
+ }
+
+ public void endVisit(
+ SingleTypeReference ref,
+ BlockScope scope)
+ {
+ makePublic(ref.binding);
+ }
+
+ private boolean isPublic(FieldBinding fieldBinding) {
+ // these are always effectively public to the inliner
+ if (fieldBinding instanceof InterTypeFieldBinding) return true;
+ return fieldBinding.isPublic();
+ }
+
+ private boolean isPublic(MethodBinding methodBinding) {
+ // these are always effectively public to the inliner
+ if (methodBinding instanceof InterTypeMethodBinding) return true;
+ return methodBinding.isPublic();
+ }
+
+ private void makePublic(TypeBinding binding) {
+ if (binding instanceof ReferenceBinding) {
+ ReferenceBinding rb = (ReferenceBinding)binding;
+ if (!rb.isPublic()) handler.notePrivilegedTypeAccess(rb);
+ } else if (binding instanceof ArrayBinding) {
+ makePublic( ((ArrayBinding)binding).leafComponentType );
+ } else {
+ return;
+ }
+ }
+}
public MethodBinding proceedMethodBinding;
+
+ public List proceedCalls = new ArrayList(2);
public boolean proceedInInners;
public ResolvedMember[] proceedCallSignatures;
public boolean[] formalsUnchangedToProceed;
pointcutDesignator.finishResolveTypes(this, this.binding,
baseArgumentCount, upperScope.referenceContext.binding);
+ if (binding == null || ignoreFurtherInvestigation) return;
- if (kind == AdviceKind.Around && binding != null) {
- //XXX set these correctly
- proceedInInners = false;
- proceedCallSignatures = new ResolvedMember[0];
- formalsUnchangedToProceed = new boolean[baseArgumentCount];
- declaredExceptions = new TypeX[0];
-
-
+ if (kind == AdviceKind.Around) {
ReferenceBinding[] exceptions =
new ReferenceBinding[] { upperScope.getJavaLangThrowable() };
proceedMethodBinding = new MethodBinding(Modifier.STATIC,
super.resolveStatements(upperScope);
if (binding != null) determineExtraArgumentFlags();
+
+ if (kind == AdviceKind.Around) {
+ int n = proceedCalls.size();
+ EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(upperScope);
+
+ //System.err.println("access to: " + Arrays.asList(handler.getMembers()));
+
+ //XXX set these correctly
+ formalsUnchangedToProceed = new boolean[baseArgumentCount];
+ proceedCallSignatures = new ResolvedMember[0];
+ proceedInInners = false;
+ declaredExceptions = new TypeX[0];
+
+ for (int i=0; i < n; i++) {
+ Proceed call = (Proceed)proceedCalls.get(i);
+ if (call.inInner) {
+ //System.err.println("proceed in inner: " + call);
+ proceedInInners = true;
+ //XXX wrong
+ //proceedCallSignatures[i] = world.makeResolvedMember(call.binding);
+ }
+ }
+
+ // if we have proceed in inners we won't ever be inlined so the code below is unneeded
+ if (!proceedInInners) {
+ PrivilegedHandler handler = (PrivilegedHandler)upperScope.referenceContext.binding.privilegedHandler;
+ //XXX timings is odd here
+ if (handler == null) {
+ handler = new PrivilegedHandler((AspectDeclaration)upperScope.referenceContext);
+ upperScope.referenceContext.binding.privilegedHandler = handler;
+ }
+
+ this.traverse(new MakeDeclsPublicVisitor(), (ClassScope)null);
+
+ AccessForInlineVisitor v = new AccessForInlineVisitor(world, handler);
+ this.traverse(v, (ClassScope) null);
+ }
+ }
}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.ajdt.internal.compiler.ast;
+
+import java.util.Arrays;
+
+import org.aspectj.ajdt.internal.compiler.lookup.*;
+import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedHandler;
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ShadowMunger;
+import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Takes a method that already has the three extra parameters
+ * thisJoinPointStaticPart, thisJoinPoint and thisEnclosingJoinPointStaticPart
+ */
+
+public class MakeDeclsPublicVisitor extends AbstractSyntaxTreeVisitorAdapter {
+
+ public void endVisit(
+ AnonymousLocalTypeDeclaration decl,
+ BlockScope scope) {
+ decl.binding.modifiers = AstUtil.makePublic(decl.binding.modifiers);
+ }
+
+ public void endVisit(LocalTypeDeclaration decl, BlockScope scope) {
+ decl.binding.modifiers = AstUtil.makePublic(decl.binding.modifiers);
+ }
+
+
+ public void endVisit(ConstructorDeclaration decl, ClassScope scope) {
+ decl.binding.modifiers = AstUtil.makePublic(decl.binding.modifiers);
+ }
+
+ public void endVisit(FieldDeclaration decl, MethodScope scope) {
+ decl.binding.modifiers = AstUtil.makePublic(decl.binding.modifiers);
+ }
+
+
+ public void endVisit(MethodDeclaration decl, ClassScope scope) {
+ decl.binding.modifiers = AstUtil.makePublic(decl.binding.modifiers);
+ }
+
+}
public class Proceed extends MessageSend {
+ public boolean inInner = false;
+
public Proceed(MessageSend parent) {
super();
if (context instanceof AdviceDeclaration) {
AdviceDeclaration adviceDecl = (AdviceDeclaration)context;
if (adviceDecl.kind == AdviceKind.Around) {
+ adviceDecl.proceedCalls.add(this);
return adviceDecl;
} else {
return null;
}
}
+ } else if (scope instanceof ClassScope) {
+ inInner = true;
}
return findEnclosingAround(scope.parent);
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Xerox/PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.ajdt.internal.compiler.ast;
+
+import java.util.Arrays;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.ShadowMunger;
+import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Takes a method that already has the three extra parameters
+ * thisJoinPointStaticPart, thisJoinPoint and thisEnclosingJoinPointStaticPart
+ */
+
+public class ProceedVisitor extends AbstractSyntaxTreeVisitorAdapter {
+ boolean needsDynamic = false;
+ boolean needsStatic = false;
+ boolean needsStaticEnclosing = false;
+ boolean hasEffectivelyStaticRef = false;
+
+ LocalVariableBinding thisJoinPointDec;
+ LocalVariableBinding thisJoinPointStaticPartDec;
+ LocalVariableBinding thisEnclosingJoinPointStaticPartDec;
+
+ LocalVariableBinding thisJoinPointDecLocal;
+ LocalVariableBinding thisJoinPointStaticPartDecLocal;
+ LocalVariableBinding thisEnclosingJoinPointStaticPartDecLocal;
+
+ boolean replaceEffectivelyStaticRefs = false;
+
+ AbstractMethodDeclaration method;
+
+ ProceedVisitor(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];
+ thisJoinPointDec = method.arguments[index++].binding;
+ thisEnclosingJoinPointStaticPartDecLocal = method.scope.locals[index];
+ thisEnclosingJoinPointStaticPartDec = method.arguments[index++].binding;
+ }
+
+ public void computeJoinPointParams() {
+ // walk my body to see what is needed
+ method.traverse(this, (ClassScope) null);
+
+ //??? add support for option to disable this optimization
+ //System.err.println("check: "+ hasEffectivelyStaticRef + ", " + needsDynamic);
+ if (hasEffectivelyStaticRef && !needsDynamic) {
+ // replace effectively static refs with thisJoinPointStaticPart
+ replaceEffectivelyStaticRefs = true;
+ needsStatic = true;
+ method.traverse(this, (ClassScope) null);
+ }
+ }
+
+ boolean isRef(NameReference ref, Binding binding) {
+ return ref.binding == binding;
+ }
+
+ boolean isRef(Expression expr, Binding binding) {
+ //System.err.println("isRef: " + expr + ", " + binding);
+ return expr != null
+ && expr instanceof NameReference
+ && isRef((NameReference) expr, binding);
+ }
+
+ public void endVisit(SingleNameReference ref, BlockScope scope) {
+ if (isRef(ref, thisJoinPointDec))
+ needsDynamic = true;
+ else if (isRef(ref, thisJoinPointStaticPartDec))
+ needsStatic = true;
+ else if (isRef(ref, thisEnclosingJoinPointStaticPartDec))
+ needsStaticEnclosing = true;
+ }
+
+ // public void checkAndFix(ASTObject body) {
+ // this.process(body);
+ // if (needsFakeStatic && !needsDynamic) {
+ // if (!this.getCompiler().getOptions().noMetaJoinPointOptimization) {
+ // makeFakeStatics = true;
+ // needsStatic = true;
+ // this.process(body);
+ // } else {
+ // needsDynamic = true;
+ // }
+ // }
+ // }
+
+ boolean canTreatAsStatic(String id) {
+ return id.equals("toString")
+ || id.equals("toShortString")
+ || id.equals("toLongString")
+ || id.equals("getKind")
+ || id.equals("getSignature")
+ || id.equals("getSourceLocation")
+ || id.equals("getStaticPart");
+ }
+
+ // 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;
+ // }
+ // }
+
+ boolean inBlockThatCantRun = false;
+
+ public boolean visit(MessageSend call, BlockScope scope) {
+ 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");
+ hasEffectivelyStaticRef = true;
+ if (call.arguments != null) {
+ int argumentsLength = call.arguments.length;
+ for (int i = 0; i < argumentsLength; i++)
+ call.arguments[i].traverse(this, scope);
+ }
+ return false;
+ }
+ }
+ }
+
+ return super.visit(call, scope);
+ }
+
+ private void replaceEffectivelyStaticRef(MessageSend call) {
+ //System.err.println("replace static ref");
+ NameReference receiver = (NameReference) call.receiver;
+ receiver.binding = thisJoinPointStaticPartDecLocal; //thisJoinPointStaticPartDec;
+ receiver.codegenBinding = thisJoinPointStaticPartDecLocal;
+
+ call.binding.declaringClass =
+ (ReferenceBinding) thisJoinPointStaticPartDec.type;
+ }
+
+ 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);
+ }
+
+ if (needsDynamic) {
+ extraArgumentFlags |= Advice.ThisJoinPoint;
+ } else {
+ removeParameter(index+1);
+ }
+
+ if (needsStatic) {
+ extraArgumentFlags |= Advice.ThisJoinPointStaticPart;
+ } else {
+ removeParameter(index+0);
+ }
+
+ return extraArgumentFlags;
+ }
+
+ private void removeParameter(int indexToRemove) {
+ TypeBinding[] parameters = method.binding.parameters;
+ method.scope.locals = removeLocalBinding(indexToRemove, method.scope.locals);
+ 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];
+ System.arraycopy(bindings, 0, ret, 0, index);
+ 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];
+ System.arraycopy(bindings, 0, ret, 0, index);
+ System.arraycopy(bindings, index+1, ret, index, len-index-1);
+ return ret;
+ }
+
+
+}
private boolean emacsSymMode = false;
private boolean noWeave = false;
private boolean XserializableAspects = false;
+ private boolean XnoInline = false;
private String lintMode = AJLINT_DEFAULT;
private File lintSpecFile = null;
XserializableAspects = xserializableAspects;
}
+ public boolean isXnoInline() {
+ return XnoInline;
+ }
+
+ public void setXnoInline(boolean xnoInline) {
+ XnoInline = xnoInline;
+ }
+
}
private void initBcelWorld(IMessageHandler handler) throws IOException {
bcelWorld = new BcelWorld(buildConfig.getClasspath(), handler);
+ bcelWorld.setXnoInline(buildConfig.isXnoInline());
bcelWeaver = new BcelWeaver(bcelWorld);
for (Iterator i = buildConfig.getAspectpath().iterator(); i.hasNext();) {
pr, nameEnvironment);
EclipseWorld ew = new EclipseWorld(le, handler);
ew.setLint(bcelWorld.getLint());
+ ew.setXnoInline(buildConfig.isXnoInline());
le.world = ew;
pr.world = ew;
le.world.buildManager = this;
public class WorkingTestMain {
public static void main(String[] args1) throws IOException {
- testExamples();
- //testOne();
+ //testExamples();
+ testOne();
}
public static void testOne() throws IOException {
//args.add("../weaver/testdata/megatrace.jar");
args.add("testdata/src1/AroundA1.java");
- //args.add("../tests/new/AroundInnerCalls.java");
+ args.add("-XnoInline");
+ //args.add("../tests/new/Counting1.java");
//args.add("-Xlint:error");
//args.add("testdata/src1/InterType.java");
//args.add("@" + examplesDir + "tjp/files.lst");
CommandTestCase.runCompiler(args, CommandTestCase.NO_ERRORS);
//CommandTestCase.runCompiler(args, new int[] {11, 14, 18, 32, 43});
-// CommandTestCase.printGenerated("../out", "AdviceOnInheritedMethod");
+ CommandTestCase.printGenerated("../out", "AroundA1");
// CommandTestCase.printGenerated("../out", "SuperC");
// CommandTestCase.printGenerated("../out", "SubC");
- //TestUtil.runMain("out;../bcweaver/testdata/megatrace.jar", "Privileged");
- //TestUtil.runMain("out;../lib/test/testing-client.jar", "AroundInnerCalls");
+ TestUtil.runMain("out;../lib/test/testing-client.jar", "AroundA1");
}
private static String examplesDir = "../docs/dist/doc/examples/";
public abstract class Advice extends ShadowMunger {
- AjAttribute.AdviceAttribute attribute; // the pointcut field is ignored
+ protected AjAttribute.AdviceAttribute attribute; // the pointcut field is ignored
protected AdviceKind kind; // alias of attribute.getKind()
protected Member signature;
//public abstract boolean munge(LazyClassGen gen);
+
+ /** returns null for mungers that are used internally, but were not part of a declared
+ * thing in source code.
+ */
public ResolvedTypeMunger getMunger() {
return munger;
}
public boolean matches(ResolvedTypeX matchType) {
ResolvedTypeX onType = matchType.getWorld().resolve(signature.getDeclaringType());
+ //System.err.println("matching: " + this + " to " + matchType + " onType = " + onType);
if (matchType.equals(onType)) return true;
+ //System.err.println("NO MATCH DIRECT");
if (onType.isInterface()) {
return matchType.isTopmostImplementor(onType);
// ---- things that don't require a world
-
/** returns Iterator<ResolvedTypeX>
*/
public final Iterator getDirectSupertypes() {
public void addInterTypeMunger(ConcreteTypeMunger munger) {
ResolvedMember sig = munger.getSignature();
- if (sig == null) {
+ if (sig == null || munger.getMunger() == null ||
+ munger.getMunger().getKind() == ResolvedTypeMunger.PrivilegedAccess)
+ {
interTypeMungers.add(munger);
return;
}
protected StructureModel model = null;
protected Lint lint = new Lint(this);
+
+ protected boolean XnoInline;
protected World() {
super();
this.lint = lint;
}
+ public boolean isXnoInline() {
+ return XnoInline;
+ }
+
+ public void setXnoInline(boolean xnoInline) {
+ XnoInline = xnoInline;
+ }
+
}
}
}
+ private boolean canInline(Shadow s) {
+ if (attribute.isProceedInInners()) return false;
+ //XXX this guard seems to only be needed for bad test cases
+ if (concreteAspect == null || concreteAspect == ResolvedTypeX.MISSING) return false;
+
+ if (concreteAspect.getWorld().isXnoInline()) return false;
+ //System.err.println("isWoven? " + ((BcelObjectType)concreteAspect).getLazyClassGen().getWeaverState());
+ return ((BcelObjectType)concreteAspect).getLazyClassGen().getWeaverState()
+ == WeaverStateKind.Woven;
+ }
+
public void implementOn(Shadow s) {
BcelShadow shadow = (BcelShadow) s;
if (getKind() == AdviceKind.Before) {
} else if (getKind() == AdviceKind.After) {
shadow.weaveAfter(this);
} else if (getKind() == AdviceKind.Around) {
- shadow.weaveAroundClosure(this, hasDynamicTests());
- //shadow.weaveAroundInline(this, hasDynamicTests());
+ if (!canInline(s)) {
+ shadow.weaveAroundClosure(this, hasDynamicTests());
+ } else {
+ shadow.weaveAroundInline(this, hasDynamicTests());
+ }
} else if (getKind() == AdviceKind.InterInitializer) {
shadow.weaveAfterReturning(this);
} else if (getKind().isCflow()) {
List typeMungers)
{
boolean b = new BcelClassWeaver(world, clazz, shadowMungers, typeMungers).weave();
+ //System.err.println(clazz.getClassName() + ", " + clazz.getWeaverState());
//clazz.print();
return b;
}
* If only one call to proceed is made, we can re-inline the original shadow.
* We are not doing that presently.
*/
+
+ // !!! THIS BLOCK OF CODE SHOULD BE IN A METHOD CALLED weaveAround(...);
+ Member mungerSig = munger.getSignature();
+ ResolvedTypeX declaringType = world.resolve(mungerSig.getDeclaringType());
+ //??? might want some checks here to give better errors
+ BcelObjectType ot = (BcelObjectType)declaringType;
+
+ LazyMethodGen adviceMethod = ot.getLazyClassGen().getLazyMethodGen(mungerSig);
+ if (!adviceMethod.getCanInline()) {
+ weaveAroundClosure(munger, hasDynamicTest);
+ return;
+ }
+
+
// start by exposing various useful things into the frame
final InstructionFactory fact = getFactory();
if (! hasDynamicTest) {
range.append(advice);
} else {
+ InstructionList afterThingie = new InstructionList(fact.NOP);
InstructionList callback = makeCallToCallback(extractedMethod);
if (terminatesWithReturn()) {
callback.append(fact.createReturn(extractedMethod.getReturnType()));
} else {
- advice.append(fact.createBranchInstruction(Constants.GOTO, range.getEnd()));
+ //InstructionHandle endNop = range.insert(fact.NOP, Range.InsideAfter);
+ advice.append(fact.createBranchInstruction(Constants.GOTO, afterThingie.getStart()));
}
range.append(munger.getTestInstructions(this, advice.getStart(), callback.getStart(), advice.getStart()));
range.append(advice);
- range.append(callback);
+ range.append(callback);
+ range.append(afterThingie);
}
// now the range contains everything we need. We now inline the advice method.
- LazyMethodGen adviceMethod =
- ((BcelObjectType) munger.getConcreteAspect())
- .getLazyClassGen()
- .getLazyMethodGen(munger.getSignature());
+
BcelClassWeaver.inlineMethod(adviceMethod, enclosingMethod, adviceMethodInvocation);
{
InstructionFactory fact = getFactory();
+ enclosingMethod.setCanInline(false);
+
// MOVE OUT ALL THE INSTRUCTIONS IN MY SHADOW INTO ANOTHER METHOD!
LazyMethodGen callbackMethod =
extractMethod(
}
// ---- fluf
- public ResolvedTypeX resolveObjectType(TypeX ty) {
+ protected ResolvedTypeX resolveObjectType(TypeX ty) {
String name = ty.getName();
JavaClass jc = null;
//UnwovenClassFile classFile = (UnwovenClassFile)sourceJavaClasses.get(name);
myGen.addAttribute(BcelAttributes.bcelAttribute(
new AjAttribute.WeaverState(s),
getConstantPoolGen()));
+ myType.setWeaverState(s);
}
public InstructionFactory getFactory() {
if (gen.getName().equals(name) && gen.getSignature().equals(signature))
return gen;
}
+
throw new BCException("Class " + this.getName() + " does not have a method "
+ name + " with signature " + signature);
}
private int maxLocals;
+ private boolean canInline = true;
+
/**
* only used by {@link BcelClassWeaver}
*/
String getRangeString(Range r, Map labelMap) {
if (r instanceof ExceptionRange) {
ExceptionRange er = (ExceptionRange) r;
- return er.toString() + " -> " + labelMap.get(er.getHandler());
+ return er.toString() + " -> " + labelMap.get(er.getHandler());
+//
+// + " PRI " + er.getPriority();
} else {
return r.toString();
}
}
}
- // exception ordering
+ // exception ordering.
+ // What we should be doing is dealing with priority inversions way earlier than we are
+ // and counting on the tree structure. In which case, the below code is in fact right.
+
+ // XXX THIS COMMENT BELOW IS CURRENTLY WRONG.
// An exception A preceeds an exception B in the exception table iff:
// * A and B were in the original method, and A preceeded B in the original exception table
// but I don't trust the only implementation, TreeSet, to do the right thing.
private static void insertHandler(ExceptionRange fresh, LinkedList l) {
- for (ListIterator iter = l.listIterator(); iter.hasNext();) {
- ExceptionRange r = (ExceptionRange) iter.next();
- if (fresh.getPriority() >= r.getPriority()) {
- iter.previous();
- iter.add(fresh);
- return;
- }
- }
- l.add(fresh);
+// for (ListIterator iter = l.listIterator(); iter.hasNext();) {
+// ExceptionRange r = (ExceptionRange) iter.next();
+// if (fresh.getPriority() >= r.getPriority()) {
+// iter.previous();
+// iter.add(fresh);
+// return;
+// }
+// }
+ l.add(0, fresh);
}
accessFlags = Utility.makePublic(accessFlags);
}
+ public boolean getCanInline() {
+ return canInline;
+ }
+
+ public void setCanInline(boolean canInline) {
+ this.canInline = canInline;
+ }
+
}
method-execution(void FancyHelloWorld.main(java.lang.String[]))
| catch java.lang.Throwable -> E6
| | field-get(java.io.PrintStream java.lang.System.out)
- | | | catch java.lang.Throwable -> E3
+ | | | catch java.lang.Throwable -> E5
| | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
- | | | catch java.lang.Throwable -> E3
+ | | | catch java.lang.Throwable -> E5
| | | GOTO L0
- | | | E3: ASTORE 5
+ | | | E5: ASTORE 5
| | | INVOKESTATIC Aspect.ajc_after_field_get ()V
| | | ALOAD 5
| | | ATHROW
| | | NOP
| | field-get(java.io.PrintStream java.lang.System.out)
| | ASTORE_1
- | | finally -> E5
- | | | catch java.lang.Exception -> E4
+ | | finally -> E4
+ | | | catch java.lang.Exception -> E3
| | | | ALOAD_1 // java.io.PrintStream out (line 11)
| | | | LDC "bye"
| | | | method-call(void java.io.PrintStream.println(java.lang.String))
| | | | | NOP
| | | | method-call(void java.io.PrintStream.println(java.lang.String))
| | | | GOTO L3
- | | | catch java.lang.Exception -> E4
- | | | E4: ASTORE_2 (line 12)
+ | | | catch java.lang.Exception -> E3
+ | | | E3: ASTORE_2 (line 12)
| | | ALOAD_1 // java.io.PrintStream out (line 13)
| | | ALOAD_2 // java.lang.Exception e
| | | method-call(void java.io.PrintStream.println(java.lang.Object))
| | | | INVOKESTATIC Aspect.ajc_after_method_call ()V
| | | | NOP
| | | method-call(void java.io.PrintStream.println(java.lang.Object))
- | | finally -> E5
+ | | finally -> E4
| | GOTO L3
- | | E5: ASTORE 4 (line 14)
+ | | E4: ASTORE 4 (line 14)
| | JSR L4
| | ALOAD 4
| | ATHROW
| ARETURN
method-execution(java.lang.String FancyHelloWorld.getName())
end public static String getName()
+
end public abstract class FancyHelloWorld
method-execution(void FancyHelloWorld.main(java.lang.String[]))
| catch java.lang.Throwable -> E6
| | field-get(java.io.PrintStream java.lang.System.out)
- | | | catch java.lang.Throwable -> E3
+ | | | catch java.lang.Throwable -> E5
| | | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
- | | | catch java.lang.Throwable -> E3
+ | | | catch java.lang.Throwable -> E5
| | | GOTO L0
- | | | E3: ASTORE 5
+ | | | E5: ASTORE 5
| | | INVOKESTATIC Aspect.ajc_afterThrowing_field_get ()V
| | | ALOAD 5
| | | ATHROW
| | | L0: NOP
| | field-get(java.io.PrintStream java.lang.System.out)
| | ASTORE_1
- | | finally -> E5
- | | | catch java.lang.Exception -> E4
+ | | finally -> E4
+ | | | catch java.lang.Exception -> E3
| | | | ALOAD_1 // java.io.PrintStream out (line 11)
| | | | LDC "bye"
| | | | method-call(void java.io.PrintStream.println(java.lang.String))
| | | | | L1: NOP
| | | | method-call(void java.io.PrintStream.println(java.lang.String))
| | | | GOTO L3
- | | | catch java.lang.Exception -> E4
- | | | E4: ASTORE_2 (line 12)
+ | | | catch java.lang.Exception -> E3
+ | | | E3: ASTORE_2 (line 12)
| | | ALOAD_1 // java.io.PrintStream out (line 13)
| | | ALOAD_2 // java.lang.Exception e
| | | method-call(void java.io.PrintStream.println(java.lang.Object))
| | | | ATHROW
| | | | L2: NOP
| | | method-call(void java.io.PrintStream.println(java.lang.Object))
- | | finally -> E5
+ | | finally -> E4
| | GOTO L3
- | | E5: ASTORE 4 (line 14)
+ | | E4: ASTORE 4 (line 14)
| | JSR L4
| | ALOAD 4
| | ATHROW
| ATHROW
method-execution(java.lang.String FancyHelloWorld.getName())
end public static String getName()
+
end public abstract class FancyHelloWorld
public static void main(String[]):
method-execution(void FancyHelloWorld.main(java.lang.String[]))
| field-get(java.io.PrintStream java.lang.System.out)
- | | catch java.lang.Throwable -> E0
+ | | catch java.lang.Throwable -> E2
| | | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 9)
- | | catch java.lang.Throwable -> E0
+ | | catch java.lang.Throwable -> E2
| | GOTO L0
- | | E0: ASTORE 5
+ | | E2: ASTORE 5
| | ALOAD 5
| | INVOKESTATIC Aspect.ajc_afterThrowing_field_get (Ljava/lang/Throwable;)V
| | ALOAD 5
| | L0: NOP
| field-get(java.io.PrintStream java.lang.System.out)
| ASTORE_1
- | finally -> E2
- | | catch java.lang.Exception -> E1
+ | finally -> E1
+ | | catch java.lang.Exception -> E0
| | | ALOAD_1 // java.io.PrintStream out (line 11)
| | | LDC "bye"
| | | method-call(void java.io.PrintStream.println(java.lang.String))
| | | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
| | | method-call(void java.io.PrintStream.println(java.lang.String))
| | | GOTO L1
- | | catch java.lang.Exception -> E1
- | | E1: ASTORE_2 (line 12)
+ | | catch java.lang.Exception -> E0
+ | | E0: ASTORE_2 (line 12)
| | ALOAD_1 // java.io.PrintStream out (line 13)
| | ALOAD_2 // java.lang.Exception e
| | method-call(void java.io.PrintStream.println(java.lang.Object))
| | | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/Object;)V
| | method-call(void java.io.PrintStream.println(java.lang.Object))
- | finally -> E2
+ | finally -> E1
| GOTO L1
- | E2: ASTORE 4 (line 14)
+ | E1: ASTORE 4 (line 14)
| JSR L2
| ALOAD 4
| ATHROW
| ARETURN
method-execution(java.lang.String FancyHelloWorld.getName())
end public static String getName()
+
end public abstract class FancyHelloWorld
| ALOAD_0
| INVOKEVIRTUAL Trace.ajc$before$Trace$51 (Ljava/lang/Object;)V
| INVOKESTATIC MyTrace.aspectOf ()LMyTrace;
- | BIPUSH 3
- | ANEWARRAY java.lang.Object
- | ASTORE 6
- | ALOAD 6
- | BIPUSH 0
+ | ACONST_NULL
+ | ASTORE 13
+ | ASTORE 12
+ | LDC "Hi" (line 9)
+ | ASTORE 14
+ | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 10)
+ | NEW java.lang.StringBuffer
+ | DUP
+ | LDC "start around: "
+ | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | ALOAD 14
+ | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | ALOAD 13 (line 11)
+ | ASTORE 18
| ALOAD_0
- | AASTORE
- | ALOAD 6
- | BIPUSH 1
| ALOAD_3
- | AASTORE
- | ALOAD 6
- | BIPUSH 2
| ALOAD 4
- | AASTORE
- | NEW DynamicHelloWorld$AjcClosure3
+ | INVOKESTATIC DynamicHelloWorld.doit_aroundBody1 (LDynamicHelloWorld;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ | ASTORE 16
+ | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 12)
+ | NEW java.lang.StringBuffer
| DUP
- | ALOAD 6
- | INVOKESPECIAL DynamicHelloWorld$AjcClosure3.<init> ([Ljava/lang/Object;)V
- | INVOKEVIRTUAL Trace.ajc$around$Trace$cc (Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
- | CHECKCAST java.lang.String
+ | LDC "exiting around with: "
+ | INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ | ALOAD 16
+ | INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ | INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ | INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ | ALOAD 16 (line 13)
| GOTO L0
- | L0: DUP
- | ASTORE 7
+ | L0: NOP
+ | CHECKCAST java.lang.String
+ | GOTO L1
+ | L1: DUP
+ | ASTORE 19
| INVOKESTATIC MyTrace.aspectOf ()LMyTrace;
| ALOAD_0
- | ALOAD 7
+ | ALOAD 19
| INVOKEVIRTUAL MyTrace.ajc$afterReturning$MyTrace$6e (Ljava/lang/Object;Ljava/lang/Object;)V
| ARETURN
method-execution(java.lang.String DynamicHelloWorld.doit(java.lang.String, java.util.List))
ARETURN
end static final String doit_aroundBody0(DynamicHelloWorld, String, java.util.List)
- static final String doit_aroundBody2(DynamicHelloWorld, String, java.util.List):
+ static final String doit_aroundBody1(DynamicHelloWorld, String, java.util.List):
INVOKESTATIC MyTrace.aspectOf ()LMyTrace;
ALOAD_0
- BIPUSH 3
- ANEWARRAY java.lang.Object
+ ACONST_NULL
ASTORE_3
- ALOAD_3
- BIPUSH 0
- ALOAD_0
- AASTORE
- ALOAD_3
- BIPUSH 1
- ALOAD_1
- AASTORE
- ALOAD_3
- BIPUSH 2
- ALOAD_2
- AASTORE
- NEW DynamicHelloWorld$AjcClosure1
+ ASTORE 5
+ ASTORE 7
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 17)
+ NEW java.lang.StringBuffer
DUP
+ LDC "start around(2): "
+ INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ ALOAD 5
+ INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ ALOAD 5 (line 18)
ALOAD_3
- INVOKESPECIAL DynamicHelloWorld$AjcClosure1.<init> ([Ljava/lang/Object;)V
- INVOKEVIRTUAL Trace.ajc$around$Trace$1bc (Ljava/lang/Object;Lorg/aspectj/runtime/internal/AroundClosure;)Ljava/lang/Object;
- CHECKCAST java.lang.String
- ARETURN
- end static final String doit_aroundBody2(DynamicHelloWorld, String, java.util.List)
-end public class DynamicHelloWorld
-
-public class DynamicHelloWorld$AjcClosure1 extends org.aspectj.runtime.internal.AroundClosure:
- public void <init>(Object[]):
- ALOAD_0
- ALOAD_1
- INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
- RETURN
- end public void <init>(Object[])
-
- public Object run(Object[]):
- ALOAD_0
- GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
- ASTORE_2
- ALOAD_1
- BIPUSH 0
- AALOAD
+ ASTORE 9
+ ASTORE 11
+ ALOAD 11
CHECKCAST DynamicHelloWorld
- ALOAD_2
- BIPUSH 1
- AALOAD
- CHECKCAST java.lang.String
- ALOAD_2
- BIPUSH 2
- AALOAD
- CHECKCAST java.util.List
- INVOKESTATIC DynamicHelloWorld.doit_aroundBody0 (LDynamicHelloWorld;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
- ARETURN
- end public Object run(Object[])
-end public class DynamicHelloWorld$AjcClosure1
-
-public class DynamicHelloWorld$AjcClosure3 extends org.aspectj.runtime.internal.AroundClosure:
- public void <init>(Object[]):
- ALOAD_0
ALOAD_1
- INVOKESPECIAL org.aspectj.runtime.internal.AroundClosure.<init> ([Ljava/lang/Object;)V
- RETURN
- end public void <init>(Object[])
-
- public Object run(Object[]):
- ALOAD_0
- GETFIELD org.aspectj.runtime.internal.AroundClosure.state [Ljava/lang/Object;
- ASTORE_2
- ALOAD_2
- BIPUSH 0
- AALOAD
- CHECKCAST DynamicHelloWorld
ALOAD_2
- BIPUSH 1
- AALOAD
+ INVOKESTATIC DynamicHelloWorld.doit_aroundBody0 (LDynamicHelloWorld;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
+ ASTORE 13
+ GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line 19)
+ NEW java.lang.StringBuffer
+ DUP
+ LDC "exiting around with(2): "
+ INVOKESPECIAL java.lang.StringBuffer.<init> (Ljava/lang/String;)V
+ ALOAD 13
+ INVOKEVIRTUAL java.lang.StringBuffer.append (Ljava/lang/Object;)Ljava/lang/StringBuffer;
+ INVOKEVIRTUAL java.lang.StringBuffer.toString ()Ljava/lang/String;
+ INVOKEVIRTUAL java.io.PrintStream.println (Ljava/lang/String;)V
+ ALOAD 13 (line 20)
+ GOTO L0
+ L0: NOP
CHECKCAST java.lang.String
- ALOAD_2
- BIPUSH 2
- AALOAD
- CHECKCAST java.util.List
- INVOKESTATIC DynamicHelloWorld.doit_aroundBody2 (LDynamicHelloWorld;Ljava/lang/String;Ljava/util/List;)Ljava/lang/String;
ARETURN
- end public Object run(Object[])
-end public class DynamicHelloWorld$AjcClosure3
+ end static final String doit_aroundBody1(DynamicHelloWorld, String, java.util.List)
+end public class DynamicHelloWorld