コンテンツにスキップ

Udon の実行モデル

Udon の命令は 9 種類で、値を計算するのは EXTERN だけです(a + b も足し算の関数を名前で呼びます)。

命令何をするか
NOP何もしない
PUSHヒープアドレスをスタックに積む
POPスタックの先頭を捨てる
JUMP_IF_FALSE積んだアドレスの値が false なら、指定の位置へ跳ぶ
JUMP指定の位置へ跳ぶ
EXTERN外部の関数を 1 本呼ぶ
ANNOTATION何もしない(引数を 1 つ取る)
JUMP_INDIRECT積んだアドレスの値を飛び先にして跳ぶ
COPYスタックが指す 2 つのアドレスのあいだで値を写す

呼べるのは Udon が公開している一覧にあるものだけで、C# の側にあるメソッドでも、一覧に無ければ TUKI0101、型なら TUKI0102 のエラーになります(エラー)。

呼び出し先とジャンプ先の決定

Section titled “呼び出し先とジャンプ先の決定”

呼ぶ関数の名前はシグネチャの文字列として命令列に書き込まれ、飛び先を実行時に決められる命令は JUMP_INDIRECT だけです(コンパイラはこれをメソッドからの return に使います)。

書き方理由出る番号
関数を値として扱う構文呼ぶ先は命令の側に書いてあり、実行時に差し替えられませんデリゲートとラムダが TUKI0108
少しずつ値を返す構文1 回の実行はエントリポイントから終わりまで通しで進みますyield が TUKI0001
実行時に名前でメンバを解決する構文呼ぶ先の名前はコンパイルの時に決まりますdynamic が TUKI0102
格納先ヒープと呼ぶ 1 本の配列だけです
ローカル変数の領域ありません。値はすべてヒープ変数に格納されます
ヒープ変数の型と数1 つずつ型を持ち、数はコンパイルの時に決まります。実行中に増やす手段はありません
配列要素をいくつ持っていても 1 つのヒープ変数に載ります。長さは実行時に決めた値でかまいませんが、作ったあとで変える書き方はありません(配列)
単位1 つのファイルが 1 つのプログラム。中の具象の Behaviour が本体です(2 つ目を同じファイルに書くと TUKI0109。ファイル構成と名前空間)
始まる場所main はありません。実行環境が呼ぶイベントと、名前で呼ばれるメソッドです(イベント)
Main という名前書けますが、実行環境は呼びません
using UnityEngine;
using Tsukimi;
public class BcMain : TsukimiBehaviour
{
void Start()
{
Debug.Log(1); // => 1
}
public static void Main() { }
}

エントリポイントからたどれないコード

Section titled “エントリポイントからたどれないコード”
命令になるものエントリポイントからの呼び出しをたどって到達したメソッドだけ
エントリポイントイベントと、public を付けたメソッド
命令にならないものpublic が付いておらず、どこからも呼ばれないメソッド。ヒープ変数も使いません
それでも受ける検査対応している構文かどうかは見ます。呼び忘れたメソッドの中に非対応の構文があれば、そこでエラーになります

上限は 3 つあり、どれもコンパイル時のエラーになります。

上限数えるもの診断
ヒープ変数 1,048,576 個struct を展開したフィールドと、各メソッドの引数とローカル変数(struct を使うプログラムだけ数えます)TUKI0104
具体化した組 256ジェネリックを具体化した組の総数TUKI0105
入れ子 8 段型引数の入れ子の深さTUKI0105

TUKI0105 の 2 つは TUKI0104 より先に実行されます。

上限決めているもの
ヒープ変数 1,048,576 個実行環境がヒープに許す最大の数です
大きさを指定しないヒープ 512 個アセンブラにヒープサイズを指定しなかった場合の既定値です。上限ではなく、この言語のプログラムは必要な大きさを渡して組むので、512 個を超えるプログラムもそのまま動作します
ジェネリックの 2 つコンパイラが増殖を防ぐために置いている数です。実行環境の側の制限ではありません
消費するもの数え方
フィールド宣言した数だけ使います。struct は中身を並べた形になるので、メンバの数だけ使います
メソッドの引数とローカル変数実行環境にローカル変数の領域が無いので、メソッドの中で宣言した変数もここに格納されます
定数と計算の途中の値ソースに書いていない値も、コンパイルの過程で格納先が必要です
外部の関数のシグネチャ文字列呼ぶ関数の種類ごとに 1 つ使います。同じ関数を何度呼んでも増えませんが、種類が増えるとそのぶん変数の枠が減ります

TUKI0104 が数えるのはフィールドと引数とローカル変数だけで、組み立てのときに実際に必要な数には、 定数と計算の途中の値、それにシグネチャの文字列が加わります。この数は見積もりです。

実行環境に例外の仕組みが無いので、throw も try / catch もエラーになります (文と制御構文)。

using UnityEngine;
using Tsukimi;
public class ExCatchTypeless : TsukimiBehaviour
{
void Start()
{
try { Debug.Log(1); } catch { Debug.Log(2); }
}
}

失敗しうる操作は、呼ぶ前に条件を調べる形でしか書けません(checked が非対応なのも同じ理由です)。

操作起きること例のある場所
整数のゼロ除算実行が停止します。小数を 0 で割ったときは Infinity になります数値のあふれと変換
範囲の外へ出る数値の変換実行が停止します。変換する外部の関数が範囲を検査しています数値のあふれと変換
null の参照のメンバの呼び出し実行が停止し、実行環境がエラーを出しますnull と参照

停止するとそのイベントの残りは実行されず、ログには、停止したことと、失敗した外部の関数の シグネチャが出ます。そのプログラムが以後どのイベントにも反応しなくなることがあり、 復帰する手段はありません(オブジェクトを再生成するか、再配置することになります)。