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
   45   46   47   48   49   50   51   52   53   54   55