Package cn.wensiqun.asmsupport.asm

Source Code of cn.wensiqun.asmsupport.asm.StackLocalMethodVisitor

package cn.wensiqun.asmsupport.asm;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import cn.wensiqun.asmsupport.clazz.AClass;
import cn.wensiqun.asmsupport.exception.InstructionException;
import cn.wensiqun.asmsupport.utils.Stack;
import cn.wensiqun.asmsupport.utils.Stackable;

public class StackLocalMethodVisitor implements MethodVisitor , Opcodes{

    private static Log log = LogFactory.getLog(StackLocalMethodVisitor.class);   
    private static final Type OBJECT_TYPE = Type.getType(Object.class);
   
  private Stack stack;
  private MethodVisitor mv;
  private Type[] nextPushTypes;
 
  public Stack getStack(){
    return stack;
  }
 
  private Type[] triggerPushStack(){
    if(nextPushTypes == null){
      return null;
    }
    stack.push(nextPushTypes);
    Type[] pushed = nextPushTypes;
    nextPushTypes = null;
    return pushed;
  }
 
  void setNextPushTypes(Type... types){
    this.nextPushTypes = types;
  }
 
  public StackLocalMethodVisitor(MethodVisitor mv, Stack stack) {
    super();
    this.stack = stack;
    //this.locals = locals;
    this.mv = mv;
  }
 
  private void stackLocalOperator(int opcode){
    stackLocalOperator(opcode, -1);
  }
 
  /**
   * Stack : ACONST_NULL, ALOAD,
   * @param opcode
   */
  private void stackLocalOperator(int opcode, int popNum){
    Stackable top;
    switch(opcode){
        case NOP :
          if(log.isDebugEnabled())
          log.debug("Instruction : NOP");
          break;
        case ACONST_NULL :
          if(log.isDebugEnabled())
          log.debug("Instruction : ACONST_NULL");
          if(nextPushTypes == null){
            nextPushTypes = new Type[]{OBJECT_TYPE};
            //throw new InternalError("please reference a type");
          }
          break;
        case ICONST_M1 :
          if(log.isDebugEnabled())
          log.debug("Instruction : ICONST_M1");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case ICONST_0 :
          if(log.isDebugEnabled())
          log.debug("Instruction : ICONST_0");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case ICONST_1 :
          if(log.isDebugEnabled())
          log.debug("Instruction : ICONST_1");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case ICONST_2 :
          if(log.isDebugEnabled())
          log.debug("Instruction : ICONST_2");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case ICONST_3 :
          if(log.isDebugEnabled())
          log.debug("Instruction : ICONST_3");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case ICONST_4 :
          if(log.isDebugEnabled())
          log.debug("Instruction : ICONST_4");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case ICONST_5 :
          if(log.isDebugEnabled())
          log.debug("Instruction : ICONST_5");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case LCONST_0 :
          if(log.isDebugEnabled())
          log.debug("Instruction : LCONST_0");
          nextPushTypes = new Type[]{Type.LONG_TYPE};
          break;
        case LCONST_1 :
          if(log.isDebugEnabled())
          log.debug("Instruction : LCONST_1");
          nextPushTypes = new Type[]{Type.LONG_TYPE};
          break;
        case FCONST_0 :
          if(log.isDebugEnabled())
          log.debug("Instruction : FCONST_0");
          nextPushTypes = new Type[]{Type.FLOAT_TYPE};
          break;
        case FCONST_1 :
          if(log.isDebugEnabled())
          log.debug("Instruction : FCONST_1");
          nextPushTypes = new Type[]{Type.FLOAT_TYPE};
          break;
        case FCONST_2 :
          if(log.isDebugEnabled())
          log.debug("Instruction : FCONST_2");
          nextPushTypes = new Type[]{Type.FLOAT_TYPE};
          break;
        case DCONST_0 :
          if(log.isDebugEnabled())
          log.debug("Instruction : DCONST_0");
          nextPushTypes = new Type[]{Type.DOUBLE_TYPE};
          break;
        case DCONST_1 :
          if(log.isDebugEnabled())
          log.debug("Instruction : DCONST_1");
          nextPushTypes = new Type[]{Type.DOUBLE_TYPE};
          break;
        case BIPUSH :
          if(log.isDebugEnabled())
          log.debug("Instruction : BIPUSH");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case SIPUSH :
          if(log.isDebugEnabled())
          log.debug("Instruction : SIPUSH");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case LDC :
          if(log.isDebugEnabled())
          log.debug("Instruction : LDC");
          if(nextPushTypes == null){
            throw new InternalError("please reference a type");
          }
          break;
        case ILOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : ILOAD");
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case LLOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : LLOAD");
          nextPushTypes = new Type[]{Type.LONG_TYPE};
          break;
        case FLOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : FLOAD");
          nextPushTypes = new Type[]{Type.FLOAT_TYPE};
          break;
        case DLOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : DLOAD");
          nextPushTypes = new Type[]{Type.DOUBLE_TYPE};
          break;
        case ALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : ALOAD");
          if(nextPushTypes == null){
            nextPushTypes = new Type[]{OBJECT_TYPE};
            //throw new InternalError("please reference a type");
          }
          break;
        case IALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : IALOAD");
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          nextPushTypes = new Type[]{Type.INT_TYPE};
          break;
        case LALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : LALOAD");
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          nextPushTypes = new Type[]{Type.LONG_TYPE};
          break;
        case FALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : FALOAD");
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          nextPushTypes = new Type[]{Type.FLOAT_TYPE};
          break;
        case DALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : DALOAD");
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          nextPushTypes = new Type[]{Type.DOUBLE_TYPE};
          break;
        case AALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : AALOAD");
          //pop index
          stack.pop();
          //pop array reference
          top = stack.pop();
          Type nextEleType = Type.getType(top.getType().getDescriptor().substring(1));
          this.setNextPushTypes(nextEleType);
          break;
        case BALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : BALOAD");
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          nextPushTypes = new Type[]{Type.BYTE_TYPE};
          break;
        case CALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : CALOAD");
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          nextPushTypes = new Type[]{Type.CHAR_TYPE};
          break;
        case SALOAD :
          if(log.isDebugEnabled())
          log.debug("Instruction : SALOAD");
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          nextPushTypes = new Type[]{Type.SHORT_TYPE};
          break;
        case ISTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : ISTORE");
          stack.pop();
          break;
        case LSTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : LSTORE");
          stack.pop();
          break;
        case FSTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : FSTORE");
          stack.pop();
          break;
        case DSTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : DSTORE");
          stack.pop();
          break;
        case ASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : ASTORE");
          stack.pop();
          break;
        case IASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : IASTORE");
          //pop value
          stack.pop();
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          break;
        case LASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : LASTORE");
          //pop value
          stack.pop();
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          break;
        case FASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : FASTORE");
          //pop value
          stack.pop();
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          break;
        case DASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : DASTORE");
          //pop value
          stack.pop();
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          break;
        case AASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : AASTORE");
          //pop value
          stack.pop();
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          break;
        case BASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : BASTORE");
          //pop value
          stack.pop();
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          break;
        case CASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : CASTORE");
          //pop value
          stack.pop();
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          break;
        case SASTORE :
          if(log.isDebugEnabled())
          log.debug("Instruction : SASTORE");
          //pop value
          stack.pop();
          //pop index
          stack.pop();
          //pop array reference
          stack.pop();
          break
        case POP :
          if(log.isDebugEnabled())
          log.debug("Instruction : POP");
          stack.pop();
          break;
        case POP2 :
          if(log.isDebugEnabled())
          log.debug("Instruction : POP2");
          stack.pop(2);
          break;
        case DUP :
          if(log.isDebugEnabled())
          log.debug("Instruction : DUP");
          top = stack.peek();
          if(top.getSize() == 1){
            setNextPushTypes(top.getType());
          }else{
            throw new InstructionException("two word value off the operand stack", DUP, (Stack)stack.clone());
          }
          break;
        case DUP_X1 :
          if(log.isDebugEnabled())
          log.debug("Instruction : DUP_X1");
          top = stack.peek();
          if(top.getSize() == 1){
            stack.insert(2, top);
          }else{
            throw new InstructionException("two word value off the operand stack", DUP_X1, (Stack)stack.clone());
          }
          break;
        case DUP_X2 :
          if(log.isDebugEnabled())
          log.debug("Instruction : DUP_X2");
          top = stack.peek();
          if(top.getSize() == 1){
            stack.insert(3, top);
          }else{
            throw new InstructionException("two word value off the operand stack", DUP_X2, (Stack)stack.clone());
          }
          break;
        case DUP2 :
          if(log.isDebugEnabled())
          log.debug("Instruction : DUP2");
          if(stack.peek().getSize() == 2){
            setNextPushTypes(stack.peek().getType());
          }else if(stack.peek().getSize() == 1
              && stack.peek(1).getSize() == 1){
            setNextPushTypes(stack.peek(1).getType(), stack.peek().getType());
          }else{
            throw new InstructionException("cannot dup top two from stack", DUP2, (Stack)stack.clone());
          }
          break;
        case DUP2_X1 :
          if(log.isDebugEnabled())
          log.debug("Instruction : DUP2_X1");
          if(stack.peek().getSize() == 2){
            stack.insert(2, stack.peek());
          }else if(stack.peek().getSize() == 1
              && stack.peek(1).getSize() == 1){
            stack.insert(2, stack.peek(1));
            stack.insert(2, stack.peek());
          }else{
            throw new InstructionException("cannot dup top two from stack", DUP2_X1, (Stack)stack.clone());
          }
          break;
        case DUP2_X2 :
          if(log.isDebugEnabled()){
          log.debug("Instruction : DUP2_X2");
            }
          if(stack.peek().getSize() == 2){
            stack.insert(3, stack.peek());
          }else if(stack.peek().getSize() == 1
              && stack.peek(1).getSize() == 1){
            stack.insert(3, stack.peek(1));
            stack.insert(3, stack.peek());
          }else{
            throw new InstructionException("cannot dup top two from stack", DUP2_X2, (Stack)stack.clone());
          }
          break;
        case SWAP :
          if(log.isDebugEnabled()){
          log.debug("Instruction : SWAP");
          }
          top = stack.peek();
          stack.pop();
          stack.insert(1, top);
          break;
        case IADD :
          if(log.isDebugEnabled())
          log.debug("Instruction : IADD");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LADD :
          if(log.isDebugEnabled())
          log.debug("Instruction : LADD");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case FADD :
          if(log.isDebugEnabled())
          log.debug("Instruction : FADD");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.FLOAT_TYPE);
          break;
        case DADD :
          if(log.isDebugEnabled())
          log.debug("Instruction : DADD");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.DOUBLE_TYPE);
          break;
        case ISUB :
          if(log.isDebugEnabled())
          log.debug("Instruction : ISUB");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LSUB :
          if(log.isDebugEnabled())
          log.debug("Instruction : LSUB");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case FSUB :
          if(log.isDebugEnabled())
          log.debug("Instruction : FSUB");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.FLOAT_TYPE);
          break;
        case DSUB :
          if(log.isDebugEnabled())
          log.debug("Instruction : DSUB");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.DOUBLE_TYPE);
          break;
        case IMUL :
          if(log.isDebugEnabled())
          log.debug("Instruction : IMUL");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LMUL :
          if(log.isDebugEnabled())
          log.debug("Instruction : LMUL");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case FMUL :
          if(log.isDebugEnabled())
          log.debug("Instruction : FMUL");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.FLOAT_TYPE);
          break;
        case DMUL :
          if(log.isDebugEnabled())
          log.debug("Instruction : DMUL");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.DOUBLE_TYPE);
          break;
        case IDIV :
          if(log.isDebugEnabled())
          log.debug("Instruction : IDIV");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LDIV :
          if(log.isDebugEnabled())
          log.debug("Instruction : LDIV");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case FDIV :
          if(log.isDebugEnabled())
          log.debug("Instruction : FDIV");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.FLOAT_TYPE);
          break;
        case DDIV :
          if(log.isDebugEnabled())
          log.debug("Instruction : DDIV");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.DOUBLE_TYPE);
          break;
        case IREM :
          if(log.isDebugEnabled())
          log.debug("Instruction : IREM");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LREM :
          if(log.isDebugEnabled())
          log.debug("Instruction : LREM");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case FREM :
          if(log.isDebugEnabled())
          log.debug("Instruction : FREM");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.FLOAT_TYPE);
          break;
        case DREM :
          if(log.isDebugEnabled())
          log.debug("Instruction : DREM");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.DOUBLE_TYPE);
          break;
        case INEG :
          if(log.isDebugEnabled())
          log.debug("Instruction : INEG");
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LNEG :
          if(log.isDebugEnabled())
          log.debug("Instruction : LNEG");
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case FNEG :
          if(log.isDebugEnabled())
          log.debug("Instruction : FNEG");
          stack.pop();
          setNextPushTypes(Type.FLOAT_TYPE);
          break;
        case DNEG :
          if(log.isDebugEnabled())
          log.debug("Instruction : DNEG");
          stack.pop();
          setNextPushTypes(Type.DOUBLE_TYPE);
          break;
        case ISHL :
          if(log.isDebugEnabled())
          log.debug("Instruction : ISHL");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LSHL :
          if(log.isDebugEnabled())
          log.debug("Instruction : LSHL");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case ISHR :
          if(log.isDebugEnabled())
          log.debug("Instruction : ISHR");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LSHR :
          if(log.isDebugEnabled())
          log.debug("Instruction : LSHR");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case IUSHR :
          if(log.isDebugEnabled())
          log.debug("Instruction : IUSHR");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LUSHR :
          if(log.isDebugEnabled())
          log.debug("Instruction : LUSHR");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case IAND :
          if(log.isDebugEnabled())
          log.debug("Instruction : IAND");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LAND :
          if(log.isDebugEnabled())
          log.debug("Instruction : LAND");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case IOR :
          if(log.isDebugEnabled())
          log.debug("Instruction : IOR");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LOR :
          if(log.isDebugEnabled())
          log.debug("Instruction : LOR");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case IXOR :
          if(log.isDebugEnabled())
          log.debug("Instruction : IXOR");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.INT_TYPE);
          break;
        case LXOR :
          if(log.isDebugEnabled())
          log.debug("Instruction : LXOR");
          stack.pop();
          stack.pop();
          setNextPushTypes(Type.LONG_TYPE);
          break;
        case IINC :
          if(log.isDebugEnabled())
          log.debug("Instruction : IINC");
          break;
        case I2L :
          if(log.isDebugEnabled())
          log.debug("Instruction : I2L");
          stack.pop();
          stack.push(Type.LONG_TYPE);
          break;
        case I2F :
          if(log.isDebugEnabled())
          log.debug("Instruction : I2F");
          stack.pop();
          stack.push(Type.FLOAT_TYPE);
          break;
        case I2D :
          if(log.isDebugEnabled())
          log.debug("Instruction : I2D");
          stack.pop();
          stack.push(Type.DOUBLE_TYPE);
          break;
        case L2I :
          if(log.isDebugEnabled())
          log.debug("Instruction : L2I");
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case L2F :
          if(log.isDebugEnabled())
          log.debug("Instruction : L2F");
          stack.pop();
          stack.push(Type.FLOAT_TYPE);
          break;
        case L2D :
          if(log.isDebugEnabled())
          log.debug("Instruction : L2D");
          stack.pop();
          stack.push(Type.DOUBLE_TYPE);
          break;
        case F2I :
          if(log.isDebugEnabled())
          log.debug("Instruction : F2I");
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case F2L :
          if(log.isDebugEnabled())
          log.debug("Instruction : F2L");
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case F2D :
          if(log.isDebugEnabled())
          log.debug("Instruction : F2D");
          stack.pop();
          stack.push(Type.DOUBLE_TYPE);
          break;
        case D2I :
          if(log.isDebugEnabled())
          log.debug("Instruction : D2I");
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case D2L :
          if(log.isDebugEnabled())
          log.debug("Instruction : D2L");
          stack.pop();
          stack.push(Type.LONG_TYPE);
          break;
        case D2F :
          if(log.isDebugEnabled())
          log.debug("Instruction : D2F");
          stack.pop();
          stack.push(Type.FLOAT_TYPE);
          break;
        case I2B :
          if(log.isDebugEnabled())
          log.debug("Instruction : I2B");
          stack.pop();
          stack.push(Type.BYTE_TYPE);
          break;
        case I2C :
          if(log.isDebugEnabled())
          log.debug("Instruction : I2C");
          stack.pop();
          stack.push(Type.CHAR_TYPE);
          break;
        case I2S :
          if(log.isDebugEnabled())
          log.debug("Instruction : I2S");
          stack.pop();
          stack.push(Type.SHORT_TYPE);
          break;
        case LCMP :
          if(log.isDebugEnabled())
          log.debug("Instruction : LCMP");
          stack.pop();
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case FCMPL :
          if(log.isDebugEnabled())
          log.debug("Instruction : FCMPL");
          stack.pop();
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case FCMPG :
          if(log.isDebugEnabled())
          log.debug("Instruction : FCMPG");
          stack.pop();
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case DCMPL :
          if(log.isDebugEnabled())
          log.debug("Instruction : DCMPL");
          stack.pop();
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case DCMPG :
          if(log.isDebugEnabled())
          log.debug("Instruction : DCMPG");
          stack.pop();
          stack.pop();
          stack.push(Type.INT_TYPE);
          break;
        case IFEQ :
          if(log.isDebugEnabled())
          log.debug("Instruction : IFEQ");
          stack.pop();
          break;
        case IFNE :
          if(log.isDebugEnabled())
          log.debug("Instruction : IFNE");
          stack.pop();
          break;
        case IFLT :
          if(log.isDebugEnabled())
          log.debug("Instruction : IFLT");
          stack.pop();
          break;
        case IFGE :
          if(log.isDebugEnabled())
          log.debug("Instruction : IFGE");
          stack.pop();
          break;
        case IFGT :
          if(log.isDebugEnabled())
          log.debug("Instruction : IFGT");
          stack.pop();
          break;
        case IFLE :
          if(log.isDebugEnabled())
          log.debug("Instruction : IFLE");
          stack.pop();
          break;
        case IF_ICMPEQ :
          if(log.isDebugEnabled())
          log.debug("Instruction : IF_ICMPEQ");
          stack.pop();
          stack.pop();
          break;
        case IF_ICMPNE :
          if(log.isDebugEnabled())
          log.debug("Instruction : IF_ICMPNE");
          stack.pop();
          stack.pop();
          break;
        case IF_ICMPLT :
          if(log.isDebugEnabled())
          log.debug("Instruction : IF_ICMPLT");
          stack.pop();
          stack.pop();
          break;
        case IF_ICMPGE :
          if(log.isDebugEnabled())
          log.debug("Instruction : IF_ICMPGE");
          stack.pop();
          stack.pop();
          break;
        case IF_ICMPGT :
          if(log.isDebugEnabled())
          log.debug("Instruction : IF_ICMPGT");
          stack.pop();
          stack.pop();
          break;
        case IF_ICMPLE :
          if(log.isDebugEnabled())
          log.debug("Instruction : IF_ICMPLE");
          stack.pop();
          stack.pop();
          break;
        case IF_ACMPEQ :
          if(log.isDebugEnabled())
          log.debug("Instruction : IF_ACMPEQ");
          stack.pop();
          stack.pop();
          break;
        case IF_ACMPNE :
          if(log.isDebugEnabled())
          log.debug("Instruction : IF_ACMPNE");
          stack.pop();
          stack.pop();
          break;
        case GOTO :
          if(log.isDebugEnabled())
          log.debug("Instruction : GOTO");
          break;
        case JSR :
          if(log.isDebugEnabled())
          log.debug("Instruction : JSR");
          break;
        case RET :
          if(log.isDebugEnabled())
          log.debug("Instruction : RET");
          break;
        case TABLESWITCH :
          if(log.isDebugEnabled())
          log.debug("Instruction : TABLESWITCH");
          break;
        case LOOKUPSWITCH :
          if(log.isDebugEnabled())
          log.debug("Instruction : LOOKUPSWITCH");
          break;
        case IRETURN :
          if(log.isDebugEnabled())
          log.debug("Instruction : IRETURN");
          stack.pop();
          break;
        case LRETURN :
          if(log.isDebugEnabled())
          log.debug("Instruction : LRETURN");
          stack.pop();
          break;
        case FRETURN :
          if(log.isDebugEnabled())
          log.debug("Instruction : FRETURN");
          stack.pop();
          break;
        case DRETURN :
          if(log.isDebugEnabled())
          log.debug("Instruction : DRETURN");
          stack.pop();
          break;
        case ARETURN :
          if(log.isDebugEnabled())
          log.debug("Instruction : ARETURN");
          stack.pop();
          break;
        case RETURN :
          if(log.isDebugEnabled())
          log.debug("Instruction : RETURN");
          break;
        case GETSTATIC :
          if(log.isDebugEnabled())
          log.debug("Instruction : GETSTATIC");
          if(nextPushTypes == null){
            throw new InternalError("please reference a type");
          }
          break;
        case PUTSTATIC :
          if(log.isDebugEnabled())
          log.debug("Instruction : PUTSTATIC");
          stack.pop();
          break;
        case GETFIELD :
          if(log.isDebugEnabled())
          log.debug("Instruction : GETFIELD");
          if(nextPushTypes == null){
            throw new InternalError("please reference a type");
          }
          break;
        case PUTFIELD :
          if(log.isDebugEnabled())
          log.debug("Instruction : PUTFIELD");
          stack.pop();
          stack.pop();
          break;
        case INVOKEVIRTUAL :
          if(log.isDebugEnabled())
          log.debug("Instruction : INVOKEVIRTUAL");
          //pop arguments
          stack.pop(popNum);
          //pop object reference
          stack.pop();
          break;
        case INVOKESPECIAL :
          if(log.isDebugEnabled())
          log.debug("Instruction : INVOKESPECIAL");
          //pop arguments
          stack.pop(popNum);
          //pop object reference
          stack.pop();
          break;
        case INVOKESTATIC :
          if(log.isDebugEnabled())
          log.debug("Instruction : INVOKESTATIC");
          //pop arguments
          stack.pop(popNum);
          break;
        case INVOKEINTERFACE :
          if(log.isDebugEnabled())
          log.debug("Instruction : INVOKEINTERFACE");
          //pop arguments
          stack.pop(popNum);
          //pop object reference
          stack.pop();
          break;
        case INVOKEDYNAMIC :
          if(log.isDebugEnabled())
          log.debug("Instruction : INVOKEDYNAMIC");
          //pop arguments
          stack.pop(popNum);
          //pop object reference
          stack.pop();
          break;
        case NEW :
          if(log.isDebugEnabled())
          log.debug("Instruction : NEW");
          break;
        case NEWARRAY :
          if(log.isDebugEnabled())
          log.debug("Instruction : NEWARRAY");
          //pop allocated dim number
          stack.pop();
          break;
        case ANEWARRAY :
          if(log.isDebugEnabled())
          log.debug("Instruction : ANEWARRAY");
          //pop the size of array
          stack.pop();
          break;
        case ARRAYLENGTH :
          if(log.isDebugEnabled())
          log.debug("Instruction : ARRAYLENGTH");
          setNextPushTypes(Type.INT_TYPE);
          //pop the reference of array
          stack.pop();
          break;
        case ATHROW :
          if(log.isDebugEnabled())
          log.debug("Instruction : ATHROW");
          //pop the exception reference
          stack.pop();
          break;
        case CHECKCAST :
          if(log.isDebugEnabled())
          log.debug("Instruction : CHECKCAST");
          //pop the raw object reference
          stack.pop();
          break;
        case INSTANCEOF :
          if(log.isDebugEnabled())
          log.debug("Instruction : INSTANCEOF");
          //pop the object reference
          stack.pop();
          break;
        case MONITORENTER :
          if(log.isDebugEnabled())
          log.debug("Instruction : MONITORENTER");
          stack.pop();
          break;
        case MONITOREXIT :
          if(log.isDebugEnabled())
          log.debug("Instruction : MONITOREXIT");
          stack.pop();
          break;
        case MULTIANEWARRAY :
          if(log.isDebugEnabled())
          log.debug("Instruction : MULTIANEWARRAY");
          stack.pop(popNum);
          break;
        case IFNULL :
          if(log.isDebugEnabled())
          log.debug("Instruction : IFNULL");
          stack.pop();
          break;
        case IFNONNULL :
          if(log.isDebugEnabled())
          log.debug("Instruction : IFNONNULL");
          stack.pop();
          break;
        default :
        throw new InternalError("cannot found instruction " + opcode);
      }
    triggerPushStack();
    if(opcode != NOP){
          stack.printState();
    }
  }

  @Override
  public AnnotationVisitor visitAnnotationDefault() {
        return mv.visitAnnotationDefault();
    }

  @Override
    public AnnotationVisitor visitAnnotation(
        final String desc,
        final boolean visible)
    {
        return mv.visitAnnotation(desc, visible);
    }

  @Override
    public AnnotationVisitor visitParameterAnnotation(
        final int parameter,
        final String desc,
        final boolean visible)
    {
        return mv.visitParameterAnnotation(parameter, desc, visible);
    }

  @Override
    public void visitAttribute(final Attribute attr) {
        mv.visitAttribute(attr);
    }

  @Override
    public void visitCode() {
        mv.visitCode();
    }

  @Override
    public void visitFrame(
        final int type,
        final int nLocal,
        final Object[] local,
        final int nStack,
        final Object[] stack)
    {
        mv.visitFrame(type, nLocal, local, nStack, stack);
    }

 
  @Override
    public void visitInsn(final int opcode) {
    stackLocalOperator(opcode);
        mv.visitInsn(opcode);
    }

  @Override
    public void visitIntInsn(final int opcode, final int operand) {
    if(opcode == NEWARRAY){
      Type arrayType = Type.getType("[" + getTypeByOperand(operand).getDescriptor());
      setNextPushTypes(arrayType);
    }
    stackLocalOperator(opcode);
        mv.visitIntInsn(opcode, operand);
    }

  @Override
    public void visitVarInsn(final int opcode, final int var) {
    stackLocalOperator(opcode);
        mv.visitVarInsn(opcode, var);
    }

  @Override
    public void visitTypeInsn(final int opcode, final String type) {
    if(opcode == INSTANCEOF){
      setNextPushTypes(Type.INT_TYPE);
    }else{
        setNextPushTypes(Type.getObjectType(type));
    }
    stackLocalOperator(opcode);
        mv.visitTypeInsn(opcode, type);
    }

  @Override
    public void visitFieldInsn(
        final int opcode,
        final String owner,
        final String name,
        final String desc)
    {
        if(opcode == GETSTATIC || opcode == GETFIELD){
          Type type = Type.getType(desc);
        this.setNextPushTypes(type);
    }
    stackLocalOperator(opcode);
        mv.visitFieldInsn(opcode, owner, name, desc);
    }

  @Override
    public void visitMethodInsn(
        final int opcode,
        final String owner,
        final String name,
        final String desc)
    {
    Type returnType = Type.getReturnType(desc);
    if(!Type.VOID_TYPE.equals(returnType)){
      setNextPushTypes(returnType);
    }
    //pop argument
    Type[] argTypes = Type.getArgumentTypes(desc);
    stackLocalOperator(opcode, argTypes.length);
        mv.visitMethodInsn(opcode, owner, name, desc);
    }

  @Override
    public void visitJumpInsn(final int opcode, final Label label) {
    stackLocalOperator(opcode);
        mv.visitJumpInsn(opcode, label);
    }

  @Override
    public void visitLabel(final Label label) {
        mv.visitLabel(label);
    }

  @Override
    public void visitLdcInsn(final Object cst) {
    Class<?> ctsCls = cst.getClass();
    if(ctsCls.equals(Type.class)){
      setNextPushTypes(AClass.CLASS_ACLASS.getType());
    }else if(ctsCls.equals(Integer.class)){
      setNextPushTypes(Type.INT_TYPE);
    }else if(ctsCls.equals(Float.class)){
      setNextPushTypes(Type.FLOAT_TYPE);
    }else if(ctsCls.equals(Long.class)){
      setNextPushTypes(Type.LONG_TYPE);
    }else if(ctsCls.equals(Double.class)){
      setNextPushTypes(Type.DOUBLE_TYPE);
    }else if(ctsCls.equals(String.class)){
      setNextPushTypes(AClass.STRING_ACLASS.getType());
    }
    stackLocalOperator(LDC);
        mv.visitLdcInsn(cst);
    }

  @Override
    public void visitIincInsn(final int var, final int increment) {
    stackLocalOperator(IINC);
        mv.visitIincInsn(var, increment);
    }

  @Override
    public void visitTableSwitchInsn(
        final int min,
        final int max,
        final Label dflt,
        final Label[] labels)
    {
    stackLocalOperator(TABLESWITCH);
        mv.visitTableSwitchInsn(min, max, dflt, labels);
    }

  @Override
    public void visitLookupSwitchInsn(
        final Label dflt,
        final int[] keys,
        final Label[] labels)
    {
    stackLocalOperator(LOOKUPSWITCH);
        mv.visitLookupSwitchInsn(dflt, keys, labels);
    }

  @Override
    public void visitMultiANewArrayInsn(final String desc, final int dims) {
    setNextPushTypes(Type.getType(desc));
    stackLocalOperator(MULTIANEWARRAY, dims);
        mv.visitMultiANewArrayInsn(desc, dims);
    }

  @Override
    public void visitTryCatchBlock(
        final Label start,
        final Label end,
        final Label handler,
        final String type)
    {
        mv.visitTryCatchBlock(start, end, handler, type);
    }

  @Override
    public void visitLocalVariable(
        final String name,
        final String desc,
        final String signature,
        final Label start,
        final Label end,
        final int index)
    {
        mv.visitLocalVariable(name, desc, signature, start, end, index);
    }

  @Override
    public void visitLineNumber(final int line, final Label start) {
        mv.visitLineNumber(line, start);
    }

  @Override
    public void visitMaxs(final int maxStack, final int maxLocals) {
        mv.visitMaxs(maxStack, maxLocals);
    }

  @Override
    public void visitEnd() {
        mv.visitEnd();
    }
 
  private Type getTypeByOperand(int order){
    switch(order){
        case T_BOOLEAN :
          return Type.BOOLEAN_TYPE;
        case T_CHAR :
          return Type.CHAR_TYPE;
        case T_BYTE :
          return Type.BYTE_TYPE;
        case T_SHORT :
          return Type.SHORT_TYPE;
        case T_INT :
          return Type.INT_TYPE;
        case T_FLOAT :
          return Type.FLOAT_TYPE;
        case T_LONG :
          return Type.LONG_TYPE;
        case T_DOUBLE :
          return Type.DOUBLE_TYPE;
        default :
          throw new InternalError();
    }
  }
 
}
TOP

Related Classes of cn.wensiqun.asmsupport.asm.StackLocalMethodVisitor

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.