Reflection 在Squeak中,我在哪里可以找到消息处理算法的代码?
当向Squeak中的对象发送消息时,运行时调用算法类似于Reflection 在Squeak中,我在哪里可以找到消息处理算法的代码?,reflection,smalltalk,squeak,Reflection,Smalltalk,Squeak,当向Squeak中的对象发送消息时,运行时调用算法类似于 curr您可能想看看。它的解释器类是执行CompiledMethod字节码的家伙,并将消息实际发送到您的对象 例如,如果您查看Object>>respondsTo的字节码,您将看到 17 <70> self 18 <C7> send: class 19 <10> pushTemp: 0 20 <E0> send: canUnderstand: 21 <7C> returnTop
17 <70> self
18 <C7> send: class
19 <10> pushTemp: 0
20 <E0> send: canUnderstand:
21 <7C> returnTop
17自
18发送:类
19:0
20发送:可以理解:
21返回顶部
解释器读入字节码,在字节码表中查找该字节码(在解释器类>>initialiseBytecodeTable中初始化),并执行适当的方法。因此(#pushReceiverByteCode)将self推到解释器的内部堆栈上。然后(#bytecodePrimClass)归结为“查找self的类”。(#pushTemporaryVariableBytecode)将参数推送到堆栈上的#respondsTo:。有趣的部分发生在(#sendLiteralSelectorBytecode)中,它调用self-normalSend
#normalSend依次计算出接收方的类(在本例中为self class
),然后调用self commonSend
,它找到我们寻求运行的实际方法,然后运行它
我是一个虚拟机新手;上面可能不是看到算法运行的绝对最佳位置,等等(甚至是最好的解释),但我希望这是一个好的开始
VM实际发送消息所使用的算法如您在问题中所述。该算法的实际实现在解释器>>commonSend
中定义。查找算法在解释器>>查找方法inclass:
中,执行算法在解释器>>内部执行方法中
前者的工作原理与您描述的一样:
列表项
请尝试在此类中查找该方法
如果未找到,请查看超类
如果递归失败,请尝试查找#不理解:
如果#doesNotUnderstand:在类层次结构中的任何位置都不存在,则抛出一个错误
后者的工作原理如下:
如果是原语,请运行原语
如果不是,则激活新方法(创建新的激活记录)
(检查是否有中断。)
进一步挖掘,ContextPart
类是一个能够运行字节码的解释器。根据其文件:
[其与此问题相关的方法]与Smalltalk机器本身的操作完全平行
如果我们检查它如何解释字节码
它的explorate
方法为每条指令调用它的exploratextInstructionfor:
interpretatenxtinstructionfor:
遇到send指令时调用send:super:numArgs:
send:super:numArgs:
调用send:to:with:super:
(假设它不是原始消息)
send:to:with:super:
使用Behavior
的lookupSelector:
找到要使用的正确选择器
行为
的查找选择器:
负责问题中出现的算法中的超类循环
所以这不是我想要的实际实现(因此这不是一个真正的答案),但我想这有助于理解精确算法的细微差别。要理解Franks的反应,你需要一些背景信息:
编译器生成一个“发送字节码”,随后由VM的字节码解释器执行(或jitted,但语义相同)。因此,您不会期望在任何类中找到实现,而是在VM中找到实现
大多数其他虚拟机都是用C、汇编或其他语言编写的
但是:squeak VM是用Smalltalk编写的,并由“Smalltalk到C编译器的子集”编译成C(所谓的“俚语”,因为它没有涵盖Smalltalk的全部语义)
使用Smalltalk编写的虚拟机当然可以在Squeak中开发、调试和测试(通过在图像中运行图像上的俚语解释器)。这就是为什么您可以在解释器中找到Frank所描述的实现。RE“compile time”-我对问题进行了编辑,以澄清我的意思。我将相应地调整我的答案。