/**
   * 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;
  }
Exemplo n.º 2
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()));
  }
Exemplo n.º 3
0
 public Instruction createInstructionNew(Element inst) {
   String t = inst.getAttributeValue("type");
   return _factory.createNew(t);
 }
  /**
   * 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();
  }