Wahrscheinlich sollten Sie sich Folgendes ansehen VMMaker . Die Klasse Interpreter ist derjenige, der die Bytecodes einer CompiledMethod ausführt und die Nachrichten an Ihre Objekte sendet.
Wenn Sie sich zum Beispiel die Bytecodes für Object>>respondsTo: ansehen, werden Sie sehen
17 <70> self
18 <C7> send: class
19 <10> pushTemp: 0
20 <E0> send: canUnderstand:
21 <7C> returnTop
Der Interpreter liest einen Bytecode ein, sucht diesen Bytecode in seiner BytecodeTabelle (initialisiert in Interpreter class>>initialiseBytecodeTable) und führt die entsprechende Methode aus. Also <70> (#pushReceiverByteCode) schiebt self auf den internen Stack des Interpreters. Dann läuft (#bytecodePrimClass) auf "finde die Klasse von self" hinaus. <10> (#pushTemporaryVariableBytecode) schiebt das Argument zu #respondsTo: auf den Stack. Der interessante Teil passiert mit (#sendLiteralSelectorBytecode), der aufruft self normalSend
. #normalSend ermittelt seinerseits die Klasse des Empfängers ( self class
in diesem Fall), und ruft dann self commonSend
der die gewünschte Methode findet und sie dann ausführt.
Ich bin ein VM-Neuling; das oben Gesagte ist vielleicht nicht der absolut beste Ort, um den Algorithmus in Aktion usw. zu sehen (oder sogar die beste Erklärung), aber ich hoffe, es ist ein guter Ausgangspunkt.
Der Algorithmus, den die VM zum Senden einer Nachricht verwendet, entspricht dem, was Sie in Ihrer Frage beschrieben haben. Die eigentliche Implementierung dieses Algorithmus ist definiert in Interpreter>>commonSend
. Der Suchalgorithmus ist in Interpreter>>lookupMethodInClass:
und der Ausführungsalgorithmus ist in Interpreter>>internalExecuteNewMethod
.
Ersteres funktioniert ähnlich wie von Ihnen beschrieben:
- Posten auflisten
- Versuchen Sie, die Methode in dieser Klasse zu finden.
- Wenn nicht gefunden, suchen Sie in der Superklasse.
- Wenn dies rekursiv fehlschlägt, versuchen Sie #doesNotUnderstand zu finden:
- Wenn #doesNotUnderstand: nirgendwo in der Klassenhierarchie existiert, wird ein Fehler ausgegeben.
Letzteres funktioniert folgendermaßen:
- Wenn es sich um ein Primitiv handelt, führen Sie das Primitiv aus.
- Ist dies nicht der Fall, aktivieren Sie die neue Methode (erstellen Sie einen neuen Aktivierungssatz).
- (Prüfen Sie auf Unterbrechungen.)