[英]In Squeak, where do I find the code for the message handling algorithm?
在Squeak中向對象發送消息時,運行時調用算法就像
doesNotUnderstand:
self
現在,一個非常相似的算法用於respondsTo:
方法,實際上它可以通過檢查respondsTo:
的代碼來看到。 我想要找到的是用於調用的上述算法的代碼的位置 。
我知道perform:
做類似的事情,但我相信它不是用於常規方法調用,而只是作為類似反射的方法調用機制(例如,直到運行時程序員不知道方法名稱)。
如果上面的代碼也被隱藏為原始指令,我會在哪里找到原始調用? 如果不是,我會在哪里找到代碼本身?
你可能想看看VMMaker 。 它的Interpreter類是執行CompiledMethod字節碼的人,實際上會將消息發送給你的對象。
例如,如果你看一下Object >> respondsTo的字節碼:你會看到
17 <70> self
18 <C7> send: class
19 <10> pushTemp: 0
20 <E0> send: canUnderstand:
21 <7C> returnTop
解釋器讀取字節碼,在其BytecodeTable中查找該字節碼(在Interpreter類>> initialiseBytecodeTable中初始化)並執行適當的方法。 所以<70>(#pushReceiverByteCode)將self推送到Interpreter的內部堆棧。 然后(#bytecodePrimClass)歸結為“找到自己的班級”。 <10>(#pushTemporaryVariableBytecode)將參數推送到#respondsTo:到堆棧上。 有趣的部分發生在(#sendLiteralSelectorBytecode),它調用self normalSend
normalSend。 #normalSend依次計算接收器的self class
(本例中為self class
),然后調用self commonSend
,它找到我們尋求運行的實際方法,然后運行它。
我是VM的新手; 以上可能不是看到算法在行動中的絕對最佳位置等(或者甚至是最好的解釋),但我希望它是一個好的開始。
VM用於實際發送消息的算法正如您在問題中概述的那樣。 該算法的實際實現在Interpreter>>commonSend
定義。 查找算法位於Interpreter>>lookupMethodInClass:
,執行算法位於Interpreter>>internalExecuteNewMethod
。
前者與你描述的一樣有效:
后者的工作方式如下:
進一步挖掘, ContextPart
類是一個能夠運行字節碼的解釋器。 根據其文件:
[它與此問題相關的方法] 與Smalltalk機器本身的操作完全平行 。
如果我們檢查它如何解釋字節碼,
interpret
方法為每條指令調用其interpretNextInstructionFor:
. interpretNextInstructionFor:
調用send:super:numArgs:
遇到send指令時。 send:super:numArgs:
calls send:to:with:super:
假設它不是原始消息)。 send:to:with:super:
使用Behavior
的lookupSelector:
找到要使用的正確選擇器。 Behavior
的lookupSelector:
是負責問題中出現的算法lookupSelector:
類循環的人。 所以這不是我正在尋找的實際實現(因此這不是一個真正的答案),但我想它可以幫助理解精確算法的細微差別。
要了解Franks的回復,您需要一些背景信息:
編譯器生成一個“發送字節碼”,后來由VM的字節碼解釋器執行(或者jitted,但語義是相同的)。 因此,您不希望在任何類中找到實現,而是在VM中。
大多數其他VM都是用C語言編寫的,匯編程序或其他什么...
但是:squeak VM是用Smalltalk編寫的,並通過“Subt-of-Smalltalk-to-C-Compiler”編譯為C(所謂的“Slang”,因為它沒有涵蓋完整的Smalltalk語義)。
用Smalltalk編寫,VM當然可以在Squeak中開發,調試和測試(通過在圖像中運行圖像上的Slang解釋器)。 這就是為什么你可以在弗蘭克描述的Interpreter中找到實現的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.