不同进程虚拟机的JIT编译器是如何实现事件窥视的



注意:这个问题是向Smalltalk、Self、Javascript、Java、C#等语言的VM实现者提出的。

JIT编译器带来的一个常见功能是自动窥视系统事件。这既用于处理UI事件,也用于触发GC。

通常,这种事件窥视包括在帧构建(当调用方法时)和循环后跳处进行检查。我想知道,

执行此检查的不同方法是什么?它们的优点和缺点是什么?你知道有什么论文描述这些技术吗?

你能告诉我它是如何在特定的虚拟机中实现的吗?(Pharo、HPS、HotSpot、V8、SpiderMonkey、CLR)

根据我所读到的内容,我想每个实现都会做以下的一些变化:

  • 指定一个硬件寄存器专门用于计数,并在达到某个阈值时进行窥视

  • 有一个定期发出信号的定时器(如何实现?)然后:

    • 移动stack_limit变量,然后在帧构建和后跳时检查该变量
    • 将堆栈标记为只读或在硬件级别不可访问(即分页),从而导致帧构建失败,并在后跳之前添加对堆栈的写入编辑好处:由于数据依赖性,写入内存比读取快。缺点:如果计数器被频繁触发,检查会变慢,因为页面错误捕获很慢。安全点被污染:任何在标记页面后使用堆栈的指令都会触发检查,该指令可能是也可能不是安全点

正如您和@melkyades提到的,一种方法是分配一些寄存器(例如EBX),通常从图像初始化为某个最大值。然后,JIT在每个本机化的方法中内联代码,这些代码在方法的开头和其中发生的每个后跳(#whileTrue:/False:)处递减计数器(顺便说一句,这就是为什么有后跳字节码的原因。)当计数器变为零时,这段代码会检查三件事:(1)是否有任何操作系统事件要查看,(2)对象存储器的状态(可能最终触发一些GC操作)和(3)堆栈指针(预测堆栈结束条件)

可以实现的一个有趣的技巧是:

@1: call CheckEventsEtc
    ...
    cmp ESP, [TOS]
    dec EBX
    jbe @1

假定dec不修改进位标志,则如果ESP变得太小或如果EBX处的计数器变为零,则jbe指令将跳转到检查例程。如果出现上述任何情况,检查程序将必须查明原因并采取相应行动。

最新更新