V4

From Qt Wiki
Jump to: navigation, search

V4 Javascript Engine

Why it was created?

Environment Variables

You need to set specific environment variables to debug this engine. In this wiki only few of them are described. To get full list of them you can try to open qtdeclarative.pro and search for text "QV4_.

  • QV4_SHOW_IR - prints intermediate representation of code. It's rather long output because the IR is printed after each of the many optimization passes. Make sure to enable the corresponding debug area, too. (TODO which one is it? I just changed qDebug() to qWarning() in showMeTheCode(IR::Function *function, const char *marker) ...)
  • QV4_SHOW_ASM prints dissassembly output. If it prints message disassembly not available for range, you need to recompile qtdeclarative with CONFIG+=disassembler.
  • QV4_FORCE_INTERPRETER - disables just-in-time compilation. This usually significantly degrades performance and therefore only should be used for debugging purposes.

Platforms without JIT

Having JIT enabled is important to get fluid animations in QML. Still there are platforms that don't support just-in-time compilation for QML. In the better case this simply is because nobody came around to implement this feature for the platform yet. Trouble only occurs if the platform itself restricts usage of JIT, be it App Store policies as for iOS, be it missing sandbox API as for Windows RT.

So what can you do, if it turns out, that JIT is not enabled for your platform?

In-house application for iOS

Easy: Open src/qml/jsruntime/qv4global_p.h, search for references to the Q_OS_IOS macro, and remove the one that explicitly disables JIT support by undefining V4_ENABLE_JIT. Just make sure to comply with all legal requirements when doing so (Apple Enterprise Developer account, proper Qt license,...).

iOS App Store, Windows RT

On this platforms your only hope is to use ahead-of-time compilation (AOT). The QML compiler that's part of Qt Commerical should help you there.

Bad compiler switches, missing platform support

If nothing above applies search src/qml/jsruntime/qv4global_p.h for instances of V4_ENABLE_JIT to understand why JIT is disabled for your platform. With some luck it turns out you are use bad compiler flags. GCC on ARM for instance must support Thumb instructions to make JIT work; check documentation for -mthumb, and -mthunmb-interwork to learn more. In other cases your target CPU simply might not be supported yet. You'll figure out and easily find someone who can remove this limitation.

Hacking

TODO: maybe explain main purprose of some subprojects (where parsing, where optimisations, where jitter is executed..)

Running the EcmaScript 262 Test suite

It's reasonable to verify new features by running the EcmaScript 262 test suite.

  • Check out the test suite submodule repository:
 git submodule update --init tests/auto/qml/ecmascripttests/test262

or

 git submodule update --init --checkout tests/manual/v4/test262

if you're on a Qt version before 5.9

  • Run the tests via the qmake target in the directory above test262:
   qmake
   make check  # Runs with the JIT or interpreter, depending on platform
   make check-interpreter  # Force a run with the interpreter

qjstest

If you're using Qt 5.12 or later, then after running make in the auto-test directory you should find a qjstest program in your bin directory. That can be used during development to run for example sub-sets of the tests like so:

   cd tests/auto/qml/ecmascripttests
   qjstest --with-test-expectations --parallel language/expressions

This would run only the tests that related to expressions, run them in parallel on all cores and compare the results against the expected failures recorded in the TestExpectations file.

You can also run an individual test like so:

   qjstest language/function-code/block-decl-strict.js

If you want to debug a test case, it's advisable to fetch the test together with the harness:

   qjstest --cat language/function-code/block-decl-strict.js > /tmp/test.js

The resulting file is self-contained and can be run with qmljs.

If you are trying to run any of the module tests this way, then you need to make sure instruct qmljs to load the file as a module:

   qjstest --cat language/module-code/parse-export-empty.js > /tmp/test.mjs
   qmljs --module /tmp/test.mjs

If the module test case imports other files (typically with a fixture infix), then you need to copy those files out of the test262 directory manually and adjust the import statements in test.mjs accordingly.