OSDN Git Service

change kgram format
[stigmata/stigmata-plugins.git] / wsp / src / main / java / jp / sourceforge / stigmata / birthmarks / wsp / OpcodeWeightCalculatePreprocessor.java
1 package jp.sourceforge.stigmata.birthmarks.wsp;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import jp.sourceforge.stigmata.BirthmarkContext;
13 import jp.sourceforge.stigmata.birthmarks.AbstractBirthmarkPreprocessor;
14 import jp.sourceforge.stigmata.cflib.Opcode;
15 import jp.sourceforge.stigmata.cflib.OpcodeExtractMethodVisitor;
16 import jp.sourceforge.stigmata.digger.ClassFileArchive;
17 import jp.sourceforge.stigmata.digger.ClassFileEntry;
18 import jp.sourceforge.stigmata.spi.BirthmarkService;
19
20 import org.objectweb.asm.ClassReader;
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.ClassWriter;
23 import org.objectweb.asm.MethodVisitor;
24 import org.objectweb.asm.Opcodes;
25
26 /**
27  *
28  * @author Haruaki Tamada
29  */
30 public class OpcodeWeightCalculatePreprocessor
31         extends AbstractBirthmarkPreprocessor{
32     public OpcodeWeightCalculatePreprocessor(BirthmarkService spi){
33         super(spi);
34     }
35
36     @Override
37     public void preprocess(ClassFileArchive[] targets,
38                            BirthmarkContext context){
39         Map<Integer, Integer> targetMap = new HashMap<Integer, Integer>();
40
41         int classCount = 0;
42         for(ClassFileArchive archive: targets){
43             classCount += readOpcodes(archive, targetMap);
44         }
45
46         Map<Integer, Integer> weights = new HashMap<Integer, Integer>();
47         for(Map.Entry<Integer, Integer> entry: targetMap.entrySet()){
48             int opcode = entry.getKey();
49             Integer count = entry.getValue();
50             int c = 0;
51             if(count != null){
52                 c = count;
53             }
54
55             weights.put(opcode, (int)Math.round(Math.log(classCount / c)));
56         }
57
58         context.putProperty("birthmarks.wsp.weights", weights);
59     }
60
61     private int readOpcodes(ClassFileArchive archive,
62                             Map<Integer, Integer> targetMap){
63         int count = 0;
64         for(ClassFileEntry entry: archive){
65             count++;
66             final List<Opcode> opcodes = new ArrayList<Opcode>();
67             try{
68                 InputStream in = entry.getLocation().openStream();
69
70                 ClassReader reader = new ClassReader(in);
71                 ClassWriter writer = new ClassWriter(0);
72                 ClassVisitor opcodeExtractVisitor = new ClassVisitor(Opcodes.ASM4, writer){
73                     @Override
74                     public MethodVisitor visitMethod(
75                             int arg0, String arg1, String arg2,
76                             String arg3, String[] arg4){
77                         OpcodeExtractMethodVisitor visitor =
78                             new OpcodeExtractMethodVisitor(
79                                 super.visitMethod(arg0, arg1, arg2, arg3, arg4),
80                                 opcodes
81                             );
82                         return visitor;
83                     }
84                 };
85                 reader.accept(opcodeExtractVisitor, 0);
86
87                 Set<Integer> set = new HashSet<Integer>();
88                 for(Opcode opcode: opcodes){
89                     if(opcode.getCategory() != Opcode.Category.TARGETER){
90                         set.add(opcode.getOpcode());
91                     }
92                 }
93
94                 for(Integer i: set){
95                     Integer v = targetMap.get(i);
96                     if(v == null){
97                         v = 0;
98                     }
99                     v = v + 1;
100                     targetMap.put(i, v);
101                 }
102             } catch(IOException e){
103             }
104         }
105         return count;
106     }
107 }