Assembly JIT分解中的冗余存储
我继续探索JIT汇编输出,发现了一对奇怪的加载/存储指令:Assembly JIT分解中的冗余存储,assembly,jvm,reverse-engineering,jit,jvm-hotspot,Assembly,Jvm,Reverse Engineering,Jit,Jvm Hotspot,我继续探索JIT汇编输出,发现了一对奇怪的加载/存储指令: mov 0x30(%rsp),%rdx ; <---- this load test %edi,%edi jne 0x00007fd3d27c5032 cmp %r11d,%r10d jae 0x00007fd3d27c4fbc mov 0x10(%rbx,%r10,4),%edi test %edi,%edi je 0x00007fd3d27c5062 mov 0xc(
mov 0x30(%rsp),%rdx ; <---- this load
test %edi,%edi
jne 0x00007fd3d27c5032
cmp %r11d,%r10d
jae 0x00007fd3d27c4fbc
mov 0x10(%rbx,%r10,4),%edi
test %edi,%edi
je 0x00007fd3d27c5062
mov 0xc(%rbp),%esi
test %esi,%esi
je 0x00007fd3d27c4fea
mov %r8d,0x1c(%rsp)
mov %rdx,0x30(%rsp) ; <---- this store
mov %rax,0x28(%rsp)
mov %ecx,0x10(%rsp)
mov %rbp,0x20(%rsp)
mov %rbx,0x8(%rsp)
mov %r13d,%ebp
mov %r10d,0x14(%rsp)
mov %r11d,0x18(%rsp)
mov %r14d,0x40(%rsp)
mov %r9,(%rsp)
lea (%r12,%rdi,8),%rdx
shl $0x3,%rsi
callq 0x00007fd3caceaf00
mov 0x20(%rsp),%r11
mov 0x10(%r11),%r10d
mov 0x8(%r12,%r10,8),%r8d
cmp $0xf2c10,%r8d
jne 0x00007fd3d27c4ffa
lea (%r12,%r10,8),%r8
mov 0x10(%r8),%r10
movabs $0x7fffffffffffffff,%r9
cmp %r9,%r10
je 0x00007fd3d27c5092
mov %r10,%rdx
add $0x1,%rdx
test %rdx,%rdx
jle 0x00007fd3d27c50ce
mov %r10,%rax
lock cmpxchg %rdx,0x10(%r8)
sete %r11b
movzbl %r11b,%r11d
test %r11d,%r11d
je 0x00007fd3d27c5116
test %r10,%r10
jle 0x00007fd3d27c4f48
mov 0x108(%r15),%r11
mov 0x14(%rsp),%r10d
inc %r10d
mov 0x1c(%rsp),%r8d
inc %r8d
test %eax,(%r11)
mov (%rsp),%r9
mov 0x40(%rsp),%r14d
mov 0x18(%rsp),%r11d
mov %ebp,%r13d
mov 0x8(%rsp),%rbx
mov 0x20(%rsp),%rbp
mov 0x10(%rsp),%ecx
mov 0x28(%rsp),%rax
movzbl 0x18(%r9),%edi
movslq %r8d,%rsi
cmp 0x30(%rsp),%rsi
jge 0x00007fd3d27c4f17
cmp %r11d,%r10d
jl 0x00007fd3d27c4dea ; this is the end of the loop
; jump to the first instruction in this listing
mov0x30(%rsp),%rdx 我复制了forArraySubscription.slowPath
。尽管寄存器映射与代码段略有不同,但代码结构完全相同
不完整的片段让你得出了错误的结论。实际上,%rdx
可以在加载和存储之间更改,因为中间有一个分支目标:->
这在查看相应的:
当
继续时,外部的。更新n
仅在寄存器中,而不在0x30(%rsp)
中。您确定这些块中的任何位置都没有分支目标吗?如果不是的话,那么它看起来像是错过了优化,但这些在JIT代码中并不少见。不过,如果加载后没有其他任何东西可以分支到任何基本块中,并且编译器可以很容易地证明这一点,那么编译器很容易发现这一点。这不是nmethod的全部内容。你能发布完整的PrintAssembly输出,包括存根吗?我想不,至少perfasm没有显示它们。。。在这里,它为jums perfasm绘制箭头,仅显示最热的区域。这并不意味着没有来自其他地方(如存根)的入站分支。对不起,存根是什么意思?这是使用“perfasm”键运行jmh的完整输出哇!真是太棒了!我希望有一天能像你一样理解汇编代码)对不起,昨天我花了一些时间在jmh中处理PrintAssembly输出(另外感谢你的回答),当我得到完整的汇编代码时,已经太晚了,我想先自己去探索一下。啊,还有。。。今天我得到了和你一样的结果,我在这里写我是白痴。。。无论如何,非常感谢你的回答!顺便问一下,你是如何用英特尔语法而不是AT&T打印assebly代码的?@QIvan
while (true) {
for (; sent < n && idx < length; sent++, idx++) {
if (canceled) {
return;
}
T element = array[idx];
if (element == null) {
subscriber.onError(new NullPointerException());
return;
}
subscriber.onNext(element);
}
n = requested;