/**
   * 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;
  }
  /** Compiles a method that overloads NodeSortRecord.extractValueFromDOM() */
  private static MethodGenerator compileExtract(
      Vector sortObjects,
      NodeSortRecordGenerator sortRecord,
      ConstantPoolGen cpg,
      String className) {
    final InstructionList il = new InstructionList();

    // String NodeSortRecord.extractValueFromDOM(dom,node,level);
    final CompareGenerator extractMethod =
        new CompareGenerator(
            ACC_PUBLIC | ACC_FINAL,
            org.apache.bcel.generic.Type.STRING,
            new org.apache.bcel.generic.Type[] {
              Util.getJCRefType(DOM_INTF_SIG),
              org.apache.bcel.generic.Type.INT,
              org.apache.bcel.generic.Type.INT,
              Util.getJCRefType(TRANSLET_SIG),
              org.apache.bcel.generic.Type.INT
            },
            new String[] {"dom", "current", "level", "translet", "last"},
            "extractValueFromDOM",
            className,
            il,
            cpg);

    // Values needed for the switch statement
    final int levels = sortObjects.size();
    final int match[] = new int[levels];
    final InstructionHandle target[] = new InstructionHandle[levels];
    InstructionHandle tblswitch = null;

    // Compile switch statement only if the key has multiple levels
    if (levels > 1) {
      // Put the parameter to the swtich statement on the stack
      il.append(new ILOAD(extractMethod.getLocalIndex("level")));
      // Append the switch statement here later on
      tblswitch = il.append(new NOP());
    }

    // Append all the cases for the switch statment
    for (int level = 0; level < levels; level++) {
      match[level] = level;
      final Sort sort = (Sort) sortObjects.elementAt(level);
      target[level] = il.append(NOP);
      sort.translateSelect(sortRecord, extractMethod);
      il.append(ARETURN);
    }

    // Compile def. target for switch statement if key has multiple levels
    if (levels > 1) {
      // Append the default target - it will _NEVER_ be reached
      InstructionHandle defaultTarget = il.append(new PUSH(cpg, EMPTYSTRING));
      il.insert(tblswitch, new TABLESWITCH(match, target, defaultTarget));
      il.append(ARETURN);
    }

    return extractMethod;
  }
예제 #3
0
  /**
   * Replace instruction ih in list il with the instructions in new_il. If new_il is null, do
   * nothing
   */
  protected static void replace_instructions(
      InstructionList il, InstructionHandle ih, InstructionList new_il) {

    if ((new_il == null) || new_il.isEmpty()) return;

    // If there is only one new instruction, just replace it in the handle
    if (new_il.getLength() == 1) {
      ih.setInstruction(new_il.getEnd().getInstruction());
      return;
    }

    // Get the start and end instruction of the new instructions
    InstructionHandle new_end = new_il.getEnd();
    InstructionHandle new_start = il.insert(ih, new_il);

    // Move all of the branches from the old instruction to the new start
    il.redirectBranches(ih, new_start);

    // Move other targets to the new instuctions.
    if (ih.hasTargeters()) {
      for (InstructionTargeter it : ih.getTargeters()) {
        if (it instanceof LineNumberGen) {
          it.updateTarget(ih, new_start);
        } else if (it instanceof LocalVariableGen) {
          it.updateTarget(ih, new_end);
        } else if (it instanceof CodeExceptionGen) {
          CodeExceptionGen exc = (CodeExceptionGen) it;
          if (exc.getStartPC() == ih) exc.updateTarget(ih, new_start);
          else if (exc.getEndPC() == ih) exc.updateTarget(ih, new_end);
          else if (exc.getHandlerPC() == ih) exc.setHandlerPC(new_start);
          else System.out.printf("Malformed CodeException: %s%n", exc);
        } else {
          System.out.printf("unexpected target %s%n", it);
        }
      }
    }

    // Remove the old handle.  There should be no targeters left to it.
    try {
      il.delete(ih);
    } catch (Exception e) {
      throw new Error("Can't delete instruction", e);
    }
  }
  /** Adds code in nl to start of method mg * */
  public static void add_to_start(MethodGen mg, InstructionList nl) {

    // Add the code before the first instruction
    InstructionList il = mg.getInstructionList();
    InstructionHandle old_start = il.getStart();
    InstructionHandle new_start = il.insert(nl);

    // Move any LineNumbers and local variable that currently point to
    // the first instruction to include the new instructions. Other
    // targeters (branches, exceptions) should not include the new
    // code
    if (old_start.hasTargeters()) {
      for (InstructionTargeter it : old_start.getTargeters()) {
        if ((it instanceof LineNumberGen) || (it instanceof LocalVariableGen))
          it.updateTarget(old_start, new_start);
      }
    }
    mg.setMaxStack();
    mg.setMaxLocals();
  }