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 HeapNEW extends HeapUtil { // Allocations by NEW are triggered via calls to both visitTypeInsn and // visitMethodInsn(INVOKESPECIAL) where the top of the stack after the first // call to visitTypeInsn contains an uninitialized reference to the newly // allocated object. The reference to the object can only be touched (with // the exception of (DUP/SWAP/POP operations) after it is fully initialized // by the call to visitMethodInsn(INVOKESPECIAL). The top of the stack when // calling visitMethodInsn(INVOKESPECIAL) contains the reference to the // uninitialized newly allocated object and all the parameter values for the // constructor arguments. static void before(boolean debug, boolean trace, MethodAdapter mv, HeapVariables lvs, String signature) { log(debug, trace, mv, "\tNEW.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, String owner) { log(debug, trace, mv, "\tNEW.after"); Label cleanup = new Label(); Label finish = new Label(); if (HeapSettings.conditional) { // STACK: [...|obj] visitCheck(mv, cleanup); // STACK: [...|obj] } // STACK: [...|obj] mv.visitLdcInsn(-1); // STACK: [...|obj|count] mv.visitLdcInsn(owner); // STACK: [...|obj|count|type] mv.visitLdcInsn((long)-1); // STACK: [...|obj|count|type|size] mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/foursquare/heapaudit/HeapUtil", "record", "(Ljava/lang/Object;ILjava/lang/String;J)V"); // STACK: [...] if (HeapSettings.conditional) { visitCleanup(mv, cleanup, finish); // STACK: [...|obj] mv.visitInsn(Opcodes.POP); // STACK: [...] visitFinish(mv, finish); // STACK: [...] } } }