多态内联缓存如何与可变类型一起使用?

时间:2009-06-27 15:57:23

标签: javascript vm-implementation dynamic-typing cache-invalidation polymorphic-functions

多态内联缓存(PIC)通过按对象类型缓存实际方法来工作,以避免昂贵的查找过程(通常是哈希表查找)。

如果类型对象是可变的,那么如何处理类型比较(即该方法可能在运行时被猴子修补为不同的东西)?

我提出的一个想法是一个“类计数器”,每次调整一个方法时会增加,但是这似乎在一个重度猴子修补的环境中会非常昂贵,因为它会杀死所有该类的PIC,即使它们的方法没有改变。

我确信必须有一个很好的解决方案,因为这个问题直接适用于JavaScript,而AFAIK所有三个大型JavaScript虚拟机都有PIC。

2 个答案:

答案 0 :(得分:1)

在V8中,我假设monkeypatching会改变对象的“隐藏类”(“map”是SELF术语)。这可以在你猴子修补对象本身。

如果你猴子修补了这个类(你可以这样做吗?),我猜它会使所有的PIC无效,因为这可能很少见。或者,它可能会重新编译旧方法以直接调度到新方法(在我猜测类型检查之后)

另外,我认为其他“大3”实际上并不使用PIC。我认为你的意思是squirrelfish和tracemonkey。前者是翻译,后者则侧重于跟踪方法,我不记得听过有关PIC的任何内容。事实上,我不认为tracemonkey对物体做任何酷事,但我可能是错的。

答案 1 :(得分:0)

使用类型推断:

  

SpiderMonkey主要使用类型推断来确定正在访问哪些属性;如果类型推断没有找到被访问对象的确切形状,SpiderMonkey使用PIC(多态内联缓存)来存储查找结果。

     

另一种形式的分析反馈是Baseline JIT的多态内联缓存。多态内联缓存是优化源自Smalltalk社区的动态调度的经典技术。

去优化是类型推断失败时发生的进程的名称:

  

当然,JavaScript是一种动态类型语言,有时候关于对象隐藏类的假设是不正确的,在这种情况下,V8将“去优化”并恢复到方法调用的原始版本检查对象隐藏类。

这需要多个编译器才能工作:

  

从技术上讲,它意味着编译器实际上是两个编译器:基本编译器和“优化器”。 (或者更重要的是,如果我们谈论的是JSC和SpiderMonkey)。这个概念非常合理并且可以产生令人难以置信的性能,但是有一个细微差别:优化的代码可能在各个地方被“去优化”,而不仅仅是在入口点,这意味着环境(局部变量,参数,上下文)应该是映射和移动。

     

Ion是优化编译器,不支持在调试模式检查中进行编译。实际上,实现这样的支持具有可疑的实用性,因为它的优化会使onStep调用充其量不合适。为了支持调试模式,堆栈上的优化代码被去优化并被保存到Baseline。也就是说,堆栈上的Ion帧被重建的Baseline帧覆盖,该帧对应于Ion代码当前正在执行的相同位置。

通过动态去优化来完成调试:

  

我们可以做得更好。以自我语言体现的90年代的梦想在JavaScript中充满活力。我们可以通过堆栈替换技术调整Self的动态去优化,以调试优化的代码。 debug mode OSR的核心思想很简单:当需要调试时,我们在堆栈上取消优化并重新编译JITed代码,随时修补返回地址。有人可能会说它几乎是优雅的,如果不是因为它在堆叠框架上造成的严重暴力。

     

考虑以下JavaScript函数:

function foo(o) { return o.f + o.g; }
  

在此示例中,属性访问可能导致从堆中已知位置的简单加载到getter调用甚至复杂DOM陷阱的任何操作,例如o是文档对象和{{ 1}}是页面中元素的名称。 Baseline JIT最初将作为完全多态分派执行这些属性访问。但是当它这样做时,它将记录它所采取的步骤,然后就地修改堆访问,以便成为将来重复类似访问的必要步骤的缓存。例如,如果对象在距对象基础偏移16处具有属性f,则代码将被修改为首先快速检查传入对象是否包含偏移量为16的属性f然后执行加载。据说这些缓存是内联的,因为它们完全表示为生成的机器代码。它们被称为多态的,因为如果遇到不同的对象结构,则修改机器代码以在执行完全动态属性查找之前切换先前遇到的对象类型。当DFG编译此代码时,它将检查内联缓存是否是单态的 - 仅针对一个对象结构进行优化 - 如果是这样,它将仅发出对该对象结构的检查,然后是直接加载。在此示例中,如果o始终是具有不变偏移的属性ff的对象,则DFG只需要为g发出一个类型检查,然后进行两次直接加载。

Data Flow Just-in-Time Compiler (DFG JIT) Optimization Pipeline

Faster-Than-Light Just-in-Time Compiler (FTL JIT) Optimization Pipeline

<强>参考