rontolisp:with-arena
(rontolisp:with-arena () body...)
ボディを実行してその値を返し、非 GC WASM バックエンド
(--no-gc)
のメモリ再利用境界を名付けます。このバックエンドでは 1 回のエクスポート呼び出しの中では
何も解放されません — バンプアロケータはエクスポート境界でしかポップしない — ため、
毎イテレーション確保するループ(文字列構築、新しい vec: ベクタ)は線形メモリを成長させます。
with-arena はそのギャップを埋めます: バンプヒープポインタをスナップショットし、ボディを
実行し、ボディが確保したすべてをポップします。残るのはボディ自身の値だけです(文字列や
packed float 配列の結果はスナップショット位置へコピーダウンされます)。インタプリタ、JVM
バックエンド、デフォルト(wasm-GC)出力では実際のガベージコレクタが回収するため、観測上は
単なる progn であり、同じソースがすべてのバックエンドで動きます。
引数
- オプションリスト。現在は空(
())でなければなりません。将来のオプションのために予約 されています。 - ボディフォーム。
prognと同様に順に評価されます。最後のフォームの値が式全体の値です (ボディが空ならnil)。
エスケープ契約(--no-gc)
ボディ内で確保されたものは、ボディ自身の値を除いて、ボディの後から到達可能で
あってはなりません。内部の確保値をアリーナより長生きする場所(たとえば外側で作った配列)
に格納すると、アリーナのポップ後にダングリングポインタになります — ホスト側の
__ronto_alloc_reset
(メモリの再利用)
と同じ規則です。
典型的な使い方 — --no-gc でホットループをフラットに保つ:
制限
- オプションリストは空でなければなりません。空でないオプションリストはエラーです。
--no-gcでは、アリーナ境界を越えて脱出するreturnはポップをスキップします (内部の確保が回収されないだけで、破壊は起きません)。- マクロは関数値を持ちません:
#'rontolisp:with-arenaはエラーです。