/** * Adds a prefix to the original method. To make it callable only from within the framework * itself. * * @param mg the MethodGen * @param method the current method * @param methodSequence the methods sequence number * @param uuid the definition UUID * @return the modified method */ private Method addPrefixToMethod( final MethodGen mg, final Method method, final int methodSequence, final String uuid) { // change the method access flags (should always be set to protected) int accessFlags = mg.getAccessFlags(); if ((accessFlags & Constants.ACC_PROTECTED) == 0) { // set the protected flag accessFlags |= Constants.ACC_PROTECTED; } if ((accessFlags & Constants.ACC_PRIVATE) != 0) { // clear the private flag accessFlags &= ~Constants.ACC_PRIVATE; } if ((accessFlags & Constants.ACC_PUBLIC) != 0) { // clear the public flag accessFlags &= ~Constants.ACC_PUBLIC; } mg.setName(getPrefixedMethodName(method, methodSequence, mg.getClassName())); mg.setAccessFlags(accessFlags); mg.setMaxStack(); mg.setMaxLocals(); return mg.getMethod(); }
private static void addTimer(ClassGen cgen, Method method) { // set up the construction tools InstructionFactory ifact = new InstructionFactory(cgen); InstructionList ilist = new InstructionList(); ConstantPoolGen pgen = cgen.getConstantPool(); String cname = cgen.getClassName(); MethodGen wrapgen = new MethodGen(method, cname, pgen); wrapgen.setInstructionList(ilist); // rename a copy of the original method MethodGen methgen = new MethodGen(method, cname, pgen); cgen.removeMethod(method); String iname = methgen.getName() + "_timing"; methgen.setName(iname); cgen.addMethod(methgen.getMethod()); Type result = methgen.getReturnType(); // compute the size of the calling parameters Type[] parameters = methgen.getArgumentTypes(); int stackIndex = methgen.isStatic() ? 0 : 1; for (int i = 0; i < parameters.length; i++) { stackIndex += parameters[i].getSize(); } // save time prior to invocation ilist.append( ifact.createInvoke( "java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory.createStore(Type.LONG, stackIndex)); // call the wrapped method int offset = 0; short invoke = Constants.INVOKESTATIC; if (!methgen.isStatic()) { ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0)); offset = 1; invoke = Constants.INVOKEVIRTUAL; } for (int i = 0; i < parameters.length; i++) { Type type = parameters[i]; ilist.append(InstructionFactory.createLoad(type, offset)); offset += type.getSize(); } ilist.append(ifact.createInvoke(cname, iname, result, parameters, invoke)); // store result for return later if (result != Type.VOID) { ilist.append(InstructionFactory.createStore(result, stackIndex + 2)); } // print time required for method call ilist.append( ifact.createFieldAccess( "java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); ilist.append(InstructionConstants.DUP); ilist.append(InstructionConstants.DUP); String text = "Call to method " + methgen.getName() + " took "; ilist.append(new PUSH(pgen, text)); ilist.append( ifact.createInvoke( "java.io.PrintStream", "print", Type.VOID, new Type[] {Type.STRING}, Constants.INVOKEVIRTUAL)); ilist.append( ifact.createInvoke( "java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory.createLoad(Type.LONG, stackIndex)); ilist.append(InstructionConstants.LSUB); ilist.append( ifact.createInvoke( "java.io.PrintStream", "print", Type.VOID, new Type[] {Type.LONG}, Constants.INVOKEVIRTUAL)); ilist.append(new PUSH(pgen, " ms.")); ilist.append( ifact.createInvoke( "java.io.PrintStream", "println", Type.VOID, new Type[] {Type.STRING}, Constants.INVOKEVIRTUAL)); // return result from wrapped method call if (result != Type.VOID) { ilist.append(InstructionFactory.createLoad(result, stackIndex + 2)); } ilist.append(InstructionFactory.createReturn(result)); // finalize the constructed method wrapgen.stripAttributes(true); wrapgen.setMaxStack(); wrapgen.setMaxLocals(); cgen.addMethod(wrapgen.getMethod()); ilist.dispose(); }