2015年2月27日 星期五

asmjit 與 libjit

大略翻了 asmjit [1] 與 libjit [2] 的實作,大概簡介一下兩者差異:
asmjit 是針對 x86 平台所做的 just-in-time toolkit,可以在 runtime 進行組語編譯並執行,分成兩種 compilation method:
.
1. Assembler: 直接使用 x86 instruction 撰寫編譯,必須寫清楚 register, memory 等 operand。
2. Compiler: 使用抽象化語法進行編譯,不需自己管理暫存器。
.
其中抽象化語法可直接使用 Variable 並且由 Compiler 自行分配暫存器,超出的部分會自動使用 Stack 的空間。

而其語法其實就是 C++,通過調用 FunctionBuilder 來建置 Function ,最後丟給 Compiler 編譯後即可使用,但 Register Allocation 的部分分析能力不強,因此作者建議若有自己做 Analysis 的話,建議還是直接使用 Assembler。 由於是 C++ 實作,asmjit 語法簡潔有力。對 x86 機器的實作算很完整。

而 libjit 較為複雜些,libjit 使用 C 語言實作,編譯單元為 Function,用法類似 asmjit 定義 Function 的方式,但定義起來較為繁瑣。 除了抽象化 opcode 來達到跨平台的目的 (目前支援 arm, x86, x86-64),還實作了 data flow analysis, control flow analysis 來做優化,優化的部分則可以指定等級。

其中 CodeGen 的部分,居然自己定義了一套 DSL 的 parser 來產生類似 LLVM Instruction Table 的定義檔... 完全不容小覷。 據我與 Marttia Barbon 通信內容了解,libjit 產生的 machine code 並不太優。

libjit 中 x86 instruction assembler 的部分,是直接使用 C function 來達成 position independent instruction 的編譯:

    x86_mov_reg_reg(buf, X86_EBP, X86_ESP, 4);

要使用 libjit 來建置一套 language VM 應該是足夠的,只不過 libjit 最近較無積極開發,最近一年的 commit 幾乎都是修正。

2015年2月25日 星期三

CLIFramework - Table Generator

CLIFramework 現在內建 Table Generator,只要輸入 Array,可自動依照不同的 Style 產生 Console 用表格,甚至能輸出成 Markdown 格式表格 (使用 MarkdownStyleTable class)

此套件是參考 Symfony/Console 的 Table Helper 部分功能的重寫及加強,除了 Symfony/Console 現有功能之外:

還可透過指定格屬性 (Cell Attribute),針對單一格或一整列設定色彩、文字對齊或數字格式 (Currency, Number, Duration .. etc)

至於超出欄寬的文字,也可指定使用切斷 (clip), 省略符號 (ellipsis) 或換行 (wrap)

請見範例程式:
https://github.com/c9s/CLIFramework/blob/master/example/table.php


畫面:


2015年2月10日 星期二

閒暇時大致研究了幾個 JIT compiler 實作:

V8 當然不用說,不僅實作了好幾種 CPU 架構的 runtime assembler ,還做了 dynamic re-compilation (Crankshaft engine) 針對 hot code 做 re-compilation。

而 Steffen Müller (@tsee) 的 jit-experimental for Perl 則是將 Perl5 op tree 建構成 libjit 看得懂得 AST,接著丟改 libjit 翻譯回來拿到 machine code,細節沒有看很多,但我猜這個 runtime overhead 一定是很高...
其他使用的 libjit 的 project 則幾乎都是 experimental projects,沒有看到其他使用 libjit 成功的案例。

Reini Urban (@rurbanJit.pm 實作,是把固定幾個 x86 instruction 的 machine code 直接寫成 macro 來使用 (如: x86 prolog, epilog, call, jmp, pushl, popl 等等),然後在模組載入後,把 Perl 的 run op 函數指標 (function pointer) 換成 Jit.pm 自己的實作,接下來就是把一些簡單的 op code 換成預先準備好的 machine code 執行。 但 Jit.pm 一執行就 crash 了..... orz

不過 Jit.pm 也教我幾件事情:
1. memalign 要處理好,不然沒有辦法設置 memory protection
2. self-modifying code 需要呼叫 sys_mprotect 這個修改 page 的 flags ,才能在調用來的記憶體上執行 machine code。
3. Perl 5 有 ASYNC flag (看起來是做 JIT 特別難處理的地方)

現階段看起來,JIT 實作的最佳參考還是 V8
就這樣,有其他細節再繼續做整理...

(以前實在太弱,寫什麼 SIC/XE assembler... 現在覺得當時應該接著練習自幹 x86 assembler 比較實際...)

2015年2月8日 星期日

Getting Merged

昨天在 livehouse 的簡報。但有些內容是現場講的,沒報名到的朋友搜瑞了


libjit 的作者 Rhys Weatherley (dotGNU 的 member) 2009 年時寫到:
"LLVM seems to have been started as a "glorified" static compiler....which aims to (略).... It has been started in 2000, and as of today it is technologically outdated. "
哇....這不是睜眼說瞎話嗎? XD