Page 50 - 《软件学报》2021年第12期
P. 50
3714 Journal of Software 软件学报 Vol.32, No.12, December 2021
m j 作为别名对〈m i ,m j 〉存储在可能别名集 AliasSet 中.在进行重构之前,首先通过别名集 AliasSet 构建锁集 LockSet,
对别名对中的监视器对象对应的锁对象进行实例化,并存入锁集 LockSet 中.别名对中两个监视器对象应对应相
同的锁对象,例如别名对〈m i ,m j 〉在 LockSet 中表示为两个键值对组合〈m i :lock k 〉,〈m j :lock k 〉,其中,lock k 为锁对象;而
没有产生别名问题的监视器对象在重构过程中对锁对象进行实例化,并存入锁集 LockSet 中.
2.3.2 负面效应分析
负面效应是指对非本地环境的修改 [15] ,例如一个操作、方法或表达式在执行过程中修改了内存单元,则程
序将产生负面效应.由于本文提出的重构方法不仅要重构读锁和写锁,而且还要进行细粒度的锁重构,因此负面
效应分析需要对整个临界区进行分析,并生成一个临界区读写模式序列来表示临界区的读写操作.在生成临界
区对应的读写模式序列时,使用字符 r 表示临界区的一个读操作,使用字符 w 表示一个写操作,使用字符 c 表示
一个 if 条件判断语句的开始且条件判断为读操作,使用字符 e 表示一个 if 判断语句的结束.
本文的负面效应分析通过 WALA [16] 的中间表示 IR 对方法中的指令进行遍历分析,判断指令是否修改内存
单元.在对方法调用指令进行分析时,为了保证重构工具的执行效率,将方法调用进入的层数限制为 5 层.具体分
析算法如算法 1 所示.
1) 首先获得临界区所对应的指令集,调用 sideEffectAnalysis 方法对每一条指令进行遍历分析(第 1 行~第
4 行);
2) 在 sideEffectAnalysis 方法中,首先对方法调用进入的层数限制进行判断(第 6 行),如果大于限制层数 5
层,为了保证临界区安全,将其认定为一个写操作,返回字符 w(第 23 行);
3) 之后,对每条指令进行分析,如果指令修改了静态字段,或修改了实例字段,或修改了堆内存,则当前指
令产生了负面效应,返回字符 w(第 7 行、第 8 行);
4) 如果指令是方法调用指令,首先对调用层数的计数器加 1(第 11 行),之后,递归调用 sideEffectAnalysis
方法对被调用方法里的指令进行分析:若被调用方法包含写指令,则当前方法调用指令产生了负面效
应,返回字符 w(第 11 行~第 15 行);如果当前被调用方法没有产生负面效应,则返回字符 r(第 16 行);
5) 如果是 if 判断语句且判断语句为读操作,返回字符 c;如果指令是 if 条件判断结束指令,则返回字符
e(第 17 行~第 20 行);
6) 其他指令均返回字符 r(第 21 行).
算法 1. 负面效应分析算法.
输入:目标临界区 c;
输出:c 对应的临界区读写模式序列 str.
1. 通过目标临界区 c 对应的中间表示 IR 获临界区 c 的指令集 Ins;
2. for 遍历指令集 Ins 中每一条指令 i do
3. str.append(sideEffectAnalysis(i,0));
4. end for
5. char sideEeffectAnalysis (指令 i,int limit):
6. if limit<5 then
7. if 指令修改静态字段||指令修改实例字段||指令修改堆内存 then
8. return w;
9. else if 指令为方法调用指令 then
10. limit++;
11. for 被调用方法中的每一条指令 k do
12. if sideEeffectAnalysis(k,limit)==w then
13. return w;
14. end if