Quantcast
Channel: Nikolay Igotti
Viewing all articles
Browse latest Browse all 30

Simple JIT compiler for your application

$
0
0
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 {unsignedchar* 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(unsignedchar 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();	
};voidCode::init_sys() {
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    size =  si.dwPageSize;
  }Code::Code(int param) : buf(NULL), size(-1), idx(0) {
   init_sys();
   buf = (unsignedchar*) VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
                                       PAGE_EXECUTE_READWRITE);
   generate(param);
}Code::~Code() {
    VirtualFree(buf, size, MEM_RELEASE);
    buf = NULL;
    size = 0;	
}voidCode::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;
}

Viewing all articles
Browse latest Browse all 30

Trending Articles