This might not be a novel idea, but I just realized earlier today how easy it would be to create an Ahead Of Time compiler for AngelScript that simply spits out C/C++ code.
Using a variant of the test I used while working on my old arm JIT compiler a couple of years ago (just two nested for loops iterating for a bit), this is ~11x faster on that test (on OSX x86-64), but real world performance will vary depending on how your scripts actually look and what they actually do.
This is just a few hours old and I don't have a large AngelScript codebase to test it on, so there might be some tweaking needed for "real" projects.
Quoting myself from the github page I set up:
While there already exists an AngelScript JIT (just in time) Compiler for x86 and x86-64, as well as my old and never finished JIT compiler for arm, there is as far as I know no AOT (ahead of time) compiler available.
Let me first define what I mean with JIT and AOT compilers in the context of AngelScript today. The public JIT compilers I know of take the compiled AngelScript bytecode and turns it into machine code for the supported architecture. This machine code is written to memory marked as being executable and then when the normal AngelScript interpreter comes across a JitEntry byte-code it jumps to this executable memory instead of continuing its normal interpreter loop.
The AOT compiler implementation provided here will instead take the AngelScript bytecode and turn it into C/C++ code which you can then compile with your normal compiler. There are both advantages and disadvantages to this approach and so this project might not be of interest at all for you depending on what you are using AngelScript for.
Let me start by listing a few of the disadvantages:
- If you use AngelScript mainly as a plugin system where 3rd parties write scripts to extend the functionality of your application, this AOT is going to be of little use to you. If however your AngelScript code is a significant part of your software and it's reaching a point where it's starting to need fewer and fewer changes then the AOT might be perfect for you.
- You need to run your program first to generate the AOT code, and then compile and link this newly generated code and run again for the AOT to have any effect. This will limit iteration speed as the program will have to be stopped, compiled, re-linked and started again. In the future I might implement (or if someone submits a pull request) a checksum check to see if the compiled script function is different from what the script actually is doing and if it is fall back to the regular interpreter for that function.
Now to some of the advantages of this approach over a JIT:
- The AOT Compiler is minimal in code and the bits that generate the AOT code is in itself generated straight from AngelScript's code base. This means that:
- It will always be in sync with the AngelScript interpreter since the same code is used
- If new byte codes are added, changed or removed, it'll automatically adapt to this with you just needing to re-run the script that generates the bytecode generating code.
- It will always do exactly what AngelScript does with the bytecode. Again as it's the same code the instances where you run into bugs where the compiled code behaves differently from the interpreter should be slim to none.
- As it's just using basic C/C++ code to generate more C/C++ code compilable with your regular toolchain, the AOT Compiler is machine architecture agnostic whereas JIT compilers only exist on very specific architectures. If you can compile and run AngelScript, you can compile and run the AOT compiler. The AngelScript features page mentions Windows, Linux, MacOS X, XBox, XBox 360, PS2, PSP, PS3, Dreamcast, Nintendo DS, Windows Mobile, iPhone, BSD, and Android, with x86, amd64, sh4, mips, ppc, ppc64, arm, so that's what I'll do too ;)
- No need for allocating executable memory. Not all platforms allow you to allocate executable memory to prevent malicious software or piracy so using a JIT compiler would be impossible on those platforms, but this AOT implementation works just fine.