/* * Copyright 2012 Phil Pratt-Szeliga and other contributors * http://chirrup.org/ * * See the file LICENSE for copying permission. */ package org.trifort.rootbeer.generate.opencl.fields; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.trifort.rootbeer.generate.opencl.OpenCLClass; import org.trifort.rootbeer.generate.opencl.OpenCLScene; import soot.RefType; import soot.Scene; import soot.SootClass; import soot.Type; import soot.options.Options; import soot.rbclassload.ClassHierarchy; import soot.rbclassload.HierarchyGraph; import soot.rbclassload.RootbeerClassLoader; import soot.rbclassload.StringNumbers; public class ReverseClassHierarchy { private List<TreeNode> m_hierarchy; /** * Builds a List<TreeNode> where each is a class just below Object. The * algorithm works when there are holes in the class hierarchy (a hole is * when the real root or a parent is not in Map<String, OpenCLClass> classes) * @param classes */ public ReverseClassHierarchy(Map<String, OpenCLClass> classes){ m_hierarchy = new ArrayList<TreeNode>(); List<TreeNode> all_tree_nodes = new ArrayList<TreeNode>(); Set<Type> dfs_types = RootbeerClassLoader.v().getDfsInfo().getDfsTypes(); Set<String> dfs_string_types = getRefTypes(dfs_types); ClassHierarchy class_hierarchy = RootbeerClassLoader.v().getClassHierarchy(); SootClass obj_class = Scene.v().getSootClass("java.lang.Object"); HierarchyGraph hgraph = class_hierarchy.getHierarchyGraph(); Set<Integer> roots = hgraph.getChildren(0); //java.lang.Object is 0 for(Integer root : roots){ String root_name = StringNumbers.v().getString(root); SootClass root_class = Scene.v().getSootClass(root_name); if(root_class.isInterface()){ continue; } OpenCLClass ocl_class = OpenCLScene.v().getOpenCLClass(root_class); TreeNode tree_node = new TreeNode(root_class, ocl_class); LinkedList<TreeNode> queue = new LinkedList<TreeNode>(); queue.add(tree_node); all_tree_nodes.add(tree_node); while(queue.isEmpty() == false){ TreeNode curr = queue.removeFirst(); SootClass soot_class = curr.getSootClass(); int num = StringNumbers.v().addString(soot_class.getName()); Set<Integer> children = hgraph.getChildren(num); for(Integer child : children){ String child_str = StringNumbers.v().getString(child); SootClass child_class = Scene.v().getSootClass(child_str); if(child_class.isInterface()){ continue; } if(dfs_string_types.contains(child_str) == false){ continue; } OpenCLClass ocl_class2 = OpenCLScene.v().getOpenCLClass(child_class); TreeNode child_node = new TreeNode(child_class, ocl_class2); curr.addChild(child_node); queue.add(child_node); } } } for(TreeNode tree_node : all_tree_nodes){ if(hasNewInvoke(tree_node, dfs_string_types)){ m_hierarchy.add(tree_node); } } } public List<TreeNode> get(){ return m_hierarchy; } private Set<String> getRefTypes(Set<Type> dfs_types){ Set<String> ret = new HashSet<String>(); for(Type type : dfs_types){ if(type instanceof RefType){ RefType ref_type = (RefType) type; String name = ref_type.getSootClass().getName(); ret.add(name); } } return ret; } private boolean hasNewInvoke(TreeNode tree_node, Set<String> dfs_types) { SootClass soot_class = tree_node.getSootClass(); if(dfs_types.contains(soot_class.getName())){ return true; } List<TreeNode> children = tree_node.getChildren(); for(TreeNode child : children){ if(hasNewInvoke(child, dfs_types)){ return true; } } return false; } }