Performance 让megamorphic呼叫站点更高效的不同技术有哪些

Performance 让megamorphic呼叫站点更高效的不同技术有哪些,performance,optimization,smalltalk,jit,vm-implementation,Performance,Optimization,Smalltalk,Jit,Vm Implementation,序言 这是关于提高JIT编译器中的消息发送效率。尽管提到Smalltalk,但这个问题适用于大多数动态JIT编译语言 问题 给定一个消息发送站点,它可以分为单态、多态或巨态。如果消息发送的接收者总是同一类型,则它是单态发送,如中所示 10 timesRepeat: [Object new]. 其中,new的接收者始终是对象。对于这种类型的发送,JIT发出单态内联缓存 有时,给定的发送站点引用几种不同的对象类型,如: #(1 'a string' 1.5) do: [:element | ele

序言

这是关于提高JIT编译器中的消息发送效率。尽管提到Smalltalk,但这个问题适用于大多数动态JIT编译语言

问题

给定一个消息发送站点,它可以分为单态、多态或巨态。如果消息发送的接收者总是同一类型,则它是单态发送,如中所示

10 timesRepeat: [Object new].
其中,
new
的接收者始终是
对象
。对于这种类型的发送,JIT发出单态内联缓存

有时,给定的发送站点引用几种不同的对象类型,如:

#(1 'a string' 1.5) do: [:element | element print]
在这种情况下,
print
被发送到不同类型的对象。对于这些情况,JIT通常会发出多态内联缓存

当一条消息被发送到同一个地方的多个不同的对象类型而不仅仅是少数对象类型时,就会发生Megamorphic消息发送。最突出的例子之一是:

Behavior>>#new
    ^self basicNew initialize
这里,
basicNew
创建对象,然后
initialize
进行初始化。你可以做:

Object new
OrderedCollection new
Dictionary new
它们都将执行相同的行为>>#新方法。由于initialize的实现在很多类中是不同的,PIC将很快填充。我对这种发送站点很感兴趣,因为我知道它们只会很少出现(只有1%的发送是巨型的)

问题

为了避免查找,megamorphic发送站点有哪些可能的和特定的优化


我想象了一些,想知道更多。PIC满后,我们必须调用查找(已满或全局缓存),但要优化,我们可以:

  • 回收图片,扔掉所有条目(许多条目可能是旧的,不经常使用)
  • 调用某种特定的巨形查找(即,将所有以前调度的类型缓存在由类型哈希访问的数组中的查找)
  • 内联包含方法(内联后,发送站点可能不再是超级站点)

如何将megamorphic选择器(如#initialize)升级到连接到接收器MethodDictionary的特殊位置,从而缩短其查找?这些特殊位置是什么?那它们怎么能附在接收者的方法词典上呢?我不知道确切的情况。但是,嘿,字典提供了很多附加内容的可能性!例如,我会考虑用一个保留密钥(例如,一个小整数)向MD添加一个关联,并将其复制到MyGasoic方法中。由于所有选择器都是符号(而不是小整数),因此不会与“常规”消息发生任何冲突。但同样,这只是一个需要更多思考和实验的想法。