JITの基礎知識についてのいくつかのリンク
Basic JIT
この文章はJITの1つの基本的な原理を述べて、その他の地方の得たバイナリコードを直接メモリに書き込んで、それから強制的なタイプを通じて関数のポインタに転化します..これでJITコードは走ることができます.
Brainfuck JIT
動的にコードをコンパイルするためにGNU Lightningが使用する.コードはやや長く、BFコードをアセンブリ書き込みファイル/
BF-JIT
见えない..
Hello, JIT World: The Joy of Simple JITs
本文はMike PollのDynASMを用いてアセンブリを転化し、各プラットフォームに適応した.
まず、非常に簡単な例です(-!簡単だとは思いませんでした)、この例にはBynASMはありません.
後にBFのJIT例を示して、読めないことを示しています...対応する完全なコードはGitHub上にありますhttps://github.com/haberman/jitdemo
A libjit wrapper for Golang
libjit GNU Cの書いたJITモジュール、教程はほとんど見ることができなくて、とても分かりにくいです.
でもGoのパッケージを見てみるといいと思います.なお、JITがどのように呼び出すかは、以下の例を参照して概ね理解することができる.
Samples https://github.com/eliben/libjit-samples
jit.js - JIT Assembler in javascript
C++のJSパッケージで、中には多くの命令が定義されていて、今は読めません.
How to start JIT-ting
本文は大体いくつかのアセンブリに関する基礎を紹介し、以下のコードの例を示した.ここではesprima解析APIを用いて上のjitを用いる.jsがJITコードを生成するのは、あまり難しくない.
文章の作者はNodeです.jsのコアメンバーの一人で、彼は別のブログでjit.を話しています.jsの例:
https://blog.indutny.com/5.allocating-numbers
Simple VM JIT with LLVM
簡単な加算がLLVMで動的にコンパイルされた例です.简単じゃない
A Basic Just-In-Time Compiler
How to JIT - an introduction
Building a simple JIT in Rust
ブログのトップページに戻ります.http://blog.tiye.me
この文章はJITの1つの基本的な原理を述べて、その他の地方の得たバイナリコードを直接メモリに書き込んで、それから強制的なタイプを通じて関数のポインタに転化します..これでJITコードは走ることができます.
#include // printf
#include // memcpy
#include // mmap, munmap
int main () {
// Hexadecimal x86_64 machine code for: int mul (int a, int b) { return a * b; }
unsigned char code [] = {
0x55, // push rbp
0x48, 0x89, 0xe5, // mov rbp, rsp
0x89, 0x7d, 0xfc, // mov DWORD PTR [rbp-0x4],edi
0x89, 0x75, 0xf8, // mov DWORD PTR [rbp-0x8],esi
0x8b, 0x75, 0xfc, // mov esi,DWORD PTR [rbp-04x]
0x0f, 0xaf, 0x75, 0xf8, // imul esi,DWORD PTR [rbp-0x8]
0x89, 0xf0, // mov eax,esi
0x5d, // pop rbp
0xc3 // ret
};
// allocate executable memory via sys call
void* mem = mmap(NULL, sizeof(code), PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
// copy runtime code into allocated memory
memcpy(mem, code, sizeof(code));
// typecast allocated memory to a function pointer
int (*func) () = mem;
// call function pointer
printf("%d * %d = %d
", 5, 11, func(5, 11));
// Free up allocated memory
munmap(mem, sizeof(code));
}
Brainfuck JIT
動的にコードをコンパイルするためにGNU Lightningが使用する.コードはやや長く、BFコードをアセンブリ書き込みファイル/
BF-JIT
见えない..
Hello, JIT World: The Joy of Simple JITs
本文はMike PollのDynASMを用いてアセンブリを転化し、各プラットフォームに適応した.
まず、非常に簡単な例です(-!簡単だとは思いませんでした)、この例にはBynASMはありません.
mmap
の方法を使って、一時的にメモリに実行可能な権限があることを許可しました.#include
#include
#include
#include
int main(int argc, char *argv[]) {
// Machine code for:
// mov eax, 0
// ret
unsigned char code[] = {0xb8, 0x00, 0x00, 0x00, 0x00, 0xc3};
if (argc < 2) {
fprintf(stderr, "Usage: jit1
");
return 1;
}
// Overwrite immediate value "0" in the instruction
// with the user's value. This will make our code:
// mov eax,
// ret
int num = atoi(argv[1]);
memcpy(&code[1], &num, 4);
// Allocate writable/executable memory.
// Note: real programs should not map memory both writable
// and executable because it is a security risk.
void *mem = mmap(NULL, sizeof(code), PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
memcpy(mem, code, sizeof(code));
// The function will return the user's value.
int (*func)() = mem;
return func();
}
後にBFのJIT例を示して、読めないことを示しています...対応する完全なコードはGitHub上にありますhttps://github.com/haberman/jitdemo
A libjit wrapper for Golang
libjit GNU Cの書いたJITモジュール、教程はほとんど見ることができなくて、とても分かりにくいです.
でもGoのパッケージを見てみるといいと思います.なお、JITがどのように呼び出すかは、以下の例を参照して概ね理解することができる.
Samples https://github.com/eliben/libjit-samples
jit.js - JIT Assembler in javascript
C++のJSパッケージで、中には多くの命令が定義されていて、今は読めません.
How to start JIT-ting
本文は大体いくつかのアセンブリに関する基礎を紹介し、以下のコードの例を示した.ここではesprima解析APIを用いて上のjitを用いる.jsがJITコードを生成するのは、あまり難しくない.
var jit = require('jit.js'),
esprima = require('esprima'),
assert = require('assert');
var ast = esprima.parse(process.argv[2]);
// Compile
var fn = jit.compile(function() {
// This will generate default entry boilerplate
this.Proc(functon() {
visit.call(this, ast);
// The result should be in 'rax' at this point
// This will generate default exit boilerplate
this.Return();
});
});
// Execute
console.log(fn());
function visit(ast) {
if (ast.type === 'Program')
visitProgram.call(this, ast);
else if (ast.type === 'Literal')
visitLiteral.call(this, ast);
else if (ast.type === 'UnaryExpression')
visitUnary.call(this, ast);
else if (ast.type === 'BinaryExpression')
visitBinary.call(this, ast);
else
throw new Error('Unknown ast node: ' + ast.type);
}
function visitProgram(ast) {
assert.equal(ast.body.length,
1,
'Only one statement programs are supported');
assert.equal(ast.body[0].type, 'ExpressionStatement');
visit.call(this, ast.body[0].expression);
}
function visitLiteral(ast) {
assert.equal(typeof ast.value, 'number');
assert.equal(ast.value | 0,
ast.value,
'Only integer numbers are supported');
this.mov('rax', ast.value);
}
function visitBinary(ast) {
// Preserve 'rbx' after leaving the AST node
this.push('rbx');
// Visit right side of expresion
visit.call(this, ast.right);
// Move it to 'rbx'
this.mov('rbx', 'rax');
// Visit left side of expression (the result is in 'rax')
visit.call(this, ast.left);
//
// So, to conclude, we've left side in 'rax' and right in 'rbx'
//
// Execute binary operation
if (ast.operator === '+') {
this.add('rax', 'rbx');
} else if (ast.operator === '-') {
this.sub('rax', 'rbx');
} else if (ast.operator === '*') {
// Signed multiplication
// rax = rax * rbx
this.imul('rbx');
} else if (ast.operator === '/') {
// Preserve 'rdx'
this.push('rdx');
// idiv is diving rdx:rax by rbx, therefore we need to clear rdx
// before running it
this.xor('rdx', 'rdx');
// Signed division, rax = rax / rbx
this.idiv('rbx');
// Restore 'rdx'
this.pop('rdx');
} else if (ast.operator === '%') {
// Preserve 'rdx'
this.push('rdx');
// Prepare to execute idiv
this.xor('rdx', 'rdx');
this.idiv('rbx');
// imul puts remainedr in 'rdx'
this.mov('rax', 'rdx');
// Restore 'rdx'
this.pop('rdx');
} else {
throw new Error('Unsupported binary operator: ' + ast.operator);
}
// Restore 'rbx'
this.pop('rbx');
// The result is in 'rax'
}
function visitUnary(ast) {
// Visit argument and put result into 'rax'
visit.call(this, ast.argument);
if (ast.operator === '-') {
// Negate argument
this.neg('rax');
} else {
throw new Error('Unsupported unary operator: ' + ast.operator);
}
}
文章の作者はNodeです.jsのコアメンバーの一人で、彼は別のブログでjit.を話しています.jsの例:
https://blog.indutny.com/5.allocating-numbers
Simple VM JIT with LLVM
簡単な加算がLLVMで動的にコンパイルされた例です.简単じゃない
A Basic Just-In-Time Compiler
How to JIT - an introduction
Building a simple JIT in Rust
ブログのトップページに戻ります.http://blog.tiye.me