JIT Compilation?

Member
Posts: 567
Joined: 2004.07
Post: #1
Hey, as some of you may know, I'm working on a forth 'compiler' (interpreter), and I was thinking about trying out a JIT compiler
I'm fairly literate in assembly, and I want the compiler to support basic assembly funtions (like they did in the olden days). It's not incredibly USEFUL, I just wanted it for later. You never know when you might want to write a specialized 'scripting' language that needs to be optimized. (e.g. for game logic).

Anyone have any experience, or at least a technical doc toward which you can point me? I've never done dynamic code generation before.

[edit]Right now I just check at runtime to see if a word is built-in or not, and if it is, I call its associated function. I was thinking of generating function pointers at runtime so I can extend that 'feature' to every word. That is precisely what I am looking for.[/edit]

It's not magic, it's Ruby.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
Dump some machine code into a block of memory, make the memory executable (man mprotect), cast the pointer to the memory to the appropriate function pointer type, and call it.

Quick Mac/Intel example:

Code:
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

static uint8_t exit_code[4096] =
{
    0x6A, 0x00,                   /* push $0 (return code) */
    0x6A, 0x00,                   /* push $0 (why? I don't understand) */
    0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax (exit is syscall 1) */
    0xCD, 0x80,                   /* int $0x80 (syscall) */
};

int main(int argc, const char *argv[])
{
    assert(((uintptr_t)exit_code & ~(uintptr_t)0xf) == (uintptr_t)exit_code);
    mprotect(exit_code, 4096, PROT_EXEC);
    ((void (*)(void))exit_code)();
    fprintf(stderr, "should have exited...\n");
    return EXIT_FAILURE;
}

You could also use libJIT (GPLed and Intel only) or LLVM to do your JITting for you.
Quote this message in a reply
Member
Posts: 567
Joined: 2004.07
Post: #3
Hmm, I'll stay away from libJIT (I'm on ppc), but mprotect is exactly what I was looking for.

What the heck are you doing with the assert there? testing whether it is in the first 16 bytes of memory? :/


...or whether it is divisible by sixteen? very confusing...

It's not magic, it's Ruby.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
checking it's 16-byte aligned. I don't think that's actually required, certainly 4 byte alignment seems to be OK on PPC:

Code:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

static uint8_t exit_code[4096] =
{
    0x38, 0x60, 0x00, 0x00, /* li r3, 0 (exit code) */
    0x38, 0x00, 0x00, 0x01, /* li r0, 1 (exit is syscall 1) */
    0x44, 0x00, 0x00, 0x02, /* syscall */
    0x60, 0x00, 0x00, 0x00, /* nop */
};

int main(int argc, const char *argv[])
{
    mprotect(exit_code, 4096, PROT_EXEC);
    ((void (*)(void))exit_code)();
    fprintf(stderr, "should have exited...\n");
    return EXIT_FAILURE;
}
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  GLSL (using CG compilation) mgf1123 1 2,361 Aug 18, 2007 02:33 PM
Last Post: OneSadCookie