The engine as it is today is a fantastic basis and fills most of our users needs. However, it also has a couple of shortcomings and problems that will need to get solved in the future. This series of blogs is going to outline our findings and present the solutions that we are planning to implement for them. The goal will be to get to a better, more flexible and easier to maintain QML engine in the future.
So let’s start of with some of the problems we’re facing with the current engine.
- Several object models
- Bindings done through JS closures
Each binding is represented as a JS function closure towards V8. This requires rewriting the expression as a closure, and then letting V8 parse the rewritten expression once again. Evaluating the binding requires calling a JS function in V8 with quite a bit of overhead to instantiate the proper context for executing the binding. This is rather slow and lead to the development of a small expression interpreter (called V4) inside the QML engine that would evaluate simple expressions. This interpreter is many times faster than evaluating through V8.
- Data type conversions
One reason why evaluation of expressions in V8 is slow is the overhead of converting data types from Qt to V8 and vice versa. Accessing a Qt property would for example create a QVariant, that would then need to be converted to a V8::Value. If the variant was a string this involved copying the string data. To soften this, various caching mechanisms were introduced, but those came at the cost of increased memory usage and additional complexity in the code.
- QML scoping rules
- Throwing away QML type info
- iOS and WinRT support
iOS does not allow making memory both executable and writable, something that existing JS engines require. WinRT doesn’t allow making memory executable at all. This makes it impossible to use V8 on these platforms without writing a full interpreter backend to V8.
- Working with upstream V8
As said above, we are currently forced to maintain a rather large and intrusive patch set on top of V8. There is no chance of merging these patches upstream, as V8 fully focuses on the browser use cases.
These different arguments have lead to a research project that was started Roberto Raggi and Aaron Kennedy in Nokia around a year ago, where they explored the feasibility of having a JS engine that is tailored to the use cases QML requires. The project with the codename v4vm was then transferred to Digia, where Simon, Erik and myself took it up and continued with it. It lived as a playground project on qt-project.org for the last couple of months.
Today we integrated this research project into a development branch of Qt Declarative, and we will continue to work on it there from now on.
The new engine contains a fully compliant ECMAScript 5.1 implementation, that runs on all platforms Qt supports. It contains a JIT that currently works on Linux, Mac and iOS. Integration into the current QML engine is currently done through a V8 compatible API layer which we plan to remove in the coming weeks. The engine can run all Qt Quick demos (with some minor glitches).
One of the things to note is that the engine is focused at QML use cases. This implies that we expect QML performance to become a lot better then it is today. Pure JS performance will on the other hand not be quite as good as what you get with V8 as a backend.
Still our current benchmark numbers are very promising also for pure JS code. The V8 benchmark runs currently around three times slower than the JS engine used in Qt 4.8 and Qt Quick 1, and we see a lot of potential for further optimisations.
Details about the new engine and our future plans will come in a followup post. You can find the code in the wip/v4 branch in the qtdeclarative repository. Feel free to play around with it. If you want to join development, feel free to contact us on #qt-v4vm on freenode.