ナカナカピエロ おきらくごくらく

写真付きで日記や趣味を書くならgooブログ

JavaScriptのバイトコードを読んでみよう

2021-03-11 22:48:41 | 日記
JavaScriptのバイトコードを読んでみよう

以前に私は以下のブログ記事で、JavaScriptのバイトコードの出力方法について書いた。

JavaScriptのバイトコード(逆アセンブル疑似コード)の見方

今度は、実際に読んでみようということで少しずつだけど、ブログ記事を書いておこうと思う。

まず基本的なことだが、JavaScriptはスクリプト型言語だが、内部ではバイトコードが生成されて

そのバイトコードがさらにネイティブなマシンコードに変換され高速に動作するようになっている。

バイトコードは仮想的なマシンコードでレジスタをもつスタックマシンとして動作する。

まあ堅苦しいことは抜かして、実際に簡単なサンプルコードで早速バイトコードを読んでみよう。

なおここで言っているバイトコードとは、V8のバイトコードになります。

V8はGoogleのオープンソースJavaScriptエンジンです。Chrome、Node.js、およびその他の多くの

アプリケーションでV8が使用されています。

■簡単なJavaScriptのサンプルコードとそのバイトコードの対応

【JavaScriptコード】

  1 var a=1999;
  2 var b=3121;
  3 var c=659;
  4 function muladd1(x,y,z) {
  5         let r=x+y*z;
  6         return r;
  7 }
  8 function muladd2(x,y,z) {
  9         let r=x*y+z;
 10         return r;
 11 }
 12 function func_example(x,y,z) {
 13         var d=muladd1(x,y,z)+muladd2(x,y,z);
 14         if (d==341) {
 15                 return 333;
 16         }
 17         return 777;
 18
 19 }
 20
 21 var e=func_example(a,b,c);
 22 console.log(e);



【バイトコード】
1行目~3行目、21行目~22行目
    StackCheck                                     # スタックチェック
    LdaSmi.Wide [1999]                             # 即値1999をアキュムレータレジスタにロードする
    StaCurrentContextSlot [4]                      # アキュムレータレジスタからCurrentContextSlot[4]にストア
    LdaSmi.Wide [3121]                             # 即値3121をアキュムレータレジスタにロードする
    StaCurrentContextSlot [5]                      # アキュムレータレジスタからCurrentContextSlot[5]にストア
    LdaSmi.Wide [659]                              # 即値659をアキュムレータレジスタにロードする
    StaCurrentContextSlot [6]                      # アキュムレータレジスタからCurrentContextSlot[6]にストア
    LdaImmutableCurrentContextSlot [4]             # CurrentContextSlot[4]からアキュムレータレジスタにロードする
    Star r4                                        # アキュムレータレジスタからレジスタr4にストア
    LdaImmutableCurrentContextSlot [5]             # CurrentContextSlot[5]からアキュムレータレジスタにロードする
    Star r5                                        # アキュムレータレジスタからレジスタr5にストア
    LdaImmutableCurrentContextSlot [6]             # CurrentContextSlot[6]からアキュムレータレジスタにロードする
    Star r6                                        # アキュムレータレジスタからレジスタr6にストア
    CallUndefinedReceiver r0, r4-r6, [0]           # func_example関数(レジスタr0にアドレスが入っている)を呼び出す
                                                   # 実引数リストは、r4-r6番に入っている
    Star r1                                        # 返却値が入っているアキュムレータレジスタをレジスタr1にストア
    LdaGlobal [4], [2]                             # グローバル変数eのアドレスをアキュムレータレジスタにロード
    Star r4                                        # アキュムレータレジスタをレジスタr4にストア
    LdaNamedProperty r4, [5], [4]                  # 名前付けられた属性(r4)をアキュムレートレジスタにロード
    Star r3                                        # console.log関数のアドレスをレジスタr3にストア
    CallProperty1 r3, r4, r1, [6]                  # レジスタr4の属性でレジスタr1のある値を引数にしてレジスタr3の関数を呼び出す	
    LdaUndefined                                   # 定数"undefined"をアキュムレータレジスタにロードする
    Return                                         # アキュムレータレジスタの値を返却する
Constant pool (size = 6)

[generated bytecode for function: muladd1]
Parameter count 4
Register count 1
Frame size 8
    StackCheck                                     # スタックチェック
    Ldar a2                                        # 第3引数が入ったレジスタa2をアキュムレートレジスタにロードする。
    Mul a1, [1]                                    # アキュムレータレジスタと第2引数が入ったレジスタa1を掛け算して
                                                   # アキュムレータレジスタに結果を格納する
    Add a0, [0]                                    # アキュムレータレジスタと第1引数が入ったレジスタa0を足し算して
                                                   # アキュムレータレジスタに結果を格納する
    Star r0                                        # アキュムレータレジスタの値をレジスタr0にストアする
    Return                                         # アキュムレータレジスタの値を返却する
Constant pool (size = 0)
Handler Table (size = 0)

[generated bytecode for function: muladd2]
Parameter count 4
Register count 2
Frame size 16
    StackCheck                                     # スタックチェック
    Ldar a1                                        # 第2引数が入ったレジスタa1をアキュムレートレジスタにロードする。
    Mul a0, [1]                                    # アキュムレータレジスタと第1引数が入ったレジスタa0を掛け算して
                                                   # アキュムレータレジスタに結果を格納する
    Star r1                                        # アキュムレータレジスタをレジスタr1にストアする
    Ldar a2                                        # 第3引数が入ったレジスタa2をアキュムレートレジスタにロードする。
    Add r1, [0]                                    # アキュムレータレジスタとレジスタr1を足し算して
                                                   # アキュムレータレジスタに結果を格納する
    Star r0                                        # アキュムレータレジスタの値をレジスタr0にストアする
    Return                                         # アキュムレータレジスタの値を返却する
Constant pool (size = 0)
Handler Table (size = 0)

[generated bytecode for function: func_example]
Parameter count 4
Register count 6
Frame size 48
    StackCheck                                     # スタックチェック
    LdaImmutableCurrentContextSlot [4]             # CurrentContextSlot[4](muladd1の関数アドレス)からアキュムレータレジスタにロードする
    Star r1                                        # アキュムレータレジスタをレジスタr1にストアする
    Mov a0, r2                                     # 第1引数が入ったレジスタa0をレジスタr2に移動する
    Mov a1, r3                                     # 第2引数が入ったレジスタa1をレジスタr3に移動する
    Mov a2, r4                                     # 第3引数が入ったレジスタa2をレジスタr4に移動する
    CallUndefinedReceiver r1, r2-r4, [1]           # muladd1関数(レジスタr1にアドレスが入っている)を呼び出す
                                                   # 実引数リストは、r2-r4番に入っている
    Star r1                                        # 返却値が入っているアキュムレータレジスタをレジスタr1にストア
    LdaImmutableCurrentContextSlot [5]             # CurrentContextSlot[5](muladd2の関数アドレス)からアキュムレータレジスタにロードする
    Star r2                                        # アキュムレータレジスタからレジスタr2にストア
    Mov a0, r3                                     # 第1引数が入ったレジスタa0をレジスタr3に移動する
    Mov a1, r4                                     # 第2引数が入ったレジスタa1をレジスタr4に移動する
    Mov a2, r5                                     # 第3引数が入ったレジスタa2をレジスタr5に移動する
    CallUndefinedReceiver r2, r3-r5, [3]           # muladd2関数(レジスタr2にアドレスが入っている)を呼び出す
                                                   # 実引数リストは、r3-r5番に入っている
    Add r1, [0]                                    # アキュムレータレジスタとレジスタr1を足し算して
                                                   # アキュムレータレジスタに結果を格納する
    Star r0                                        # 返却値が入っているアキュムレータレジスタをレジスタr0にストア
    LdaSmi.Wide [341]                              # 即値341をアキュムレータレジスタにロードする
    TestEqual r0, [5]                              # アキュムレータレジスタとレジスタr0が等しいかテストする
    JumpIfFalse [7] (000000AA7251FD80 @ 58)        # もし比較結果がFALSEなら000000AA7251FD80番地にジャンプする
    LdaSmi.Wide [333]                              # 即値333をアキュムレータレジスタにロードする
    Return                                         # アキュムレータレジスタの値を返却する
000000AA7251FD80 @ 58
    LdaSmi.Wide [777]                              # 即値777をアキュムレータレジスタにロードする
    Return                                         # アキュムレータレジスタの値を返却する
Constant pool (size = 0)
Handler Table (size = 0)


大分、JavaScriptのバイトコードに慣れてきたのではないだろうか。

JavaScriptのバイトコードに関する仕様書やドキュメントらしきものはないため、何かのお役に立てばよいかと思う。

■各バイトコード命令の簡単な意味
●StackCheck
スタックポインタがスタックのlimit値を超えているかどうかチェックする命令
・・・工事中・・・

■その他
●意味不明な[数値]
関数のいわゆるフィードバックベクトルのインデックス。
フィードバックベクトルには、パフォーマンスの最適化に使用される実行時情報が含まれているが、
バイトコードを読む分にはとりあえずは無視してよい。

■参考文献
Understanding V8’s Bytecode by @fhinkel
Ignition: V8 Interpreter
Speculative Optimization in V8--An Introduction to Speculative Optimization in V8

■変更歴
ver0.0 初版(2021/03/11):今後も拡張予定
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

【訓練校1月生】Java基礎演習講座八日目サブ講師(内職でJavaScript)

2021-03-11 20:11:50 | 日記
【訓練校1月生】Java基礎演習講座八日目サブ講師(内職でJavaScript)

今日は木曜日。晴れ。

5時半起床。寝過ごした。昨日2時半まで起きていたので眠い。

6時過ぎに家を出て、朝食は会社近くの朝マック。

電車の中で、「平均・分散から始める一般化線形モデル入門」を読んでいた。

第4部を読了。

今日は昨日の日付と時間の演習の続きとコレクションを講義予定。

メイン講師は前会社の入社時の最初の元課長。

時間まで、WSL2上で動作しているUbuntuにTexLive(basic)のインストールをしていた。

以下の記事を参考にした。

texlive2020(basic)のインストール on WSL

とりあえず、Ubuntu上でサンプルのtexファイルからdviファイル、PDFファイルと変換する

ことができることまで確認できた(祝)。

またPDFからWordに変換するツール"Renee PDF Aide"をインストールして、サンプルが

無事Wordに変換されるところまで確認した。

9:00~訓練校講義開始。

一限目は、昨日の続きで日付の演習。Meは内職して、結局何だかんだTex環境は、

Overleafが一番いいじゃね、というところで落ち着いた。

Overleafの日本語設定は、以下の記事が参考になった。

Overleaf v2 で日本語を使用する方法 - TeX Alchemist Online

ちゃんと日本語のTexファイルもPDFに変換できた。

これで数式を書いたPDF文書を作成できる。嗚呼、Texの書き方忘れちゃったよ。。。(´;ω;`)ウゥゥ

とりあえず数学を教えるための文書作成ツールは揃った。パチパチ。

一応、合間合間に受講生のサポートもして、サブ講師としての仕事もちゃんとこなした。

二限目は、日付の演習の続き。その後、ようやく今日の本題のコレクションの講義が始まる。

Meは内職で、JavaScriptのバイトコードを調べていた。 以下が参考になった。

V8 Iginition Interpreter - abcdefGets
The Journey of the Code

三限目は、コレクションの演習問題。Meは内職でJavaScriptのバイトコードを調べていた。

昼食。

四限目、五限目は、やはり内職でJavaScriptのバイトコードを調べていた。

六限目は、JavaScriptのエンジンであるd8コマンドをビルドしようと試みたが失敗。

15:30に講義終了。

結局、今日は、内職ばかりやっていた。。。

定時退勤。

夕飯は外で済ませて帰宅。

お風呂入って寝る。

明日は、訓練校1月生 Java基礎演習講座九日目(第17章~第18章)サブ講師予定。

例外処理がメインかな。。。明日でJava基礎演習も修了。

【今後の予定】
・2021年01月~   職業訓練校Java&Python&Web技術者(3か月)

【詳細TODOリスト】
・03/24(AM) 訓練校01月生 データベースとWebシステム概論(JavaEE)

【今日の読書】
多変量統計解析法 田中 豊
平均・分散から始める一般化線形モデル入門 馬場 真哉
Pythonで学ぶあたらしい統計学の教科書 (AI & TECHNOLOGY) 馬場 真哉
心を知るための人工知能: 認知科学としての記号創発ロボティクス (越境する認知科学) 谷口 忠大
物理学者のすごい思考法 (インターナショナル新書) 橋本 幸士
統計学への確率論、その先へ―ゼロからの測度論的理解と漸近理論への架け橋 清水 泰隆
代数幾何学入門:代数学の基礎を出発点として 永井 保成
ランダム行列の数理と科学 渡辺澄夫
認知バイアス 心に潜むふしぎな働き (ブルーバックス) 鈴木 宏昭
絵で見てわかるSQL Serverの仕組み 平山 理(P.84/314読了)
ベイズ統計の理論と方法 渡辺 澄夫
経済・ファイナンスのための カルマンフィルター入門 (統計ライブラリー) 森平 爽一郎(P.21/215読了)
ライブ講義 大学生のための応用数学入門 (KS理工学専門書) 奈佐原 顕郎
心は量子で語れるか―21世紀物理の進むべき道をさぐる (ブルーバックス) ロジャー・ペンローズ(P.71/286読了)
解析力学・量子論 第2版 須藤 靖(P.55/304読了)
数理科学 2020年 11 月号 [雑誌]
人工知能 機械学習はどこまで進化するのか (別冊日経サイエンス239) 竹内郁雄
データ分析の力 因果関係に迫る思考法 (光文社新書) 伊藤 公一朗
一般ゲージ理論と共変解析力学 中嶋 慧
応用に役立つ50の最適化問題 (応用最適化シリーズ) 藤澤 克樹
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Python Tips

2021-03-11 01:01:00 | 日記
Python Tips

今日の訓練校1月生から聞かれたPythonの質問で、直ぐに返答できなかったので、

備忘録として残しておく。

質問は、以下の式が何故Trueになるのか?という質問だった。
1>-1==(1-2)

Pythonでは上記式は
(1>-1) and (-1==(1-2))

と同じ意味になるらしく、Trueになるとのことだった。。。知らなかった。。。

ちなみにdisコマンドで逆アセンブルして検証した結果、

確かに上記式と等価なバイトコードが出力されていた。
  2           0 LOAD_CONST               1 (1)
              2 LOAD_CONST               2 (-1)
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               4 (>)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_CONST               2 (-1)
             14 COMPARE_OP               2 (==)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE

バイトコードの使用は以下のドキュメントを参照の事。

dis --- Python バイトコードの逆アセンブラ
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

【訓練校1月生】Java基礎演習講座七日目サブ講師

2021-03-11 00:40:01 | 日記
【訓練校1月生】Java基礎演習講座七日目サブ講師

今日は水曜日。晴れ。

5時半起床。寝過ごした。

6時過ぎに家を出て、朝食は会社近くの朝マック。

電車の中で、「平均・分散から始める一般化線形モデル入門」を読んでいた。

今日は教科書のスッキリわかるJava入門第3版の14章~15章を講義予定。

JavaAPI、文字列と日付が今日の講義内容。

メイン講師は前会社の入社時の最初の元課長。

時間まで、上記本を読み、第3部読了。

9:00~訓練校講義開始。

一限目は、Object型の説明。

二限目は、教育関係の取締役から某会社のIT技術者養成講座の提案資料が

メールで送られてきたので、研修室を抜け出して、口頭で相談しに行き、

気付け事項を纏め、メールにて返信した。

三限目は、Object型のメソッドについての演習で受講生対応した。

昼食。

四限目は、文字列操作の講義から。演習。

五限目は、正規表現の講義。演習。

六限目は、日付と時間の講義。結構、高速に講義が進み、ギリギリ講義終了。

日付と時間の演習は明日やることになった。

15:30に講義終了。

その後、受講生のサポート対応。Pythonの質問が出たのでバイトコードを教えてあげた。

以下、Pythonのバイトコード命令仕様の一覧。

dis --- Python バイトコードの逆アセンブラ

今日は教育関係の取締役が出張のため、少し早めに時差退勤。

夕飯は外で済ませて帰宅。

簡単にTex環境できるかなあって思ってやっていたら、結局、死んでれらになってしまい、

しかもWindowsで環境構築失敗。WSL2のUbuntuに作ろうとしたら、大量のインストール

が走ってしまい終わらない。。。。とりあえず放っておくことにした。

Ubuntuのインストールは以下の記事を参考にしている。

HEROIC 2021 Ubuntu ソフトウェア

お風呂入って寝る。

明日は、訓練校1月生 Java基礎演習講座八日目(第16章コレクション)サブ講師予定。

【今後の予定】
・2021年01月~   職業訓練校Java&Python&Web技術者(3か月)

【詳細TODOリスト】
・03/24(AM) 訓練校01月生 データベースとWebシステム概論(JavaEE)

【今日の読書】
多変量統計解析法 田中 豊
平均・分散から始める一般化線形モデル入門 馬場 真哉
Pythonで学ぶあたらしい統計学の教科書 (AI & TECHNOLOGY) 馬場 真哉
心を知るための人工知能: 認知科学としての記号創発ロボティクス (越境する認知科学) 谷口 忠大
物理学者のすごい思考法 (インターナショナル新書) 橋本 幸士
統計学への確率論、その先へ―ゼロからの測度論的理解と漸近理論への架け橋 清水 泰隆
代数幾何学入門:代数学の基礎を出発点として 永井 保成
ランダム行列の数理と科学 渡辺澄夫
認知バイアス 心に潜むふしぎな働き (ブルーバックス) 鈴木 宏昭
絵で見てわかるSQL Serverの仕組み 平山 理(P.84/314読了)
ベイズ統計の理論と方法 渡辺 澄夫
経済・ファイナンスのための カルマンフィルター入門 (統計ライブラリー) 森平 爽一郎(P.21/215読了)
ライブ講義 大学生のための応用数学入門 (KS理工学専門書) 奈佐原 顕郎
心は量子で語れるか―21世紀物理の進むべき道をさぐる (ブルーバックス) ロジャー・ペンローズ(P.71/286読了)
解析力学・量子論 第2版 須藤 靖(P.55/304読了)
数理科学 2020年 11 月号 [雑誌]
人工知能 機械学習はどこまで進化するのか (別冊日経サイエンス239) 竹内郁雄
データ分析の力 因果関係に迫る思考法 (光文社新書) 伊藤 公一朗
一般ゲージ理論と共変解析力学 中嶋 慧
応用に役立つ50の最適化問題 (応用最適化シリーズ) 藤澤 克樹
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする