バイトコード(ポータブルコードまたはpコードとも呼ばれる)は、ソフトウェアインタープリタによる効率的な実行のために設計された命令セットの一種です。人間が読める[1]ソースコードとは異なり、バイトコードはコンパクトな数値コード、定数、参照(通常は数値アドレス)であり、プログラムオブジェクトの型、スコープ、ネストの深さなどの意味解析とコンパイラの解析結果をエンコードします。
バイトコードという名前は、1バイトの オペコードとそれに続くオプションのパラメータを持つ命令セットに由来しています。バイトコードなどの中間表現は、解釈を容易にするためにプログラミング言語の実装によって出力される場合があり、また、同じコードを異なるデバイス上のクロスプラットフォームで実行できるようにすることで、ハードウェアとオペレーティング システムへの依存を減らすために使用される場合もあります。バイトコードは、多くの場合、仮想マシン( p コード マシン、つまりインタープリタ) で直接実行されるか、またはパフォーマンスを向上させるために マシン コードにさらにコンパイルされることがあります。
バイトコード命令はソフトウェアによって処理されるため、任意の複雑さになる可能性がありますが、それでも従来のハードウェア命令に類似していることがよくあります。仮想スタックマシンが最も一般的ですが、仮想レジスタマシンも構築されています。[2] [3]異なる部分は、オブジェクトモジュールと同様に別々のファイルに格納されることがよくありますが、実行中に動的にロードされます。
実行
バイトコード プログラムは、命令を 1 つずつ解析して直接実行することで実行できます。この種のバイトコード インタプリタは非常に移植性に優れています。動的トランスレータまたはジャストインタイム(JIT) コンパイラと呼ばれる一部のシステムは、実行時に必要に応じてバイトコードをマシン コードに変換します。これにより、仮想マシンはハードウェア固有になりますが、バイトコードの移植性は失われません。たとえば、JavaおよびSmalltalkコードは通常バイトコード形式で保存され、実行前にバイトコードをマシン コードに変換する JIT コンパイルが行われます。これにより、バイトコードがネイティブ マシン コードにコンパイルされるときにプログラムの実行前に遅延が発生しますが、ソース コードを直接解釈する場合と比較して、実行速度が大幅に向上します。通常は 1 桁程度 (10 倍程度) 向上します。[4]
パフォーマンス上の利点のため、今日では多くの言語実装は、最初にソース コードをバイトコードにコンパイルし、次にバイトコードを仮想マシンに渡すという 2 段階でプログラムを実行します。Java 、Raku、Python、PHP、[a] Tcl、mawk、Forthには、この種のバイトコードベースの仮想マシンがあります (ただし、Forth はこのようにバイトコード経由でコンパイルされることはめったになく、その仮想マシンはより汎用的です)。PerlとRuby 1.8の実装は、代わりにソース コードから派生した抽象構文木表現を調べることで機能します。
最近では、 V8 [1]とDart [7]の作者は、高速で効率的な VM 実装には中間バイトコードが必要であるという考え方に異議を唱えています。現在、これらの言語実装は両方とも、バイトコードを介さずにソースコードからマシンコードに直接 JIT コンパイルを行っています。[8]
例
- ActionScript は、Flash Player およびAIRの一部である ActionScript 仮想マシン (AVM) で実行されます。ActionScript コードは通常、コンパイラによってバイトコード形式に変換されます。コンパイラの例としては、Adobe Flash Professional に組み込まれているコンパイラや、Adobe Flash Builder に組み込まれていてAdobe Flex SDKで利用できるコンパイラなどがあります。
- Adobe Flashオブジェクト
- BANCStarは元々はインターフェース構築ツールのバイトコードだったが、言語としても使われている。
- バークレーパケットフィルタ
- EBPF
- バークレーパスカル[9]
- バイトコードエンジニアリングライブラリ
- C からJava 仮想マシンコンパイラ
- Common LispのCLISP実装は長年バイトコードのみにコンパイルされていましたが、現在はGNU lightningの助けを借りてネイティブコードへのコンパイルもサポートしています。
- CMUCLとScieneer Common LispのCommon Lisp実装は、ネイティブコードまたはバイトコードにコンパイルすることができ、バイトコードの方がはるかにコンパクトである。
- 共通言語ランタイムによって実行される共通中間言語。C#などの.NET言語で使用されます。
- Androidプラットフォーム用に設計されたDalvikバイトコードは、 Dalvik仮想マシンによって実行されます。
- Inferno(オペレーティングシステム)用に設計されたDisバイトコードは、 Dis仮想マシンによって実行されます。
- Eiffelプログラミング言語用のEiffelStudio
- EM、アムステルダムコンパイラキット仮想マシン。中間コンパイル言語および最新のバイトコード言語として使用される。
- Emacsはテキスト エディタであり、その機能のほとんどは、組み込みのLisp方言であるEmacs Lispによって実装されています。これらの機能はバイトコードにコンパイルされます。このアーキテクチャにより、ユーザーは高級言語を使用してエディタをカスタマイズすることができ、バイトコードにコンパイルすると適切なパフォーマンスが得られます。
- 埋め込み可能なCommon Lisp実装は、バイトコードまたはCコードにコンパイルできます。
- Common Lisp は、指定された関数の基になるコードを標準出力に出力する
disassemble関数[10]を提供します。結果は実装に依存し、バイトコードに解決される場合とされない場合があります。その検査はデバッグや最適化の目的で利用できます。 [11] たとえば、Steel Bank Common Lisp は以下を生成します。
(逆アセンブル' ( lambda ( x ) ( print x ))) ; (LAMBDA (X)) の逆アセンブリ; 2436F6DF: 850500000F22 TEST EAX, [#x220F0000] ; 引数解析なしのエントリ ポイント; E5: 8BD6 MOV EDX, ESI ; E7: 8B05A8F63624 MOV EAX, [#x2436F6A8] ; #<PRINT の FDEFINITION オブジェクト> ; ED: B904000000 MOV ECX, 4 ; F2: FF7504 PUSH DWORD PTR [EBP+4] ; F5: FF6005 JMP DWORD PTR [EAX+5] ; F8: CC0A BREAK 10 ;エラー トラップ; FA: 02 バイト #X02 ; FB: 18 バイト #X18; INVALID-ARG-COUNT-ERROR ; FC: 4F バイト #X4F; ECX
- EricssonのErlang実装ではBEAMバイトコードが使用される
- Ethereumの仮想マシン (EVM) は、独自のバイトコードを使用して、Ethereum でのトランザクション実行 (スマート コントラクト) を行うランタイム環境です。
- Icon [12]とUnicon [13]プログラミング言語
- インフォコムはZマシンを使用してソフトウェアアプリケーションの移植性を高めた。
- Javaバイトコード。Java仮想マシンによって実行される。
- Oberon-2プログラミング言語とOberon オペレーティング システムの移植性を高めるために Oberon -2プログラミング言語で使用されるKeiko バイトコード。
- KEYBはMS-DOS / PC DOSキーボードドライバで、そのリソースファイルKEYBOARD.SYSにはレイアウト情報と、常駐ドライバ内のインタープリタによって実行される短いpコードシーケンスが含まれています。 [14] [15]
- LLVM IR
- 仮想世界で使用されるスクリプト言語である LSL は、仮想マシン上で実行されるバイトコードにコンパイルされます。Second Life にはオリジナルの Mono バージョンがあり、Inworldz は Phlox バージョンを開発しました。
- Lua言語はレジスタベースのバイトコード仮想マシンを使用する
- MATLAB言語のmコード[16]
- Malbolge は、3 値仮想マシン用の難解な マシン言語です。
- Visual C++およびVisual Basicで使用されるMicrosoft P コード
- マルチプラン[17]
- BCPLプログラミング言語のOコード
- OCaml言語はオプションでコンパクトなバイトコード形式にコンパイルされます
- Pascal言語のUCSD Pascal実装のp コード
- パロット仮想マシン
- Pick BASIC (Data BASICまたはMultiValue BASICとも呼ばれる)
- 統計計算用のR環境では、コンパイラパッケージを通じてバイトコードコンパイラが提供されており、これは現在Rバージョン2.13.0で標準となっています。このバージョンのRをコンパイルして、基本パッケージと推奨パッケージでこれを利用することができます。[18]
- ピラミッド2000アドベンチャーゲーム
- Pythonスクリプトは実行時にPythonのバイトコード言語にコンパイルされ、コンパイルされたファイル(.pyc)はスクリプトのフォルダ内にキャッシュされます。
- コンパイルされたコードは、低レベルのバイトコードをデバッグするための組み込みツールを使用して分析および調査できます。ツールはシェルから初期化できます。例:
>>> import dis # "dis" - Python バイトコードをニーモニックに逆アセンブラーします。 >>> dis . dis ( 'print("Hello, World!")' ) 1 0 LOAD_NAME 0 (print) 2 LOAD_CONST 0 ('Hello, World!') 4 CALL_FUNCTION 1 6 RETURN_VALUE
- バイトコードインタープリタを使用したScheme 48実装
- Smalltalk言語の多くの実装のバイトコード
- Parallax Propellerマイクロコントローラに組み込まれたSpinインタープリタ
- SQLiteデータベースエンジンはSQL文を特注のバイトコード形式に変換します。[19]
- アップルSWEET16
- Tcl
- TIMI は、 IBM iプラットフォーム上のコンパイラーによって使用されます。
- 小さなベーシック
- Visual FoxProはバイトコードにコンパイルされます
- Webアセンブリ
- Ruby用のYARVとRubinius
- Zコード
- PHP用のZend Engineオペコード
参照
注記
- ^ PHP 8ではジャストインタイムコンパイルが採用されていますが、 [5] [6]以前はデフォルトバージョンでは採用されていませんでしたが、HHVMなどのオプションがありました。PHPの古いバージョンの場合: PHPオペコードはプログラムが起動されるたびに生成され、常に解釈され、ジャストインタイムコンパイルされません。
参考文献
- ^ ab 「Dynamic Machine Code Generation」。Google Inc. 2017年3月5日時点のオリジナルよりアーカイブ。2024年12月1日閲覧。
- ^ 「Lua 5.0 の実装」。(注: これにはレジスタベースの仮想マシンが関係します。)
- ^ 「Dalvik VM」。2013年5月18日時点のオリジナルよりアーカイブ。2012年10月29日閲覧。(注: この VM はレジスタベースです。)
- ^ 「バイトコードとマシンコード」www.allaboutcomputing.net . 2017年10月23日閲覧。
- ^ O'Phinney、Matthew Weier。「新しい PHP JIT コンパイラの探索」。Zend by Perforce。2021年 2 月 19 日閲覧。
- ^ 「PHP 8: The JIT - stitcher.io」。stitcher.io 。2021年2月19日閲覧。
- ^ Loitsch, Florian. 「バイトコード VM ではないのはなぜか?」。Google。2013 年 5 月 12 日のオリジナルからアーカイブ。
- ^ 「JavaScript の神話: JavaScript には標準バイトコードが必要」。2ality.com。
- ^ G., Adam Y. (2022-07-11). 「Berkeley Pascal」. GitHub . 2022-01-08に閲覧。
- ^ 「CLHS: 関数 DISASSEMBLE」www.lispworks.com。
- ^ Collective (2023-12-13). 「The Common Lisp Cookbook – Performance Tuning and Tips」. lispcookbook.github.io .
- ^ 「Icon プログラミング言語の実装」(PDF)。2016 年 3 月 5 日のオリジナル(PDF)からアーカイブ。2011年 9 月 9 日に取得。
- ^ 「Icon と Unicon の実装の概要」(PDF) 。2022年 10 月 9 日時点のオリジナルよりアーカイブ(PDF) 。
- ^ Paul, Matthias R. (2001-12-30). 「KEYBOARD.SYS 内部構造」。ニュースグループ: comp.os.msdos.programmer。2017-09-09 にオリジナルからアーカイブ。2016-09-17に取得。
[…] 実際、形式は、ロシア語、リトアニア語、中国語、日本語の問題を含む
MS-DOS
3.3 - 8.0、
PC DOS
3.3 - 2000、および Windows NT、2000、および XP で基本的に同じです[…]。わずかな違いや非互換性はありますが、一般的な形式は長年にわたって変更されていません。[…] 一部のデータエントリには通常のテーブルが含まれています[…] ただし、ほとんどのエントリには、
条件分岐などを含む、 *
実行時
に*
何らかの
p コードインタープリターによって解釈される
実行可能コード
が含まれています。このため、
KEYB
ドライバーは、インタープリターを除いて同じレベルの機能を実現するのに 3 ~ 4 Kb で実行できるテーブル駆動型キーボード ドライバーと比較して、非常に大きなメモリ フットプリントを持ちます。[…]
- ^ Mendelson, Edward (2001-07-20). 「MS-DOS および Windows DOS でユーロを表示する方法」。フルスクリーンの MS-DOS (Windows 95 または Windows 98 のフルスクリーン DOS を含む) でユーロ記号を表示します。2016-09-17 にオリジナルからアーカイブ。2016-09-17に取得。
[…] Matthias [R.] Paul […] は、
IBM PC DOSバージョンのキーボード ドライバーは、
Microsoft
ドライバーでは認識されない内部プロシージャを使用しているため、可能であれば、Microsoft バージョンと IBM バージョンを混在させるのではなく、
KEYB.COM
と
KEYBOARD.SYS
の両方の
IBM
バージョンを使用する必要があると警告しています。
[…]
(注: ここでの「手順」とは、Microsoft バージョンの KEYB ドライバーではサポートされていない IBM KEYBOARD.SYS ファイル内の追加のバイトコードを意味します。)
- ^ 「米国特許6,973,644」。2017年3月5日時点のオリジナルよりアーカイブ。2009年5月21日閲覧。
- ^ Microsoft C Pcode 仕様。p. 13。Multiplan
は
、当時の多種多様なハードウェア間で移植可能にするために、
マシン コードではなく、
インタープリタ
によって実行される一種のバイト コードに
コンパイルされました。このバイト コードは、計算に使用するマシン固有の
浮動小数点形式
と、外部 (標準) 形式である
2 進化 10 進数
(BCD) を区別します。PACK および UNPACK 命令は、この 2 つの形式を変換します。
- ^ 「R のインストールと管理」。cran.r-project.org。
- ^ 「SQLite バイトコード エンジン」。2017 年 4 月 14 日時点のオリジナルよりアーカイブ。2016 年 8 月 29 日閲覧。
