你可能想看看VMMaker。它的 Interpreter 类是执行 CompiledMethod 字节码的人,并且实际上会将消息发送到您的对象。
例如,如果您查看 Object>>respondsTo: 的字节码,您会看到
17 <70> self
18 <C7> send: class
19 <10> pushTemp: 0
20 <E0> send: canUnderstand:
21 <7C> returnTop
解释器读入一个字节码,在其 BytecodeTable 中查找该字节码(在解释器类>>initialiseBytecodeTable 中初始化)并执行适当的方法。所以 <70> (#pushReceiverByteCode) 将 self 推送到解释器的内部堆栈中。然后 (#bytecodePrimClass) 归结为“找到自己的班级”。<10> (#pushTemporaryVariableBytecode) 将参数推送到#respondsTo: 到堆栈上。有趣的部分发生在 (#sendLiteralSelectorBytecode),它调用self normalSend
. #normalSend 依次计算出接收者的类(self class
在这种情况下),然后调用self commonSend
,它找到我们寻求运行的实际方法,然后运行它。
我是VM新手;以上可能不是查看算法运行等的绝对最佳位置(甚至不是最好的解释),但我希望这是一个很好的起点。
虚拟机用于实际发送消息的算法与您在问题中概述的一样。该算法的实际实现在Interpreter>>commonSend
. 查找算法在里面Interpreter>>lookupMethodInClass:
,执行算法在里面Interpreter>>internalExecuteNewMethod
。
前者的工作原理与您描述的一样:
- 项目清单
- 尝试在这个类中找到方法。
- 如果找不到,请查看超类。
- 如果递归失败,请尝试查找#doesNotUnderstand:
- 如果 #doesNotUnderstand: 在类层次结构中的任何位置都不存在,则抛出错误。
后者的工作方式如下:
- 如果是原语,则运行原语。
- 如果不是,请激活新方法(创建新的激活记录)。
- (检查中断。)