Package org.aspectj.apache.bcel.generic

Examples of org.aspectj.apache.bcel.generic.Type


    // Add an accessor for this new field, the
    // ajc$<aspectname>$localAspectOf() method
    // e.g.
    // "public com_blah_SecurityAspect ajc$com_blah_SecurityAspect$localAspectOf()"
    Type fieldType = BcelWorld.makeBcelType(aspectType);
    LazyMethodGen mg = new LazyMethodGen(Modifier.PUBLIC | Modifier.STATIC, fieldType, NameMangler
        .perTypeWithinLocalAspectOf(aspectType), new Type[0], new String[0], gen);
    InstructionList il = new InstructionList();
    // PTWIMPL ?? Should check if it is null and throw
    // NoAspectBoundException
View Full Code Here


          body.append(InstructionFactory.createThis());
          pos++;
        }
        Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
        for (int i = 0, len = paramTypes.length; i < len; i++) {
          Type paramType = paramTypes[i];
          body.append(InstructionFactory.createLoad(paramType, pos));
          pos += paramType.getSize();
        }
        body.append(Utility.createInvoke(fact, classWeaver.getWorld(), interMethodBody));
        body.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(mangledInterMethod.getReturnType())));

        if (classWeaver.getWorld().isInJava5Mode()) { // Don't need bridge
          // methods if not in
          // 1.5 mode.
          createAnyBridgeMethodsForCovariance(classWeaver, munger, unMangledInterMethod, onType, classGen, paramTypes);
        }

      } else {
        // ??? this is okay
        // if (!(mg.getBody() == null)) throw new
        // RuntimeException("bas");
      }

      if (world.isInJava5Mode()) {
        String basicSignature = mangledInterMethod.getSignature();
        String genericSignature = ((ResolvedMemberImpl) mangledInterMethod).getSignatureForAttribute();
        if (!basicSignature.equals(genericSignature)) {
          // Add a signature attribute to it
          newMethod.addAttribute(createSignatureAttribute(classGen.getConstantPool(), genericSignature));
        }
      }
      // XXX make sure to check that we set exceptions properly on this
      // guy.
      classWeaver.addLazyMethodGen(newMethod);
      classWeaver.getLazyClassGen().warnOnAddedMethod(newMethod.getMethod(), getSignature().getSourceLocation());

      addNeededSuperCallMethods(classWeaver, onType, munger.getSuperMethodsCalled());

      return true;

    } else if (onInterface && !Modifier.isAbstract(unMangledInterMethod.getModifiers())) {

      // This means the 'gen' should be the top most implementor
      // - if it is *not* then something went wrong after we worked
      // out that it was the top most implementor (see pr49657)
      if (!classGen.getType().isTopmostImplementor(onType)) {
        ResolvedType rtx = classGen.getType().getTopmostImplementor(onType);
        if (rtx == null) {
          // pr302460
          // null means there is something wrong with what we are looking at
          ResolvedType rt = classGen.getType();
          if (rt.isInterface()) {
            ISourceLocation sloc = munger.getSourceLocation();
            classWeaver.getWorld().getMessageHandler().handleMessage(
                MessageUtil.error("ITD target " + rt.getName()
                    + " is an interface but has been incorrectly determined to be the topmost implementor of "
                    + onType.getName() + ". ITD is " + this.getSignature(), sloc));
          }
          if (!onType.isAssignableFrom(rt)) {
            ISourceLocation sloc = munger.getSourceLocation();
            classWeaver.getWorld().getMessageHandler().handleMessage(
                MessageUtil.error("ITD target " + rt.getName() + " doesn't appear to implement " + onType.getName()
                    + " why did we consider it the top most implementor? ITD is " + this.getSignature(), sloc));
          }
        } else if (!rtx.isExposedToWeaver()) {
          ISourceLocation sLoc = munger.getSourceLocation();
          classWeaver.getWorld().getMessageHandler().handleMessage(
              MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR, rtx,
                  getAspectType().getName()), (sLoc == null ? getAspectType().getSourceLocation() : sLoc)));
        } else {
          // XXX what does this state mean?
          // We have incorrectly identified what is the top most
          // implementor and its not because
          // a type wasn't exposed to the weaver
        }
        return false;
      } else {

        ResolvedMember mangledInterMethod = AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, false);

        LazyMethodGen mg = makeMethodGen(classGen, mangledInterMethod);

        // From 98901#29 - need to copy annotations across
        if (classWeaver.getWorld().isInJava5Mode()) {
          AnnotationAJ annotationsOnRealMember[] = null;
          ResolvedType toLookOn = aspectType;
          if (aspectType.isRawType()) {
            toLookOn = aspectType.getGenericType();
          }
          ResolvedMember realMember = getRealMemberForITDFromAspect(toLookOn, memberHoldingAnyAnnotations, false);
          if (realMember == null) {
            throw new BCException("Couldn't find ITD holder member '" + memberHoldingAnyAnnotations + "' on aspect "
                + aspectType);
          }
          annotationsOnRealMember = realMember.getAnnotations();

          if (annotationsOnRealMember != null) {
            for (AnnotationAJ annotationX : annotationsOnRealMember) {
              AnnotationGen a = ((BcelAnnotation) annotationX).getBcelAnnotation();
              AnnotationGen ag = new AnnotationGen(a, classWeaver.getLazyClassGen().getConstantPool(), true);
              mg.addAnnotation(new BcelAnnotation(ag, classWeaver.getWorld()));
            }
          }

          copyOverParameterAnnotations(mg, realMember);
        }

        if (mungingInterface) {
          // we want the modifiers of the ITD to be used for all
          // *implementors* of the
          // interface, but the method itself we add to the interface
          // must be public abstract
          mg.setAccessFlags(Modifier.PUBLIC | Modifier.ABSTRACT);
        }

        Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes());
        Type returnType = BcelWorld.makeBcelType(mangledInterMethod.getReturnType());

        InstructionList body = mg.getBody();
        InstructionFactory fact = classGen.getFactory();
        int pos = 0;

        if (!Modifier.isStatic(mangledInterMethod.getModifiers())) {
          body.append(InstructionFactory.createThis());
          pos++;
        }
        for (int i = 0, len = paramTypes.length; i < len; i++) {
          Type paramType = paramTypes[i];
          body.append(InstructionFactory.createLoad(paramType, pos));
          pos += paramType.getSize();
        }

        body.append(Utility.createInvoke(fact, classWeaver.getWorld(), interMethodBody));
        Type t = BcelWorld.makeBcelType(interMethodBody.getReturnType());
        if (!t.equals(returnType)) {
          body.append(fact.createCast(t, returnType));
        }
        body.append(InstructionFactory.createReturn(returnType));
        mg.definingType = onType;

View Full Code Here

  }

  private void createBridge(BcelClassWeaver weaver, ResolvedMember unMangledInterMethod, LazyClassGen classGen,
      ResolvedMember toBridgeTo) {
    Type[] paramTypes;
    Type returnType;
    InstructionList body;
    InstructionFactory fact;
    int pos;
    ResolvedMember bridgerMethod = AjcMemberMaker.bridgerToInterMethod(unMangledInterMethod, classGen.getType());
    ResolvedMember bridgingSetter = AjcMemberMaker.interMethodBridger(toBridgeTo, aspectType, false); // pr250493

    LazyMethodGen bridgeMethod = makeMethodGen(classGen, bridgingSetter);
    paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes());
    Type[] bridgingToParms = BcelWorld.makeBcelTypes(unMangledInterMethod.getParameterTypes());
    returnType = BcelWorld.makeBcelType(bridgingSetter.getReturnType());
    body = bridgeMethod.getBody();
    fact = classGen.getFactory();
    pos = 0;
    if (!Modifier.isStatic(bridgingSetter.getModifiers())) {
      body.append(InstructionFactory.createThis());
      pos++;
    }
    for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      body.append(InstructionFactory.createLoad(paramType, pos));
      if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(
          unMangledInterMethod.getParameterTypes()[i].getErasureSignature())) {
        // System.err.println("Putting in cast from "+
        // paramType+" to "+bridgingToParms[i]);
        body.append(fact.createCast(paramType, bridgingToParms[i]));
      }
      pos += paramType.getSize();
    }

    body.append(Utility.createInvoke(fact, weaver.getWorld(), bridgerMethod));
    body.append(InstructionFactory.createReturn(returnType));
    classGen.addMethodGen(bridgeMethod);
View Full Code Here

    bridgeMethod.setAccessFlags(bridgeMethod.getAccessFlags() | 0x00000040 /*
                                         * BRIDGE = 0x00000040
                                         */);
    // UnresolvedType[] newParams =
    // munger.getSignature().getParameterTypes();
    Type returnType = BcelWorld.makeBcelType(theBridgeMethod.getReturnType());
    body = bridgeMethod.getBody();
    fact = clazz.getFactory();

    if (!Modifier.isStatic(unMangledInterMethod.getModifiers())) {
      body.append(InstructionFactory.createThis());
      pos++;
    }
    for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      body.append(InstructionFactory.createLoad(paramType, pos));
      // if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().
      // equals
      // (unMangledInterMethod.getParameterTypes()[i].getErasureSignature
      // ())) {
      // System.err.println("Putting in cast from "+paramType+" to "+
      // bridgingToParms[i]);
      // body.append(fact.createCast(paramType,bridgingToParms[i]));
      // }
      pos += paramType.getSize();
    }

    body.append(Utility.createInvoke(fact, world, unMangledInterMethod));
    body.append(InstructionFactory.createReturn(returnType));
    clazz.addMethodGen(bridgeMethod);
View Full Code Here

    }

    boolean shouldApply = munger.matches(weaver.getLazyClassGen().getType(), aspectType);

    if (shouldApply) {
      Type bcelReturnType = BcelWorld.makeBcelType(introduced.getReturnType());

      // If no implementation class was specified, the intention was that
      // the types matching the pattern
      // already implemented the interface, let's check that now!
      if (munger.getImplClassName() == null && !munger.specifiesDelegateFactoryMethod()) {
        boolean isOK = false;
        List<LazyMethodGen> existingMethods = gen.getMethodGens();
        for (LazyMethodGen m : existingMethods) {
          if (m.getName().equals(introduced.getName())
              && m.getParameterSignature().equals(introduced.getParameterSignature())
              && m.getReturnType().equals(bcelReturnType)) {
            isOK = true;
          }
        }
        if (!isOK) {
          // the class does not implement this method, they needed to
          // supply a default impl class
          IMessage msg = new Message("@DeclareParents: No defaultImpl was specified but the type '" + gen.getName()
              + "' does not implement the method '" + stringifyMember(introduced) + "' defined on the interface '"
              + introduced.getDeclaringType() + "'", weaver.getLazyClassGen().getType().getSourceLocation(), true,
              new ISourceLocation[] { munger.getSourceLocation() });
          weaver.getWorld().getMessageHandler().handleMessage(msg);
          return false;
        }

        return true;
      }

      LazyMethodGen mg = new LazyMethodGen(introduced.getModifiers() - Modifier.ABSTRACT, bcelReturnType, introduced
          .getName(), BcelWorld.makeBcelTypes(introduced.getParameterTypes()), BcelWorld
          .makeBcelTypesAsClassNames(introduced.getExceptions()), gen);

      // annotation copy from annotation on ITD interface
      if (weaver.getWorld().isInJava5Mode()) {
        AnnotationAJ annotationsOnRealMember[] = null;
        ResolvedType toLookOn = weaver.getWorld().lookupOrCreateName(introduced.getDeclaringType());
        if (fromType.isRawType()) {
          toLookOn = fromType.getGenericType();
        }
        // lookup the method
        ResolvedMember[] ms = toLookOn.getDeclaredJavaMethods();
        for (ResolvedMember m : ms) {
          if (introduced.getName().equals(m.getName()) && introduced.getSignature().equals(m.getSignature())) {
            annotationsOnRealMember = m.getAnnotations();
            break;
          }
        }
        if (annotationsOnRealMember != null) {
          for (AnnotationAJ anno : annotationsOnRealMember) {
            AnnotationGen a = ((BcelAnnotation) anno).getBcelAnnotation();
            AnnotationGen ag = new AnnotationGen(a, weaver.getLazyClassGen().getConstantPool(), true);
            mg.addAnnotation(new BcelAnnotation(ag, weaver.getWorld()));
          }
        }
      }

      InstructionList body = new InstructionList();
      InstructionFactory fact = gen.getFactory();

      // getfield
      body.append(InstructionConstants.ALOAD_0);
      body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
      InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
      body.append(ifNonNull);

      // Create and store a new instance
      body.append(InstructionConstants.ALOAD_0); // 'this' is where we'll store the field value

      // TODO for non-static case, call aspectOf() then call the factory method on the retval
      // TODO decide whether the value can really be cached

      // locate the aspect and call the static method in it
      if (munger.specifiesDelegateFactoryMethod()) {
        ResolvedMember rm = munger.getDelegateFactoryMethod(weaver.getWorld());

        // Check the method parameter is compatible with the type of the instance to be passed
        if (rm.getArity() != 0) {
          ResolvedType parameterType = rm.getParameterTypes()[0].resolve(weaver.getWorld());
          if (!parameterType.isAssignableFrom(weaver.getLazyClassGen().getType())) {
            signalError("For mixin factory method '" + rm + "': Instance type '" + weaver.getLazyClassGen().getType()
                + "' is not compatible with factory parameter type '" + parameterType + "'", weaver);
            return false;
          }
        }
        if (Modifier.isStatic(rm.getModifiers())) {
          if (rm.getArity() != 0) {
            body.append(InstructionConstants.ALOAD_0);
          }
          body.append(fact.createInvoke(rm.getDeclaringType().getName(), rm.getName(), rm.getSignature(),
              Constants.INVOKESTATIC));
          body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
        } else {
          // Need to call aspectOf() to obtain the aspect instance then call the factory method upon that
          UnresolvedType theAspect = munger.getAspect();
          body.append(fact.createInvoke(theAspect.getName(), "aspectOf", "()" + theAspect.getSignature(),
              Constants.INVOKESTATIC));
          if (rm.getArity() != 0) {
            body.append(InstructionConstants.ALOAD_0);
          }
          body.append(fact.createInvoke(rm.getDeclaringType().getName(), rm.getName(), rm.getSignature(),
              Constants.INVOKEVIRTUAL));
          body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
        }
      } else {
        body.append(fact.createNew(munger.getImplClassName()));
        body.append(InstructionConstants.DUP);
        body.append(fact
            .createInvoke(munger.getImplClassName(), "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
        body.append(Utility.createSet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));
      }

      // if not null use the instance we've got
      InstructionHandle ifNonNullElse = body.append(InstructionConstants.ALOAD_0);
      ifNonNull.setTarget(ifNonNullElse);
      body.append(Utility.createGet(fact, munger.getDelegate(weaver.getLazyClassGen().getType())));

      // args
      int pos = 0;
      if (!Modifier.isStatic(introduced.getModifiers())) { // skip 'this' (?? can this really
        // happen)
        // body.append(InstructionFactory.createThis());
        pos++;
      }
      Type[] paramTypes = BcelWorld.makeBcelTypes(introduced.getParameterTypes());
      for (int i = 0, len = paramTypes.length; i < len; i++) {
        Type paramType = paramTypes[i];
        body.append(InstructionFactory.createLoad(paramType, pos));
        pos += paramType.getSize();
      }
      body.append(Utility.createInvoke(fact, Constants.INVOKEINTERFACE, introduced));
      body.append(InstructionFactory.createReturn(bcelReturnType));

      mg.getBody().append(body);
View Full Code Here

  }

  private static LazyMethodGen makeDispatcher(LazyClassGen onGen, String dispatchName, ResolvedMember superMethod,
      BcelWorld world, boolean isSuper) {
    Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
    Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());

    int modifiers = Modifier.PUBLIC;
    if (onGen.isInterface()) {
      modifiers |= Modifier.ABSTRACT;
    }

    LazyMethodGen mg = new LazyMethodGen(modifiers, returnType, dispatchName, paramTypes, UnresolvedType.getNames(superMethod
        .getExceptions()), onGen);
    InstructionList body = mg.getBody();

    if (onGen.isInterface()) {
      return mg;
    }

    // assert (!superMethod.isStatic())
    InstructionFactory fact = onGen.getFactory();
    int pos = 0;

    body.append(InstructionFactory.createThis());
    pos++;
    for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      body.append(InstructionFactory.createLoad(paramType, pos));
      pos += paramType.getSize();
    }
    if (isSuper) {
      body.append(Utility.createSuperInvoke(fact, world, superMethod));
    } else {
      body.append(Utility.createInvoke(fact, world, superMethod));
View Full Code Here

      }
      weaver.addInitializer(this);
      // System.err.println("impl body on " + gen.getType() + " for " +
      // munger);

      Type fieldType = BcelWorld.makeBcelType(field.getType());

      FieldGen fg = makeFieldGen(gen, AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType));

      if (annotationsOnRealMember != null) {
        for (int i = 0; i < annotationsOnRealMember.length; i++) {
View Full Code Here

    InstructionFactory fact;
    LazyMethodGen bridgeMethod = makeMethodGen(gen, bridgingSetter);
    bridgeMethod.setAccessFlags(bridgeMethod.getAccessFlags() | 0x00000040); // BRIDGE = 0x00000040
    Type[] paramTypes = BcelWorld.makeBcelTypes(bridgingSetter.getParameterTypes());
    Type[] bridgingToParms = BcelWorld.makeBcelTypes(itdfieldSetter.getParameterTypes());
    Type returnType = BcelWorld.makeBcelType(bridgingSetter.getReturnType());
    InstructionList body = bridgeMethod.getBody();
    fact = gen.getFactory();
    int pos = 0;

    if (!Modifier.isStatic(bridgingSetter.getModifiers())) {
      body.append(InstructionFactory.createThis());
      pos++;
    }
    for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      body.append(InstructionFactory.createLoad(paramType, pos));
      if (!bridgingSetter.getParameterTypes()[i].getErasureSignature().equals(
          itdfieldSetter.getParameterTypes()[i].getErasureSignature())) {
        body.append(fact.createCast(paramType, bridgingToParms[i]));
      }
      pos += paramType.getSize();
    }

    body.append(Utility.createInvoke(fact, weaver.getWorld(), itdfieldSetter));
    body.append(InstructionFactory.createReturn(returnType));
    gen.addMethodGen(bridgeMethod);
View Full Code Here

    if ((newflags & 0x00000100) != 0) {
      newflags = newflags - 0x100;// NATIVE = 0x00000100 - need to clear it
    }

    bridgeMethod.setAccessFlags(newflags);
    Type returnType = BcelWorld.makeBcelType(theBridgeMethod.getReturnType());
    Type[] paramTypes = BcelWorld.makeBcelTypes(theBridgeMethod.getParameterTypes());
    Type[] newParamTypes = whatToBridgeToMethodGen.getArgumentTypes();
    body = bridgeMethod.getBody();
    fact = clazz.getFactory();

    if (!whatToBridgeToMethodGen.isStatic()) {
      body.append(InstructionFactory.createThis());
      pos++;
    }
    for (int i = 0, len = paramTypes.length; i < len; i++) {
      Type paramType = paramTypes[i];
      body.append(InstructionFactory.createLoad(paramType, pos));
      if (!newParamTypes[i].equals(paramTypes[i])) {
        if (world.forDEBUG_bridgingCode) {
          System.err.println("Bridging: Cast " + newParamTypes[i] + " from " + paramTypes[i]);
        }
        body.append(fact.createCast(paramTypes[i], newParamTypes[i]));
      }
      pos += paramType.getSize();
    }

    body.append(Utility.createInvoke(fact, world, whatToBridgeTo));
    body.append(InstructionFactory.createReturn(returnType));
    clazz.addMethodGen(bridgeMethod);
View Full Code Here

    // System.err.println("DEBUG: Transforming synchronized method: "+
    // synchronizedMethod.getName());
    final InstructionFactory fact = synchronizedMethod.getEnclosingClass().getFactory();
    InstructionList body = synchronizedMethod.getBody();
    InstructionList prepend = new InstructionList();
    Type enclosingClassType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());

    // STATIC METHOD TRANSFORMATION
    if (synchronizedMethod.isStatic()) {

      // What to do here depends on the level of the class file!
      // LDC can handle class literals in Java5 and above *sigh*
      if (synchronizedMethod.getEnclosingClass().isAtLeastJava5()) {
        // MONITORENTER logic:
        // 0: ldc #2; //class C
        // 2: dup
        // 3: astore_0
        // 4: monitorenter
        int slotForLockObject = synchronizedMethod.allocateLocal(enclosingClassType);
        prepend.append(fact.createConstant(enclosingClassType));
        prepend.append(InstructionFactory.createDup(1));
        prepend.append(InstructionFactory.createStore(enclosingClassType, slotForLockObject));
        prepend.append(InstructionFactory.MONITORENTER);

        // MONITOREXIT logic:

        // We basically need to wrap the code from the method in a
        // finally block that
        // will ensure monitorexit is called. Content on the finally
        // block seems to
        // be always:
        //
        // E1: ALOAD_1
        // MONITOREXIT
        // ATHROW
        //
        // so lets build that:
        InstructionList finallyBlock = new InstructionList();
        finallyBlock.append(InstructionFactory.createLoad(Type.getType(java.lang.Class.class), slotForLockObject));
        finallyBlock.append(InstructionConstants.MONITOREXIT);
        finallyBlock.append(InstructionConstants.ATHROW);

        // finally -> E1
        // | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line
        // 21)
        // | LDC "hello"
        // | INVOKEVIRTUAL java.io.PrintStream.println
        // (Ljava/lang/String;)V
        // | ALOAD_1 (line 20)
        // | MONITOREXIT
        // finally -> E1
        // GOTO L0
        // finally -> E1
        // | E1: ALOAD_1
        // | MONITOREXIT
        // finally -> E1
        // ATHROW
        // L0: RETURN (line 23)

        // search for 'returns' and make them jump to the
        // aload_<n>,monitorexit
        InstructionHandle walker = body.getStart();
        List<InstructionHandle> rets = new ArrayList<InstructionHandle>();
        while (walker != null) {
          if (walker.getInstruction().isReturnInstruction()) {
            rets.add(walker);
          }
          walker = walker.getNext();
        }
        if (!rets.isEmpty()) {
          // need to ensure targeters for 'return' now instead target
          // the load instruction
          // (so we never jump over the monitorexit logic)

          for (Iterator<InstructionHandle> iter = rets.iterator(); iter.hasNext();) {
            InstructionHandle element = iter.next();
            InstructionList monitorExitBlock = new InstructionList();
            monitorExitBlock.append(InstructionFactory.createLoad(enclosingClassType, slotForLockObject));
            monitorExitBlock.append(InstructionConstants.MONITOREXIT);
            // monitorExitBlock.append(Utility.copyInstruction(element
            // .getInstruction()));
            // element.setInstruction(InstructionFactory.createLoad(
            // classType,slotForThis));
            InstructionHandle monitorExitBlockStart = body.insert(element, monitorExitBlock);

            // now move the targeters from the RET to the start of
            // the monitorexit block
            for (InstructionTargeter targeter : element.getTargetersCopy()) {
              // what kinds are there?
              if (targeter instanceof LocalVariableTag) {
                // ignore
              } else if (targeter instanceof LineNumberTag) {
                // ignore
                // } else if (targeter instanceof
                // InstructionBranch &&
                // ((InstructionBranch)targeter).isGoto()) {
                // // move it...
                // targeter.updateTarget(element,
                // monitorExitBlockStart);
              } else if (targeter instanceof InstructionBranch) {
                // move it
                targeter.updateTarget(element, monitorExitBlockStart);
              } else {
                throw new BCException("Unexpected targeter encountered during transform: " + targeter);
              }
            }
          }
        }

        // now the magic, putting the finally block around the code
        InstructionHandle finallyStart = finallyBlock.getStart();

        InstructionHandle tryPosition = body.getStart();
        InstructionHandle catchPosition = body.getEnd();
        body.insert(body.getStart(), prepend); // now we can put the
        // monitorenter stuff on
        synchronizedMethod.getBody().append(finallyBlock);
        synchronizedMethod.addExceptionHandler(tryPosition, catchPosition, finallyStart, null/* ==finally */, false);
        synchronizedMethod.addExceptionHandler(finallyStart, finallyStart.getNext(), finallyStart, null, false);
      } else {

        // TRANSFORMING STATIC METHOD ON PRE JAVA5

        // Hideous nightmare, class literal references prior to Java5

        // YIKES! this is just the code for MONITORENTER !
        // 0: getstatic #59; //Field class$1:Ljava/lang/Class;
        // 3: dup
        // 4: ifnonnull 32
        // 7: pop
        // try
        // 8: ldc #61; //String java.lang.String
        // 10: invokestatic #44; //Method
        // java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
        // 13: dup
        // catch
        // 14: putstatic #59; //Field class$1:Ljava/lang/Class;
        // 17: goto 32
        // 20: new #46; //class java/lang/NoClassDefFoundError
        // 23: dup_x1
        // 24: swap
        // 25: invokevirtual #52; //Method
        // java/lang/Throwable.getMessage:()Ljava/lang/String;
        // 28: invokespecial #54; //Method
        // java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
        // 31: athrow
        // 32: dup <-- partTwo (branch target)
        // 33: astore_0
        // 34: monitorenter
        //
        // plus exceptiontable entry!
        // 8 13 20 Class java/lang/ClassNotFoundException
        Type classType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());
        Type clazzType = Type.getType(Class.class);

        InstructionList parttwo = new InstructionList();
        parttwo.append(InstructionFactory.createDup(1));
        int slotForThis = synchronizedMethod.allocateLocal(classType);
        parttwo.append(InstructionFactory.createStore(clazzType, slotForThis)); // ? should be the real type ? String or
        // something?
        parttwo.append(InstructionFactory.MONITORENTER);

        String fieldname = synchronizedMethod.getEnclosingClass().allocateField("class$");
        FieldGen f = new FieldGen(Modifier.STATIC | Modifier.PRIVATE, Type.getType(Class.class), fieldname,
            synchronizedMethod.getEnclosingClass().getConstantPool());
        synchronizedMethod.getEnclosingClass().addField(f, null);

        // 10: invokestatic #44; //Method
        // java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
        // 13: dup
        // 14: putstatic #59; //Field class$1:Ljava/lang/Class;
        // 17: goto 32
        // 20: new #46; //class java/lang/NoClassDefFoundError
        // 23: dup_x1
        // 24: swap
        // 25: invokevirtual #52; //Method
        // java/lang/Throwable.getMessage:()Ljava/lang/String;
        // 28: invokespecial #54; //Method
        // java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
        // 31: athrow
        String name = synchronizedMethod.getEnclosingClass().getName();

        prepend.append(fact.createGetStatic(name, fieldname, Type.getType(Class.class)));
        prepend.append(InstructionFactory.createDup(1));
        prepend.append(InstructionFactory.createBranchInstruction(Constants.IFNONNULL, parttwo.getStart()));
        prepend.append(InstructionFactory.POP);

        prepend.append(fact.createConstant(name));
        InstructionHandle tryInstruction = prepend.getEnd();
        prepend.append(fact.createInvoke("java.lang.Class", "forName", clazzType,
            new Type[] { Type.getType(String.class) }, Constants.INVOKESTATIC));
        InstructionHandle catchInstruction = prepend.getEnd();
        prepend.append(InstructionFactory.createDup(1));

        prepend.append(fact.createPutStatic(synchronizedMethod.getEnclosingClass().getType().getName(), fieldname,
            Type.getType(Class.class)));
        prepend.append(InstructionFactory.createBranchInstruction(Constants.GOTO, parttwo.getStart()));

        // start of catch block
        InstructionList catchBlockForLiteralLoadingFail = new InstructionList();
        catchBlockForLiteralLoadingFail.append(fact.createNew((ObjectType) Type.getType(NoClassDefFoundError.class)));
        catchBlockForLiteralLoadingFail.append(InstructionFactory.createDup_1(1));
        catchBlockForLiteralLoadingFail.append(InstructionFactory.SWAP);
        catchBlockForLiteralLoadingFail.append(fact.createInvoke("java.lang.Throwable", "getMessage",
            Type.getType(String.class), new Type[] {}, Constants.INVOKEVIRTUAL));
        catchBlockForLiteralLoadingFail.append(fact.createInvoke("java.lang.NoClassDefFoundError", "<init>", Type.VOID,
            new Type[] { Type.getType(String.class) }, Constants.INVOKESPECIAL));
        catchBlockForLiteralLoadingFail.append(InstructionFactory.ATHROW);
        InstructionHandle catchBlockStart = catchBlockForLiteralLoadingFail.getStart();
        prepend.append(catchBlockForLiteralLoadingFail);
        prepend.append(parttwo);
        // MONITORENTER
        // pseudocode: load up 'this' (var0), dup it, store it in a new
        // local var (for use with monitorexit) and call
        // monitorenter:
        // ALOAD_0, DUP, ASTORE_<n>, MONITORENTER
        // prepend.append(InstructionFactory.createLoad(classType,0));
        // prepend.append(InstructionFactory.createDup(1));
        // int slotForThis =
        // synchronizedMethod.allocateLocal(classType);
        // prepend.append(InstructionFactory.createStore(classType,
        // slotForThis));
        // prepend.append(InstructionFactory.MONITORENTER);

        // MONITOREXIT
        // here be dragons

        // We basically need to wrap the code from the method in a
        // finally block that
        // will ensure monitorexit is called. Content on the finally
        // block seems to
        // be always:
        //
        // E1: ALOAD_1
        // MONITOREXIT
        // ATHROW
        //
        // so lets build that:
        InstructionList finallyBlock = new InstructionList();
        finallyBlock.append(InstructionFactory.createLoad(Type.getType(java.lang.Class.class), slotForThis));
        finallyBlock.append(InstructionConstants.MONITOREXIT);
        finallyBlock.append(InstructionConstants.ATHROW);

        // finally -> E1
        // | GETSTATIC java.lang.System.out Ljava/io/PrintStream; (line
        // 21)
        // | LDC "hello"
        // | INVOKEVIRTUAL java.io.PrintStream.println
        // (Ljava/lang/String;)V
        // | ALOAD_1 (line 20)
        // | MONITOREXIT
        // finally -> E1
        // GOTO L0
        // finally -> E1
        // | E1: ALOAD_1
        // | MONITOREXIT
        // finally -> E1
        // ATHROW
        // L0: RETURN (line 23)
        // frameEnv.put(donorFramePos, thisSlot);

        // search for 'returns' and make them to the
        // aload_<n>,monitorexit
        InstructionHandle walker = body.getStart();
        List rets = new ArrayList();
        while (walker != null) { // !walker.equals(body.getEnd())) {
          if (walker.getInstruction().isReturnInstruction()) {
            rets.add(walker);
          }
          walker = walker.getNext();
        }
        if (rets.size() > 0) {
          // need to ensure targeters for 'return' now instead target
          // the load instruction
          // (so we never jump over the monitorexit logic)

          for (Iterator iter = rets.iterator(); iter.hasNext();) {
            InstructionHandle element = (InstructionHandle) iter.next();
            // System.err.println("Adding monitor exit block at "+
            // element);
            InstructionList monitorExitBlock = new InstructionList();
            monitorExitBlock.append(InstructionFactory.createLoad(classType, slotForThis));
            monitorExitBlock.append(InstructionConstants.MONITOREXIT);
            // monitorExitBlock.append(Utility.copyInstruction(element
            // .getInstruction()));
            // element.setInstruction(InstructionFactory.createLoad(
            // classType,slotForThis));
            InstructionHandle monitorExitBlockStart = body.insert(element, monitorExitBlock);

            // now move the targeters from the RET to the start of
            // the monitorexit block
            for (InstructionTargeter targeter : element.getTargetersCopy()) {
              // what kinds are there?
              if (targeter instanceof LocalVariableTag) {
                // ignore
              } else if (targeter instanceof LineNumberTag) {
                // ignore
                // } else if (targeter instanceof GOTO ||
                // targeter instanceof GOTO_W) {
                // // move it...
                // targeter.updateTarget(element,
                // monitorExitBlockStart);
              } else if (targeter instanceof InstructionBranch) {
                // move it
                targeter.updateTarget(element, monitorExitBlockStart);
              } else {
                throw new BCException("Unexpected targeter encountered during transform: " + targeter);
              }
            }
          }
        }
        // body =
        // rewriteWithMonitorExitCalls(body,fact,true,slotForThis,
        // classType);
        // synchronizedMethod.setBody(body);

        // now the magic, putting the finally block around the code
        InstructionHandle finallyStart = finallyBlock.getStart();

        InstructionHandle tryPosition = body.getStart();
        InstructionHandle catchPosition = body.getEnd();
        body.insert(body.getStart(), prepend); // now we can put the
        // monitorenter stuff on

        synchronizedMethod.getBody().append(finallyBlock);
        synchronizedMethod.addExceptionHandler(tryPosition, catchPosition, finallyStart, null/* ==finally */, false);
        synchronizedMethod.addExceptionHandler(tryInstruction, catchInstruction, catchBlockStart,
            (ObjectType) Type.getType(ClassNotFoundException.class), true);
        synchronizedMethod.addExceptionHandler(finallyStart, finallyStart.getNext(), finallyStart, null, false);
      }
    } else {

      // TRANSFORMING NON STATIC METHOD
      Type classType = BcelWorld.makeBcelType(synchronizedMethod.getEnclosingClass().getType());
      // MONITORENTER
      // pseudocode: load up 'this' (var0), dup it, store it in a new
      // local var (for use with monitorexit) and call
      // monitorenter:
      // ALOAD_0, DUP, ASTORE_<n>, MONITORENTER
View Full Code Here

TOP

Related Classes of org.aspectj.apache.bcel.generic.Type

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.