/**
   * 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();
  }
예제 #2
0
  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();
  }