BEAM命令
この記事は英語の原文を日本語に翻訳したものです。原文: https://blog.stenmans.org/theBeamBook/#AP-Instructions
翻訳元: happi/theBeamBook 7998e22e78417dbe20e5136b9aee862a1ecaa404(コミット 7998e22)
本章では、BEAM汎用命令セットの大半の命令を詳しく見ていきます。
次節では、コード内のドキュメント(lib/compiler/src/genop.tabを参照)から生成した簡単な説明とともに、すべての命令を一覧にしています。
関数とラベル
label Lbl
汎用命令セットの命令番号1は、実のところ命令と呼べるようなものではありません。 コード中の現在位置に名前、というより番号を与えるだけの、モジュールローカルなラベルです。
各ラベルはジャンプの着地点になりうるため、ベーシックブロックの開始位置を示す場合があります。
func_info Module Function Arity
各関数のコードはfunc_info命令から始まります。
この命令はfunction clauseエラーを生成するために使われ、関数の実際のコードはfunc_info命令の直後にあるラベルから実行が始まります。
ガード付きの関数を考えてみましょう。
id(I) when is_integer(I) -> I.
この関数に対応するBeamコードはおおむね次のようになります。
{function, id, 1, 4}.
{label,3}.
{func_info,{atom,test1},{atom,id},1}.
{label,4}.
{test,is_integer,{f,3},[{x,0}]}.
return.
ここでメタ情報{function, id, 1, 4}は、id/1関数の実行がラベル4から始まることを示しています。
ラベル4ではx0に対してis_integerを行い、失敗するとfunc_info命令を指すラベル3(f3)へジャンプしてfunction clause例外を生成します。
成功した場合はそのまま処理を続け、引数(x0)を返します。
Exportレコード(erts/emulator/beam/export.hで定義)を指しています。
このレコード内にあるいくつかの専用のメモリワードは、トレース機構がすべてのプロセスによる関数の呼び出し・返却のたびに発火する特別なトレース命令を配置するために使われます。テスト命令
型テスト
型テスト命令(is_* Lbl Argument)は、引数が指定した型かどうかを調べ、そうでなければラベルLblへジャンプします。
beamの逆アセンブラは、これらの命令をすべてtest命令として包んで表示します。例えば次のようになります。
{test,is_integer,{f,3},[{x,0}]}.
現在の型テスト命令には、is_integer、is_float、is_number、is_atom、is_pid、is_reference、is_port、is_nil、is_binary、is_list、is_nonempty_list、is_function、is_function2、is_boolean、is_bitstr、is_tupleがあります。
さらに、アリティ3を取る型テスト命令が1つあります。test_arity Lbl Arg Arityです。
この命令は、引数(タプルであることを前提とします)のアリティがArityであるかどうかを調べます。
通常、この命令の直前にはis_tuple命令が置かれます。
比較
比較命令(is_* Lbl Arg1 Arg2)は、命令の指示に従って2つの引数を比較し、比較が成立しなければLblへジャンプします。
比較命令には、is_lt、is_ge、is_eq、is_ne、is_eq_exact、is_ne_exactがあります。
Erlangのすべての項は順序付けられているため、これらの命令はどんな2つの項でも比較できることを思い出してください。
たとえば、アトムselfがself()の返すpidより小さいかどうかを調べることもできます(実際に小さいです)。
数値については、比較がErlangのnumber型に基づいて行われることに注意してください(詳しくは型システムの章を参照してください)。 つまり、floatとintegerが混在する比較では、精度の低い方の数値がもう一方の型に変換されてから比較されます。 たとえば私の環境では、1と1.0は等しいと比較され、9999999999999999と1.0e16も同様です。 浮動小数点数の比較には常にリスクが伴うため避けるべきであり、結果は基盤となるハードウェアによって変わることがあります。
整数の1と浮動小数点数の1.0を確実に区別して比較したい場合は、is_eq_exactとis_ne_exactを使います。
これはErlangの演算子=:=と=/=に対応します。
関数呼び出し
本章では、さまざまな呼び出し命令が何を行うのかを概観します。 関数呼び出しの仕組みについての詳しい説明は、呼び出しの章を参照してください。
call Arity Label
同一モジュール内、ラベルLabelにあるアリティArityの関数を呼び出します。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
呼び出し後の現在のコードアドレスはCPに保存されます。
ローカル呼び出しでは、指定するラベルは常にそのコードが開始する関数の2番目のラベルです。
コンテキストスイッチが必要になった際にMFAを取得できるよう、そのラベルの直前の命令はfunc_infoであることが前提とされています。
call_only Arity Label
同一モジュール内、ラベルLabelにあるアリティArityの関数へ末尾再帰呼び出しを行います。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されません。
call_last Arity Label Deallocate
スタックをDeallocateワード分解放したうえで、同一モジュール内、ラベルLabelにあるアリティArityの関数へ末尾再帰呼び出しを行います。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されません。
call_ext Arity Destination
Destinationで指定される、アリティArityの関数へ外部呼び出しを行います。
アセンブリ上でDestinationは通常{extfunc, Module, Function, Arity}のように書かれ、これはモジュールのimportsセクションに追加されます。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されます。
call_ext_only Arity Destination
Destinationで指定される、アリティArityの関数へ末尾再帰的な外部呼び出しを行います。
アセンブリ上でDestinationは通常{extfunc, Module, Function, Arity}のように書かれます。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されません。
call_ext_last Arity Destination Deallocate
スタックをDeallocateワード分解放したうえで、Destinationで指定される、アリティArityの関数へ末尾再帰的な外部呼び出しを行います。
アセンブリ上でDestinationは通常{extfunc, Module, Function, Arity}のように書かれます。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されません。
bif0 Bif Reg, bif[1,2] Lbl Bif [Arg,…] Reg
与えられた引数でbifBifを呼び出し、結果をRegに格納します。
bifが失敗した場合はLblへジャンプします。
アリティ0のbifは失敗しえないため、bif0には失敗時のラベルがありません。
gc_bifを参照してください。gc_bif[1-3] Lbl Live Bif [Arg, …] Reg
与えられた引数でbifBifを呼び出し、結果をRegに格納します。
bifが失敗した場合はLblへジャンプします。
引数はx(Live)、x(Live+1)、x(Live+2)に格納されます。
Liveを持つため、ガベージコレクションを起動するのに十分な情報が得られます。call_fun Arity
call_fun命令は、引数が先頭のArity個の引数レジスタに置かれ、fun(クロージャへのポインタ)が最後の引数の次のレジスタx[Arity+1]に置かれていることを前提とします。
つまり、アリティ0の呼び出しではクロージャはx[0]に置かれます。
アリティ1の呼び出しではx[0]に引数が、x[1]にクロージャが入ります。以下同様です。
badarityを送出します。
関数でない値が渡された場合はbadfunを送出します。apply Arity
X registersに格納されたArity個の引数で関数呼び出しをapplyします。
モジュールを表すアトムはx[Arity]に、関数を表すアトムはx[Arity+1]に格納されます。
モジュールはタプルで表現されることもあります。
apply_last Arity Dealloc
CPをポップし、要素を解放してからCPを再びプッシュするという手順で、スタック上のDealloc個の要素を解放します。
続いて、新しい場所へジャンプすることで、X registersに格納されたArity個の引数を使って末尾再帰呼び出しを行います。
モジュールと関数を表すアトムは、それぞれx[Arity]とx[Arity+1]に格納されます。
モジュールはタプルで表現されることもあります。
スタックとヒープの管理
BeamにおけるErlangプロセスのスタックとヒープは同じメモリ領域を共有しています(詳しい説明はプロセスの章とメモリの章を参照してください)。 スタックはアドレスの低い方向へ、ヒープはアドレスの高い方向へ伸びていきます。 スタックかヒープのどちらかで利用可能な量を超える空間が必要になると、Beamはガベージコレクションを行います。
- リーフ関数:他の関数を一切呼び出さない関数のことです。
- 非リーフ関数:他の関数を呼び出す可能性がある関数のことです。
これらの命令は、非リーフ関数が現在のスタックフレームを構築・解体するためにも使われます。 つまり、関数に入るときに継続ポインタ(CP)がスタックに保存され、抜けるときにスタックから読み戻されます。
リーフ関数の骨格は次のようになります。
{function, Name, Arity, StartLabel}.
{label,L1}.
{func_info,{atom,Module},{atom,Name},Arity}.
{label,L2}.
...
return.
非リーフ関数の骨格は次のようになります。
{function, Name, Arity, StartLabel}.
{label,L1}.
{func_info,{atom,Module},{atom,Name},Arity}.
{label,L2}.
{allocate,Need,Live}.
...
call ...
...
{deallocate,Need}.
return.
allocate StackNeed Live
継続ポインタ(CP)を保存し、スタック上にStackNeedワード分の領域を追加で確保します。
確保の途中でメモリが尽きた場合はGCを呼び出し、先頭のLive個のxレジスタがルートセットの一部を構成します。
たとえばLiveが2であれば、GCはレジスタX0とX1を保存し、残りは未使用として解放されます。
スタック上に確保する際は、スタックポインタ(E)が減少します。
allocateの実行例(Allocate 1 0)
Before After
| xxx | | xxx |
E -> | xxx | | xxx |
| | | ??? | caller save slot
... E -> | CP |
... ...
HTOP -> | | HTOP -> | |
| xxx | | xxx |
allocate_heap StackNeed HeapNeed Live
継続ポインタ(CP)を保存し、スタック上にStackNeedワード分の領域を追加で確保します。
さらに、ヒープ上にもHeapNeedワード分の空きがあることを保証します。
確保の途中でメモリが尽きた場合は、保持すべきXレジスタの数をLiveとしてGCを呼び出します。
allocate_zero StackNeed Live
この命令はallocateと同様に動作しますが、確保したスタックスロットをNILでクリアする点が異なります。
allocate_zeroの実行例(allocate_zero 1 0)
Before After
| xxx | | xxx |
E -> | xxx | | xxx |
| | | NIL | caller save slot
... E -> | CP |
... ...
HTOP -> | | HTOP -> | |
| xxx | | xxx |
allocate_heap_zero StackNeed HeapNeed Live
allocate_heap_zero命令はallocate_heap命令と同様に動作しますが、確保したスタックスロットをNILでクリアする点が異なります。
test_heap HeapNeed Live
test_heap命令は、ヒープ上にHeapNeedワード分の空きがあることを保証します。
確保の途中でメモリが尽きた場合は、保持すべきXレジスタの数をLiveとしてGCを呼び出します。
init N
init命令は、CPポインタより上のNワード分のスタックにNILを書き込んでクリアします。
deallocate N
deallocate命令はallocateの逆の操作を行います。
CP(継続ポインタ)を復元し、N+1ワード分のスタックを解放します。
return
return命令は、継続ポインタ(CP)に入っているアドレスへジャンプします。
CPの値はC言語における0にあたる値に設定されます。
trim N Remaining
CPを一時変数へポップし、スタックのNワード分を解放してから、CPをスタックの先頭に戻します。
(引数Remainingは、私が知るかぎり使われていません。)
trimの実行例(Trim 2)
Before After
| ??? | | ??? |
| xxx | E -> | CP |
| xxx | | ... |
E -> | CP | | ... |
| | | ... |
... ...
HTOP -> | | HTOP -> | |
| xxx | | xxx |
データの移動、抽出、書き換え
move Source Destination
移動元Source(リテラルまたはレジスタ)の値を、移動先レジスタDestinationへ移動します。
get_list Source Head Tail
リストセルを分解する操作です。
Sourceで指定されたリスト(consセル)のheadとtail(car部とcdr部)を取り出し、レジスタHeadとTailに格納します。
get_tuple_element Source Element Destination
配列の添字読み出し操作です。
Sourceタプルの位置Elementにある要素を取り出し、レジスタDestinationに格納します。
set_tuple_element NewElement Tuple Position
配列の添字を使った破壊的更新操作です。
TupleのPositionにある要素を、新しい値NewElementで更新します。
項の構築
put_list Head Tail Destination
ヒープ上に新しいリスト(cons)セルを構築し(2ワード)、そのアドレスをレジスタDestinationに格納します。
リストセルの第1要素にはHeadの値が、第2要素にはTailの値が設定されます。
put_tuple Size Destination
ヒープ上に空のタプルを構築し(Size+1ワード)、そのアドレスをレジスタDestinationに格納します。
この時点では要素は設定されません。
put_tuple命令の後には必ず複数のput命令が続き、要素を1つずつ破壊的に設定していきます。
put Value
直前のput_tuple命令で作られたタプルの次の要素へ、Valueを破壊的に格納します。
書き込みアドレスはVM内部で保持・インクリメントされます。
新しいタプルの内容を設定するには、複数のput命令が使われます。
make_fun2 LambdaIndex
モジュールのLambdaテーブル上のインデックスによって定義される関数オブジェクトを生成します。 Lambdaテーブルは、エントリポイント(ラベルまたはexportエントリ)、アリティ、そしてfrozen変数をいくつ取るかを定義します。 frozen変数の値は現在の実行コンテキスト(Xレジスタ)からコピーされ、関数オブジェクトに格納されます。
個々のBEAM命令の詳細な一覧は本翻訳の対象外です。 原文オンライン版(https://blog.stenmans.org/theBeamBook/#AP-Instructions)を参照してください。
個別の命令
引数の型は次のとおりです。
| 型 | 説明 |
|---|---|
| a | 即値のアトム。例: 'foo' |
| c | 即値の定数値(アトム、nil、small int)。Pid?かもしれない |
| d | レジスタまたはスタックスロットのいずれか |
| e | exportテーブルエントリへの参照 |
| f | ラベル、すなわちコードアドレス |
| I | 整数。例: 42 |
| j | 省略可能なコードラベル |
| l | 浮動小数点レジスタ |
| P | 正の(符号なし)整数リテラル |
| r | レジスタR0(x[0]) |
| s | リテラル、レジスタ、スタックスロットのいずれか |
| t | 項。例: [{foo, bar}] |
| x | レジスタ。例: {x, 5}に対する5 |
| y | スタックスロット。例: {y, 1}に対する1 |
すべてのBEAM命令の一覧
| 命令 | 引数 | 説明 |
|---|---|---|
| allocate | t t | スタック上にいくつかのワードを確保する |
| allocate_heap | t I t | ヒープ上にいくつかのワードを確保する |
| allocate_heap_zero | t I t | ヒープを確保し、ワードをNILに設定する |
| allocate_init | t I y | |
| allocate_zero | t t | スタックを確保し、ワードを0に設定する? |
| apply | I | x[Arity]のモジュールとx[Arity+1]の関数に対して、x[0..Arity-1]の引数を適用する |
| apply_last | I P | applyと同様だが、CPを保存せずPワードを解放する |
| badarg | j | badargエラーを生成する |
| badmatch | rxy | badmatchエラーを生成する |
| bif1 | f b s d | 1引数でbifを呼び出し、失敗した場合はfへジャンプする |
| bif1_body | b s d | |
| bs_context_to_binary | rxy | |
| bs_put_string | I I | |
| bs_test_tail_imm2 | f rx I | |
| bs_test_unit | f rx I | |
| bs_test_unit8 | f rx | |
| bs_test_zero_tail2 | f rx | |
| call_bif0 | e | |
| call_bif1 | e | |
| call_bif2 | e | |
| call_bif3 | e | |
| case_end | rxy | case_clauseエラーを生成する |
| catch | y f | |
| catch_end | y | |
| deallocate | I | スタックからいくつかのワードを解放し、CPをポップする |
| deallocate_return | Q | deallocateとreturnを組み合わせる |
| extract_next_element | xy | |
| extract_next_element2 | xy | |
| extract_next_element3 | xy | |
| fclearerror | ||
| fconv | d l | |
| fmove | qdl ld | |
| get_list | rxy rxy rxy | リストセルをheadとtailに分解する |
| i_apply | 引数x2で関数x0:x1のコードを呼び出し、CPを保存する | |
| i_apply_fun | 引数x1で関数オブジェクトx0のコードを呼び出し、CPを保存する | |
| i_apply_fun_last | P | 引数x1で関数オブジェクトx0のコードへジャンプし、CPを復元してP個のスタックセルを解放する |
| i_apply_fun_only | 引数x1で関数オブジェクトx0のコードへジャンプする | |
| i_apply_last | P | 引数x2で関数x0:x1のコードへジャンプする |
| i_apply_only | 引数x2で関数x0:x1のコードへジャンプする | |
| i_band | j I d | |
| i_bif2 | f b d | |
| i_bif2_body | b d | |
| i_bor | j I d | |
| i_bs_add | j I d | |
| i_bs_append | j I I I d | |
| i_bs_get_binary2 | f rx I s I d | |
| i_bs_get_binary_all2 | f rx I I d | |
| i_bs_get_binary_all_reuse | rx f I | |
| i_bs_get_binary_imm2 | f rx I I I d | |
| i_bs_get_float2 | f rx I s I d | |
| i_bs_get_integer | f I I d | |
| i_bs_get_integer_16 | rx f d | |
| i_bs_get_integer_32 | rx f I d | |
| i_bs_get_integer_8 | rx f d | |
| i_bs_get_integer_imm | rx I I f I d | |
| i_bs_get_integer_small_imm | rx I f I d | |
| i_bs_get_utf16 | rx f I d | |
| i_bs_get_utf8 | rx f d | |
| i_bs_init | I I d | |
| i_bs_init_bits | I I d | |
| i_bs_init_bits_fail | rxy j I d | |
| i_bs_init_bits_fail_heap | I j I d | |
| i_bs_init_bits_heap | I I I d | |
| i_bs_init_fail | rxy j I d | |
| i_bs_init_fail_heap | I j I d | |
| i_bs_init_heap | I I I d | |
| i_bs_init_heap_bin | I I d | |
| i_bs_init_heap_bin_heap | I I I d | |
| i_bs_init_writable | ||
| i_bs_match_string | rx f I I | |
| i_bs_private_append | j I d | |
| i_bs_put_utf16 | j I s | |
| i_bs_put_utf8 | j s | |
| i_bs_restore2 | rx I | |
| i_bs_save2 | rx I | |
| i_bs_skip_bits2 | f rx rxy I | |
| i_bs_skip_bits2_imm2 | f rx I | |
| i_bs_skip_bits_all2 | f rx I | |
| i_bs_start_match2 | rxy f I I d | |
| i_bs_utf16_size | s d | |
| i_bs_utf8_size | s d | |
| i_bs_validate_unicode | j s | |
| i_bs_validate_unicode_retract | j | |
| i_bsl | j I d | |
| i_bsr | j I d | |
| i_bxor | j I d | |
| i_call | f | |
| i_call_ext | e | |
| i_call_ext_last | e P | |
| i_call_ext_only | e | |
| i_call_fun | I | |
| i_call_fun_last | I P | |
| i_call_last | f P | |
| i_call_only | f | |
| i_element | rxy j s d | |
| i_fadd | l l l | |
| i_fast_element | rxy j I d | |
| i_fcheckerror | ||
| i_fdiv | l l l | |
| i_fetch | s s | |
| i_fmul | l l l | |
| i_fnegate | l l l | |
| i_fsub | l l l | |
| i_func_info | I a a I | function_clauseエラーを生成する |
| i_gc_bif1 | j I s I d | |
| i_gc_bif2 | j I I d | |
| i_gc_bif3 | j I s I d | |
| i_get | s d | |
| i_get_tuple_element | rxy P rxy | |
| i_hibernate | ||
| i_increment | rxy I I d | |
| i_int_bnot | j s I d | |
| i_int_div | j I d | |
| i_is_eq | f | |
| i_is_eq_exact | f | |
| i_is_eq_exact_immed | f rxy c | |
| i_is_eq_exact_literal | f rxy c | |
| i_is_ge | f | |
| i_is_lt | f | |
| i_is_ne | f | |
| i_is_ne_exact | f | |
| i_is_ne_exact_immed | f rxy c | |
| i_is_ne_exact_literal | f rxy c | |
| i_jump_on_val | rxy f I I | |
| i_jump_on_val_zero | rxy f I | |
| i_loop_rec | f r | |
| i_m_div | j I d | |
| i_make_fun | I t | |
| i_minus | j I d | |
| i_move_call | c r f | |
| i_move_call_ext | c r e | |
| i_move_call_ext_last | e P c r | |
| i_move_call_ext_only | e c r | |
| i_move_call_last | f P c r | |
| i_move_call_only | f c r | |
| i_new_bs_put_binary | j s I s | |
| i_new_bs_put_binary_all | j s I | |
| i_new_bs_put_binary_imm | j I s | |
| i_new_bs_put_float | j s I s | |
| i_new_bs_put_float_imm | j I I s | |
| i_new_bs_put_integer | j s I s | |
| i_new_bs_put_integer_imm | j I I s | |
| i_plus | j I d | |
| i_put_tuple | rxy I | アリティIのタプルを生成し、結果をrxyに格納する。要素は続くput命令で設定する |
| i_recv_set | f | |
| i_rem | j I d | |
| i_select_tuple_arity | r f I | |
| i_select_tuple_arity | x f I | |
| i_select_tuple_arity | y f I | |
| i_select_tuple_arity2 | r f A f A f | |
| i_select_tuple_arity2 | x f A f A f | |
| i_select_tuple_arity2 | y f A f A f | |
| i_select_val | r f I | 値を{Value, Label}のペアのリストと比較し、一致すればジャンプする。一致しなければfへジャンプする |
| i_select_val | x f I | 上と同様だがxレジスタの場合 |
| i_select_val | y f I | 上と同様だがyレジスタの場合 |
| i_select_val2 | r f c f c f | 値を{c1, f1}または{c2, f2}の2つのペアと比較してジャンプする。失敗した場合はfへジャンプする |
| i_select_val2 | x f c f c f | 上と同様だがxレジスタの場合 |
| i_select_val2 | y f c f c f | 上と同様だがyレジスタの場合 |
| i_times | j I d | |
| i_trim | I | スタックをI要素分切り詰め、先頭のCPは保持する |
| i_wait_error | ||
| i_wait_error_locked | ||
| i_wait_timeout | f I | |
| i_wait_timeout | f s | |
| i_wait_timeout_locked | f I | |
| i_wait_timeout_locked | f s | |
| if_end | if_clauseエラーを生成する | |
| init | y | スタック上の1ワードをNIL([])に設定する |
| init2 | y y | スタック上の2ワードをNIL([])に設定する |
| init3 | y y y | スタック上の3ワードをNIL([])に設定する |
| int_code_end | プログラムの終端(スタックなしのreturnと同じ) | |
| is_atom | f rxy | 値がアトムかどうかを調べ、そうでなければジャンプする |
| is_bitstring | f rxy | 値がビット列かどうかを調べ、そうでなければジャンプする |
| is_boolean | f rxy | 値がアトムtrueまたはfalseかどうかを調べ、そうでなければジャンプする |
| is_float | f rxy | 値が浮動小数点数かどうかを調べ、そうでなければジャンプする |
| is_function | f rxy | 値が関数かどうかを調べ、そうでなければジャンプする |
| is_function2 | f s s | 値が関数かどうかを調べ、そうでなければジャンプする |
| is_integer | f rxy | 値がbig integerまたはsmall integerかどうかを調べ、そうでなければジャンプする |
| is_integer_allocate | f rx I I | |
| is_list | f rxy | 値がリストまたはNILかどうかを調べ、そうでなければジャンプする |
| is_nil | f rxy | 値が空リスト[]かどうかを調べ、そうでなければジャンプする |
| is_nonempty_list | f rxy | 値が空でないリスト(consポインタ)かどうかを調べ、そうでなければジャンプする |
| is_nonempty_list_allocate | f rx I t | |
| is_nonempty_list_test_heap | f r I t | |
| is_number | f rxy | 値がbig integer、small integer、floatのいずれかかどうかを調べ、そうでなければジャンプする |
| is_pid | f rxy | 値がpidかどうかを調べ、そうでなければジャンプする |
| is_port | f rxy | 値がportかどうかを調べ、そうでなければジャンプする |
| is_reference | f rxy | 値がreferenceかどうかを調べ、そうでなければジャンプする |
| is_tuple | f rxy | 値がタプルかどうかを調べ、そうでなければジャンプする |
| is_tuple_of_arity | f rxy A | 値がアリティAのタプルかどうかを調べ、そうでなければジャンプする |
| jump | f | 位置(ラベル)fへジャンプする |
| label | L | コード中の位置を示すマーカーで、ロード時に取り除かれる |
| line | I | ソースファイル中の位置を示すマーカーで、ロード時に取り除かれる |
| loop_rec_end | f | プロセスのreceiveポインタを進め、loop_rec命令へジャンプする |
| move | rxync rxy | 値またはレジスタを別のレジスタへ移動する |
| move2 | x x x x | 値のペアを移動先のペアへ移動する |
| move2 | x y x y | 値のペアを移動先のペアへ移動する |
| move2 | y x y x | 値のペアを移動先のペアへ移動する |
| move_call | xy r f | |
| move_call_last | xy r f Q | |
| move_call_only | x r f | |
| move_deallocate_return | xycn r Q | |
| move_jump | f ncxy | |
| move_return | xcn r | |
| move_x1 | c | 値をx1に格納する |
| move_x2 | c | 値をx2に格納する |
| node | rxy | rxyを現在のノード名を表すアトムにする |
| put | rxy | この命令の並びはi_put_tupleの後に置かれ、タプルの要素を(0番目から)初期化するために使われる |
| put_list | s s d | headとtailからリストセルを構築し、consポインタを移動先dに格納する |
| raise | s s | 指定した型の例外を送出する。互換性維持の都合上、例外の型は第2引数のスタックトレースから取り出す必要がある |
| recv_mark | f | メッセージ取得の再開位置として既知の位置に印を付ける(参照の最適化) |
| remove_message | プロセスのinboxから現在のメッセージを取り除く(受信済みとする) | |
| return | CPにあるアドレスへジャンプし、CPを0に設定する | |
| self | rxy | rxyを現在のプロセスのpidに設定する |
| send | メッセージx1をプロセスx0のinboxへ送信する。プロセスが存在しなくてもエラーにはならない | |
| set_tuple_element | s d P | 添字を使ってタプルの要素を破壊的に更新する |
| system_limit | j | |
| test_arity | f rxy A | rxyにある関数オブジェクト(クロージャまたはexport)がアリティAかどうかを調べ、そうでなければfへジャンプする |
| test_heap | I t | ヒープの空き容量を確認する |
| test_heap_1_put_list | I y | |
| timeout | タイマーを設定し、メッセージの到着かタイマーイベントのどちらか早い方を待ってプロセスの実行を明け渡す | |
| timeout_locked | ||
| try | y f | スタックセルyに特別なcatch値を書き込み、tryブロックが有効であることを示す。例外が発生するとVMはラベルfへジャンプする。これ以降実行されるコードは例外から保護される |
| try_case | y | try_endと同様に保護区間の終わりを示し、スタック上のcatch値をクリアして例外マッチングのコード区間を開始する |
| try_case_end | s | |
| try_end | y | スタックセルyからcatch値をクリアし、保護区間の終わりを示す |
| wait | f | メッセージの到着を待ってプロセスをスケジュールアウトする(明け渡す) |
| wait_locked | f | |
| wait_unlocked | f |