--- /dev/null
+package jp.sourceforge.stigmata.birthmarks.wsp;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+public class StackPattern implements Iterable<CurrentDepth>{
+ private List<CurrentDepth> depthList = new ArrayList<CurrentDepth>();
+
+ public StackPattern(){
+ }
+
+ public int getLength(){
+ return depthList.size();
+ }
+
+ public void update(int depth, Opcode opcode){
+ update(new CurrentDepth(depth, opcode));
+ }
+
+ public void update(CurrentDepth depth){
+ depthList.add(depth);
+ }
+
+ public Iterator<CurrentDepth> iterator(){
+ return Collections.unmodifiableList(depthList).iterator();
+ }
+}
* @version $Revision$
*/
public class StackPatternBasedBirthmarkExtractor extends ASMBirthmarkExtractor{
+ public StackPatternBasedBirthmarkExtractor(BirthmarkSpi service){
+ super(service);
+ }
@Override
public BirthmarkExtractVisitor createExtractVisitor(ClassWriter writer, Birthmark birthmark, BirthmarkEnvironment environment){
return new Visitor(writer, birthmark, environment);
}
- public StackPatternBasedBirthmarkExtractor(BirthmarkSpi service){
- super(service);
- }
-
@Override
public ExtractionUnit[] getAcceptableUnits(){
return new ExtractionUnit[] {
}
private BirthmarkElement[] buildElement(List<Opcode> opcodes){
+ StackPattern pattern = buildStackPattern(opcodes);
List<BirthmarkElement> elements = new ArrayList<BirthmarkElement>();
+
+ StackPattern subpattern = new StackPattern();
+ for(CurrentDepth depth: pattern){
+ subpattern.update(depth);
+ if(depth.getDepth() == 0){
+ elements.add(new StackPatternBasedBirthmarkElement(subpattern));
+ subpattern = new StackPattern();
+ }
+ }
+ elements.add(new StackPatternBasedBirthmarkElement(subpattern));
+
+ return elements.toArray(new BirthmarkElement[elements.size()]);
+ }
+
+ private StackPattern buildStackPattern(List<Opcode> opcodes){
Map<Label, Integer> tableMap = new HashMap<Label, Integer>();
+ StackPattern pattern = new StackPattern();
int currentDepth = 0;
+ Integer forwardedStatus = null;
for(Opcode opcode: opcodes){
- Integer forwardedStatus = null;
- if(opcode.getCategory() != Opcode.Category.TARGETER){
+ if(opcode.getCategory() == Opcode.Category.TARGETER){
forwardedStatus = tableMap.get(((LabelOpcode)opcode).getLabel());
}
- if(forwardedStatus == null){
- currentDepth += opcode.getAct();
- }
else{
- currentDepth = forwardedStatus + opcode.getAct();
- }
- if(opcode.getCategory() == Opcode.Category.BRANCH){
- for(Iterator<Label> i = opcode.labels(); i.hasNext(); ){
- Label label = i.next();
- tableMap.put(label, currentDepth);
+ if(forwardedStatus == null){
+ currentDepth += opcode.getAct();
+ }
+ else{
+ currentDepth = forwardedStatus + opcode.getAct();
+ }
+ forwardedStatus = null;
+
+ pattern.update(currentDepth, opcode);
+ if(opcode.getCategory() == Opcode.Category.BRANCH){
+ for(Iterator<Label> i = opcode.labels(); i.hasNext(); ){
+ Label label = i.next();
+ tableMap.put(label, currentDepth);
+ }
}
}
}
-
- return elements.toArray(new BirthmarkElement[elements.size()]);
+ return pattern;
}
private class Visitor extends BirthmarkExtractVisitor{
+ private List<Opcode> opcodeList = new ArrayList<Opcode>();
+
public Visitor(ClassVisitor visitor, Birthmark birthmark, BirthmarkEnvironment environment){
super(visitor, birthmark, environment);
}
public void visitEnd(){
+ BirthmarkElement[] elements = buildElement(opcodeList);
+ for(BirthmarkElement element: elements){
+ addElement(element);
+ }
}
@Override
public MethodVisitor visitMethod(int arg0, String arg1, String arg2, String arg3, String[] arg4){
MethodVisitor visitor = super.visitMethod(arg0, arg1, arg2, arg3, arg4);
- OpcodeExtractionMethodVisitor opcodeVisitor = new OpcodeExtractionMethodVisitor(visitor);
- opcodeVisitor.addOpcodeExtractionFinishListener(new OpcodeExtractionFinishListener(){
- @Override
- public void finishExtractionOpcodes(List<Opcode> opcodes){
- BirthmarkElement[] elements = buildElement(opcodes);
-
- for(BirthmarkElement be: elements){
- addElement(be);
- }
- }
- });
+ OpcodeExtractionMethodVisitor opcodeVisitor = new OpcodeExtractionMethodVisitor(visitor, opcodeList);
return opcodeVisitor;
}