• Partial Escape Analysis Notes


    邮件讨论

    ------ 1.
    在C2中实现PEA的潜在挑战, from V.I

    1. 移动分配位置是最大的挑战,目前C2没有可靠的方式重新计算JVM state。唯一可行的办法就是在IR build的时候就在重要的地方捕获这些jvm state,然后保留到PEA阶段。
    2. 移动 vs split。也不一定说非要移动分配,还可以split单个分配到多个地方。比如下面代码
       MyPair p = new MyPair(1, 2);
       if (cond1) {
         ...
         if (cond2) {
            ... = p; // escapes
         }
         ...
         if (cond3) {
            ... = p; // escapes
         }
         ...
    }
    

    既可以移动分配,

    if (cond1) {
         MyPair p = new MyPair(1, 2);
         if (cond2) {
            ... = p; // escapes
         }
         ...
         if (cond3) {
            ... = p; // escapes
         }
         ...
       }
    

    也可以split分配

       if (cond1) {
         ...
         if (cond2) {
            ... = new MyPair(1, 2); // escapes
         }
         ...
         if (cond3) {
            ... = new MyPair(1, 2); // escapes
         }
         ...
       }
    

    这可能插入非常多的分配,所以如果要split,需要在哪下地方插分配也是需要抉择的。
    4. 逃逸位置将ir分成两个部分:对象逃逸前,对象逃逸后。为了保留对象的identity invariant。PEA不能只是在每个逃逸位置放一个分配,它应该尊重逃逸事件的顺序,并且保证党有多个逃逸事件时同样的对象被观察到。

    MyPair p = new MyPair(1, 2);
    if (cond1) {
       a.f = p; // escapes here
    }
    if (cond2) {
       b.f = p; // escapes here
    }
    ...
    if (a.f == b.f) { // true when (cond1 && cond2)
    

    比如,如果每个逃逸点插分配,那么最后if结果是错误的。
    5. 要正确处理CFG合并是非常重要的,是这个优化可行的前提。

    MyPair p = new MyPair(1, 2);
    ...
    if (cond1) {
       ... = p; // escapes
    }
    // merge point
    // no escape points beyound it
    

    即使这里只有一个逃逸点,也不能假设merge point之后对象不会逃逸。不变的是,在每个cfg merge point,要么所有pred blocks的对象都materalized,要么没有一个pred block的对象materialized。一些可能的分配放置是:

    MyPair p = NULL;
    ... // may benefit from scalarization
    p = new MyPair(1, 2);
    if (cond1) {
       ... = p; // escapes
    }
    // merge point
    
    
    MyPair p = NULL;
    ... // may benefit from scalarization of p
    if (cond1) {
       ... // may benefit from scalarization of p
       p = new MyPair(1, 2);
       ... = p; // escapes
    } else {
       ... // may benefit from scalarization of p
       p = new MyPair(1, 2);
    }
    
    // merge point: no p materialization allowed beyond this point
    
    // p = phi(p_cond1, p_cond2)
    

    总的来说,不太可能专门创建一个pea phase,扩展目前ea看起来是最有希望的方向

    1. ea构造cg
      2)对于全局逃逸对象:基于逃逸位置信息,pea选择可能可以的分配位置。
      3)基于pea结果,全局逃逸分配或者被移动,或者被split。
      4)再次在修改后的ir上运行ea。
      重复上述流程,直到ir稳定,或者timeout。

    --- 2.
    Tobias也提到,最关键的问题也最困难的问题是目前EA不能很好的处理甚至一些很简单的控制流merge,即对象及时没有在任何路径上逃逸,但是i因为对于EA来说cfg太复杂,以至于ea不能证明这个对象没有逃逸。相关的例子可以参见https://cr.openjdk.java.net/~thartmann/EA_examples

    Graal PEA论文细节

    1. 数据结构

    核心是在该逃逸的地方逃逸,不该逃逸的地方标量化。核心数据结构:
    image
    当遍历控制流的时候,pea会遇到一些对分配状态有影响的node,他们需要特殊对待。总体分三类:

    • allocate node会创建virtualobject
    • 如果一个node的任意input在alias中,那么当前node需要重新求值
    • merge和countedloop需要合并多个状态

    2. pattern

    具体来说,由下面一些pattern:
    image
    对于instance allocation,会创建VirtualObject和VirtualState,然后VirtualState里面的entries会初始化为默认值。同时向alias、state插入新entry,前者插入当前allocation node到VirtualObject的映射,后者插VirutalObject到VirtualState的映射。

    image
    只有长度statically known的数组分配才能被pea处理。类似对象分配,数组分配会创建VirtualObject和VirtualState,然后alias,state插入映射。VirtualState的entries对应数组大小,为了让overhead不太大,目前graal pea要求这个statically known的size必须<=32。否则pea不处理。

    image
    将非virtual对象的field赋值到virtual对象,会更新field的VirtualState。比如图片将常量5赋值给key,直接更新key对应的entries。
    image
    image
    如果操作不是上面提到的可以virtualize的,比如从LoadIndexed一个非常量索引,或者其他情况,就需要materialize,引用当前对象的节点也需要替换为引用materalized后的值,比如
    image
    storefield引用了一个escaped的对象,pea处理时候需要引用materliazed的值

    3.控制流合并,分割

    image
    在cfg split的位置,比如if出的key,需要为每个successor拷贝一份状态(VirtualState),然后每个分支独立修改各种状态,分别赋值5和6,最后cfg merge,需要创建一个Phi来合并两个VirtualObject的field,由于将key赋值给cacheKey,对象发生逃逸,需要materialize,对象状态也要修改为EscapedState。合并VirtualObject的状态有详细的规则:

    • 如果VirtualObject在所有predecessor逃逸了,那么合并后的状态是EscapedState,materializedValue指向一个新创建的phi,它会合并所有predecessor状态。
    • 如果VirtualObject在一些predecessor逃逸了,一些没有,那么所有virtual状态都需要materialize(??那这岂不是pea没用了)
    • 如果VirtualObject在所有predecessor都是virtual,那么合并后的状态也是virtual,所有VirtualState里面的field都需要合并。对于每个field,MergeProcess会查找这个field在所有predecessor VirtualObject:
      • 如果所有field都是一样的,那么那么这个值就是信状态的值
      • 果有些field不一样,MergeProcessor会对这些field创建Phi,
        一些想法
        ea实现大概是,遍历所有节点,找到感兴趣的节点,构造出PointsToNode(FieldNod,JavaObjectNode,LocalVarNode)。pea它沿着控制流遍历,用不同的概念来构造cg,所以看起来V.I提到的潜在可行的方法并不是最优的选择,甚至是不可行的,照着graal pea做一个可能是比较好的方式。

    大致流程:先算出cfg,然后遍历每个基本块里面的每个节点,按照论文提到的方式,对于一些特殊的节点(CastII,AllocateXX)做处理,遇到控制流split/merge还要特殊处理状态。

    1. 在逃逸分析前构造CFG
    2. 实现Graal PEA算法
      a. 处理控制流split/merge
      b. 处理循环
      c. 处理各种操作的effect
      d. 精心挑选节点,针对这些节点实现虚拟机过程
    3. 基于PEA结果,实现各种优化
      a. 标量替换优化
      b. 指针比较优化
      c. memory alias narrowing
      d. tba

    潜在难点

    1. 目前c2构造cfg是在codegen做的,而ea是优化的早期做的,不能直接复用PhaseCFG,因为它用了一些matcher的能力。要在优化早期将ideal graph转成cfg是很大的工作(1.识别bblock 2. schedule nodes to bblocks 3. 识别loop)
    2. 正如V.I提到,c2没有可靠的方式重新算状态,node需要materialize或者cfg split/merge这些需要状态的地方,都要求在IR构造阶段提前准备好,不一定能准备好,可能是最大的风险点
    3. 在实现pea后,还需要把当前c2 ea的一些特性也加到pea上,比如指针比较优化,memory alias narrowing很复杂。
    4. tba

    参考

    MS SUMMARY: https://gist.github.com/JohnTortugo/c2607821202634a6509ec3c321ebf370

    AWS MAIL: https://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2021-May/047486.html

    MS MAIL: https://mail.openjdk.java.net/pipermail/hotspot-dev/2021-October/055049.html

    PEA具体实现:https://ssw.jku.at/Teaching/PhDTheses/Stadler/Thesis_Stadler_14.pdf(grraal pea)

    PEA概述:https://www.ssw.uni-linz.ac.at/Research/Papers/Stadler14/Stadler2014-CGO-PEA.pdf

    EA论文:https://www.researchgate.net/publication/2804836_Escape_Analysis_for_Java(c2 ea原始论文)

    过程间分析的ea论文:https://www.usenix.org/legacy/events/vee05/full_papers/p111-kotzmann.pdf(c2 ea分析callee用到的字节码层面做ea的论文)

  • 相关阅读:
    常见邮件服务器(接收服务器和发送邮件服务器)地址
    Linux下搭建SVN服务器(CentOS)
    macBook下更新python
    画画练习20180627
    如何用Photoshop画一个发光金币(unity游戏素材教程)
    Python+VSCode+Git 学习总结
    如何在MFC DLL中向C#类发送消息
    MFC信号量使用指南
    回归cnBlogs
    Web自动化测试框架Watir(基于Ruby)
  • 原文地址:https://www.cnblogs.com/kelthuzadx/p/15726402.html
Copyright © 2020-2023  润新知