Jump to content
• Advertisement
• entries
628
• comments
1454
• views
1011979

# Epoch JIT Compilation

1028 views

What a hell of a night.

After much tinkering with the Epoch compiler and its internals, I decided to take some time and explore a diversion, just for fun. While the core language is much better off than it was a couple of weeks ago, I've spent so much energy on mundane bug fixes and tiny feature reimplementations that I needed a break.

I'd previously experimented with native code generation via LLVM, but only on a minuscule scale and with the simplest of programs. My project for tonight (yes, I know it's 7AM) was to build out a JIT compilation mode for the Epoch virtual machine, and get at least rudimentary native code execution working.

I'm proud to announce that this project - while taxing and exhausting and far more prolonged than it should have been - is a rousing success.

The code needs a lot of cleanup, and there's some downright hackery going on in a few places, but it works:

This is the Release 12 Epoch compiler building a simple test benchmark and executing it in two modes: one in the "pure" VM mode, and one where some of the arithmetic is offloaded to the JIT compiler and runs as native code. As you can clearly see from the screenshot, the JIT version wins by a handy margin - and it's still far from optimal.

There's still a lot of room for improving the VM itself, of course, and the language has a few crufty edge cases that make it slower than it should be even when JIT compiled to native code. With a little bit of magic and trickery, I can probably get that margin substantially wider.

Last but not least, for the curious, here's the source code to the benchmark:

//// JIT.EPOCH//// Just in time compilation test for Epoch//timeGetTime : -> integer ms = 0 [external("WinMM.dll", "timeGetTime")]entrypoint :{integer four = 1 + 3assert(four == 4)vmbench(2, 3)jitbench(2, 3)}vmbench : integer a, integer b{integer begintime = timeGetTime()integer counter = 0integer result = 0while(counter < 100000){result = vmmath(a, b, result)counter++}integer duration = timeGetTime() - begintimestring durationstr = cast(string, duration)print("VM benchmark lasted: " ; durationstr)string resultstr = cast(string, result)print("Result: " ; resultstr)}jitbench : integer a, integer b{integer begintime = timeGetTime()integer counter = 0integer result = 0while(counter < 100000){result = jitmath(a, b, result)counter++}integer duration = timeGetTime() - begintimestring durationstr = cast(string, duration)print("JIT benchmark lasted: " ; durationstr)string resultstr = cast(string, result)print("Result: " ; resultstr)}vmmath : integer a, integer b, integer accumulator -> integer ret = a * b{ret = ret + accumulator}jitmath : integer a, integer b, integer accumulator -> integer ret = a * b [native]{ret = ret + accumulator}

I would have eliminated some of the code duplication using higher order functions, but indirect function calls would mean another set of JIT wizardry and I'm just too exhausted to care at the moment. That can come later.

If you study the code carefully, you'll notice that there's exactly one difference between the VM and JIT code paths: the [native] tag on the JIT version. This tag indicates to the VM that, when it loads the program, it should JIT compile the function body into native code, and henceforth execute it as such instead of through the VM instruction engine itself.

You may notice that the code is a bit contrived in a few places and could be shorter or more elegant in a few ways. This is mostly due to the fact that the R12 compiler is still a work in heavy progress, and a lot of permutations of syntax don't quite work yet. Thankfully, those are getting fewer and farther between, and it shouldn't be terribly long before the language is back up to par and supports the kind of concision and expressiveness that I've always had in mind.

Assuming, of course, I don't wander back into LLVM land and start fooling around with optimizations again...

## Recommended Comments

Very nice! I've been meaning to play around with LLVM for a while now.

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account

## Sign in

Already have an account? Sign in here.

Sign In Now
• Advertisement
• Advertisement

×

## Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!