Package de.scoopgmbh.copper.instrument

Source Code of de.scoopgmbh.copper.instrument.BuildStackInfoAdapter

/*
* Copyright 2002-2013 SCOOP Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.scoopgmbh.copper.instrument;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.org.apache.bcel.internal.classfile.ClassFormatException;

import de.scoopgmbh.copper.instrument.StackInfo.ComputationalCategory;

public class BuildStackInfoAdapter extends MethodVisitor implements Opcodes, ByteCodeStackInfo {
 
  static final Logger logger = LoggerFactory.getLogger(BuildStackInfoAdapter.class);
 
  static final Type retAddressType = Type.getObjectType("ReturnAddress");

  StackInfo lastDeclaredFrame;
  StackInfo currentFrame;
  StackInfo previousFrame;
  Map<Label, StackInfo> forwardFrames  = new HashMap<Label, StackInfo>();
  Map<Label, int[]>     lineNumbers    = new HashMap<Label, int[]>();
  List<LocalVariable>   localVariables = new ArrayList<LocalVariable>();
  MethodVisitor delegate;

  public BuildStackInfoAdapter(String classType, boolean isStatic, String methodName, String arguments, String extendedArguments) {
    super(ASM4);
    int i = 0;
    Type[] argumentTypes = Type.getArgumentTypes(arguments);
    currentFrame = new StackInfo();
    if (!isStatic)
      currentFrame.setLocal(i++, Type.getType(classType));
    for (Type t : argumentTypes) {
      currentFrame.setLocal(i++, t);
      if (StackInfo.getCategory(t) == ComputationalCategory.CAT_2)
        i++;
    }
    lastDeclaredFrame = new StackInfo(currentFrame);
    this.delegate = new NullMethodVisitor();
  }
 
  public void setMethodVisitor(MethodVisitor mVisitor) {
    this.delegate = mVisitor;
  }

  @Override
  public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
    return delegate.visitAnnotation(arg0, arg1);
  }

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

  @Override
  public void visitAttribute(Attribute arg0) {
    delegate.visitAttribute(arg0);
  }

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

  @Override
  public void visitEnd() {
    delegate.visitEnd();
  }

 
  @Override
  public void visitFieldInsn(int arg0, String arg1, String arg2, String arg3) {
    savePreviousFrame();
    Type t = deferTypFromCanonicalName(arg3);
    switch (arg0) {
    case GETSTATIC:
      currentFrame.pushStack(t); break;
    case PUTSTATIC:
      currentFrame.popStackUnchecked();
      break;
    case GETFIELD:
      currentFrame.replaceStack(t); break;
    case PUTFIELD:
      currentFrame.popStackUnchecked();
      currentFrame.popStackUnchecked();
      break;
    default: logger.debug("Unhandled: ");     
    }
    if (logger.isDebugEnabled()) logger.debug("fieldInsn "+getOpCode(arg0)+" '"+arg1+"' '"+arg2+"' '"+arg3+"'");
    delegate.visitFieldInsn(arg0, arg1, arg2, arg3);
  }

 
  @Override
  public void visitFrame(int arg0, int arg1, Object[] arg2, int arg3,
      Object[] arg4) {
    savePreviousFrame();
    if (logger.isDebugEnabled()) logger.debug("stackBefore: "+currentFrame.stack);
    if (logger.isDebugEnabled()) logger.debug("localBefore: "+currentFrame.localsToString());
    currentFrame = new StackInfo(lastDeclaredFrame);
    switch (arg0) {
    case F_SAME: // representing frame with exactly the same locals as the previous frame and with the empty stack.
      currentFrame.stack.clear(); break;
    case F_SAME1: //representing frame with exactly the same locals as the previous frame and with single value on the stack (nStack is 1 and stack[0] contains value for the type of the stack item).
      Type t = StackInfo.deferLocalDesc(arg4[0]);
      currentFrame.stack.clear(); currentFrame.stack.push(t); break;
    case F_APPEND: // representing frame with current locals are the same as the locals in the previous frame, except that additional locals are defined (nLocal is 1, 2 or 3 and local elements contains values representing added types).
      currentFrame.appendLocals(arg1, arg2); break;
    case F_CHOP: //�Opcodes.F_CHOP representing frame with current locals are the same as the locals in the previous frame, except that the last 1-3 locals are absent and with the empty stack (nLocals is 1, 2 or 3).
      currentFrame.removeLocals(arg1); currentFrame.stack.clear(); break;
    case Opcodes.F_FULL: //representing complete frame data.
    case Opcodes.F_NEW:
      currentFrame.clearFrame(); currentFrame.appendLocals(arg1, arg2); currentFrame.appendStack(arg3, arg4); break;
    default:
      throw new BuildStackFrameException("Unkwnon frame type "+arg0);

    }
    lastDeclaredFrame = new StackInfo(currentFrame);
    if (logger.isDebugEnabled()) logger.debug("stack: "+currentFrame.stack);
    if (logger.isDebugEnabled()) logger.debug("local: "+currentFrame.localsToString());
    if (logger.isDebugEnabled()) logger.debug("frame "+getFrameType(arg0)+" '"+arg1+"' '"+Arrays.asList(arg2)+"' '"+arg3+"' '"+Arrays.asList(arg4)+"'");
    delegate.visitFrame(arg0, arg1, arg2, arg3, arg4);
  }

  @Override
  public void visitIincInsn(int arg0, int arg1) {
    savePreviousFrame();
    delegate.visitIincInsn(arg0, arg1);
  }

  @Override
  public void visitInsn(int arg0) {
    savePreviousFrame();
    switch (arg0) {
    case ICONST_0:
    case ICONST_1:
    case ICONST_2:
    case ICONST_3:
    case ICONST_4:
    case ICONST_5:
    case ICONST_M1:
      currentFrame.pushStack(Type.INT_TYPE); break;
    case FCONST_0:
    case FCONST_1:
    case FCONST_2:
      currentFrame.pushStack(Type.FLOAT_TYPE); break;
    case DCONST_0:
    case DCONST_1:
      currentFrame.pushStack(Type.DOUBLE_TYPE); break;
    case LCONST_0:
    case LCONST_1:
      currentFrame.pushStack(Type.LONG_TYPE); break;
    case ACONST_NULL:
      currentFrame.pushStack(StackInfo.AconstNullType); break;
//      currentFrame.pushStack(Type.getType(Object.class)); break;
    case DUP:
      currentFrame.dupStack(); break;
    case DUP_X1:
      currentFrame.dupX1Stack(); break;
    case DUP_X2:
      currentFrame.dupX2Stack(); break;
    case DUP2:
      currentFrame.dup2Stack(); break;
    case DUP2_X1:
      currentFrame.dup2X1Stack(); break;
    case DUP2_X2:
      currentFrame.dup2X2Stack(); break;
    case POP:
      currentFrame.popStack(); break;
    case POP2:
      currentFrame.pop2Stack(); break;
    case SWAP:
      currentFrame.swapStack(); break;
    case IADD:
    case IAND:
    case ISUB:
    case IMUL:
    case IDIV:
    case IOR:
    case ISHL:
    case ISHR:
    case IUSHR:
    case IREM:
    case IXOR:
      currentFrame.popStackChecked(Type.INT_TYPE);
    case INEG:
      currentFrame.replaceStackChecked(Type.INT_TYPE,Type.INT_TYPE); break;
    case LADD:
    case LAND:
    case LOR:
    case LSUB:
    case LMUL:
    case LDIV:
    case LREM:
    case LXOR:
      currentFrame.popStackChecked(Type.LONG_TYPE);
    case LNEG:
      currentFrame.replaceStackChecked(Type.LONG_TYPE,Type.LONG_TYPE); break;
    case LSHL:
    case LSHR:
    case LUSHR:
      currentFrame.popStackChecked(Type.INT_TYPE);
      currentFrame.replaceStackChecked(Type.LONG_TYPE,Type.LONG_TYPE); break;
    case DADD:
    case DSUB:
    case DMUL:
    case DDIV:
    case DREM:
      currentFrame.popStackChecked(Type.DOUBLE_TYPE);
    case DNEG:
      currentFrame.replaceStackChecked(Type.DOUBLE_TYPE,Type.DOUBLE_TYPE); break;
    case FADD:
    case FSUB:
    case FMUL:
    case FDIV:
    case FREM:
      currentFrame.popStackChecked(Type.FLOAT_TYPE);
    case FNEG:
      currentFrame.replaceStackChecked(Type.FLOAT_TYPE, Type.FLOAT_TYPE); break;
    case FCMPG:
    case FCMPL:
      currentFrame.popStackChecked(Type.FLOAT_TYPE); currentFrame.replaceStackChecked(Type.FLOAT_TYPE, Type.INT_TYPE); break;
    case DCMPG:
    case DCMPL:
      currentFrame.popStackChecked(Type.DOUBLE_TYPE); currentFrame.replaceStackChecked(Type.DOUBLE_TYPE, Type.INT_TYPE); break;
    case F2D:
      currentFrame.replaceStackChecked(Type.FLOAT_TYPE, Type.DOUBLE_TYPE); break;
    case F2I:
      currentFrame.replaceStackChecked(Type.FLOAT_TYPE, Type.INT_TYPE); break;
    case F2L:
      currentFrame.replaceStackChecked(Type.FLOAT_TYPE, Type.LONG_TYPE); break;
    case I2B:
      currentFrame.replaceStackChecked(Type.INT_TYPE, Type.BYTE_TYPE); break;
    case I2C:
      currentFrame.replaceStackChecked(Type.INT_TYPE, Type.CHAR_TYPE); break;
    case I2D:
      currentFrame.replaceStackChecked(Type.INT_TYPE, Type.DOUBLE_TYPE); break;
    case I2F:
      currentFrame.replaceStackChecked(Type.INT_TYPE, Type.FLOAT_TYPE); break;
    case I2L:
      currentFrame.replaceStackChecked(Type.INT_TYPE, Type.LONG_TYPE); break;
    case I2S:
      currentFrame.replaceStackChecked(Type.INT_TYPE, Type.SHORT_TYPE); break;
    case L2D:
      currentFrame.replaceStackChecked(Type.LONG_TYPE, Type.DOUBLE_TYPE); break;
    case L2F:
      currentFrame.replaceStackChecked(Type.LONG_TYPE, Type.FLOAT_TYPE); break;
    case L2I:
      currentFrame.replaceStackChecked(Type.LONG_TYPE, Type.INT_TYPE); break;
    case D2F:
      currentFrame.replaceStackChecked(Type.DOUBLE_TYPE, Type.FLOAT_TYPE); break;
    case D2I:
      currentFrame.replaceStackChecked(Type.DOUBLE_TYPE, Type.INT_TYPE); break;
    case D2L:
      currentFrame.replaceStackChecked(Type.DOUBLE_TYPE, Type.LONG_TYPE); break;
    case LCMP:
      currentFrame.popStackChecked(Type.LONG_TYPE); currentFrame.replaceStackChecked(Type.LONG_TYPE, Type.INT_TYPE); break;
    case ARRAYLENGTH:
      currentFrame.popStack();
      currentFrame.pushStack(Type.INT_TYPE);
      break;
    case RETURN:
    case IRETURN:
    case LRETURN:
    case DRETURN:
    case FRETURN:
    case ARETURN:
      currentFrame.clearFrame();
      break;
    case ATHROW:
      Type t = currentFrame.popStack();
      currentFrame.clearStack();
      currentFrame.pushStack(t);
      break;
    case AALOAD:
      currentFrame.popStackChecked(Type.INT_TYPE);
      Type arrayType = currentFrame.popStack();
      currentFrame.pushStack(arrayType.getElementType());
      break;
    case BALOAD:
      arrayLoad(Type.BYTE_TYPE);
      break;
    case CALOAD:
      arrayLoad(Type.CHAR_TYPE);
      break;
    case DALOAD:
      arrayLoad(Type.DOUBLE_TYPE);
      break;
    case FALOAD:
      arrayLoad(Type.FLOAT_TYPE);
      break;
    case IALOAD:
      arrayLoad(Type.INT_TYPE);
      break;
    case LALOAD:
      arrayLoad(Type.LONG_TYPE);
      break;
    case SALOAD:
      arrayLoad(Type.SHORT_TYPE);
      break;
    case BASTORE:
      arrayStore(Type.BYTE_TYPE);
      break;
    case CASTORE:
      arrayStore(Type.CHAR_TYPE);
      break;   
    case DASTORE:
      arrayStore(Type.DOUBLE_TYPE);
      break;   
    case FASTORE:
      arrayStore(Type.FLOAT_TYPE);
      break;   
    case IASTORE:
      arrayStore(Type.INT_TYPE);
      break;
    case LASTORE:
      arrayStore(Type.LONG_TYPE);
      break;
    case SASTORE:
      arrayStore(Type.SHORT_TYPE);
      break;
    case AASTORE:
      currentFrame.popStack();
      currentFrame.popStackChecked(Type.INT_TYPE);
      currentFrame.popStack();
      break;
    case MONITORENTER:
    case MONITOREXIT:
      currentFrame.popStack();
      break;
    case NOP: break;
    default: logger.debug("Unhandled: ");
    }
    if (logger.isDebugEnabled()) logger.debug("insn "+getOpCode(arg0));
    delegate.visitInsn(arg0);   
  }
 
  @Override
  public void visitIntInsn(int arg0, int arg1) {
    savePreviousFrame();
    switch (arg0) {
    case BIPUSH:
      currentFrame.pushStack(Type.BYTE_TYPE); break;
    case SIPUSH:
      currentFrame.pushStack(Type.SHORT_TYPE); break;
    case NEWARRAY:
      currentFrame.replaceStackChecked(Type.INT_TYPE, getArrayType(arg1)); break;
    default:
      logger.debug("Unhandled: ");
    }
    if (logger.isDebugEnabled()) logger.debug("intInsn "+getOpCode(arg0)+" "+arg1);
    delegate.visitIntInsn(arg0, arg1);
  }

  @Override
  public void visitJumpInsn(int arg0, Label arg1) {
    savePreviousFrame();
    switch (arg0) {
    case Opcodes.IF_ACMPEQ:
    case Opcodes.IF_ACMPNE:
    case Opcodes.IF_ICMPEQ:
    case Opcodes.IF_ICMPGE:
    case Opcodes.IF_ICMPGT:
    case Opcodes.IF_ICMPLE:
    case Opcodes.IF_ICMPLT:
    case Opcodes.IF_ICMPNE:
      currentFrame.popStack();
    case Opcodes.IFEQ:
    case Opcodes.IFGE:
    case Opcodes.IFGT:
    case Opcodes.IFLE:
    case Opcodes.IFLT:
    case Opcodes.IFNE:
    case Opcodes.IFNONNULL:
    case Opcodes.IFNULL:
      currentFrame.popStack();
    case Opcodes.GOTO:
      forwardFrames.put(arg1, new StackInfo(currentFrame)); break;
    case Opcodes.JSR:
      currentFrame.pushStack(retAddressType);
      forwardFrames.put(arg1, new StackInfo(currentFrame)); break;
    default:
      logger.debug("Unhandled: ");
    }
    if (logger.isDebugEnabled()) logger.debug("jumpInsn "+getOpCode(arg0)+" "+arg1);
    delegate.visitJumpInsn(arg0, arg1);
  }

  @Override
  public void visitLabel(Label arg0) {
    savePreviousFrame();
    if (logger.isDebugEnabled()) logger.debug("label "+arg0);
    StackInfo f = forwardFrames.get(arg0);
    if (f != null)
      currentFrame = new StackInfo(f);
    delegate.visitLabel(arg0);
  }

  @Override
  public void visitLdcInsn(Object arg0) {
    savePreviousFrame();
    if (arg0 instanceof Type)
      currentFrame.pushStack((Type)arg0);
    else if (arg0 instanceof String)
      currentFrame.pushStack(Type.getType(String.class));
    else if (arg0 instanceof Float)
      currentFrame.pushStack(Type.FLOAT_TYPE);
    else if (arg0 instanceof Double)
      currentFrame.pushStack(Type.DOUBLE_TYPE);
    else if (arg0 instanceof Integer)
      currentFrame.pushStack(Type.INT_TYPE);
    else if (arg0 instanceof Long)
      currentFrame.pushStack(Type.LONG_TYPE);
    else
      logger.debug("Unhandled: ");
    if (logger.isDebugEnabled()) logger.debug("ldcInsn "+arg0);
    delegate.visitLdcInsn(arg0);
  }

  @Override
  public void visitLineNumber(int arg0, Label arg1) {
    getLineNumber(arg1)[0] = arg0;
    currentFrame.setLineNo(arg0);
    delegate.visitLineNumber(arg0, arg1);
  }

  @Override
  public void visitLocalVariable(String name, String desc, String signature,
      Label start, Label end, int index) {
    localVariables.add(new LocalVariable(name,desc,start,end,index));
    delegate.visitLocalVariable(name, desc, signature, start, end, index);
  }

  @Override
  public void visitLookupSwitchInsn(Label arg0, int[] arg1, Label[] arg2) {
    savePreviousFrame();
    if (logger.isDebugEnabled()) logger.debug("lookupSwitchInsn "+arg0+" "+Arrays.toString(arg1)+" "+Arrays.toString(arg2));
    delegate.visitLookupSwitchInsn(arg0, arg1, arg2);
  }

  @Override
  public void visitMaxs(int arg0, int arg1) {
    delegate.visitMaxs(arg0, arg1);
  }

  @Override
  public void visitMethodInsn(int arg0, String arg1, String arg2, String arg3) {
    savePreviousFrame();
    Type deferredReturnType = deferReturnType(arg3);
    switch (arg0) {
    case INVOKESTATIC:
      currentFrame.popStackBySignature(arg3);
      if (deferredReturnType != Type.VOID_TYPE)
        currentFrame.pushStack(deferredReturnType);
      break;
    case INVOKESPECIAL:
    case INVOKEINTERFACE:
    case INVOKEVIRTUAL:
      currentFrame.popStackBySignature(arg3);
      currentFrame.popStack();
      if (deferredReturnType != Type.VOID_TYPE)
        currentFrame.pushStack(deferredReturnType);
      break;
    default:
      logger.debug("Unhandled: ");
    }
    if (logger.isDebugEnabled()) logger.debug("methodInsn "+getOpCode(arg0)+" "+arg1+" "+arg2+" "+arg3);
    delegate.visitMethodInsn(arg0, arg1, arg2, arg3);
  }

  @Override
  public void visitMultiANewArrayInsn(String arg0, int arg1) {
    savePreviousFrame();
    for (int i = 0; i < arg1; ++i)
      currentFrame.popStackChecked(Type.INT_TYPE);
    currentFrame.pushStack(Type.getObjectType(arg0));
    if (logger.isDebugEnabled()) logger.debug("visitMultiANewArrayInsn "+arg0+" "+arg1);
    delegate.visitMultiANewArrayInsn(arg0, arg1);
  }

  @Override
  public AnnotationVisitor visitParameterAnnotation(int arg0, String arg1,
      boolean arg2) {
    return delegate.visitParameterAnnotation(arg0, arg1, arg2);
  }

  @Override
  public void visitTableSwitchInsn(int arg0, int arg1, Label arg2, Label... arg3) {
    savePreviousFrame();
    if (logger.isDebugEnabled()) logger.debug("tableSwitchInsn "+arg0+" "+arg1+" "+arg2+" "+Arrays.asList(arg3));
    delegate.visitTableSwitchInsn(arg0, arg1, arg2, arg3);
  }

  @Override
  public void visitTryCatchBlock(Label arg0, Label arg1, Label arg2,
      String arg3) {
    if (logger.isDebugEnabled()) logger.debug("tryCatchBlock "+arg0+" "+arg1+" "+arg2+" "+arg3);
    delegate.visitTryCatchBlock(arg0, arg1, arg2, arg3);
  }

  @Override
  public void visitTypeInsn(int arg0, String arg1) {
    savePreviousFrame();
    Type objectType = Type.getObjectType(arg1);
    switch (arg0) {
    case NEW:
      currentFrame.pushStack(objectType); break;
    case CHECKCAST:
      currentFrame.replaceStack(objectType); break;
    case ANEWARRAY:
      currentFrame.replaceStack(Type.getObjectType("["+objectType.getDescriptor())); break;
    case INSTANCEOF:
      currentFrame.replaceStack(Type.INT_TYPE); break;
    default:
      logger.debug("Unhandled:");
    }
    if (logger.isDebugEnabled()) logger.debug("typeInsn: "+getOpCode(arg0)+" "+arg1);
    delegate.visitTypeInsn(arg0, arg1);
  }

  @Override
  public void visitVarInsn(int arg0, int arg1) {
    savePreviousFrame();
    switch (arg0) {
    case ALOAD:
      currentFrame.pushStack(currentFrame.getLocal(arg1)); break;
    case ASTORE:
      currentFrame.setLocal(arg1, currentFrame.popStack()); break;
    case FLOAD:
      if (!StackInfo.compatible(currentFrame.getLocal(arg1), Type.FLOAT_TYPE))
        throw new BuildStackFrameException("FLOAD expects a float, but got "+currentFrame.getLocal(arg1));
      currentFrame.pushStack(currentFrame.getLocal(arg1)); break;     
    case FSTORE:
      currentFrame.setLocal(arg1, currentFrame.popStack()); break;
    case ILOAD:
      if (!StackInfo.compatible(currentFrame.getLocal(arg1), Type.INT_TYPE))
        throw new BuildStackFrameException("ILOAD expects an int, but got "+currentFrame.getLocal(arg1));
      currentFrame.pushStack(Type.INT_TYPE); break;
    case LLOAD:
      if (!StackInfo.compatible(currentFrame.getLocal(arg1), Type.LONG_TYPE))
        throw new BuildStackFrameException("LLOAD expects a long, but got "+currentFrame.getLocal(arg1));
      currentFrame.pushStack(Type.LONG_TYPE); break;
    case DLOAD:
      if (!StackInfo.compatible(currentFrame.getLocal(arg1), Type.DOUBLE_TYPE))
        throw new BuildStackFrameException("DLOAD expects a double, but got "+currentFrame.getLocal(arg1));
      currentFrame.pushStack(Type.DOUBLE_TYPE); break;
    case ISTORE:
      if (!StackInfo.compatible(currentFrame.popStack(), Type.INT_TYPE))
        throw new BuildStackFrameException("ISTORE expects an int, but got "+currentFrame.getLocal(arg1));
      currentFrame.setLocal(arg1, Type.INT_TYPE); break;
    case DSTORE:
      if (!StackInfo.compatible(currentFrame.pop2Stack(), Type.DOUBLE_TYPE))
        throw new BuildStackFrameException("DSTORE expects a double, but got "+currentFrame.getLocal(arg1));
      currentFrame.setLocal(arg1, Type.DOUBLE_TYPE); break;
    case LSTORE:
      if (!StackInfo.compatible(currentFrame.pop2Stack(), Type.LONG_TYPE))
        throw new BuildStackFrameException("LSTORE expects a long, but got "+currentFrame.getLocal(arg1));
      currentFrame.setLocal(arg1, Type.LONG_TYPE); break;
    default:
      logger.debug("Unhandled:");
    }
    if (logger.isDebugEnabled()) logger.debug("varInsn: "+getOpCode(arg0)+" "+arg1);
    delegate.visitVarInsn(arg0, arg1);
  }

  public static void main(String[] args) throws Exception {
    File basedir = new File("C:/SVN/POLZUG-Solution-1.0-trucking/projects/gui/target/classes");
    testAllClasses(basedir,basedir);

  }

  private static void testAllClasses(File baseDir, File dir) throws FileNotFoundException, IOException, ClassNotFoundException {
    File[] files = dir.listFiles(new FilenameFilter() {
      @Override
      public boolean accept(File dir, String name) {
        return name.endsWith(".class");
      }
    });
    for (File f : files) {
      testClass(f, f.getAbsolutePath().substring(baseDir.getAbsolutePath().length()+1).replace(".class", "").replace("\\","."));
    }
    files = dir.listFiles(new FileFilter() {
      @Override
      public boolean accept(File pathname) {
       
        return pathname.isDirectory();
      }
    });
    for (File f : files) {
      testAllClasses(baseDir, f);
    }
  }

  private static void testClass(File file, final String className) throws IOException, FileNotFoundException {
    ClassReader cr = new ClassReader(new FileInputStream(file));
    ClassWriter cw = new ClassWriter(0);
    final String cDesc = Type.getObjectType(className).getDescriptor();
    ClassVisitor cv = new ClassVisitor(ASM4, cw) {


      @Override
      public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        if (logger.isDebugEnabled()) logger.debug("=======>"+access+" "+name+" "+desc+" "+signature);
        return new BuildStackInfoAdapter(cDesc, (access&Opcodes.ACC_STATIC) > 0, name, desc, signature);
      }

      @Override
      public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) {
        if (logger.isDebugEnabled()) logger.debug("== VISIT INNER =======>"+arg0+" "+arg1+" "+arg2+" "+arg3);
        super.visitInnerClass(arg0, arg1, arg2, arg3);
      }

    };
    cr.accept(cv, 0);
  }

  String getOpCode(int opCode) {
    for (Field f : Opcodes.class.getDeclaredFields()) {
      try {
        if (f.getName().startsWith("F_")
            || f.getName().startsWith("T_")
            || f.getName().startsWith("ACC_")
            || f.getName().startsWith("V1_")
              )
          continue;
        if (f.getInt(null) == opCode) {
          return f.getName();
        }
      } catch (IllegalArgumentException e) {
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      }
    }
    return "No Opcode for "+opCode;
  }
 
  String getFrameType(int frameType) {
    for (Field f : Opcodes.class.getDeclaredFields()) {
      try {
        if (!f.getName().startsWith("F_")
              )
          continue;
        if (f.getInt(null) == frameType) {
          return f.getName();
        }
      } catch (IllegalArgumentException e) {
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      }
    }
    return "No frame type for "+frameType;
  }
 
  Type getArrayElementType(int type) {
    switch (type) {
    case T_BOOLEAN: return Type.BOOLEAN_TYPE;
    case T_BYTE: return Type.BYTE_TYPE;
    case T_CHAR: return Type.CHAR_TYPE;
    case T_DOUBLE: return Type.DOUBLE_TYPE;
    case T_FLOAT: return Type.FLOAT_TYPE;
    case T_INT: return Type.INT_TYPE;
    case T_LONG: return Type.LONG_TYPE;
    case T_SHORT: return Type.SHORT_TYPE;
    }
    throw new BuildStackFrameException("Illegal array type code: "+type);
  }
 
  Type getArrayType(int type) {
    Type t = getArrayElementType(type);
    return Type.getObjectType("["+t.getDescriptor());
  }
 
  String getStackInfo(Object[] args) {
    StringBuilder sb = new StringBuilder("[");
    for (Object arg : args) {
      if (arg == null)
        sb.append("null");
      else {
        try {
          sb.append(deferTypFromCanonicalName(arg.toString()));
        } catch (ClassFormatException ex) {
          sb.append(arg.toString());
        }
      }
      sb.append(", ");
    }
    if (sb.length() > 1)
      sb.setLength(sb.length()-2);
    sb.append(']');
    return sb.toString();

  }

  static Type deferTypFromCanonicalName(String name) {
    return Type.getType(name);
  }

  static Type deferReturnType(String signature) {
    return Type.getReturnType(signature);
  }
 
  void savePreviousFrame() {
    previousFrame = new StackInfo(currentFrame);
  }

  void arrayLoad(Type arrayType) {
    currentFrame.popStackChecked(Type.INT_TYPE);
    currentFrame.replaceStack(arrayType);   
  }

  void arrayStore(Type arrayType) {
    currentFrame.popStackChecked(arrayType);
    currentFrame.popStackChecked(Type.INT_TYPE);
    currentFrame.popStack();   
  }

  @Override
  public StackInfo getPreviousStackInfo() {
    return new StackInfo(previousFrame);
  }
 
  @Override
  public StackInfo getCurrentStackInfo() {
    return new StackInfo(currentFrame);
  }

  private int[] getLineNumber(Label l) {
    int[] lineNo = lineNumbers.get(l);
    if (lineNo == null) {
      lineNumbers.put(l, lineNo = new int[]{-1});
    }
    return lineNo;
  }
 
  @Override
  public String[] getLocalNames(int lineNo, int count) {
    String[] names = new String[count];
    outerLoop: for (int index = 0; index < count; ++index) {
      names[index] = "var"+index;
      for (LocalVariable var : localVariables) {
        if (var.index == index && var.fromLine[0] <= lineNo && var.toLine[0] >= lineNo) {
          names[index] = var.name;
          continue outerLoop;
        }
      }
    }
    return names;
  }

  @Override
  public Type[] getLocalDescriptors(int lineNo, int count) {
    Type[] types = new Type[count];
    outerLoop: for (int index = 0; index < count; ++index) {
      for (LocalVariable var : localVariables) {
        if (var.index == index && var.fromLine[0] <= lineNo && var.toLine[0] >= lineNo) {
          types[index] = Type.getType(var.declaredDescriptor);
          continue outerLoop;
        }
      }
    }
    return types;
  }

  public class LocalVariable {
   
    public LocalVariable(String name, String declaredDescriptor, Label from, Label to, int index) {
      this.name     = name;
      this.fromLine = getLineNumber(from);
      this.toLine   =   getLineNumber(to);
      if (this.toLine[0] == -1)
        this.toLine[0] = Integer.MAX_VALUE;
      this.index    = index;
      this.declaredDescriptor = declaredDescriptor;
    }
   
    String name;
    int[]  fromLine;
    int[]  toLine;
    int    index;
    String declaredDescriptor;
   
  }

}
TOP

Related Classes of de.scoopgmbh.copper.instrument.BuildStackInfoAdapter

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.