Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A new PHP JIT implementation based on IR JIT framework #12079

Merged
merged 259 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
259 commits
Select commit Hold shift + click to select a range
4cf9a2a
IR update
dstogov Nov 29, 2022
edad2d3
Use folding to allow constant folding and common subexpression elimin…
dstogov Nov 29, 2022
55a9cb3
Implement IR JIT for INIT_FCALL, INIT_FCALL_BY_NAME and INIT_NS_FCALL…
dstogov Nov 30, 2022
98fee72
Implement IR JIT for SEND_VAL and SEND_VAL_EX
dstogov Dec 1, 2022
f4965fc
Implement IR JIT for SEND_REF
dstogov Dec 1, 2022
89d47ab
Implement IR JIT for SEND_VAR* instructions (incompltere - few tests …
dstogov Dec 2, 2022
552bcb5
Implement IR JIT for CHECK_FUNC_ARG
dstogov Dec 5, 2022
7cd0c70
Implement IR JIT for CHECK_UNDEF_ARGS
dstogov Dec 5, 2022
44481d4
Implement IR JIT for ROPE_INIT, ROPE_ADD and ROPE_END
dstogov Dec 5, 2022
0aeddcc
Implement IR JIT for FREE, FE_FREE, ECHO, STRLEN and COUNT
dstogov Dec 5, 2022
5809fd5
Implement IR JIT for IN_ARRAY
dstogov Dec 5, 2022
e486bba
Implement IR JIT support for separate VM stack overflow check
dstogov Dec 5, 2022
3486ad2
Implement IR JIT for INIT_DYNAMIC_CALL
dstogov Dec 5, 2022
cc5af33
Implemenr IR JIT for INIT_METHOD_CALL
dstogov Dec 7, 2022
60d25ca
Fix IR JIT for IN_ARRAY and COUNT
dstogov Dec 7, 2022
297ecdb
Implement IR JIT for VERIFY_RETURN_TYPE
dstogov Dec 7, 2022
b1240f5
Force C compiler to store preserved registers to allow JIT using them
dstogov Dec 9, 2022
044de77
Implement IR JIT for DO_FCALL, DO_UCALL, DO_ICALL and DO_FCALL_BY_NAME
dstogov Dec 9, 2022
8197542
Implement IR JIT for FETCH_CONSTANT
dstogov Dec 12, 2022
5730e0a
Fix (reverse) guard conditions
dstogov Dec 12, 2022
ef9a24e
Implement IR JIT for RECV and RECV_INIT
dstogov Dec 12, 2022
c770d92
Implement IR JIT for RETURN
dstogov Dec 13, 2022
2d10c54
Implement IR JIT for BIND_GLOBAL
dstogov Dec 14, 2022
ac8c561
Fix guard for: int++ => double
dstogov Dec 14, 2022
f562c2b
Fix exception handling
dstogov Dec 14, 2022
ad120f9
Allow deoptimization of zval type only (if some register is spilled b…
dstogov Dec 14, 2022
ce81c2c
Fix overflow handling
dstogov Dec 14, 2022
a0c5322
Implement IR JIT for FE_RESET_R and FE_FETCH_R
dstogov Dec 15, 2022
4fc8807
Eliminate extra temporary register
dstogov Dec 16, 2022
5bde17c
Better registers usage
dstogov Dec 16, 2022
5205bca
Implement IR JIT for FETCH_DIM_* and ISSET_DIM
dstogov Dec 22, 2022
da68de6
Implement IR JIT for ASSIGN_DIM and ASSIGN_DIM_OP
dstogov Dec 26, 2022
3a83946
cleanup
dstogov Dec 27, 2022
6a389e8
Generae IR that produces a better x86[_64] code
dstogov Dec 27, 2022
b3f2b80
Allow trace register allocation for live ranges terminated before ent…
dstogov Dec 28, 2022
489fa45
Remove following END->BEGIN nodes during IR construction
dstogov Dec 28, 2022
2bc29a1
Remove useless (duplicate) guard
dstogov Dec 28, 2022
477cd93
Avoid useless exception check
dstogov Dec 28, 2022
322b985
Prevent duplicate store
dstogov Dec 28, 2022
a79bf60
Eliminate repatable re-assignment of stack zval types
dstogov Dec 28, 2022
f629619
Enable combination of some instructions with the following SEND_VAL f…
dstogov Dec 28, 2022
13f4ed4
Avoid generation of useless RLOADs
dstogov Dec 28, 2022
fe0255c
Eliminatare refcouting in a sequence of FETCH_DIM_R
dstogov Dec 28, 2022
8b21f1b
Fix assertion
dstogov Dec 28, 2022
b527559
Remove ZREG_ZVAL_ADDREF flag from an element of abstract stack
dstogov Dec 29, 2022
55ec6e3
Implement IR JIT for FETCH_OBJ_*
dstogov Jan 11, 2023
e264431
Implement IR JIT for ASSIGN_OBJ
dstogov Jan 11, 2023
c44c7c5
Implement IR JIT for ASSIGN_OBJ_OP
dstogov Jan 11, 2023
d2d73e9
cleanup
dstogov Jan 11, 2023
ac857f6
Implement IR JIT for (PRE/POST)_(INC/DEC)_OBJ
dstogov Jan 12, 2023
df6be03
ws
dstogov Jan 12, 2023
f59583c
cleanup
dstogov Jan 12, 2023
fb77e41
Fix IR JIT for constructor call
dstogov Jan 13, 2023
4d2ba14
Fix opcache.jit=1201 IR JIT.
dstogov Jan 13, 2023
fcd0163
Fix IR construction for the case when both IF targets are the same
dstogov Jan 13, 2023
996a7e7
Avoid PHP LEAVE code duplication in function IR JIT.
dstogov Jan 13, 2023
f8b4a0d
Reload operands from memeory when overflow (this improves hot code)
dstogov Jan 13, 2023
f70097b
Implement IR JIT for SWITCH_LONG, SWITCH_STRING and MATCH
dstogov Jan 18, 2023
2849dfd
Initialize result to IS_UNDEF
dstogov Jan 18, 2023
9b5b90a
Fix JIT integraion with observer (Zend/tests/gh10346.phpt failure)
dstogov Jan 19, 2023
32fe8e6
Fix incorrect compilation of FE_FETCH with predicted empty array
dstogov Jan 19, 2023
da4fe5a
Fix register allocation
dstogov Jan 19, 2023
8621618
Use sign extension inxted of zero
dstogov Jan 19, 2023
9bbeedb
Fix trace register allocator
dstogov Jan 19, 2023
8663d75
cleanp
dstogov Jan 20, 2023
9906d8d
Fix address sanitizer warning
dstogov Jan 20, 2023
5793566
Calculate JIT trace prologue sixe on startup (to avoid magic constants).
dstogov Jan 20, 2023
761e5c6
Add cgecks for merge arrays overflow (this should be refactored using…
dstogov Jan 20, 2023
1214ab1
Cache TLS access to perform corresponding read once per basic block
dstogov Jan 23, 2023
1da98f0
cleanup unused variable
dstogov Jan 23, 2023
7429a46
Fix IR JIT support for CLANG build (CALL VM without global register v…
dstogov Jan 24, 2023
081effc
Fix IR JIT for CALL VM with global register variables
dstogov Jan 24, 2023
8b6f985
Allow %rpb ysage in JIT for CALL VM (we save and restore it in prolog…
dstogov Jan 24, 2023
55771f4
cleanup
dstogov Jan 24, 2023
4b94e20
Allocate enough fixed stack to keep preserved registers
dstogov Jan 26, 2023
1152ddf
We don't have to care about x29 and x30
dstogov Jan 26, 2023
7dce8f4
cleanup (JMPZ/NZ_EX work fine)
dstogov Jan 26, 2023
f41b9a8
Revert "cleanup (JMPZ/NZ_EX work fine)"
dstogov Jan 26, 2023
b2bfab2
Don't allocate register for PHP variables that are loaded from memory…
dstogov Jan 26, 2023
6736fb0
Eliminate redundand deoptimization stores
dstogov Jan 26, 2023
60c23fb
cleanup
dstogov Jan 27, 2023
406d312
cleanup
dstogov Jan 27, 2023
d03e088
cleanup
dstogov Jan 27, 2023
df99df2
Optimization for constant comparison
dstogov Jan 30, 2023
7efbceb
Cleanup and elimination of dead deoptimization stores
dstogov Jan 30, 2023
a65d2bd
Eliminate duplicate constant loading
dstogov Jan 30, 2023
fff2212
Set proper initial SP offset info for GDB backtraces
dstogov Jan 31, 2023
aae334a
Add spill stores
dstogov Jan 31, 2023
2407368
Remove low limit on number of deoptimization constants
dstogov Jan 31, 2023
21ba94c
Emit dead code only when it's really necessary for IR graph
dstogov Jan 31, 2023
e8f11e4
cleanup
dstogov Jan 31, 2023
7d4c939
cleanup
dstogov Jan 31, 2023
538d8a7
Prefer loading long constants from memory (instead of loading immedia…
dstogov Feb 1, 2023
2fe61cd
Regiter disasm labels using macros (add missing helpers)
dstogov Feb 1, 2023
c876936
Make IR franework to care about GUARD JMP reordering
dstogov Feb 1, 2023
803b287
Avoid reloading
dstogov Feb 1, 2023
ef05026
Improve register allocation for IR tracing JIT
dstogov Feb 1, 2023
04eab37
Add comment
dstogov Feb 2, 2023
7b07b86
Fix deoptimization on result type guard of FETCH_DIM_R and FETCH_OBJ_R
dstogov Feb 2, 2023
9de67d3
If HYBRID VM can't provide some stack space for JIT code in "red zone…
dstogov Feb 3, 2023
ba60549
Dump IR for stubs only if disassembling of stubs is requested
dstogov Feb 3, 2023
eaaa6b8
Revert "Dump IR for stubs only if disassembling of stubs is requested"
dstogov Feb 3, 2023
e36025f
Dump IR for stubs only if disassembling of stubs is requested (anothe…
dstogov Feb 3, 2023
7ff8824
Improve overflow deoptimization for ADD(_,1) and SUB(_,1)
dstogov Feb 6, 2023
4857023
Switch to IR Builder API
dstogov Feb 10, 2023
ae64b0d
Switch to new IR builder macros
dstogov Feb 13, 2023
c0ab97d
Fix jit_set_Z_TYPE_INFO() call. op3 is a simple constant (not a ir_ref).
dstogov Feb 13, 2023
3707beb
Generate better code
dstogov Feb 14, 2023
57de2f6
Enable empty ENTRY block merging
dstogov Feb 14, 2023
a1d5856
Improve code generated for array separation/creation before an update
dstogov Feb 14, 2023
38e742d
Fix incorrect deleteion of PHI source (op1 is used for control link)
dstogov Feb 15, 2023
f025b93
Load constant once
dstogov Feb 15, 2023
942a815
cleanup
dstogov Feb 15, 2023
405e639
Improve control-flow to avoid two IS_ARRAY checks for REFERENCEs
dstogov Feb 15, 2023
3468833
Update comments
dstogov Feb 16, 2023
0b2ed32
cleanup
dstogov Feb 16, 2023
1701e06
Clenup comments
dstogov Feb 16, 2023
fb44261
Fix AAarch 64 build (disable stack adjustment auto-detection)
dstogov Feb 16, 2023
84b3b70
Add filename and line number to closure names
dstogov Feb 17, 2023
777c540
Reserve stack for parameter passing
dstogov Feb 17, 2023
10f4b61
Increase size of CPU stack reserved for JIT-ed code
dstogov Feb 17, 2023
881a259
Fix addess sanitizer warnings
dstogov Feb 17, 2023
4031616
Clenup: introduce OPTIMIZE_FOR_SIZE macro (disabled by default)
dstogov Feb 17, 2023
c84db8d
Port 08e759120690520e99f9f2d38afeb21bcd1de197 to IR JIT
dstogov Feb 21, 2023
faf8c45
cleanup
dstogov Feb 21, 2023
e311d2f
Preload constant and use tests that may be compiled into better code
dstogov Feb 21, 2023
76d1a5f
Convert helpers to stubs
dstogov Feb 21, 2023
ffd6526
Introduce a helper data structure (ir_refs) to collect references for…
dstogov Feb 22, 2023
b9f1792
Use ir_refs
dstogov Feb 22, 2023
fd00ea6
Improve code generated by zend_jit_zval_copy_deref()
dstogov Feb 22, 2023
65167f8
Use "cold" attribute to influence IR block scheduler and achieve bett…
dstogov Feb 22, 2023
6c4e883
Keep info collected by recursion analyzer
dstogov Feb 24, 2023
ed87e39
Use HTTPS URL to allow fetching without a SSH key
dstogov Mar 2, 2023
3e57c1e
Update IR
dstogov Mar 3, 2023
604fad7
Update IR
dstogov Mar 3, 2023
2c880eb
Add IR JIT support for Wondows (Win64 support is incomplete)
dstogov Mar 3, 2023
b055d21
Update IR
dstogov Mar 3, 2023
79d1f66
Update IR
dstogov Mar 7, 2023
b7cff55
Fix support for Windows ZTS build
dstogov Mar 7, 2023
4711eb3
Fix stack alignment
dstogov Mar 7, 2023
4336048
Cleanup ir_ctx.control usage
dstogov Mar 10, 2023
55131b7
Fixed support for irreducable (incomplete) and merged loops
dstogov Mar 14, 2023
56460c2
Revert "Fixed support for irreducable (incomplete) and merged loops"
dstogov Mar 14, 2023
f78bfaa
Generate better code for RECV_ENTRies
dstogov Mar 14, 2023
dfcf747
Use simpler and more efficient checks
dstogov Mar 15, 2023
0f75000
Switch to new ENTRY node concept
dstogov Mar 17, 2023
a4ad9c7
Limit register usage across the OSR ENTRY point
dstogov Mar 22, 2023
32a8fef
Upate MEM type only if we write to memory
dstogov Mar 22, 2023
f8ed858
Use LOOP_END without a reference edge
dstogov Mar 22, 2023
4cd2643
Use new ir_init() prototype
dstogov Mar 28, 2023
c2a1776
Delay LOAD for better LOAD fusion
dstogov Mar 30, 2023
f7afc2f
Fix RECV/RECV_INIT compilation with opcache.jit=1235
dstogov Apr 6, 2023
3226320
iPtoperly compile fake closures (they mau be called as regular functi…
dstogov Apr 6, 2023
1d754b5
Fix reabase
dstogov Apr 6, 2023
ef27251
Fix rebase and add --with-capstone support for IR JIT
dstogov Apr 6, 2023
50b4e3f
Replace zend_uchar -> uint8_t
dstogov Apr 6, 2023
bd4bd8b
IR JIT support for delayed destructor for zend_assign_to_typed_ref/prop
dstogov Apr 6, 2023
7db3bd3
Handle zend_execute_internal in IR JIT
dstogov Apr 6, 2023
4d92a31
Fix readonly+clone IR JIT issues
dstogov Apr 6, 2023
1a302b1
Switch to ir_ctx.mflags
dstogov Apr 18, 2023
985912d
Ckeanup "inputs_count" access
dstogov Apr 21, 2023
9b5c075
Disable CSE for nodes bound to PHP local varibles
dstogov Apr 25, 2023
9c98c0d
Fix deoptimization code when link traces
dstogov Apr 26, 2023
7c0f937
Fix missing type store
dstogov Apr 26, 2023
ffa84ce
Fix tracing JIT for overflowing INC/DEC
dstogov Apr 26, 2023
f9022f5
Remove ir_remove_unreachable_blocks() call. Now it's called by ir_bui…
dstogov Apr 27, 2023
3950ee2
IR JIT: Fixed inaccurate range inference usage for UNDEF/NULL/FALSE
dstogov May 2, 2023
4bd5650
IR JIT: Fixed GH-11127 (JIT fault)
dstogov May 2, 2023
b311658
Avoid allocation of unused exit point
dstogov May 10, 2023
fb99de1
Don't record already stored PHP variables in SNAPSHOTs
dstogov May 10, 2023
6d909c3
Delay variable load
dstogov May 10, 2023
62c437e
Disable CSE across ENTRY
dstogov May 10, 2023
820c765
Fixed disabling CSE
dstogov May 10, 2023
008f245
Fix deoptimization
dstogov May 11, 2023
c542bd8
Fixed deoptimization
dstogov May 11, 2023
fcb55df
Disable incorrect register allocation
dstogov May 11, 2023
d78c858
Fix JIT for INDENTICAL+JMPZ_EX
dstogov May 11, 2023
0a18004
Add comments
dstogov May 11, 2023
555f8c7
Fixed missed type stores
dstogov May 12, 2023
c2bbd76
IR JIT: added support for CLDEMOTE
dstogov May 15, 2023
ccf1b31
Fixed incorrect constant usage
dstogov May 17, 2023
3f2b7f6
Disable compilation of PHP functions with irreducible CGF
dstogov May 23, 2023
1574d12
Fixed liveness check
dstogov May 23, 2023
a04286d
Fixed code for constant conditional jump
dstogov May 23, 2023
08e79dc
Add type store to avoid use-after-free
dstogov May 23, 2023
61feb23
Fixed liveness analyses
dstogov May 24, 2023
971a4c8
Gnerate SNAPSHOT for virtual method calls
dstogov May 24, 2023
0520487
More accurate search for staticaly inferred info about a trace SSA va…
dstogov May 24, 2023
a0b5478
Fix incorrect result use type_info
dstogov May 24, 2023
677c987
Fix JMPZ/NZ_EX support and missing type store
dstogov May 25, 2023
28a7426
Fixed trace type inference and missing type store
dstogov May 25, 2023
0a71689
Store type of unused CV to prevent possible following use after free
dstogov May 26, 2023
e85e864
Fixed deoptimizaton info
dstogov May 31, 2023
53b55d1
Fixed stack layout
dstogov May 31, 2023
147323a
Implemented support for veneers on AArch64
dstogov Jun 1, 2023
7b82954
Dsable CSE to avoid over-optimization
dstogov Jun 7, 2023
5302cb6
Don't bind nodes for TMP PHP variables
dstogov Jun 7, 2023
30670ba
Re-enable CSE for temporary variables as we don't bind them anymore
dstogov Jun 7, 2023
4a81c49
Switch to CPU stack spill slots
dstogov Jun 15, 2023
3025e8b
Add codegen info dump
dstogov Jun 21, 2023
1f7d4e0
Initialize CV variables through FP (this enables some folding optimiz…
dstogov Jun 29, 2023
825af91
Use zero-extension that can be eliminated
dstogov Jul 4, 2023
68e956d
Avoid generation of dead PHIs
dstogov Aug 1, 2023
d8c3d8d
Increase preallocated spill stack size
dstogov Aug 2, 2023
fd31208
Enable IR based JIT by default
dstogov Aug 29, 2023
31390eb
Fixed build with -disable-opcache-jit
dstogov Aug 31, 2023
3091305
Use explicit type conversion & force load values to registerts
dstogov Aug 31, 2023
2e71a2a
Fix IR build
dstogov Aug 31, 2023
05a7cc0
Checkout submodules in github actions
dstogov Aug 31, 2023
36e1d9a
Fixed Windows build
dstogov Aug 31, 2023
736723a
Fixed Windows build
dstogov Aug 31, 2023
df9e215
Fixed reattach to IR JIT SHM
dstogov Aug 31, 2023
375cca1
Update IR
dstogov Sep 1, 2023
3708d5d
Checkout submodules in nightly CI
dstogov Sep 1, 2023
2e2144e
Fix MACOS ZTS in IR JIT
dstogov Sep 4, 2023
a6cffcc
Update ir
dstogov Sep 4, 2023
f099941
Fixed incorrect register allocation
dstogov Sep 5, 2023
dabf2c6
Fixed incorect code generation
dstogov Sep 5, 2023
33bebb6
Fixed tracing jit for BIND_INIT_STATIC_OR_JMP
dstogov Sep 5, 2023
a18cc16
Update README
dstogov Sep 6, 2023
ab40832
Typos
dstogov Sep 11, 2023
fa418a6
Revert JIT disabling for run-tests.php workers
dstogov Sep 11, 2023
60ab2ff
Fixed code review issues
dstogov Sep 11, 2023
54d40de
Update IR
dstogov Sep 12, 2023
e7c04ec
Update IR
dstogov Sep 12, 2023
16b82b2
Update IR
dstogov Sep 12, 2023
b189b91
Allow exit_point duplication, when the deoptimization info differs be…
dstogov Sep 14, 2023
654ae29
Use bound spill slots for CV (once again)
dstogov Sep 14, 2023
15bbe57
Improve error handling
dstogov Sep 14, 2023
0605bd2
Removed IR submodule
dstogov Sep 14, 2023
87b85aa
Remove IR submodule from workflows
dstogov Sep 14, 2023
afc773a
Embed IR
dstogov Sep 14, 2023
a2ea5d2
Add .gitignore
dstogov Sep 14, 2023
1ce6646
Fixed according to feedback
dstogov Sep 18, 2023
7e77941
Force C saving preserved registers only for HYBRID VM
dstogov Sep 18, 2023
943ec88
Update IR
dstogov Sep 18, 2023
87666da
cleanup
dstogov Sep 18, 2023
e64b2b7
Replace ZEND_ASSERT(0) by ZEND_UNREACHABLE()
dstogov Sep 19, 2023
72ade5c
Update IR and remove unused IR files
dstogov Sep 19, 2023
74e82f2
Fixed inconsistency between IR code-generation and register-allocation
dstogov Sep 26, 2023
c417f21
Update IR
dstogov Oct 11, 2023
290059a
Update ir_PHI*() according to IR construction API changes
dstogov Oct 11, 2023
053772d
Fixed 32-bit build
dstogov Oct 11, 2023
02a9d73
Update IR
dstogov Oct 18, 2023
7fba3de
Support for ir_TAILCALL() prototype changes
dstogov Oct 18, 2023
2ac2190
Update IR
dstogov Oct 18, 2023
44451b0
Fixed incorrect extension (ZEXT->SEXT)
dstogov Oct 18, 2023
487b22f
Fix SSA dominance
dstogov Oct 19, 2023
193a03d
Update IR
dstogov Oct 20, 2023
66d40ad
Fixed support ir_ctx.ret_type
dstogov Oct 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions Zend/zend_vm_execute.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions Zend/zend_vm_execute.skl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex)

{%INTERNAL_LABELS%}

#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
/* Force C compiler to store preserved registers to allow JIT using them */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this not make problems with MSVC or non-GNU-compatible C compilers? (e.g. intel ICC)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand you don't save esi and edi in i386 for example because they are global registers. Same reasoning for other architectures.
What if GCC global regs is not enabled? Don't you then need to save those registers too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this not make problems with MSVC or non-GNU-compatible C compilers? (e.g. intel ICC)?

MSVC is not affected by this macros an JIT produces a less efficient code.
ICC is actually based on GCC.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand you don't save esi and edi in i386 for example because they are global registers.

esi and edi are saved/restored manually through orig_opline ans orig_execute_data.

What if GCC global regs is not enabled?

e.g. for CLANG build...

Don't you then need to save those registers too?

Good catch. The current JIT implementation uses this feature only for HYBRID VM.
It probably makes sense to wrap this builtins with ``#if```.

For CALL VM, JIT now saves/restores all the preserved registers, but this may be improved, at least for CLANG.

# if defined(__GNUC__) && defined(__i386__)
__asm__ __volatile__ (""::: "ebx");
# elif defined(__GNUC__) && defined(__x86_64__)
__asm__ __volatile__ (""::: "rbx","r12","r13");
# elif defined(__GNUC__) && defined(__aarch64__)
__asm__ __volatile__ (""::: "x19","x20","x21","x22","x23","x24","x25","x26");
# endif
#endif
LOAD_OPLINE();
ZEND_VM_LOOP_INTERRUPT_CHECK();

Expand Down
8 changes: 4 additions & 4 deletions Zend/zend_vm_gen.php
Original file line number Diff line number Diff line change
Expand Up @@ -2046,14 +2046,14 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
} else {
out($f,"#if defined(ZEND_VM_IP_GLOBAL_REG) || defined(ZEND_VM_FP_GLOBAL_REG)\n");
out($f,$m[1]."struct {\n");
out($f,"#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE\n");
out($f,$m[1]."\tchar hybrid_jit_red_zone[ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE];\n");
out($f,"#endif\n");
out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
out($f,$m[1]."\tconst zend_op *orig_opline;\n");
out($f,"#endif\n");
out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
out($f,$m[1]."\tzend_execute_data *orig_execute_data;\n");
out($f,"#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE\n");
out($f,$m[1]."\tchar hybrid_jit_red_zone[ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE];\n");
out($f,"#endif\n");
out($f,"#endif\n");
out($f,$m[1]."} vm_stack_data;\n");
out($f,"#endif\n");
Expand Down Expand Up @@ -2339,7 +2339,7 @@ function gen_vm_opcodes_header(
$str .= "\n";
$str .= "#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) && !defined(__SANITIZE_ADDRESS__)\n";
$str .= "# if ((defined(i386) && !defined(__PIC__)) || defined(__x86_64__) || defined(_M_X64))\n";
$str .= "# define ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE 16\n";
$str .= "# define ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE 48\n";
$str .= "# endif\n";
$str .= "#endif\n";
$str .= "\n";
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_vm_opcodes.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions build/Makefile.global
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ clean:
rm -f ext/opcache/jit/zend_jit_x86.c
rm -f ext/opcache/jit/zend_jit_arm64.c
rm -f ext/opcache/minilua
rm -f ext/opcache/jit/ir/gen_ir_fold_hash
rm -f ext/opcache/jit/ir/minilua
rm -f ext/opcache/jit/ir/ir_fold_hash.h
rm -f ext/opcache/jit/ir/ir_emit_x86.h
rm -f ext/opcache/jit/ir/ir_emit_aarch64.h

distclean: clean
rm -f Makefile config.cache config.log config.status Makefile.objects Makefile.fragments libtool main/php_config.h main/internal_functions_cli.c main/internal_functions.c Zend/zend_dtrace_gen.h Zend/zend_dtrace_gen.h.bak Zend/zend_config.h
Expand Down
70 changes: 68 additions & 2 deletions ext/opcache/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ PHP_ARG_WITH([capstone],,
[no],
[no])

PHP_ARG_ENABLE([opcache-jit-ir],
[whether to enable JIT based on IR framework],
[AS_HELP_STRING([--disable-opcache-jit-ir],
[Disable JIT based on IR framework (use old JIT)])],
[yes],
[no])

if test "$PHP_OPCACHE" != "no"; then

dnl Always build as shared extension
Expand All @@ -44,7 +51,7 @@ if test "$PHP_OPCACHE" != "no"; then
esac
fi

if test "$PHP_OPCACHE_JIT" = "yes"; then
if test "$PHP_OPCACHE_JIT" = "yes" -a "$PHP_OPCACHE_JIT_IR" = "no" ; then
AC_DEFINE(HAVE_JIT, 1, [Define to enable JIT])
ZEND_JIT_SRC="jit/zend_jit.c jit/zend_jit_gdb.c jit/zend_jit_vm_helpers.c"

Expand Down Expand Up @@ -86,6 +93,62 @@ if test "$PHP_OPCACHE" != "no"; then

PHP_SUBST(DASM_FLAGS)
PHP_SUBST(DASM_ARCH)

JIT_CFLAGS=

elif test "$PHP_OPCACHE_JIT" = "yes" -a "$PHP_OPCACHE_JIT_IR" = "yes"; then
AC_DEFINE(HAVE_JIT, 1, [Define to enable JIT])
AC_DEFINE(ZEND_JIT_IR, 1, [Use JIT IR framework])
ZEND_JIT_SRC="jit/zend_jit.c jit/zend_jit_vm_helpers.c jit/ir/ir.c jit/ir/ir_strtab.c \
jit/ir/ir_cfg.c jit/ir/ir_sccp.c jit/ir/ir_gcm.c jit/ir/ir_ra.c jit/ir/ir_save.c \
jit/ir/ir_dump.c jit/ir/ir_gdb.c jit/ir/ir_perf.c jit/ir/ir_check.c \
jit/ir/ir_patch.c jit/ir/ir_emit.c"

dnl Find out which ABI we are using.
case $host_alias in
x86_64-*-darwin*)
IR_TARGET=IR_TARGET_X64
DASM_FLAGS="-D X64APPLE=1 -D X64=1"
DASM_ARCH="x86"
;;
x86_64*)
IR_TARGET=IR_TARGET_X64
DASM_FLAGS="-D X64=1"
DASM_ARCH="x86"
;;
i[[34567]]86*)
IR_TARGET=IR_TARGET_X86
DASM_ARCH="x86"
;;
x86*)
IR_TARGET=IR_TARGET_X86
DASM_ARCH="x86"
;;
aarch64*)
IR_TARGET=IR_TARGET_AARCH64
DASM_ARCH="aarch64"
;;
esac

AS_IF([test x"$with_capstone" = "xyes"],[
PKG_CHECK_MODULES([CAPSTONE],[capstone >= 3.0.0],[
AC_DEFINE([HAVE_CAPSTONE], [1], [Capstone is available])
PHP_EVAL_LIBLINE($CAPSTONE_LIBS, OPCACHE_SHARED_LIBADD)
PHP_EVAL_INCLINE($CAPSTONE_CFLAGS)
ZEND_JIT_SRC+=" jit/ir/ir_disasm.c"
],[
AC_MSG_ERROR([capstone >= 3.0 required but not found])
])
])

PHP_SUBST(IR_TARGET)
PHP_SUBST(DASM_FLAGS)
PHP_SUBST(DASM_ARCH)

JIT_CFLAGS="-I@ext_builddir@/jit/ir -D${IR_TARGET} -DIR_PHP"
if test "$ZEND_DEBUG" = "yes"; then
JIT_CFLAGS="${JIT_CFLAGS} -DIR_DEBUG"
fi
fi

AC_CHECK_FUNCS([mprotect memfd_create shm_create_largepage])
Expand Down Expand Up @@ -310,7 +373,7 @@ int main(void) {
shared_alloc_mmap.c \
shared_alloc_posix.c \
$ZEND_JIT_SRC,
shared,,"-Wno-implicit-fallthrough -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1",,yes)
shared,,"-Wno-implicit-fallthrough -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 ${JIT_CFLAGS}",,yes)

PHP_ADD_EXTENSION_DEP(opcache, pcre)

Expand All @@ -320,6 +383,9 @@ int main(void) {

if test "$PHP_OPCACHE_JIT" = "yes"; then
PHP_ADD_BUILD_DIR([$ext_builddir/jit], 1)
if test "$PHP_OPCACHE_JIT_IR" = "yes"; then
PHP_ADD_BUILD_DIR([$ext_builddir/jit/ir], 1)
fi
PHP_ADD_MAKEFILE_FRAGMENT($ext_srcdir/jit/Makefile.frag)
fi
PHP_SUBST(OPCACHE_SHARED_LIBADD)
Expand Down
43 changes: 42 additions & 1 deletion ext/opcache/config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ if (PHP_OPCACHE != "no") {

ARG_ENABLE("opcache-jit", "whether to enable JIT", "yes");

ARG_ENABLE("opcache-jit-ir", "whether to enable JIT based on IR framework", "yes");

ZEND_EXTENSION('opcache', "\
ZendAccelerator.c \
zend_accelerator_blacklist.c \
Expand All @@ -18,7 +20,7 @@ if (PHP_OPCACHE != "no") {
zend_shared_alloc.c \
shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");

if (PHP_OPCACHE_JIT == "yes") {
if (PHP_OPCACHE_JIT == "yes" && PHP_OPCACHE_JIT_IR == "no") {
if (CHECK_HEADER_ADD_INCLUDE("dynasm/dasm_x86.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) {
var dasm_flags = (X64 ? "-D X64=1" : "") + (X64 ? " -D X64WIN=1" : "") + " -D WIN=1";
if (PHP_ZTS == "yes") {
Expand All @@ -37,6 +39,45 @@ if (PHP_OPCACHE != "no") {
} else {
WARNING("JIT not enabled, headers not found");
}
} else if (PHP_OPCACHE_JIT == "yes" && PHP_OPCACHE_JIT_IR == "yes") {
if (CHECK_HEADER_ADD_INCLUDE("ir/ir.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) {
var dasm_flags = (X64 ? "-D X64=1" : "") + (X64 ? " -D X64WIN=1" : "") + " -D WIN=1";
var ir_target = (X64 ? "IR_TARGET_X64" : "IR_TARGET_X86");
var ir_src = "ir_strtab.c ir_cfg.c ir_sccp.c ir_gcm.c ir_ra.c ir_save.c \
ir_dump.c ir_check.c ir_patch.c";

DEFINE("IR_TARGET", ir_target);
DEFINE("DASM_FLAGS", dasm_flags);
DEFINE("DASM_ARCH", "x86");
dstogov marked this conversation as resolved.
Show resolved Hide resolved

AC_DEFINE('HAVE_JIT', 1, 'Define to enable JIT');
AC_DEFINE('ZEND_JIT_IR', 1, 'Use JIT IR framework');

ADD_FLAG("CFLAGS_OPCACHE", "/I \"ext\\opcache\\jit\\ir\" /D "+ir_target+" /D IR_PHP");
if (PHP_DEBUG == "yes") {
ADD_FLAG("CFLAGS_OPCACHE", "/D IR_DEBUG");
}

if (CHECK_HEADER_ADD_INCLUDE("capstone\\capstone.h", "CFLAGS_OPCACHE", PHP_OPCACHE+ ";" + PHP_PHP_BUILD + "\\include") &&
CHECK_LIB("capstone.lib", "opcache", PHP_OPCACHE)) {
AC_DEFINE('HAVE_CAPSTONE', 1, 'capstone support enabled');
ir_src += " ir_disasm.c";
}

ADD_MAKEFILE_FRAGMENT(configure_module_dirname + "\\jit\\Makefile.frag.w32");

ADD_SOURCES(configure_module_dirname + "\\jit",
"zend_jit.c zend_jit_vm_helpers.c",
"opcache", "ext\\opcache\\jit");
ADD_SOURCES(configure_module_dirname + "\\jit\\ir",
"ir.c", "opcache", "ext\\opcache\\jit\\ir");
ADD_SOURCES(configure_module_dirname + "\\jit\\ir",
"ir_emit.c", "opcache", "ext\\opcache\\jit\\ir");
ADD_SOURCES(configure_module_dirname + "\\jit\\ir",
ir_src, "opcache", "ext\\opcache\\jit\\ir");
} else {
WARNING("JIT not enabled, headers not found");
}
}

ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
Expand Down
27 changes: 27 additions & 0 deletions ext/opcache/jit/Makefile.frag
Original file line number Diff line number Diff line change
@@ -1,4 +1,29 @@
ifdef IR_TARGET
# New IR based JIT
$(builddir)/jit/ir/minilua: $(srcdir)/jit/ir/dynasm/minilua.c
$(BUILD_CC) $(srcdir)/jit/ir/dynasm/minilua.c -lm -o $@

$(builddir)/jit/ir/ir_emit_$(DASM_ARCH).h: $(srcdir)/jit/ir/ir_$(DASM_ARCH).dasc $(srcdir)/jit/ir/dynasm/*.lua $(builddir)/jit/ir/minilua
$(builddir)/jit/ir/minilua $(srcdir)/jit/ir/dynasm/dynasm.lua $(DASM_FLAGS) -o $@ $(srcdir)/jit/ir/ir_$(DASM_ARCH).dasc

$(builddir)/jit/ir/ir_emit.lo: \
$(srcdir)/jit/ir/ir_emit.c $(builddir)/jit/ir/ir_emit_$(DASM_ARCH).h

$(builddir)/jit/ir/gen_ir_fold_hash: $(srcdir)/jit/ir/gen_ir_fold_hash.c $(srcdir)/jit/ir/ir_strtab.c
$(BUILD_CC) -D${IR_TARGET} -DIR_PHP -DIR_PHP_MM=0 -o $@ $<

$(builddir)/jit/ir/ir_fold_hash.h: $(builddir)/jit/ir/gen_ir_fold_hash $(srcdir)/jit/ir/ir_fold.h $(srcdir)/jit/ir/ir.h
$(builddir)/jit/ir/gen_ir_fold_hash < $(srcdir)/jit/ir/ir_fold.h > $(builddir)/jit/ir/ir_fold_hash.h

$(builddir)/jit/ir/ir.lo: \
$(builddir)/jit/ir/ir_fold_hash.h

$(builddir)/jit/zend_jit.lo: \
$(srcdir)/jit/zend_jit_helpers.c \
$(srcdir)/jit/zend_jit_ir.c

else
# Old DynAsm based JIT
$(builddir)/minilua: $(srcdir)/jit/dynasm/minilua.c
$(BUILD_CC) $(srcdir)/jit/dynasm/minilua.c -lm -o $@

Expand All @@ -15,6 +40,8 @@ $(builddir)/jit/zend_jit.lo: \
$(srcdir)/jit/zend_jit_trace.c \
$(srcdir)/jit/zend_elf.c

endif

# For non-GNU make, jit/zend_jit.lo and ./jit/zend_jit.lo are considered distinct targets.
# Use this workaround to allow building from inside ext/opcache.
jit/zend_jit.lo: $(builddir)/jit/zend_jit.lo
46 changes: 46 additions & 0 deletions ext/opcache/jit/Makefile.frag.w32
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
!if "$(IR_TARGET)" != ""
# New IR based JIT

$(BUILD_DIR)\\minilua.exe: ext\opcache\jit\ir\dynasm\minilua.c
@if exist $(BUILD_DIR)\\minilua.exe del $(BUILD_DIR)\\minilua.exe
$(PHP_CL) /Fo$(BUILD_DIR)\ /Fd$(BUILD_DIR)\ /Fp$(BUILD_DIR)\ /FR$(BUILD_DIR) /Fe$(BUILD_DIR)\minilua.exe ext\opcache\jit\ir\dynasm\minilua.c

ext\opcache\jit\ir\ir_emit_x86.h: ext\opcache\jit\ir\ir_x86.dasc $(BUILD_DIR)\\minilua.exe
@if exist ext\opcache\jit\ir\ir_emit_x86.h del ext\opcache\jit\ir\ir_emit_x86.h
$(BUILD_DIR)\\minilua.exe ext/opcache/jit/ir/dynasm/dynasm.lua $(DASM_FLAGS) -o $@ ext/opcache/jit/ir/ir_x86.dasc

$(BUILD_DIR)\\gen_ir_fold_hash.exe: ext\opcache\jit\ir\gen_ir_fold_hash.c ext\opcache\jit\ir\ir_strtab.c
@if exist $(BUILD_DIR)\\gen_ir_fold_hash.exe del $(BUILD_DIR)\\gen_ir_fold_hash.exe
$(PHP_CL) /D $(IR_TARGET) /Fo$(BUILD_DIR)\ /Fd$(BUILD_DIR)\ /Fp$(BUILD_DIR)\ /Fe$(BUILD_DIR)\\gen_ir_fold_hash.exe ext\opcache\jit\ir\gen_ir_fold_hash.c

ext\opcache\jit\ir\ir_fold_hash.h: $(BUILD_DIR)\\gen_ir_fold_hash.exe ext\opcache\jit\ir\ir_fold.h ext\opcache\jit\ir\ir.h
@if exist ext\opcache\jit\ir\ir_fold_hash.h del ext\opcache\jit\ir\ir_fold_hash.h
$(BUILD_DIR)\\gen_ir_fold_hash.exe < ext\opcache\jit\ir\ir_fold.h > ext\opcache\jit\ir\ir_fold_hash.h

$(BUILD_DIR)\ext\opcache\jit\ir\ir_ra.obj: \
ext\opcache\jit\ir\ir.h \
ext\opcache\jit\ir\ir_private.h \
ext\opcache\jit\ir\ir_x86.h

$(BUILD_DIR)\ext\opcache\jit\ir\ir_emit.obj: \
ext\opcache\jit\ir\ir.h \
ext\opcache\jit\ir\ir_private.h \
ext\opcache\jit\ir\ir_x86.h \
ext\opcache\jit\ir\ir_emit_x86.h

$(BUILD_DIR)\ext\opcache\jit\ir\ir.obj: \
ext\opcache\jit\ir\ir.h \
ext\opcache\jit\ir\ir_private.h \
ext\opcache\jit\ir\ir_fold.h \
ext\opcache\jit\ir\ir_fold_hash.h

$(BUILD_DIR)\ext\opcache\jit\zend_jit.obj: \
ext\opcache\jit\zend_jit_ir.c \
ext\opcache\jit\zend_jit_helpers.c \
ext\opcache\jit\ir\ir.h \
ext\opcache\jit\ir\ir_builder.h

!else
# Old DynAsm based JIT

$(BUILD_DIR)\\minilua.exe: ext\opcache\jit\dynasm\minilua.c
@if exist $(BUILD_DIR)\\minilua.exe del $(BUILD_DIR)\\minilua.exe
$(PHP_CL) /Fo$(BUILD_DIR)\ /Fd$(BUILD_DIR)\ /Fp$(BUILD_DIR)\ /FR$(BUILD_DIR) /Fe$(BUILD_DIR)\minilua.exe ext\opcache\jit\dynasm\minilua.c
Expand All @@ -14,3 +59,4 @@ $(BUILD_DIR)\ext\opcache\jit\zend_jit.obj: \
ext/opcache/jit/zend_jit_perf_dump.c \
ext/opcache/jit/zend_jit_trace.c \
ext/opcache/jit/zend_jit_vtune.c
!endif
32 changes: 32 additions & 0 deletions ext/opcache/jit/README-IR.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
New JIT implementation
======================

This branch provides a new JIT implementation based on [IR - Lightweight
JIT Compilation Framework](https://github.com/dstogov/ir).

As opposed to the PHP 8.* JIT approach that generates native code directly from
PHP byte-code, this implementation generates intermediate representation (IR)
and delegates all lower-level tasks to the IR Framework. IR for JIT is like an
AST for compiler.

Key benefits of the new JIT implementation:
- Usage of IR opens possibilities for better optimization and register
allocation (the resulting native code is more efficient)
- PHP doesn't have to care about most low-level details (different CPUs,
calling conventions, TLS details, etc)
- it's much easier to implement support for new targets (e.g. RISCV)
- IR framework is going to be developed separately from PHP and may accept
contributions from other projects (new optimizations, improvements, bug fixes)

Disadvantages:
- JIT compilation becomes slower (this is almost invisible for tracing
JIT, but function JIT compilation of Wordpress becomes 4 times slower)

The necessary part of the IR Framework is embedded into php-src. So, the PR
doesn't introduce new dependencies.

The new JIT implementation successfully passes all CI workflows, but it's still
not mature and may cause failures. To reduce risks, this patch doesn't remove
the old JIT implementation (that is the same as PHP-8.3 JIT). It's possible
to build PHP with the old JIT by configuring with **--disable-opcache-jit-ir**.
In the future the old implementation should be removed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, the old implementation should be removed in the same minor version.

  1. If the new JIT is not the default, nobody will test it
  2. If the new JIT is the default, nobody will use the old JIT
  3. One JIT is complex enough to maintain 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to agree :)

Loading