Sign in to follow this  
WitchLord

First fully functional JIT compiler for AngelScript available

Recommended Posts

The developers at [url="http://www.blind-mind.com/"]Blind Mind Studios[/url] have implemented the first fully functional JIT compiler for AngelScript.

It is now available to the public as an open source project, with the master repository hosted at github.com.

[url="https://github.com/BlindMindStudios/AngelScript-JIT-Compiler"]https://github.com/BlindMindStudios/AngelScript-JIT-Compiler[/url]


I haven't had a chance to test it myself, but what Andrew (Thy Reaper) tells me is quite impressive. With the JIT compiler the performance typically improves between 1.5 to 3 times, and in some cases even reaches levels of native C++ code.

This is especially impressive because the JIT compiler itself is implemented in relatively few lines of code, which makes it perfect for embedding.


Currently the JIT compiler only supports x86, but I'm sure it can be quite easily extended to other CPUs as well.



Post your impressions here.

Also, if there are suggestions for further improving AngelScript to make the JIT compiled code even better I'd love to hear them.

Share this post


Link to post
Share on other sites
This. is. [i]cool[/i].

One of these days I plan on using AngelScript... I just need to find a need for scripting first... and for that to happen I need to stop doing homework and work on hobby projects, but the homework never ends...

Anyway, I'm excited to use this in the future! Thanks Andreas (for AngleScript) and Blind Mind Studios (for the JIT compiler)!

Share this post


Link to post
Share on other sites
Those tests are not rigorous, but still telling:
Large loop with raw arithmetic: 4 times faster.
Constructing and traversing a large "random" binary tree: 2 times faster (expected more here, no native calls are involved).
Bubblesort of ints array (with stock array addon): around 2.5 times faster.

I haven't had the chance to test it in production yet - first I have to eliminate the reliance on std::function as StlPort does not support it - but it appears very promising.

Share this post


Link to post
Share on other sites
Hello everyone, I'm the owner of Blind Mind Studios, and responsible for the JIT. If you have any questions or suggestions, let me know.

[quote name='TheAtom' timestamp='1329411974' post='4913700']
Those tests are not rigorous, but still telling:
Large loop with raw arithmetic: 4 times faster.
Constructing and traversing a large "random" binary tree: 2 times faster (expected more here, no native calls are involved).
Bubblesort of ints array (with stock array addon): around 2.5 times faster
[/quote]

The binary tree is going slower than you might expect because the JIT doesn't natively handle context switches, for a variety of reasons. Any time a script function is called, the JIT has to return to the AngelScript context for it to allocate stack memory, locate pointers, etc. In the case of native calls, on the other hand, many are completely handled by the JIT.

[quote name='_Vicious_' timestamp='1329371174' post='4913577']
wow, that's impressive! the only gripe I have about it is that it depends on C++0x but that's not a critical thing, probably
[/quote]

The primary use of C++0x is for lambdas due to so much use of local variables for the psuedo-assembly (each pseudo-register being a stack local variable).

[quote name='Cornstalks' timestamp='1329345548' post='4913496']
Anyway, I'm excited to use this in the future! Thanks Andreas (for AngleScript) and Blind Mind Studios (for the JIT compiler)!
[/quote]

You're welcome!

Share this post


Link to post
Share on other sites
I think I´ve found a potential problem in the way the JIT is implemented in Angelscript. Blind Mind Studios´ web site shows a sample code for use with their JIT:

[source lang="java"]int main() {
asIScriptEngine* engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

//Create the JIT Compiler. The build flags are explained below,
//as well as in as_jit.h
asCJitCompiler* jit = new asCJITCompiler(0);

//Enable JIT helper instructions; without these,
//the JIT will not be invoked
engine->SetEngineProperty(asEP_INCLUDE_JIT_INSTRUCTIONS, 1);

//Bind the JIT compiler to the engine
engine->SetJITCompiler(jit);

//.............Setup some other stuff, compile and execute your scripts.....

//Clean up your engine. Code pages will automatically be cleared
//by the JIT when the engine is released.
DiscardModules();
engine->Release();
delete jit;

return 0;
}[/source]

The problem is in the last lines: when we call engine->Release(), we´re not destroying the engine, we´re just telling it that we won´t hold a reference to it anymore. The engine might continue to exist for some undefined time. Then we destroy (delete) jit, which actually destroys the JIT compiler (which is kind of the correct thing to do, otherwise we might be leaking memory). What if after that the engine (which still might be alive) tries to access the now defunct JIT? Crash! I think the JIT should also be a reference counted object. Edited by Tzarls

Share this post


Link to post
Share on other sites
[quote name='Tzarls' timestamp='1344483055' post='4967625']
I think I´ve found a potential problem in the way the JIT is implemented in Angelscript. Blind Mind Studios´ web site shows a sample code for use with their JIT:

[source lang="java"]int main() {
asIScriptEngine* engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

//Create the JIT Compiler. The build flags are explained below,
//as well as in as_jit.h
asCJitCompiler* jit = new asCJITCompiler(0);

//Enable JIT helper instructions; without these,
//the JIT will not be invoked
engine->SetEngineProperty(asEP_INCLUDE_JIT_INSTRUCTIONS, 1);

//Bind the JIT compiler to the engine
engine->SetJITCompiler(jit);

//.............Setup some other stuff, compile and execute your scripts.....

//Clean up your engine. Code pages will automatically be cleared
//by the JIT when the engine is released.
DiscardModules();
engine->Release();
delete jit;

return 0;
}[/source]

The problem is in the last lines: when we call engine->Release(), we´re not destroying the engine, we´re just telling it that we won´t hold a reference to it anymore. The engine might continue to exist for some undefined time. Then we destroy (delete) jit, which actually destroys the JIT compiler (which is kind of the correct thing to do, otherwise we might be leaking memory). What if after that the engine (which still might be alive) tries to access the now defunct JIT? Crash! I think the JIT should also be a reference counted object.
[/quote]

IMO you should just call SetJITCompiler(NULL);

/f

Share this post


Link to post
Share on other sites
Alternatively you could store the jitcompiler as the [url="http://www.angelcode.com/angelscript/sdk/docs/manual/classas_i_script_engine.html#aabee8d6ef426c434adee85ec6d57f940"]script engine's user data[/url], and [url="http://www.angelcode.com/angelscript/sdk/docs/manual/classas_i_script_engine.html#a8fa4fc9aacb99db6d4be0a5542b85e35"]register a cleanup function with the engine[/url] to delete the jitcompiler when the engine is deleted.

Share this post


Link to post
Share on other sites
[quote name='quarnster' timestamp='1344492408' post='4967639']

IMO you should just call SetJITCompiler(NULL);

/f
[/quote]

I don´t know if that´s a good idea - it should work only if Angelscript checks the jitCompiler pointer for NULLness and act accordingly.

Share this post


Link to post
Share on other sites
[quote name='Andreas Jonsson' timestamp='1344525721' post='4967812']
Alternatively you could store the jitcompiler as the [url="http://www.angelcode.com/angelscript/sdk/docs/manual/classas_i_script_engine.html#aabee8d6ef426c434adee85ec6d57f940"]script engine's user data[/url], and [url="http://www.angelcode.com/angelscript/sdk/docs/manual/classas_i_script_engine.html#a8fa4fc9aacb99db6d4be0a5542b85e35"]register a cleanup function with the engine[/url] to delete the jitcompiler when the engine is deleted.
[/quote]

The problem I see with this approach is that since one JIT compiler can serve many engines (Blind Mind Studios´ does) in a multi engine scenario it would be a problem to decide which of the engines has to delete the jitCompiler. So I still think that making the JIT a reference counted object might solve all that issues - the engines themselves would release such references when it is safe to do so. Of course the programmer should remember to release the original reference (the one created when he JIT was first constructed).

Share this post


Link to post
Share on other sites

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

Sign in to follow this