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;
}
Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

nike

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today