序言
这是关于提高 JIT 编译器中的消息发送效率。尽管提到的是 Smalltalk,但这个问题适用于大多数动态 JIT 编译语言。
问题
给定一个消息发送站点,它可以分为单态、多态或巨型。如果消息发送的接收者始终是同一类型,则它是单态发送,如下所示
10 timesRepeat: [Object new].
其中new
的接收者始终是Object
。对于这种类型的发送,JIT 会发出单态内联缓存。
有时,给定的发送站点引用几种不同的对象类型,例如:
#(1 'a string' 1.5) do: [:element | element print]
在这种情况下,print
被发送到不同类型的对象。对于这些情况,JIT 通常会发出多态内联缓存。
当消息不仅发送到同一位置的几个不同对象类型,而是发送到许多不同对象类型时,就会发生超态消息发送。最突出的例子之一是:
Behavior>>#new
^self basicNew initialize
这里,basicNew
创建对象,然后 initialize
进行初始化。你可以这样做:
Object new
OrderedCollection new
Dictionary new
它们都会执行相同的Behavior>>#new方法。由于初始化的实现在很多类中是不同的,PIC很快就会被填满。 我对这种发送站点感兴趣,因为我知道它们很少出现(只有 1% 的发送是超形态的)。
问题
What are the possible and specific optimizations for megamorphic send sites to avoid doing a lookup?
最佳答案
我想象了一些,并且想了解更多。 PIC 满后,我们必须调用查找(无论是满的还是全局缓存的),但为了优化我们可以:
- 回收 PIC,丢弃所有条目(许多条目可能是旧的且不经常使用)。
- 调用某种特定的超态查找(即将所有先前分派(dispatch)的类型缓存在由类型哈希访问的数组中)。
- 内联包含方法(内联后,发送站点可能会停止变态)
关于performance - 有哪些不同的技术可以使超形态调用站点更加高效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29021373/