diff --git a/.gitbook/assets/harmonyOS (1).png b/.gitbook/assets/harmonyOS (4) (1).png
similarity index 100%
rename from .gitbook/assets/harmonyOS (1).png
rename to .gitbook/assets/harmonyOS (4) (1).png
diff --git a/.gitbook/assets/harmonyOS.png b/.gitbook/assets/harmonyOS (4) (2).png
similarity index 100%
rename from .gitbook/assets/harmonyOS.png
rename to .gitbook/assets/harmonyOS (4) (2).png
diff --git a/.gitbook/assets/harmonyOS (4) (3).png b/.gitbook/assets/harmonyOS (4) (3).png
new file mode 100644
index 0000000..885b3a2
Binary files /dev/null and b/.gitbook/assets/harmonyOS (4) (3).png differ
diff --git a/.gitbook/assets/harmonyOS (4) (4).png b/.gitbook/assets/harmonyOS (4) (4).png
new file mode 100644
index 0000000..885b3a2
Binary files /dev/null and b/.gitbook/assets/harmonyOS (4) (4).png differ
diff --git a/.gitbook/assets/harmonyOS (4).png b/.gitbook/assets/harmonyOS (4).png
new file mode 100644
index 0000000..885b3a2
Binary files /dev/null and b/.gitbook/assets/harmonyOS (4).png differ
diff --git a/.gitbook/assets/image-20201210134143907.png b/.gitbook/assets/image-20201210134143907.png
new file mode 100644
index 0000000..74be335
Binary files /dev/null and b/.gitbook/assets/image-20201210134143907.png differ
diff --git a/.gitbook/assets/image-20201210134328575.png b/.gitbook/assets/image-20201210134328575.png
new file mode 100644
index 0000000..ea65209
Binary files /dev/null and b/.gitbook/assets/image-20201210134328575.png differ
diff --git a/.gitbook/assets/image-20201210135019104.png b/.gitbook/assets/image-20201210135019104.png
new file mode 100644
index 0000000..126b73e
Binary files /dev/null and b/.gitbook/assets/image-20201210135019104.png differ
diff --git a/.gitbook/assets/image-20201210135047052.png b/.gitbook/assets/image-20201210135047052.png
new file mode 100644
index 0000000..eaf6714
Binary files /dev/null and b/.gitbook/assets/image-20201210135047052.png differ
diff --git a/.gitbook/assets/image-20201210145819255.png b/.gitbook/assets/image-20201210145819255.png
new file mode 100644
index 0000000..4d52e92
Binary files /dev/null and b/.gitbook/assets/image-20201210145819255.png differ
diff --git a/.gitbook/assets/image-20201210151627827.png b/.gitbook/assets/image-20201210151627827.png
new file mode 100644
index 0000000..b9a8f9b
Binary files /dev/null and b/.gitbook/assets/image-20201210151627827.png differ
diff --git a/.gitbook/assets/image-20201210165334864.png b/.gitbook/assets/image-20201210165334864.png
new file mode 100644
index 0000000..04f4f01
Binary files /dev/null and b/.gitbook/assets/image-20201210165334864.png differ
diff --git a/.gitbook/assets/image-20201210183358390.png b/.gitbook/assets/image-20201210183358390.png
new file mode 100644
index 0000000..4e65935
Binary files /dev/null and b/.gitbook/assets/image-20201210183358390.png differ
diff --git a/.gitbook/assets/image-20201210183700963.png b/.gitbook/assets/image-20201210183700963.png
new file mode 100644
index 0000000..d395056
Binary files /dev/null and b/.gitbook/assets/image-20201210183700963.png differ
diff --git a/.gitbook/assets/image-20201210184448955.png b/.gitbook/assets/image-20201210184448955.png
new file mode 100644
index 0000000..619ac1c
Binary files /dev/null and b/.gitbook/assets/image-20201210184448955.png differ
diff --git a/.gitbook/assets/image-20201210184527645.png b/.gitbook/assets/image-20201210184527645.png
new file mode 100644
index 0000000..39f02f4
Binary files /dev/null and b/.gitbook/assets/image-20201210184527645.png differ
diff --git a/.gitbook/assets/image-20201210184850528.png b/.gitbook/assets/image-20201210184850528.png
new file mode 100644
index 0000000..4c4ea8e
Binary files /dev/null and b/.gitbook/assets/image-20201210184850528.png differ
diff --git a/.gitbook/assets/image-20201210191310040.png b/.gitbook/assets/image-20201210191310040.png
new file mode 100644
index 0000000..a32d885
Binary files /dev/null and b/.gitbook/assets/image-20201210191310040.png differ
diff --git a/.gitbook/assets/image-20201210192001954.png b/.gitbook/assets/image-20201210192001954.png
new file mode 100644
index 0000000..4076d86
Binary files /dev/null and b/.gitbook/assets/image-20201210192001954.png differ
diff --git a/.gitbook/assets/image-20201210193321202.png b/.gitbook/assets/image-20201210193321202.png
new file mode 100644
index 0000000..1f8ce15
Binary files /dev/null and b/.gitbook/assets/image-20201210193321202.png differ
diff --git a/.gitbook/assets/image-20201210193735607.png b/.gitbook/assets/image-20201210193735607.png
new file mode 100644
index 0000000..d80033f
Binary files /dev/null and b/.gitbook/assets/image-20201210193735607.png differ
diff --git a/.gitbook/assets/image-20201210195519912.png b/.gitbook/assets/image-20201210195519912.png
new file mode 100644
index 0000000..25fb594
Binary files /dev/null and b/.gitbook/assets/image-20201210195519912.png differ
diff --git a/.gitbook/assets/image-20201210200518022.png b/.gitbook/assets/image-20201210200518022.png
new file mode 100644
index 0000000..ea5abee
Binary files /dev/null and b/.gitbook/assets/image-20201210200518022.png differ
diff --git a/.gitbook/assets/image-20201210200637330.png b/.gitbook/assets/image-20201210200637330.png
new file mode 100644
index 0000000..d6fa71f
Binary files /dev/null and b/.gitbook/assets/image-20201210200637330.png differ
diff --git a/.gitbook/assets/image-20201210201540194.png b/.gitbook/assets/image-20201210201540194.png
new file mode 100644
index 0000000..552016a
Binary files /dev/null and b/.gitbook/assets/image-20201210201540194.png differ
diff --git a/.gitbook/assets/image-20201216173124146.png b/.gitbook/assets/image-20201216173124146.png
new file mode 100644
index 0000000..2bddf83
Binary files /dev/null and b/.gitbook/assets/image-20201216173124146.png differ
diff --git a/.gitbook/assets/image-20201216175534756.png b/.gitbook/assets/image-20201216175534756.png
new file mode 100644
index 0000000..6b6727d
Binary files /dev/null and b/.gitbook/assets/image-20201216175534756.png differ
diff --git a/.gitbook/assets/image-20201216175748133.png b/.gitbook/assets/image-20201216175748133.png
new file mode 100644
index 0000000..42be157
Binary files /dev/null and b/.gitbook/assets/image-20201216175748133.png differ
diff --git a/.gitbook/assets/image-20201216180114246.png b/.gitbook/assets/image-20201216180114246.png
new file mode 100644
index 0000000..3bf26c9
Binary files /dev/null and b/.gitbook/assets/image-20201216180114246.png differ
diff --git a/.gitbook/assets/image-20201216180216650.png b/.gitbook/assets/image-20201216180216650.png
new file mode 100644
index 0000000..170ed56
Binary files /dev/null and b/.gitbook/assets/image-20201216180216650.png differ
diff --git a/.gitbook/assets/image-20201216180422745.png b/.gitbook/assets/image-20201216180422745.png
new file mode 100644
index 0000000..fd0e97a
Binary files /dev/null and b/.gitbook/assets/image-20201216180422745.png differ
diff --git a/.gitbook/assets/image-20201216180523896.png b/.gitbook/assets/image-20201216180523896.png
new file mode 100644
index 0000000..6c5f10e
Binary files /dev/null and b/.gitbook/assets/image-20201216180523896.png differ
diff --git a/.gitbook/assets/image-20201216202538515.png b/.gitbook/assets/image-20201216202538515.png
new file mode 100644
index 0000000..b8bfbda
Binary files /dev/null and b/.gitbook/assets/image-20201216202538515.png differ
diff --git a/.gitbook/assets/image-20201216204823876.png b/.gitbook/assets/image-20201216204823876.png
new file mode 100644
index 0000000..06e6730
Binary files /dev/null and b/.gitbook/assets/image-20201216204823876.png differ
diff --git a/.gitbook/assets/image-20201216205125278.png b/.gitbook/assets/image-20201216205125278.png
new file mode 100644
index 0000000..0328b62
Binary files /dev/null and b/.gitbook/assets/image-20201216205125278.png differ
diff --git a/.gitbook/assets/image-20201216210158092.png b/.gitbook/assets/image-20201216210158092.png
new file mode 100644
index 0000000..8befdf7
Binary files /dev/null and b/.gitbook/assets/image-20201216210158092.png differ
diff --git a/.gitbook/assets/image-20201216210347469.png b/.gitbook/assets/image-20201216210347469.png
new file mode 100644
index 0000000..afc0a38
Binary files /dev/null and b/.gitbook/assets/image-20201216210347469.png differ
diff --git a/README.md b/README.md
index fb361e6..1aff0f8 100644
--- a/README.md
+++ b/README.md
@@ -6,31 +6,31 @@ Getting started with static program analysis. Read this and start writing your f
> ❓ How to automatically and efficiently guarantee software quality
-静态程序分析入门。阅读此书并着手编写你的第一个静态程序分析器吧!本仓库关注一个非常重要的问题:
+静态程序分析入门。阅读此书并着手编写你的第一个静态程序分析器吧!本仓库关注一个非常重要的问题:
> ❓ 如何自动化地高效保障软件质量
* [《静态程序分析》Gitbook在线阅读地址](https://ranger-nju.gitbook.io/static-program-analysis-book/)
+ * 有时gitbook需要科学上网才能访问,没法科学上网的小伙伴可以试试访问[这里](https://spa-book.pblo.gq/)。
* [《静态程序分析》GitHub项目地址](https://github.com/RangerNJU/Static-Program-Analysis-Book)
* 离线阅读方式
1. 将本仓库**下载**到本地(安装Git后,在命令行中执行命令`git clone https://github.com/RangerNJU/Static-Program-Analysis-Book.git`)
2. 周期性地**更新**,在仓库目录下执行`git pull`
3. 使用[Typora](https://typora.io/)等本地Markdown阅读器**阅读**
-### 表达你的声音 👂
+### 表达你的声音 👂
* **批评的意见很有价值。** 这是我第一次书写教程,一定有很多做得不好的地方。如果你觉得有值得修改或值得讨论的地方(包括但不仅限于行文风格,内容准确性,图例与解释的易读性等等),可以选择:
-
-1. 加入QQ群(951182704)匿名或实名表达你的意见与看法
-2. 提issue
-3. 通过邮箱联系我(ranger.nju\#gmail.com\)
- * 如果你觉得我写得不错,可以到GitHub仓库中给我一个Star,也可以在自己的社交圈子中宣传,让更多的人了解这个项目。
-
+* 加入QQ群(951182704)匿名或实名表达你的意见与看法
+* 提issue
+* 通过邮箱联系我(ranger.nju\#gmail.com\)
+ * 如果你觉得我写得不错,可以到GitHub仓库中给我一个Star,也可以在自己的社交圈子中宣传,让更多的人了解这个项目。
### 更新记录与里程碑事件
-1. Oct, 2020. 设立Repo,一个月内获得Star、Fork和PR 🥳
+1. Oct, 2020. 设立Repo,一个月内解锁Star、Fork和PR。
2. Nov. 将IR与Data Flow Analysis的相关内容暂时移出仓库,更新七至十课——Interprocedural Analysis、Pointer Analysis-Introduction and Foundations。
+3. Dec. 更新十一和十二两课——Context Sensitive Pointer Analysis,指针分析大结局。🥳
## 这一《静态程序分析》教程对谁有用?
@@ -58,7 +58,7 @@ Getting started with static program analysis. Read this and start writing your f
#### 编程语言的分类
-当今的计算机世界,面对这样一条恶龙: 👇
+当今的计算机世界,面对这样一条恶龙: 👇
> 数十年来语言的核心没有变化,但软件的规模和复杂性增长迅速,如何保证程序的可靠性?
@@ -126,7 +126,7 @@ Getting started with static program analysis. Read this and start writing your f
1. 学术门槛较高,学习者必须有良好的数学基础才能入门。
2. 验证代价较高,一般来说非常重要的项目会使用这一方式保证程序质量。甚至在操作系统这样重要的软件中,也并不一定会使用。\(截图来自鸿蒙OS直播发布会\)
-![](.gitbook/assets/harmonyOS%20%281%29.png)
+![](.gitbook/assets/harmonyOS%20%284%29%20%284%29.png)
## 加入项目/How to contribute
@@ -134,6 +134,8 @@ Getting started with static program analysis. Read this and start writing your f
欢迎希望添加更好的讲解资料或对教程内容进行扩充的小伙伴 `fork, modify, PR` 三连。
+**提醒:引用图片时请使用相对路径。**
+
## 本地化/Localization
We'd love help translating this book! Open a new issue to start working on a new language. Feel free to start :\)
diff --git a/SUMMARY.md b/SUMMARY.md
index adeb5cc..021450d 100644
--- a/SUMMARY.md
+++ b/SUMMARY.md
@@ -1,13 +1,28 @@
# Table of contents
* [简介](README.md)
+
+## 前言
+
* [写在前面](ch0/README.md)
* [为什么是这本书?](ch0/00-01-why-this-book.md)
* [资料来源与版权信息](ch0/00-02-sources-and-license.md)
-* [静态程序分析简介与数据流分析](ch1.md)
-* [过程间分析](ch2/README.md)
- * [过程间分析简介](ch2/02-01-inter-analysis-spa.md)
- * [指针分析简介](ch2/02-02-pointer-analysis-spa.md)
- * [指针分析理论一](ch2/02-03-pointer2-analysis-spa.md)
- * [指针分析理论二](ch2/02-04-pointer3-analysis-spa.md)
+
+## 数据流分析
+
+* [静态程序分析简介与数据流分析](ch1/ch1.md)
+
+## 过程间分析
+
+* [过程间分析简介](ch2/ch2.md)
+
+## 指针分析
+
+* [指针分析简介](ch3/pointer-analysis/README.md)
+ * [指针分析简介](ch3/pointer-analysis/03-01-pointer-analysis-spa.md)
+ * [指针分析理论(上)](ch3/pointer-analysis/03-02-pointer2-analysis-spa.md)
+ * [指针分析理论(下)](ch3/pointer-analysis/03-03-pointer3-analysis-spa.md)
+* [指针分析进阶](ch3/context-sensitivity/README.md)
+ * [上下文敏感分析(上)](ch3/context-sensitivity/03-04-context-sensitivity.md)
+ * [上下文敏感分析(下)](ch3/context-sensitivity/03-05-cs2.md)
diff --git a/ch1.md b/ch1/ch1.md
similarity index 100%
rename from ch1.md
rename to ch1/ch1.md
diff --git a/ch2/README.md b/ch2/README.md
deleted file mode 100644
index 04d22ec..0000000
--- a/ch2/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# 过程间分析
-
-**阅读提示:使用屏幕较大的设备能够看到自带的Sticky Table of Contents,更有利于理清阅读思路。**
-
-对应视频在:
-
-* [第七课-过程间分析](https://www.bilibili.com/video/BV1GQ4y1T7zm)
-* [第八课-指针分析](https://www.bilibili.com/video/BV1gg4y1z78p)
-
diff --git a/ch2/02-01-inter-analysis-spa.md b/ch2/ch2.md
similarity index 96%
rename from ch2/02-01-inter-analysis-spa.md
rename to ch2/ch2.md
index c918e7f..60a2861 100644
--- a/ch2/02-01-inter-analysis-spa.md
+++ b/ch2/ch2.md
@@ -1,5 +1,12 @@
# 过程间分析简介
+**阅读提示:使用屏幕较大的设备能够看到自带的Sticky Table of Contents,更有利于理清阅读思路。**
+
+对应视频在:
+
+* [第七课-过程间分析](https://www.bilibili.com/video/BV1GQ4y1T7zm)
+* [第八课-指针分析](https://www.bilibili.com/video/BV1gg4y1z78p)
+
## 过程间分析简介
本小节通过四个部分介绍过程间分析。
@@ -178,15 +185,15 @@ A:分别调用A和C中定义的foo方法。
![](../.gitbook/assets/image-20201029230504891.png)
-2. 处理main后向WL中加入A.foo\(\)
+1. 处理main后向WL中加入A.foo\(\)
![](../.gitbook/assets/image-20201029230535984.png)
-3. 中间省略一些步骤,这里面对C.bar\(\)时,虽然会调用A.foo\(\),但由于A.foo\(\)之前已经处理过(在集合RM中),之后不会再进行处理
+1. 中间省略一些步骤,这里面对C.bar\(\)时,虽然会调用A.foo\(\),但由于A.foo\(\)之前已经处理过(在集合RM中),之后不会再进行处理
![](../.gitbook/assets/image-20201029230622120.png)
-4. 这里C.m\(\)是不可达的死代码
+1. 这里C.m\(\)是不可达的死代码
![](../.gitbook/assets/image-20201029230909895.png)
@@ -260,8 +267,6 @@ Edge transfer处理引入的call & return edge。为此,我们需要**在之
## Key points
-**The X You Need To Understand in This Lecture**
-
1. How to build call graph via class hierarchy analysis
* 如何利用CHA构建调用关系图\(call graph\)
2. Concept of interprocedural control-flow graph
diff --git a/ch3/context-sensitivity/03-04-context-sensitivity.md b/ch3/context-sensitivity/03-04-context-sensitivity.md
new file mode 100644
index 0000000..2a858d8
--- /dev/null
+++ b/ch3/context-sensitivity/03-04-context-sensitivity.md
@@ -0,0 +1,153 @@
+# 上下文敏感分析(上)
+
+> 上下文敏感分析是提高指针分析精度最有效的技术,没有之一。
+
+本课分为以下五个部分:
+
+1. Introduction\(Example\)
+2. Introduction\(Theory\)
+3. Context Sensitive Pointer Analysis: Rules
+4. Context Sensitive Pointer Analysis: Algorithms
+5. Context Sensitivity Variants
+
+在上半篇中我们讲解前三个部分,下半篇会继续讲最后的两个部分。
+
+## Introduction\(example\)
+
+首先用一个例子直观地说明上下文不敏感分析的问题所在。
+
+```java
+void main() {
+Number n1, n2, x, y;
+ n1 = new One(); // 𝑜1
+ n2 = new Two(); // 𝑜2
+ x = id(n1);
+ y = id(n2);
+ int i = x.get();
+ //假设使用我们之前所讲述的上下文不敏感分析
+ //这里i的常量分析结果是什么?
+}
+Number id(Number n) {
+ return n;
+}
+interface Number {
+ int get();
+}
+class One implements Number {
+ public int get() { return 1; }
+}
+class Two implements Number {
+ public int get() { return 2; }
+}
+```
+
+使用我们之前描述的算法,由于不考虑调用的顺序,会得到这样的PFG。
+
+![](../../.gitbook/assets/image-20201210134143907.png)
+
+也就因此造成了分析结果的低精度,即在动态运行时i一定是1,而分析的结果认为i为NAC\(Not a constant\):
+
+![](../../.gitbook/assets/image-20201210134328575.png)
+
+如果我们使用上下文敏感的分析方式,区分不同时间对的id调用,则会得到这样的PFG:
+
+![](../../.gitbook/assets/image-20201210135019104.png)
+
+对应地也就能得到更为精确的分析结果:
+
+![](../../.gitbook/assets/image-20201210135047052.png)
+
+## Introduction\(Theory\)
+
+### C.I.\(Context Insensitive\)
+
+是什么原因导致了上下文不敏感分析的低精度?
+
+1. 在动态执行时,对同一个函数的不同调用,往往有着不同的调用上下文(calling contexts),如上一小节的例子中两次对id的调用。
+2. 不同的调用上下文会被混合并传播,进而形成假的数据流。如上一小节的例子中指针x和y指向两个目标。
+
+### C.S.\(Context Sensitive\)
+
+上下文敏感分析通过区分不同调用上下文的数据流,对调用上下文建模。举个例子,在这一段代码中,对id调用的上下文就是两行call-site,记为\[1\]和\[2\]:
+
+```java
+x = id(n1); //context 1 for id()
+y = id(n2); //context 2 for id()
+int i = x.get();
+
+Number id(Number n) {
+ return n;
+}
+```
+
+进而,我们可以**通过对同一函数的不同调用添加标号进行区分**,而得到更精确的PFG:
+
+![](../../.gitbook/assets/image-20201210145819255.png)
+
+### C.S. heap
+
+**对于Java中被动态分配到heap上的对象,我们也需要对他们做相应的标记以提高分析精度。**例子:~~(或许真的需要录视频了?)~~
+
+* 不做标记时,第八行new出来的对象无法区分,只能同一记作 $$o_8$$
+* 做标记后,可以分别记为$$ 3:o_8$$和$$ 4:o_8$$
+
+![](../../.gitbook/assets/image-20201210151627827.png)
+
+不过,采取C.I.+ C.S. heap进行分析时,C.S. heap就不能提高精度了。
+
+![](../../.gitbook/assets/image-20201210165334864.png)
+
+## Context Sensitive Pointer Analysis: Rules
+
+### Domains and Notations
+
+接下来我们用介绍适用于上下文敏感分析的规则。
+
+首先我们讨论的Domain中,methods/variables/objects都升级为带有上下文标识的。
+
+![](../../.gitbook/assets/image-20201216173124146.png)
+
+新引入符号说明:引入C表示所有的上下文组成的集合,c表示具体的某个上下文。
+
+值得一提的是,fields不需要带有上下文标记,因为field总是依赖于某一个object。只要object被标记进而通过上下文可被区分了,fields自然也可以被区分。一个不太准确但是可以帮助理解的例子是,如果你能区分一对双胞胎,那么他/她们口袋里的东西也是可以被区分的。
+
+### Rules
+
+首先我们考虑不包含调用(Call)语句的四类语句所对应的规则。
+
+![](../../.gitbook/assets/image-20201216175534756.png)
+
+对比一下上下文不敏感指针分析的规则:
+
+![](../../.gitbook/assets/image-20201216175748133.png)
+
+**唯一的区别在于,对象被加上了上下文标识。**
+
+然后我们来看看调用如何处理。在上下文敏感的指针分析中,规则如下:
+
+![](../../.gitbook/assets/image-20201216180216650.png)
+
+再次对比一下上下文不敏感指针分析的规则:
+
+![](../../.gitbook/assets/image-20201216180114246.png)
+
+**这次我们添加了一个Select函数,它的作用是为object添加上下文标识,例如:**
+
+* 为参数添加上下文标识
+
+![](../../.gitbook/assets/image-20201216180422745.png)
+
+* 为返回值添加上下文标识
+
+![](../../.gitbook/assets/image-20201216180523896.png)
+
+**也就是说,上下文的信息是在处理调用时添加的。**
+
+## Key points
+
+* Concept of context sensitivity \(**C.S.**\)
+* Concept of context-sensitive heap \(**C.S. heap**\)
+* **Why** C.S. **and** C.S. heap improve **precision**
+ * 单独使用C.S.或C.S. heap依然会损失精度
+* Context-sensitive pointer analysis **rules**
+
diff --git a/ch3/context-sensitivity/03-05-cs2.md b/ch3/context-sensitivity/03-05-cs2.md
new file mode 100644
index 0000000..771671b
--- /dev/null
+++ b/ch3/context-sensitivity/03-05-cs2.md
@@ -0,0 +1,264 @@
+# 上下文敏感分析(下)
+
+> 上下文敏感分析是提高指针分析精度最有效的技术,没有之一。
+
+本课分为以下五个部分:
+
+1. Introduction\(Example\)
+2. Introduction\(Theory\)
+3. Context Sensitive Pointer Analysis: Rules
+4. Context Sensitive Pointer Analysis: Algorithms
+5. Context Sensitivity Variants
+
+在上半篇中我们讲解了前三个部分,下半篇来继续讲最后的两个部分。
+
+~~挖个坑——本文所有的例子其实都更适合视频讲解。~~
+
+## Context Sensitive Pointer Analysis: Algorithms
+
+### Idea
+
+除了PFG做了相应改进之外,算法的总体思路没有改变。
+
+![](../../.gitbook/assets/image-20201210183358390.png)
+
+具体来说,带有上下文信息的Node和Edge的构成带有上下文信息的PFG:
+
+![](../../.gitbook/assets/image-20201210183700963.png)
+
+### Algorithm
+
+![](../../.gitbook/assets/image-20201210184448955.png)
+
+乍一看挺吓人的,对吧?不过你应该对上下文敏感\(C.S.\)指针分析算法的小伙伴上下文不敏感\(C.I.\)指针分析算法很熟悉了(下图中所有上下文标记都用色块遮挡了):
+
+![](../../.gitbook/assets/image-20201210184527645.png)
+
+因此,在接下来的内容中我们更关注和上下文相关的部分,而不像之前一样详细地关注所有细节。
+
+值得一提的差异是,RM和CG两个集合在本节所述的上下文敏感算法中都是带有上下文信息的。举个例子,在C.S.的分析中,caller和callee都带有上下文信息($$c^t$$ 代表callee的上下文标记,c:2->$$c^t:\dots$$表示第二行的caller调用了带有$$c^t$$标记的callee):
+
+![](../../.gitbook/assets/image-20201210184850528.png)
+
+### Select in ProcessCall
+
+![](../../.gitbook/assets/image-20201216202538515.png)
+
+在这一部分,我们只需要理解Select的作用(对于Select的具体实现,会在后面讲解):
+
+* ProcessCall接收两个参数,意义是:带有上下文标记的x新增一个带有上下文标记指向目标o。
+* Select接收参数(这里虽然有4个参数,但并非每种实现方式都需要用到所有的4个参数)
+ * c。x的上下文标记
+ * l。调用点本身(call site),在例子中以行号标识调用点
+ * $$c' : o_i $$。receiver object
+ * m。 目标method
+* Select返回callee的context $$ c^t$$
+
+## Context Sensitivity Variants
+
+> 那,讲讲Select吧?
+
+Select函数实现时的具体差异,产生了不同的上下文敏感分析的变种方法,它们有不同的优缺点。具体来说,就是
+
+![](../../.gitbook/assets/image-20201210191310040.png)
+
+### C.I.
+
+* 可以视为**C.S. 的一种特殊情况**,无论传递给Select的参数是什么,总是返回同样的上下文。即:
+
+```java
+Select(*,*,*) = []
+```
+
+### Call-Site Sensitivity
+
+* 用一系列的**调用链\(call chain/call stream\)作为上下文标识**。
+* Also called **call-string sensitivity**, or **k-CFA**
+
+```java
+Select(c,l,*) = [𝑙`, 𝑙``, 𝑙]
+// where 𝑐 = [𝑙`, … , 𝑙``]
+// 即:只根据caller已有的上下文和
+// call-site的新增上下文
+// 计算callee的上下文
+```
+
+举个例子直观地展示Call-Site Sensitivity:
+
+![](../../.gitbook/assets/image-20201210192001954.png)
+
+当然,如果bar是递归的,分析出来的context可能会包含非常多的内容……
+
+![](../../.gitbook/assets/image-20201210193321202.png)
+
+#### k-Limiting Context Abstraction
+
+为了避免上面所说的递归导致的算法无法终止的情况,我们可以给contexts的长度设一个上界k。
+
+* 1-call-site/1-CFA
+
+ ```java
+ Select(*,l,*) = [l]
+ // 即:不继承caller已经带有的上下文
+ // 只考虑call-site新引入的上下文
+ // "只记得最近一次经过的路口是哪一个"
+ ```
+
+ ![](../../.gitbook/assets/image-20201210193735607.png)
+
+* 2-call-site/2-CFA
+
+ ```java
+ Select(c,l,*) = [l``,l]
+ // where c = [l`,l``]
+ // 即:"只记得最后两次经过的路口是哪两个"
+ ```
+
+### Call-Site Example
+
+分析以下代码,给出指针流图PFG和调用关系图CG作为结果。(不需要关注heap上的变量和this变量,因为它们在这个例子中不是重点)
+
+```java
+class C {
+ static void main() {
+ C c = new C();
+ c.m();
+ }
+
+ Number id(Number n) {
+ return n;
+ }
+ void m() {
+ Number n1,n2,x,y;
+ n1 = new One();
+ n2 = new Two();
+ x = this.id(n1);
+ y = this.id(n2);
+ x.get();
+ // 先想想动态执行的时候上一行调用的结果是什么?
+ }
+}
+```
+
+答案如下:
+
+![](../../.gitbook/assets/image-20201216204823876.png)
+
+和C.I.对比,我们可以发现对于16行处的分析,C.S.\(1-Call-Site\)更加精确。
+
+![](../../.gitbook/assets/image-20201216205125278.png)
+
+### Object Sensitivity
+
+* **以receiver object作为上下文标识**
+* Each context consists of a list of abstract objects \(represented by their allocation sites\)
+ * At a method call, use the receiver object with its heap
+
+ context as callee context
+
+ * Distinguish the operations of data flow on different objects
+* ![](../../.gitbook/assets/image-20201210195519912.png)
+
+### Object Example & Comparison
+
+分别用1-Call-Site和1-Object的方式分析以下代码,给出所有指针(包括Variable和Field)所指向的对象。
+
+```java
+a1 = new A();
+a2 = new A();
+b1 = new B();
+b2 = new B();
+a1.set(b1);
+a2.set(b2);
+x = a1.get();
+
+class A {
+ B f;
+ void set(B b) {
+ this.doSet(b);
+ }
+ void doSet(B p) {
+ this.f = p;
+ }
+ B get() {
+ return this.f;
+ }
+}
+```
+
+![](../../.gitbook/assets/image-20201210200518022.png)
+
+在12行,1-call-site的分析方法产生了不精确分析结果。在Call Graph中我们能够更好地看到这一点:
+
+![](../../.gitbook/assets/image-20201210200637330.png)
+
+更加通俗地说,1-call-site只能记得自己是从哪个路口走到当前位置的,而1-object能够记得自己是谁。
+
+然而并不能说明1-object的精度一定比1-call-site高。比如在分析以下代码时:
+
+```java
+class C {
+ static void main() {
+ C c = new C();
+ c.m();
+ }
+
+ Number id(Number n) {
+ return n;
+ }
+
+ void m() {
+ Number n1,n2,x,y;
+ n1 = new One();
+ n2 = new Two();
+ x = this.id(n1);
+ y = this.id(n2);
+ // 1-object无法区分以上两条调用
+ // 但是1-call-site可以区分
+ x.get();
+ }
+}
+```
+
+因此,在**理论上**,两种方法不可比。而在针对OO语言\(如Java\)的**实践中**,object方法的表现(无论是精度还是速度)**通常**更好,因为这更符合OO语言的特性。
+
+### Type Sensitivity
+
+* 和Object Sensitivity类似,但是粒度更粗而效率更高——这种方法只关注Object是在哪一个Class中被声明的。
+* Each context consists of a list of types
+ * At a method call, use the type containing the allocation site of the receiver object with its heap context as callee context
+
+![](../../.gitbook/assets/image-20201210201540194.png)
+
+例如(如果你发现这个例子不太好理解,请先往下看看下一个例子):
+
+![](../../.gitbook/assets/image-20201216210158092.png)
+
+### Comparison\(Type vs. Object Sensitivity\)
+
+阅读顺序建议:绿框->蓝框->无框。在Object-sensitivity中我们记录下每一个object被声明出来的行数。在Type-sensitivity中我们只记录它们都是在Class X中声明的。
+
+![](../../.gitbook/assets/image-20201216210347469.png)
+
+### Sum up
+
+In general:
+
+* Precision: object > type > call-site
+* Efficiency: type > object > call-site
+
+## Key points
+
+* **Algorithm** for context-sensitive pointer analysis
+ * 和C.I.几乎一致
+* 3 Common context sensitivity **variants**
+ * Call-Site Sensitivity
+ * Object Sensitivity
+ * Type Sensitivity
+* **Differences and relationship** among common
+
+ context sensitivity variants
+
+ * 在面向对象语言(如Java)中,Object Sensitivity通常比Call-Site Sensitivity表现更好
+ * 如果追求速度,可以进而选用Type Sensitivity
+
diff --git a/ch3/context-sensitivity/README.md b/ch3/context-sensitivity/README.md
new file mode 100644
index 0000000..ceed470
--- /dev/null
+++ b/ch3/context-sensitivity/README.md
@@ -0,0 +1,3 @@
+# 指针分析进阶
+
+这一部分介绍精度更高的上下文敏感指针分析。
\ No newline at end of file
diff --git a/ch2/02-02-pointer-analysis-spa.md b/ch3/pointer-analysis/03-01-pointer-analysis-spa.md
similarity index 83%
rename from ch2/02-02-pointer-analysis-spa.md
rename to ch3/pointer-analysis/03-01-pointer-analysis-spa.md
index b83a437..06eeaec 100644
--- a/ch2/02-02-pointer-analysis-spa.md
+++ b/ch3/pointer-analysis/03-01-pointer-analysis-spa.md
@@ -15,23 +15,23 @@
接下来我们对比基于CHA的分析方法和指针分析的分析方法。首先,回想一下CHA的构造过程。在这个程序中对`get()`的调用,在CHA分析下,应该调用哪几个方法?
-![](../.gitbook/assets/image-20201105183618529.png)
+![](../../.gitbook/assets/image-20201105183618529.png)
### 使用CHA分析
-![](../.gitbook/assets/image-20201109140057119.png)
+![](../../.gitbook/assets/image-20201109140057119.png)
可以看出,由于只关心类的层次结构,分析结果的三个箭头中有两个是false positive。也因此导致了分析结果的不精确。
-![](../.gitbook/assets/image-20201109140605829.png)
+![](../../.gitbook/assets/image-20201109140605829.png)
### 使用指针分析
利用指针分析,我们能知道n指向的对象就是new One\(\)语句所新建出来的对象。所以能精确地知道x一定会取1。
-![](../.gitbook/assets/image-20201109154728420.png)
+![](../../.gitbook/assets/image-20201109154728420.png)
-![](../.gitbook/assets/image-20201109154844509.png)
+![](../../.gitbook/assets/image-20201109154844509.png)
**比较两种分析,可以看出CHA速度快而精度低,接下来我们学习高精度的指针分析。**
@@ -44,7 +44,7 @@
什么是指针分析呢?举个例子(省略中间过程):
-![](../.gitbook/assets/image-20201105184327763.png)
+![](../../.gitbook/assets/image-20201105184327763.png)
### 区分指针分析与别名分析
@@ -71,7 +71,7 @@ y = new Y();
> 业界大佬们说它很重要。
-![](../.gitbook/assets/image-20201105184919660.png)
+![](../../.gitbook/assets/image-20201105184919660.png)
## Key Factors of Pointer Analysis
@@ -80,7 +80,7 @@ y = new Y();
* Pointer analysis is a complex system
* Multiple factors affect the precision and efficiency of the system
-![](../.gitbook/assets/image-20201105185230667.png)
+![](../../.gitbook/assets/image-20201105185230667.png)
### Heap Abstraction
@@ -94,17 +94,17 @@ for (…) {
解决方法也很简单,学校里同学太多了就分成班级来管理,我们也可以对堆上的对象进行抽象:
-![](../.gitbook/assets/image-20201105185431196.png)
+![](../../.gitbook/assets/image-20201105185431196.png)
相关的技术有很多,这里只讲一个最常用的分支Allocation-Site Abstraction。而Storeless的方法本课程不涉及。
-![](../.gitbook/assets/image-20201105185630758.png)
+![](../../.gitbook/assets/image-20201105185630758.png)
#### Allocation-Site Abstraction
虽然动态时对象的个数可能是无限的,但是new语句的个数一定是有限的。我们可以按照new语句来进行抽象。
-![](../.gitbook/assets/image-20201105185806532.png)
+![](../../.gitbook/assets/image-20201105185806532.png)
### Context Sensitivity
@@ -112,11 +112,11 @@ for (…) {
如果将上下文做区分(进行额外的标记,如记录下图中p指向的目标),对参数不同时的调用做不同的分析,则称为**上下文敏感分析**。
-![](../.gitbook/assets/image-20201105190333596.png)
+![](../../.gitbook/assets/image-20201105190333596.png)
反之,如果不区分上下文,则称为**上下文不敏感分析**。由于忽略了一部分信息,可能会损失分析的精度。
-![](../.gitbook/assets/image-20201105190439805.png)
+![](../../.gitbook/assets/image-20201105190439805.png)
我们首先学习不敏感的分析方法,在之后的课程中介绍上下文敏感分析。
@@ -135,11 +135,11 @@ c.f = "y";
对于流敏感的分析,会得到如下的mapping。`o1`代表在第一行动态分配的对象。
-![](../.gitbook/assets/image-20201105191248594.png)
+![](../../.gitbook/assets/image-20201105191248594.png)
如果使用流不敏感的分析,会得到如下的mapping。
-![](../.gitbook/assets/image-20201105191705757.png)
+![](../../.gitbook/assets/image-20201105191705757.png)
### Analysis Scope
@@ -162,7 +162,7 @@ Java中的Pointers有以下几类:
* Array element: array\[i\]
* 涉及数组的分析中,我们**忽略下标**,代之以一个域(a single field)。例如,在下图中我们用arr表示。
* 原因之一:数组下标是变量时难以计算具体值
- * 在之后介绍的算法中,**可作为Instance field处理**![](../.gitbook/assets/image-20201105194030384.png)
+ * 在之后介绍的算法中,**可作为Instance field处理**![](../../.gitbook/assets/image-20201105194030384.png)
### 关注的语句类型
@@ -187,12 +187,11 @@ r = x.k(a, …)
复杂的Store和Load指令可以解构成简单的,所以我们可以只考虑对上述五种基本类型语句的分析:
-![](../.gitbook/assets/image-20201105194707507.png)
+![](../../.gitbook/assets/image-20201105194707507.png)
## Key points
-**The X You Need To Understand in This Lecture**
+* **What is pointer analysis?**
+* Understand **the key factors** of pointer analysis
+* Understand **what we analyze** in pointer analysis
-- **What is pointer analysis?**
-- Understand **the key factors** of pointer analysis
-- Understand **what we analyze** in pointer analysis
\ No newline at end of file
diff --git a/ch2/02-03-pointer2-analysis-spa.md b/ch3/pointer-analysis/03-02-pointer2-analysis-spa.md
similarity index 79%
rename from ch2/02-03-pointer2-analysis-spa.md
rename to ch3/pointer-analysis/03-02-pointer2-analysis-spa.md
index dc212ac..d07fb98 100644
--- a/ch2/02-03-pointer2-analysis-spa.md
+++ b/ch3/pointer-analysis/03-02-pointer2-analysis-spa.md
@@ -1,4 +1,4 @@
-# 指针分析理论基础一
+# 指针分析理论(上)
接下来两篇文章将主要介绍以下四点内容。前三点对应线下课程第九课,最后一点对应第十课。
@@ -11,11 +11,11 @@
## Notations
-![](../.gitbook/assets/image-20201105195029800.png)
+![](../../.gitbook/assets/image-20201105195029800.png)
首先介绍常用数学符号,不会的同学可以复习一下离散数学。
-![](../.gitbook/assets/image-20201105195154527.png)
+![](../../.gitbook/assets/image-20201105195154527.png)
分别定义变量,域,对象(用下标标识是在第几行创建的对象),实例域和指针(是变量和实例对象的并),和指向关系。`X`表示笛卡尔积。
@@ -33,29 +33,29 @@ if(...){
_前排提示:与《数理逻辑》/《形式化语义》梦幻联动。没学过的同学也不要着急。_
-![](../.gitbook/assets/image-20201105195524932.png)
+![](../../.gitbook/assets/image-20201105195524932.png)
主要解释Rule一列中的内容。**横线上的内容是前提\(Premises\),横线下的内容是结论\(Conclusion\)。**
用简单易懂的语言描述,看到new语句,我们就将新建的对象加入`pt(x)`。
-![](../.gitbook/assets/image-20201105195943007.png)
+![](../../.gitbook/assets/image-20201105195943007.png)
对于Assign语句,我们将x指向y指向的对象。
-![](../.gitbook/assets/image-20201105235312349.png)
+![](../../.gitbook/assets/image-20201105235312349.png)
对于Store和Load亦然。
-![](../.gitbook/assets/image-20201105200112512.png)
+![](../../.gitbook/assets/image-20201105200112512.png)
-![](../.gitbook/assets/image-20201105200123601.png)
+![](../../.gitbook/assets/image-20201105200123601.png)
### Summary
最后用一图总结。**第一条规则添加指向,而后三条规则传递指向关系。**
-![](../.gitbook/assets/image-20201105200412145.png)
+![](../../.gitbook/assets/image-20201105200412145.png)
## How to Implement Pointer Analysis
@@ -63,7 +63,7 @@ _别处的资料都没有全家桶,只介绍某些特殊情况下的分析算
本质上来说,指针分析是在指针间**传递**指向关系。
-![](../.gitbook/assets/image-20201105200815104.png)
+![](../../.gitbook/assets/image-20201105200815104.png)
inclusion constraints的具体解释:在上述表示的结论部分中可以写作两个集合间的包含关系。如Load应该表示为:
@@ -72,7 +72,7 @@ inclusion constraints的具体解释:在上述表示的结论部分中可以
> Key to implementation: when 𝑝𝑡\(𝑥\)is **changed**, **propagate** the **changed par**t to the **related pointers** of 𝑥
-![](../.gitbook/assets/image-20201105201018655.png)
+![](../../.gitbook/assets/image-20201105201018655.png)
### Pointer Flow Graph
@@ -88,21 +88,21 @@ inclusion constraints的具体解释:在上述表示的结论部分中可以
* `Edges: Pointer × Pointer`
* **An edge 𝑥 -> 𝑦** means that the objects pointed by pointer 𝑥 **may flow to \(and also be pointed to by\)** pointer 𝑦
-![](../.gitbook/assets/image-20201105201421501.png)
+![](../../.gitbook/assets/image-20201105201421501.png)
### Example
假设c和d一开始都指向 $$o_i$$,根据上述规则,我们能够从左侧的程序语句从上到下构建出右侧的指针流图。
-![](../.gitbook/assets/image-20201105201746860.png)
+![](../../.gitbook/assets/image-20201105201746860.png)
因此,所有b所指向的对象更新时,都要传递到e中。这是一个求传递闭包\(transitive closure\)的过程。假如我们考虑j位置的一条新语句`b = new T();`
-![](../.gitbook/assets/image-20201105201939088.png)
+![](../../.gitbook/assets/image-20201105201939088.png)
PFG的整个构造过程,需要在构建PFG和在已有的PFG上传递指向关系这两个步骤间循环往复。这两个步骤是相互依赖的,所以需要精心设计算法来实现分析。
-![](../.gitbook/assets/image-20201105202101633.png)
+![](../../.gitbook/assets/image-20201105202101633.png)
## Pointer Analysis: Algorithms
@@ -115,28 +115,28 @@ PFG的整个构造过程,需要在构建PFG和在已有的PFG上传递指向
首先,四个红框部分对应之前提到的四种基本语句——New、Assign、Store和Load。接下来做详细讲解。
-![](../.gitbook/assets/image-20201127170432941.png)
+![](../../.gitbook/assets/image-20201127170432941.png)
### Handling of New and Assign
#### Init and adding edges
-![](../.gitbook/assets/image-20201112191544354.png)
+![](../../.gitbook/assets/image-20201112191544354.png)
首先考虑两种简单的语句:New和Assign。
-* 前三行代码做初始化的工作,并针对所有的**New**语句,将所有的初始指向关系加入WorkList。注意pt(n)初始化后为空集{},随着算法的迭代会增加元素。
+* 前三行代码做初始化的工作,并针对所有的**New**语句,将所有的初始指向关系加入WorkList。注意pt\(n\)初始化后为空集{},随着算法的迭代会增加元素。
* 之后的两行代码处理**Assign**语句,添加`y->x`的边到PFG中。添加边的具体算法如下
-![](../.gitbook/assets/image-20201112191630283.png)
+![](../../.gitbook/assets/image-20201112191630283.png)
#### Propagate
-![](../.gitbook/assets/image-20201112193329365.png)
+![](../../.gitbook/assets/image-20201112193329365.png)
传播的具体算法如下,标号为2的语句是整个算法中唯一执行后改变指向关系的语句。
-![](../.gitbook/assets/image-20201112193357268.png)
+![](../../.gitbook/assets/image-20201112193357268.png)
#### Detial-Differential Propagation
@@ -153,22 +153,22 @@ Solve(𝑆)
首先我们考虑不使用Differential Propagation的情况,首先是a->c->d的传递路线。
-![](../.gitbook/assets/image-20201112194234928.png)
+![](../../.gitbook/assets/image-20201112194234928.png)
然后是b->c->d的传递路线,虽然 $$\{o_1, o_3\}$$之前已经在c所指向的集合中了,但依然需要参与传播,这是冗余的。
-![](../.gitbook/assets/image-20201112194358502.png)
+![](../../.gitbook/assets/image-20201112194358502.png)
我们再来看使用Differential Propagation的情况,只需要传播$$\{o_5\}$$一项即可。在实际应用中这能够大大减小开销。
-![](../.gitbook/assets/image-20201112194555582.png)
+![](../../.gitbook/assets/image-20201112194555582.png)
* In practice, Δ is usually small compared with the original set, so propagating only the new points-to information \(Δ\)
* Besides, Δ is also important for efficiency when handling stores, loads, and method calls, as explained later
### Handling Store and Load
-![](../.gitbook/assets/image-20201112195502575.png)
+![](../../.gitbook/assets/image-20201112195502575.png)
对于AddEdge函数中第二个if的说明:仅在第一次添加s->t到PFG时添加pt\(s\)的信息到t,是因为Propagate中的语句能够处理后续的pt\(s\)变化。
@@ -176,7 +176,7 @@ Solve(𝑆)
至此,我们完整地介绍了为了教学目的设计的指针分析算法。
-![](../.gitbook/assets/image-20201123205009821.png)
+![](../../.gitbook/assets/image-20201123205009821.png)
### Example
@@ -194,12 +194,11 @@ e = d.f;
这一例子动态内容很多,所以计划录制一小段视频讲解。先放个答案,能自己推导对的同学就可以跳过视频了。
-![](../.gitbook/assets/image-20201126221950557.png)
+![](../../.gitbook/assets/image-20201126221950557.png)
## Key points
-**The X You Need To Understand in This Lecture**
-
* **Rules** for pointer analysis
* **PFG**\(Pointer flow graph\)
-* **Algorithm** for pointer analysis
\ No newline at end of file
+* **Algorithm** for pointer analysis
+
diff --git a/ch2/02-04-pointer3-analysis-spa.md b/ch3/pointer-analysis/03-03-pointer3-analysis-spa.md
similarity index 78%
rename from ch2/02-04-pointer3-analysis-spa.md
rename to ch3/pointer-analysis/03-03-pointer3-analysis-spa.md
index d935b28..946063f 100644
--- a/ch2/02-04-pointer3-analysis-spa.md
+++ b/ch3/pointer-analysis/03-03-pointer3-analysis-spa.md
@@ -1,4 +1,4 @@
-# 指针分析理论基础二
+# 指针分析理论(下)
首先回顾一下在上一篇文章中列出的大纲。
@@ -36,30 +36,30 @@ void foo(A a) {
各个符号的定义为:
-
+![](../../.gitbook/assets/image-20201201151956869.png)
-![](../.gitbook/assets/image-20201126230831572.png)
+![](../../.gitbook/assets/image-20201126230831572.png)
-> 一个参考答案:保存现场,构造调用栈帧,传递参数,跳转到目标函数开始执行……目标函数执行完毕跳转回来,后从预定的位置取返回值(若需要),恢复现场,继续往下执行……
+> 一个参考答案:保存现场,构造调用栈帧,传递参数,跳转到目标函数开始执行……目标函数执行完毕跳转回来,后从预定的位置取返回值(若需要),恢复现场,继续往下执行……
在静态分析中,我们更多地关心数据流,而非控制流。而针对Java,处理函数调用的数据流可以分为以下四个部分:
1. 确定目标方法。用第7课介绍过的Dispatch函数完成。
2. 传receiver object
-![](../.gitbook/assets/image-20201126184745576.png)
+![](../../.gitbook/assets/image-20201126184745576.png)
-3. 传参数
+1. 传参数
-![](../.gitbook/assets/image-20201126185008506.png)
+![](../../.gitbook/assets/image-20201126185008506.png)
-4. 传返回值
+1. 传返回值
-![](../.gitbook/assets/image-20201126185233403.png)
+![](../../.gitbook/assets/image-20201126185233403.png)
因此,我们可以对应规则,在PFG上添加Edge实现过程间信息的传递。完整的规则如下:
-![](../.gitbook/assets/image-20201126231116221.png)
+![](../../.gitbook/assets/image-20201126231116221.png)
#### Detail-1
@@ -67,9 +67,9 @@ void foo(A a) {
通过这两个图可以直观地说明原因:
-![](../.gitbook/assets/image-20201126231403264.png)
+![](../../.gitbook/assets/image-20201126231403264.png)
-![](../.gitbook/assets/image-20201126231437769.png)
+![](../../.gitbook/assets/image-20201126231437769.png)
_在每次算法执行时,_$$o_i$$_是确定的某个(只有一个)对象,然后针对这个对象做Dispatch,能够找到对应的唯一的receiver object._
@@ -77,20 +77,20 @@ _在每次算法执行时,_$$o_i$$_是确定的某个(只有一个)对象
像之前用CHA做过程间分析时一样,我们需要将分析的过程和Call graph构建的过程结合起来。
-![](../.gitbook/assets/image-20201126231722298.png)
+![](../../.gitbook/assets/image-20201126231722298.png)
不同的是,这次我们只分析从main方法(或者一般性地说,程序入口)开始可达的部分。原因有二:
1. 提升分析速度。因为我们能够避免分析不会被执行到的死代码。
2. 提升分析精度。避免了unreachable部分的代码调用reachable部分方法时可能引起的精度下降。
-![](../.gitbook/assets/image-20201126191225969.png)
+![](../../.gitbook/assets/image-20201126191225969.png)
## Algorithm: PA with Method Calls
接下来介绍一个具体的、易于理解和实现的算法。由于指针分析是静态程序分析的基础,理解了这个看起来枯燥的算法后,更容易在静态程序分析领域触类旁通。~~而且据说后面两节课会学得更加轻松~~
-![](../.gitbook/assets/image-20201126191650221.png)
+![](../../.gitbook/assets/image-20201126191650221.png)
算法整体上来说和上一节课所介绍的大框架相似,黄色标记的部分是这次新加入的部分。绿色部分是对新的全局变量的说明:
@@ -104,7 +104,7 @@ AddReachable的作用是:
* **输入参数**m是最新的可达方法。
* 函数修改维护全局的RM、S和$$S_m$$,并处理新的方法m中的New和Assign语句。
-![](../.gitbook/assets/image-20201126194125039.png)
+![](../../.gitbook/assets/image-20201126194125039.png)
#### Detail-3
@@ -121,9 +121,9 @@ ProcessCall的作用是:
* 输入的$$o_i$$是x新指向的目标。
* 函数在可达的语句集合S中,选择所有与x有关的过程调用,做之前提到的数据流相关四步处理(确定被调用方法、传对象、传参数,传返回值)。
-![](../.gitbook/assets/image-20201126195311513.png)
+![](../../.gitbook/assets/image-20201126195311513.png)
-![](../.gitbook/assets/image-20201126195425756.png)
+![](../../.gitbook/assets/image-20201126195425756.png)
## Example
@@ -148,14 +148,13 @@ class B extends A {
答案如下:
-![](../.gitbook/assets/image-20201126201000426.png)
+![](../../.gitbook/assets/image-20201126201000426.png)
这个流不敏感的分析算法在分析精度上仍然可以改进。我们将在接下来的课程中学习精度更高的流敏感分析。
## Key points
-**The X You Need To Understand in This Lecture**
-
* Pointer analysis **rule for method call**
* **Algorithm** for inter-procedural pointer analysis
* **On-the-fly call graph construction**
+
diff --git a/ch3/pointer-analysis/README.md b/ch3/pointer-analysis/README.md
new file mode 100644
index 0000000..0a0364a
--- /dev/null
+++ b/ch3/pointer-analysis/README.md
@@ -0,0 +1,3 @@
+# 指针分析简介
+
+这一部分介绍比CHA分析精度更高的指针分析技术(上下文不敏感版本)。
\ No newline at end of file