Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / mcr-controller / src / edu / tamu / aser / profile / ProfileMethodTransformer.java
diff --git a/JMCR-Stable/mcr-controller/src/edu/tamu/aser/profile/ProfileMethodTransformer.java b/JMCR-Stable/mcr-controller/src/edu/tamu/aser/profile/ProfileMethodTransformer.java
new file mode 100644 (file)
index 0000000..dbe2786
--- /dev/null
@@ -0,0 +1,451 @@
+package edu.tamu.aser.profile;
+
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import edu.tamu.aser.rvinstrumentation.RVConfig;
+import edu.tamu.aser.rvinstrumentation.RVGlobalStateForInstrumentation;
+import edu.tamu.aser.rvinstrumentation.RVInstrumentor;
+
+public class ProfileMethodTransformer extends MethodVisitor implements Opcodes {
+
+       final static String CLASS_INTEGER = "java/lang/Integer";
+       final static String CLASS_BOOLEAN = "java/lang/Boolean";
+       final static String CLASS_CHAR = "java/lang/Character";
+       final static String CLASS_SHORT = "java/lang/Short";
+       final static String CLASS_BYTE = "java/lang/Byte";
+       final static String CLASS_LONG = "java/lang/Long";
+       final static String CLASS_FLOAT = "java/lang/Float";
+       final static String CLASS_DOUBLE = "java/lang/Double";
+
+       final static String METHOD_VALUEOF = "valueOf";
+       final static String DESC_INTEGER_VALUEOF = "(I)Ljava/lang/Integer;";
+       final static String DESC_BOOLEAN_VALUEOF = "(Z)Ljava/lang/Boolean;";
+       final static String DESC_BYTE_VALUEOF = "(B)Ljava/lang/Byte;";
+       final static String DESC_SHORT_VALUEOF = "(S)Ljava/lang/Short;";
+       final static String DESC_CHAR_VALUEOF = "(C)Ljava/lang/Character;";
+       final static String DESC_LONG_VALUEOF = "(J)Ljava/lang/Long;";
+       final static String DESC_FLOAT_VALUEOF = "(F)Ljava/lang/Float;";
+       final static String DESC_DOUBLE_VALUEOF = "(D)Ljava/lang/Double;";
+
+    boolean isInit, isSynchronized, isStatic, staticLock;
+       String methodSignature;
+       String className;
+          String methodName;
+
+       private int maxindex_cur;// current max index of local variables
+       private int line_cur;
+
+       public ProfileMethodTransformer(int access, String desc,
+                       String methodName, String className, MethodVisitor mv) {
+           
+        super(Opcodes.ASM5, mv);
+
+               this.methodSignature = methodName + desc;
+               this.isInit = (methodName.equals("<init>") || methodName
+                               .equals("<clinit>"));
+
+        this.maxindex_cur = Type.getArgumentsAndReturnSizes(desc) + 1;
+        this.className = className;
+        this.methodName = methodName;
+
+    
+            
+       }
+       @Override
+    public void visitLineNumber(int line, Label start) {
+        line_cur = line;
+        mv.visitLineNumber(line, start);
+    }
+//     @Override
+//        public void visitFieldInsn(int opcode, String owner, String name,
+//                 String desc) {
+//        mv.visitFieldInsn(opcode, owner, name, desc);
+//
+//     }
+       public void visitFieldInsn(int opcode, String owner, String name,
+                       String desc) {
+
+               String sig_var = (owner + "." + name).replace("/", ".");
+               String sig_loc = (owner + "|" + methodSignature + "|" + sig_var + "|" + line_cur)
+                               .replace("/", ".");
+               int SID = RVGlobalStateForInstrumentation.instance
+                               .getVariableId(sig_var);
+               int ID = RVGlobalStateForInstrumentation.instance
+                               .getLocationId(sig_loc);
+
+        if (!isInit) {
+        
+               switch (opcode) {
+               case GETSTATIC:
+                               addBipushInsn(mv, ID);
+                               addBipushInsn(mv, SID);
+                               addBipushInsn(mv, 0);
+    
+                               mv.visitMethodInsn(INVOKESTATIC, ProfileInstrumentor.logClass,
+                                               RVConfig.instance.LOG_FIELD_ACCESS,
+                                               RVConfig.instance.DESC_LOG_FIELD_ACCESS_DETECT_SHARING);
+                       break;
+    
+               case PUTSTATIC:
+    
+                    addBipushInsn(mv,ID);
+                    addBipushInsn(mv,SID);
+                
+                    addBipushInsn(mv,1);
+                    mv.visitMethodInsn(INVOKESTATIC, ProfileInstrumentor.logClass, RVConfig.instance.LOG_FIELD_ACCESS,
+                            RVConfig.instance.DESC_LOG_FIELD_ACCESS_DETECT_SHARING);
+    
+                       break;
+    
+               case GETFIELD:
+    
+                    addBipushInsn(mv,ID);
+                   addBipushInsn(mv,SID);
+                   
+                   addBipushInsn(mv,0);
+    
+                   
+                   mv.visitMethodInsn(INVOKESTATIC, ProfileInstrumentor.logClass, RVConfig.instance.LOG_FIELD_ACCESS,
+                           RVConfig.instance.DESC_LOG_FIELD_ACCESS_DETECT_SHARING);
+                       break;
+    
+               case PUTFIELD:
+                       if (name.startsWith("this$")
+                                       || (className.contains("$") && name.startsWith("val$"))) {
+                               // inner class or strange class
+                               break;
+                       }
+    
+                        addBipushInsn(mv,ID);
+                 addBipushInsn(mv,SID);
+                 addBipushInsn(mv,1); 
+                
+                mv.visitMethodInsn(INVOKESTATIC, ProfileInstrumentor.logClass, RVConfig.instance.LOG_FIELD_ACCESS,
+                        RVConfig.instance.DESC_LOG_FIELD_ACCESS_DETECT_SHARING);
+                       break;
+               default:
+                       System.err.println("Unknown field access opcode " + opcode);
+                       System.exit(1);
+               }
+        }
+        mv.visitFieldInsn(opcode, owner, name, desc);
+
+       }
+       
+         
+    @Override
+    public void visitMethodInsn(int opcode, String owner, String name,
+            String desc) {
+        // maxindex_cur++;
+         mv.visitMethodInsn(opcode, owner, name, desc);
+
+//        String sig_loc = (className + "|" + methodSignature + "|" + line_cur)
+//                .replace("/", ".");
+//        int ID = RVGlobalStateForInstrumentation.instance
+//                .getLocationId(sig_loc);
+//        switch (opcode) {
+//        case INVOKEVIRTUAL:
+//            if (RVGlobalStateForInstrumentation.instance.isThreadClass(owner)
+//                    && name.equals("start") && desc.equals("()V")) {
+//                maxindex_cur++;
+//                int index = maxindex_cur;
+//
+//                mv.visitInsn(DUP);
+//                mv.visitVarInsn(ASTORE, index);
+//                addBipushInsn(mv, ID);
+//                mv.visitVarInsn(ALOAD, index);
+//                mv.visitMethodInsn(INVOKESTATIC, ProfileInstrumentor.logClass,
+//                        RVConfig.instance.LOG_THREAD_BEFORE_START,
+//                        RVConfig.instance.DESC_LOG_THREAD_START);
+//
+//                mv.visitMethodInsn(opcode, owner, name, desc);
+//
+//            } else if (RVGlobalStateForInstrumentation.instance
+//                    .isThreadClass(owner)
+//                    && name.equals("join")
+//                    && desc.equals("()V")) {
+//                // consider timed join later
+//                maxindex_cur++;
+//                int index = maxindex_cur;
+//
+//                // Comment out reason below
+//                 //mv.visitInsn(DUP);
+//
+//                mv.visitVarInsn(ASTORE, index);
+//
+//                // Comment out join because it will be called inside performJoin
+//                // by MCR
+//                 //mv.visitMethodInsn(opcode, owner, name, desc);
+//
+//                addBipushInsn(mv, ID);
+//                mv.visitVarInsn(ALOAD, index);
+//                mv.visitMethodInsn(INVOKESTATIC, ProfileInstrumentor.logClass,
+//                        RVConfig.instance.LOG_THREAD_JOIN,
+//                        RVConfig.instance.DESC_LOG_THREAD_JOIN);
+//
+//            } else {
+//                mv.visitMethodInsn(opcode, owner, name, desc);
+//            }
+//
+//            break;
+//        case INVOKESPECIAL:
+//        case INVOKESTATIC:
+//        case INVOKEINTERFACE:
+//            mv.visitMethodInsn(opcode, owner, name, desc);
+//            break;
+//        default:
+//            System.err.println("Unknown method invocation opcode " + opcode);
+//            System.exit(1);
+//        }
+    }
+//    public void visitMaxs(int maxStack, int maxLocals) {
+//        mv.visitMaxs(maxStack + 5, maxindex_cur+2);//may change to ...
+//
+//    }
+//     @Override
+//     public void visitVarInsn(int opcode, int var) {
+//             if (var > maxindex_cur) {
+//                     maxindex_cur = var;
+//             }
+//
+//             switch (opcode) {
+//             case LSTORE:
+//             case DSTORE:
+//             case LLOAD:
+//             case DLOAD:
+//                     if (var == maxindex_cur) {
+//                             maxindex_cur = var + 1;
+//                     }
+//                     mv.visitVarInsn(opcode, var);
+//                     break;
+//             case ISTORE:
+//             case FSTORE:
+//             case ASTORE:
+//             case ILOAD:
+//             case FLOAD:
+//             case ALOAD:
+//             case RET:
+//                     mv.visitVarInsn(opcode, var);
+//                     break;
+//             default:
+//                     System.err.println("Unknown var instruction opcode " + opcode);
+//                     System.exit(1);
+//             }
+//     }
+
+       
+    private int arrayStoreOpcode(int opcode)
+    {
+        switch (opcode) {
+        case AASTORE:return ASTORE;
+        case FASTORE:return FSTORE;
+        case DASTORE:return DSTORE;
+        case LASTORE:return LSTORE;
+        case BASTORE:
+        case CASTORE:
+        case SASTORE:
+        case IASTORE:
+        default: return ISTORE; 
+        }
+    }
+       private int arrayLoadOpcode(int opcode)
+    {
+        switch (opcode) {
+        case AASTORE:return ALOAD;
+        case FASTORE:return FLOAD;
+        case DASTORE:return DLOAD;
+        case LASTORE:return LLOAD;
+        case BASTORE:
+        case CASTORE:
+        case SASTORE:
+        case IASTORE:
+        default: return ILOAD; 
+        }
+    }
+    private void instrumentArrayAccess(int opcode, boolean isWrite)
+    {
+        //super.updateThreadLocation();
+        //this.informSchedulerAboutArrayAccess(true, !isWrite);
+        
+        String sig_loc = (className + "|" + methodSignature + "|" + line_cur)
+                .replace("/", ".");
+        int ID = RVGlobalStateForInstrumentation.instance
+                .getLocationId(sig_loc);
+        
+
+        if(isWrite)
+        {
+            maxindex_cur++;
+            int index1 = maxindex_cur;
+            mv.visitVarInsn(arrayStoreOpcode(opcode), index1);
+            maxindex_cur++;
+            int index2 = maxindex_cur;
+            mv.visitVarInsn(ISTORE, index2);
+
+            mv.visitInsn(DUP);
+            maxindex_cur++;
+            int index3 = maxindex_cur;
+            mv.visitVarInsn(ASTORE, index3);// arrayref
+
+
+            addBipushInsn(mv, ID);
+            mv.visitVarInsn(ALOAD, index3);
+            mv.visitVarInsn(ILOAD, index2);
+
+            addBipushInsn(mv, 1);
+
+            mv.visitMethodInsn(INVOKESTATIC, ProfileInstrumentor.logClass, RVConfig.instance.LOG_ARRAY_ACCESS,
+                    RVConfig.instance.DESC_LOG_ARRAY_ACCESS_DETECT_SHARING);
+            
+            mv.visitVarInsn(ILOAD, index2);// index
+            mv.visitVarInsn(arrayLoadOpcode(opcode), index1);// value
+         
+        }
+        else {
+            mv.visitInsn(DUP2);
+            maxindex_cur++;
+            int index1 = maxindex_cur;
+            mv.visitVarInsn(ISTORE, index1);
+            maxindex_cur++;
+            int index2 = maxindex_cur;
+            mv.visitVarInsn(ASTORE, index2);
+            
+
+            addBipushInsn(mv, ID);
+            mv.visitVarInsn(ALOAD, index2);
+            mv.visitVarInsn(ILOAD, index1);
+
+            addBipushInsn(mv, 1);
+
+            mv.visitMethodInsn(INVOKESTATIC, ProfileInstrumentor.logClass, RVConfig.instance.LOG_ARRAY_ACCESS,
+                    RVConfig.instance.DESC_LOG_ARRAY_ACCESS_DETECT_SHARING);
+    }
+    }
+    public void visitJumpInsn(int opcode, Label label) {
+        String sig_loc = (className + "|" + methodSignature + "|" + line_cur)
+                .replace("/", ".");
+        int ID = RVGlobalStateForInstrumentation.instance
+                .getLocationId(sig_loc);
+
+        switch (opcode) {
+        case IFEQ:// branch
+        case IFNE:
+        case IFLT:
+        case IFGE:
+        case IFGT:
+        case IFLE:
+        case IF_ICMPEQ:
+        case IF_ICMPNE:
+        case IF_ICMPLT:
+        case IF_ICMPGE:
+        case IF_ICMPGT:
+        case IF_ICMPLE:
+        case IF_ACMPEQ:
+        case IF_ACMPNE:
+        case IFNULL:
+        case IFNONNULL:
+//            addBipushInsn(mv, ID);
+//            mv.visitMethodInsn(INVOKESTATIC, RVInstrumentor.logClass,
+//                    RVConfig.instance.LOG_BRANCH,
+//                    RVConfig.instance.DESC_LOG_BRANCH);
+        default:
+            mv.visitJumpInsn(opcode, label);
+            break;
+        }
+    }
+    @Override
+    public void visitIincInsn(int var, int increment) {
+        if (var > maxindex_cur) {
+            maxindex_cur = var;
+        }
+        mv.visitIincInsn(var, increment);
+    }
+    public void visitVarInsn(int opcode, int var) {
+        if (var > maxindex_cur) {
+            maxindex_cur = var;
+        }
+
+        switch (opcode) {
+        case LSTORE:
+        case DSTORE:
+        case LLOAD:
+        case DLOAD:
+            if (var == maxindex_cur) {
+                maxindex_cur = var + 1;
+            }
+            mv.visitVarInsn(opcode, var);
+            break;
+        case ISTORE:
+        case FSTORE:
+        case ASTORE:
+        case ILOAD:
+        case FLOAD:
+        case ALOAD:
+        case RET:
+            mv.visitVarInsn(opcode, var);
+            break;
+        default:
+            System.err.println("Unknown var instruction opcode " + opcode);
+            System.exit(1);
+        }
+    }
+    
+       //@Override
+       public void visitInsn(int opcode) {
+
+           if(!isInit)
+           {
+
+    
+               // Array access here
+               if (opcode == Opcodes.AALOAD || opcode == Opcodes.IALOAD
+                               || opcode == Opcodes.LALOAD || opcode == Opcodes.SALOAD
+                               || opcode == Opcodes.CALOAD || opcode == Opcodes.DALOAD
+                               || opcode == Opcodes.FALOAD || opcode == Opcodes.BALOAD) {
+                   
+                instrumentArrayAccess(opcode,false);     
+
+    
+               } else if (opcode == Opcodes.AASTORE || opcode == Opcodes.IASTORE
+                               || opcode == Opcodes.LASTORE || opcode == Opcodes.SASTORE
+                               || opcode == Opcodes.CASTORE || opcode == Opcodes.DASTORE
+                               || opcode == Opcodes.FASTORE || opcode == Opcodes.BASTORE) {
+                   
+                instrumentArrayAccess(opcode,true);            
+    
+               }
+           }
+           
+         mv.visitInsn(opcode);
+     
+       }
+
+       private void addBipushInsn(MethodVisitor mv, int val) {
+               switch (val) {
+               case 0:
+                       mv.visitInsn(ICONST_0);
+                       break;
+               case 1:
+                       mv.visitInsn(ICONST_1);
+                       break;
+               case 2:
+                       mv.visitInsn(ICONST_2);
+                       break;
+               case 3:
+                       mv.visitInsn(ICONST_3);
+                       break;
+               case 4:
+                       mv.visitInsn(ICONST_4);
+                       break;
+               case 5:
+                       mv.visitInsn(ICONST_5);
+                       break;
+               default:
+                       mv.visitLdcInsn(new Integer(val));
+                       break;
+               }
+       }
+}