Nikolay Igotti
Simple JIT compiler for your application
Just in time code generation usually considered to be complicated task, and it really is. Although there are cases (for example in multimedia, games or cryptographic application) when it does makes sense to create as optimal inner loops as possible, specific for particular data known only at the runtime. In following sample code for x86 Win32 I will create specialized code which will add specific value to the argument of function. Uses MSVC++ specific inline asm.
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
class Code {
unsigned char* buf;
int size;
int idx;
enum reg {
ax=0, cx, dx, bx, sp, bp, si, di
};
void init_sys();
void generate(int param);
bool put_byte(unsigned char b) {
if (idx >= size) {
return false;
}
buf[idx++] = b;
return true;
}
bool put_int(int i) {
if (idx >= size-4) {
return false;
}
*(int*)(buf+idx) = i;
idx +=4;
return true;
}
void pop(reg r) {
put_byte(0x58 | r);
}
void push(reg r) {
put_byte(0x50 | r);
}
void add(reg r, int imm8) {
put_byte(0x83);
put_byte(0xc0 | r);
put_byte(imm8 & 0xff);
}
void jmp(reg r) {
put_byte(0xff);
put_byte(0xe0 | r);
}
public:
Code(int param);
~Code();
};
void Code::init_sys() {
SYSTEM_INFO si;
GetSystemInfo(&si);
size = si.dwPageSize;
}
Code::Code(int param) : buf(NULL), size(-1), idx(0) {
init_sys();
buf = (unsigned char*) VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
generate(param);
}
Code::~Code() {
VirtualFree(buf, size, MEM_RELEASE);
buf = NULL;
size = 0;
}
void Code::generate(int param) {
add(ax, param);
jmp(dx);
FlushInstructionCache(GetCurrentProcess(), buf, size);
}
int __declspec(naked) invoke(Code* c, int p) {
__asm {
pop edx
mov ecx, [esp]
mov eax, [esp+4]
jmp [ecx]
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Code c1(5), c2(8);
printf("got %d and %d\n", invoke(&c1, 4), invoke(&c2, 4));
getchar();
return 0;
}
Posted at 09:50PM Jun 21, 2007 by nike in Sun | Comments[0]
Comments:
Thursday Jun 21, 2007