rfc:jit
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:jit [2019/02/05 06:37] – dmitry | rfc:jit [2020/08/01 23:41] (current) – RFC was implemented in PHP 8.0 carusogabriel | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: JIT ====== | ====== PHP RFC: JIT ====== | ||
- | * Version: | + | * Version: |
* Date: 2019-01-28 | * Date: 2019-01-28 | ||
* Author: Dmitry Stogov < | * Author: Dmitry Stogov < | ||
- | * Status: | + | * Status: |
* First Published at: https:// | * First Published at: https:// | ||
Line 25: | Line 25: | ||
PHP JIT is implemented as an almost independent part of OPcache. It may be enabled/ | PHP JIT is implemented as an almost independent part of OPcache. It may be enabled/ | ||
- | When enabled, native code of PHP files is stored in an additional region of the OPcache shared memory and op_array-> | + | When enabled, native code of PHP files is stored in an additional region of the OPcache shared memory and op_array-> |
- | We use DynAsm (developed for LuaJIT project) for generation of native code. It's a very lightweight and advanced tool, but does assume good, and very low-level development knowledge of target assembler languages. | + | We use DynAsm (developed for LuaJIT project) for generation of native code. It's a very lightweight and advanced tool, but does assume good, and very low-level development knowledge of target assembler languages. |
+ | PHP JIT doesn' | ||
+ | |||
+ | If type of PHP variable is exactly inferred (in SSA) to LONG or DOUBLE, and it can't be accessed indirectly, JIT may store its value directly in CPU registers, avoiding memory stores and loads. PHP JIT liner-scan register allocation algorithm, tat combines high speed with reasonable quality. | ||
The quality of the JIT may be demonstrated on Mandelbrot benchmark published at https:// | The quality of the JIT may be demonstrated on Mandelbrot benchmark published at https:// | ||
Line 261: | Line 264: | ||
jmp .L10 | jmp .L10 | ||
</ | </ | ||
+ | |||
+ | In comparison to V8, HHVM, PyPy and most others modern JIT implementations PHP JIT is extremely simple, but anyway it increases the level of the whole PHP complexity, risk of new kind of bugs and cost of development and maintenance. | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
Line 273: | Line 278: | ||
==== To Existing Extensions ==== | ==== To Existing Extensions ==== | ||
- | none | + | JIT is going to affect third party debuggers (e.g. xdebug) and profilers (e.g. XHProf, Blackfire, Tideways). |
+ | |||
+ | For debugging a particular request, it's possible to disable JIT (together with opcache) changing " | ||
+ | |||
+ | Run-time profiling should work even with JIT-ed code, but this might require development of additional tracing API and corresponding JIT extension, to generate tracing callbacks. | ||
==== To Opcache ==== | ==== To Opcache ==== | ||
Line 325: | Line 334: | ||
It's planned to provide additional effort, improving JIT for real-life apps, using profiling and speculative optimizations. | It's planned to provide additional effort, improving JIT for real-life apps, using profiling and speculative optimizations. | ||
- | ===== Open Issues | + | ==== JIT Debugging |
- | Make sure there are no open issues | + | As any complication, |
+ | |||
+ | In case of crash, we may just run app under gdb until the crash, check that JIT is involved in crash backtrace and find the place: | ||
+ | |||
+ | < | ||
+ | $ gdb php | ||
+ | |||
+ | (gdb) r app.php | ||
+ | |||
+ | ... | ||
+ | |||
+ | (gdb) bt | ||
+ | |||
+ | #1 0xe960dc11 in ?? () | ||
+ | #2 0x08689524 in zend_execute (op_array=0xf4074460, return_value=0x0) at Zend/ | ||
+ | #3 0x085cb93b in zend_execute_scripts (type=8, retval=0x0, file_count=3) at Zend/ | ||
+ | #4 0x0855a890 in php_execute_script (primary_file=0xffffcbfc) at main/ | ||
+ | #5 0x0868ba25 in do_cli (argc=2, argv=0x9035820) at sapi/ | ||
+ | #6 0x0868c65b in main (argc=2, argv=0x9035820) at sapi/ | ||
+ | </ | ||
+ | |||
+ | Unknown function "??" | ||
+ | |||
+ | < | ||
+ | (gdb) p (char*)executor_global.current_execute_data.func.op_array.filename.val | ||
+ | (gdb) p executor_global.current_execute_data.opline.lineno | ||
+ | </ | ||
+ | |||
+ | Line number may be inaccurate, because JIT doesn' | ||
+ | We may disassemble the code around the bogus instruction to understand the real " | ||
+ | |||
+ | < | ||
+ | (gdb) disassemble 0xe960dc00, | ||
+ | </ | ||
+ | |||
+ | Also, it may be useful to analyse bytecode and assembler dump of the bogus JIT-ed function. | ||
+ | |||
+ | < | ||
+ | $ php --opcache.jit_debug=1 app.php | ||
+ | $ php --opcache.jit_debug=2 app.php | ||
+ | </ | ||
+ | |||
+ | To catch the mistake, we might need to trace the JIT code generator (when it generates | ||
+ | |||
+ | PHP JIT may use GDB API to provide information about generated code to debugger. However, it works only for reasonable small scripts. In case of big amount of JIT-ed code, GDB just stuck registering functions. In case we can isolate the bogus code, we may debug JIT in more comfortable way. | ||
+ | |||
+ | < | ||
+ | $ gdb php | ||
+ | |||
+ | (gdb) r -dopcache.jit_debug=0x100 test.php | ||
+ | ... | ||
+ | |||
+ | (gdb) bt | ||
+ | |||
+ | #1 0xe960dc11 in JIT$foo () at test.php: | ||
+ | #2 0x08689524 in zend_execute (op_array=0xf4074460, | ||
+ | #3 0x085cb93b in zend_execute_scripts (type=8, retval=0x0, file_count=3) at Zend/ | ||
+ | #4 0x0855a890 in php_execute_script (primary_file=0xffffcbfc) at main/ | ||
+ | #5 0x0868ba25 in do_cli (argc=2, argv=0x9035820) at sapi/ | ||
+ | #6 0x0868c65b in main (argc=2, argv=0x9035820) at sapi/ | ||
+ | |||
+ | (gdb) disassemble | ||
+ | ... | ||
+ | (gdb) layout asm | ||
+ | </ | ||
+ | |||
+ | ===== State and compatibility ===== | ||
+ | Currently we support x86 and x86_64 on POSIX platforms (tested on Linux with GCC and LVVM) and Windows (both non-ZTS and ZTS builds). We support " | ||
+ | There are no any restrictions on C compiler and OS any more. | ||
===== Future Scope ===== | ===== Future Scope ===== | ||
Line 332: | Line 409: | ||
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== | ||
- | This project requires a 50%+1 majority. | + | Support for JIT is more a strategic PHP question. JIT definitely requires a lot of work, but it may be actively developed only as a part of PHP, with common effort. |
+ | |||
+ | This project requires a 2/3+1 majority. Voting opened 2019-03-21 and closes 2019-03-28. | ||
<doodle title=" | <doodle title=" | ||
Line 339: | Line 418: | ||
</ | </ | ||
- | As PHP 7.4 is already branched and its engine is not expected to be significantly changed (consequently requiring corresponding changes to the JIT implementation), | + | As PHP 7.4 is already branched and its engine is not expected to be significantly changed (consequently requiring corresponding changes to the JIT implementation), |
+ | |||
+ | In case JIT is not included in PHP-7.4 and PHP-8 introduces language compatibility breaks (it already does), existing applications couldn' | ||
<doodle title=" | <doodle title=" | ||
Line 352: | Line 433: | ||
===== Implementation ===== | ===== Implementation ===== | ||
- | After the project is implemented, | + | Merged |
- | - the version(s) it was merged | + | |
- | | + | |
- | - a link to the PHP manual entry for the feature | + | |
- | - a link to the language specification section (if any) | + | |
===== References ===== | ===== References ===== | ||
- [[https:// | - [[https:// | ||
- [[https:// | - [[https:// | ||
- | |||
- | ===== Rejected Features ===== | ||
- | Keep this updated with features that were discussed on the mail lists. | ||
rfc/jit.1549348667.txt.gz · Last modified: 2019/02/05 06:37 by dmitry