boolean isStatic = (mn.access & ACC_STATIC) != 0;
log("Instrumenting " + mn.name + " " + mn.desc + " "
+ (isStatic ? " static " : ""));
Label fStartl = new Label();
Label fEndl = new Label();
LabelNode fStart = new LabelNode(fStartl);
LabelNode fEnd = new LabelNode(fEndl);
// Label vStartl = new Label();
// Label vEndl = new Label();
// LabelNode vStart = new LabelNode(vStartl);
// LabelNode vEnd = new LabelNode(vEndl);
LabelNode mStart = null;// (LabelNode) mn.instructions.getFirst();
LabelNode mEnd = null; // (LabelNode) mn.instructions.getLast();
for (ListIterator<AbstractInsnNode> i = mn.instructions.iterator(); i
.hasNext();) {
AbstractInsnNode node = i.next();
if (node instanceof LabelNode) {
if (mStart == null) {
mStart = (LabelNode) node;
} else {
mEnd = (LabelNode) node;
}
} else {
if (mStart == null) {
throw new RuntimeException(
"Expected instructions of " + cn.name + " : " + mn.name + " " + mn.desc + " to start with a label, got "
+ node.getClass());
}
}
}
Label mStartl = mStart.getLabel();
if (mEnd == null) {
mEnd = new LabelNode(new Label());
mn.instructions.add(mEnd);
}
List<LocalVariableNode> paramsAndThis = new ArrayList<LocalVariableNode>();
for (Object o : mn.localVariables) {
LocalVariableNode lvn = (LocalVariableNode) o;
if (lvn.start.getLabel().equals(mStartl)) {
paramsAndThis.add(lvn);
}
}
int purrSecretIndex = 0;
for (LocalVariableNode lvn : paramsAndThis) {
purrSecretIndex += Type.getType(lvn.desc).getSize();
}
Set<String> lvNames = new HashSet<String>();
for (Object o : mn.localVariables) {
LocalVariableNode lvn = (LocalVariableNode) o;
if (lvn.index >= purrSecretIndex) {
lvn.index = lvn.index + 1;
}
lvNames.add(lvn.name);
}
String purrSecretUniqueName = makeUnique("_purrSecret", lvNames);
mn.localVariables.add(paramsAndThis.size(), new LocalVariableNode(
purrSecretUniqueName, OBJECT_DESC, null, mStart, mEnd,
purrSecretIndex));
mn.maxLocals += 1;
for (Iterator<?> i = mn.instructions.iterator(); i.hasNext();) {
Object current = i.next();
if (current instanceof VarInsnNode) {
VarInsnNode vin = (VarInsnNode) current;
if (vin.var >= purrSecretIndex) {
vin.var = vin.var + 1;
}
}
if (current instanceof IincInsnNode) {
IincInsnNode iin = (IincInsnNode) current;
iin.var = iin.var + 1;
log("Incremented iinc var to " + iin.var);
}
}
InsnList pre = new InsnList();
// pre.add(vStart);
if (isStatic) {
pre.add(new LdcInsnNode(cn.name));
} else {
pre.add(new VarInsnNode(ALOAD, 0)); // "this" is index 0 locvar.
}
pre.add(new MethodInsnNode(INVOKESTATIC, classDesc, BEFORE,
ONE_OBJECT_PARAM + OBJECT_DESC));
pre.add(new VarInsnNode(ASTORE, purrSecretIndex));
pre.add(fStart);
mn.instructions.insert(mStart, pre);
List<AbstractInsnNode> terminalNodes = new ArrayList<AbstractInsnNode>();
for (int i = 0; i < mn.instructions.size(); i++) {
AbstractInsnNode insn = mn.instructions.get(i);
int opcode = insn.getOpcode();
if (isReturnOpcode(opcode)) {
terminalNodes.add(insn);
}
}
LabelNode okReturnLabel = new LabelNode( new Label() );
// LabelNode throwReturnLabel = new LabelNode( new Label() );
Integer returnOpcode = null;
for (AbstractInsnNode ain : terminalNodes) {
// mn.instructions.insertBefore(ain,
// preExitInsns(cn, mn, purrSecretIndex));