<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8716539354830932074</id><updated>2012-02-24T12:32:57.844+09:00</updated><title type='text'>PyPy Status Blog JA</title><subtitle type='html'>&lt;a href="http://morepypy.blogspot.com/"&gt;PyPy Status Blog&lt;/a&gt;の日本語翻訳ブログ。</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-8067288438739406804</id><published>2012-02-24T12:31:00.002+09:00</published><updated>2012-02-24T12:32:57.886+09:00</updated><title type='text'>より大きなフローグラフ言語の例</title><content type='html'>より大きなフローグラフ言語の例&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;トレーシングと部分評価の比較 Part4&lt;/h2&gt;&lt;br /&gt;このエントリは部分評価とトレーシングの比較シリーズの四つ目、そして最後のエントリです。&lt;br /&gt;長い道のりを歩んでいます。&lt;br /&gt;&lt;a href="http://morepypy-ja.blogspot.com/2012/01/part-1.html"&gt;シリーズの最初&lt;/a&gt;では小さなフローグラフ言語のインタプリタとその部分評価器をお見せしました。&lt;br /&gt;&lt;a href="http://morepypy-ja.blogspot.com/2012/02/flowgraph.html"&gt;二つ目&lt;/a&gt;では同じ言語にトレーサがどのように動作するかと、部分評価とどのように関係するかについてお見せしました。&lt;br /&gt;&lt;a href="http://morepypy-ja.blogspot.com/2012/02/flowgraph_09.html"&gt;三つ目&lt;/a&gt;ではトレースのためのオプティマイザについて説明しました。&lt;br /&gt;この最後のエントリでは、トレーシングと部分評価の二つの別々のアプローチの例を挙げ、その意味から比較と対比します。&lt;br /&gt;フローチャート言語のプログラムは、これまで見てきたものはかなり小さいのですが、今回は大きなプログラムの例で示したいと思います。それは非常に単純なバイトコードセットのインタプリタです。&lt;br /&gt;部分評価器がインタプリタにどのような処理を行うかを見ていきます。そして、トレーサが同様に何を行うかも見ていきます。&lt;br /&gt;このシリーズで使われている全てのコードはこちらにあります: &lt;a href="http://paste.pocoo.org/show/550282/"&gt;http://paste.pocoo.org/show/550282/&lt;/a&gt; (トレースをプリントするよりよい方法などのいくつかの小さなプログラムを追加しています。)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;バイトコードインタプリタ&lt;/h2&gt;&lt;br /&gt;フローグラフ言語でプログラムを記述することは痛みを伴いますが、今まで見てきた小さなものよりもう少し興味深い例を与えるためにまだ書かなければいけません。例は、非常に簡単なレジスタマシンのバイトコードインタプリタで、その一つであるアキュムレータは実際に全ての操作が実行されます。&lt;br /&gt;&lt;br /&gt;この言語のオペコードは;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;jump_if_a&lt;/tt&gt;: アキュムレータが非ゼロの場合、ターゲットアドレスにジャンプします&lt;br /&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;mov_a_r0&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;mov_a_r1&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;mov_a_r2&lt;/tt&gt;: アキュムレータの値をそれぞれのレジスタに移します&lt;br /&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;mov_r0_a&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;mov_r1_a&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;mov_r2_a&lt;/tt&gt;: レジスタの値をアキュムレータに移します&lt;br /&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;add_r0_to_a&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;add_r1_to_a&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;add_r2_to_a&lt;/tt&gt;: レジスタの値をアキュムレータに加算します&lt;br /&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;decr_a&lt;/tt&gt;: アキュムレータの値をデクリメントします&lt;br /&gt;&lt;li&gt;&lt;tt class="docutils literal"&gt;return_a&lt;/tt&gt;: アキュムレータの値をプリントしてプログラムを終了します&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;インタプリタは現在のプログラムカウンタの一にあるオペコードを読み、if 文までの一連の(長い)バイトコードをディスパッチし正しいオペコードを行するメインループを持ちます。&lt;br /&gt;その後、次のオペコードに対しても同様の処理を行います。&lt;br /&gt;&lt;br /&gt;擬似コードとしてのフローグラフ言語のソースコードの一部です:&lt;br /&gt;&lt;pre class="literal-block"&gt;bytecode_loop:&lt;br /&gt;    opcode = bytecode[pc]&lt;br /&gt;    pc = pc + 1&lt;br /&gt;    c = opcode == 'jump_if_a'&lt;br /&gt;    if c goto op_jump_if_a else goto not_jump_if_a&lt;br /&gt;&lt;br /&gt;# select the right bytecode via a long series of if statements&lt;br /&gt;not_jump_if_a:&lt;br /&gt;    c = opcode == 'mov_a_r0'&lt;br /&gt;    if y goto op_mov_a_r0 else goto not_mov_a_r0&lt;br /&gt;not_mov_a_r0:&lt;br /&gt;    c = opcode == 'mov_a_r0'&lt;br /&gt;    if y goto op_mov_a_r1 else goto not_mov_a_r1&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;# bytecode implementations&lt;br /&gt;op_mov_a_r0:&lt;br /&gt;    r0 = a&lt;br /&gt;    goto bytecode_loop&lt;br /&gt;&lt;br /&gt;op_jump_if_a:&lt;br /&gt;    c = a == 0&lt;br /&gt;    target = bytecode[pc]&lt;br /&gt;    pc += 1&lt;br /&gt;    if c goto bytecode_loop else goto op_jump_if_a_jump&lt;br /&gt;&lt;br /&gt;op_jump_if_a_jump:&lt;br /&gt;    pc = target&lt;br /&gt;    goto bytecode_loop&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;そして実際に Prolog の fact として動きます。(完全な実装は上記リンクを辿ると見つけられます):&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #0099FF; font-style: italic"&gt;% bytecode dispatch loop&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;op_jump_if_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;not_jump_if_a&lt;/span&gt;))))).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0099FF; font-style: italic"&gt;% select the right bytecode via a long series of if statements&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_jump_if_a&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;op_mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;not_mov_a_r0&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_a_r0&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;op_mov_a_r1&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;not_mov_a_r1&lt;/span&gt;))).&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0099FF; font-style: italic"&gt;% bytecode implementations&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;op_jump_if_a&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;target&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;op_jump_if_a_jump&lt;/span&gt;))))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;op_jump_if_a_jump&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;target&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;promote&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;op_mov_a_r0&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;))).&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;tt class="docutils literal"&gt;bytecode_loop&lt;/tt&gt; ブロックはメインのディスパッチループです。&lt;br /&gt;バイトコードリストからプログラムカウンタの一にあるオペコードを読み出し、&lt;br /&gt;現在のオペコードを様々な既存のオペコードと比較する長い一連の if 文を持ちます。&lt;br /&gt;インタプリタの完全なコードは上のリンクを辿るとあります。&lt;br /&gt;&lt;br /&gt;インタプリタのバイトコードは実際には非常に複雑なプログラムを許可しませんが、以下のように数値を二乗するプログラムを書くことに使えます:&lt;br /&gt;&lt;pre class="literal-block"&gt;mov_a_r0     # r0 = a&lt;br /&gt;mov_a_r1     # r1 = a&lt;br /&gt;# 2:&lt;br /&gt;mov_r0_a     # r0--&lt;br /&gt;decr_a&lt;br /&gt;mov_a_r0&lt;br /&gt;mov_r2_a     # r2 += a&lt;br /&gt;add_r1_to_a&lt;br /&gt;mov_a_r2&lt;br /&gt;mov_r0_a     # if r0!=0: goto 2&lt;br /&gt;jump_if_a 2&lt;br /&gt;mov_r2_a     # return r2&lt;br /&gt;return_a&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;バイトコードインタプリタの部分的な評価&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;最初のエントリの部分評価器は、簡単にバイトコードインタプリタを部分評価できます。&lt;br /&gt;静的な入力は、上記のように二乗の計算を行うバイトコードとプログラムカウンタの初期値です。&lt;br /&gt;動的な入力はアキュムレータの内容(二乗する値)です。これは次のように行えます:&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;bytecode_square&lt;/span&gt;(&lt;span style="color: #003333"&gt;B&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #003333"&gt;Env&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; [&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;B&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;],&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;do_pe&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Label&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #003333"&gt;REnv&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; [&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;],&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;Label&lt;/span&gt;), &lt;span style="color: #003333"&gt;REnv&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;listing&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;block&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #FF6600"&gt;256&lt;/span&gt;&lt;br /&gt;:- &lt;span style="color: #CC3300"&gt;dynamic&lt;/span&gt; &lt;span style="color: #CC3300"&gt;block&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #555555"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #CC3300"&gt;lots&lt;/span&gt; &lt;span style="color: #CC3300"&gt;of&lt;/span&gt; &lt;span style="color: #CC3300"&gt;generated&lt;/span&gt; &lt;span style="color: #CC3300"&gt;code&lt;/span&gt;&lt;span style="color: #555555"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;部分評価器が処理した結果生成されたコードは若干読みづらいです。&lt;br /&gt;以下のように様々なパスを含んでいるためです:&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;...&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;op_return_a1&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_decr_a1&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;op_return_a1&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_add_r2_to_a2&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_decr_a1&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_add_r1_to_a2&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_add_r2_to_a2&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_add_r0_to_a3&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_add_r1_to_a2&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_r2_a3&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_add_r0_to_a3&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_r1_a5&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_r2_a3&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_r0_a5&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_r1_a5&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_a_r27&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_r0_a5&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_a_r18&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_a_r27&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_a_r09&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_a_r18&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_jump_if_a11&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_mov_a_r09&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop12&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;not_jump_if_a11&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;op_mov_r2_a2&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop12&lt;/span&gt;))).&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;すなわち、何もせずに別のブロックにジャンプするブロックが沢山あるということです。&lt;br /&gt;散在するいくつかのブロックは実際のオペレーションを含んでいます。&lt;br /&gt;手動で出力されたコードを綺麗にし、以下のようなものができあがりました。&lt;br /&gt;(このクリーンアップの手順は、良い部分評価システムであれば部分評価の後に評価器自身が行うでしょう):&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop1&lt;/span&gt;,&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;bytecode_loop11&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;op_jump_if_a_jump1&lt;/span&gt;)))))))))))).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop11&lt;/span&gt;,&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;))).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;op_jump_if_a_jump1&lt;/span&gt;,&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;bytecode_loop11&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;op_jump_if_a_jump1&lt;/span&gt;)))))))))).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;このコードから何が見えてくるのでしょうか?&lt;br /&gt;部分評価器は 最初のオペコード &lt;tt class="docutils literal"&gt;mov_a_r0&lt;/tt&gt; と &lt;tt class="docutils literal"&gt;mov_a_r1&lt;/tt&gt; に対応する &lt;tt class="docutils literal"&gt;bytecode_loop1&lt;/tt&gt; ブロックを生成し、一回のループの反復で一緒に処理されます。&lt;br /&gt;そして、メインループのコピー(&lt;tt class="docutils literal"&gt;op_jump_if_a_jump1&lt;/tt&gt; ラベル)か、結果を出力して停止する &lt;tt class="docutils literal"&gt;bytecode_loop1&lt;/tt&gt; へとジャンプします。&lt;br /&gt;バイトコードを処理した結果の残留コードを実行します:&lt;br /&gt;アキュムレータの値を二乗し、出力します。&lt;br /&gt;使われる全てのバイトコードとプログラムカウンタはなくなります。&lt;br /&gt;&lt;br /&gt;何故部分評価器は同じように見えるメインループの二つのコピーを生成したのでしょうか?&lt;br /&gt;その理由は二つ目のコピーにある追加の静的情報 &lt;tt class="docutils literal"&gt;target = 2&lt;/tt&gt; がわかったためです。&lt;br /&gt;&lt;tt class="docutils literal"&gt;target&lt;/tt&gt;  はインタプリタのソースにあるジャンプ先を指定する変数ですが、この処理の間はとても簡単です。&lt;br /&gt;この追加の静的情報は残留コードに何の影響も及ぼしませんが、同じコードが無駄に生成されます。&lt;br /&gt;これは、過剰な特殊化の例です。&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;インタプリタをトレースする&lt;/h2&gt;&lt;br /&gt;このセクションでは、インタプリタのトレースを試みたときに何が起こるかをお見せします。&lt;br /&gt;一回の反復で停止してしまうため、トレースを生成する自然な方法有用ではありません。&lt;br /&gt;この問題を回避する方法に注目しました。&lt;br /&gt;このセクションで説明している問題は、&lt;a href="https://bitbucket.org/pypy/extradoc/src/tip/talk/icooolps2009/bolz-tracing-jit-final.pdf"&gt;Tracing the meta-level: PyPy's tracing JIT compiler&lt;/a&gt;というペーパーのコアとなっています(ペーパー中では例より少し高度なバイトコードインタプリタを使っています)。&lt;br /&gt;&lt;br /&gt;インタプリタのトレースするために &lt;tt class="docutils literal"&gt;bytecode&lt;/tt&gt; と &lt;tt class="docutils literal"&gt;pc&lt;/tt&gt; の二つの変数を常にプロモートすることは、上記のコードから &lt;tt class="docutils literal"&gt;bytecode_loop&lt;/tt&gt; ブロックを置き換えるのに有用です。&lt;br /&gt;それらを知らずにトレースを生成することはあまり意味がなく、面白みもありません。&lt;br /&gt;これは、上記の部分評価の例で静的にそれらの変数を作ることと似ています:&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;promote&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;bytecode_loop_promote_bytecode&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_bytecode&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;promote&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;bytecode_loop_promote_pc&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_pc&lt;/span&gt;,&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;      &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;op_jump_if_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;not_jump_if_a&lt;/span&gt;))))).&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;インタプリタの残りの部分は変更していません。&lt;br /&gt;&lt;br /&gt; インタプリタのトレースするために、 単純な &lt;tt class="docutils literal"&gt;bytecode_loop&lt;/tt&gt; ラベルから開始します。&lt;br /&gt; インタプリタ中の &lt;tt class="docutils literal"&gt;bytecode_loop&lt;/tt&gt; ラベルは一番高い頻度で飛び先として使われるためです。 (プロファイラは簡単に確立する可能性があります):&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;bytecode_square&lt;/span&gt;(&lt;span style="color: #003333"&gt;B&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;A&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; [&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;B&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;a&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;A&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;A&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;A&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;],&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_trace&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC3300"&gt;trace&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;],[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_bytecode&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_pc&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;op_jump_if_a&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;op_mov_a_r0&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;op_mov_a_r1&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;op_mov_a_r2&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;not_mov_r0_a&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC3300"&gt;opttrace&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;],[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_bytecode&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;]],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_pc&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;([&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;]))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #FF6600"&gt;256&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #003333"&gt;B&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; [&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;|...],&lt;br /&gt;&lt;span style="color: #003333"&gt;A&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;16&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: #003333"&gt;Env&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; [&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;|...], &lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;a&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;]&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;生成されたこれらのトレースはとても短いです。&lt;br /&gt;&lt;tt class="docutils literal"&gt;bytecode&lt;/tt&gt; と &lt;tt class="docutils literal"&gt;pc&lt;/tt&gt; のプロモートとともに開始し、続いてバイトコードの 2 番目に位置する命令であるオペコード &lt;tt class="docutils literal"&gt;mov_r0_a&lt;/tt&gt; を実行します。&lt;br /&gt;そして &lt;tt class="docutils literal"&gt;pc&lt;/tt&gt; をインクリメントし、ループの開始に戻ります。&lt;br /&gt;最適化されたトレースを見ると、本質的に役に立たないことは明らかです。&lt;br /&gt;それらは一回の反復でのみ実行されます。二回目の反復では &lt;tt class="docutils literal"&gt;pc&lt;/tt&gt; は 3 になり、 &lt;tt class="docutils literal"&gt;guard_value&lt;/tt&gt; が冒頭で失敗してしまうためです。&lt;br /&gt;&lt;br /&gt;この問題はバイトコードディスパッチループのトレースを一回以上行うことで解決できます。&lt;br /&gt;この手法はメタトレーシングと呼ばれます。&lt;br /&gt;この挙動を得るために、このシンプルな例では、開始するのに十分な (かつ終了する) トレースを別のラベル &lt;tt class="docutils literal"&gt;op_jump_if_a_jump&lt;/tt&gt; で行っています。&lt;br /&gt;このラベルは、インタプリタが &lt;tt class="docutils literal"&gt;jump_if_a&lt;/tt&gt; バイトコードを実行し、ジャンプしたときにヒットします。&lt;br /&gt;実行されたバイトコードプログラム上のレベルのループでは、一つのジャンプにすぎません。&lt;br /&gt;従って、このラベルからトレースすることでバイトコード上の全てのループがトレースされます。&lt;br /&gt;全てのループとは、制御フロー言語のバイトコードディスパッチループに潜在的に含まれる多くの反復です。&lt;br /&gt;&lt;br /&gt;生成結果は以下のとおりです:&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;bytecode_square&lt;/span&gt;(&lt;span style="color: #003333"&gt;B&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;A&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; [&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;B&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;11&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;a&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;A&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;A&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;A&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;target&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;],&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_trace&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;op_jump_if_a_jump&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC3300"&gt;trace&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;target&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;],[],&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;],[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_bytecode&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_pc&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;op_jump_if_a&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;op_mov_a_r0&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;op_mov_a_r1&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;op_mov_a_r2&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;not_mov_r0_a&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;],[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_bytecode&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_pc&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;))&lt;br /&gt;  ...&lt;br /&gt;  &lt;span style="color: #CC3300"&gt;lots&lt;/span&gt; &lt;span style="color: #CC3300"&gt;of&lt;/span&gt; &lt;span style="color: #CC3300"&gt;operations&lt;/span&gt; &lt;span style="color: #CC3300"&gt;ommitted&lt;/span&gt;&lt;br /&gt;  ...&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;],[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_bytecode&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;9&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_pc&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;not_jump_if_a&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;target&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC3300"&gt;opttrace&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;target&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;],[],&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;]],&lt;span style="color: #CC3300"&gt;bytecode_loop_promote_pc&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;a&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;],&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;11&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;target&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;],&lt;span style="color: #CC3300"&gt;bytecode_loop&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;([&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;return_a&lt;/span&gt;]))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;11&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opcode&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;jump_if_a&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;target&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;))&lt;br /&gt;  &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #FF6600"&gt;256&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #003333"&gt;B&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; [&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;|...],&lt;br /&gt;&lt;span style="color: #003333"&gt;A&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;16&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: #003333"&gt;Env&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; [&lt;span style="color: #CC3300"&gt;bytecode&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;[&lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r1&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r0_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;decr_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_a_r0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mov_r2_a&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add_r1_to_a&lt;/span&gt;|...], &lt;span style="color: #CC3300"&gt;pc&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;11&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;a&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r0&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r1&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;16&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;r2&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;target&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;] .&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;よくなったように見えます。&lt;br /&gt;トレースはインタプリタで実行する、上記例で示した二乗関数のループの中の全てのバイトコードに対応します。&lt;br /&gt;最適化されたコードは二つの(&lt;tt class="docutils literal"&gt;bytecode&lt;/tt&gt; がまだ二乗関数のなかの一つであるかと、 &lt;tt class="docutils literal"&gt;pc&lt;/tt&gt; が 2 であるかどうかをチェックする)ガードから始まります。そして、実際に計算するオペレーションのみ行います。&lt;br /&gt;バイトコードディスパッチは行われず、従ってインタプリタ実行のオーバヘッドは全て取り除かれます。二つの &lt;tt class="docutils literal"&gt;guard_value&lt;/tt&gt; オペレーションから離れて開始されます。&lt;br /&gt;&lt;br /&gt;トレースの中のたくさんの割り当ては不要です。&lt;br /&gt;例えば &lt;tt class="docutils literal"&gt;r0&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;r1&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;r2&lt;/tt&gt; レジスタと加算器 &lt;tt class="docutils literal"&gt;a&lt;/tt&gt; 間のコピーなどです。&lt;br /&gt;これらは SSA 形式を利用したより賢い最適化を用いることで簡単に解決できます。&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;インタプリタに関する結論&lt;/h2&gt;&lt;br /&gt;部分評価とメタトレーシングのどちらも例で用いた二乗を計算するバイトコードをインタプリタオーバヘッドのない、本質的なな計算でお見せした形式に変換する際に使われます。&lt;br /&gt;素直な部分評価器はジャンプを行うだけのような沢山の追加のブロック生成しますが、後処理工程で解決可能です。&lt;br /&gt;トレーサそのものは無駄に短いトレースを生成しますが、別の地点からトレースを開始する簡単なトリックを施すことでかなり良くなります。&lt;br /&gt;&lt;br /&gt;実際のメタとレーシングシステムでは、メタトレーサはインタプリタの作者のために、どのバイトコードがバックエンドのジャンプに対応するかをマークするためのの方法が必要になります。&lt;br /&gt;また、トレースをキャッシュするだけでなく自動的にトレースが開始されるように良く統合されている必要があります。&lt;br /&gt;加えて、よく失敗するガード対処するしたり、失敗したガードに新しいトレースを接続する必要があります。&lt;br /&gt;ただし、それらの全てはこの一連のプログエントリで発表した机上の空論に過ぎません。&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;高度な結論&lt;/h2&gt;&lt;br /&gt;トレーシングと部分評価の類似点に関するいくつかの高レベルな結論:トレーシングと部分評価は、自動的にインタプリタのオーバヘッドを減らすという似た問題に対処しようとしました。これらのアプローチはわずかに異なります。&lt;br /&gt;&lt;br /&gt;トレーシングはいくつかの追加の情報をプロセスに保持するのみで、通常の評価機構にとても近いです。&lt;br /&gt;しかし、トレーサの中で使われるオプティマイザは部分評価器ととても似た構造をとっています。&lt;br /&gt;オプティマイザの仕事は、とても単純でオペレーションを線形リストにするのみです。制御フロー全てに対処する必要はありません。&lt;br /&gt;&lt;br /&gt;トレーシングの検出は部分評価器の一部を利用し、 (「それらの中の評価できるものを評価するのみで、それ以外は残す」ということです)、部分評価されなかった(展開を制御する)パーツをより実用的なメカニズムによって置き換えます。&lt;br /&gt;そのメカニズムは、実際のプログラムで実行される典型的な制御フローパスの選択を観測します。&lt;br /&gt;同時に、トレーサの焦点はループに当たっています。&lt;br /&gt;それらはプログラムの実行時間の殆どを占めているためです。&lt;br /&gt;&lt;br /&gt;トレーシングの別の視点では、どのパスを見ているかの情報を提供する神託(実際に実行されたプログラム)によって部分評価器の制御コンポーネントを置き換えます。&lt;br /&gt;&lt;br /&gt;&lt;!-- "部分評価の形式" が抜けた --&gt;&lt;br /&gt;&lt;br /&gt;ここ示したような非常に簡単なインタプリタでは既に効果が現れています。&lt;br /&gt;単純な部分評価器は二つの全く同じループを生成するなどの過剰な特殊化を行います。&lt;br /&gt;トレーサはそのような挙動をせず、初期化するオペコードではないループ自体のコードだけを生成します。&lt;br /&gt;&lt;br /&gt;このシリーズでは、以上のようなものを作りました。お付き合いありがとうございます。&lt;br /&gt;また、ここにこれらのPostをする前に一貫して良いフィードバックをくれた Samuele と Sven に感謝を示します。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-8067288438739406804?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/8067288438739406804/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2012/02/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/8067288438739406804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/8067288438739406804'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2012/02/blog-post.html' title='より大きなフローグラフ言語の例'/><author><name>shoma</name><uri>http://www.blogger.com/profile/17043127701763147055</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-8568035274688043294</id><published>2012-02-09T15:36:00.001+09:00</published><updated>2012-02-09T15:51:52.838+09:00</updated><title type='text'>FlowGraph 言語のトレースの最適化</title><content type='html'>原文は&lt;a href="http://morepypy.blogspot.com/2012/02/optimizing-traces-of-flow-graph.html"&gt;こちら&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;トレーシングと部分評価の比較 Part3&lt;/h2&gt;&lt;br /&gt;これは部分評価とトレーシングを比較するシリーズの三つ目のエントリです。&lt;a href="http://morepypy-ja.blogspot.com/2012/01/part-1.html"&gt;最初のエントリ&lt;/a&gt;では、小さ FlowGraph 言語をインタプリタとともに紹介し、FlowGraph 言語の部分評価器をお見せしました。&lt;a href="http://morepypy-ja.blogspot.com/2012/02/flowgraph.html"&gt;二つ目のエントリ&lt;/a&gt;では、トレーサが同じ言語にどのように働くかと、部分評価とトレーサの二つの実行がどのように関係するのかをお見せしまし、プロモーションの機能をトレーサに追加しました。&lt;br /&gt;このエントリでは、トレーサによって生成されたトレースをどのように最適化するかをお見せし、部分評価のオプティマイザの構造とトレーサのオプティマイザの構造を比較します。&lt;br /&gt;このエントリで使われているソースコードはここにあります: &lt;a href="http://paste.pocoo.org/show/547304/"&gt;http://paste.pocoo.org/show/547304/&lt;/a&gt;&lt;br /&gt;&lt;h2&gt;トレースの最適化&lt;/h2&gt;&lt;br /&gt;前回のエントリで、どのようにスペシャルモードでの制御フローグラフプログラムの実行によるガードとともに線形化したトレースを生成するかを見ました。トレースはいつも &lt;span style="font-style:italic;"&gt;loop&lt;/span&gt; 文で終わり、開始地点にジャンプします。トレーサはインタプリタが実行したオペレーションのログを取るだけなので、出力されるトレースには余計なオペレーションが含まれてしまいます。一方で、トレースはプロモーションといくつかの決定を通して、最適化に利用できるいくつかの実行時の値も含みます。以下の例は、前回のエントリのサンプルのプロモーションによって生成されたトレースです。&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;))))))&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;guard_value(x, 5, ...)&lt;/span&gt; の操作の後、 &lt;span style="font-style:italic;"&gt;x&lt;/span&gt; が 5 であるとわかります。ただし 5 ではない場合、実行はインタプリタにフォールバックされます。従って、 ガードの後の &lt;span style="font-style:italic;"&gt;x&lt;/span&gt; に対するオペレーションは、定数に畳み込めます。定数畳み込みの並べ替えを行うために追加の最適化のステップが必要です。どの変数が定数として扱えるかと、どの値が部分環境で使われているかの情報を利用しながら最適化のステップはトレースに沿って動作します。オプティマイザは定数引数のみを持つオペレーションを取り除き、それ以外をトレースに残します。このプロセスは部分評価に実際に非常に似ていて、いくつかの分かっている変数は定数になり、定数引数のみのオペレーションは最適化によって取り去られ、残りはそのままです。&lt;br /&gt;最適化を行うためのコードを以下に示します。&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;RArg&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;C&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;remove_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;RArg1&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C1&lt;/span&gt;), &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C2&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;C1&lt;/span&gt;, &lt;span style="color: #003333"&gt;C2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;remove_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;部分評価と同じですね!部分評価器からのヘルパ関数 &lt;span style="font-style:italic;"&gt;presolve&lt;/span&gt; と部分環境 &lt;span style="font-style:italic;"&gt;PEnv&lt;/span&gt; の再利用をしています。オペレーションの引数が部分環境の中で定数だと分かっている時、オペレーションは最適化の際に実行され、トレースから取り除かれます。そうでなければオペレーションは出力のトレースに残ります。結果の変数(部分評価器内にあるもの) は部分環境から取り除くために必要です。不明な結果によって上書きされるためです。&lt;br /&gt;トレースの中でガードで対処する必要があります。&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, [], &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, [], &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;,&lt;br /&gt;        &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #FF6600"&gt;0&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;ガードされた変数が実際は定数だとわかったとき、ガードを取り除けます。&lt;br /&gt;注意としては、定数のガードが失敗したときは可能ではありません。 (??)&lt;br /&gt;トレーサは実際の値で実行している間のオペレーションを記録します。&lt;br /&gt;従って、値のガードが成功するにはオプティマイザが定数を検出する必要があります。&lt;br /&gt;&lt;span style="font-style:italic;"&gt;guard_false&lt;/span&gt; は &lt;span style="font-style:italic;"&gt;guard_true&lt;/span&gt; と若干違います。&lt;span style="font-style:italic;"&gt;guard_false&lt;/span&gt; の後は引数が実際に 0 だとわかりますが、 &lt;span style="font-style:italic;"&gt;guard_true&lt;/span&gt; の後は値がゼロではないことのみ知り、正確な値はわかりません。&lt;br /&gt;別の点に注目してください。カードによる最適化で、これまでのところ常に空リストだったガードオペレーションの二つ目の引数が部分環境 &lt;span style="font-style:italic;"&gt;PEnv&lt;/span&gt; に置換されます。この置換がなぜ必要なのかを掘り下げて論じます。&lt;br /&gt;変数の関係に関する本当に詳細な情報を提供することを除き、 &lt;span style="font-style:italic;"&gt;guard_value&lt;/span&gt; の最適化はとても似ています。&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;C&lt;/span&gt;, [], &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C1&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;,&lt;br /&gt;        &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;C&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;C&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;このオペレーションは、オプティマイザが後のオペレーションで定数畳み込みのために利用する定数変数を得る主な方法です。以下が部分評価との主な違いです。&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;オプティマイザは開始時にいくつかの変数の値を知っています。&lt;br /&gt;&lt;li&gt;トレースの最適化時、最初はどの変数の値もわかりません。&lt;br /&gt;&lt;li&gt;いくつかの変数についての情報は、ガードの実行後後にのみ得られます。&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;今はループ文で何が起こるのかの情報が不足しています。原則として、再度ループ文に入るとそれになる。(それって何? トレース状態?)&lt;br /&gt;ただし、ループ文でいくつかの追加のオペレーションが出力のために必要です。出力とは、最適化して取り去ったオペレーションとそれによって定数として割り当てられる変数の結果の値です。それが意味するところは、関係する可能性のある変数がいくつかの古い値を持っている可能性があるということです。ループの次のイテレーションは、明らかに間違っているこの古い値で続けます。従って、ループ文以前にいくつか割り当てた部分環境のエントリごとに一つ出力する必要があります。&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;generate_assignments&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;generate_assignments&lt;/span&gt;([], &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;generate_assignments&lt;/span&gt;([&lt;span style="color: #003333"&gt;Var&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;Val&lt;/span&gt; | &lt;span style="color: #003333"&gt;Tail&lt;/span&gt;], &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;Var&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;Val&lt;/span&gt;), &lt;span style="color: #003333"&gt;T&lt;/span&gt;)) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;generate_assignments&lt;/span&gt;(&lt;span style="color: #003333"&gt;Tail&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;どのように割り当ての生成が働くかの例としては、以下の例を見てください。部分環境が &lt;span style="font-style:italic;"&gt;[x/5, y/10]&lt;/span&gt; であるときに、続く割り当てが生成されます。&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;generate_assignments&lt;/span&gt;([&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;10&lt;/span&gt;], &lt;span style="color: #003333"&gt;Out&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #003333"&gt;Out&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;10&lt;/span&gt;), &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;)).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;それらがオプティマイザのコードの全てです。一方、基本的な構造は、部分評価器とよく似ていて、複雑な部分もあまりありません。部分評価器を作るのが難しいものは、制御フローステートメントへの対処と、同じブロックが同じ定数を使って部分評価されたときはコードが再利用可能かどうかの確認と対処の両方必要です。ここでは、全ての複雑なものは置いておきます。トレーサは既に全ての制御フローを削除してガードに置換していて、一回のループオペレーションが終わっています。従って、オプティマイザは単純に 1 パスのオペレーションを実行でき、いくつかを削除します。(ループ文へのいくつかの追加のケアも行います)&lt;br /&gt;この機能を使うと、前回のエントリのプロモーションの例からトレースの最適化を行えます。&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;optimize&lt;/span&gt;(&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;,&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;)))))),&lt;br /&gt;    [],&lt;br /&gt;    &lt;span style="color: #003333"&gt;LoopOut&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #003333"&gt;LoopOut&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;, &lt;span style="color: #FF6600"&gt;3&lt;/span&gt;, [], &lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;7&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;6&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;7&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;6&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;7&lt;/span&gt;), &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;)))))))&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;より読みやすく、最適化したバージョンは以下です:&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;, &lt;span style="color: #FF6600"&gt;3&lt;/span&gt;, [], &lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;7&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;6&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;7&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;6&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;7&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;)))))))&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;意図したとおり、 &lt;span style="font-style:italic;"&gt;guard_value&lt;/span&gt; の後の &lt;span style="font-style:italic;"&gt;x&lt;/span&gt; へのオペレーションは全て削除されます。ただし、いくつか追加された割り当て (x, x2, x3) が最終的に生成されています。この追加の変数は余分なものに見えますが、オプティマイザにはそれを簡単に認識するための十分な情報がありません。この挙動は修正できますが、より複雑にするというコストをかける必要があります。(実際のシステムでは静的単一代入形式 (static single assignment/SSA) にトレースを変換することがこの問題への解となっています)&lt;br /&gt;&lt;h2&gt;インタプリタの再開&lt;/h2&gt;&lt;br /&gt;なぜ上記のコードは最適化できないガードのために部分環境を追加する必要があるのでしょうか? 理由は、なぜループの前に割り当てを追加しなければならないのか、ということに関連します。問題は、オプティマイザが変数の値を知るとき、オプティマイザが変数への割り当てを取り除くことにあります。それが意味することは、実行中の最適化されたトレースからインタプリタへのスイッチバックを行うときに環境の中のいくつかの変数が更新されず、インタプリタの実行が不適切に行われてしまいます。&lt;br /&gt;上記の例で、これを変数 &lt;span style="font-style:italic;"&gt;x2&lt;/span&gt; と &lt;span style="font-style:italic;"&gt;x3&lt;/span&gt; に適用します。二つ目のガードが失敗したとき、最適化された場合はそれらは代入されません。従って、ガードは変数とその値(常に定数です)をリストします。&lt;br /&gt;スイッチバックするとき、インタプリタ側の対応する変数に対する割り当てを作らなければいけません。従って、前回のエントリのコードに以下のように &lt;span style="font-style:italic;"&gt;resume_interp&lt;/span&gt; 関数を適用する必要があります。&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;write_resumevars&lt;/span&gt;([], &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;write_resumevars&lt;/span&gt;([&lt;span style="color: #003333"&gt;Key&lt;/span&gt; &lt;span style="color: #555555"&gt;/&lt;/span&gt; &lt;span style="color: #003333"&gt;Value&lt;/span&gt; | &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;], &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Key&lt;/span&gt;, &lt;span style="color: #003333"&gt;Value&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_resumevars&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env1&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;resume_interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResumeVars&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_resumevars&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResumeVars&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Block&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Block&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;再開時に、 &lt;span style="font-style:italic;"&gt;ResumeVars&lt;/span&gt; (元の部分環境) は単に元の通常環境に追加され、インタプリタに戻ります。ガードの失敗時にトレースの実行を終了し、インタプリタの実行を再開するために必要な、ガードにアタッチされたデータは、多くの場合非常に複雑なトレースシステムの一部です。ほとんどのガードが失敗しないうちはデータは大きくなる可能性があります。従って、ほとんどの実際のシステムではアタッチされるデータの困難な圧縮を試みたりその後のガードとのデータの共有を試みたりしています。&lt;br /&gt;&lt;h2&gt;まとめ&lt;/h2&gt;&lt;br /&gt;このエントリでは、部分環境の変数を適用してトレースを最適化方法とその原理について説明しました。&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;定数引数のみを持つ全てのオペレーションを実行し、それ以外を残すこと&lt;br /&gt;&lt;li&gt;制御フローを含まないため、トレースの最適化はとても単純であること&lt;br /&gt;&lt;li&gt;制御フローに関する全ての疑問はトレーシングコンポーネントによって予め解決しているということ&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;次の、そしてシリーズ最後のエントリでは、小さなバイトコードインタプリタを最適化できるトレーシングと部分評価のより大きな例をお見せします。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-8568035274688043294?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/8568035274688043294/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2012/02/flowgraph_09.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/8568035274688043294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/8568035274688043294'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2012/02/flowgraph_09.html' title='FlowGraph 言語のトレースの最適化'/><author><name>shoma</name><uri>http://www.blogger.com/profile/17043127701763147055</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-4061328901036616371</id><published>2012-02-05T01:11:00.001+09:00</published><updated>2012-02-05T01:15:31.848+09:00</updated><title type='text'>FlowGraph 言語のための単純なトレーサ</title><content type='html'>原文は&lt;a href="http://morepypy.blogspot.com/2012/01/simple-tracer-for-flow-graph-language.html"&gt;こちら&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Part2 トレーシングと部分評価の比較&lt;/h2&gt;&lt;br /&gt;部分評価とトレーシングの比較シリーズの二つ目のエントリです。最初のエントリでは、小さな FlowGraph 言語とそのインタプリタを作り、その言語の部分評価器を示しました。このエントリでは、同じ言語のトレーサがどのように働くか、両方の実行がどのように関係するのかを示します。このエントリで使われるコードはここにあります: &lt;a href="http://paste.pocoo.org/show/543542/"&gt;http://paste.pocoo.org/show/543542/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;トレースの実行&lt;/h2&gt;&lt;br /&gt;トレーサのアイデア(言語の一般的な説明)は、通常の解釈を完全に行いますが、同時に実行された全ての通常のオペレーション(例: フロー制御でないオペレーションなど)のログを保持します。これは、トレーサがブロックの開始から対応する閉じたループを実行する間続けられます。その後、トレースが停止し、最後のオペレーションが開始へのジャンプによって置き換えられます。トレースが終了した後、必要に応じて最適化してトレースを実行できます。&lt;br /&gt;&lt;br /&gt;トレーサを書くために、インタプリタのルールから始めます。述語を &lt;span style="font-style:italic;"&gt;trace&lt;/span&gt; にリネームし、いくつかの引数を追加しています。従って、以下のインタプリタののルールと:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;トレーサの以下のルールからなります:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;), &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;), &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;実際に対応するインタプリタのルール本体が、どのようなトレースのルールなのかの唯一の違いはトレースの再帰呼び出しです。&lt;span style="font-style:italic;"&gt;trace&lt;/span&gt; の引数の意味は以下の通りです。最初と二番目の引数は、インタプリタで使われるような現在実行しているオペレーションと環境です。続く引数はトレースしているオペレーションの出力先で、上の例では実際に実行されたオペレーションになっています。TraceAnchor はその時構築しているトレースに関する追加の情報です。ほとんどの時間、 &lt;span style="font-style:italic;"&gt;trace&lt;/span&gt; の再帰呼び出しで渡されます。その中に何が含まれているかは後で参照します。&lt;br /&gt;&lt;br /&gt;print_ant_stop のルール簡単に実行でき、(そのためトレースもまた) 単に停止するだけです:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;), &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;print&lt;/span&gt;(&lt;span style="color: #003333"&gt;Val&lt;/span&gt;), &lt;span style="color: #CC3300"&gt;nl&lt;/span&gt;.&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;残りは &lt;span style="font-style:italic;"&gt;jump&lt;/span&gt; と &lt;span style="font-style:italic;"&gt;if&lt;/span&gt; の制御オペレーションのルールです。トレースはジャンプを含まないように実行パスを線形化します。ただし、最初のラベルへのジャンプに到達したとき、トレースは停止します。従って、 &lt;span style="font-style:italic;"&gt;jump&lt;/span&gt; の実装は二つのケースがあります:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;) :-&lt;br /&gt;    (&lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;traceanchor&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;FullTrace&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #003333"&gt;T&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;,&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;write&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;trace&lt;/span&gt;), &lt;span style="color: #CC3300"&gt;nl&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;write&lt;/span&gt;(&lt;span style="color: #003333"&gt;FullTrace&lt;/span&gt;), &lt;span style="color: #CC3300"&gt;nl&lt;/span&gt;,&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_optimize&lt;/span&gt;(&lt;span style="color: #003333"&gt;FullTrace&lt;/span&gt;, &lt;span style="color: #003333"&gt;OptTrace&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;write&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;opttrace&lt;/span&gt;), &lt;span style="color: #CC3300"&gt;nl&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;write&lt;/span&gt;(&lt;span style="color: #003333"&gt;OptTrace&lt;/span&gt;), &lt;span style="color: #CC3300"&gt;nl&lt;/span&gt;,&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #003333"&gt;OptTrace&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;OptTrace&lt;/span&gt;)&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Block&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #003333"&gt;Block&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;)&lt;br /&gt;    ).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;小さな単位でこのコードを解剖してみましょう。最初に、 &lt;span style="font-style:italic;"&gt;TraceAnchor&lt;/span&gt; が何かを見ます。&lt;span style="font-style:italic;"&gt;TraceAnchor&lt;/span&gt; は &lt;span style="font-style:italic;"&gt;traceanchor(StartLabel, FullTrace)&lt;/span&gt; というフォームの用語です。&lt;span style="font-style:italic;"&gt;StartLabel&lt;/span&gt; はトレースを開始したプログラムのラベルです。(ループが閉じられた時と同様に同様に終了する必要があります)&lt;span style="font-style:italic;"&gt;FullTrace&lt;/span&gt; は構築している全てのトレースを保持するアキュムレータです。&lt;br /&gt;&lt;br /&gt;ターゲットラベル L が &lt;span style="font-style:italic;"&gt;trace anchor&lt;/span&gt; にストアさているかどうかをルールのチェック開始の際に確認します。もし含まれていれば、トレースを停止できます。T をトレースする残りの部分は、 &lt;span style="font-style:italic;"&gt;loop&lt;/span&gt; のオペレーションが割り当てられ、トレースの最初にジャンプして戻ります。その後、プリントしてトレースを最適化します。そして、実行時に &lt;span style="font-style:italic;"&gt;FullTrace&lt;/span&gt; は &lt;span style="font-style:italic;"&gt;traceanchor&lt;/span&gt; の一部として使います。&lt;br /&gt;&lt;br /&gt;ジャンプする先のラベルが &lt;span style="font-style:italic;"&gt;StartLabel&lt;/span&gt; ではない場合、オペレーションを記録せずにトレースを継続します。ルールのこの部分では、再度同じようなジャンプの解釈をします。&lt;br /&gt;&lt;br /&gt;今のところ、どのような興味深い最適化も行いません。最適化されていないトレースを返すだけです:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;do_optimize&lt;/span&gt;(&lt;span style="color: #003333"&gt;FullTrace&lt;/span&gt;, &lt;span style="color: #003333"&gt;FullTrace&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;今足りていないオペレーションは &lt;span style="font-style:italic;"&gt;if&lt;/span&gt; です。&lt;span style="font-style:italic;"&gt;if&lt;/span&gt; 文は特別な処理が必要です。トレースする制御フローの数が発散してしまうからです。トレースは線形です。したがって分岐する可能性のあるパスの内片方しか記録できません。実行される別のパスをトレースすることはトレースの実行時に可能です。したがって、トレース中の真偽値と、トレースの実行中に真偽値がまだ同じ条件かどうかを確認する必要があります。これは、この条件をチェックするガードオペレーションで済んでいます。続くルールを実装します:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;L1&lt;/span&gt;, &lt;span style="color: #003333"&gt;L2&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;==&lt;/span&gt; &lt;span style="color: #FF6600"&gt;0&lt;/span&gt; &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #003333"&gt;L&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;L2&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, [], &lt;span style="color: #003333"&gt;L1&lt;/span&gt;, &lt;span style="color: #003333"&gt;NT&lt;/span&gt;)&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #003333"&gt;L&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;L1&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, [], &lt;span style="color: #003333"&gt;L2&lt;/span&gt;, &lt;span style="color: #003333"&gt;NT&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;NT&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;これはインタプリタの &lt;span style="font-style:italic;"&gt;if&lt;/span&gt; のルールにとても似ています。ルールは条件が真であれば &lt;span style="font-style:italic;"&gt;guard_true&lt;/span&gt; をケース中に挿入し、条件が偽であれば &lt;span style="font-style:italic;"&gt;guard_false&lt;/span&gt; を挿入します。ガードの引数は以下の通りです。&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;ガードを行う変数&lt;/li&gt;&lt;br /&gt;&lt;li&gt;空のリスト(この理由は後々説明します)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ガードの失敗時とトレースの残りの部分の実行を続けるために必要なラベル&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;トレースの開始時に便利に使える小さな述語も追加しましょう:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;do_trace&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;StartBlock&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #003333"&gt;StartBlock&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ProducedTrace&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;traceanchor&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;ProducedTrace&lt;/span&gt;)).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;最初の実行によって、述語はラベルと環境を受け取り、受け取った環境とともにラベルを実行します。その後、トレースを実行し、最終的にカードが失敗するとインタプリタにジャンプして戻ります。これを、ラベル &lt;span style="font-style:italic;"&gt;L&lt;/span&gt; のブロック文とコードを読むことで実行します。そして未束縛の変数 &lt;span style="font-style:italic;"&gt;ProducedTrace&lt;/span&gt; とともに &lt;span style="font-style:italic;"&gt;trace&lt;/span&gt; を呼び出し、トレースとトレースを開始したラベルを含むトレースアンカーを保持し、トレース変数が生成されます。&lt;br /&gt;&lt;br /&gt;この述語とトレースを使うと、トレースの実行がないだけで前回のブログポストは既にトレースできる力のある実装です。(実行は次のセクションでおこないます):&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;do_trace&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;x&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;10&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;20&lt;/span&gt;]).&lt;br /&gt;&lt;span style="color: #CC3300"&gt;trace&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;power_done&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;)))&lt;br /&gt;&lt;span style="color: #CC3300"&gt;opttrace&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;power_done&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;)))&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;計算されたトレースは:&lt;br /&gt;&lt;br /&gt;&lt;pre class="literal-block"&gt;&lt;br /&gt;op2(res,mul,var(res),var(x),&lt;br /&gt;op2(y,sub,var(y),const(1),&lt;br /&gt;guard_true(y,[],power_done,&lt;br /&gt;loop)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;実際 &lt;span style="font-style:italic;"&gt;power_rec&lt;/span&gt; からのループの中身です。&lt;span style="font-style:italic;"&gt;if&lt;/span&gt; が &lt;span style="font-style:italic;"&gt;guard_true&lt;/span&gt; になると、ガードが失敗した場合 &lt;span style="font-style:italic;"&gt;power_done&lt;/span&gt; にジャンプします。&lt;br /&gt;&lt;br /&gt;実際のトレースシステムには、トレーサを開始するための方法が必要になります。例えばインタプリタの中でのプロファイリングの実行によるものや頻繁に実行されるラベルでトレーサを開始するなどです。また、同じラベルのトレースは、通常同じ経路であればキャッシュされます。これらの詳細はこの単純なモデルではそのままです。&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;トレースの実行&lt;/h2&gt;&lt;br /&gt;実際のトレースシステムでは、トレースはマシンコードになり、 CPU で直接実行されます。私たちの小さなモデルでは、単にこのモデルのための別のインタプリタを書き出すだけです。このインタプリタはとても単純で、インタプリタにとても似ています:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;これらのルールはインタプリタの &lt;span style="font-style:italic;"&gt;op1&lt;/span&gt; と &lt;span style="font-style:italic;"&gt;op2&lt;/span&gt; のルールと完全に等価です。&lt;span style="font-style:italic;"&gt;runtrace&lt;/span&gt; は、自身の再帰呼び出しで常に渡される追加の引数 &lt;span style="font-style:italic;"&gt;TraceFromStart&lt;/span&gt; が必要です。&lt;br /&gt;&lt;br /&gt;トレースの最後に到達し、ループ文が検出されると単に最初から開始します:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;残りの質問は、ガードが発生した時に何をするかです。このケースでは、ガード条件をチェックする必要があります。ガードが成功した場合、トレースの実行は続けられます。それ以外の場合トレースは終了し、インタプリタは実行を再開します:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResumeVars&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;==&lt;/span&gt; &lt;span style="color: #FF6600"&gt;0&lt;/span&gt; &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;resume_interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResumeVars&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;)&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;)&lt;br /&gt;    ).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;guard_false&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResumeVars&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;==&lt;/span&gt; &lt;span style="color: #FF6600"&gt;0&lt;/span&gt; &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;)&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;resume_interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResumeVars&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;)&lt;br /&gt;    ).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;resume_interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, [], &lt;span style="color: #003333"&gt;L&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Block&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Block&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;どのように実行がガードオペレーションの第三引数にエンコードされたラベルとしてインタプリタに引き渡されるのでしょうか。&lt;span style="font-style:italic;"&gt;ResumeVars&lt;/span&gt; が何なのかは、後のエントリで見ることにします。今のところ、それは常に空のリストであると仮定します。&lt;br /&gt;&lt;br /&gt;トレースのためのこのインタプリタを使うことで、サンプルをトレースし、実行できます:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;:- &lt;span style="color: #CC00FF"&gt;do_trace&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;x&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;10&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;20&lt;/span&gt;]).&lt;br /&gt;&lt;span style="color: #CC3300"&gt;trace&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;power_done&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;)))&lt;br /&gt;&lt;span style="color: #CC3300"&gt;opttrace&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;power_done&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;)))&lt;br /&gt;&lt;span style="color: #FF6600"&gt;100000000000000000000&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;もちろんこの例はあまり面白くありません。トレースの結果はほとんどオリジナルのコードと同じだからです。後のエントリではより面白い例を示します。&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;拡張機能: プロモーション&lt;/h2&gt;&lt;br /&gt;ここでは、トレーサは実際にはインタプリタにはあまり手を加えていません。しかし、この線形化コントロールフローに深く高度な動作はありません。このセクションでは、より面白いことをするためにコントロールフロー言語にトレーサを許可する、重要ですが単純な拡張機能を追加します。この拡張機能はプロモーションと呼ばれます。&lt;br /&gt;&lt;br /&gt;プロモーションは、基本的にはプログラマがコントロールフロープログラムに追加できるヒントです。プロモーションは変数 V と ラベル L を引数に取る &lt;span style="font-style:italic;"&gt;promote(V, L)&lt;/span&gt; のようなオペレーションです。インタプリタがこの文を実行するとき、単にラベル L にジャンプし、変数を無視します:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;promote&lt;/span&gt;(&lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;ただし、トレーサはいくつかの遙かに面白いことをします。トレーサの &lt;span style="font-style:italic;"&gt;promote&lt;/span&gt; 文は V の値について知るために非常に役立つであろうヒントをトレーサに与え、残りのトレースでその値は定数として保持する必要があります。従って、トレーサがプロモーションを検出すると、特殊な種類の &lt;span style="font-style:italic;"&gt;guard_value&lt;/span&gt; と呼ばれるガードを挿入します:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;promote&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;, [], &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;), &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;trace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;T&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceAnchor&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;guard_value&lt;/span&gt; は興味深いオペレーションです。変数 V の現在の値 FVal をトレースの中に凍結するからです。トレースが実行される時、ガードは変数の現在の値と凍結した値が同じかどうかをチェックします。もし同じであれば、実行は継続されます。そうでなければトレースは終了します:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;FVal&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResumeVars&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;==&lt;/span&gt; &lt;span style="color: #003333"&gt;FVal&lt;/span&gt; &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;runtrace&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;TraceFromStart&lt;/span&gt;)&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;resume_interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResumeVars&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;)&lt;br /&gt;    ).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;このオペレーションはどのように使えるのでしょうか? これは、変数 V があまり変更されないことや、これにより現在の値をトレースの中に凍結するのに役立つといったようにトレーサとコミュニケーションをとる方法です。これによって毎回 V の値を知ることなく処理を進められます。&lt;br /&gt;&lt;br /&gt;ここで、(少し考えられた)例を見てみましょう:&lt;br /&gt;&lt;br /&gt;&lt;pre class="literal-block"&gt;&lt;br /&gt;l:&lt;br /&gt;    c = i &amp;gt;= 0&lt;br /&gt;    if c goto b else goto l_done&lt;br /&gt;&lt;br /&gt;l_done:&lt;br /&gt;    print_and_stop(var(i))&lt;br /&gt;&lt;br /&gt;b:&lt;br /&gt;    promote(x, b2)&lt;br /&gt;&lt;br /&gt;b2:&lt;br /&gt;    x2 = x * 2&lt;br /&gt;    x3 = x2 + 1&lt;br /&gt;    i = i - x3&lt;br /&gt;    goto l&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;プログラムの構文に落とし込みます:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;l&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;         &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;b&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;))).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;b&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;promote&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;),&lt;br /&gt;          &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;add&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;          &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;),&lt;br /&gt;          &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;l&lt;/span&gt;))))).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;これは単純な &lt;span style="font-style:italic;"&gt;x * 2 + 1&lt;/span&gt; のカウントダウンを行うループです。どのような &lt;span style="font-style:italic;"&gt;x&lt;/span&gt; が入力されたとしても、 &lt;span style="font-style:italic;"&gt;i &gt;= 0&lt;/span&gt; が真である期間は長くありません。&lt;span style="font-style:italic;"&gt;x&lt;/span&gt; がほとんど変更されないと仮定すると、 &lt;span style="font-style:italic;"&gt;x * 2 + 1&lt;/span&gt; が定数に畳み込みが可能なのでイテレーションごとに再実行する必要がないとプロモートする価値があります。これは &lt;span style="font-style:italic;"&gt;x&lt;/span&gt; のプロモーションによって完了します (もちろんこのループは不変のループを使ったコードに最適化され、よく動くでしょう、 &lt;span style="font-style:italic;"&gt;x&lt;/span&gt; はループ中では実際に変更されないためです)。&lt;br /&gt;&lt;br /&gt;これをトレースするには、以下のクエリを実行する必要があります:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;do_trace&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;b&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;100&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;x&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;]).&lt;br /&gt;&lt;span style="color: #CC3300"&gt;trace&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;))))))&lt;br /&gt;&lt;span style="color: #CC3300"&gt;opttrace&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;))))))&lt;br /&gt;&lt;span style="color: #555555"&gt;-&lt;/span&gt;&lt;span style="color: #FF6600"&gt;10&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;トレースをより読みやすい方法で書くと:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;guard_value&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;,&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;b2&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x2&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x3&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,&lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;,&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;i&lt;/span&gt;),&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;),&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;guard_true&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;c&lt;/span&gt;,[],&lt;span style="color: #CC3300"&gt;l_done&lt;/span&gt;,&lt;br /&gt;&lt;span style="color: #CC3300"&gt;loop&lt;/span&gt;))))))&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;guard_value&lt;/span&gt; の後で、 &lt;span style="font-style:italic;"&gt;x&lt;/span&gt; へのオペレーションの実行は定数にたたみ込まれてなくなります。&lt;span style="font-style:italic;"&gt;x&lt;/span&gt; が 5 であると実行が継続される前にガードが保証するからです。実際に定数畳み込みを実行するには、トレースを最適化するためのいくつかのコンポーネントが必要です。これは次回のエントリで言及します。&lt;br /&gt;&lt;br /&gt;このセクションでは、どのようにトレーサにプロモーションを実装するかについて話し、何をどのように使うかについては触れていません。プロモーションは一番重要な PyPy のトレーシングのアプローチの成功のために責任のある要素の一つです。どのようにこれが動くのかは、&lt;a href="https://bitbucket.org/pypy/extradoc/src/tip/talk/icooolps2011/bolz-hints-final.pdf"&gt;"Runtime feedback in a meta-tracing JIT for efficient dynamic languages"&lt;/a&gt;で詳しく説明されています。&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;結論&lt;/h2&gt;&lt;br /&gt;このエントリでは、とても小さな最小限のトレーサと、生成されたトレースのためのインタプリタを見ました。トレーサはオリジナルのインタプリタにとても似ていて、それはまた実行されたオペレーションを追跡して、さらにプログラムを実行します。トレーシングの段階ではループは閉じられていて、その後トレースは最適化され、実行されます。失敗のガードがヒットしている間トレースの実行が続きます。ある時点で、実行は通常のインタプリタに戻ります (そしてこのシンプルな実装では通常のインタプリタに戻ったままになります) 。&lt;br /&gt;&lt;br /&gt;オリジナルのプログラムで &lt;span style="font-style:italic;"&gt;promote&lt;/span&gt; を呼ぶことでヒントの追加を可能にするトレーサの拡張もお見せしました。実行時の値をトレースに凍結して保持するフィードバックをトレーサに指示するものです。この拡張機能は、前回のエントリで実装した部分評価器では不可能です。部分評価は厳密に実行前に終了し、変数の値がわかっていない場合は、実行時の値は見つけられない可能性が高いです。&lt;br /&gt;&lt;br /&gt;次のエントリでは、プログラムの実行前にトレースをどのように最適化するかと、どのようにトレースのオプティマイザが部分評価と関わるかについてお見せします。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-4061328901036616371?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/4061328901036616371/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2012/02/flowgraph.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/4061328901036616371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/4061328901036616371'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2012/02/flowgraph.html' title='FlowGraph 言語のための単純なトレーサ'/><author><name>shoma</name><uri>http://www.blogger.com/profile/17043127701763147055</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-7113064041439232055</id><published>2012-01-27T13:24:00.005+09:00</published><updated>2012-01-27T13:52:53.328+09:00</updated><title type='text'>部分評価とトレーシングの比較 Part 1</title><content type='html'>原文は&lt;a href="http://morepypy.blogspot.com/2012/01/comparing-partial-evaluation-and.html"&gt;こちら&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;私の博士論文の一部として、私は今 PyPy のメタトレーシングアプローチと従来の言語処理系からの情報のみ利用する(JIT)コンパイラの様々なアイデアとの関連について考えています。これらの線に沿って一番研究されたアイデアの一つは&lt;a href="http://en.wikipedia.org/wiki/Partial_evaluation"&gt;部分評価&lt;/a&gt;です。部分評価は、基本的にコンパイラに付属するという PyPy と同じゴールを持っています。インタプリタを書き、コンパイラをコストなしに手に入れるということです。ゴールにたどり着く方法は、若干違います。この一連のブログポストでは、PyPy のメタトレーシングと部分評価の類似点と相違点を探してみようと思います。&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Flow Graph 言語&lt;/h2&gt;&lt;br /&gt;「部分評価」が何なのかと「メタトレーシング」が何なのかの明確な理解のために両者の「実行モデル」を示します。その後、小さな命令型言語を定義し、その言語のための部分評価器とトレーサーがどのようなものなのかを示します。全てのコードは Prolog で実装されるでしょう。(パターンマッチングが使える関数型言語でも構いませんが、私が知る中では Prolog がベストです。バックトレーシングは使いませんので、単に関数型プログラムとして読めます。)このポストでは、言語とその言語の部分評価器の定義から始めます。このブログのポストに書かれた全てのコードはここにあります: &lt;a href="http://paste.pocoo.org/show/541004/"&gt;http://paste.pocoo.org/show/541004/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;言語は概念的には PyPy の Flow Graph に近いものです。しかし、少し制限があります。関数呼び出しを持たず、ラベルづけされた、一連の実行する命令の後に条件付き、もしくは条件なしのジャンプが付随するブロックから構成されます。全ての操作は、いくつかの演算をいくつかの引数に適用し、計算された値を変数に代入します。&lt;br /&gt;&lt;br /&gt;x の y 乗を計算する単純なプログラムはこのようなものです:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;power:&lt;br /&gt;    res = 1&lt;br /&gt;    if y goto power_rec else goto power_done&lt;br /&gt;&lt;br /&gt;power_rec:&lt;br /&gt;    res = res * x&lt;br /&gt;    y = y - 1&lt;br /&gt;    if y goto power_rec else goto power_done&lt;br /&gt;&lt;br /&gt;power_done:&lt;br /&gt;    print_and_stop(res)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Prolog のデータ構造で同じプログラムを表します。以下のような Prolog のコードです:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;             &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;power_done&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;),&lt;br /&gt;                 &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;),&lt;br /&gt;                 &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;power_done&lt;/span&gt;)))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_done&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;))).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;ブロックのそれぞれのルールは、最初にブロックのラベルを示し、コードが続きます。これで一つのブロックを宣言します。コードは op1 か op2 文が連なり、ジャンプ、 if もしくは print_and_stop によって終了します。op1 は一つの引数を受ける &lt;span style="font-style:italic;"&gt;op1(res_variable, operation_name, argument, next_statement)&lt;/span&gt; のような命令です。引数は &lt;span style="font-style:italic;"&gt;var(name)&lt;/span&gt; 形式の変数か &lt;span style="font-style:italic;"&gt;const(value)&lt;/span&gt; 形式の定数が使えます。&lt;br /&gt;&lt;br /&gt;この FlowGraph 言語を実行するには、最初にいくつかの補助機能を必要とします。最初のいくつかの補助機能は、インタプリタがプログラムで発生する、変数名の実行中の値とのマッピングに使うためのデータ構造で、実行環境を扱うことに関係します。Python では辞書型がこの目的で使われます。しかし、 Prolog では キーと値のペアのリストを使ってエミュレートしなければいけません。(かなり効率は悪いですが、必要十分です):&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;X&lt;/span&gt;, [], &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;) :- &lt;span style="color: #CC00FF"&gt;throw&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;key_not_found&lt;/span&gt;(&lt;span style="color: #003333"&gt;X&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;Key&lt;/span&gt;, [&lt;span style="color: #003333"&gt;Key&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;Value&lt;/span&gt; | &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;], &lt;span style="color: #003333"&gt;Value&lt;/span&gt;) :- !.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;Key&lt;/span&gt;, [&lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt; | &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;], &lt;span style="color: #003333"&gt;Value&lt;/span&gt;) :- &lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;Key&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;Value&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;([], &lt;span style="color: #003333"&gt;X&lt;/span&gt;, &lt;span style="color: #003333"&gt;V&lt;/span&gt;, [&lt;span style="color: #003333"&gt;X&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;V&lt;/span&gt;]).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;([&lt;span style="color: #003333"&gt;Key&lt;/span&gt;&lt;span style="color: #CC3300"&gt;/&lt;/span&gt;&lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt; | &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;], &lt;span style="color: #003333"&gt;Key&lt;/span&gt;, &lt;span style="color: #003333"&gt;Value&lt;/span&gt;, [&lt;span style="color: #003333"&gt;Key&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;Value&lt;/span&gt; | &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;]) :- !.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;([&lt;span style="color: #003333"&gt;Pair&lt;/span&gt; | &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;], &lt;span style="color: #003333"&gt;Key&lt;/span&gt;, &lt;span style="color: #003333"&gt;Value&lt;/span&gt;, [&lt;span style="color: #003333"&gt;Pair&lt;/span&gt; | &lt;span style="color: #003333"&gt;NewRest&lt;/span&gt;]) :- &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;Key&lt;/span&gt;, &lt;span style="color: #003333"&gt;Value&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewRest&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;remove_env&lt;/span&gt;([], &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;, []).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;remove_env&lt;/span&gt;([&lt;span style="color: #003333"&gt;Key&lt;/span&gt;&lt;span style="color: #CC3300"&gt;/&lt;/span&gt;&lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt; | &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;], &lt;span style="color: #003333"&gt;Key&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;) :- !.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;remove_env&lt;/span&gt;([&lt;span style="color: #003333"&gt;Pair&lt;/span&gt; | &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;], &lt;span style="color: #003333"&gt;Key&lt;/span&gt;, [&lt;span style="color: #003333"&gt;Pair&lt;/span&gt; | &lt;span style="color: #003333"&gt;NewRest&lt;/span&gt;]) :- &lt;span style="color: #CC00FF"&gt;remove_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;Key&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewRest&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;X&lt;/span&gt;), &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #003333"&gt;X&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Y&lt;/span&gt;) :- &lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;X&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Y&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;これらの関数の実装は重要ではありません。lookup 関数は環境のリストからキーを見つけ、 write_env 関数は新しいキーと値のペアを環境に追加し、 remove_env 関数はキーを削除します。resolve 関数は、定数か変数のいずれかを引数として取り、値を返す為に使います。もし定数であればその値が返され、変数であれば環境からルックアップします。注意として、&lt;br /&gt;lookup と resolve の最後の引数は、実際には戻り値で、このような方法は Prolog ではよくあるアプローチです。&lt;br /&gt;&lt;br /&gt;これまでのところ、基本演算のプログラム上の意味が定義されていません。そのため、基本演算とともに do_op 関数を定義します:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;same&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;, &lt;span style="color: #003333"&gt;Y&lt;/span&gt;, &lt;span style="color: #003333"&gt;Z&lt;/span&gt;) :- &lt;span style="color: #003333"&gt;Z&lt;/span&gt; &lt;span style="color: #555555"&gt;is&lt;/span&gt; &lt;span style="color: #003333"&gt;X&lt;/span&gt; &lt;span style="color: #555555"&gt;*&lt;/span&gt; &lt;span style="color: #003333"&gt;Y&lt;/span&gt;.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;add&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;, &lt;span style="color: #003333"&gt;Y&lt;/span&gt;, &lt;span style="color: #003333"&gt;Z&lt;/span&gt;) :- &lt;span style="color: #003333"&gt;Z&lt;/span&gt; &lt;span style="color: #555555"&gt;is&lt;/span&gt; &lt;span style="color: #003333"&gt;X&lt;/span&gt; &lt;span style="color: #555555"&gt;+&lt;/span&gt; &lt;span style="color: #003333"&gt;Y&lt;/span&gt;.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;sub&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;, &lt;span style="color: #003333"&gt;Y&lt;/span&gt;, &lt;span style="color: #003333"&gt;Z&lt;/span&gt;) :- &lt;span style="color: #003333"&gt;Z&lt;/span&gt; &lt;span style="color: #555555"&gt;is&lt;/span&gt; &lt;span style="color: #003333"&gt;X&lt;/span&gt; &lt;span style="color: #555555"&gt;-&lt;/span&gt; &lt;span style="color: #003333"&gt;Y&lt;/span&gt;.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;eq&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;, &lt;span style="color: #003333"&gt;Y&lt;/span&gt;, &lt;span style="color: #003333"&gt;Z&lt;/span&gt;) :- &lt;span style="color: #003333"&gt;X&lt;/span&gt; &lt;span style="color: #555555"&gt;==&lt;/span&gt; &lt;span style="color: #003333"&gt;Y&lt;/span&gt; &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: #003333"&gt;Z&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;1&lt;/span&gt;; &lt;span style="color: #003333"&gt;Z&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;0&lt;/span&gt;.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;ge&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;, &lt;span style="color: #003333"&gt;Y&lt;/span&gt;, &lt;span style="color: #003333"&gt;Z&lt;/span&gt;) :- &lt;span style="color: #003333"&gt;X&lt;/span&gt; &lt;span style="color: #555555"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;Y&lt;/span&gt; &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: #003333"&gt;Z&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;1&lt;/span&gt;; &lt;span style="color: #003333"&gt;Z&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;0&lt;/span&gt;.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;readlist&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;I&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;) :- &lt;span style="color: #CC00FF"&gt;nth0&lt;/span&gt;(&lt;span style="color: #003333"&gt;I&lt;/span&gt;, &lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;, &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;, &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;) :- &lt;span style="color: #CC00FF"&gt;throw&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;missing_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;)).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;重要なことなのでもう一度言います。最後の引数は出力先の変数です。&lt;br /&gt;&lt;br /&gt;単純な操作を実行する準備が整いました。なので、 interp という述語を定義します。これは、最初の引数が実行環境、二つ目の引数が実行する操作を表します。例では、一つか二つの引数をと共に基本演算を実行しています。:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;最初に、引数を値として解決します。その後、演算が実行され、結果が環境に書き戻されます。そして interp がプログラムの残りの部分とともに呼び出されます。同様に、条件なしジャンプと print_end_stop も簡単です。:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Block&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Block&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;resolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;print&lt;/span&gt;(&lt;span style="color: #003333"&gt;Val&lt;/span&gt;), &lt;span style="color: #CC3300"&gt;nl&lt;/span&gt;.&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;条件なしジャンプの中では、単にターゲットのブロックを取得し、その実行を継続します。print_and_stop の実行は、引数を解決し、値をプリントし、終了します。&lt;br /&gt;&lt;br /&gt;条件付きジャンプだけはは少し難しいです:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;L1&lt;/span&gt;, &lt;span style="color: #003333"&gt;L2&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;lookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;==&lt;/span&gt; &lt;span style="color: #FF6600"&gt;0&lt;/span&gt; &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;L2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Block&lt;/span&gt;)&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;L1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Block&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Block&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;最初に変数を環境からルックアップし、変数の値がゼロであれば二つ目のブロックの実行を継続します。そうでなければ最初のブロックを継続します。&lt;br /&gt;&lt;br /&gt;このインタプリタは、上記のサンプルを Prolog のコンソールでこのように実行できます:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #AA0000; background-color: #FFAAAA"&gt;$&lt;/span&gt; &lt;span style="color: #CC3300"&gt;swipl&lt;/span&gt; &lt;span style="color: #555555"&gt;-&lt;/span&gt;&lt;span style="color: #CC3300"&gt;s&lt;/span&gt; &lt;span style="color: #CC3300"&gt;cfglang&lt;/span&gt;.&lt;span style="color: #CC3300"&gt;pl&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power&lt;/span&gt;, &lt;span style="color: #003333"&gt;Block&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;interp&lt;/span&gt;(&lt;span style="color: #003333"&gt;Block&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;10&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;10&lt;/span&gt;]).&lt;br /&gt;&lt;span style="color: #FF6600"&gt;10000000000&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2&gt;FlowGraph 言語の部分評価&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;それでは、この単純な FlowGraph 言語のための部分評価器がどのようなものか見てみましょう。部分評価は特殊化とも呼ばれ、プログラム操作のテクニックです。部分評価は入力のプログラムを受け取り、(うまくいけば)シンプルで高速な出力プログラムに変換します。これは、入力プログラム中のいくつかの変数を定数であると仮定します。定数にのみ作用する全ての演算は、畳み込まれます。それ以外の全ての演算は、出力プログラムでもそのままにする必要があります。(残留プログラムと呼ばれます)従って、部分評価器は、単にいくつかの演算を実行できないだけで、殆どインタプリタのような結果をもたらします。また、出力は単なる値ではなく、最適化できなかった残りの演算のリストです。&lt;br /&gt;&lt;br /&gt;部分評価器は通常の環境では使えません。全ての変数の値が知られているインタプリタとは異なるためです。そのために、部分的な環境の下では分かっている変数のみを保存します。これらの部分的な環境のために、いくつかの新しい補助関数が必要です:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;Key&lt;/span&gt;, [], &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #003333"&gt;Key&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;Key&lt;/span&gt;, [&lt;span style="color: #003333"&gt;Key&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #003333"&gt;Value&lt;/span&gt; | &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;], &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;Value&lt;/span&gt;)) :- !.&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;Key&lt;/span&gt;, [&lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt; | &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;], &lt;span style="color: #003333"&gt;Value&lt;/span&gt;) :- &lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;Key&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;Value&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;X&lt;/span&gt;), &lt;span style="color: #006699; font-weight: bold"&gt;_&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;X&lt;/span&gt;)).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;) :- &lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;X&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;plookup 関数は変数と部分環境を受け取り、変数が部分環境内で見つかった場合は &lt;span style="font-style:italic;"&gt;const(Value)&lt;/span&gt; を、見つからなかった場合は &lt;span style="font-style:italic;"&gt;var(Key)&lt;/span&gt; を返します。同様に presolve は lookup の代わりに plookup を使う以外は resolve と同じ関数です。&lt;br /&gt;&lt;br /&gt;これらの補助関数を使うことで部分評価器を書き始められます。下記の二つのルールは定数の畳み込みのための主な最適化で使います。部分評価器のアイデアは、定数引数のみを含む操作を見てください。それらは定数の畳み込み操作を行い、それ以外はそうではありません:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;pe&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;RArg&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;C&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;remove_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;op1&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;pe&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;pe&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Rest&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;RArg1&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C1&lt;/span&gt;), &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C2&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_op&lt;/span&gt;(&lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;C1&lt;/span&gt;, &lt;span style="color: #003333"&gt;C2&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;write_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Res&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;remove_env&lt;/span&gt;(&lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #003333"&gt;ResultVar&lt;/span&gt;, &lt;span style="color: #003333"&gt;Op&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg1&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg2&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;)&lt;br /&gt;    ),&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;pe&lt;/span&gt;(&lt;span style="color: #003333"&gt;Rest&lt;/span&gt;, &lt;span style="color: #003333"&gt;NEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;RestResidual&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;pe という述語は、部分環境を受け取り、現在の演算と行われる可能性のある新しい演算を返します。単純な演算の部分評価のために、これらの引数は部分環境からルックアップされます。もし全てのの引数が定数であれば、演算は実行できるので、新しい演算は生成されません。それ以外の場合は今見ているものと同じように動作する新しい残留演算を生成する必要があります。また、結果の変数は部分環境から削除する必要があります。不明な値によって上書きされるためです。&lt;br /&gt;&lt;br /&gt;潜在的に生成された残留演算は &lt;span style="font-style:italic;"&gt;NewOp&lt;/span&gt; の出力引数として保存されます。再帰呼び出しの出力の引数は、新しく生成された残留演算の最後の引数で、再帰的な呼び出しによって埋められます。これは Prolog では典型的なアプローチですが、 Prolog に馴染みない人には奇妙に見えるかもしれません。&lt;br /&gt;&lt;br /&gt;注意として、これらのルールの最初のケースでは、解釈のようなことのみを行います。二つ目のケースでは、実際にはなにもしておらず、残留演算を生成しているだけです。この通常の評価と部分評価の間の関連は、とても典型的なものです。&lt;br /&gt;&lt;br /&gt;条件なしジャンプと print_and_stop はとても簡単です:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;pe&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;LR&lt;/span&gt;)) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;do_pe&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;LR&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;pe&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;), &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #003333"&gt;RArg&lt;/span&gt;)) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;presolve&lt;/span&gt;(&lt;span style="color: #003333"&gt;Arg&lt;/span&gt;, &lt;span style="color: #003333"&gt;Env&lt;/span&gt;, &lt;span style="color: #003333"&gt;RArg&lt;/span&gt;).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;部分評価のために、条件なしジャンプは再度ジャンプを生成します。既存のジャンプターゲットのラベルは、残留コードを生成するために、ラベル L 渡とされた部分環境を伴って部分評価器にで評価することで計算されます。&lt;span style="font-style:italic;"&gt;print_and_stop&lt;/span&gt; は単に &lt;span style="font-style:italic;"&gt;print_and_stop&lt;/span&gt; を返すだけです。&lt;span style="font-style:italic;"&gt;do_pe&lt;/span&gt; のコードをすぐに見てみましょう。&lt;br /&gt;&lt;br /&gt;条件付きジャンプはより興味深いです:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;pe&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;L1&lt;/span&gt;, &lt;span style="color: #003333"&gt;L2&lt;/span&gt;), &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt;) :-&lt;br /&gt;    &lt;span style="color: #CC00FF"&gt;plookup&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;Val&lt;/span&gt;),&lt;br /&gt;    (&lt;span style="color: #003333"&gt;Val&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #003333"&gt;C&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        (&lt;span style="color: #003333"&gt;C&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #FF6600"&gt;0&lt;/span&gt; &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #003333"&gt;L&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;L2&lt;/span&gt;&lt;br /&gt;        ;&lt;br /&gt;            &lt;span style="color: #003333"&gt;L&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #003333"&gt;L1&lt;/span&gt;&lt;br /&gt;        ),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_pe&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;LR&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #003333"&gt;LR&lt;/span&gt;)&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_pe&lt;/span&gt;(&lt;span style="color: #003333"&gt;L1&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;L1R&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;do_pe&lt;/span&gt;(&lt;span style="color: #003333"&gt;L2&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;L2R&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #003333"&gt;NewOp&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;if&lt;/span&gt;(&lt;span style="color: #003333"&gt;V&lt;/span&gt;, &lt;span style="color: #003333"&gt;L1R&lt;/span&gt;, &lt;span style="color: #003333"&gt;L2R&lt;/span&gt;)&lt;br /&gt;    ).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;最初に、条件変数の値を参照します。もしそれが定数であれば、よりよいコードを生成できます。静的に一つのパスにしか到達できないことが分かるためです。従って、そのパスのへのコードを生成し、条件なしのジャンプを出力します。もし条件変数が部分評価時にわからなければ、どちらのパスに対しても部分評価を適用し、残留コードして条件付きジャンプを生成します。&lt;br /&gt;&lt;br /&gt;部分評価器がインタプリタよりも多く作業を行う可能性がある原因のルールは一つで、 &lt;span style="font-style:italic;"&gt;if&lt;/span&gt; の後でしばしば両方のパスを探索しなければいけないということです。最悪のケースでは、このプロセスは終了しません。なので、実際の部分評価器では、どのように終了するかを確認しなければいけませんそれを行うための多くのアルゴリズムがありますが、ここではこの問題を無視します。&lt;br /&gt;&lt;br /&gt;今 &lt;span style="font-style:italic;"&gt;do_pe&lt;/span&gt; という述語がなにをしているかを理解することが必要です。一番重要なタスクは、以前に部分評価されたかどうかをメモ化するコードによって、同じ作業を二回しないことを確認することです。そのために部分環境のラベルから残留コードのラベルへのマッピングを保持します:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC00FF"&gt;do_pe&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;LR&lt;/span&gt;) :-&lt;br /&gt;    (&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;LR&lt;/span&gt;) &lt;span style="color: #CC3300"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #CC3300"&gt;true&lt;/span&gt;&lt;br /&gt;    ;&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;gensym&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;LR&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;assert&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;LR&lt;/span&gt;)),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;L&lt;/span&gt;, &lt;span style="color: #003333"&gt;Code&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;pe&lt;/span&gt;(&lt;span style="color: #003333"&gt;Code&lt;/span&gt;, &lt;span style="color: #003333"&gt;PEnv&lt;/span&gt;, &lt;span style="color: #003333"&gt;Residual&lt;/span&gt;),&lt;br /&gt;        &lt;span style="color: #CC00FF"&gt;assert&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #003333"&gt;LR&lt;/span&gt;, &lt;span style="color: #003333"&gt;Residual&lt;/span&gt;))&lt;br /&gt;    ).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;もしラベル L が既に部分環境 &lt;span style="font-style:italic;"&gt;PEnv&lt;/span&gt; の中で部分評価されていることをコードキャッシュが示すのであれば、以前生成した残留コードのラベル LPrevious が返ります。それ以外は &lt;span style="font-style:italic;"&gt;gensym&lt;/span&gt; によって新しいラベルが生成され、コードキャッシュは新しいラベルを割り当てて通知し、ブロックは部分評価され、残留コードがデータベースに追加されます。&lt;br /&gt;&lt;br /&gt;部分評価について知るための用語集: この部分評価器は polyvariant online 部分評価器です。 "Polyvariant" の意味するところは、全てのラベル、いくつかの特殊化したバージョンのブロックを生成できるということです。"Online" の意味は、部分評価器を走らせる前の事前処理がないということです。&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;部分評価の例&lt;/h2&gt;&lt;br /&gt;このコードで、部分評価の古典的な例を見られます。(恐らく部分評価における "Hello, world" のようなものです) 冪乗関数について部分評価器に尋ね、指数 y が定数(例えば 5)や、ベースの x が不明であるということです:&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;do_pe&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;], &lt;span style="color: #003333"&gt;LR&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #003333"&gt;LR&lt;/span&gt; &lt;span style="color: #555555"&gt;=&lt;/span&gt; &lt;span style="color: #CC3300"&gt;power1&lt;/span&gt;.&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;このようなリストのコードが生成されます。&lt;br /&gt;&lt;br /&gt;&lt;div class="highlight" style="background: #f0f3f3"&gt;&lt;pre style="line-height: 125%"&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;listing&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;code_cache&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;power1&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;5&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;res&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;power_rec1&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;4&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;power_rec2&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;3&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;power_rec3&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;2&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;power_rec4&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;power_rec5&lt;/span&gt;).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;code_cache&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_done&lt;/span&gt;, [&lt;span style="color: #CC3300"&gt;y&lt;/span&gt;&lt;span style="color: #555555"&gt;/&lt;/span&gt;&lt;span style="color: #FF6600"&gt;0&lt;/span&gt;], &lt;span style="color: #CC3300"&gt;power_done1&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #CC3300"&gt;?-&lt;/span&gt; &lt;span style="color: #CC00FF"&gt;listing&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;block&lt;/span&gt;)&lt;br /&gt;.... &lt;span style="color: #CC3300"&gt;the&lt;/span&gt; &lt;span style="color: #CC3300"&gt;block&lt;/span&gt; &lt;span style="color: #CC3300"&gt;definition&lt;/span&gt; &lt;span style="color: #CC3300"&gt;of&lt;/span&gt; &lt;span style="color: #CC3300"&gt;the&lt;/span&gt; &lt;span style="color: #CC3300"&gt;user&lt;/span&gt; &lt;span style="color: #CC3300"&gt;program&lt;/span&gt; ....&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_done1&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;print_and_stop&lt;/span&gt;(&lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec5&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_done1&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec4&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec5&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec3&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec4&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec2&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec3&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec1&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;op2&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;res&lt;/span&gt;, &lt;span style="color: #CC3300"&gt;mul&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;const&lt;/span&gt;(&lt;span style="color: #FF6600"&gt;1&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;var&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;x&lt;/span&gt;), &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec2&lt;/span&gt;))).&lt;br /&gt;&lt;span style="color: #CC00FF"&gt;block&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power1&lt;/span&gt;, &lt;span style="color: #CC00FF"&gt;jump&lt;/span&gt;(&lt;span style="color: #CC3300"&gt;power_rec1&lt;/span&gt;)).&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;code_cache&lt;/span&gt; は、部分環境の下でどのオリジナルラベルがどの残留ラベルに対応するかを教えてくれます。従って、y が 5 であるという想定のもとで &lt;span style="font-style:italic;"&gt;power1&lt;/span&gt; が &lt;span style="font-style:italic;"&gt;power&lt;/span&gt; のコードに含まれます。リストのブロックを見ると、 &lt;span style="font-style:italic;"&gt;power1&lt;/span&gt; というラベルは x を全く使用せずに、単純に 5 回 x を掛けるコード対応します。オリジナルのプログラムではループであったものは、完全に展開されてループ変数の y は消えてしまいました。うまくいけばこれはオリジナルのプログラムよりも速くなります。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;結論&lt;/h2&gt;&lt;br /&gt;このブログのポストで見たものは、 Prolog で作られたシンプルな Flow Graph 言語のインタプリタと、その部分評価器です。部分評価器は、本質的にはインタプリタのあらゆるルールを複製します。もし全ての処理中の引数が全て分かっているならば、それはインタプリタのように振る舞います。そうでなければ単純に残留コードに演算をコピーするだけです。&lt;br /&gt;&lt;br /&gt;部分評価は様々なアプリケションに利用できますが、最もよく引用されて適用されるるものの一つはインタプリタです。インタプリタが走らせるプログラムは部分評価器によって定数とみなされます。したがって、特殊化されたバージョンのインタプリタは入力するプログラムを全く使用せずに生成されます。残留コードは入力プログラムのコンパイルされたバージョンであるとみなせます。&lt;br /&gt;&lt;br /&gt;このシリーズの次のブログポストでは、同じ FlowGraph 言語の単純なトレーサを書いてみます。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-7113064041439232055?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/7113064041439232055/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2012/01/part-1.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/7113064041439232055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/7113064041439232055'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2012/01/part-1.html' title='部分評価とトレーシングの比較 Part 1'/><author><name>shoma</name><uri>http://www.blogger.com/profile/17043127701763147055</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-6659834644256665079</id><published>2011-12-09T07:41:00.002+09:00</published><updated>2011-12-09T07:46:57.709+09:00</updated><title type='text'>PyPy 1.7 on Win32</title><content type='html'>原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/11/pypy-17-on-win32.html"&gt;PyPy 1.7 on Win32&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;やぁ、みんな！&lt;br /&gt;&lt;br /&gt;We have fixed _continuation on Win32 (thanks Stakkars), and so we have now a Win32 version of PyPy 1.7.&lt;br /&gt;&lt;br /&gt;私はWin32の&lt;a href="http://doc.pypy.org/en/latest/stackless.html"&gt;_continuation&lt;/a&gt;を完了する（ありがとうStakkars）とともに、Win32版の&lt;a href="http://pypy.org/download.html"&gt;PyPy 1.7&lt;/a&gt;をリリースしました。&lt;br /&gt;&lt;br /&gt;（原文：Posted by Armin Rigo）&lt;br /&gt;（翻訳：Tohru Ike）&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-6659834644256665079?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/6659834644256665079/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/12/pypy-17-on-win32.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/6659834644256665079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/6659834644256665079'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/12/pypy-17-on-win32.html' title='PyPy 1.7 on Win32'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-8278314981071007074</id><published>2011-11-21T23:02:00.010+09:00</published><updated>2011-11-22T01:27:03.708+09:00</updated><title type='text'>PyPy 1.7 - スイートスポットの拡大</title><content type='html'>&lt;p&gt;原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/11/pypy-17-widening-sweet-spot.html"&gt;PyPy 1.7 - widening the sweet spot&lt;/a&gt;&lt;/p&gt;&lt;p&gt;PyPy 1.7のリリースをアナウンスできることを嬉しく思います。バージョン1.6から、いつも通り多くのバグフィックスとパフォーマンスの改善が行われました。しかしながら、以前のバージョンとは異なり、このバージョンではPyPyの"スイートスポットの拡大"に焦点を当てています。すなわち、PyPyによって高速化できるPythonコードのクラスの幅がとても広がりました。PyPy 1.7はこちらからダウンロードできます。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;a href="http://pypy.org/download.html"&gt;http://pypy.org/download.html&lt;/a&gt;&lt;/blockquote&gt;&lt;h3&gt;PyPyとはなにか&lt;/h3&gt;&lt;p&gt;PyPyはとても素直なPythonインタプリタで、CPython 2.7とほぼ完全な互換性があります。トレーシングJITを採用したことで高速化を実現しました（pypy 1.7とCPython 2.7.1の性能比較は&lt;a href="http://speed.pypy.org/"&gt;こちら&lt;/a&gt;）。&lt;/p&gt;&lt;p&gt;このリリースは、x86上で動作するLinux 32/64、Mac OS X 32/64、Windows 32をサポートしています。Windows 64は現在作業中ですが、ネイティブではサポートされません。&lt;/p&gt;&lt;p&gt;このリリースのメイントピックは、PyPyが高速化できるコードの幅が広がったことにあります。我々のベンチマークによれば、PyPy 1.7はPyPy1.6と比較して平均して30％以上、いくつかのベンチマークでは20倍以上高速化しています。&lt;/p&gt;&lt;h3&gt;ハイライト&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;多くのパフォーマンスの改善。例を上げればキリがないほど高速化された部分があります。&lt;/li&gt;&lt;li&gt;バグフィックスと、CPythonとの互換性の確保。&lt;/li&gt;&lt;li&gt;Windowsにおける修正&lt;/li&gt;&lt;li&gt;デフォルトでスタックレスを実現しました。しかしながら、多くループはJITに割り込んでしまいます。ですから、スタックレスを基礎としたプログラムの高速化は実現していません。この制約を取り除くための情報がありましたらpypy-devまでコンタクトしてください。&lt;/li&gt;&lt;li&gt;PyPyにおけるNumPyの名称がnumpypyに変更されました。numpypyを試すためには、シンプルに、import numpypy as numpy と、プログラムの始めに記述してください。PyPyのnumpyは1.6と比較して飛躍的に進化しています。主な特徴はdtypeの実装にあります。&lt;/li&gt;&lt;li&gt;JSONのエンコーダが新しいものに置き換わっています（デコーダではありません）。これはPure Pythonで書かれていますが、CPythonのC拡張を用いたものと比較して、いくつかのケースで2倍高速になっています。これはPyPy 1.6と比較すると20倍以上高速化しています。&lt;/li&gt;&lt;li&gt;RPythonモジュールにおけるメモリのフットプリントがいくつか改善されています。これは暗号やtornadoなどにおいてインパクトがあります。&lt;/li&gt;&lt;li&gt;cpyextで動くCPython C APIにおいてさらなる進展がありました。&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;まだ完成していないが、1.8において期待される事項&lt;/h3&gt;&lt;p&gt;このリリースでは完成しなかったが、次のリリース 1.8において期待してよいかもしれないこと（これはここで書くべきではないかもしれませんが）。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;リストの特別な実装。整数／浮動小数／文字列のリストにおいて、array.arrayと同様のコンパクトな実装のブランチがあります。いくつかの応用において、パフォーマンス／メモリ使用量の劇的な改善が見込まれます。&lt;/li&gt;&lt;li&gt;NumPyにおいて進行中の成果。多次元配列はすぐ実現するでしょう。&lt;/li&gt;&lt;li&gt;ふたつの新しいJITアセンブラのバックエンドがあります。PowerPCとARM向けのものです。&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;資金調達&lt;/h3&gt;&lt;p&gt;ここで触れるべきことではないかもしれませんが、PyPyにおけるNumPyとPython 3のプロジェクトにおいて資金調達のキャンペーンが行われています。この件について素早く情報が欲しいかたは、&lt;a href="http://pypy.org/numpydonate.html"&gt;numpy proposal&lt;/a&gt;や&lt;a href="http://pypy.org/py3donate.html"&gt;py3k proposal&lt;/a&gt;をご覧ください。PyPyの進捗に関心があり、全体としての方向性に信頼をおいているならば、&lt;a href="http://pypy.org/"&gt;genral pot&lt;/a&gt;への寄付もご検討ください（寄付は常に受け入れています）。&lt;/p&gt;&lt;p&gt;Cheers,&lt;/p&gt;&lt;p&gt;Maciej Fijałkowki, Armin Rigo and the entire PyPy team&lt;/p&gt;&lt;p&gt;（原文：Posted by Maciej Fijalkowski）&lt;/p&gt;&lt;p&gt;（翻訳：Kentaro Iizuka）&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-8278314981071007074?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/8278314981071007074/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/11/pypy-17.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/8278314981071007074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/8278314981071007074'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/11/pypy-17.html' title='PyPy 1.7 - スイートスポットの拡大'/><author><name>Kentaro Iizuka</name><uri>http://www.blogger.com/profile/12768512360137681962</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/-2g9tI6PchUs/TspKgXds59I/AAAAAAAAAN8/YHxrkz0SGCg/s220/IMG_0288.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-998003987967594313</id><published>2011-09-04T18:52:00.002+09:00</published><updated>2011-12-09T07:47:32.689+09:00</updated><title type='text'>ソフトウェアトランザクショナルメモリが必要です。</title><content type='html'>原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/08/we-need-software-transactional-memory.html"&gt;We need Software Transactional Memory&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hi、みんな。ここはPythonやPythonnoような言語の実装における、現時点のソフトウェアトランザクショナルメモリについての論文の短い要約（抽出物）です。&lt;br /&gt;&lt;br /&gt;このブログ記事をより良くしてくれたIRCの人々(lucian, Alex Gaynor, rguillebert, timonator, Da_Blitz)に感謝します。&lt;br /&gt;現在の議論の目的のために、私たちはPythonとJavaのマルチスレッド化を比べています。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;複雑なハイレベル言語における問題&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Javaのように、Python言語は保証します:  Python仮想マシンはスレッドの誤った使用が原因でクラッシュすることは受け入れられません。&lt;br /&gt;Javaのプリミティブ操作は、フィールドのオブジェクトフィールドを読み書きするようなものです; 対応する保証は、方針に沿っています。&lt;br /&gt;プログラムがオブジェクトのフィールドを読み取り、別のスレッドが同じオブジェクトの同じフィールドに書き込む時、プログラムは、古い値または新しい値を参照するでしょう。&lt;br /&gt;しかし、全く違った値ではなく、仮想マシンはクラッシュしません。Pythonのような高級言語は、"プリミティブな操作"は、はるかに複雑であるという事実があるため、Javaとは異なります。&lt;br /&gt;それは例えば、いくつかのハッシュマップでおそらくアップデートを行って見られるかもしれません。&lt;br /&gt;一般的には、それはすべての操作をシングルプロセッサの命令にアトミックに必ずし、完全にマップするのは不可能である。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;JYTHON: きめ細かいロック&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;この問題はJavaの上で動作するJythonインタプリタでは"明示的に"解決されています。&lt;br /&gt;解決策は次の文の通り明示的です：Jythonインタプリタ全体を通して、一つ一つの操作は、Javaレベルのロックメカニズムを慎重に利用しています。これは、"きめ細かいロック"のアプリケーションです。例えば、属性をハッシュマップの数だけ参照する操作はロック（__getattribute__における）の獲得と解放により保護されています。&lt;br /&gt;&lt;br /&gt;このソリューションの引っ込めは、必要な細部へのこだわりです。一箇所でもロックをミスしたのであれば、いずれかのバグがあります。 --- このようなバグは、以前のバグが修正されているようにデバッグするため、ますますまれにしか起こらず困難なケースで発生します  ---&lt;br /&gt;&lt;br /&gt;また、私たちは"CPythonとの違い"のもとでそれを適正に保存します。しかしながら、二つのスレッドが異なる順序で同じオブジェクトをロックしようとすると、デッドロックの危険性があります。実際には、予想に反して私が手書きするほど悪い状態ではありません。Jythonにおけるロックの数は適切であり、そして、期待どおりに動作するすべての"一般的なケース"が可能になります。（稀なケースは、以下を参照してください。）&lt;br /&gt;&lt;br /&gt;性能面では、Java仮想マシン自体は、長期間にわたって猛烈な最適化されているロックが付&lt;br /&gt;属しています。&lt;br /&gt;しかしながらCでコーディングされたソリューションの場合は、手動でロックを最適化するために余分な作業が多く必要になります（多くのバグを含んでしまうだろう）。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;CPYTHON: きめのあらいロック&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;CPython、C言語によるPythonの標準実装では異なる単純なアプローチを取った：それはシングルグローバルロックを持ち、グローバルインタプリタロック（GIL）と呼ばれる。&lt;br /&gt;それは"きめのあらいロック"を使用しています: ロックは、全体の実行であっちこっちにある1つのバイトコードが取得されて、リリースされます（実際に100のような少ない数のバイトコード）。それらを呼び出す複数バイトコードはGILで自分自身をシリアライズされるので、この解決策は、2つの操作が互いに競合しないことを保証するのに十分です。それは、インタプリタ全体にわたって慎重なロックを獲得するコードを書くのを避ける --- Jythonとは異なった ---解決策です。また、より強い保証を提供しています：すべてのバイトコードは、アトミックに完全に実行されます。&lt;br /&gt;&lt;br /&gt;今日において、GILのアプローチの引き戻しは、マルチコアマシン上では明白です：複数のスレッドを開始し、バイトコードの実行をシリアル化することによって、実際には複数のコアのインタプリタの使用を許可しません。&lt;br /&gt;&lt;br /&gt;PyPy、PythonによるPythonの実装では、これまでと同じアプローチを採用しています。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;現在の処理&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;これまで見てきたように、我々は次のような解決策：既存のPython言語、CPython実装は、マルチスレッドの使用状況についての非常に強い保証を提供しています。&lt;br /&gt;それは、ほとんどの既存のマルチスレッドのPythonプログラムが実際にそのような強い保証に頼ることは重要であると強調する。&lt;br /&gt;これは、人口のリストを受け取り、いくつかのスレッドで行う問題の例で見ることができます:&lt;br /&gt;&lt;br /&gt;next_item = global_list.pop()&lt;br /&gt;&lt;br /&gt;これは、暗黙的にpop()がリストからアトミックの除去を実行するという事実を当てにしています。&lt;br /&gt;二つのスレッドが同時に同じリストからポップしようとすると、2つの操作は、ある順序または別で発生します。&lt;br /&gt;しかし、それらは例えば、両方のスレッドへ同じオブジェクトを返すか、リストオブジェクトの内部状態までぶち壊します。&lt;br /&gt;&lt;br /&gt;このような例を念頭に置いて、私たちはこれらのマルチコア問題を含む強力な保証を落とす解決策を望んでいないことは明らかです。&lt;br /&gt;しかしながらJythonがそうするように障壁を下げるのは、間違いありません; しかし、いくつかのPython実装は、いくつかの保証を提供しなくてはいけません、または、マルチスレッド化を全く提供してはいけません。&lt;br /&gt;これは、組み込み型のメソッドの多くがアトミックであるという事実が含まれています。&lt;br /&gt;&lt;br /&gt;(それは、全てにおいてマルチスレッドを提供していないことも実際にはまた、（部分的な）問題の解決策であることに留意すべきです。&lt;br /&gt;最近、いくつかの"ハック"は、多かれ少なかれ透過的なアクセスし複数の独立したプロセス (e.g. &lt;a href="http://docs.python.org/library/multiprocessing.html"&gt;multiprocessing&lt;/a&gt;).をプログラマに与えることが明らかです。&lt;br /&gt;これらはいくつかのコンテキストで適切な解決策を提供するわけだが、マルチスレッドのように広く適用されません。&lt;br /&gt;典型的な例として、それらは、複数のコアが、全くシリアライズできない情報を処理する必要があるとき適用しません。&lt;br /&gt;--- いくつかのプロセス間における、いかなるデータ交換の要件。)&lt;br /&gt;&lt;br /&gt;ここに、Jythonの一貫性がCPythonのGILよりどう弱いかの例があります。&lt;br /&gt;それを示しているのに一般的でない例を要しており、CPythonのようなプログラマがそれらを予想するどんな仕事もせず、一般的に、実装の詳細として考えられている。&lt;br /&gt;考察:&lt;br /&gt;&lt;br /&gt;Thread 1:  set1.update(set2)&lt;br /&gt;Thread 2:  set2.update(set3)&lt;br /&gt;Thread 3:  set3.update(set1)&lt;br /&gt;&lt;br /&gt;各操作はCPythonの場合にはアトミックです。&lt;br /&gt;しかし、Jythonの場合は、次の2つの手順（各々は、アトミックとみなすことができる）に分けられる：引数から読み取り、そして、対象のsetを更新する。&lt;br /&gt;最初にset1 = {1}, set2 = {2}, set3 = {3} を行うとします。CPythonにおいて、独立したスレッドの実行順序の結果、最も小さなset {1, 2, 3} になります。&lt;br /&gt;Jythonにおいて、すべての3つのsetが2つだけの要素を含むだけで終わっている可能性があります。&lt;br /&gt;例は、少しこじつけですが、CPythonとの一貫性はJythonのより厳密に強くなって表示されるべきです。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;PYPY&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;PyPyはCPythonやJythonに非常に似たPythonインタプリタです。しかし、生成方法は独特です。&lt;br /&gt;それはPythonのサブセットであるRPythonで書かれたインタプリタであり、自動的に"翻訳"と呼ばれる段階で完全な仮想マシン（Cのコードを生成）になって手に入ります。&lt;br /&gt;このコンテキストでは、CPythonとJythonのコンテキストはは異なります: PyPyではまったくもって簡単に、"翻訳時"にインタプリタへ任意のプログラム全体の変換を適用することが可能です。&lt;br /&gt;&lt;br /&gt;この点を考慮し、インタプリタによってRPythonで操作の全オブジェクトにロックを追加し、プログラム全体の変換を想像することは可能です。&lt;br /&gt;これはJythonと同様な状況として終わるでしょう。&lt;br /&gt;しかしながら、それは慎重な手動配置でのロックがJythonの場合は回避され、デッドロックの問題が自動的に解決するとはなりません。&lt;br /&gt;（実際には、デッドロックフリーであることは自動的に確保、検証できないグローバルプログラムのプロパティです;&lt;br /&gt;いくらかのJythonの変更は、理論的にはこのプロパティを破るため、巧妙なデッドロックを導入することができます。&lt;br /&gt;同じことが、ノンアトミックに適用されます。）&lt;br /&gt;&lt;br /&gt;実際には、もし、インタプリタがスレッド1のバイトコードでAとB、およびスレッド2のバイトコードでBとA(反対の順序)に（読み取りおよび書き込みの両方の）アクセスした場合、私たちは簡単にそれを確認することができ、&lt;br /&gt;--- また、あなたが2番目のオブジェクトにアクセスする必要がある、と決める前に最初のオブジェクトにアクセスしている必要があります。 ---&lt;br /&gt;その時、アトミック性の強い保証を維持しながらデッドロックを（GILから離れて）回避する方法はありません。&lt;br /&gt;確かに、両方のスレッドがそのバイトコードの実行の途中に進行した場合は、既にスレッド1によって変更されており、同様にBは既にスレッド2によって変更されています。&lt;br /&gt;その場合、うまくスレッドを実行し続けるのは、可能ではありません。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;USING SOFTWARE TRANSACTIONAL MEMORY&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;ソフトウェアトランザクショナルメモリ(STM)は、明らかに上述の問題に解決策をもたらすアプローチです。&lt;br /&gt;実行し続けるどこのスレッドが間違った状況で終わった場合、私たちは、中断しロールバックすることができます。&lt;br /&gt;これは、データベースのトランザクションの概念と似ています。&lt;br /&gt;上述の例において、一方または両方のスレッドは、トラブルや中断を実行しようとしていることがわかります。&lt;br /&gt;これは、彼らはこれまでに中止または単にまだコミットされていないものすべての副作用において、バイトコードの先頭で実行を再開する方法を持っている必要があることをより、具体的に意味しています。&lt;br /&gt;&lt;br /&gt;私たちは、中断してロールバックする能力はPythonのマルチスレッド実装に欠けているパズルのピースだと考えています。&lt;br /&gt;実際に、上記の問題のプレゼンテーションによれば、それはCPythonの一貫性とアトミック性の同じレベルを提供したすべての解決策は、中断とロールバックの容量を伴うことは避けられないです。--- これは正確にそのSTMを避けることができないことを意味します。&lt;br /&gt;&lt;br /&gt;OK、しかしなぜJythonのアプローチで落ち着いて、インタプリタを通して左右の慎重なロックをかけないのか？&lt;br /&gt;（1）私たちは、すべての操作のアトミック性を考慮し、決定を確認する（またはJythonのを盗む）必要がありますし、それらを&lt;a href="http://doc.pypy.org/en/latest/cpython_differences.html"&gt;ここ&lt;/a&gt;に文書化します;&lt;br /&gt;（2）それはまた、これらのロックを最適化するために、本当に多くの作業となります。e.g. JITのみならずJVMが行うことと同様に;&lt;br /&gt;（3）それは直交すべき機能のどこにでも手動で微調整するコードを必要とし、それはPyPyの方法ではありません;&lt;br /&gt;（3）はおそらくここで最も重要です：あなたはPyPyで実装する言語ごとに作業をやり直す必要があります。&lt;br /&gt;私自身もまたポイント（4）を意味する：それは楽いことではない :-)&lt;br /&gt;&lt;br /&gt;詳細であるが、次のようにプロセスは働くだろう。&lt;br /&gt;（これは、1つの可能なモデルの概要を説明します; 異なったモデルがより良くなることは確実です。）すべてのスレッドで:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;バイトコードの開始時に、私たちは"トランザクション"を起動します。これは、トランザクションで発生するログを記録するために、スレッドローカルなデータ構造を設定することを意味します。&lt;/li&gt;&lt;li&gt;私たちは、ログに読み込まれるすべてのオブジェクトを、行いたい変更と同様に記録します。&lt;/li&gt;&lt;li&gt;この時間の間に、私たちは"読み取り"の不整合を検出し、現在のトランザクションの開始時間より遅いオブジェクトの"最終修正"タイムスタンプによって証明し、また中断する。&lt;/li&gt;&lt;li&gt;これは、コードの残りの部分が矛盾した値とともに実行されるのを防ぐことができます。&lt;/li&gt;&lt;li&gt;私たちは"読み取り"矛盾なくバイトコードの最後に到達した場合は、私たちは、アトミックに"書き込み"の不整合を確認してください。&lt;/li&gt;&lt;li&gt;これらは、他のスレッド内のオブジェクトへの同時更新から生じる矛盾です。---「書き込み」という私たちのオブジェクトか「読み込み」という私たちのオブジェクトのどちらか&lt;/li&gt;&lt;li&gt;不一致がまったく見つからない場合、私たちは、トランザクションを遅延をコピーすることによって、メインメモリにログから書き込み、"コミット"します。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;どれの取引が始まるか、終わりがまさにポイントであるか指す、どれですか?&lt;br /&gt;トランザクションが開始または終了するポイントは正確なポイントで、CPythonでは、グローバルインタプリタロックは、それぞれ取得され、解放されます。&lt;br /&gt;&lt;br /&gt;私たちであれば(純粋に性能のために)CPythonがGILを取得して、Nバイトコードごとにリリースするという事実を無視してください。その時これを意味しています。&lt;br /&gt;&lt;ol&gt;&lt;li&gt;私たちは、任意のバイトコードの前にGILを（トランザクションを開始する）を取得し、バイトコードの後に私たちは、それ（トランザクションを終了する）を放します; そして&lt;/li&gt;&lt;li&gt;CライブラリやOSへの外部呼び出しを行う前に、私たちは、GIL（トランザクションを終了する）を放し、その後のそれ（次のトランザクションを開始する）を再取得します&lt;/li&gt;&lt;/ol&gt;特にこのモデルは、システムコールと同様に、私たちは --- まさに --- システムコールのようにロールバックすることができないトランザクション以外に何もできず、STMの条件に適しています。&lt;br /&gt;確かに、構造によって、CPythonではそれらはGILの解放で発生するため、これらのシステムコールはトランザクションの外で発生します。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;PERFORMANCE&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;今のところ、多くの詳細な実装はまだ未解決です。&lt;br /&gt;ユーザーの観点（i.e. Pythonを使用してプログラマ）から、最も関連しているものは総合的なパフォーマンスの影響です。&lt;br /&gt;私たちは、これまで正確な数値を与えることはできず、また、初期性能がものすごく悪いと予想しています。（10倍遅いかもしれない）;&lt;br /&gt;しかしながら、ロック機構、ロックを挿入するグルーバルプログラムの変換、ガーベージコレクション（GC）、ジャストインタイムコンパイラ（JIT）への連続な改善において、私たちはそれがほぼ妥当なパフォーマンス（たぶん、最大2倍遅い）を得ることが可能であると信じています。&lt;br /&gt;例えば、GCは発生したスレッドから漏れることなくオブジェクト上のフラグを保持する。&lt;br /&gt;私たちは、これらが多くの失われた性能を取り戻すことができる最適化の一種であると信じています。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;THE STATE OF STM&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;トランザクショナルメモリは、Tom Knightにより1986年の論文で配信され、それ自体は比較的古い考え方です。&lt;br /&gt;最初はハードウェアサポート、1995年に大衆化されたソフトウェアのみのトランザクショナルメモリ（STM）の考え方に基づいており、最近では集中的な研究の焦点となっています。&lt;br /&gt;&lt;br /&gt;上記で説明したアプローチ --- 言語の実装の中核を形成するためにSTMを使用 --- は、私たちの知る限り、新しいです。&lt;br /&gt;これまでのところ、ほとんどの実装ではライブラリの機能として、STMを提供しています。&lt;br /&gt;&lt;br /&gt;それは明示的に使用する必要があります。多くの場合、オブジェクトは、STMによって保護されている必要があり、明示的に宣言の形態であってもよい（オブジェクトベースTSTMs）。&lt;br /&gt;STMのネイティブサポートがClojure言語で特に現れ始めたのは最近のことです。&lt;br /&gt;&lt;br /&gt;STMは、アプローチとして、Wikipediaに "大幅にマルチスレッドプログラムの概念的な理解を簡素化し、そのようなオブジェクトやモジュールなど既存の高レベルな抽象化と調和して働くことによって、プログラムのメンテナンス性の向上に役立ちます。" と記載されています。&lt;br /&gt;私たちは実際に、これらの利点は、内部的に使用されているだけでなく、同様にPythonプログラマに公開されているほど重要であると考えています。&lt;br /&gt;&lt;br /&gt;これは、Pythonプログラマは非常にシンプルなインターフェイスを与えるだろう:&lt;br /&gt;&lt;br /&gt;with atomic:&lt;br /&gt;   &amp;lt;これらの操作はアトミックに実行されます&amp;gt;&lt;br /&gt;&lt;br /&gt;（これは&lt;a href="http://mail.python.org/pipermail/python-dev/2003-February/033259.html"&gt;古い考え方&lt;/a&gt;です。私を含め2003人の人々はこれを面白いハックだと考えました。&lt;br /&gt;いま私がブログ記事を書き、"それはハックではなかった、それは明確にハックされたロックを使用している。"と主張します。私は、&lt;a href="http://en.wikipedia.org/wiki/Software_transactional_memory#Composable_operations"&gt;composability&lt;/a&gt;のアイデアを買っています。）&lt;br /&gt;&lt;br /&gt;実用的な観点から、私はロチェスター大学STM（RSTM）において、最近の研究の焦点となっているC++ライブラリ --- と結果のコレクション --- を真剣に探し始めた。&lt;br /&gt;特に代表的な論文の一つが、Michael F. Spear、Luke Dalessandro、Virendra J. MaratheとMichael L. Scottによる&lt;br /&gt;&lt;a href="http://www.cs.rochester.edu/u/spear/ppopp09.pdf"&gt;A Comprehensive Strategy for Contention Management in Software Transactional Memory&lt;/a&gt;です。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;CONCLUSION&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;これらのアイデアを取り、Pythonのような複雑な高水準言語の実装のコンテキストでこれらを適用すると、独自な難問が出てきます。&lt;br /&gt;このコンテキストでは、PyPyを使用することは、実験プラットフォーム、また最近ではそのパフォーマンスのために注目されているプラットフォームにおいて道理にかなっています。&lt;br /&gt;代替手段は興味ありません：例えばCPythonのでそれを行うと、グローバルインタプリタを書き換えることを意味します。&lt;br /&gt;PyPyは代わりに、私たちは翻訳時に体系的に適用される変換としてそれを書きます。&lt;br /&gt;また、PyPyは動的言語のために高速なインタプリタを生成するための一般的なプラットフォームです; PyPyにおいてSTMの実装だけではなく、同様にPython用だけではなく、他の言語の実装のために、Pythonの制約から抜け出して動作します。&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;&lt;br /&gt;これはほとんど私（Armin Rigo）が声を出して暴れる実験をしています; PyPyチーム全体が現在それに取り組むために、次の数年をフルタイムで費やすことを意味する記事と混同するべきではありません。&lt;br /&gt;私が述べたようにそれは実際のPythonインタプリタに直交しており、それはいかなる場合でも、翻訳時にオンまたはオフにすることができる機能です;&lt;br /&gt;私が知っている多くのまたはほとんどのユースケースでは、人々は2倍遅くしかしスケールするものより、むしろ速いPyPyに興味を持ち、手に入れたいと考えています。&lt;br /&gt;私が言ったものはまったく本当に新しくありません。&lt;br /&gt;証明のため、&lt;a href="http://sabi.net/nriley/pubs/dls6-riley.pdf"&gt;Riley and Zilles (2006)&lt;/a&gt;と&lt;a href="http://www.cs.auckland.ac.nz/~fuad/parpycan.pdf"&gt;Tabba (2010) &lt;/a&gt;の両方は、私がここで説明したように、開始/終了のトランザクションにCPythonのかPyPyインタプリタのGILを回し、ハードウェアトランザクショナルメモリを試したので、参照して下さい。&lt;br /&gt;&lt;br /&gt;（原文：Posted by Armin Rigo）&lt;br /&gt;（翻訳：Tohru Ike）&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-998003987967594313?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/998003987967594313/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/09/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/998003987967594313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/998003987967594313'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/09/blog-post.html' title='ソフトウェアトランザクショナルメモリが必要です。'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-4518421773328446321</id><published>2011-08-19T11:12:00.006+09:00</published><updated>2011-12-09T07:47:50.039+09:00</updated><title type='text'>PyPy 1.6 - kickass panda</title><content type='html'>原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/08/pypy-16-kickass-panda.html"&gt;PyPy 1.6 - kickass panda&lt;/a&gt;&lt;br /&gt;&lt;p&gt;私たちは、PyPy1.6のリリースを発表できることを嬉しく思います。このリリースでは、多くのバグ修正と1.5以上のパフォーマンスの向上をもたらし、Windows32とOS X 64bitのサポートの向上をします。このバージョンでは、Python2.7.1を完全に実装し、CPythonのC拡張読み込みをベータレベルサポートしています。ここからダウンロードできます。&lt;/p&gt;&lt;p&gt;&lt;a class="reference external" a="" href="http://pypy.org/download.html"&gt;http://pypy.org/download.html&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;PyPyとは？&lt;/h3&gt;&lt;p&gt;PyPyは、非常に準拠しているPythonインタプリタであり、ほぼ、簡単にCPython2.7.1を代替できます。それはトレーシングJITコンパイラを統合しているため、高速です。（&lt;a href="http://speed.pypy.org/"&gt;pypy1.6とCPython2.6.2のパフォーマンス比較&lt;/a&gt;）&lt;/p&gt;&lt;p&gt;このリリースでは、x86マシンで実行しているLinuxの64/32または、Mac OS Xがサポートされています。Windows 32はベータです（ほぼ動作しますが、多くの小さな問題はこれまで修正されていません）&lt;/p&gt;&lt;p&gt;このリリースの主なトピックは、スピードと安定性です: 私たちのベンチマークスイートの平均において、PyPy1.6は既に私たちのベンチマークではCPythonより高速なPyPy1.5より&lt;strong&gt;20%から30%&lt;/strong&gt;速いです。&lt;/p&gt;&lt;p&gt;速度の改善はPyPyを構成する多くの層を最適化することで実現しました。&lt;br /&gt;とりわけ、私たちはガーベージコレクタ、JITのウォームアップ時間、JITによって実行される最適化、生成されたマシンコードの品質とPythonインタプリタの実装を改善しました。&lt;/p&gt;&lt;h3&gt;ハイライト&lt;/h3&gt;&lt;ul class="simple"&gt;&lt;li&gt;多数のパフォーマンス向上は、全体にかなりのスピードアップをもたらします:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;非常に大きなオブジェクトや配列を扱う時のGCの振る舞い。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;fast ctypes:&lt;/strong&gt;現在呼ばれるctypes関数はJITによって最適化され、PyPy1.5より60倍高速で、CPythonより10倍高速である。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ジェネレータの改良(1): 単純なジェネレータは現在、ループ呼出しをインライン展開しており、PyPy1.5より3.5倍高速化し、パフォーマンスアップしました。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ジェネレータの改良(2): 他の最適化のおかげで、ジェネレータはインライン化されてなくともPyPy1.5より10%から20%速いです。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;JITの高速なウォームアップ時間。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;single floatのJITサポート (e.g., for &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;array('f')&lt;/span&gt;&lt;/tt&gt;)。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;最適化された辞書: 辞書の内部表現は、現在、動的に保存されているオブジェクトの種類に応じて適宜選択します。高速なコードと小さなメモリフットプリントの結果です。例えば、キーがすべて文字列、またはすべて整数である辞書。 他の辞書でもバグ修正のため、より小さくなります。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;これはあなたのPythonコードがJITによってコンパイルされアセンブリまで落とし込まれたものを確認するウェブベースツールであるJitViewerを含む最初の公式リリースです。&lt;br /&gt;&lt;a class="reference external" href="http://morepypy.blogspot.com/2011/08/visualization-of-jitted-code.html"&gt;jitviewer&lt;/a&gt; 0.1は既にリリースされておりPyPy1.6でうまく動いています。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;CPythonの拡張モジュールAPIが改善され、より多くの拡張機能をサポートしています。何がサポートされているかの情報については、私たちの&lt;a class="reference external" href="https://bitbucket.org/pypy/compatibility/wiki/Home"&gt;互換性wiki&lt;/a&gt;を参照してください。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;マルチバイトエンコーディングのサポート：これはCPythonが原因となって残っていた最後の領域でした。しかし、今私たちはそれを完全にサポートしています。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;numpyのための準備的サポート：このリリースでは、PyPy JITと統合された非常に高速なnumpyのモジュールのプレビューが含まれています。残念ながら、これは、あなたが既存のnumpyのプログラムを作って、PyPyでそれの実行を期待できるということを意味するものではありません。なぜならば、モジュールはまだ未完成であり、numpyAPIのいくつかをサポートしているためです。しかしながら、いくつかの詳細を除いて、その仕組は非常に高速でなければなりません:-)&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;バグ修正:  1.5リリース以来、私たちは&lt;a class="reference external" href="https://bugs.pypy.org/"&gt;バグトラッカー&lt;/a&gt;にある53のバグを修正しました。私たちが発見し、バグトラッカー以外の経路を介して報告された多くののバグはカウントしていません。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;喝采を贈る&lt;/p&gt;&lt;p&gt;Hakan Ardo, Carl Friedrich Bolz, Laura Creighton, Antonio Cuni, Maciej Fijalkowski, Amaury Forgeot d'Arc, Alex Gaynor, Armin Rigo とPyPyチームへ&lt;/p&gt;&lt;p&gt;（原文：Posted by Maciej Fijalkowski）&lt;/p&gt;&lt;br /&gt;（翻訳：Tohru Ike）&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-4518421773328446321?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/4518421773328446321/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/08/pypy-16-kickass-panda.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/4518421773328446321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/4518421773328446321'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/08/pypy-16-kickass-panda.html' title='PyPy 1.6 - kickass panda'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-473358222244270287</id><published>2011-08-15T00:16:00.008+09:00</published><updated>2011-08-15T09:10:34.755+09:00</updated><title type='text'>JITされたコードの視覚化</title><content type='html'>原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/08/visualization-of-jitted-code.html"&gt;Visualization of JITted code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;こんにちわ。&lt;br /&gt;&lt;br /&gt;私たちはjitviewerの最初の公式リリースを発表できることを誇りに思います。&lt;br /&gt;現在のところ、jitviewerはPyPyのJITによってマシンコードにコンパイルされた&lt;br /&gt;Pythonソースコードの理解を助けるちょっとした内部ツールです。&lt;br /&gt;&lt;br /&gt;インストールするには、PyPyのごく最近のバージョン（8月9よりも新しい）、例えば、&lt;a href="http://buildbot.pypy.org/nightly/trunk/"&gt;ナイトリービルド&lt;/a&gt;のいずれかが必要です:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;pipとdistributeをインストールするまたは、PyPyで作られた&lt;a href="http://pypi.python.org/pypi/virtualenv"&gt;virtualenv&lt;/a&gt;か、次の述べる&lt;a href="http://doc.pypy.org/en/latest/getting-started.html#installing-pypy"&gt;installation instructions&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;PyPyのソースコードチェックアウトし、PYTHONPATHに確実に入れてください。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;pip install jitviewer。グローバルにインストールされたpipではなく、PyPyの管理下にあるpipを実行する必要があることに注意して下さい。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;jitviewerをはじめるには&lt;a href="http://bitbucket.org/pypy/jitviewer/src/24adc3403cd8/README"&gt;README&lt;/a&gt;を見るまたは、それをただ実行したいなら&lt;a href="http://wyvern.cs.uni-duesseldorf.de:5000/"&gt;オンラインデモ&lt;/a&gt;を試みてください。&lt;br /&gt;&lt;br /&gt;jitviewerはflaskとjinja2で書かれたWebアプリケーションです。&lt;br /&gt;ウェブ開発経験があって、PyPyを助けたいなら、私たちに遠慮無く連絡してください。PyPyを向上する多くのことがあります :-)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;本当のところjitviewerは何をするのでしょうか？&lt;/h3&gt;&lt;br /&gt;ページの上部には、JITでコンパイルされたコードの一部分のリストが表示されます。&lt;br /&gt;あなたは通常のループと"エントリブリッジ"の両方を確認することができます。ここでは、それらの違いについて議論する適当な場所ではありませんが、たぶんあなたは、通常はほとんどの時間が費やされている場所なので、ループをもっとも見たがっているでしょう。&lt;br /&gt;&lt;br /&gt;各ループにおいて、ループの&lt;strong&gt;最初&lt;/strong&gt;の命令を含んだ関数の名前が表示されることに注意してください。&lt;br /&gt;しかしながら、JITによって行われるインライン化のおかげで、それに他の関数のコードが含まれます。&lt;br /&gt;&lt;br /&gt;あなたがひとたびループを選択すると、jitviewerはJITがどのような階層的な方法でPythonソースコードをアセンブラにコンパイルしたのかを示します。それは4つのレベルで表示します:&lt;br /&gt;&lt;br /&gt;Pythonソースコード: 空色で示された行だけが、この特定のループのためにコンパイルされており、灰色のものはそうではありません。&lt;br /&gt;&lt;br /&gt;Pythonバイトコード, あなたが実行することによって得るもの:&lt;pre&gt;&lt;code&gt;def f(a, b):&lt;br /&gt;   return a + b&lt;br /&gt;import dis&lt;br /&gt;dis.dis(f)&lt;/code&gt;&lt;/pre&gt;命令コード(opcodes)は、例えば LOAD\_FAST, LOAD\_GLOBAL などです。&lt;br /&gt;太字になっていない命令コード(opcodes)は、完全にJITで常に最適化されています&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JITコードの中間表現(IR)。これは操作（整数加算のような、構造体のフィールド読み出し）とガード（私達の仮定が実際に真であることを確認する）の組合せです。ガードは赤色です。それらの操作は"Cと同じレベルで": そう、例えば、+は、CPUのレジスタに格納された2つのボックス化が解除された整数を取ります。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;アセンブラ: あなたは、右上メニューの"Show assembler"をクリックして、それを確認することができます。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;時に、ガードが頻繁に失敗し、アセンブラの新しい部分が呼ばれてコンパイルされた事がわかるでしょう。&lt;br /&gt;これはコードを通した迂回経路であり、そして、それはブリッジと呼ばれます。&lt;br /&gt;ガードの横にリンクがある時には、jitviewerでブリッジを見ることができます。&lt;br /&gt;&lt;br /&gt;詳しい情報の成果を得たいのであれば&lt;a href="http://doc.pypy.org/en/latest/jit/index.html"&gt;jit documentation&lt;/a&gt;を探して下さい。&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;いまだに混沌としています&lt;/h3&gt;&lt;br /&gt;私が現状について説明すると、Jitviewerは完全ではありません。&lt;br /&gt;あなたが、IRC上に現れたり、私たちのメーリングリストへメールを送ることは自由であり、また私たちはそれを説明し、解決策を改良するでしょう。&lt;br /&gt;詳細については、&lt;a href="http://pypy.org/contact.html"&gt;お問い合わせ&lt;/a&gt;のページを参照してください。&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;fijal &amp; antocuni&lt;br /&gt;&lt;br /&gt;（原文：Posted by Maciej Fijalkowski）&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-473358222244270287?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/473358222244270287/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/08/jit.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/473358222244270287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/473358222244270287'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/08/jit.html' title='JITされたコードの視覚化'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-3346108651632876532</id><published>2011-08-03T09:31:00.017+09:00</published><updated>2011-08-03T11:12:54.093+09:00</updated><title type='text'>PyPyはCより速い。あらためて：stringフォーマッティング</title><content type='html'>原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/08/pypy-is-faster-than-c-again-string.html"&gt;PyPy is faster than C, again: string formatting&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;stringフォーマッティングは、おそらくPythonであなたが通常することであり、あえて考えたりはしないでしょう。&lt;br /&gt;それはとても簡単で、まさに"%d %d" % (i, i)すれば完了です。&lt;br /&gt;結果のバッファをどのように測るかは考えません。あなたの出力の最後に適したNULLバイトを持っているようと、または他の細かい事があろうと。Cに相当するのは次のようになります：&lt;br /&gt;&lt;pre&gt;&lt;code&gt;char x[44];&lt;br /&gt;sprintf(x, "%d %d", i, i);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;２行目のところで立ち止まり、数がどれくらい大きくなるかもしれないかを考慮して、サイズを過大評価しなければならなかったことに注意してください。&lt;br /&gt;(44 = 64ビット上で最も大きい数の長さ(20) + 1 (符号のための) * 2 + 1 (空白のための) + 1 (NULバイト))&lt;br /&gt;この投稿の著者、fijalとalexはこの３つの計算の試みを異議なしで実現しました :-)&lt;br /&gt;&lt;br /&gt;この関数からxを返すことができない場合を除きすばらしいです。よりよい比較は次のようになります。&lt;br /&gt;&lt;pre&gt;&lt;code&gt;char *x = malloc(44 * sizeof(char));&lt;br /&gt;sprintf(x, "%d %d", i, i);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;xはいくらかの状況でわずかに過剰割り当てされますが、すばらしいです。&lt;br /&gt;&lt;br /&gt;しかし、ただstringフォーマッティングの実現について議論するために、私たちはここいるわけではなく、速いPyPyを明確に新たなunroll-if-altブランチとともに示し、議論するためにここにいます。Pythonは次のコードをもたらします：&lt;br /&gt;&lt;pre&gt;&lt;code&gt;def main():&lt;br /&gt;    for i in xrange(10000000):&lt;br /&gt;        "%d %d" % (i, i)&lt;br /&gt;&lt;br /&gt;main()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Cコード：&lt;pre&gt;&lt;code&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;    int i = 0;&lt;br /&gt;    char x[44];&lt;br /&gt;    for (i = 0; i &lt; 10000000; i++) {&lt;br /&gt;        sprintf(x, "%d %d", i, i);&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;PyPyのunroll-if-alt branchブランチのheadで実行し、コンパイルはGCC4.5.2 -O4（他の最適化レベルをテストし、これが最高のパフォーマンスをもたらした）。PyPyで実行すると&lt;strong&gt;0.85&lt;/strong&gt;秒、コンパイル済みのバイナリで実行すると&lt;strong&gt;1.63&lt;/strong&gt;秒かかりました。&lt;br /&gt;私たちはこれは動的コンパイルの信じられないほどの可能性を示すと考えおり、GCCはsprintfの呼び出しをインライン化またはアンロールすることができません。理由はlibcが内部に位置しているためです。&lt;br /&gt;&lt;br /&gt;Cのベンチマークコード：&lt;pre&gt;&lt;code&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;    int i = 0;&lt;br /&gt;    for (i = 0; i &lt; 10000000; i++) {&lt;br /&gt;        char *x = malloc(44 * sizeof(char));&lt;br /&gt;        sprintf(x, "%d %d", i, i);&lt;br /&gt;        free(x);&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;前に議論されたとおり、これはPythonに匹敵し、&lt;strong&gt;1.96&lt;/strong&gt;秒の結果が得られます。&lt;br /&gt;&lt;br /&gt;パフォーマンスの結論：&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Platform&lt;/th&gt;&lt;th&gt;GCC (stack)&lt;/th&gt;&lt;th&gt;GCC (malloc)&lt;/th&gt;&lt;th&gt;CPython&lt;/th&gt;&lt;th&gt;PyPy (unroll-if-alt)&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Time&lt;/th&gt;&lt;td&gt;1.63s&lt;/td&gt;&lt;td&gt;1.96s&lt;/td&gt;&lt;td&gt;10.2s&lt;/td&gt;&lt;td&gt;0.85s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;relative to C&lt;/th&gt;&lt;td&gt;1x&lt;/td&gt;&lt;td&gt;0.83x&lt;/td&gt;&lt;td&gt;0.16x&lt;/td&gt;&lt;td&gt;1.9x&lt;/td&gt;&lt;tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;全体的にPyPyは2倍速いです。これは明らかに、静的より動的コンパイラが優っています。 - sprintf関数はlibcにあり、不変な文字列に特化することができず、実行されるときはつねに、文字列を評価しなければなりません。&lt;br /&gt;PyPyのケースでは、私たちは、剰余演算子の左側の文字列が不変であると検出すれば、アセンブラに特化することができます。&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;alex &amp; fijal&lt;br /&gt;&lt;br /&gt;（原文：Posted by Maciej Fijalkowski）&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-3346108651632876532?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/3346108651632876532/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/08/pypycstring.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/3346108651632876532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/3346108651632876532'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/08/pypycstring.html' title='PyPyはCより速い。あらためて：stringフォーマッティング'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-5131809862759774664</id><published>2011-07-08T02:04:00.009+09:00</published><updated>2011-07-08T02:27:53.228+09:00</updated><title type='text'>Pythonでのリアルタイム画像処理</title><content type='html'>原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/07/realtime-image-processing-in-python.html"&gt;Realtime image processing in Python&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;画像処理は、CPUを酷使する悪名高い仕事です。&lt;br /&gt;ですので、リアルタイムで画像処理をするのにPythonで試みるのは馬鹿げており、高速な言語でアルゴリズムを実装する必要があります。&lt;br /&gt;Pythonは明らかにこのタスクに十分な速度がありません。そうですよね？&lt;br /&gt;&lt;br /&gt;実際には、画像処理において、PyPy JITコンパイラはリアルタイムのビデオ処理を行うために十分な速さのコードを生み出すことが判明しました。&lt;br /&gt;&lt;br /&gt;sobel.pyは、画像、&lt;a href="http://en.wikipedia.org/wiki/Sobel_operator"&gt;Sobel operator&lt;/a&gt;のエッジを強める古典的な方法を実装しています。それは、&lt;a href="http://en.wikipedia.org/wiki/Image_gradient"&gt;グラデーション&lt;/a&gt;の大きさの近似値です。&lt;br /&gt;&lt;br /&gt;処理時間は画像と3x3カーネルの間の2つの&lt;a href="http://en.wikipedia.org/wiki/Convolution"&gt;畳み込み処理&lt;/a&gt;に費やしています。&lt;br /&gt;この処理は、入力画像を出力画像へピクセルを越えてコピーするシングルループで構成されています。&lt;br /&gt;&lt;br /&gt;あなたは適切ななデモをダウンロードしてあなた自身で試すことができます。&lt;br /&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;pypy-image-demo.tar.bz2: このアーカイブはソースコードのみを含んでいます。これは既にインストールされているPyPyを必要とします。&lt;/li&gt;&lt;li&gt;pypy-image-demo-full.tar.bz2: このアーカイブは、Linux32bitと64bitのソースコードとビルド済みのPyPyバイナリの両方が含まれています&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;デモを実行するには、MPlayerがシステムにインストールされている必要があります。デモはLinux上でのみテストされて、それが他のシステムでも動作する（か動作しないかもしれません）可能性があります。&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ pypy pypy-image-demo/sobel.py&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ pypy pypy-image-demo/magnify.py&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;デフォルトでは、２つのデモはサンプルのAVIファイルを使用します。&lt;br /&gt;より多くの楽しみを得るために、例に従いMPlayerに適切なパラメータを渡すことで、ウェブカメラを使用することができます。&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ pypy demo/sobel.py tv://&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;デフォルトではmagnify.pyは&lt;a href="http://en.wikipedia.org/wiki/Nearest-%20neighbor_interpolation"&gt;近傍法&lt;/a&gt;を使用します。&lt;br /&gt;オプション-bを追加することにより、&lt;a href="http://en.wikipedia.org/wiki/Bilinear_interpolation"&gt;バイリニア補間&lt;/a&gt;が代わりに使用され、より滑らかな結果が与えられます。&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;$ pypy demo/magnify.py -b&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;magnify.pyのアルゴリズムの実装はただ一つしかありません。&lt;br /&gt;二つの異なった挿入メソッドは実装されます。クラスのサブクラス化に&lt;br /&gt;画像を表現し、補間を埋め込むピクセルアクセスメソッドの内側でよく使われます。&lt;br /&gt;&lt;br /&gt;PyPyは画素アクセス法をインライン化し、アルゴリズムの実装を特化できるので、良好なパフォーマンスをこの抽象化で達成することができます。&lt;br /&gt;C++では、画素アクセス法のようなものは仮想的になり、実行時のオーバーヘッドを招くことなく同じ効果を得るためにテンプレートを使用する必要があります。&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;object width="320" height="212"&gt;&lt;param name="movie" value="http://www.youtube-nocookie.com/v/5DtlBC_Zbq4?version=3&amp;amp;hl=ja_JP"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube-nocookie.com/v/5DtlBC_Zbq4?version=3&amp;amp;hl=ja_JP" type="application/x-shockwave-flash" width="320" height="212" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;上記の&lt;a href="http://www.youtube.com/watch?v=5DtlBC_Zbq4"&gt;ビデオ&lt;/a&gt;は、PyPyとCPythonが並んでsobel.pyを実行しているところです。&lt;br /&gt;（PyPyはウェブカメラから入力を受け、CPythonはテストファイルから入力を受けます）&lt;br /&gt;また、PyPyがCPythonよりどのくらい高速であるか実感したいならば、後でデモを走らせて下さい。これらは、上記tarballリンクの標準のtest.avi ビデオとPyPyプレビルドバイナリを使用した際のマシン（(Ubuntu 64 bit, Intel i7 920, 4GB RAM)）での平均したfps(frames per second)です。&lt;br /&gt;sobel.pyの場合:&lt;div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;PyPy: ~47.23 fps&lt;/li&gt;&lt;li&gt;CPython: ~0.08 fps&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;magnify.pyの場合:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;PyPy: ~26.92 fps&lt;/li&gt;&lt;li&gt;CPython: ~1.78 fps&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;これはsobel.pyでは、PyPyが590倍速いことを意味しています。&lt;br /&gt;magnify.pyでは、それほど違いは明白ではなく高速化は"たった"15倍です。&lt;br /&gt;&lt;br /&gt;このことはPyPyができる極端な例であることに注意しなければいけません。&lt;br /&gt;とりわけ、期待してはいけません（まだ :-)）&lt;br /&gt;&lt;br /&gt;これがPyPyができることの極端な例であることに注意しなければなりません。 特に、あなたは予想できません(まだ(^o^))。 リアルタイムのときに任意のビデオ処理アルゴリズムを走らせるほど速いPyPy、デモだけがPyPyにはそこに到着する可能性があるとまだ立証しています。&lt;br /&gt;PyPyに、リアルタイムで任意のビデオ処理アルゴリズムを実行するのに十分な速さを期待することはできません。しかしデモの結果は、PyPyが十分な速度を達成する可能性を秘めていることを証明しています。&lt;br /&gt;&lt;br /&gt;（原文：Posted by Antonio Cuni）&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-5131809862759774664?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/5131809862759774664/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/07/python.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/5131809862759774664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/5131809862759774664'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/07/python.html' title='Pythonでのリアルタイム画像処理'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-8162856718646075952</id><published>2011-06-30T23:44:00.014+09:00</published><updated>2011-07-01T19:47:54.413+09:00</updated><title type='text'>グローバルインタプリタロックを無くす方法</title><content type='html'>原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/06/global-interpreter-lock-or-how-to-kill.html"&gt;Global Interpreter Lock, or how to kill it&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;EuroPythonで私（Armin Rigo）のライトニングトークを聴いた人は、突然知ったでしょう。我々はグローバルインタプリタロック---悪名高いGIL、複数のスレッドが実際にPythonコードへ干渉するのを防ぐCPythonのものです ---を取り除く計画を持っています。&lt;br /&gt;&lt;br /&gt;それは画期的なものではありません。なぜならJythonは既にGILを取り除くことに対応しています。&lt;br /&gt;Jythonは非常に慎重に全ての変更可能な組み込み型にロックを追加し、それらに対して、効率的になるよう基盤にあるJavaプラットフォームを頼っています。（結果は非常に慎重にCPythonで同様なロックを追加するより速いです）&lt;br /&gt;"非常に慎重"は本当の本当に慎重を意味します。&lt;br /&gt;例えば、'dict1.update(dict2)' はdict1とdict2の両方をロックする必要があります。しかし、あなたが安易にしてしまうなら、'dict2.update(dict1)'はデッドロックを生じる可能性があります。&lt;br /&gt;&lt;br /&gt;PyPy、CPython、IronPythonとすべてはGILを持っています。&lt;br /&gt;しかし、我々はPyPyに対して、&lt;a href="http://en.wikipedia.org/wiki/Software_transactional_memory"&gt;Software Transactional Memory&lt;/a&gt;（ソフトウェアトランザクショナルメモリ）に基づく、Jythonとは大きく異なるアプローチを検討しています。&lt;br /&gt;ソフトウェアトランザクションメモリはコンピュータサイエンスにおける近年の研究成果であり、ロックより良い解決策を提供します。&lt;br /&gt;ここでソフトウェアトランザクションメモリについて、簡単に紹介します。&lt;br /&gt;&lt;br /&gt;あなたが"list1"から項目をpopして"list2の'にpopしたものを追加したいとしましょう​​：&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def f(list1, list2):&lt;br /&gt;    x = list1.pop()&lt;br /&gt;    list2.append(x)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;これは、マルチスレッドとして安全な例ではありません（GILであるとしても）。&lt;br /&gt;つまり、スレッド1でf(l1, l2)とスレッド2でf(l2, l1)を呼び出した場合です。&lt;br /&gt;&lt;br /&gt;あなたが望む動作として、全く効果がないということです。(xは一方のリストからもう一方のリストまで動かされた後、元に戻ります)&lt;br /&gt;しかし、それは、二つのリストのトップは入れ替わる代わりに、タイミングの問題によって起こることがあります。&lt;br /&gt;&lt;br /&gt;これを治す一つの方法は、グローバルロックを使用することです:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def f(list1, list2):&lt;br /&gt;    global_lock.acquire()&lt;br /&gt;    x = list1.pop()&lt;br /&gt;    list2.append(x)&lt;br /&gt;    global_lock.release()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;これを修正するより良い方法は、リストが備えているロックを使用することです:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def f(list1, list2):&lt;br /&gt;    acquire_all_locks(list1.lock, list2.lock)&lt;br /&gt;    x = list1.pop()&lt;br /&gt;    list2.append(x)&lt;br /&gt;    release_all_locks(list1.lock, list2.lock)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;２番目の解決策はJythonのモデルです。そしてもう一方の１番目はCPythonのモデルです。CPythonインタプリタでGILを獲得し、一つのバイトコード（実際は100のような実数）にし、そしてGILを解放します。&lt;br /&gt;そしてさらに、100の次の分岐を続けます。&lt;br /&gt;&lt;br /&gt;ソフトウェアトランザクションは３番目の解決策をもたらします:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def f(list1, list2):&lt;br /&gt;    while True:&lt;br /&gt;        t = transaction()&lt;br /&gt;        x = list1.pop(t)&lt;br /&gt;        list2.append(t, x)&lt;br /&gt;        if t.commit():&lt;br /&gt;            break&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;この解決策では、トランザクションオブジェクトを作成し、すべてのリストへの読み書きで使用します。&lt;br /&gt;それはは実際にいくつかの異なるモデルがありますが、そのうちの一つに注目してみましょう。&lt;br /&gt;トランザクション中に、我々は実際にはまったくもってグローバルメモリを変更しません。その代わりに、スレッドローカルトランザクションオブジェクトを使用します&lt;br /&gt;。&lt;br /&gt;&lt;br /&gt;我々はそのオブジェクトに、どれから読むか、どのオブジェクトに書くか、何の値を書くか格納します。&lt;br /&gt;それは、トランザクションに達した時、私たちはコミットの試みに達するのみです。&lt;br /&gt;コミットは失敗するかもしれません。もし他のコミットがその間に発生した場合、矛盾が発生します。その場合、トランザクションは中止し、再度はじめから処理をやり直さなければなりません。&lt;br /&gt;&lt;br /&gt;前の2つの解決策がCPythonとJythonのモデルであるのと同様に、STMの解決策は、PyPyの将来におけるモデルであるかのように見えます。&lt;br /&gt;PyPyインタプリタは、トランザクションを開始、複数のバイトコードを実行、トランザクションを終了という処理をとてもよく繰り返します。&lt;br /&gt;これはCPythonのGILが行っていることと大変似通っています。&lt;br /&gt;特に、この処理はプログラマがGILの場合と同様に、同一の保証を与えられることを意味します。&lt;br /&gt;唯一の違いは、コードがお互いを妨げない限り、マルチスレッドで並列に実行できるということです。&lt;br /&gt;(とりわけ、あなたが既存のマルチスレッド化されたプログラムにおいて、GILだけではなく実際のロックも必要とするなら、これは不思議にもそれらの必要性を削除しません。&lt;br /&gt;あなたがロックよりそれを好むなら、PythonプログラムにSTMを触れさせる特別な組み込みモジュールを取得する可能性がありますが、それは別の質問です）&lt;br /&gt;&lt;br /&gt;なぜそのアイデアをCPythonに適用しないのでしょうか？&lt;br /&gt;なぜならば、私たちはいたるところを変更する必要があるからでしょう。先程の例で説明すれば、&lt;br /&gt;私はもう 'list1.pop()'と呼出しをしません。必ず呼出しは'list1.pop(t)'です。これはすべて実装を"トランザクション的な"動きを行うために、変える必要があると言うことです。&lt;br /&gt;&lt;br /&gt;これは、代わりに実際にリストが格納されているグローバルメモリを変更することを意味します。つまり、代わりのトランザクションのオブジェクトの変更を記録しなければなりません。&lt;br /&gt;私たちのインタプリタがCPythonのようにC言語で記述されている場合、我々は、明示的にいたるところでそれを書く必要があります。&lt;br /&gt;それはより高いレベルの言語ではなく、書かれている場合など、変換ルールのセットとして、PyPyはそのまま、次に我々はこの動作を追加することができ、それが必要な場所であればどこでもそれらを自動的に適用されます。&lt;br /&gt;&lt;br /&gt;それがPyPyのようなより高いレベルの言語で代わりに記述されているのであれば、&lt;br /&gt;我々は変換規則のセットとして、この振舞いを加えることができますとともに、自動的にどこにでも、変換規則が必要であるところに振る舞いを適用します。&lt;br /&gt;また、変換時のオプションを指定することができます。&lt;br /&gt;あなたはGILがある現在の"pypy"、または、余分な出力処理のためより遅いでしょうがSTMがあるバージョンを得ることができます。&lt;br /&gt;（どのくらい遅いかって？私はさっぱりわからないけど、荒っぽい推測として、２〜５倍程度遅いかもしれません。&lt;br /&gt;十分なコアがある場合は、その限りスケールしすばらしいですよ。 :-）&lt;br /&gt;&lt;br /&gt;最終的な注記：STMの研究は、ごく真新しく（2003年頃開始）、多くの亜種があり、どの場合にどれがより優れているかは、まだ明らかではありません。&lt;br /&gt;私が判断できる限り、"A Comprehensive Strategy for Contention Management in Software Transactional Memory"（日本語注記：ソフトウェアの取引のメモリにおける主張管理のための包括的戦略）で説明されたアプローチは、1つが最先端であるということであるように思えます。それはまた、"すべてのケースに十分良い"ように思えます。&lt;br /&gt;&lt;br /&gt;それで、いつグローバルインタプリタを取り除くことをするのでしょうか？私はまだ明言することができません。&lt;br /&gt;それはまだアイデアの段階ですが、私はそれが実現できると思います。それを書くには私たちはどのくらいの時間を取るでしょうか？&lt;br /&gt;再びさっぱりわかりません、しかし、我々は何日ではなく何ヶ月であると調べています。&lt;br /&gt;これは私がユーロの資金が9月1日がなくなった後も、フルタイムで作業できるようにしたいと思ったりなど...。&lt;br /&gt;&lt;br /&gt;現在、私たちは私が着手できるように金を工面するのにcrowdfundingを使用する方法を調べています。 とってもすぐにブログ記事のポストを期待していてください。&lt;br /&gt;しかし、これはcrowdfundingするうってつけの候補者に似ています。  --GILを無くすために10ユーロを支払うことをいとわない何千人ものあなた方が一応は存在します。今、私たちはこれを実現するだけです。&lt;br /&gt;&lt;br /&gt;（原文：Posted by Armin Rigo）&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-8162856718646075952?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/8162856718646075952/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/06/blog-post_30.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/8162856718646075952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/8162856718646075952'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/06/blog-post_30.html' title='グローバルインタプリタロックを無くす方法'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8716539354830932074.post-6326581668460217344</id><published>2011-06-25T15:24:00.013+09:00</published><updated>2011-07-08T11:41:43.263+09:00</updated><title type='text'>調査の報告</title><content type='html'>原文はこちら: &lt;a href="http://morepypy.blogspot.com/2011/06/report-back-from-our-survey.html"&gt;Report back from our survey&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;やぁ、みんな。&lt;br /&gt;&lt;br /&gt;私は調査の結果を報告します。&lt;br /&gt;まず最初に、私たちは多くのユーザーがPyPyを快くプロダクトで使うというレポートにとっても喜んでいます。&lt;br /&gt;回答者の多く（97%）はPyPyは速いという理由で使用しています。&lt;br /&gt;しかし、26％（回答者は複数回答を選択できる）で、メモリ使用量が少ないという理由でPyPyを使用しています。&lt;br /&gt;PyPy使用していないユーザーのうち、最も一般的な理由は、"その他"に続きC拡張でした。&lt;br /&gt;&lt;br /&gt;みんなからのコメントを読んでから私たちが学んだことがいくつかあります：&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Google docsはこのような物よりよいUIを必要としています。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;とても多くの人々がNumPyとSciPyを望み、C拡張を望んでいます。（25%の回答者はなんとかNumPyを使いたいと言った。）&lt;br /&gt;私たちは既に&lt;a href="http://morepypy.blogspot.com/2011/05/numpy-in-pypy-status-and-roadmap.html"&gt;NumPyに関するプランを話題にした記事&lt;/a&gt;を書きました。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;様々なOSのリポジトリにパッケージを持つことは、ユーザーの勉強と実行に大きな助けとなるでしょう。&lt;/li&gt;&lt;/ol&gt;すべての回答者の多大な貢献に感謝します！&lt;br /&gt;最後に、もしあなたがPyPyをプロダクションで使っているのであれば、私たちはあなたに多いに感謝します。&lt;br /&gt;そして、もし時間を割くことができるのであれば、&lt;a href="http://mail.python.org/mailman/listinfo/pypy-dev"&gt;メーリングリスト&lt;/a&gt;経由で連絡を下さい。&lt;br /&gt;&lt;br /&gt;Thanks, Alex&lt;br /&gt;&lt;br /&gt;(原文：Posted by Alex)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8716539354830932074-6326581668460217344?l=morepypy-ja.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://morepypy-ja.blogspot.com/feeds/6326581668460217344/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://morepypy-ja.blogspot.com/2011/06/blog-post.html#comment-form' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/6326581668460217344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8716539354830932074/posts/default/6326581668460217344'/><link rel='alternate' type='text/html' href='http://morepypy-ja.blogspot.com/2011/06/blog-post.html' title='調査の報告'/><author><name>rokujyouhitoma</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/__RQtB3SeUAk/TKQycrvt1SI/AAAAAAAAAKA/eq3beKEoaQM/S220/tohru.jpg'/></author><thr:total>0</thr:total></entry></feed>
