MethodEventInstrumentor(MethodEventProducer mep) {
super(mep);
}
public void instrument(JiapiMethod jm) {
InstructionList il = jm.getInstructionList();
InstructionFactory factory = il.getInstructionFactory();
JiapiClass mep = getEventProducer();
JiapiMethod methodEntered = null;
JiapiMethod methodExited = null;
JiapiField jiapiField = getEventProducerField();
// a flag, that tells whether or not InstructionList being
// processed is in a static method.
boolean isStatic = Modifier.isStatic(il.getDeclaringMethod().getModifiers());
try {
methodEntered =
mep.getDeclaredMethod("methodEntered",
new String[] { "java.lang.Object",
"java.lang.String" });
methodExited =
mep.getDeclaredMethod("methodExited",
new String[] { "java.lang.Object",
"java.lang.String" });
}
catch(Exception e) {
System.out.println("ERROR: " + e);
}
// Create instructions for method entrance
InstructionList entryList = il.createEmptyList();
entryList.add(factory.getField(jiapiField));
if (isStatic) {
entryList.add(factory.pushConstant(il.getDeclaringMethod().getDeclaringClass().getName())); // BUG: we should pass a Class
}
else {
entryList.add(factory.pushThis());
}
entryList.add(factory.pushConstant(il.getDeclaringMethod().getName()));
entryList.add(factory.invoke(methodEntered));
// Skip super(....) call, if in <init> method
int superIdx = il.indexOf(Opcodes.INVOKESPECIAL);
// BUG: we should insert entrylist on <clinit> pass the
// __jiapi_field initialization
if (!"<clinit>".equals(il.getDeclaringMethod().getName())) {
// FIXME: See bug above
il.insert(superIdx+1, entryList);
}
else {
int idx = findFieldInitIndex(il, jiapiField);
if (idx != -1) {
il.insert(idx + 1, entryList);
}
}
// Create instructions for method exits
InstructionList exitList = il.createEmptyList();
exitList.add(factory.getField(jiapiField));
if (isStatic) {
exitList.add(factory.pushConstant(il.getDeclaringMethod().getDeclaringClass().getName())); // BUG: we should pass a Class
}
else {
exitList.add(factory.pushThis());
}
exitList.add(factory.pushConstant(il.getDeclaringMethod().getName()));
exitList.add(factory.invoke(methodExited));
// Find all method exits
int idx = il.indexOf(OpcodeGroups.RETURN_INSTRUCTIONS, 0);
while (idx != -1) {
Instruction ins = il.get(idx);
il.insert(idx, exitList);
// Next index. Skip Instructions created above.
idx = il.indexOf(OpcodeGroups.RETURN_INSTRUCTIONS,
idx + exitList.size() + 1);
}
}