DeepSeek hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp 源码分析
·
我来分析 OpenJDK HotSpot 中 PPC 架构下的 Shenandoah 垃圾回收器屏障汇编代码文件。
文件概述
shenandoahBarrierSetAssembler_ppc.cpp 是 Shenandoah GC 在 PPC(PowerPC)架构上的屏障汇编实现。Shenandoah 使用读屏障和写屏障来实现并发垃圾回收,该文件负责生成这些屏障的机器码。
核心功能
1. 屏障类型
Shenandoah 主要实现以下屏障:
- 读屏障(Read Barrier):在对象引用加载时检查并处理
- 写屏障(Write Barrier):在引用赋值时执行
- SATB 屏障(Snapshot-at-the-Beginning):用于并发标记
关键函数分析
1. 读屏障实现
void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm,
DecoratorSet decorators,
BasicType type,
Register dst,
Address src,
Register tmp1,
Register tmp_thread) {
// 如果不是对象引用类型,直接加载
if (!is_reference_type(type)) {
BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
return;
}
// 加载对象引用
BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
// 如果不在 GC 临界区,跳过屏障
if (ShenandoahBarrierSet::skip_barrier_load(decorators)) {
return;
}
// 生成读屏障代码
Label done;
Label resolve;
// 检查是否需要处理
__ ld(tmp1, in_bytes(ShenandoahRuntime::load_reference_barrier_weak()), dst);
__ cmpdi(CCR0, tmp1, 0);
__ beq(CCR0, done);
// 调用运行时解析函数
__ bind(resolve);
__ mr(R3_ARG1, dst); // 参数:对象引用
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier),
R3_ARG1);
__ mr(dst, R3_RET); // 更新返回值
__ bind(done);
}
2. 写屏障实现
void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm,
DecoratorSet decorators,
BasicType type,
Address dst,
Register val,
Register tmp1,
Register tmp2,
Register tmp3) {
// 如果是对象引用类型,需要写屏障
if (is_reference_type(type)) {
// 前屏障(Pre-barrier):SATB 标记
if (ShenandoahSATBBarrier) {
pre_barrier(masm, decorators, dst, val, tmp1, tmp2, tmp3);
}
// 执行实际存储
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
// 后屏障(Post-barrier):更新引用
if (ShenandoahStoreValEnqueueBarrier) {
post_barrier(masm, decorators, dst, val, tmp1, tmp2, tmp3);
}
} else {
// 非引用类型,直接存储
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
}
}
3. SATB 前屏障
void ShenandoahBarrierSetAssembler::pre_barrier(MacroAssembler* masm,
DecoratorSet decorators,
Address dst,
Register val,
Register tmp1,
Register tmp2,
Register tmp3) {
// 如果值寄存器为空,需要先加载
if (val == noreg) {
val = tmp1;
BarrierSetAssembler::load_at(masm, decorators, T_OBJECT, val, dst, tmp2, tmp3);
}
// 检查值是否为 NULL
__ cmpdi(CCR0, val, 0);
__ beq(CCR0, done);
// 检查 GC 状态
Register thread = tmp2;
__ get_thread(thread);
__ lbz(tmp3, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), thread);
__ andi_(tmp3, tmp3, ShenandoahHeap::HAS_FORWARDED);
__ beq(CCR0, done);
// 调用 SATB 标记函数
__ mr(R3_ARG1, val);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::satb_write_barrier_pre),
R3_ARG1);
__ bind(done);
}
4. 后屏障实现
void ShenandoahBarrierSetAssembler::post_barrier(MacroAssembler* masm,
DecoratorSet decorators,
Address dst,
Register val,
Register tmp1,
Register tmp2,
Register tmp3) {
// 检查是否需要屏障
if (val == noreg) {
return;
}
// 检查值是否为 NULL
__ cmpdi(CCR0, val, 0);
__ beq(CCR0, done);
// 获取线程局部存储
Register thread = tmp1;
__ get_thread(thread);
// 检查 GC 状态
__ lbz(tmp2, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), thread);
__ andi_(tmp2, tmp2, ShenandoahHeap::HAS_FORWARDED);
__ beq(CCR0, done);
// 检查是否在集合中
__ ld(tmp2, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset()), thread);
__ cmpdi(CCR0, tmp2, 0);
__ beq(CCR0, done);
// 将对象加入队列
__ mr(R3_ARG1, val);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::satb_write_barrier_post),
R3_ARG1);
__ bind(done);
}
5. 屏障优化
void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm,
Register dst,
Address src,
Register tmp1,
Register tmp2) {
// 快速路径:检查是否需要转发
Label not_forwarded;
Label done;
// 检查转发指针
__ ld(tmp1, in_bytes(ShenandoahHeap::_base), R16_THREAD);
__ ld(tmp2, in_bytes(ShenandoahHeap::_top), R16_THREAD);
// 比较是否在转发范围内
__ cmpld(CCR0, dst, tmp1);
__ cmpld(CCR1, dst, tmp2);
__ blt(CCR0, not_forwarded);
__ bge(CCR1, not_forwarded);
// 需要转发,调用运行时
__ mr(R3_ARG1, dst);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier),
R3_ARG1);
__ mr(dst, R3_RET);
__ b(done);
__ bind(not_forwarded);
__ bind(done);
}
6. 原子操作屏障
void ShenandoahBarrierSetAssembler::atomic_xchg(MacroAssembler* masm,
BasicType type,
Register new_val,
Address dest,
Register tmp1,
Register tmp2) {
if (is_reference_type(type)) {
// 对象引用的原子交换需要屏障
__ mr(tmp1, new_val);
// 执行原子交换
BarrierSetAssembler::atomic_xchg(masm, type, new_val, dest, tmp2, noreg);
// 后屏障
post_barrier(masm, 0, dest, new_val, tmp2, noreg, noreg);
} else {
BarrierSetAssembler::atomic_xchg(masm, type, new_val, dest, tmp1, tmp2);
}
}
PPC 架构特定考虑
1. 寄存器使用
// PPC 调用约定
#define R3_ARG1 R3 // 第一个参数寄存器
#define R3_RET R3 // 返回值寄存器
#define R16_THREAD R16 // 线程指针寄存器
2. 内存屏障指令
// PPC 内存屏障指令
__ sync(); // 完全内存屏障
__ lwsync(); // 轻量级同步屏障
__ isync(); // 指令同步屏障
3. 条件寄存器使用
// 使用多个条件寄存器避免冲突
__ cmpdi(CCR0, val, 0); // CCR0 用于 NULL 检查
__ cmpld(CCR1, dst, tmp1); // CCR1 用于范围检查
性能优化技术
1. 快速路径检查
- 先检查是否需要屏障,避免不必要的函数调用
- 使用位测试快速判断 GC 状态
- NULL 值快速返回
2. 内联汇编优化
- 将简单屏障完全内联展开
- 复杂情况才调用运行时函数
- 最小化寄存器保存恢复开销
3. 分支预测
// 使用静态分支预测
__ bge(CCR0, slow_path); // 假定大部分情况走快速路径
__ beq(CCR0, done); // NULL 检查通常为假
与 GC 状态交互
// GC 状态位定义
enum GCState {
NOT_IN_GC = 0,
HAS_FORWARDED = 1 << 0, // 对象已被转发
MARKING = 1 << 1, // 标记阶段
EVACUATION = 1 << 2, // 疏散阶段
UPDATEREFS = 1 << 3 // 引用更新阶段
};
总结
shenandoahBarrierSetAssembler_ppc.cpp 实现了 Shenandoah GC 在 PPC 架构上的核心屏障机制:
- 读屏障:确保从堆读取的对象引用是最新的
- 写屏障:维护 SATB 队列和引用更新
- 架构优化:充分利用 PPC 的寄存器资源和内存模型
- 性能平衡:快速路径内联,慢速路径调用运行时
这个实现展示了如何将高级 GC 算法与特定 CPU 架构的底层特性结合,在保证正确性的同时达到高性能。
更多推荐


所有评论(0)