package com.foursquare.heapaudit;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
class HeapThreaded extends HeapUtil {
// Before the init method of java/lang/Thread is called, duplicate the
// thread object reference on the stack. Immediately after the init method
// has been called, extend the recorders on the local thread such that the
// child thread can continue with the same set of recorders. The top of the
// stack when calling visitMethodInsn(INVOKESPECIAL) contains the reference
// to the newly allocated object and all the parameter values for the method
// arguments.
static void before(boolean debug,
boolean trace,
MethodAdapter mv,
HeapVariables lvs,
String signature) {
log(debug,
trace,
mv,
"\tThreaded.before");
Type[] args = Type.getArgumentTypes(signature);
int[] vars = new int[args.length];
Label start = new Label();
Label end = new Label();
mv.visitLabel(start);
for (int i = args.length - 1; i >= 0; --i) {
vars[i] = lvs.define(args[i],
start,
end);
// STACK [...|obj|...|arg]
mv.visitVarInsn(args[i].getOpcode(Opcodes.ISTORE),
vars[i]);
// STACK [...|obj|...]
}
// STACK [...|obj]
mv.visitInsn(Opcodes.DUP);
// STACK [...|obj|obj]
for (int i = 0; i < args.length; ++i) {
// STACK [...|obj|obj|...]
mv.visitVarInsn(args[i].getOpcode(Opcodes.ILOAD),
vars[i]);
// STACK [...|obj|obj|...|arg]
}
mv.visitLabel(end);
}
static void after(boolean debug,
boolean trace,
MethodAdapter mv) {
log(debug,
trace,
mv,
"\tThreaded.after");
// STACK: [...|obj]
mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
"java/lang/Thread",
"getId",
"()J");
// STACK: [...|id]
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/foursquare/heapaudit/HeapUtil",
"extend",
"(J)V");
// STACK: [...]
}
}