OSDN Git Service

almost button up
[stigmata/stigmata-plugins.git] / wsp / src / main / java / jp / sourceforge / stigmata / birthmarks / wsp / OpcodeWeightCalculatePreprocessor.java
1 package jp.sourceforge.stigmata.birthmarks.wsp;
2
3 /*
4  * $Id$
5  */
6
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.util.ArrayList;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15
16 import jp.sourceforge.stigmata.BirthmarkContext;
17 import jp.sourceforge.stigmata.birthmarks.AbstractBirthmarkPreprocessor;
18 import jp.sourceforge.stigmata.digger.ClassFileArchive;
19 import jp.sourceforge.stigmata.digger.ClassFileEntry;
20 import jp.sourceforge.stigmata.spi.BirthmarkSpi;
21
22 import org.objectweb.asm.ClassAdapter;
23 import org.objectweb.asm.ClassReader;
24 import org.objectweb.asm.ClassWriter;
25 import org.objectweb.asm.MethodVisitor;
26
27 /**
28  * 
29  * @author Haruaki Tamada
30  * @version $Revision$
31  */
32 public class OpcodeWeightCalculatePreprocessor extends AbstractBirthmarkPreprocessor{
33     public OpcodeWeightCalculatePreprocessor(BirthmarkSpi spi){
34         super(spi);
35     }
36
37     @Override
38     public void preprocess(ClassFileArchive[] targets, 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, Map<Integer, Integer> targetMap){
62         int count = 0;
63         for(ClassFileEntry entry: archive){
64             count++;
65             final List<Opcode> opcodes = new ArrayList<Opcode>();
66             try{
67                 InputStream in = entry.getLocation().openStream();
68
69                 ClassReader reader = new ClassReader(in);
70                 ClassWriter writer = new ClassWriter(false);
71                 ClassAdapter opcodeExtractVisitor = new ClassAdapter(writer){
72                     @Override
73                     public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4){
74                         OpcodeExtractionMethodVisitor visitor =
75                             new OpcodeExtractionMethodVisitor(super.visitMethod(arg0, arg1, arg2, arg3, arg4), opcodes);
76                         return visitor;
77                     }
78                 };
79                 reader.accept(opcodeExtractVisitor, false);
80
81                 Set<Integer> set = new HashSet<Integer>();
82                 for(Opcode opcode: opcodes){
83                     if(opcode.getCategory() != Opcode.Category.TARGETER){
84                         set.add(opcode.getOpcode());
85                     }
86                 }
87
88                 for(Integer i: set){
89                     Integer v = targetMap.get(i);
90                     if(v == null){
91                         v = 0;
92                     }
93                     v = v + 1;
94                     targetMap.put(i, v);
95                 }
96             } catch(IOException e){
97             }
98         }
99         return count;
100     }
101 }