Skip to content

摸C3需求 #53

Description

@lfeng14

假设这批PR最终都合入并解决冲突,EA、late inline、Type/Loop PGO、arraycopy、字符串和Unsafe intrinsic这几条主线已经有人覆盖。继续对齐C2时,优先检查以下空白。

优先级 仍需拉齐的能力 当前状态
P0 Java堆感知的Alias Analysis 明确缺少
P0 GC barrier后移、消除和合并 已实现barrier,但流水线明显不完整
P0验收 PEA完整优化链 有PR,但要确认是否真正覆盖C2的标量替换、拆装箱和锁优化
P1 MethodHandle/invokedynamic专项优化 通用Type PGO和late inline不一定覆盖完整
P1 非虚拟对象的锁粗化、嵌套锁消除 PEA只能覆盖其中一部分
P1 内联收益模型、代码尺寸控制 late inline解决“时机”,不等于解决“选谁内联”
P1 Java语义下的循环向量化 LLVM有向量化,但可能受barrier、statepoint和alias信息限制
P2 剩余C2 intrinsic 仍有缺项,但这五个用例中暂未形成头部热点
P2 ZGC/Shenandoah等collector适配 当前一些intrinsic只对G1/Serial开放

1. Java堆感知的Alias Analysis

这是目前源码中最明确、而且不在所列PR里的缺口。LLVM AA不了解:

  • 两个新分配Java对象一定不同;
  • 精确Klass带来的对象/数组布局;
  • oop handle和Java heap对象之间的关系;
  • 不同Java字段、数组之间的别名关系。

源码已经直接写了TODO:

// LLVM AA does not understand Java oop handles, exact Klass facts,
// or Java heap allocation provenance.

见 [ArrayCopySpecialization.cpp (line 89)](/home/luofeng/jdk21-c3-jit/jeandle-llvm/llvm/lib/Transforms/Jeandle/ArrayCopySpecialization.cpp:89)。

这会限制load/store消除、LICM、arraycopy特化和向量化。它和PEA也有明显协同:PEA证明对象身份和逃逸范围,Java AA把这些信息继续提供给后续LLVM优化。

建议任务可以定义为:

增加Jeandle JavaHeapAA或通过noalias/alias scope/attributes传播对象来源、字段和数组别名信息。

2. GC barrier优化流水线

当前C3必须在O3之前插入高层barrier调用,因为barrier pass还不能处理O3产生的memory intrinsic和vector指令;源码明确说明未内联barrier可能阻塞优化:

// But the uninlined barrier calls can still block useful optimizations.

见 [Pipeline.cpp (line 274)](/home/luofeng/jdk21-c3-jit/jeandle-llvm/llvm/lib/Jeandle/Pipeline.cpp:274)。

C2则把barrier作为Ideal Graph和Macro Expansion的一部分,可以利用类型、逃逸和内存链信息消除或合并部分barrier。

建议拆成:

  1. InsertGCBarriers识别O3生成的memory intrinsic和vector store。
  2. 将barrier插入推迟到主要标量、循环和向量优化之后。
  3. 利用PEA/Java AA消除新对象初始化期间不必要的post barrier。
  4. 支持相邻card mark合并和冗余barrier消除。

这个方向对neo4j和page-rank的对象、数组密集路径比较值得关注。

3. PEA需要按完整链路验收

!123不是小型“删除死分配”补丁,从本地origin/pea看,已经涉及对象/数组虚拟化、分支和循环合流、按逃逸点物化、deopt对象恢复和monitor处理。因此不建议另外再立一个重复EA任务。

但需要确认它是否真正覆盖这些C2能力:

逃逸分析
 → 对象/数组标量替换
 → 分配消除
 → boxing对象消除
 → 不逃逸对象锁消除
 → deopt/异常/OSR时正确物化
 → GC barrier和内存操作继续简化

尤其要检查:

  • 对象进入deopt state后是否仍可虚拟化;
  • 循环中的对象是否能够稳定收敛;
  • Integer/Long/Float/Double.valueOf及Tuple/lambda捕获对象能否消除;
  • 对虚拟对象的monitorenter/exit能否一起消除;
  • 编译时间和IR膨胀是否可控。

page-rank和par-mnemonics适合作为PEA验收样本。

4. MethodHandle/invokedynamic专项优化

!106/115/116主要是类型profile传播和类型检查特化,!120是通用late inline。还需要确认它们是否覆盖C2的:

  • IncrementalInlineMH
  • MethodHandle adapter链的延迟内联;
  • invokedynamic CallSite target常量化;
  • guardWithTest分支profile;
  • lambda/metafactory调用链折叠;
  • 去虚化后再次触发内联。

这对Spark/Scala的page-rank、Stream/lambda密集的par-mnemonics和reactors都可能有价值。不能只看“late inline PR已存在”,需要检查它支持的是普通调用、virtual call,还是也包括MH/indy调用链。

5. 锁粗化和嵌套锁消除

!126修复的是contended monitorenter的deopt状态,属于正确性,不是锁优化。

PEA可以消除“虚拟对象”上的锁,但C2还具有:

  • EliminateLocks:锁粗化;
  • EliminateNestedLocks:同一对象的嵌套锁消除。

见 [c2_globals.hpp (line 448)](/home/luofeng/jdk21-c3-jit/src/hotspot/share/opto/c2_globals.hpp:448)。

当前没有看到C3中对应的独立优化pass。因此,在PEA之外还应检查:

synchronized (obj) { operation1(); }
synchronized (obj) { operation2(); }

是否可以合并为一次加锁,以及递归/嵌套同步是否能删除重复monitor操作。这个方向可能影响philosophers,但应先解决STM多模态的观测问题。

6. late inline之后仍缺内联收益模型

!120解决的是“能不能晚点内联”,不自动解决:

  • 哪个调用值得内联;
  • 内联后代码尺寸是否失控;
  • 多态调用要生成几个版本;
  • 编译CPU预算是否值得;
  • 如何平衡调用消除和i-cache/iTLB压力。

page-rank已经观察到部分C3热点代码比C2大1.4~3.3倍;neo4j有frontend/iTLB压力。因此late inline合入后,仍需要代码尺寸感知的收益模型和版本化预算,不能简单扩大阈值。

7. 循环向量化不要和Loop PGO混为一项

当前C3已经有LICM、loop unswitch、loop predication、IRCE和LLVM O3,!122补的是循环profile。它们不等于C2 SuperWord效果已经拉齐。

需要验证:

  • Java数组访问能否提供足够的alias信息;
  • safepoint/statepoint是否阻断向量化;
  • GC barrier是否使vector store退回标量;
  • Vector API的masked load/store、gather/scatter、reduction是否完整;
  • 编译后是否确实生成AArch64 NEON/SVE指令。

这更适合用向量化成功率、生成指令和循环吞吐量验收,而不是单纯检查有没有LLVM vectorizer。

8. 剩余intrinsic

当前仍未看到的C2 intrinsic包括若干:

  • Object.cloneReflection.getCallerClass
  • 部分unaligned get/put;
  • 部分getAndAdd/getAndSet类型;
  • ByteBuffer CRC;
  • Montgomery运算;
  • Vector masked/gather/scatter/reduction等。

但旧profile中只有reactors的clone/getCallerClass各约0.05%~0.06%,对这五项不是当前P0。

最后还要修正前面的一个判断:当前分支已经有[StringBuilder/StringBuffer concat fusion (line 104)](/home/luofeng/jdk21-c3-jit/src/hotspot/share/jeandle/jeandleStringConcat.cpp:104),所以OptimizeStringConcat不能再列为“C3完全没有”;后续应该比较覆盖范围和收益,而不是重新立项实现。

综合来看,在现有PR之外,最值得新增的两条主任务是:

  1. JavaHeap Alias Analysis + PEA信息向后续优化传播。
  2. GC barrier后移、消除、合并,并解除对O3/向量化的阻塞。

然后再审查!120是否完整覆盖MethodHandle/invokedynamic,以及!123是否覆盖锁消除、boxing和deopt物化全链路。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions