今天读了读Soot中的SmartLocalDefs类,因为在其mailing list里面至少有2封邮件[1][2]推荐看看这个类,慕名而来
可惜的是,这个类相关的注释/文档太少,所以特此记录,以备后用。
首先这个类的成员包括5个域, 4个方法和1个内部类,下面就按次序简单描述一下各个部分。
一. 域
1)
private final Map<Cons, ArrayList<Unit>> answer;
answer用于存储该类所做分析的最终结果:将(cons Unit Local)映射到其所有可能的def所在的Units
2)
private final Map<Local, HashSet<Unit>> localToDefs;
localToDefs将每个Local映射到定义它的所有Units
3)
private final UnitGraph graph;
graph是分析过程中所用的流图
4)
private final LocalDefsAnalysis analysis;
analysis是内部类LocalDefsAnalysis的一个引用,稍后具体介绍LocalDefsAnalysis
5)
private final Map<Unit, HashSet> unitToMask;
unitToMask将Unit映射到在该Unit之后依然live的Locals
二. 方法
1)
public SmartLocalDefs(UnitGraph g, LiveLocals live)
类的构造函数,这个类的主要逻辑集中在该方法中(一大部分分析由内部类完成)。除了打印log之外,它干的活主要包括如下几个步骤:
- 初始化graph, localToDefs,unitToMask
- 将graph作为参数生成内部类LocalDefsAnalysis的一个实例。其实内部类在其构造函数被调用后,它已经默默的把主要的数据流分析都做完了
- 对于每个Unit(记为u),首先找出它use的Locals,然后将每一个Local(记为v)能到达该Unit的defs取出,最后构建一个(cons u v)并将其连同对应的defs放入answer.
2)
private Local localDef(Unit u)
返回u当中定义的Local(即local变量)。
注意,方法里一个隐含的assertion是一个Unit至多能定义一个Local。
3)
private HashSet<Unit> defsOf( Local l )
返回l所有可能的defs。这个方法直接将l作为key从localToDefs里面去找value了,如果找不到就先put一个空的HashSet,然后将其返回。所以该方法的返回值总是non-null。
4)
public List<Unit> getDefsOfAt(Local l, Unit s)
这个方法就是client使用SmartLocalDefs的主要途径,即提供一个Local和一个Unit,获取在这个Unit中所有l的defs。
三. 内部类
终于轮到苦工内部类LocalDefsAnalysis了。该类扩展了Soot框架提供的ForwardFlowAnalysis类,实现了一系列Soot进行数据流分析所需要的方法(关于这些方法的细节,可参考[3])。
这里就记录当前还没看太明白的问题:
protected void flowThrough(Object inValue, Object unit, Object outValue) {
Unit u = (Unit) unit;
HashSet in = (HashSet) inValue;
HashSet<Unit> out = (HashSet<Unit>) outValue;
out.clear();
Set mask = unitToMask.get(u);
Local l = localDef(u);
HashSet<Unit> allDefUnits = null;
if (l == null)
{//add all units contained in mask
for( Iterator inUIt = in.iterator(); inUIt.hasNext(); ) {
final Unit inU = (Unit) inUIt.next();
if( mask.contains(localDef(inU)) ){
out.add(inU);
}
}
}else
{//check unit whether contained in allDefUnits before add into out set.
allDefUnits = defsOf(l);
for( Iterator inUIt = in.iterator(); inUIt.hasNext(); ) {
final Unit inU = (Unit) inUIt.next();
if( mask.contains(localDef(inU)) )
{//only add unit not contained in allDefUnits
if ( allDefUnits.contains(inU)){
out.remove(inU);
} else {
out.add(inU);
}
}
}
out.removeAll(allDefUnits);
if(mask.contains(l)) out.add(u);
}
}
1)为什么倒数第2行还要removeAll?
2)为什么最后1行在out.add(u)之前还要判断l是否在mask中?
其实还有一个大问题:这个SmartLocalDefs和SimpleLocalDefs有什么具体区别?
等回头有时间了,再仔细琢磨琢磨吧
[1] http://www.sable.mcgill.ca/pipermail/soot-list/2008-July/001872.html
[2] http://www.sable.mcgill.ca/pipermail/soot-list/2007-March/001084.html
[3] http://www.sable.mcgill.ca/soot/tutorial/analysis/index.html