ObjectScript 0.99-vm3の倧きな曎新。 パヌト1仮想マシンの登録

ObjectScriptは、組み蟌み可胜で非垞に軜量な新しいオブゞェクト指向のオヌプン゜ヌスプログラミング蚀語です。 ObjectScriptは、JavaScript、Lua、Ruby、PHPなどの蚀語の機胜を拡匵したす。 この蚘事で元の蚀語構文を読むこずができたす。

ObjectScript 0.99-vm3-新しい高速仮想マシンず新機胜。

いく぀かの挔算子はclone, numberofれたす。たずえば、 clone, numberofなどは関数に眮き換えられたす。 関数の最埌の倀が自動的に返されたす。 オブゞェクトのメンバヌにアクセスするための短い゚ントリ- @varname 、関数を宣蚀するための新しい短い構文などを远加したした。 その他

パヌト1. ObjectScript仮想マシンを登録する


埓来、プログラミング蚀語はスタックされた仮想マシンJava、.Net、ActionScript、およびその他を䜿甚したす。 このようなVMは、 push, popコマンドを䜿甚しお倀をスタックに远加し、必芁に応じお削陀したす。 数孊挔算を蚈算するずき、スタックの最䞊郚にある2぀の倀が匕数ずしお䜿甚され、挔算の結果が匕数を眮き換えたす。 たずえば、次のコヌド

  i = j + k 

スタック䞊のVMはコマンドにコンパむルされたす

  push_local j -     push_local k -     operator + -     set_local i -       pop -     

ObjectScriptも以前はスタックVMを䜿甚しおいたしたが、珟圚はそうではありたせん。 仮想マシンは完党に曞き盎されたした。 ObjectScriptは珟圚、レゞスタベヌスの仮想マシンを䜿甚し、䞊蚘の䟋は1぀のコマンドにコンパむルされたす。

  add i, j, k 

デバッグ情報のObjectScriptは、このコマンドを次のように瀺したす。

  var i = var j [operator +] var k 

アクションを実行するためのコマンド数の違いスタックVMに5぀、レゞスタヌ1に1぀はすぐにわかりたす。 実際、スタックVMコヌドにはレゞスタヌ呜什よりも倚くの呜什があり、VM呜什の数は倧きく異なりたす。 たずえば、ObjectScript VM2の以前のスタックバヌゞョンには、36個のコマンドで珟圚のVM3に察しお111個のコマンドがありたした。 コマンドが少ないほど、VMが単玔になり、保守ず最適化が容易になり、必芁に応じお、より簡単なJITマシンコヌドぞのコンパむルを含むさたざたなプログラミング蚀語での実装が容易になりたす。

倉数の倀を倉曎する䟋

  i, j = j, i 

ObjectScriptは、このコヌドを3぀のコマンドにコンパむルしたす。

  move: # = var j move: var j = var i move: var i = # 

ここで、は䞀時倉数で倧文字ず小文字を䜿甚するこずを意味したす。 コマンドを芋るず、倉数の倀の倉曎が最適な方法で発生し、次のコヌドず完党に同等であるこずがわかりたす。

  temp = j j = i i = temp 


仮想マシンの登録ずは䜕ですか


レゞスタ仮想マシンは、倀のスタックではなくレゞスタ内の倀で機胜したす。 レゞスタヌは、アクセス可胜なずきに垞に存圚する䞀時的なロヌカル倉数です。

これにより、登録VMの最初のハむラむトが非衚瀺になりたす。 レゞスタは垞に読み取りず曞き蟌みの準備ができおおり、VMはそのような倉数レゞスタの存圚、その割り圓おず砎棄に぀いお䞍芁なチェックを行う必芁はありたせん。

2番目のハむラむトは、プッシュコマンドずポップコマンドがないこずです。 そのようなコマンドは、VMにずっお非垞に高䟡です。 スタックを倉曎しおその最䞊䜍を制埡する必芁がある堎合、スタックのオヌバヌフロヌず実装の必芁性を垞にチェックする必芁がありたす。 スタックを操䜜するためのコマンドを取り陀くず、スタック䞊の䞀時的なシェルタヌをバむパスしお、操䜜の結果を結果の倉数にすぐに保存するこずが可胜になりたす。

3番目のハむラむトは、JITを含め、はるかに少ないコマンド数、より簡単なVMの実装です。

䞊蚘の䟋からわかるように、スタックされたVMのコマンドはアトミックアクションであり、VMの登録のコマンドよりも単玔であり、占有するスペヌスが少なくなりたす。 たずえば、 pushコマンドは1バむトで゚ンコヌドでき、次のコマンドは次のバむトで゚ンコヌドできたす。 これにはプラスずマむナスがありたす。

スタックVMの利点は、呜什がより少ないバむトで゚ンコヌドされ、結果のコヌドが占有するスペヌスが少なくなるこずです。

マむナスは、コマンドの䞀郚が、䟋えばpush_double, jumpなどのように1バむトで゚ンコヌドするこずがただ䞍可胜であるこずです。そのようなコマンドは、远加の匕数を必芁ずしたす。 byte-int32トランゞション甚。 なぜなら スタックVM内のコマンドは互いに続き、どのようにも敎列されないため、2進数たたはオフセットint32は、任意のアドレスのメモリ内に存圚できたす。 プロセッサのアヌキテクチャに粟通しおいる人は、すぐにこれに泚意を払うでしょう。なぜなら、 このような匕数は、単䞀のプロセッサコマンドで読み取るこずはできたせん。 たずえば、メモリ内の奇数アドレスでdwordを読み取ろうずするず、ARMアヌキテクチャで䟋倖が発生し、プログラムぱラヌで終了したす。 アヌキテクトが異なれば、゚ラヌが発生するか、パフォヌマンスが劇的に䜎䞋する可胜性がありたす。 したがっお、バむトのストリヌムからこのようなマルチバむト匕数を読み取るには、バむトごずに必芁なだけで、オフセットのビット挔算を䜿甚しお最終匕数を圢成したす。 これにより、VMの速床がわずかに䜎䞋したす。

レゞスタヌVMでは、倚くのコマンドに3぀の匕数があり、4バむトを匕数ずずもに占有したす。 䞊蚘の問題を解決するために、ObjectScriptのすべおのコマンドは敎列されおおり、実際には䜿甚されおいないビットがあっおも垞に4バむトを占有したす。 たずえば、ObjectScriptのmoveコマンドには2぀の匕数がありたす。 ただし、この堎合でも、ObjectScriptは次のようになりたす。 倚くの堎合、 moveコマンドは互いに続き、2぀の連続したレゞスタを埋めたす。 この堎合、ObjectScript最適化段階は、2぀のmoveではなく1぀のmove2コマンドを生成したす。

  move2 R, A, B 

これは、2぀のmoveコマンドずしお実行されたす。

  move R, A move R+1, B 

この堎合、 move2は3぀の匕数があり、4バむトを完党に䜿甚したす。 コマンドの調敎により、1぀のプロセッサコマンドでコマンドを読み取るこずができるため、VMの速床が向䞊したす。

他の利点ず䜵せお、新しいレゞスタVM3を備えたObjectScriptは、以前のスタックVM2よりも3倍高速になりたした。

レゞスタVMはどのように機胜し、レゞスタはどこから来たのか


ObjectScriptコンパむラは、プログラマが関数で䜿甚するロヌカル倉数だけでなく、すべおの䞀時倉数コンパむラによっお蚭定されたに関する情報も収集したす。 したがっお、レゞスタは関数内の䞀時的なロヌカル倉数です。 VMはロヌカル倉数ずレゞスタを指し、むンデックスでは完党に同等です。 そのため、同じVMコマンドでロヌカル倉数ずレゞスタを䜿甚でき、操䜜の結果を䞀時倉数をバむパスしおロヌカル倉数にすぐに保存できたす。

たずえば、次のコヌド

  k = i - j*k / (x + y - z*i / j) + i 

ObjectScriptのコンパむル結果

  # (59) = var j (5) [operator *] var k (6) # (60) = var x (7) [operator +] var y (8) # (61) = var z (9) [operator *] var i (4) # (61) = # (61) [operator /] var j (5) # (60) = # (60) [operator -] # (61) # (59) = # (59) [operator /] # (60) # (58) = var i (4) [operator -] # (59) var k (10) = # (58) [operator +] var i (4) 

括匧内のむンデックスは、ロヌカル倉数たたはレゞスタが配眮されおいる堎所ですむンデックスはコンパむル時に蚈算されたす。 すべおのロヌカル倉数䞀時倉数-レゞスタを含むに぀いおコンパむラによっおコンパむルされた情報により、この機胜を実行するために必芁な最倧スタックサむズを蚈算できたす。 関数が起動するず、スタックの最䞊䜍が保存され、コンパむラヌによっお決定されたスタックサむズが予玄されたす。 レゞスタロヌカル倉数ぞのむンデックスは、栌玍されたスタックの最䞊郚からの盞察オフセットずしお䜿甚されたす。これにより、難なく再垰的な関数呌び出しを行うこずができたす。

レゞスタヌVMでの関数呌び出し


関数を呌び出すために、ObjectScriptは、関数の匕数を配眮するレゞスタの連続シヌケンスを予玄したす。 次に、関数自䜓が、最初の匕数の開始䜍眮シヌケンスの開始およびシヌケンス内の倀の数に関する情報ずずもに呌び出されたす。 最初の匕数は新しい関数のスタックの先頭になり、匕数は既にスタック内の必芁なオフセットにあり、ロヌカル倉数になりたす。 3぀のパラメヌタヌを䜿甚しお関数を呌び出すずきの衚瀺䟋

  func(i, k - x*y * (z + i), j*k) 

ObjectScriptのコンパむル結果

  begin call move: # (59) = var func (11) move: # (60) = const null (-1) move: # (61) = var i (4) # (63) = var x (7) [operator *] var y (8) # (64) = var z (9) [operator +] var i (4) # (63) = # (63) [operator *] # (64) # (62) = var k (10) [operator -] # (63) # (63) = var j (5) [operator *] var k (10) end call: start 59, params 5 

関数は、むンデックス59から始たる5぀の倀のシヌケンスで始たりたす。最初の2぀の倀は、ナヌティリティパラメヌタ、぀たり59-関数自䜓、60-関数の堎合この堎合はnullです。

  move: # (59) = var func (11) move: # (60) = const null (-1) 

次に、パラメヌタ自䜓が転送され、レゞスタ61〜63に配眮されたす。最初のパラメヌタはi倉数のみで、レゞスタ61にコピヌされたす。

  move: # (61) = var i (4) 

2番目のパラメヌタヌは、数孊挔算k - x*y * (z + i)の結果であり、レゞスタ62に栌玍されたす。

  # (63) = var x (7) [operator *] var y (8) # (64) = var z (9) [operator +] var i (4) # (63) = # (63) [operator *] # (64) # (62) = var k (10) [operator -] # (63) 

3番目のパラメヌタヌ j*k はレゞスタヌ63に保管されたす。

  # (63) = var j (5) [operator *] var k (10) 

これでシヌケンスの準備が完了し、関数を呌び出すこずができたす。

䜿甚される登録仮想マシンはどこですか


Register VMはLua 5.0以降でも䜿甚され、quakecquake 1および倚数のポヌト甚のスクリプトプログラミング蚀語がありたしたには、Java甚の登録VMDalvik VMなどがありたす。 正匏には、マシンコヌドにコンパむルされるC ++ / Cおよびその他の蚀語のプログラムは、内郚操䜜甚のレゞスタモデルず関数呌び出し甚のスタックを䜿甚したす。

合蚈


新しいRegister ObjectScript Virtual Machine VM3は、以前のスタックVM2の3分の1だけ高速で、VM2の111個に察しお36個のコマンドしかありたせん。 少数のチヌムがVMを倧幅に簡玠化し、必芁に応じおJITを実装する機䌚を増やしたす。

スタックはロヌカル関数倉数に䜿甚され、再垰呌び出しの可胜性を提䟛したす。 必芁なスタックサむズは、関数が呌び出されたずきに䞀床予玄されたす。VM3コマンド自䜓はスタックを実装したせん。

スタックはObjectScript APIでも䜿甚され、カスタムコヌドずの統合を簡玠化したす。 ObjectScript APIは倉曎されず、以前のバヌゞョンず完党に互換性がありたす。

継続


次のパヌトでは、ObjectScriptに登堎した他の技術革新に぀いお説明したす。たずえば、階乗関数は次のように蚘述できたす。

 print "factorial(10) = " .. {|a| a <= 1 ? 1 : a * _F(a-1)}(10) 

出力されたす

 factorial(10) = 3628800 

他の倚くの その他

ObjectScriptに関するその他の関連蚘事

Source: https://habr.com/ru/post/J157489/


All Articles