Package org.aspectj.weaver.bcel

Source Code of org.aspectj.weaver.bcel.BcelRenderer

/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* Contributors:
*     PARC     initial implementation
* ******************************************************************/


package org.aspectj.weaver.bcel;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.ReferenceType;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.MemberImpl;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.ast.And;
import org.aspectj.weaver.ast.Call;
import org.aspectj.weaver.ast.CallExpr;
import org.aspectj.weaver.ast.CastExpr;
import org.aspectj.weaver.ast.Expr;
import org.aspectj.weaver.ast.FieldGet;
import org.aspectj.weaver.ast.FieldGetCall;
import org.aspectj.weaver.ast.FieldGetOn;
import org.aspectj.weaver.ast.HasAnnotation;
import org.aspectj.weaver.ast.IExprVisitor;
import org.aspectj.weaver.ast.ITestVisitor;
import org.aspectj.weaver.ast.Instanceof;
import org.aspectj.weaver.ast.Literal;
import org.aspectj.weaver.ast.Not;
import org.aspectj.weaver.ast.Or;
import org.aspectj.weaver.ast.StringConstExpr;
import org.aspectj.weaver.ast.Test;
import org.aspectj.weaver.ast.Var;
import org.aspectj.weaver.internal.tools.MatchingContextBasedTest;

// we generate right to left, btw.
public class BcelRenderer implements ITestVisitor, IExprVisitor {

    private InstructionList instructions;
    private InstructionFactory fact;
    private BcelWorld world;

    InstructionHandle sk, fk, next = null;

    private BcelRenderer(InstructionFactory fact, BcelWorld world) {
        super();
        this.fact = fact;
        this.world = world;
        this.instructions = new InstructionList();
    }

    // ---- renderers
   
    public static InstructionList renderExpr(
        InstructionFactory fact,
        BcelWorld world,
        Expr e)
    {
        BcelRenderer renderer = new BcelRenderer(fact, world);
        e.accept(renderer);
        return renderer.instructions;
    }
    public static InstructionList renderExpr(
        InstructionFactory fact,
        BcelWorld world,
        Expr e,
        Type desiredType)
    {
        BcelRenderer renderer = new BcelRenderer(fact, world);
        e.accept(renderer);
        InstructionList il = renderer.instructions;
        il.append(Utility.createConversion(fact, BcelWorld.makeBcelType(e.getType()), desiredType));
        return il;
    }

    public static InstructionList renderExprs(
        InstructionFactory fact,
        BcelWorld world,
        Expr[] es)
    {
        BcelRenderer renderer = new BcelRenderer(fact, world);
        for (int i = es.length - 1; i >= 0; i--) {
            es[i].accept(renderer);
        }
        return renderer.instructions;
    }

    /*
     * Get the instructions representing this test.
     *
     * @param e test to render
     * @param sk instructionHandle to jump to if our rendered check succeeds (typically start of advice)
     * @param fk instructionHandle to jump to if our rendered check fails (typically after end of advice)
     * @param next instructionHandle that will follow this generated code.  Passing in null will generate
     *             one unnecessary GOTO instruction.
     *
     * @returns the instruction list representing this expression
     */
    public static InstructionList renderTest(
        InstructionFactory fact,
        BcelWorld world,
        Test e,
        InstructionHandle sk,
        InstructionHandle fk,
        InstructionHandle next)
    {
        BcelRenderer renderer = new BcelRenderer(fact, world);
        renderer.recur(e, sk, fk, next);
        return renderer.instructions;
    }

    /*
     * Get the instructions representing this test.
     *
     * @param e test to render
     * @param sk instructionHandle to jump to if our rendered check succeeds (typically start of advice)
     * @param fk instructionHandle to jump to if our rendered check fails (typically after end of advice)
     *
     * @returns the instruction list representing this expression
     */
    public static InstructionList renderTest(
        InstructionFactory fact,
        BcelWorld world,
        Test e,
        InstructionHandle sk,
        InstructionHandle fk)
    {
        return renderTest(fact, world, e, sk, fk, null);
    }

    // ---- recurrers

    private void recur(
        Test e,
        InstructionHandle sk,
        InstructionHandle fk,
        InstructionHandle next)
    {
        this.sk = sk;
        this.fk = fk;
        this.next = next;
        e.accept(this);
    }

    // ---- test visitors

    public void visit(And e) {
        InstructionHandle savedFk = fk;
        recur(e.getRight(), sk, fk, next);
        InstructionHandle ning = instructions.getStart();
        recur(e.getLeft(), ning, savedFk, ning);
    }

    public void visit(Or e) {
        InstructionHandle savedSk = sk;
        recur(e.getRight(), sk, fk, next);
        recur(e.getLeft(), savedSk, instructions.getStart(), instructions.getStart());
    }

    public void visit(Not e) {
        recur(e.getBody(), fk, sk, next);
    }

    public void visit(Instanceof i) {
        instructions.insert(createJumpBasedOnBooleanOnStack());
        instructions.insert(
            Utility.createInstanceof(fact, (ReferenceType) BcelWorld.makeBcelType(i.getType())));
        i.getVar().accept(this);
    }

    public void visit(HasAnnotation hasAnnotation) {
        // in Java:
        // foo.class.isAnnotationPresent(annotationClass);
        // in bytecode:
        // load var onto the stack  (done for us later)
        // invokevirtual java/lang/Object.getClass:()Ljava/lang/Class
        // ldc_w annotationClass
        // invokevirtual java/lang/Class.isAnnotationPresent:(Ljava/lang/Class;)Z
        InstructionList il = new InstructionList();
        Member getClass = MemberImpl.method(UnresolvedType.OBJECT, 0, "getClass", "()Ljava/lang/Class;");
        il.append(Utility.createInvoke(fact, world, getClass));
        // aload annotationClass
        String s = hasAnnotation.getAnnotationType().getName();
        il.append(fact.createConstant(new ObjectType(hasAnnotation.getAnnotationType().getName())));
//        int annClassIndex = fact.getConstantPool().addClass(hasAnnotation.getAnnotationType().getSignature());
//        il.append(new LDC_W(annClassIndex));
        Member isAnnotationPresent = MemberImpl.method(UnresolvedType.forName("java/lang/Class"),0,
                "isAnnotationPresent","(Ljava/lang/Class;)Z");
        il.append(Utility.createInvoke(fact,world,isAnnotationPresent));
        il.append(createJumpBasedOnBooleanOnStack());
        instructions.insert(il);
        hasAnnotation.getVar().accept(this);
    }
   
    /* (non-Javadoc)
     * @see org.aspectj.weaver.ast.ITestVisitor#visit(org.aspectj.weaver.internal.tools.MatchingContextBasedTest)
     */
    public void visit(MatchingContextBasedTest matchingContextTest) {
      throw new UnsupportedOperationException("matching context extension not supported in bytecode weaving");
    }
   
  private InstructionList createJumpBasedOnBooleanOnStack() {
    InstructionList il = new InstructionList();
        if (sk == fk) {
            // don't bother generating if it doesn't matter
            if (sk != next) {
                il.insert(InstructionFactory.createBranchInstruction(Constants.GOTO, sk));
            }
            return il;
        }

        if (fk == next) {
            il.insert(InstructionFactory.createBranchInstruction(Constants.IFNE, sk));
        } else if (sk == next) {
            il.insert(InstructionFactory.createBranchInstruction(Constants.IFEQ, fk));
        } else {
            il.insert(InstructionFactory.createBranchInstruction(Constants.GOTO, sk));
            il.insert(InstructionFactory.createBranchInstruction(Constants.IFEQ, fk));
        }
        return il;   
  }


    public void visit(Literal literal) {
        if (literal == Literal.FALSE)
            throw new BCException("bad");
    }

  public void visit(Call call) {
    Member method = call.getMethod();
    // assert method.isStatic()
    Expr[] args = call.getArgs();
    //System.out.println("args: " + Arrays.asList(args));
    InstructionList callIl = new InstructionList();
    for (int i=0, len=args.length; i < len; i++) {
      //XXX only correct for static method calls
      Type desiredType = BcelWorld.makeBcelType(method.getParameterTypes()[i]);
      callIl.append(renderExpr(fact, world, args[i], desiredType));
    }
    //System.out.println("rendered args: " + callIl);
    callIl.append(Utility.createInvoke(fact, world, method));
    callIl.append(createJumpBasedOnBooleanOnStack());
    instructions.insert(callIl);   
  }

  public void visit(FieldGetCall fieldGetCall) {
    Member field = fieldGetCall.getField();
    Member method = fieldGetCall.getMethod();
    InstructionList il = new InstructionList();
    il.append(Utility.createGet(fact, field));
    // assert !method.isStatic()
    Expr[] args = fieldGetCall.getArgs();
    //System.out.println("args: " + Arrays.asList(args));
    il.append(renderExprs(fact, world, args))
    //System.out.println("rendered args: " + callIl);
    il.append(Utility.createInvoke(fact, world, method));
    il.append(createJumpBasedOnBooleanOnStack());
    instructions.insert(il)
  }

    // ---- expr visitors

    public void visit(Var var) {
        BcelVar bvar = (BcelVar) var;
        bvar.insertLoad(instructions, fact);
    }  
   
    public void visit(FieldGet fieldGet) {
    Member field = fieldGet.getField();
    // assert field.isStatic()
    instructions.insert(Utility.createGet(fact, field));   
    }
   
  public void visit(CallExpr call) {
    Member method = call.getMethod();
    // assert method.isStatic()
    Expr[] args = call.getArgs();
    InstructionList callIl = renderExprs(fact, world, args)
    callIl.append(Utility.createInvoke(fact, world, method));
    instructions.insert(callIl);   
  }

    /**
     * Visit a string constant
     * @param stringConst
     */
    public void visit(StringConstExpr stringConst) {
        instructions.insert(fact.createConstant(stringConst.getStringConst()));
    }

    /**
     * Visit a CHECKCAST
     * @param castExpr
     */
    public void visit(CastExpr castExpr) {
        instructions.append(fact.createCheckCast(new ObjectType(castExpr.getTypeName())));
    }

    /**
     * Visit a field GET (static or not, depends on the field)
     * @param fieldGet
     */
    public void visit(FieldGetOn fieldGet) {
    Member field = fieldGet.getField();
    instructions.insert(Utility.createGetOn(fact, field, fieldGet.getDeclaringType()));   
    }
}
TOP

Related Classes of org.aspectj.weaver.bcel.BcelRenderer

TOP
Copyright © 2018 www.massapi.com. 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.