Newtank

个人站

欢迎来到我的个人站~


过程间分析

目录

调用图构造(使用CHA)

调用图

调用图是程序中调用关系的表示。其中的点是所有的方法,边是从调用者到被调用者的调用关系。

面向对象语言的调用图构造

  • 类层次分析(CHA)
  • 快速类型分析(RTA)
  • 变量类型分析(VTA)
  • 指针分析(k-CFA)

越往下越精确但越慢。

Java的方法调用

  静态调用 特殊调用 虚调用
指令 invokestatic invokespecial invokeinterface/invokevirtual
接收对象 no yes yes
目标方法类型 静态方法 私有方法、超类方法、构造方法 其他实例方法
目标方法数量 1 1 1-n(多态性)
决定时机 编译时 编译时 运行时

invokedynamic暂不考虑。

动态分派

Java在运行时使用动态分派。实际调用的对象取决于:

  • 接收对象的实际类型
  • 调用的方法签名

我们在此认定一个方法用签名来作为其标识符。

  • 签名=类+方法名+描述符
  • 描述符=返回值+参数类型

例如以下的方法

class C {
	T foo(P p, Q q, R r){}
}

其签名为<C: T foo(P,Q,R)>,简写为C.foo(P,Q,R)

我们定义函数$Dispatch(c,m)$来模拟运行时的方法分派,其中$c$是方法的实际接收对象类型,$m$是调用时的方法签名。如果$c$包含和$m$的名称与描述符相同的非抽象方法$m^{‘}$,则$Dispatch(c,m)=m^{‘}$,否则$Dispatch(c,m)=Dispatch(c^{‘},m)$,其中$c^{‘}$是$c$的超类。

类层次分析

其需要整个程序的类型层次。根据方法调用的接收变量的声明类型来解析虚调用。

类层次分析使用保守分析,认为一个变量引用可能指向其声明类型和所有子类型。

我们定义以下方法来根据解析CHA中一次调用所有可能指向的方法

CHA的优点是快,缺点是不够精确。其最常用的场景是IDE中。

通过CHA可以构建出这个程序的一个调用图

  • 从起始方法开始
  • 对每个可达的方法m,对m中每次调用cs使用Resolve(cs)来解析。
  • 重复以上直到没有发现新的方法。

过程间数据流分析

过程间控制流图

过程间控制流图(ICFG)包括方法内的CFG,还包括两种额外的边:

  • 调用边:从调用者节点指向候选方法
  • 返回边:从候选节点的退出节点指向调用的下一条语句的边

控制流分析

  过程内分析 过程间分析
程序表示 CFG ICFG
转移函数 节点转移 节点转移+边转移

边转移包括调用边转移和返回边转移。

以过程间常量传播为例

节点转移:

  • 调用类语句:单位函数(不处理)
  • 其他语句:和过程内常量传播相同

边转移:

  • 普通边:不处理、
  • 调用与返回间边:kill本地变量,传播其他本地变量
  • 调用边:传递参数值
  • 返回边:传递返回值