public void weaveCflowEntry(final BcelAdvice munger, final Member cflowField) {
final boolean isPer = munger.getKind() == AdviceKind.PerCflowBelowEntry || munger.getKind() == AdviceKind.PerCflowEntry;
final Type objectArrayType = new ArrayType(Type.OBJECT, 1);
final InstructionFactory fact = getFactory();
final BcelVar testResult = genTempVar(ResolvedType.BOOLEAN);
InstructionList entryInstructions = new InstructionList();
{
InstructionList entrySuccessInstructions = new InstructionList();
if (munger.hasDynamicTests()) {
entryInstructions.append(Utility.createConstant(fact, 0));
testResult.appendStore(entryInstructions, fact);
entrySuccessInstructions.append(Utility.createConstant(fact, 1));
testResult.appendStore(entrySuccessInstructions, fact);
}
if (isPer) {
entrySuccessInstructions.append(fact.createInvoke(munger.getConcreteAspect().getName(),
NameMangler.PERCFLOW_PUSH_METHOD, Type.VOID, new Type[] {}, Constants.INVOKESTATIC));
} else {
BcelVar[] cflowStateVars = munger.getExposedStateAsBcelVars(false);
if (cflowStateVars.length == 0) {
// This should be getting managed by a counter - lets make sure.
if (!cflowField.getType().getName().endsWith("CFlowCounter")) {
throw new RuntimeException("Incorrectly attempting counter operation on stacked cflow");
}
entrySuccessInstructions.append(Utility.createGet(fact, cflowField));
// arrayVar.appendLoad(entrySuccessInstructions, fact);
entrySuccessInstructions.append(fact.createInvoke(NameMangler.CFLOW_COUNTER_TYPE, "inc", Type.VOID,
new Type[] {}, Constants.INVOKEVIRTUAL));
} else {
BcelVar arrayVar = genTempVar(UnresolvedType.OBJECTARRAY);
int alen = cflowStateVars.length;
entrySuccessInstructions.append(Utility.createConstant(fact, alen));
entrySuccessInstructions.append(fact.createNewArray(Type.OBJECT, (short) 1));
arrayVar.appendStore(entrySuccessInstructions, fact);
for (int i = 0; i < alen; i++) {
arrayVar.appendConvertableArrayStore(entrySuccessInstructions, fact, i, cflowStateVars[i]);
}
entrySuccessInstructions.append(Utility.createGet(fact, cflowField));
arrayVar.appendLoad(entrySuccessInstructions, fact);
entrySuccessInstructions.append(fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "push", Type.VOID,
new Type[] { objectArrayType }, Constants.INVOKEVIRTUAL));
}
}
InstructionList testInstructions = munger.getTestInstructions(this, entrySuccessInstructions.getStart(), range
.getRealStart(), entrySuccessInstructions.getStart());
entryInstructions.append(testInstructions);
entryInstructions.append(entrySuccessInstructions);
}
// this is the same for both per and non-per
weaveAfter(new BcelAdvice(null, null, null, 0, 0, 0, null, munger.getConcreteAspect()) {
@Override
public InstructionList getAdviceInstructions(BcelShadow s, BcelVar extraArgVar, InstructionHandle ifNoAdvice) {
InstructionList exitInstructions = new InstructionList();
if (munger.hasDynamicTests()) {
testResult.appendLoad(exitInstructions, fact);
exitInstructions.append(InstructionFactory.createBranchInstruction(Constants.IFEQ, ifNoAdvice));
}
exitInstructions.append(Utility.createGet(fact, cflowField));
if (munger.getKind() != AdviceKind.PerCflowEntry && munger.getKind() != AdviceKind.PerCflowBelowEntry
&& munger.getExposedStateAsBcelVars(false).length == 0) {
exitInstructions.append(fact.createInvoke(NameMangler.CFLOW_COUNTER_TYPE, "dec", Type.VOID, new Type[] {},
Constants.INVOKEVIRTUAL));
} else {
exitInstructions.append(fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "pop", Type.VOID, new Type[] {},
Constants.INVOKEVIRTUAL));
}
return exitInstructions;
}
});