/*
* Copyright 2012 Phil Pratt-Szeliga and other contributors
* http://chirrup.org/
*
* See the file LICENSE for copying permission.
*/
package org.trifort.rootbeer.entry;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import soot.SootField;
import soot.Type;
import soot.rbclassload.ClassHierarchy;
import soot.rbclassload.DfsInfo;
import soot.rbclassload.FieldSignatureUtil;
import soot.rbclassload.HierarchySignature;
import soot.rbclassload.HierarchyValueSwitch;
import soot.rbclassload.RootbeerClassLoader;
import soot.rbclassload.StringNumbers;
import soot.rbclassload.StringToType;
/**
*
* @author pcpratts
*/
public class RootbeerDfs {
private DfsInfo m_currDfsInfo;
public void run(DfsInfo dfs_info) {
m_currDfsInfo = dfs_info;
String signature = dfs_info.getRootMethodSignature();
Set<HierarchySignature> visited = new HashSet<HierarchySignature>();
//System.out.println("doing rootbeer dfs: "+signature);
LinkedList<HierarchySignature> queue = new LinkedList<HierarchySignature>();
queue.add(new HierarchySignature(signature));
queue.add(new HierarchySignature("<org.trifort.rootbeer.runtime.Sentinal: void <init>()>"));
queue.add(new HierarchySignature("<org.trifort.rootbeer.runtimegpu.GpuException: void <init>()>"));
queue.add(new HierarchySignature("<org.trifort.rootbeer.runtimegpu.GpuException: org.trifort.rootbeer.runtimegpu.GpuException arrayOutOfBounds(int,int,int)>"));
CompilerSetup setup = new CompilerSetup();
for(String method : setup.getDontDfs()){
visited.add(new HierarchySignature(method));
}
while(queue.isEmpty() == false){
HierarchySignature curr = queue.removeFirst();
doDfsForRootbeer(curr, queue, visited);
}
}
private void doDfsForRootbeer(HierarchySignature signature,
LinkedList<HierarchySignature> queue, Set<HierarchySignature> visited){
if(visited.contains(signature)){
return;
}
visited.add(signature);
StringToType converter = new StringToType();
FieldSignatureUtil futil = new FieldSignatureUtil();
//load all virtual methods to be followed
ClassHierarchy class_hierarchy = RootbeerClassLoader.v().getClassHierarchy();
List<HierarchySignature> virt_methods = class_hierarchy.getVirtualMethods(signature);
for(HierarchySignature virt_method : virt_methods){
if(virt_method.equals(signature) == false){
queue.add(virt_method);
}
}
//if we should follow into method, don't
if(RootbeerClassLoader.v().dontFollow(signature)){
return;
}
m_currDfsInfo.addType(signature.getClassName());
m_currDfsInfo.addType(signature.getReturnType());
m_currDfsInfo.addMethod(signature.toString());
//go into the method
HierarchyValueSwitch value_switch = RootbeerClassLoader.v().getValueSwitch(signature);
for(Integer num : value_switch.getAllTypesInteger()){
String type_str = StringNumbers.v().getString(num);
Type type = converter.convert(type_str);
m_currDfsInfo.addType(type);
}
for(HierarchySignature method_sig : value_switch.getMethodRefsHierarchy()){
m_currDfsInfo.addMethod(signature.toString());
queue.add(method_sig);
}
for(String field_ref : value_switch.getFieldRefs()){
futil.parse(field_ref);
SootField soot_field = futil.getSootField();
m_currDfsInfo.addField(soot_field);
}
for(Integer num : value_switch.getInstanceOfsInteger()){
String type_str = StringNumbers.v().getString(num);
Type type = converter.convert(type_str);
m_currDfsInfo.addInstanceOf(type);
}
}
}