【问题标题】:In Squeak, where do I find the code for the message handling algorithm?在 Squeak 中,我在哪里可以找到消息处理算法的代码?
【发布时间】:2010-07-26 08:31:38
【问题描述】:

在 Squeak 中向对象发送消息时,运行时调用算法类似于

  1. curr
  2. 在 curr 不为零时重复
    1. 在该类的方法中搜索选择器;如果存在,调用它并返回
    2. curr
  3. 致电doesNotUnderstand:self

现在,respondsTo: 方法使用了一个非常相似的算法,确实可以通过检查respondsTo: 的代码看到它。 我要查找的是用于调用的上述算法的代码位置

我知道 perform: 做了类似的事情,但我相信它不用于常规方法调用,而仅用作类似反射的方法调用机制(例如,当程序员直到运行时才知道方法名称时)。

如果上面的代码也被隐藏为原始指令,我在哪里可以找到原始调用?如果不是,我在哪里可以找到代码本身?

【问题讨论】:

    标签: reflection smalltalk squeak


    【解决方案1】:

    您可能想查看VMMaker。它的 Interpreter 类是执行 CompiledMethod 字节码的人,并且实际上会将消息发送到您的对象。

    例如,如果您查看 Object>>respondsTo: 的字节码,您会看到

    17 <70> self
    18 <C7> send: class
    19 <10> pushTemp: 0
    20 <E0> send: canUnderstand:
    21 <7C> returnTop
    

    解释器读入一个字节码,在它的字节码表中查找该字节码(在解释器类>>initialiseBytecodeTable中初始化)并执行适当的方法。所以 (#pushReceiverByteCode) 将 self 推送到解释器的内部堆栈中。然后 (#bytecodePrimClass) 归结为“找到自己的班级”。 (#pushTemporaryVariableBytecode) 将参数推送到#respondsTo: 到堆栈上。有趣的部分发生在 (#sendLiteralSelectorBytecode),它调用 self normalSend。 #normalSend 依次计算出接收者的类(本例中为self class),然后调用self commonSend,它找到我们要运行的实际方法,然后运行它。

    我是虚拟机新手;以上可能不是查看实际算法等的绝对最佳位置(甚至不是最佳解释),但我希望这是一个很好的起点。

    VM 用于实际发送消息的算法与您在问题中概述的一样。该算法的实际实现在Interpreter&gt;&gt;commonSend 中定义。查找算法在Interpreter&gt;&gt;lookupMethodInClass:,执行算法在Interpreter&gt;&gt;internalExecuteNewMethod

    前者的工作原理与您描述的一样:

    1. 列表项
    2. 尝试在此类中查找方法。
    3. 如果找不到,请查看超类。
    4. 如果递归失败,请尝试查找#doesNotUnderstand:
    5. 如果 #doesNotUnderstand: 在类层次结构中的任何位置都不存在,则抛出错误。

    后者的工作方式如下:

    1. 如果是原语,请运行原语。
    2. 如果不是,请激活新方法(创建新的激活记录)。
    3. (检查中断。)

    【讨论】:

    • RE "compile-time" - 我已经编辑了问题以澄清我的意思。
    • 我会相应地调整我的答案。
    【解决方案2】:

    进一步挖掘,ContextPart 类是一个能够运行字节码的解释器。根据其文档:

    [与此问题相关的方法]与 Smalltalk 机器本身的操作完全平行

    如果我们检查它是如何解释字节码的,

    1. 它的interpret 方法为每条指令调用它的interpretNextInstructionFor:
    2. 遇到发送指令时,interpretNextInstructionFor: 会调用 send:super:numArgs:
    3. send:super:numArgs: 调用 send:to:with:super:(假设它不是原始消息)。
    4. send:to:with:super: 使用 BehaviorlookupSelector: 来定位要使用的正确选择器。
    5. BehaviorlookupSelector: 负责问题中出现的算法中的超类循环。

    所以这不是我正在寻找的实际实现(因此这不是真正的答案),但我想它可以帮助理解精确算法的细微差别。 p>

    【讨论】:

      【解决方案3】:

      要了解弗兰克斯的反应,您需要一些背景信息:

      编译器生成一个“发送字节码”,稍后由VM的字节码解释器执行(或jitted,但语义相同)。因此,您不会期望在任何类中找到实现,而是在 VM 中。

      大多数其他 VM 是用 C、Assembler 或其他语言编写的...

      但是:squeak VM 是用 Smalltalk 编写的,并由“Subset-of-Smalltalk-to-C-Compiler”(所谓的“俚语”,因为它不涵盖完整的 Smalltalk 语义)编译为 C。

      使用 Smalltalk 编写的虚拟机当然可以在 Squeak 中进行开发、调试和测试(通过在图像中对图像运行 Slang 解释器)。这就是为什么您可以按照 Frank 的描述在 Interpreter 中找到实现。

      【讨论】:

        猜你喜欢
        • 2012-03-17
        • 1970-01-01
        • 2017-07-27
        • 2011-08-31
        • 1970-01-01
        • 2023-03-12
        • 2019-06-03
        • 1970-01-01
        • 2013-11-23
        相关资源
        最近更新 更多