ホームページ  >  記事  >  バックエンド開発  >  Python仮想マシンのバイトコードの制御フローを実装する方法

Python仮想マシンのバイトコードの制御フローを実装する方法

王林
王林転載
2023-05-26 12:13:201511ブラウズ

制御フローの実装

制御フロー コードのこの部分には主に次のバイトコード命令が含まれます。次のすべてのバイトコード命令にはパラメータがあります:

  • #JUMP_FORWARD,完全な命令は、このパラメータを現在実行中のバイトコード命令の位置に追加し、対応する結果にジャンプして実行を継続します。

  • スタックの先頭要素が true の場合、バイトコードの実行位置を受け取ったパラメータ値に変更する命令は「POP_JUMP_IF_TRUE」です。スタックから最上位の要素をポップします。

  • POP_JUMP_IF_FALSE、この命令は POP_JUMP_IF_TRUE と同じですが、唯一の違いは、スタックの最上位要素が true に等しいかどうかを判断することです。

  • JUMP_IF_TRUE_OR_POP、スタックの最上位要素が true に等しい場合、バイトコードの実行位置はパラメータに対応する値に設定され、最上位要素をポップする必要はありませんスタックの。スタックの最上位要素が false の場合、その要素はポップされる必要があります。

  • JUMP_IF_FALSE_OR_POP は JUMP_IF_TRUE_OR_POP と同じですが、スタックの最上位要素が false に等しい必要があります。

  • JUMP_ABSOLUTE は、バイトコードの実行位置をパラメータの値に直接設定します。

一般に、これらのジャンプ命令により、Python インタープリターはバイトコードの実行時に特定の条件に従って実行フローを変更し、ループや条件文などの基本的な言語構造を実装できます。

ここで、例を使用して、上記のさまざまな命令の実行プロセスを深く理解します。

import dis
 
 
def test_control01():
    a = 1
 
    if a > 1:
        print("a > 1")
    elif a < 1:
        print("a < 1")
    else:
        print("a == 1")
 
if __name__ == &#39;__main__&#39;:
    dis.dis(test_control01)

上記のプログラムの出力結果は次のとおりです。

6 0 LOAD_CONST 1 (1)

2 STORE_FAST
4 LOAD_FAST 3 22

9 12 LOAD_GLOBAL 0 (print)
14 LOAD_CONST 2 (' a > 1')
16 CALL_FUNCTION 1
18 POP_TOP
20 JUMP_FORWARD 26 (~48)

10 >> 22 LOAD_FAST 0 (a)
24 LOAD_CONST 1 (1)
26 Compare_op 0 (& lt;)
28 POP_JUMP_IF_FALSE 40
11 30 Load_global 0 (印刷)
32 load_const 3( 'a&lt; 1')## 34 call_function 1
36 pop_top
38 jump_forward 8(48)

13&gt;&gt; CALL_FUNCTION 1
46 POP_TOP
48 LOAD_CONST 0 (なし)
50 RETURN_VALUE


上記をシミュレーションしてみましょう。バイトコード実行プロセスが開始されました。カウンターを使用して現在のバイトコードの実行位置を示します:

バイトコードの実行が開始される前のスタック スペースとカウンタのステータスは次のとおりです:



最初のバイトコード LOAD_CONST を実行します。実行後、カウンタ = 2 になります。このバイトコードは 1 バイトを占め、パラメータ スタックは 1 バイトであるため、次回実行されるバイトコードの位置はバイトコード内になります。下位 3 つの位置、対応するsubscript は 2 なので、counter = 2 となります。

Python仮想マシンのバイトコードの制御フローを実装する方法

次に、2 番目のバイトコード STORE_FAST を実行します。a を 1 に指定します。同じ STORE_FAST オペコードとオペランドがそれぞれ 1 バイトを占有するため、このワードが実行されます。セクションコード後のスタックスペース、カウンター = 4。

Python仮想マシンのバイトコードの制御フローを実装する方法

次に、LOAD_FAST は a が指すオブジェクト (1) をスタックにロードします。このとき、counter = 6 となり、LOAD_CONST は定数 1 をスタックにロードします。カウンタ = 8 の場合、これら 2 つの命令を実行した後のスタック スペースの変化は、次の図に示すようになります。この命令には、パラメータが比較の記号を表します。ここでは > 1 を比較しており、比較結果はスタックにプッシュされます。COMPARE_OP が最初にスタックの 2 つの入力をポップアップするため、比較結果は false ですスペースがあるので、これを実行した後の命令後のスタックスペースとカウンタの値は以下の通りです:

Python仮想マシンのバイトコードの制御フローを実装する方法

次の命令はPOP_JUMP_IF_FALSEです。前のバイトコードと同じように、このバイトコードはスタックの一番上で false をポップし、ジャンプして、カウンターの値をパラメーターの値に直接プログラムします。ここでのパラメーターは 22 なので、カウンター = 22 になります。この命令を実行した後、

Python仮想マシンのバイトコードの制御フローを実装する方法

22 にジャンプしたため、次に実行される命令は LOAD_FAST で、変数 a をスタック領域にロードします。定数 1 をスタック領域に追加します これら 2 回の実行後、状況は次のようになります:

Python仮想マシンのバイトコードの制御フローを実装する方法

今度は POP_JUMP_IF_FALSE を実行しますが、今回の結果も false です。したがって、POP_JUMP_IF_FALSE の実行を続けます。今回のパラメータは 40 で、counter の値を 40 に直接設定します。

Python仮想マシンのバイトコードの制御フローを実装する方法

次に、LOAD_GLOBAL はグローバル変数印刷関数 counter をロードして 42 になり、LOAD_CONST は文字列 "a == 1" をスタック領域にロードし、counter = 44、ステータスは次のとおりです:

Python仮想マシンのバイトコードの制御フローを実装する方法

CALL_FUNCTION このバイトコードには 1 つのパラメータがあり、関数を呼び出すためのパラメータの数を示します。print 関数のパラメータは 1 つだけなので、ここでは 1 です。 「a== 1」という文字列を出力しますが、ここで注意が必要なのは、print関数はNoneを返すため、CALL_FUNCTION実行後のステータスは次のようになります。

#この時点で上記の関数はほぼ実行されていますが、以降のいくつかのバイトコードは非常に単純なので説明は省略します。

以上がPython仮想マシンのバイトコードの制御フローを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。