@@ -104,10 +104,15 @@ public abstract class Advice extends ShadowMunger { | |||
return shadow.hasThis(); | |||
} else if (kind == AdviceKind.Around) { | |||
if (shadow.getKind() == Shadow.PreInitialization) { | |||
world.showMessage(IMessage.WARNING, | |||
world.showMessage(IMessage.ERROR, | |||
"around on pre-initialization not supported (compiler limitation)", | |||
getSourceLocation(), shadow.getSourceLocation()); | |||
return false; | |||
} else if (shadow.getKind() == Shadow.Initialization) { | |||
world.showMessage(IMessage.ERROR, | |||
"around on initialization not supported (compiler limitation)", | |||
getSourceLocation(), shadow.getSourceLocation()); | |||
return false; | |||
} else { | |||
if (!getSignature().getReturnType().isConvertableFrom(shadow.getReturnType(), world)) { | |||
//System.err.println(this + ", " + sourceContext + ", " + start); |
@@ -35,29 +35,88 @@ import org.aspectj.util.*; | |||
public abstract class Shadow { | |||
private final Kind kind; | |||
private final Member signature; | |||
protected final Shadow enclosingShadow; | |||
protected List mungers = new ArrayList(1); | |||
// ---- | |||
protected Shadow(Kind kind, Member signature) { | |||
protected Shadow(Kind kind, Member signature, Shadow enclosingShadow) { | |||
this.kind = kind; | |||
this.signature = signature; | |||
this.enclosingShadow = enclosingShadow; | |||
} | |||
// ---- | |||
public abstract World getIWorld(); | |||
/** | |||
* could this(*) pcd ever match | |||
*/ | |||
public final boolean hasThis() { | |||
if (getKind().neverHasThis()) { | |||
return false; | |||
} else if (getKind().isEnclosingKind()) { | |||
return !getSignature().isStatic(); | |||
} else if (enclosingShadow == null) { | |||
return false; | |||
} else { | |||
return enclosingShadow.hasThis(); | |||
} | |||
} | |||
/** | |||
* the type of the this object here | |||
* | |||
* @throws IllegalStateException if there is no this here | |||
*/ | |||
public final TypeX getThisType() { | |||
if (!hasThis()) throw new IllegalStateException("no this"); | |||
if (getKind().isEnclosingKind()) { | |||
return getSignature().getDeclaringType(); | |||
} else { | |||
return enclosingShadow.getThisType(); | |||
} | |||
} | |||
/** | |||
* a var referencing this | |||
* | |||
* @throws IllegalStateException if there is no target here | |||
*/ | |||
public abstract Var getThisVar(); | |||
/** | |||
* could target(*) pcd ever match | |||
*/ | |||
public final boolean hasTarget() { | |||
return !(getSignature().isStatic() || (getKind() == ConstructorCall) | |||
|| (getKind() == PreInitialization)); | |||
if (getKind().neverHasTarget()) { | |||
return false; | |||
} else if (getKind().isTargetSameAsThis()) { | |||
return hasThis(); | |||
} else { | |||
return !getSignature().isStatic(); | |||
} | |||
} | |||
/** | |||
* the type of the target object here | |||
* | |||
* @throws IllegalStateException if there is no target here | |||
*/ | |||
public final TypeX getTargetType() { | |||
if (!hasTarget()) return ResolvedTypeX.MISSING; | |||
if (!hasTarget()) throw new IllegalStateException("no target"); | |||
return getSignature().getDeclaringType(); | |||
} | |||
/** | |||
* a var referencing the target | |||
* | |||
* @throws IllegalStateException if there is no target here | |||
*/ | |||
public abstract Var getTargetVar(); | |||
public TypeX[] getArgTypes() { | |||
if (getKind() == FieldSet) return new TypeX[] { getSignature().getReturnType() }; | |||
return getSignature().getParameterTypes(); | |||
@@ -73,12 +132,9 @@ public abstract class Shadow { | |||
return getSignature() | |||
.getParameterTypes().length; | |||
} | |||
public abstract boolean hasThis(); | |||
public abstract TypeX getThisType(); | |||
public abstract TypeX getEnclosingType(); | |||
public abstract Var getThisVar(); | |||
public abstract Var getTargetVar(); | |||
public abstract Var getArgVar(int i); | |||
public abstract Var getThisJoinPointVar(); | |||
@@ -128,7 +184,7 @@ public abstract class Shadow { | |||
/** A type-safe enum representing the kind of shadows | |||
*/ | |||
public static final class Kind extends TypeSafeEnum { | |||
private boolean argsOnStack; | |||
private boolean argsOnStack; //XXX unused | |||
public Kind(String name, int key, boolean argsOnStack) { | |||
super(name, key); | |||
@@ -140,7 +196,7 @@ public abstract class Shadow { | |||
} | |||
public boolean argsOnStack() { | |||
return argsOnStack; | |||
return !isTargetSameAsThis(); | |||
} | |||
// !!! this is false for handlers! | |||
@@ -148,6 +204,44 @@ public abstract class Shadow { | |||
return true; | |||
} | |||
// XXX revisit along with removal of priorities | |||
public boolean hasHighPriorityExceptions() { | |||
return !isTargetSameAsThis(); | |||
} | |||
/** | |||
* These are all the shadows that contains other shadows within them and | |||
* are often directly associated with methods. | |||
*/ | |||
public boolean isEnclosingKind() { | |||
return this == MethodExecution || this == ConstructorExecution || | |||
this == AdviceExecution || this == StaticInitialization | |||
|| this == Initialization; | |||
} | |||
public boolean isTargetSameAsThis() { | |||
return this == MethodExecution | |||
|| this == ConstructorExecution | |||
|| this == StaticInitialization | |||
|| this == PreInitialization | |||
|| this == AdviceExecution | |||
|| this == Initialization; | |||
} | |||
public boolean neverHasTarget() { | |||
return this == ConstructorCall | |||
|| this == ExceptionHandler | |||
|| this == PreInitialization | |||
|| this == StaticInitialization; | |||
} | |||
public boolean neverHasThis() { | |||
return this == PreInitialization | |||
|| this == StaticInitialization; | |||
} | |||
public String getSimpleName() { | |||
int dash = getName().lastIndexOf('-'); | |||
if (dash == -1) return getName(); | |||
@@ -233,6 +327,9 @@ public abstract class Shadow { | |||
// ---- type access methods | |||
@@ -495,6 +495,10 @@ class BcelClassWeaver implements IClassWeaver { | |||
(InstructionHandle) srcToDest.get(oldRange.getEnd())); | |||
shadowMap.put(oldRange, freshRange); | |||
//recipient.matchedShadows.add(freshShadow); | |||
// XXX should go through the NEW copied shadow and update | |||
// the thisVar, targetVar, and argsVar | |||
// ??? Might want to also go through at this time and add | |||
// "extra" vars to the shadow. | |||
} | |||
} | |||
} | |||
@@ -634,13 +638,16 @@ class BcelClassWeaver implements IClassWeaver { | |||
enclosingShadow = BcelShadow.makeConstructorExecution(world, mg, superOrThisCall); | |||
// walk the body | |||
boolean beforeSuperOrThisCall = true; | |||
if (shouldWeaveBody(mg)) { //!mg.isAjSynthetic()) { | |||
for (InstructionHandle h = mg.getBody().getStart(); | |||
h != null; | |||
h = h.getNext()) { | |||
if (h == superOrThisCall) | |||
if (h == superOrThisCall) { | |||
beforeSuperOrThisCall = false; | |||
continue; | |||
match(mg, h, enclosingShadow, shadowAccumulator); | |||
} | |||
match(mg, h, beforeSuperOrThisCall ? null : enclosingShadow, shadowAccumulator); | |||
} | |||
match(enclosingShadow, shadowAccumulator); | |||
} |
@@ -78,9 +78,7 @@ public class BcelShadow extends Shadow { | |||
private ShadowRange range; | |||
private final BcelWorld world; | |||
private final LazyMethodGen enclosingMethod; | |||
private final BcelShadow enclosingShadow; | |||
private boolean fallsThrough; | |||
private boolean fallsThrough; //XXX not used anymore | |||
// ---- initialization | |||
@@ -96,10 +94,9 @@ public class BcelShadow extends Shadow { | |||
LazyMethodGen enclosingMethod, | |||
BcelShadow enclosingShadow) | |||
{ | |||
super(kind, signature); | |||
super(kind, signature, enclosingShadow); | |||
this.world = world; | |||
this.enclosingMethod = enclosingMethod; | |||
this.enclosingShadow = enclosingShadow; | |||
fallsThrough = kind.argsOnStack(); | |||
} | |||
@@ -273,7 +270,7 @@ public class BcelShadow extends Shadow { | |||
// overrides | |||
public TypeX getEnclosingType() { | |||
return world.resolve(getEnclosingClass().getClassName()); | |||
return getEnclosingClass().getType(); | |||
} | |||
public LazyClassGen getEnclosingClass() { | |||
@@ -652,23 +649,6 @@ public class BcelShadow extends Shadow { | |||
} | |||
// ---- type access methods | |||
public boolean hasThis() { | |||
if (getKind() == PreInitialization) return false; | |||
return !getEnclosingCodeSignature().isStatic(); | |||
//???return !enclosingMethod.isStatic(); | |||
} | |||
public TypeX getThisType() { | |||
if (!hasThis()) return ResolvedTypeX.MISSING; | |||
return getEnclosingCodeSignature().getDeclaringType(); | |||
//???return TypeX.forName(getEnclosingClass().getClassName()); | |||
} | |||
public boolean isTargetDifferentFromThis() { | |||
return hasTarget() && isExpressionKind(); | |||
} | |||
private ObjectType getTargetBcelType() { | |||
return (ObjectType) world.makeBcelType(getTargetType()); | |||
} | |||
@@ -677,10 +657,28 @@ public class BcelShadow extends Shadow { | |||
} | |||
// ---- kinding | |||
/** | |||
* If the end of my range has no real instructions following then | |||
* my context needs a return at the end. | |||
*/ | |||
public boolean terminatesWithReturn() { | |||
return getRange().getRealNext() == null; | |||
} | |||
public boolean isExpressionKind() { | |||
if (getKind() == PreInitialization) return true; | |||
return getKind().argsOnStack(); | |||
/** | |||
* Is arg0 occupied with the value of this | |||
*/ | |||
public boolean arg0HoldsThis() { | |||
if (getKind().isEnclosingKind()) { | |||
return !getSignature().isStatic(); | |||
} else if (enclosingShadow == null) { | |||
//XXX this is mostly right | |||
// this doesn't do the right thing for calls in the pre part of introduced constructors. | |||
return !enclosingMethod.isStatic(); | |||
} else { | |||
return ((BcelShadow)enclosingShadow).arg0HoldsThis(); | |||
} | |||
} | |||
// ---- argument getting methods | |||
@@ -770,7 +768,7 @@ public class BcelShadow extends Shadow { | |||
// the enclosing of an execution is itself | |||
return getThisJoinPointStaticPartBcelVar(); | |||
} else { | |||
return enclosingShadow.getThisJoinPointStaticPartBcelVar(); | |||
return ((BcelShadow)enclosingShadow).getThisJoinPointStaticPartBcelVar(); | |||
} | |||
} | |||
@@ -815,8 +813,8 @@ public class BcelShadow extends Shadow { | |||
public void initializeTargetVar() { | |||
InstructionFactory fact = getFactory(); | |||
if (targetVar != null) return; | |||
if (! isExpressionKind()) { | |||
initializeThisVar(); | |||
if (getKind().isTargetSameAsThis()) { | |||
if (hasThis()) initializeThisVar(); | |||
targetVar = thisVar; | |||
} else { | |||
initializeArgVars(); // gotta pop off the args before we find the target | |||
@@ -846,7 +844,7 @@ public class BcelShadow extends Shadow { | |||
} | |||
} else { | |||
int index = 0; | |||
if (hasThis()) index++; | |||
if (arg0HoldsThis()) index++; | |||
for (int i = 0; i < len; i++) { | |||
TypeX type = getArgType(i); | |||
@@ -966,7 +964,7 @@ public class BcelShadow extends Shadow { | |||
enclosingMethod.addExceptionHandler(range.getStart().getNext(), protectedEnd.getPrev(), | |||
handlerStart, (ObjectType)BcelWorld.makeBcelType(catchType), //???Type.THROWABLE, | |||
// high priority if our args are on the stack | |||
isExpressionKind()); | |||
getKind().hasHighPriorityExceptions()); | |||
} | |||
@@ -994,7 +992,7 @@ public class BcelShadow extends Shadow { | |||
enclosingMethod.addExceptionHandler(range.getStart().getNext(), protectedEnd.getPrev(), | |||
handlerStart, (ObjectType)BcelWorld.makeBcelType(catchType), | |||
// high priority if our args are on the stack | |||
isExpressionKind()); | |||
getKind().hasHighPriorityExceptions()); | |||
} | |||
@@ -1173,7 +1171,7 @@ public class BcelShadow extends Shadow { | |||
range.append(advice); | |||
} else { | |||
InstructionList callback = makeCallToCallback(extractedMethod); | |||
if (! isExpressionKind()) { | |||
if (terminatesWithReturn()) { | |||
callback.append(fact.createReturn(extractedMethod.getReturnType())); | |||
} else { | |||
advice.append(fact.createBranchInstruction(Constants.GOTO, range.getEnd())); | |||
@@ -1358,7 +1356,7 @@ public class BcelShadow extends Shadow { | |||
} else { | |||
InstructionList callback = makeCallToCallback(callbackMethod); | |||
InstructionList postCallback = new InstructionList(); | |||
if (! isExpressionKind()) { | |||
if (terminatesWithReturn()) { | |||
callback.append(fact.createReturn(callbackMethod.getReturnType())); | |||
} else { | |||
advice.append(fact.createBranchInstruction(Constants.GOTO, postCallback.append(fact.NOP))); | |||
@@ -1652,7 +1650,7 @@ public class BcelShadow extends Shadow { | |||
int newi = 0; | |||
// if we're passing in a this and we're not argsOnStack we're always | |||
// passing in a target too | |||
if (hasThis()) { ret.put(0, 0); oldi++; newi+=1; } | |||
if (arg0HoldsThis()) { ret.put(0, 0); oldi++; newi+=1; } | |||
//assert targetVar == thisVar | |||
for (int i = 0; i < getArgCount(); i++) { | |||
TypeX type = getArgType(i); | |||
@@ -1661,6 +1659,12 @@ public class BcelShadow extends Shadow { | |||
newi += type.getSize(); | |||
} | |||
} | |||
// System.err.println("making remap for : " + this); | |||
// if (targetVar != null) System.err.println("target slot : " + targetVar.getSlot()); | |||
// if (thisVar != null) System.err.println(" this slot : " + thisVar.getSlot()); | |||
// System.err.println(ret); | |||
return ret; | |||
} | |||
@@ -1684,7 +1688,7 @@ public class BcelShadow extends Shadow { | |||
TypeX targetType = getTargetType(); | |||
ResolvedMember resolvedMember = getSignature().resolve(world); | |||
if (resolvedMember != null && Modifier.isProtected(resolvedMember.getModifiers()) && | |||
!samePackage(targetType.getPackageName(), getThisType().getPackageName())) | |||
!samePackage(targetType.getPackageName(), getEnclosingType().getPackageName())) | |||
{ | |||
if (!targetType.isAssignableFrom(getThisType(), world)) { | |||
throw new BCException("bad bytecode"); | |||
@@ -1777,7 +1781,7 @@ public class BcelShadow extends Shadow { | |||
return new SourceLocation(new File(getEnclosingClass().getFileName()), getSourceLine()); | |||
} | |||
public BcelShadow getEnclosingShadow() { | |||
public Shadow getEnclosingShadow() { | |||
return enclosingShadow; | |||
} | |||
@@ -1786,6 +1790,6 @@ public class BcelShadow extends Shadow { | |||
} | |||
public boolean isFallsThrough() { | |||
return fallsThrough; | |||
return !terminatesWithReturn(); //fallsThrough; | |||
} | |||
} |
@@ -42,14 +42,20 @@ public final class ExceptionRange extends Range { | |||
/** | |||
* After this constructor is called, this range is not well situated unless | |||
* {@link #associateWithTargets} is called | |||
* | |||
* XXX priority should be fixed | |||
*/ | |||
public ExceptionRange(InstructionList body, TypeX exceptionType, int priority) { | |||
super(body); | |||
this.exceptionType = exceptionType; | |||
this.priority = priority; | |||
} | |||
public ExceptionRange(InstructionList body, TypeX exceptionType, boolean highPriority) { | |||
this(body, exceptionType, highPriority ? Integer.MAX_VALUE : -1); | |||
/** | |||
* @param insideExisting | |||
*/ | |||
public ExceptionRange(InstructionList body, TypeX exceptionType, boolean insideExisting) { | |||
this(body, exceptionType, insideExisting ? Integer.MAX_VALUE : -1); | |||
} | |||
public void associateWithTargets( | |||
InstructionHandle start, |
@@ -80,6 +80,10 @@ abstract class Range implements InstructionTargeter { | |||
return getRealEnd(end); | |||
} | |||
InstructionHandle getRealNext() { | |||
return getRealStart(end); | |||
} | |||
static InstructionHandle getRealPrev(InstructionHandle ih) { | |||
InstructionHandle ret = ih.getPrev(); | |||
while (isRangeHandle(ret)) { |