Ejemplo n.º 1
0
 private Instruction createInvokeInstruction(Element inst, short kind)
     throws IllegalXMLVMException {
   String classType = inst.getAttributeValue("class-type");
   String methodName = inst.getAttributeValue("method");
   Element signature = inst.getChild("signature", nsXMLVM);
   Type retType = collectReturnType(signature);
   Type[] argTypes = collectArgumentTypes(signature);
   return _factory.createInvoke(classType, methodName, retType, argTypes, kind);
 }
Ejemplo n.º 2
0
  private void generateInvokeEntryPoint(
      GenScope scope,
      InstructionList il,
      InstructionFactory ifact,
      String transformationName,
      String entryPointName,
      LocalVariableGen lvg) {

    // Configure the transformation
    il.append(InstructionFactory.DUP);
    il.append(
        ifact.createInvoke(
            DefaultTypes.IdcTransformation.getClassName(),
            "configure_",
            Type.VOID,
            new Type[] {},
            Constants.INVOKEVIRTUAL));
    // TODO: Configure the models properly, not as I'm doing directly in instantiateTransformation
    // directly

    // Put the params into the stack and invoke, but first check the type of the transformation
    // object
    ObjectType transformationType = new ObjectType(transformationName);
    il.append(ifact.createCheckCast(transformationType));
    // [Transformation, param1, ..., paramN]
    EList<Variable> params = this.getEntryPointParameters();
    Type[] types = new Type[params.size()];
    int i = 0;
    for (Variable variable : params) {
      scope.loadVariable(variable, il);
      types[i++] = Type.OBJECT;
    }
    il.append(
        ifact.createInvoke(
            transformationType.getClassName(),
            entryPointName,
            Type.OBJECT,
            types,
            Constants.INVOKEVIRTUAL));

    il.append(new ASTORE(lvg.getIndex()));
  }
Ejemplo n.º 3
0
  private Method generateSuperAccessor(
      ConstantPoolGen cpg,
      String className,
      SuperMethodDescriptor superMethod,
      InstructionFactory factory) {
    int endPos = superMethod.signature.indexOf(')');
    String segment = superMethod.signature.substring(1, endPos);
    String[] typeNames = (segment.length() > 0) ? segment.split(",") : new String[0];
    Type[] argTypes = new Type[typeNames.length];
    for (int i = 0; i < argTypes.length; i++) argTypes[i] = Type.getType(typeNames[i]);

    int index = superMethod.signature.lastIndexOf(')') + 1;
    Type returnType = Type.getType(superMethod.signature.substring(index));

    Type baseType = new ObjectType(className);
    Type[] wrapperTypes = new Type[argTypes.length + 1];
    System.arraycopy(argTypes, 0, wrapperTypes, 1, argTypes.length);
    wrapperTypes[0] = baseType;
    String[] argNames = new String[wrapperTypes.length];
    for (int i = 0; i < argNames.length; i++) {
      argNames[i] = "arg" + i;
    }
    InstructionList il = new InstructionList();
    MethodGen mg =
        new MethodGen(
            (Constants.ACC_PUBLIC | Constants.ACC_STATIC),
            returnType,
            wrapperTypes,
            argNames,
            OT_PREFIX + superMethod.methodName + "$super",
            className,
            il,
            cpg);
    il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is base instance
    for (int i = 0; i < argTypes.length; i++)
      il.append(InstructionFactory.createLoad(argTypes[i], i + 1));

    // if super method is also callin bound directly invoke the orig-version
    // (to avoid that BaseMethodTransformation.checkReplaceWickedSuper() has to rewrite this code
    // again):
    String methodName =
        (CallinBindingManager.isBoundBaseMethod(
                superMethod.superClass, superMethod.methodName, superMethod.signature))
            ? genOrigMethName(superMethod.methodName)
            : superMethod.methodName;

    il.append(
        factory.createInvoke(
            superMethod.superClass, methodName, returnType, argTypes, INVOKESPECIAL));
    il.append(InstructionFactory.createReturn(returnType));
    mg.setMaxStack();
    mg.setMaxLocals();
    return mg.getMethod();
  }
  /**
   * Transforms the init method to create the newly added join point member field.
   *
   * @param cp the ConstantPoolGen
   * @param cg the ClassGen
   * @param init the constructor for the class
   * @param method the current method
   * @param factory the objectfactory
   * @param methodSequence the methods sequence number
   * @return the modified constructor
   */
  private MethodGen createJoinPointField(
      final ConstantPoolGen cp,
      final ClassGen cg,
      final Method init,
      final Method method,
      final InstructionFactory factory,
      final int methodSequence) {

    final MethodGen mg = new MethodGen(init, cg.getClassName(), cp);
    final InstructionList il = mg.getInstructionList();
    final InstructionHandle[] ihs = il.getInstructionHandles();

    // grab the handle to the the return instruction of the constructor
    InstructionHandle ih = ihs[0];
    for (int i = 0; i < ihs.length; i++) {
      Instruction instruction = ihs[i].getInstruction();
      if (instruction instanceof ReturnInstruction) {
        ih = ihs[i]; // set the instruction handle to the return instruction
        break;
      }
    }

    final String joinPoint = getJoinPointName(method, methodSequence);

    final InstructionHandle ihPost;
    ihPost = il.insert(ih, factory.createLoad(Type.OBJECT, 0));
    il.insert(ih, factory.createNew(TransformationUtil.THREAD_LOCAL_CLASS));

    il.insert(ih, InstructionConstants.DUP);

    il.insert(
        ih,
        factory.createInvoke(
            TransformationUtil.THREAD_LOCAL_CLASS,
            "<init>",
            Type.VOID,
            new Type[] {},
            Constants.INVOKESPECIAL));

    il.insert(
        ih,
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint,
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.PUTFIELD));
    il.redirectBranches(ih, ihPost);

    mg.setMaxStack();
    mg.setMaxLocals();

    return mg;
  }
Ejemplo n.º 5
0
  private void createMethod_0() {
    InstructionList il = new InstructionList();
    MethodGen method =
        new MethodGen(
            ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[] {}, "<init>", objectType, il, _cp);

    InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
    il.append(
        _factory.createInvoke(
            "java.lang.Object", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
    InstructionHandle ih_4 = il.append(_factory.createReturn(Type.VOID));
    method.setMaxStack();
    method.setMaxLocals();
    _cg.addMethod(method.getMethod());
    il.dispose();
  }
Ejemplo n.º 6
0
  @Override
  public void generate(GenScope scope) {
    InstructionList il = scope.getInstructionList();
    InstructionFactory ifact = scope.getInstructionFactory();
    ConstantPoolGen cpg = scope.getConstantPool();

    String transformationName = this.getTransformationName();
    String entryPointName = this.getEntryPointName();

    LocalVariableGen lvg = scope.newLocalVariable(this, Type.OBJECT);

    // Probably this could be improved, but for the moment a transformation
    // object will provide a facility to instantiate another transformation

    // Create the new transformation
    // [This_Transformation, "TransformationName"] -> instantiateTransformation ->
    // [Created_Transformation]
    scope.generateGetTransformation();
    il.append(ifact.createConstant(transformationName));
    il.append(
        ifact.createInvoke(
            DefaultTypes.IdcTransformation.getClassName(),
            "instantiateTransformation",
            DefaultTypes.IdcTransformation,
            new Type[] {Type.STRING},
            Constants.INVOKEVIRTUAL));

    // There are two cases
    //
    // 1. Explicit invocation of a transformation rule

    if (entryPointName != null) {
      generateInvokeEntryPoint(scope, il, ifact, transformationName, entryPointName, lvg);
    } else {
      generateInvokeTransformation(scope, il, ifact, transformationName, lvg);
    }
  }
Ejemplo n.º 7
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();
  }
Ejemplo n.º 8
0
  /**
   * Transforms invoke instructions that match the specified list for this class to call the
   * specified static call instead.
   */
  private InstructionList xform_inst(MethodGen mg, Instruction inst) {

    switch (inst.getOpcode()) {
      case Constants.INVOKESTATIC:
        {
          InstructionList il = new InstructionList();
          INVOKESTATIC is = (INVOKESTATIC) inst;
          String cname = is.getClassName(pgen);
          String mname = is.getMethodName(pgen);
          Type[] args = is.getArgumentTypes(pgen);
          MethodDef orig = new MethodDef(cname + "." + mname, args);
          MethodInfo call = method_map.get(orig);
          if (call != null) {
            call.cnt++;
            String classname = call.method_class;
            String methodname = mname;
            debug_map.log(
                "%s.%s: Replacing method %s.%s (%s) with %s.%s%n",
                mg.getClassName(),
                mg.getName(),
                cname,
                mname,
                UtilMDE.join(args, ", "),
                classname,
                methodname);
            il.append(
                ifact.createInvoke(
                    classname, methodname, is.getReturnType(pgen), args, Constants.INVOKESTATIC));
          }
          return (il);
        }

      case Constants.INVOKEVIRTUAL:
        {
          InstructionList il = new InstructionList();
          INVOKEVIRTUAL iv = (INVOKEVIRTUAL) inst;
          String cname = iv.getClassName(pgen);
          String mname = iv.getMethodName(pgen);
          Type[] args = iv.getArgumentTypes(pgen);
          Type instance_type = iv.getReferenceType(pgen);
          Type[] new_args = BCELUtil.insert_type(instance_type, args);
          MethodDef orig = new MethodDef(cname + "." + mname, args);
          if (debug_class) System.out.printf("looking for %s in map %s%n", orig, method_map);
          MethodInfo call = method_map.get(orig);
          if (call != null) {
            call.cnt++;
            String classname = call.method_class;
            String methodname = mname;
            debug_map.log(
                "Replacing method %s.%s (%s) with %s.%s%n",
                cname, mname, ArraysMDE.toString(args), classname, methodname);
            il.append(
                ifact.createInvoke(
                    classname,
                    methodname,
                    iv.getReturnType(pgen),
                    new_args,
                    Constants.INVOKESTATIC));
          }
          return (il);
        }

      default:
        return (null);
    }
  }
Ejemplo n.º 9
0
  private void generateInvokeTransformation(
      GenScope scope,
      InstructionList il,
      InstructionFactory ifact,
      String transformationName,
      LocalVariableGen lvg) {
    il.append(InstructionFactory.DUP);
    il.append(InstructionFactory.DUP);
    il.append(InstructionFactory.DUP);

    // Configure the invoked transformation: view filter
    scope.loadVariable(this.getInputViewFilter(), il);
    il.append(
        ifact.createInvoke(
            DefaultTypes.IdcTransformation.getClassName(),
            "configure_invocation_",
            Type.VOID,
            new Type[] {DefaultTypes.RunnableClosure},
            Constants.INVOKEVIRTUAL));

    // Configure the transformation
    il.append(InstructionFactory.DUP);
    il.append(
        ifact.createInvoke(
            DefaultTypes.IdcTransformation.getClassName(),
            "configure_",
            Type.VOID,
            new Type[] {},
            Constants.INVOKEVIRTUAL));

    // Set parameters
    for (NamedInvocationParameter p : this.getParameters()) {
      il.append(InstructionFactory.DUP);
      il.append(ifact.createConstant(p.getFormalName()));
      scope.loadVariable(p.getResult(), il);
      il.append(
          ifact.createInvoke(
              DefaultTypes.IdcTransformation.getClassName(),
              "setParameterValue",
              Type.VOID,
              new Type[] {Type.STRING, Type.OBJECT},
              Constants.INVOKEVIRTUAL));
    }

    // Start the transformation
    il.append(
        ifact.createInvoke(
            DefaultTypes.IdcTransformation.getClassName(),
            "start_",
            Type.VOID,
            new Type[] {},
            Constants.INVOKEVIRTUAL));

    // Get a target element from a trace
    if (this.getOutputResolutionSourceElement() != null) {
      scope.loadVariable(this.getOutputResolutionSourceElement(), il);
      il.append(ifact.createConstant(this.getQueueName()));
      il.append(ifact.createConstant(this.getSrcTraceAttributeName()));
      il.append(ifact.createConstant(this.getTgtTraceAttributeName()));
      il.append(
          ifact.createInvoke(
              DefaultTypes.IdcTransformation.getClassName(),
              "retrieve_from_invocation_",
              Type.OBJECT,
              new Type[] {Type.OBJECT, Type.STRING, Type.STRING, Type.STRING},
              Constants.INVOKEVIRTUAL));
    } else {
      il.append(InstructionFactory.ACONST_NULL);
    }

    il.append(new ASTORE(lvg.getIndex()));
  }
Ejemplo n.º 10
0
  @Override
  public void generate(GenScope scope) {
    InstructionList il = scope.getInstructionList();
    InstructionFactory ifact = scope.getInstructionFactory();
    ConstantPoolGen cpg = scope.getConstantPool();

    LocalVariableGen lvg = scope.newLocalVariable(this, Type.OBJECT);

    // TODO: I'm going to assume that there is an optional kindOf and
    //       and p() predicate.
    if (this.getPredicates().size() > 2)
      throw new UnsupportedOperationException("QMatchJVMGen. Only 2 fixed predicates implemented.");

    KindOfPredicate kindOf = null;
    PropertyEqualsPredicate prop = null;

    if (getPredicates().get(0) instanceof KindOfPredicate) {
      kindOf = (KindOfPredicate) getPredicates().get(0);
      prop = (PropertyEqualsPredicate) getPredicates().get(1);
    } else {
      prop = (PropertyEqualsPredicate) getPredicates().get(0);
    }

    // Create the object, then the parameters of the constructor
    String requestClass = "org.eclectic.idc.jvm.runtime.RequestKindProperty";
    il.append(ifact.createNew(requestClass));
    il.append(InstructionConstants.DUP);

    scope.generateGetModelManager();
    if (kindOf == null) {
      il.append(InstructionConstants.ACONST_NULL);
    } else {
      ReadMetaJVMGen readMeta = new ReadMetaJVMGen();
      readMeta.setClassName(kindOf.getClassName());
      readMeta.setModel(kindOf.getModel());
      readMeta.setName("_readMeta_for" + getName());

      readMeta.setFile(this.getFile());
      readMeta.setColumn(this.getColumn());
      readMeta.setRow(this.getRow());

      readMeta.generate(scope);
      scope.loadVariable(readMeta, il);
    }

    il.append(ifact.createConstant(prop.getPropertyName()));
    scope.loadVariable(prop.getValue(), il);
    // In the stack: IdcMetaclass, featureName, value + receptor x 2

    il.append(
        ifact.createInvoke(
            requestClass,
            "<init>",
            Type.VOID,
            new Type[] {
              DefaultTypes.ModelManager, DefaultTypes.IdcMetaclass, Type.STRING, Type.OBJECT
            },
            Constants.INVOKESPECIAL));

    if (getGetterClosure() != null) {
      il.append(InstructionConstants.DUP);
      scope.loadVariable(getGetterClosure(), il);
      il.append(
          ifact.createInvoke(
              requestClass,
              "setGetterClosure",
              Type.VOID,
              new Type[] {DefaultTypes.IClosure},
              Constants.INVOKEVIRTUAL));
    }

    // Generate debug info
    il.append(InstructionConstants.DUP);
    if (getFile() == null) {
      il.append(InstructionConstants.ACONST_NULL);
    } else {
      il.append(ifact.createConstant(getFile()));
    }
    il.append(ifact.createConstant(getRow()));
    il.append(ifact.createConstant(getColumn()));
    il.append(
        ifact.createInvoke(
            requestClass,
            "setDebugInfo",
            Type.VOID,
            new Type[] {Type.STRING, Type.INT, Type.INT},
            Constants.INVOKEVIRTUAL));
    // End-of debug info

    QueueJVMGen jvmQ = (QueueJVMGen) getQueue();
    CommonGen.generateGetQueue(scope, jvmQ);
    il.append(InstructionConstants.SWAP);

    il.append(
        ifact.createInvoke(
            DefaultTypes.ContinuationResolverHelper.getClassName(),
            "requestAndWait",
            Type.OBJECT,
            new Type[] {DefaultTypes.HistoryQueue, DefaultTypes.IRequest},
            Constants.INVOKESTATIC));

    // il.append(ifact.createInvoke(jvmQ.getClassName(),
    //		"requestAndWait", Type.OBJECT, new Type[] { DefaultTypes.IRequest },
    // Constants.INVOKEVIRTUAL));

    // il.append(InstructionConstants.DUP);
    // CommonGen.print(il, ifact);

    il.append(new ASTORE(lvg.getIndex()));
  }
  /**
   * Creates a proxy method for the original method specified. This method has the same signature as
   * the original method and catches the invocation for further processing by the framework before
   * redirecting to the original method.
   *
   * @todo pass the 'class' as a Class instance not a String to the join point. Add the class field
   *     to the class using BCEL (see AdviseStaticMethodTransformer.java)
   * @param cp the ConstantPoolGen
   * @param cg the ClassGen
   * @param originalMethod the current method
   * @param factory the objectfactory
   * @param methodId the id of the current method in the lookup tabl
   * @param methodSequence the methods sequence number
   * @param accessFlags the access flags of the original method
   * @param uuid the uuid for the weave model defining the pointcut
   * @param controllerClassName the class name of the controller class to use
   * @return the proxy method
   */
  private Method createProxyMethod(
      final ConstantPoolGen cp,
      final ClassGen cg,
      final MethodGen originalMethod,
      final InstructionFactory factory,
      final int methodId,
      final int methodSequence,
      final int accessFlags,
      final String uuid,
      final String controllerClassName) {

    InstructionList il = new InstructionList();

    String joinPoint = getJoinPointName(originalMethod.getMethod(), methodSequence);

    final MethodGen method =
        new MethodGen(
            accessFlags,
            Type.getReturnType(originalMethod.getSignature()),
            Type.getArgumentTypes(originalMethod.getSignature()),
            originalMethod.getArgumentNames(),
            originalMethod.getName(),
            cg.getClassName(),
            il,
            cp);

    String[] exceptions = originalMethod.getExceptions();
    for (int i = 0; i < exceptions.length; i++) {
      method.addException(exceptions[i]);
    }

    int indexParam = 1;
    int indexStack = 0;
    int indexJoinPoint = Type.getArgumentTypes(originalMethod.getSignature()).length * 2 + 1;

    // if (threadLocal == null) {
    //    threadLocal = new SerializableThreadLocal();
    // }
    il.append(factory.createLoad(Type.OBJECT, 0));
    il.append(
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint,
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.GETFIELD));

    BranchInstruction ifNotNull = factory.createBranchInstruction(Constants.IFNONNULL, null);
    il.append(ifNotNull);
    il.append(factory.createLoad(Type.OBJECT, 0));
    il.append(factory.createNew(TransformationUtil.THREAD_LOCAL_CLASS));

    il.append(InstructionConstants.DUP);
    il.append(
        factory.createInvoke(
            TransformationUtil.THREAD_LOCAL_CLASS,
            "<init>",
            Type.VOID,
            Type.NO_ARGS,
            Constants.INVOKESPECIAL));
    il.append(
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint.toString(),
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.PUTFIELD));

    // Object joinPoint = ___jp.get();
    BranchInstruction biIfNotNull = null;
    InstructionHandle ihIfNotNull = null;

    ifNotNull.setTarget(il.append(factory.createLoad(Type.OBJECT, 0)));

    il.append(
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint.toString(),
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.GETFIELD));
    il.append(
        factory.createInvoke(
            TransformationUtil.THREAD_LOCAL_CLASS,
            "get",
            Type.OBJECT,
            Type.NO_ARGS,
            Constants.INVOKEVIRTUAL));

    il.append(factory.createStore(Type.OBJECT, indexJoinPoint));
    il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));

    // if (joinPoint == null) {
    biIfNotNull = factory.createBranchInstruction(Constants.IFNONNULL, null);
    il.append(biIfNotNull);

    // joinPoint = new WeakReference(new MemberMethodJoinPoint(uuid, this, "foo.bar.Baz", 10));
    //        il.append(factory.createNew(TransformationUtil.WEAK_REFERENCE_CLASS));
    //        il.append(InstructionConstants.DUP);

    il.append(factory.createNew(TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS));
    il.append(InstructionConstants.DUP);

    il.append(new PUSH(cp, uuid));
    il.append(factory.createLoad(Type.OBJECT, 0));
    il.append(new PUSH(cp, cg.getClassName()));
    il.append(new PUSH(cp, methodId));
    il.append(new PUSH(cp, controllerClassName));

    il.append(
        factory.createInvoke(
            TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS,
            "<init>",
            Type.VOID,
            new Type[] {Type.STRING, Type.OBJECT, Type.STRING, Type.INT, Type.STRING},
            Constants.INVOKESPECIAL));
    il.append(factory.createStore(Type.OBJECT, indexJoinPoint));

    // threadLocal.set(joinPoint);
    il.append(factory.createLoad(Type.OBJECT, 0));
    il.append(
        factory.createFieldAccess(
            cg.getClassName(),
            joinPoint.toString(),
            new ObjectType(TransformationUtil.THREAD_LOCAL_CLASS),
            Constants.GETFIELD));
    il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));
    il.append(
        factory.createInvoke(
            TransformationUtil.THREAD_LOCAL_CLASS,
            "set",
            Type.VOID,
            new Type[] {Type.OBJECT},
            Constants.INVOKEVIRTUAL));

    ihIfNotNull = il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));
    indexJoinPoint += 2;

    il.append(factory.createCheckCast(TransformationUtil.MEMBER_METHOD_JOIN_POINT_TYPE));
    il.append(factory.createStore(Type.OBJECT, indexJoinPoint));

    biIfNotNull.setTarget(ihIfNotNull);

    // if we have parameters, wrap them up
    if (Type.getArgumentTypes(originalMethod.getSignature()).length != 0) {

      // create and allocate the parameters array
      il.append(new PUSH(cp, Type.getArgumentTypes(originalMethod.getSignature()).length));
      il.append(factory.createNewArray(Type.OBJECT, (short) 1));

      il.append(InstructionConstants.DUP);
      il.append(new PUSH(cp, indexStack));
      indexStack++;

      // add all the parameters, wrap the primitive types in their object counterparts
      for (int count = 0;
          count < Type.getArgumentTypes(originalMethod.getSignature()).length;
          count++) {

        String wrapperClass = null;
        BasicType type = null;
        boolean hasLongOrDouble = false;

        if (Type.getArgumentTypes(originalMethod.getSignature())[count] instanceof ObjectType
            || Type.getArgumentTypes(originalMethod.getSignature())[count] instanceof ArrayType) {
          // we have an object or an array
          il.append(factory.createLoad(Type.OBJECT, indexParam));
          il.append(InstructionConstants.AASTORE);
          indexParam++;
        } else if (Type.getArgumentTypes(originalMethod.getSignature())[count]
            instanceof ArrayType) {
          // we have an array
          il.append(factory.createLoad(Type.OBJECT, indexParam));
          il.append(InstructionConstants.AASTORE);
          indexParam++;
        } else if (Type.getArgumentTypes(originalMethod.getSignature())[count]
            instanceof BasicType) {
          hasLongOrDouble = false;
          // we have a primitive type
          if ((Type.getArgumentTypes(originalMethod.getSignature())[count]).equals(Type.LONG)) {
            wrapperClass = "java.lang.Long";
            type = Type.LONG;
            hasLongOrDouble = true;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.INT)) {
            wrapperClass = "java.lang.Integer";
            type = Type.INT;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.SHORT)) {
            wrapperClass = "java.lang.Short";
            type = Type.SHORT;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.DOUBLE)) {
            wrapperClass = "java.lang.Double";
            type = Type.DOUBLE;
            hasLongOrDouble = true;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.FLOAT)) {
            wrapperClass = "java.lang.Float";
            type = Type.FLOAT;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.CHAR)) {
            wrapperClass = "java.lang.Character";
            type = Type.CHAR;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.BYTE)) {
            wrapperClass = "java.lang.Byte";
            type = Type.BYTE;
          } else if ((Type.getArgumentTypes(originalMethod.getSignature())[count])
              .equals(Type.BOOLEAN)) {
            wrapperClass = "java.lang.Boolean";
            type = Type.BOOLEAN;
          } else {
            throw new RuntimeException(
                "unknown parameter type: "
                    + Type.getArgumentTypes(originalMethod.getSignature())[count]);
          }
          il.append(factory.createNew(wrapperClass));
          il.append(InstructionConstants.DUP);
          il.append(factory.createLoad(type, indexParam));
          il.append(
              factory.createInvoke(
                  wrapperClass, "<init>", Type.VOID, new Type[] {type}, Constants.INVOKESPECIAL));
          il.append(InstructionConstants.AASTORE);
          indexParam++;
        } // end handle basic or object type

        if (count != Type.getArgumentTypes(originalMethod.getSignature()).length - 1) {
          // if we don't have the last parameter, create the parameter on the stack
          il.append(InstructionConstants.DUP);
          il.append(new PUSH(cp, indexStack));
          indexStack++;

          // long or double needs two registers to fit
          if (hasLongOrDouble) indexParam++;
        }
      }

      // create the object array
      il.append(factory.createStore(Type.OBJECT, indexParam));

      // if threadsafe grab the newly retrieved local join point field from the stack
      il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));

      // invoke joinPoint.setParameter(..)
      il.append(factory.createLoad(Type.OBJECT, indexParam));
      il.append(
          factory.createInvoke(
              TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS,
              "setParameters",
              Type.VOID,
              new Type[] {new ArrayType(Type.OBJECT, 1)},
              Constants.INVOKEVIRTUAL));
      indexParam++;
    } // end - if parameters.length != 0

    // if threadsafe grab the newly retrieved local join point field from the stack
    il.append(factory.createLoad(Type.OBJECT, indexJoinPoint));
    il.append(
        factory.createInvoke(
            TransformationUtil.MEMBER_METHOD_JOIN_POINT_CLASS,
            "proceed",
            Type.OBJECT,
            Type.NO_ARGS,
            Constants.INVOKEVIRTUAL));

    if (!Type.getReturnType(originalMethod.getSignature()).equals(Type.VOID)) {
      // create the result from the invocation
      il.append(factory.createStore(Type.OBJECT, indexParam));
      il.append(factory.createLoad(Type.OBJECT, indexParam));

      // cast the result and return it, if the return type is a
      // primitive type, retrieve it from the wrapped object first
      // unless the return object is null (AW-100)
      if (Type.getReturnType(originalMethod.getSignature()) instanceof BasicType) {
        if (Type.getReturnType(originalMethod.getSignature()).equals(Type.VOID)) {; // skip
        } else {
          BranchInstruction ifNullBranch =
              factory.createBranchInstruction(Constants.IFNONNULL, null);
          InstructionHandle elseBranch = null;
          il.append(ifNullBranch);
          if (Type.getReturnType(originalMethod.getSignature()).equals(Type.LONG)) {
            il.append(new PUSH(cp, 0L));
            il.append(factory.createReturn(Type.LONG));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Long")));
            il.append(
                factory.createInvoke(
                    "java.lang.Long",
                    "longValue",
                    Type.LONG,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.INT)) {
            il.append(new PUSH(cp, 0));
            il.append(factory.createReturn(Type.INT));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Integer")));
            il.append(
                factory.createInvoke(
                    "java.lang.Integer",
                    "intValue",
                    Type.INT,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.SHORT)) {
            il.append(new PUSH(cp, (short) 0));
            il.append(factory.createReturn(Type.SHORT));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Short")));
            il.append(
                factory.createInvoke(
                    "java.lang.Short",
                    "shortValue",
                    Type.SHORT,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.DOUBLE)) {
            il.append(new PUSH(cp, 0.0d));
            il.append(factory.createReturn(Type.DOUBLE));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Double")));
            il.append(
                factory.createInvoke(
                    "java.lang.Double",
                    "doubleValue",
                    Type.DOUBLE,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.FLOAT)) {
            il.append(new PUSH(cp, 0.0f));
            il.append(factory.createReturn(Type.FLOAT));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Float")));
            il.append(
                factory.createInvoke(
                    "java.lang.Float",
                    "floatValue",
                    Type.FLOAT,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.CHAR)) {
            il.append(new PUSH(cp, '\u0000'));
            il.append(factory.createReturn(Type.CHAR));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Character")));
            il.append(
                factory.createInvoke(
                    "java.lang.Character",
                    "charValue",
                    Type.CHAR,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.BYTE)) {
            il.append(new PUSH(cp, (byte) 0));
            il.append(factory.createReturn(Type.BYTE));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Byte")));
            il.append(
                factory.createInvoke(
                    "java.lang.Byte",
                    "byteValue",
                    Type.BYTE,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else if (Type.getReturnType(originalMethod.getSignature()).equals(Type.BOOLEAN)) {
            il.append(new PUSH(cp, false));
            il.append(factory.createReturn(Type.BOOLEAN));
            elseBranch = il.append(factory.createLoad(Type.OBJECT, indexParam));
            il.append(factory.createCheckCast(new ObjectType("java.lang.Boolean")));
            il.append(
                factory.createInvoke(
                    "java.lang.Boolean",
                    "booleanValue",
                    Type.BOOLEAN,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
          } else {
            throw new Error(
                "unknown return type: " + Type.getReturnType(originalMethod.getSignature()));
          }
          ifNullBranch.setTarget(elseBranch);
        }
      } else {
        // cast the result to the right type
        il.append(
            factory.createCast(Type.OBJECT, Type.getReturnType(originalMethod.getSignature())));
      }
    }
    il.append(factory.createReturn(Type.getReturnType(originalMethod.getSignature())));

    method.setMaxStack();
    method.setMaxLocals();
    return method.getMethod();
  }