深入探讨虚拟机运行时的java线程栈帧、Java/JVM沟通
2023-04-29 来源:飞速影视
栈帧
线程是程序执行的代名词,而程序执行过程中一个至关重要的东西是栈帧。它可以存放局部变量、方法参数等数据。先进先出(FIFO)的数据结构也原生地为函数调用和递归函数调用提供了可能。在4.1.2节中讨论了线程栈顶部的一些保护页和相关机制,本节将关注4.1.2节中用于描述方法调用的栈帧(frame),如代码清单4-14所示:
代码清单4-14 frame结构
class frame {private:intptr_t* _sp; // 栈顶指针address _pc; // 指向下一条指令的指针(RIP)CodeBlob* _cb; // 持有pc的代码块deopt_state _deopt_state; // 退优化状态(未退优化、退优化、未知)public:...#include CPU_HEADER(frame) // 巧妙地用#include包含CPU架构相关的代码};HotSpot VM将CPU无关的代码放置于runtime/frame中,然后用头文件包含指令#include巧妙地根据不同的CPU架构包含不同的代码,CPU_HEADER将会在编译的时候被替换为指定的架构,如x86是hotspot/cpu/x86/frame_x86.hpp。
与前面线程一样,frame只是一个数据结构,不管有没有这个数据结构,C 代码在执行的时候都是存在栈帧的,所以,虚拟机没有创造frame,它只是借用frame这个数据结构来描述栈帧。除了frame外还有vframe,如代码清单4-15所示,vframe是对frame的进一步封装,表示Java层面的虚拟栈帧。除了frame提供的信息外还能通过vframe访问到栈帧所属线程和Callee-saved寄存器。
代码清单4-15 vframe布局
class vframe: public ResourceObj {protected:frame _fr; // 物理栈帧RegisterMap _reg_map; // callee-saved寄存器JavaThread* _thread; // 栈帧所属线程public:...};Callee-saved表示被调用者保存的寄存器,如果方法调用者希望调用了方法后某些寄存器还能保持原来的值,就需要被调用者在使用它们前提前保存。与之类似的概念是Caller-saved,即调用者在调用前自行保存这些寄存器的值,而被调用者可以自由使用它。两者的区别就是如果某个寄存器需要在一个调用后使用,那么是调用者保存它的值(Caller-saved)还是被调用者保存它的值(Callee-saved)。
本站仅为学习交流之用,所有视频和图片均来自互联网收集而来,版权归原创者所有,本网站只提供web页面服务,并不提供资源存储,也不参与录制、上传
若本站收录的节目无意侵犯了贵司版权,请发邮件(我们会在3个工作日内删除侵权内容,谢谢。)
www.fs94.org-飞速影视 粤ICP备74369512号