1.根据函数调用栈的结构:
在被调函数栈帧的栈底 %rbp + 8(栈地址向下增长,堆地址向上增长,栈底的正偏移值指向调用函数栈帧内容)保存着被调函数的传入参数,这里即:
JavaCallWrapper指针、返回结果指针、返回结果类型、被调用方法的methodOop、被调用方法的解释代码的入口地址、参数地址、参数个数。
StubRoutines::call_stub [0x0000000002400567, 0x00000000024006cb[ (356 bytes) : push %rbp : mov %rsp,%rbp : sub $0xd8,%rsp
2.rcx、rdx、r8d、r9d分别保存着传入call_stub的前4个参数,现在需要将其复制到栈上的shadow space中
//分别使用rcx、rdx、r8、r9来保存第1、2、3、4个参数,多出来的其他参数用栈空间来传递 //使用xmm0-4来传递第1-4个浮点数参数 : mov %r9,0x28(%rbp) 0x0000000002400576: mov %r8d,0x20(%rbp) 0x000000000240057a: mov %rdx,0x18(%rbp) 0x000000000240057e: mov %rcx,0x10(%rbp)
3.将被调用者保存寄存器的值压入call_stub栈中:
;; save registers: : mov %rbx,-0x8(%rbp) 0x0000000002400586: mov %r12,-0x20(%rbp) 0x000000000240058a: mov %r13,-0x28(%rbp) 0x000000000240058e: mov %r14,-0x30(%rbp) 0x0000000002400592: mov %r15,-0x38(%rbp) 0x0000000002400596: vmovdqu %xmm6,-0x48(%rbp) 0x000000000240059b: vmovdqu %xmm7,-0x58(%rbp) 0x00000000024005a0: vmovdqu %xmm8,-0x68(%rbp) 0x00000000024005a5: vmovdqu %xmm9,-0x78(%rbp) 0x00000000024005aa: vmovdqu %xmm10,-0x88(%rbp) 0x00000000024005b2: vmovdqu %xmm11,-0x98(%rbp) 0x00000000024005ba: vmovdqu %xmm12,-0xa8(%rbp) 0x00000000024005c2: vmovdqu %xmm13,-0xb8(%rbp) 0x00000000024005ca: vmovdqu %xmm14,-0xc8(%rbp) 0x00000000024005d2: vmovdqu %xmm15,-0xd8(%rbp) 0x00000000024005da: mov %rsi,-0x10(%rbp) 0x00000000024005de: mov %rdi,-0x18(%rbp) : mov 0x48(%rbp),%r15 0x00000000024005e6: mov 0x6d01a2c3(%rip),%r12 # 0x000000006f41a8b0
4.call_stub的参数保存着Java方法的参数,现在就需要将参数压入call_stub栈中
/栈底指针的0x40偏移保存着参数的个数 0x00000000024005ed: mov 0x40(%rbp),%r9d : test %r9d,%r9d 0x00000000024005f4: je 0x000000000240060d //若参数个数不为0,则遍历参数,将所有参数压入本地栈 : mov 0x38(%rbp),%r8 0x00000000024005fe: mov %r9d,%edx ;; loop: * i = parameter_size; //确保不等于0 * do{ * push(parameter[i]); * i--; * }while(i!=0); */ 0x0000000002400601: mov (%r8),%rax 0x0000000002400604: add $0x8,%r8 0x0000000002400608: dec %edx 0x000000000240060a: push %rax 0x000000000240060b: jne 0x0000000002400601
5.调用Java方法的解释代码