为什么hotspot生成的已编译方法在执行之前将eax隐匿在堆栈的上方? [英] Why do hotspot generated compiled methods stash eax high up the stack before execution?
问题描述
查看从OpenJDK的HotSpot生成的汇编代码时,序言中有一部分将%eax
值复制到堆栈(rsp-0x14000)
的更远位置,我不明白为什么这样做: >
When looking at generated assembly code from OpenJDK's HotSpot, there is part of the prologue that copies the %eax
value to a location further up the stack (rsp-0x14000)
, and I don't understand why it's doing that:
[Disassembling for mach='i386:x86-64']
[Entry Point]
[Verified Entry Point]
[Constants]
# {method} {0x0000000120f0f410} 'add' '(JJ)J' in 'Test'
# parm0: rsi:rsi = long
# parm1: rdx:rdx = long
# [sp+0x40] (sp of caller)
0x000000010cd8a3e0: mov %eax,-0x14000(%rsp)
0x000000010cd8a3e7: push %rbp
0x000000010cd8a3e8: sub $0x30,%rsp
0x000000010cd8a3ec: movabs $0x120f0f5d0,%rax
; {metadata(method data for {method} {...} 'add' '(JJ)J' in 'Test')}
这个地址似乎用于不同编译方法的许多其他赋值,而且我还没有看到从哪里读取该内存位置:
This same address seems to be used for a number of other assignments for different compiled methods, and I've not seen where that memory location is read from:
# {method} {0x0000000120000090} 'indexOf' '(I)I' in 'java/lang/String'
[Verified Entry Point]
0x000000010c29bfa0: mov DWORD PTR [rsp-0x14000],eax
...
# {method} {0x00000001203fb410} 'add' '(JJ)J' in 'Test'
[Verified Entry Point]
0x000000010c29c3a0: mov DWORD PTR [rsp-0x14000],eax
我是通过这段Java代码生成的:
I'm generating this from this piece of Java code:
public class Test {
public static void main(String args[]) {
long total = 0;
for(int i=0;i<20_000;i++) {
total = add(total,i);
}
System.out.println("Total is: " + total);
}
public static long add(long a, long b) {
return a+b;
}
}
我正在用以下方法运行它:
and I'm running this with:
$ java -XX:CompileCommand=print,*.* Test
我正在使用的Java版本是:
The version of Java I'm using is:
$ java -version
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
它在OSX 10.11.4上
and it's on OSX 10.11.4
$ uname -a
Darwin alblue.local 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64
任何人都可以解释这是怎么做的,是否会引起争用写入该地址?我在不同的JVM和不同的示例中看到了用于偏移量的不同数字,但是当我看到它被使用时,该数字对于同一会话中所有JVM的调用都保持不变.
Can anyone explain what this is doing, and whether it would cause contention writing to that address? I've seen different numbers used for the offset in different JVMs and with different examples, but when I have seen it being used the number has remained constant for all invocations of the JVM in the same session.
推荐答案
It's called stackbanging. I can't find much documentation on the details, but a cursory google search indicates that it serves several purposes, such as notifying the VM through a page fault handler about the need for stack growth and ensuring it has enough headroom for internal events such as method deoptimization or unwinding the stack in case of asynchronous exceptions such as SOE or OOME.
这篇关于为什么hotspot生成的已编译方法在执行之前将eax隐匿在堆栈的上方?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!