22#if defined(IR_TARGET_X86)
27# define ZREG_FIRST_FPR 8
28# define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<6) | (1<<7))
29#elif defined(IR_TARGET_X64)
34# define ZREG_FIRST_FPR 16
36# define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<6) | (1<<7) | (1<<12) | (1<<13) | (1<<14) | (1<<15))
42# define IR_SHADOW_ARGS 32
44# define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<12) | (1<<13) | (1<<14) | (1<<15))
46#elif defined(IR_TARGET_AARCH64)
51# define ZREG_FIRST_FPR 32
52# define IR_REGSET_PRESERVED ((1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23) | \
53 (1<<24) | (1<<25) | (1<<26) | (1<<27) | (1<<28))
55# error "Unknown IR target"
58#define ZREG_RX ZREG_IP
60#define OPTIMIZE_FOR_SIZE 0
64#define _ir_CTX (&jit->ctx)
67#define ir_CONST_ADDR(_addr) jit_CONST_ADDR(jit, (uintptr_t)(_addr))
68#define ir_CONST_FUNC(_addr) jit_CONST_FUNC(jit, (uintptr_t)(_addr), 0)
69#define ir_CONST_FC_FUNC(_addr) jit_CONST_FUNC(jit, (uintptr_t)(_addr), IR_FASTCALL_FUNC)
70#define ir_CAST_FC_FUNC(_addr) ir_fold2(_ir_CTX, IR_OPT(IR_PROTO, IR_ADDR), (_addr), \
71 ir_proto_0(_ir_CTX, IR_FASTCALL_FUNC, IR_I32))
73#define ir_CONST_FUNC_PROTO(_addr, _proto) \
74 jit_CONST_FUNC_PROTO(jit, (uintptr_t)(_addr), (_proto))
77#define ir_ADD_OFFSET(_addr, _offset) \
78 jit_ADD_OFFSET(jit, _addr, _offset)
80#ifdef ZEND_ENABLE_ZVAL_LONG64
81# define IR_LONG IR_I64
82# define ir_CONST_LONG ir_CONST_I64
83# define ir_UNARY_OP_L ir_UNARY_OP_I64
84# define ir_BINARY_OP_L ir_BINARY_OP_I64
85# define ir_ADD_L ir_ADD_I64
86# define ir_SUB_L ir_SUB_I64
87# define ir_MUL_L ir_MUL_I64
88# define ir_DIV_L ir_DIV_I64
89# define ir_MOD_L ir_MOD_I64
90# define ir_NEG_L ir_NEG_I64
91# define ir_ABS_L ir_ABS_I64
92# define ir_SEXT_L ir_SEXT_I64
93# define ir_ZEXT_L ir_ZEXT_I64
94# define ir_TRUNC_L ir_TRUNC_I64
95# define ir_BITCAST_L ir_BITCAST_I64
96# define ir_FP2L ir_FP2I64
97# define ir_ADD_OV_L ir_ADD_OV_I64
98# define ir_SUB_OV_L ir_SUB_OV_I64
99# define ir_MUL_OV_L ir_MUL_OV_I64
100# define ir_NOT_L ir_NOT_I64
101# define ir_OR_L ir_OR_I64
102# define ir_AND_L ir_AND_I64
103# define ir_XOR_L ir_XOR_I64
104# define ir_SHL_L ir_SHL_I64
105# define ir_SHR_L ir_SHR_I64
106# define ir_SAR_L ir_SAR_I64
107# define ir_ROL_L ir_ROL_I64
108# define ir_ROR_L ir_ROR_I64
109# define ir_MIN_L ir_MIN_I64
110# define ir_MAX_L ir_MAX_I64
111# define ir_LOAD_L ir_LOAD_I64
113# define IR_LONG IR_I32
114# define ir_CONST_LONG ir_CONST_I32
115# define ir_UNARY_OP_L ir_UNARY_OP_I32
116# define ir_BINARY_OP_L ir_BINARY_OP_I32
117# define ir_ADD_L ir_ADD_I32
118# define ir_SUB_L ir_SUB_I32
119# define ir_MUL_L ir_MUL_I32
120# define ir_DIV_L ir_DIV_I32
121# define ir_MOD_L ir_MOD_I32
122# define ir_NEG_L ir_NEG_I32
123# define ir_ABS_L ir_ABS_I32
124# define ir_SEXT_L ir_SEXT_I32
125# define ir_ZEXT_L ir_ZEXT_I32
126# define ir_TRUNC_L ir_TRUNC_I32
127# define ir_BITCAST_L ir_BITCAST_I32
128# define ir_FP2L ir_FP2I32
129# define ir_ADD_OV_L ir_ADD_OV_I32
130# define ir_SUB_OV_L ir_SUB_OV_I32
131# define ir_MUL_OV_L ir_MUL_OV_I32
132# define ir_NOT_L ir_NOT_I32
133# define ir_OR_L ir_OR_I32
134# define ir_AND_L ir_AND_I32
135# define ir_XOR_L ir_XOR_I32
136# define ir_SHL_L ir_SHL_I32
137# define ir_SHR_L ir_SHR_I32
138# define ir_SAR_L ir_SAR_I32
139# define ir_ROL_L ir_ROL_I32
140# define ir_ROR_L ir_ROR_I32
141# define ir_MIN_L ir_MIN_I32
142# define ir_MAX_L ir_MAX_I32
143# define ir_LOAD_L ir_LOAD_I32
153#define ir_refs_size(_n) (offsetof(ir_refs, refs) + sizeof(ir_ref) * (_n))
154#define ir_refs_init(_name, _n) _name = alloca(ir_refs_size(_n)); \
155 do {_name->count = 0; _name->limit = (_n);} while (0)
166static size_t zend_jit_trace_prologue_size = (size_t)-1;
167#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
168static uint32_t allowed_opt_flags = 0;
169static uint32_t default_mflags = 0;
171static bool delayed_call_chain = 0;
175extern uint32_t _tls_index;
176extern char *_tls_start;
177extern char *_tls_end;
180static size_t tsrm_ls_cache_tcb_offset = 0;
181static size_t tsrm_tls_index = 0;
182static size_t tsrm_tls_offset = 0;
184# define EG_TLS_OFFSET(field) \
185 (executor_globals_offset + offsetof(zend_executor_globals, field))
187# define CG_TLS_OFFSET(field) \
188 (compiler_globals_offset + offsetof(zend_compiler_globals, field))
190# define jit_EG(_field) \
191 ir_ADD_OFFSET(jit_TLS(jit), EG_TLS_OFFSET(_field))
193# define jit_CG(_field) \
194 ir_ADD_OFFSET(jit_TLS(jit), CG_TLS_OFFSET(_field))
198# define jit_EG(_field) \
199 ir_CONST_ADDR(&EG(_field))
201# define jit_CG(_field) \
202 ir_CONST_ADDR(&CG(_field))
206#define jit_CALL(_call, _field) \
207 ir_ADD_OFFSET(_call, offsetof(zend_execute_data, _field))
209#define jit_EX(_field) \
210 jit_CALL(jit_FP(jit), _field)
212#define jit_RX(_field) \
213 jit_CALL(jit_IP(jit), _field)
215#define JIT_STUBS(_) \
216 _(exception_handler, IR_SKIP_PROLOGUE) \
217 _(exception_handler_undef, IR_SKIP_PROLOGUE) \
218 _(exception_handler_free_op2, IR_SKIP_PROLOGUE) \
219 _(exception_handler_free_op1_op2, IR_SKIP_PROLOGUE) \
220 _(interrupt_handler, IR_SKIP_PROLOGUE) \
221 _(leave_function_handler, IR_SKIP_PROLOGUE) \
222 _(negative_shift, IR_SKIP_PROLOGUE) \
223 _(mod_by_zero, IR_SKIP_PROLOGUE) \
224 _(invalid_this, IR_SKIP_PROLOGUE) \
225 _(undefined_function, IR_SKIP_PROLOGUE) \
226 _(throw_cannot_pass_by_ref, IR_SKIP_PROLOGUE) \
227 _(icall_throw, IR_SKIP_PROLOGUE) \
228 _(leave_throw, IR_SKIP_PROLOGUE) \
229 _(hybrid_runtime_jit, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
230 _(hybrid_profile_jit, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
231 _(hybrid_func_hot_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
232 _(hybrid_loop_hot_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
233 _(hybrid_func_trace_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
234 _(hybrid_ret_trace_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
235 _(hybrid_loop_trace_counter, IR_SKIP_PROLOGUE | IR_START_BR_TARGET) \
236 _(trace_halt, IR_SKIP_PROLOGUE) \
237 _(trace_escape, IR_SKIP_PROLOGUE) \
238 _(trace_exit, IR_SKIP_PROLOGUE) \
239 _(undefined_offset, IR_FUNCTION | IR_FASTCALL_FUNC) \
240 _(undefined_key, IR_FUNCTION | IR_FASTCALL_FUNC) \
241 _(cannot_add_element, IR_FUNCTION | IR_FASTCALL_FUNC) \
242 _(assign_const, IR_FUNCTION | IR_FASTCALL_FUNC) \
243 _(assign_tmp, IR_FUNCTION | IR_FASTCALL_FUNC) \
244 _(assign_var, IR_FUNCTION | IR_FASTCALL_FUNC) \
245 _(assign_cv_noref, IR_FUNCTION | IR_FASTCALL_FUNC) \
246 _(assign_cv, IR_FUNCTION | IR_FASTCALL_FUNC) \
247 _(new_array, IR_FUNCTION | IR_FASTCALL_FUNC) \
249#define JIT_STUB_ID(name, flags) \
252#define JIT_STUB_FORWARD(name, flags) \
253 static int zend_jit_ ## name ## _stub(zend_jit_ctx *jit);
255#define JIT_STUB(name, flags) \
256 {JIT_STUB_PREFIX #name, zend_jit_ ## name ## _stub, flags},
303#if defined(IR_TARGET_X64)
306#elif defined(IR_TARGET_X86)
309#elif defined (IR_TARGET_AARCH64)
313# error "Unknown IR target"
318#define ZEND_JIT_EXIT_POINTS_SPACING 4
319#define ZEND_JIT_EXIT_POINTS_PER_GROUP 32
321static uint32_t zend_jit_exit_point_by_addr(
const void *
addr);
324static int zend_jit_assign_to_variable(
zend_jit_ctx *jit,
329 uint32_t var_def_info,
335 bool check_exception);
349#if defined(_WIN32) || defined(IR_TARGET_AARCH64)
351static void** zend_jit_stub_handlers =
NULL;
353static void* zend_jit_stub_handlers[
sizeof(zend_jit_stubs) /
sizeof(zend_jit_stubs[0])];
356#if defined(IR_TARGET_AARCH64)
360typedef struct TLSDescriptor {
367#define IR_HAS_VENEERS (1U<<31)
369static const void *zend_jit_get_veneer(
ir_ctx *ctx,
const void *
addr)
371 int i,
count =
sizeof(zend_jit_stubs) /
sizeof(zend_jit_stubs[0]);
373 for (i = 0; i <
count; i++) {
374 if (zend_jit_stub_handlers[i] ==
addr) {
375 return zend_jit_stub_handlers[
count + i];
380 && (
void*)
addr >= dasm_buf && (
void*)
addr < dasm_end) {
381 uint32_t exit_point = zend_jit_exit_point_by_addr(
addr);
383 if (exit_point != (uint32_t)-1) {
387 return (
const void*)((
char*)ctx->deoptimization_exits_base + (exit_point * 4));
394static bool zend_jit_set_veneer(
ir_ctx *ctx,
const void *
addr,
const void *veneer)
396 int i,
count =
sizeof(zend_jit_stubs) /
sizeof(zend_jit_stubs[0]);
397 uint32_t exit_point = zend_jit_exit_point_by_addr(
addr);
399 if (exit_point != (uint32_t)-1) {
402 for (i = 0; i <
count; i++) {
403 if (zend_jit_stub_handlers[i] ==
addr) {
404 const void **
ptr = (
const void**)&zend_jit_stub_handlers[
count + i];
406 ctx->
flags2 |= IR_HAS_VENEERS;
432static void zend_jit_commit_veneers(
void)
434 int i,
count =
sizeof(zend_jit_stubs) /
sizeof(zend_jit_stubs[0]);
436 for (i = 0; i <
count; i++) {
437 if (zend_jit_stub_handlers[
count + i]) {
438 zend_jit_stub_handlers[i] = zend_jit_stub_handlers[
count + i];
439 zend_jit_stub_handlers[
count + i] =
NULL;
445static bool zend_jit_prefer_const_addr_load(
zend_jit_ctx *jit, uintptr_t
addr)
447#if defined(IR_TARGET_X86)
449#elif defined(IR_TARGET_X64)
450 return addr > 0xffffffff;
451#elif defined(IR_TARGET_AARCH64)
452 return addr > 0xffff;
454# error "Unknown IR target"
458static const char* zend_reg_name(int8_t reg)
475 if (ref == jit->tls) {
479 if (insn->op >= IR_START || insn->op == IR_CALL) {
486 tsrm_ls_cache_tcb_offset ? tsrm_ls_cache_tcb_offset : tsrm_tls_index,
487 tsrm_ls_cache_tcb_offset ?
IR_NULL : tsrm_tls_offset);
525 insn->optx =
IR_OPT(IR_FUNC_ADDR, IR_ADDR);
534#if defined(IR_TARGET_X86)
541 return jit_CONST_FUNC_PROTO(jit,
addr, proto);
586 insn->optx =
IR_OPT(IR_FUNC_ADDR, IR_ADDR);
587#if defined(IR_TARGET_X86)
603 uint32_t stack_size = op_array->
last_var + op_array->
T;
605 if (
ptr == zend_jit_stub_handlers[jit_stub_exception_handler]
606 ||
ptr == zend_jit_stub_handlers[jit_stub_exception_handler_undef]
607 ||
ptr == zend_jit_stub_handlers[jit_stub_exception_handler_free_op1_op2]
608 ||
ptr == zend_jit_stub_handlers[jit_stub_exception_handler_free_op2]
609 ||
ptr == zend_jit_stub_handlers[jit_stub_interrupt_handler]
610 ||
ptr == zend_jit_stub_handlers[jit_stub_leave_function_handler]
611 ||
ptr == zend_jit_stub_handlers[jit_stub_negative_shift]
612 ||
ptr == zend_jit_stub_handlers[jit_stub_mod_by_zero]
613 ||
ptr == zend_jit_stub_handlers[jit_stub_invalid_this]
614 ||
ptr == zend_jit_stub_handlers[jit_stub_undefined_function]
615 ||
ptr == zend_jit_stub_handlers[jit_stub_throw_cannot_pass_by_ref]
616 ||
ptr == zend_jit_stub_handlers[jit_stub_icall_throw]
617 ||
ptr == zend_jit_stub_handlers[jit_stub_leave_throw]
618 ||
ptr == zend_jit_stub_handlers[jit_stub_trace_halt]
619 ||
ptr == zend_jit_stub_handlers[jit_stub_trace_escape]) {
626 uint32_t exit_point = 0,
n = 0;
631 exit_point = zend_jit_exit_point_by_addr(
ptr);
638 if (stack_size ||
n) {
640 uint32_t snapshot_size, i;
642 snapshot_size = stack_size;
643 while (snapshot_size > 0) {
652 if (snapshot_size ||
n) {
656 for (i = 0; i < snapshot_size; i++) {
691 uint32_t stack_size, stack_offset;
695 ctx->
status = -ZEND_JIT_TRACE_STOP_TOO_MANY_EXITS;
702 if (stack_size != 0) {
712 return new_exit_point;
717 int8_t *reg_ops = ctx->
regs[snapshot_ref];
720 int8_t reg = reg_ops[op];
736 return a->reg == b->
reg
743 uint32_t exit_point, exit_flags;
744 ir_ref n = snapshot->inputs_count;
747 exit_point = zend_jit_exit_point_by_addr(
addr);
753 zend_jit_resolve_ref_snapshot(&
func, ctx, snapshot_ref, snapshot,
n - 1);
754 zend_jit_resolve_ref_snapshot(&
this, ctx, snapshot_ref, snapshot,
n);
760 addr = (
void*)zend_jit_trace_get_exit_addr(exit_point);
768 for (i = 2; i <=
n; i++) {
772 int8_t *reg_ops = ctx->
regs[snapshot_ref];
773 int8_t reg = reg_ops[i];
776 ZEND_ASSERT(var < t->exit_info[exit_point].stack_size);
782 addr = (
void*)zend_jit_trace_get_exit_addr(exit_point);
800 addr = (
void*)zend_jit_trace_get_exit_addr(exit_point);
812 addr = (
void*)zend_jit_trace_get_exit_addr(exit_point);
821 addr = (
void*)zend_jit_trace_get_exit_addr(exit_point);
831 addr = (
void*)zend_jit_trace_get_exit_addr(exit_point);
837 int32_t idx = _add_trace_const(t, ctx->
ir_base[ref].
val.
i64);
850 jit_SNAPSHOT(jit,
addr);
865#elif defined(HAVE_BUILTIN_CONSTANT_P)
885#elif defined(HAVE_BUILTIN_CONSTANT_P)
907 if (ref == jit->
fp) {
911 if (insn->op >= IR_START || insn->op == IR_CALL) {
944 if (GCC_GLOBAL_REGS) {
945 jit_STORE_IP(jit, ref);
956static void zend_jit_track_last_valid_opline(
zend_jit_ctx *jit)
962static void zend_jit_use_last_valid_opline(
zend_jit_ctx *jit)
970static bool zend_jit_trace_uses_initial_ip(
zend_jit_ctx *jit)
983static void zend_jit_reset_last_valid_opline(
zend_jit_ctx *jit)
991 zend_jit_reset_last_valid_opline(jit);
998 zend_jit_start_reuse_ip(jit);
1010static int zend_jit_save_call_chain(
zend_jit_ctx *jit, uint32_t call_level)
1014 if (call_level == 1) {
1031 delayed_call_chain = 0;
1048 zend_jit_use_last_valid_opline(jit);
1050 if (GCC_GLOBAL_REGS) {
1061 if (GCC_GLOBAL_REGS) {
1062 jit_STORE_IP(jit, ref);
1068 if (GCC_GLOBAL_REGS) {
1075 zend_jit_set_last_valid_opline(jit, target);
1086 return zend_jit_set_ip(jit, target);
1092 zend_jit_use_last_valid_opline(jit);
1093 if (GCC_GLOBAL_REGS) {
1099 if (!GCC_GLOBAL_REGS) {
1100 zend_jit_reset_last_valid_opline(jit);
1148 return jit_Z_TYPE_ref(jit, jit_ZVAL_ADDR(jit,
addr));
1174 return jit_Z_TYPE_FLAGS_ref(jit, jit_ZVAL_ADDR(jit,
addr));
1200 return jit_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit,
addr));
1224 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit,
addr), type_info);
1233 &&
JIT_G(current_frame)
1285 return ir_IF(jit_Z_TYPE_FLAGS(jit,
addr));
1371 if (!zend_jit_spilling_may_cause_conflict(jit, var,
val)) {
1384 while (phi !=
NULL) {
1388 if (dst_phi->
pi >= 0) {
1392 phi = zend_ssa_next_use_phi(jit->
ssa, var, phi);
1397 ZEND_ASSERT(!zend_ssa_next_use_phi(jit->
ssa, src_var, dst_phi) &&
"reg forwarding");
1403 if (phi_insn->op == IR_PHI) {
1407 for (
j = 0,
p = &dst_phi->
sources[0], q = phi_insn->ops + 2;
j <
n;
j++,
p++, q++) {
1408 if (*
p == src_var) {
1415 phi = zend_ssa_next_use_phi(jit->
ssa, var, phi);
1433 ref = jit_Z_LVAL_ref(jit, jit_ZVAL_ADDR(jit, mem_addr));
1435 ref = jit_Z_DVAL_ref(jit, jit_ZVAL_ADDR(jit, mem_addr));
1439 zend_jit_def_reg(jit,
addr, ref);
1447 int src_var = phi->
sources[0];
1459 if (!zend_ssa_next_use_phi(jit->
ssa, dst_var, phi)) {
1483 bool phi_inputs_are_the_same = 1;
1494 for (i = 0; i <
n; i++) {
1495 int src_var = phi->
sources[i];
1500 phi_inputs_are_the_same = 0;
1504 same_src_ref = src_ref;
1505 }
else if (same_src_ref != src_ref) {
1506 phi_inputs_are_the_same = 0;
1511 if (phi_inputs_are_the_same) {
1524 return zend_jit_use_reg(jit,
addr);
1526 return jit_Z_LVAL_ref(jit, jit_ZVAL_ADDR(jit,
addr));
1533 zend_jit_def_reg(jit,
addr, lval);
1539#if SIZEOF_ZEND_LONG == 4
1560 return zend_jit_use_reg(jit,
addr);
1562 return jit_Z_DVAL_ref(jit, jit_ZVAL_ADDR(jit,
addr));
1585 return jit_Z_PTR_ref(jit, jit_ZVAL_ADDR(jit,
addr));
1644 jit_set_Z_PTR(jit, dst, ref);
1646 jit_GC_ADDREF(jit, ref);
1653 jit_set_Z_TYPE_INFO(jit, dst,
IS_DOUBLE);
1672 jit_set_Z_LVAL(jit, dst, jit_Z_LVAL(jit, src));
1674 jit_set_Z_DVAL(jit, dst, jit_Z_DVAL(jit, src));
1676#if SIZEOF_ZEND_LONG == 4
1678 jit_set_Z_W2(jit, dst, jit_Z_W2(jit, src));
1681 ref = jit_Z_PTR(jit, src);
1682 jit_set_Z_PTR(jit, dst, ref);
1690 uint8_t
type = concrete_type(src_info);
1691 jit_set_Z_TYPE_INFO(jit, dst,
type);
1695 jit_set_Z_TYPE_INFO_ex(jit, dst,
type);
1705 jit_GC_ADDREF(jit, ref);
1721 ref = jit_Z_LVAL(jit, src);
1722 jit_set_Z_LVAL(jit, dst, ref);
1723 jit_set_Z_LVAL(jit, dst2, ref);
1725 ref = jit_Z_DVAL(jit, src);
1726 jit_set_Z_DVAL(jit, dst, ref);
1727 jit_set_Z_DVAL(jit, dst2, ref);
1729#if SIZEOF_ZEND_LONG == 4
1731 ref = jit_Z_W2(jit, src);
1732 jit_set_Z_W2(jit, dst, ref);
1733 jit_set_Z_W2(jit, dst2, ref);
1736 ref = jit_Z_PTR(jit, src);
1737 jit_set_Z_PTR(jit, dst, ref);
1738 jit_set_Z_PTR(jit, dst2, ref);
1744 uint8_t
type = concrete_type(src_info);
1749 jit_set_Z_TYPE_INFO_ex(jit, dst, type_ref);
1752 jit_set_Z_TYPE_INFO_ex(jit, dst2, type_ref);
1756 jit_set_Z_TYPE_INFO_ex(jit, dst,
type);
1757 jit_set_Z_TYPE_INFO_ex(jit, dst2,
type);
1768 jit_GC_ADDREF2(jit, ref);
1770 jit_GC_ADDREF(jit, ref);
1792 jit_SET_EX_OPLINE(jit, opline);
1801 jit_SET_EX_OPLINE(jit, opline);
1808 jit_SET_EX_OPLINE(jit, opline);
1826 if_refcounted = jit_if_REFCOUNTED(jit,
addr);
1831 ref = jit_Z_PTR(jit,
addr);
1832 ref2 = jit_GC_DELREF(jit, ref);
1834 if (((op_info) &
MAY_BE_GUARD) || RC_MAY_BE_1(op_info)) {
1835 if (((op_info) &
MAY_BE_GUARD) || RC_MAY_BE_N(op_info)) {
1836 if_not_zero =
ir_IF(ref2);
1840 jit_ZVAL_DTOR(jit, ref, op_info, opline);
1850 ir_ref if_ref, if_collectable;
1857 if_collectable = jit_if_COLLECTABLE_ref(jit, ref2);
1862 ref2 = jit_Z_PTR_ref(jit, ref2);
1865 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
1868 if_may_not_leak = jit_if_GC_MAY_NOT_LEAK(jit, ref);
1874 jit_SET_EX_OPLINE(jit, opline);
1893 jit_ZVAL_PTR_DTOR(jit,
1895 op_info, 0, opline);
1902 ir_ref if_not_zero, if_may_not_leak;
1905 if_not_zero =
ir_IF(jit_GC_DELREF(jit, ref));
1913 if_may_not_leak = jit_if_GC_MAY_NOT_LEAK(jit, ref);
1925static void zend_jit_check_timeout(
zend_jit_ctx *jit,
const zend_op *opline,
const void *exit_addr)
1932 ir_GUARD_NOT(ref, jit_STUB_ADDR(jit, jit_stub_interrupt_handler));
1937 jit_LOAD_IP_ADDR(jit, opline);
1938 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_interrupt_handler));
1945static int zend_jit_exception_handler_stub(
zend_jit_ctx *jit)
1957 if (GCC_GLOBAL_REGS) {
1973static int zend_jit_exception_handler_undef_stub(
zend_jit_ctx *jit)
1975 ir_ref ref, result_type, if_result_used;
1977 ref =
jit_EG(opline_before_exception);
1984 if (
sizeof(
void*) == 8) {
1990 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
1995static int zend_jit_exception_handler_free_op1_op2_stub(
zend_jit_ctx *jit)
2005 if (
sizeof(
void*) == 8) {
2013 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_free_op2));
2018static int zend_jit_exception_handler_free_op2_stub(
zend_jit_ctx *jit)
2028 if (
sizeof(
void*) == 8) {
2036 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_undef));
2041static int zend_jit_interrupt_handler_stub(
zend_jit_ctx *jit)
2043 ir_ref if_timeout, if_exception;
2045 if (GCC_GLOBAL_REGS) {
2067 if (GCC_GLOBAL_REGS) {
2075static int zend_jit_leave_function_handler_stub(
zend_jit_ctx *jit)
2087 }
else if (GCC_GLOBAL_REGS) {
2098 }
else if (GCC_GLOBAL_REGS) {
2107static int zend_jit_negative_shift_stub(
zend_jit_ctx *jit)
2114 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_free_op1_op2));
2125 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_free_op1_op2));
2129static int zend_jit_invalid_this_stub(
zend_jit_ctx *jit)
2136 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler_undef));
2140static int zend_jit_undefined_function_stub(
zend_jit_ctx *jit)
2146 if (
sizeof(
void*) == 8) {
2160 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
2165static int zend_jit_throw_cannot_pass_by_ref_stub(
zend_jit_ctx *jit)
2167 ir_ref opline, ref, rx, if_eq, if_tmp;
2174 if (
sizeof(
void*) == 8) {
2194 jit_STORE_IP(jit, opline);
2207 if (
sizeof(
void*) == 8) {
2211 jit_ZVAL_PTR_DTOR(jit,
2216 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
2238 jit_STORE_IP(jit,
jit_EG(exception_op));
2240 if (GCC_GLOBAL_REGS) {
2244 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
2265 jit_LOAD_IP(jit,
jit_EG(exception_op));
2267 if (GCC_GLOBAL_REGS) {
2271 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
2279static int zend_jit_hybrid_runtime_jit_stub(
zend_jit_ctx *jit)
2290static int zend_jit_hybrid_profile_jit_stub(
zend_jit_ctx *jit)
2308 addr = run_time_cache;
2318static int _zend_jit_hybrid_hot_counter_stub(
zend_jit_ctx *jit, uint32_t cost)
2348static int zend_jit_hybrid_func_hot_counter_stub(
zend_jit_ctx *jit)
2354 return _zend_jit_hybrid_hot_counter_stub(jit,
2358static int zend_jit_hybrid_loop_hot_counter_stub(
zend_jit_ctx *jit)
2364 return _zend_jit_hybrid_hot_counter_stub(jit,
2372 if (GCC_GLOBAL_REGS) {
2388 return _zend_jit_orig_opline_handler(jit,
offset);
2391static int _zend_jit_hybrid_trace_counter_stub(
zend_jit_ctx *jit, uint32_t cost)
2411 ref =
jit_EG(current_execute_data);
2414 jit_STORE_IP(jit, ref);
2426static int zend_jit_hybrid_func_trace_counter_stub(
zend_jit_ctx *jit)
2432 return _zend_jit_hybrid_trace_counter_stub(jit,
2436static int zend_jit_hybrid_ret_trace_counter_stub(
zend_jit_ctx *jit)
2442 return _zend_jit_hybrid_trace_counter_stub(jit,
2446static int zend_jit_hybrid_loop_trace_counter_stub(
zend_jit_ctx *jit)
2452 return _zend_jit_hybrid_trace_counter_stub(jit,
2460 }
else if (GCC_GLOBAL_REGS) {
2469static int zend_jit_trace_escape_stub(
zend_jit_ctx *jit)
2471 if (GCC_GLOBAL_REGS) {
2484 if (GCC_GLOBAL_REGS) {
2495 if (GCC_GLOBAL_REGS) {
2496 ref =
jit_EG(current_execute_data);
2499 jit_STORE_IP(jit, ref);
2509 ref =
jit_EG(current_execute_data);
2512 if (GCC_GLOBAL_REGS) {
2514 jit_STORE_IP(jit, ref);
2518 zend_jit_check_timeout(jit,
NULL,
NULL);
2520 addr = zend_jit_orig_opline_handler(jit);
2521 if (GCC_GLOBAL_REGS) {
2524#if defined(IR_TARGET_X86)
2535static int zend_jit_undefined_offset_stub(
zend_jit_ctx *jit)
2537 if (GCC_GLOBAL_REGS) {
2546static int zend_jit_undefined_key_stub(
zend_jit_ctx *jit)
2548 if (GCC_GLOBAL_REGS) {
2557static int zend_jit_cannot_add_element_stub(
zend_jit_ctx *jit)
2560 ir_ref ref, if_result_used;
2568 if (
sizeof(
void*) == 8) {
2578 ir_CONST_ADDR(
"Cannot add element to the array as the next element is already occupied"));
2584static int zend_jit_assign_const_stub(
zend_jit_ctx *jit)
2593 if (!zend_jit_assign_to_variable(
2595 var_addr, var_addr, -1, -1,
2613 if (!zend_jit_assign_to_variable(
2615 var_addr, var_addr, -1, -1,
2633 if (!zend_jit_assign_to_variable(
2635 var_addr, var_addr, -1, -1,
2636 IS_VAR, val_addr, val_info,
2644static int zend_jit_assign_cv_noref_stub(
zend_jit_ctx *jit)
2653 if (!zend_jit_assign_to_variable(
2655 var_addr, var_addr, -1, -1,
2656 IS_CV, val_addr, val_info,
2670 jit_set_Z_PTR(jit, var_addr, ref);
2685 if (!zend_jit_assign_to_variable(
2687 var_addr, var_addr, -1, -1,
2688 IS_CV, val_addr, val_info,
2698#if defined (__CET__) && (__CET__ & 1) != 0
2706#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
2711#elif defined(IR_TARGET_AARCH64)
2712 jit->
ctx.get_veneer = zend_jit_get_veneer;
2713 jit->
ctx.set_veneer = zend_jit_set_veneer;
2723#if defined(IR_TARGET_AARCH64)
2726#elif defined(_WIN64)
2728#elif defined(IR_TARGET_X86_64)
2733 if (GCC_GLOBAL_REGS) {
2747#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE
2759#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
2776 delayed_call_chain = 0;
2803 zend_string_release(jit->
name);
2810static void *zend_jit_ir_compile(
ir_ctx *ctx,
size_t *
size,
const char *
name)
2863#if !defined(IR_TARGET_AARCH64)
2893 code_buffer.
start = dasm_buf;
2894 code_buffer.
end = dasm_end;
2895 code_buffer.
pos = *dasm_ptr;
2900 *dasm_ptr = code_buffer.
pos;
2902#if defined(IR_TARGET_AARCH64)
2903 if (ctx->
flags2 & IR_HAS_VENEERS) {
2904 zend_jit_commit_veneers();
2911static void zend_jit_setup_stubs(
void)
2918 for (i = 0; i <
sizeof(zend_jit_stubs)/
sizeof(zend_jit_stubs[0]); i++) {
2919 zend_jit_init_ctx(&jit, zend_jit_stubs[i].
flags);
2921 if (!zend_jit_stubs[i].stub(&jit)) {
2922 zend_jit_free_ctx(&jit);
2923 zend_jit_stub_handlers[i] =
NULL;
2927 entry = zend_jit_ir_compile(&jit.
ctx, &
size, zend_jit_stubs[i].name);
2929 zend_jit_free_ctx(&jit);
2933 zend_jit_stub_handlers[i] = entry;
2960 zend_jit_free_ctx(&jit);
2964#define REGISTER_HELPER(n) \
2965 ir_disasm_add_symbol(#n, (uint64_t)(uintptr_t)n, sizeof(void*));
2966#define REGISTER_DATA(n) \
2967 ir_disasm_add_symbol(#n, (uint64_t)(uintptr_t)&n, sizeof(n));
2969static void zend_jit_setup_disasm(
void)
2977 memset(&opline, 0,
sizeof(opline));
3172static void zend_jit_calc_trace_prologue_size(
void)
3181 if (!GCC_GLOBAL_REGS) {
3183 jit_STORE_FP(jit, ref);
3189 entry = zend_jit_ir_compile(&jit->
ctx, &
size,
"JIT$trace_prologue");
3190 zend_jit_free_ctx(jit);
3196 zend_jit_trace_prologue_size =
size;
3199#if !defined(ZEND_WIN32) && !defined(IR_TARGET_AARCH64)
3200static uintptr_t zend_jit_hybrid_vm_sp_adj = 0;
3217 if (
arg->cnt == 3) {
3223static void ZEND_FASTCALL zend_jit_touch_vm_stack_data(
void *vm_stack_data)
3230 zend_jit_hybrid_vm_sp_adj =
arg.cfa[2] -
arg.cfa[1];
3240 orig_zend_touch_vm_stack_data = zend_touch_vm_stack_data;
3241 zend_touch_vm_stack_data = zend_jit_touch_vm_stack_data;
3243 zend_touch_vm_stack_data = orig_zend_touch_vm_stack_data;
3252static PRUNTIME_FUNCTION zend_jit_uw_func =
NULL;
3254#ifdef ZEND_JIT_RT_UNWINDER
3255static PRUNTIME_FUNCTION zend_jit_unwind_callback(DWORD64 pc, PVOID
context)
3257 return zend_jit_uw_func;
3261static void zend_jit_setup_unwinder(
void)
3264 static const unsigned char uw_data[] = {
3281 static const unsigned char uw_data_exitcall[] = {
3287 0x10, 0x01, 0x2f, 0x00,
3298 zend_jit_uw_func = (PRUNTIME_FUNCTION)*dasm_ptr;
3300 sizeof(uw_data) +
sizeof(uw_data_exitcall) +
sizeof(uw_data), 16);
3302 zend_jit_uw_func[0].BeginAddress = 0;
3303 zend_jit_uw_func[1].BeginAddress = (uintptr_t)zend_jit_stub_handlers[jit_stub_trace_exit] - (uintptr_t)dasm_buf;
3304 zend_jit_uw_func[2].BeginAddress = (uintptr_t)zend_jit_stub_handlers[jit_stub_undefined_offset] - (uintptr_t)dasm_buf;
3306 zend_jit_uw_func[0].EndAddress = zend_jit_uw_func[1].BeginAddress;
3307 zend_jit_uw_func[1].EndAddress = zend_jit_uw_func[2].BeginAddress;
3308 zend_jit_uw_func[2].EndAddress = (uintptr_t)dasm_end - (uintptr_t)dasm_buf;
3310 zend_jit_uw_func[0].UnwindData = (uintptr_t)zend_jit_uw_func - (uintptr_t)dasm_buf +
sizeof(RUNTIME_FUNCTION) * 4;
3311 zend_jit_uw_func[1].UnwindData = zend_jit_uw_func[0].UnwindData +
sizeof(uw_data);
3312 zend_jit_uw_func[2].UnwindData = zend_jit_uw_func[1].UnwindData +
sizeof(uw_data_exitcall);
3314 memcpy((
char*)dasm_buf + zend_jit_uw_func[0].UnwindData, uw_data,
sizeof(uw_data));
3315 memcpy((
char*)dasm_buf + zend_jit_uw_func[1].UnwindData, uw_data_exitcall,
sizeof(uw_data_exitcall));
3316 memcpy((
char*)dasm_buf + zend_jit_uw_func[2].UnwindData, uw_data,
sizeof(uw_data));
3318#ifdef ZEND_JIT_RT_UNWINDER
3319 RtlInstallFunctionTableCallback(
3320 (uintptr_t)dasm_buf | 3,
3321 (uintptr_t) dasm_buf,
3322 (uintptr_t)dasm_end - (uintptr_t)dasm_buf,
3323 zend_jit_unwind_callback,
3327 RtlAddFunctionTable(zend_jit_uw_func, 3, (uintptr_t)dasm_buf);
3333static void zend_jit_setup(
bool reattached)
3335#if defined(IR_TARGET_X86)
3336 if (!zend_cpu_supports_sse2()) {
3340#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
3341 allowed_opt_flags = 0;
3342 if (zend_cpu_supports_avx()) {
3345# if defined(PHP_HAVE_BUILTIN_CPU_SUPPORTS) && defined(__GNUC__) && (ZEND_GCC_VERSION >= 11000)
3346 if (zend_cpu_supports_cldemote()) {
3347 default_mflags |= IR_X86_CLDEMOTE;
3352#if defined(IR_TARGET_AARCH64)
3353 tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset();
3356 if (tsrm_ls_cache_tcb_offset == 0) {
3357 TLSDescriptor **where;
3360 "adrp %0, :tlsdesc:_tsrm_ls_cache\n"
3361 "add %0, %0, :tlsdesc_lo12:_tsrm_ls_cache\n"
3367 TLSDescriptor *tlsdesc = where[1];
3369 tsrm_tls_offset = tlsdesc->offset;
3371 tsrm_tls_index = (tlsdesc->index + 1) * 8;
3373# elif defined(__MUSL__)
3374 if (tsrm_ls_cache_tcb_offset == 0) {
3378 "adrp %0, :tlsdesc:_tsrm_ls_cache\n"
3379 "add %0, %0, :tlsdesc_lo12:_tsrm_ls_cache\n"
3382 size_t *tlsdesc = where[1];
3384 tsrm_tls_offset = tlsdesc[1];
3385 tsrm_tls_index = tlsdesc[0] * 8;
3390# elif defined(_WIN64)
3391 tsrm_tls_index = _tls_index *
sizeof(
void*);
3396 void ***tls_mem = ((
void****)__readgsqword(0x58))[_tls_index];
3397 void *
val = _tsrm_ls_cache;
3399 size_t size = (
char*)&_tls_end - (
char*)&_tls_start;
3402 if (*tls_mem ==
val) {
3403 tsrm_tls_offset =
offset;
3413# elif defined(ZEND_WIN32)
3414 tsrm_tls_index = _tls_index *
sizeof(
void*);
3419 void ***tls_mem = ((
void****)__readfsdword(0x2c))[_tls_index];
3420 void *
val = _tsrm_ls_cache;
3422 size_t size = (
char*)&_tls_end - (
char*)&_tls_start;
3425 if (*tls_mem ==
val) {
3426 tsrm_tls_offset =
offset;
3436# elif defined(__APPLE__) && defined(__x86_64__)
3437 tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset();
3438 if (tsrm_ls_cache_tcb_offset == 0) {
3441 "leaq __tsrm_ls_cache(%%rip),%0"
3443 tsrm_tls_offset = ti[2];
3444 tsrm_tls_index = ti[1] * 8;
3446# elif defined(__GNUC__) && defined(__x86_64__)
3447 tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset();
3448 if (tsrm_ls_cache_tcb_offset == 0) {
3449#if defined(__has_attribute) && __has_attribute(tls_model) && !defined(__FreeBSD__) && \
3450 !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__MUSL__)
3453 asm (
"movq _tsrm_ls_cache@gottpoff(%%rip),%0"
3455 tsrm_ls_cache_tcb_offset =
ret;
3456#elif defined(__MUSL__)
3460 "leaq _tsrm_ls_cache@tlsgd(%%rip), %0\n"
3462 tsrm_tls_offset = ti[1];
3463 tsrm_tls_index = ti[0] * 8;
3464#elif defined(__FreeBSD__)
3468 "leaq _tsrm_ls_cache@tlsgd(%%rip), %0\n"
3470 tsrm_tls_offset = ti[1];
3472 tsrm_tls_index = (ti[0] + 1) * 8;
3477 "leaq _tsrm_ls_cache@tlsgd(%%rip), %0\n"
3479 tsrm_tls_offset = ti[1];
3480 tsrm_tls_index = ti[0] * 16;
3483# elif defined(__GNUC__) && defined(__i386__)
3484 tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset();
3485 if (tsrm_ls_cache_tcb_offset == 0) {
3486#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__MUSL__)
3489 asm (
"leal _tsrm_ls_cache@ntpoff,%0\n"
3491 tsrm_ls_cache_tcb_offset =
ret;
3493 size_t *ti, _ebx, _ecx, _edx;
3498 "1:\tmovl (%%esp), %%ebx\n\t"
3501 "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"
3502 "leal _tsrm_ls_cache@tlsldm(%%ebx), %0\n\t"
3503 "call ___tls_get_addr@plt\n\t"
3504 "leal _tsrm_ls_cache@tlsldm(%%ebx), %0\n"
3505 :
"=a" (ti),
"=&b" (_ebx),
"=&c" (_ecx),
"=&d" (_edx));
3506 tsrm_tls_offset = ti[1];
3507 tsrm_tls_index = ti[0] * 8;
3513#if !defined(ZEND_WIN32) && !defined(IR_TARGET_AARCH64)
3515 zend_jit_set_sp_adj_vm();
3520 zend_jit_setup_disasm();
3537 zend_jit_calc_trace_prologue_size();
3539 zend_jit_setup_stubs();
3544 zend_jit_setup_unwinder();
3548static void zend_jit_shutdown_ir(
void)
3584 if (jit->
ctx.
ir_base[if_ref].op3 == true_block) {
3591static void zend_jit_case_start(
zend_jit_ctx *jit,
int switch_b,
int case_b,
ir_ref switch_ref);
3593static void _zend_jit_add_predecessor_ref(
zend_jit_ctx *jit,
int b,
int pred,
ir_ref ref)
3612 }
else if (jit->
ctx.
ir_base[ref].op == IR_IF) {
3613 jit_IF_TRUE_FALSE_ex(jit, ref, b);
3615 }
else if (jit->
ctx.
ir_base[ref].op == IR_SWITCH) {
3616 zend_jit_case_start(jit, pred, b, ref);
3618 }
else if (jit->
ctx.
ir_base[ref].op == IR_UNREACHABLE) {
3633static void _zend_jit_merge_smart_branch_inputs(
zend_jit_ctx *jit,
3634 uint32_t true_label,
3635 uint32_t false_label,
3645 true_path = true_inputs;
3654 false_path = false_inputs;
3661 if (true_label == false_label && true_path && false_path) {
3663 _zend_jit_add_predecessor_ref(jit, true_label, jit->
b,
ir_END());
3664 }
else if (!true_path && !false_path) {
3667 _zend_jit_add_predecessor_ref(jit, true_label, jit->
b, true_path);
3670 _zend_jit_add_predecessor_ref(jit, true_label, jit->
b, true_path);
3673 _zend_jit_add_predecessor_ref(jit, false_label, jit->
b, false_path);
3693 if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
3694 n = insn->inputs_count;
3696 for (
j = k = 0, q = r = insn->ops + 1;
j <
n;
j++, q++) {
3700 phi = insn + 1 + (
n >> 2);
3701 while (phi->op == IR_PI) {
3704 while (phi->op == IR_PHI) {
3706 phi += 1 + ((
n + 1) >> 2);
3717 insn->op = IR_BEGIN;
3718 insn->inputs_count = 0;
3720 insn->inputs_count = k;
3725 (insn+k2)->optx = IR_NOP;
3728 phi = insn + 1 + (
n >> 2);
3729 while (phi->op == IR_PI) {
3732 while (phi->op == IR_PHI) {
3735 phi->op1 = phi->op2;
3737 phi->inputs_count = 0;
3739 phi->inputs_count = k + 1;
3741 n2 = 1 + ((
n + 1) >> 2);
3742 k2 = 1 + ((k + 1) >> 2);
3744 (phi+k2)->optx = IR_NOP;
3747 phi += 1 + ((
n + 1) >> 2);
3755static void zend_jit_case_start(
zend_jit_ctx *jit,
int switch_b,
int case_b,
ir_ref switch_ref)
3787 if (default_b == case_b) {
3833 while (insn->op >= IR_CALL && insn->op <= IR_TRAP) {
3846 }
else if (
n == 1) {
3859 jit_IF_TRUE_FALSE_ex(jit, ref, b);
3862 jit_IF_TRUE_FALSE_ex(jit, ref, b);
3865 }
else if (op == IR_SWITCH) {
3866 zend_jit_case_start(jit, pred, b, ref);
3869 ZEND_ASSERT(op == IR_END || op == IR_UNREACHABLE || op == IR_RETURN);
3884 int forward_edges_count = 0;
3885 int back_edges_count = 0;
3899 forward_edges_count++;
3908 jit_IF_TRUE_FALSE_ex(jit, ref, b);
3910 }
else if (op == IR_SWITCH) {
3911 zend_jit_case_start(jit, pred, b, ref);
3914 ZEND_ASSERT(op == IR_END || op == IR_UNREACHABLE || op == IR_RETURN);
3979 _zend_jit_add_predecessor_ref(jit, succ, b,
ir_END());
3989 if (GCC_GLOBAL_REGS) {
3990 ref = jit_IP32(jit);
3996 if (GCC_GLOBAL_REGS) {
4006static int zend_jit_jmp_frameless(
4009 const void *exit_addr,
4012 ir_ref ref, if_ref, cache_result, function_result, phi_result, cache_slot_ref;
4017 cache_result =
ir_LOAD_L(cache_slot_ref);
4020 if_ref =
ir_IF(cache_result);
4037 _zend_jit_add_predecessor_ref(jit, bb->
successors[0], jit->
b, ref);
4038 _zend_jit_add_predecessor_ref(jit, bb->
successors[1], jit->
b, ref);
4045static int zend_jit_cond_jmp(
zend_jit_ctx *jit,
const zend_op *next_opline,
int target_block)
4057 zend_jit_set_last_valid_opline(jit, next_opline);
4061 ref = jit_IF_ex(jit, jit_CMP_IP(jit, IR_NE, next_opline), target_block);
4063 _zend_jit_add_predecessor_ref(jit, bb->
successors[0], jit->
b, ref);
4064 _zend_jit_add_predecessor_ref(jit, bb->
successors[1], jit->
b, ref);
4067 zend_jit_set_last_valid_opline(jit, next_opline);
4081 zend_jit_reset_last_valid_opline(jit);
4082 return zend_jit_set_ip(jit, next_opline - 1);
4089 jit_STUB_ADDR(jit, jit_stub_exception_handler));
4092static void zend_jit_check_exception_undef_result(
zend_jit_ctx *jit,
const zend_op *opline)
4099static void zend_jit_type_check_undef(
zend_jit_ctx *jit,
4103 bool check_exception,
4109 if (!in_cold_path) {
4115 jit_SET_EX_OPLINE(jit, opline);
4118 if (check_exception) {
4120 zend_jit_check_exception_undef_result(jit, opline);
4122 zend_jit_check_exception(jit);
4132 bool check_exception)
4136 if_def =
ir_IF(jit_Z_TYPE_ref(jit, ref));
4140 jit_SET_EX_OPLINE(jit, opline);
4145 if (check_exception) {
4146 zend_jit_check_exception(jit);
4149 ref2 =
jit_EG(uninitialized_zval);
4153 return ir_PHI_2(IR_ADDR, ref2, ref);
4156static void zend_jit_recv_entry(
zend_jit_ctx *jit,
int b)
4172 if (!GCC_GLOBAL_REGS) {
4176 jit_STORE_FP(jit, 2);
4183static void zend_jit_osr_entry(
zend_jit_ctx *jit,
int b)
4190 if (!GCC_GLOBAL_REGS) {
4194 jit_STORE_FP(jit, 2);
4203 if (!GCC_GLOBAL_REGS) {
4207 jit_STORE_FP(jit, 2);
4217 zend_jit_set_ip(jit, opline);
4223 if (GCC_GLOBAL_REGS) {
4230 zend_jit_check_exception(jit);
4233 switch (opline->
opcode) {
4243 zend_jit_set_last_valid_opline(jit, opline + 2);
4246 zend_jit_set_last_valid_opline(jit, opline + 1);
4258 zend_jit_set_ip(jit, opline);
4276 if (GCC_GLOBAL_REGS) {
4320 _zend_jit_add_predecessor_ref(jit, succ, jit->
b, ref);
4323 zend_jit_reset_last_valid_opline(jit);
4328static int zend_jit_call(
zend_jit_ctx *jit,
const zend_op *opline,
unsigned int next_block)
4330 return zend_jit_tail_handler(jit, opline);
4339 jit_set_Z_LVAL(jit, dst, zend_jit_use_reg(jit, src));
4341 (
Z_REG(dst) != ZREG_FP ||
4342 !
JIT_G(current_frame) ||
4344 jit_set_Z_TYPE_INFO(jit, dst,
IS_LONG);
4347 jit_set_Z_DVAL(jit, dst, zend_jit_use_reg(jit, src));
4349 (
Z_REG(dst) != ZREG_FP ||
4350 !
JIT_G(current_frame) ||
4352 jit_set_Z_TYPE_INFO(jit, dst,
IS_DOUBLE);
4366 jit_set_Z_LVAL(jit, dst, zend_jit_use_reg(jit, src));
4367 if (
Z_REG(dst) != ZREG_FP || !
JIT_G(current_frame)) {
4368 jit_set_Z_TYPE_INFO(jit, dst,
IS_LONG);
4372 jit_set_Z_TYPE_INFO(jit, dst,
IS_LONG);
4375 jit_set_Z_DVAL(jit, dst, zend_jit_use_reg(jit, src));
4376 if (
Z_REG(dst) != ZREG_FP || !
JIT_G(current_frame)) {
4377 jit_set_Z_TYPE_INFO(jit, dst,
IS_DOUBLE);
4381 jit_set_Z_TYPE_INFO(jit, dst,
IS_DOUBLE);
4395 zend_jit_def_reg(jit, dst, jit_Z_LVAL(jit, src));
4397 zend_jit_def_reg(jit, dst, jit_Z_DVAL(jit, src));
4404static int zend_jit_store_var(
zend_jit_ctx *jit, uint32_t info,
int var,
int ssa_var,
bool set_type)
4409 return zend_jit_spill_store(jit, src, dst, info, set_type);
4412static int zend_jit_store_ref(
zend_jit_ctx *jit, uint32_t info,
int var, int32_t src,
bool set_type)
4417 jit_set_Z_LVAL(jit, dst, src);
4419 (
Z_REG(dst) != ZREG_FP ||
4420 !
JIT_G(current_frame) ||
4422 jit_set_Z_TYPE_INFO(jit, dst,
IS_LONG);
4425 jit_set_Z_DVAL(jit, dst, src);
4427 (
Z_REG(dst) != ZREG_FP ||
4428 !
JIT_G(current_frame) ||
4430 jit_set_Z_TYPE_INFO(jit, dst,
IS_DOUBLE);
4445 if (insn->op == IR_RLOAD && insn->op2 == reg) {
4448 }
else if (insn->op == IR_START) {
4464 return zend_jit_deopt_rload(jit,
type, reg);
4476 jit_set_Z_LVAL(jit, dst, src);
4477 jit_set_Z_TYPE_INFO(jit, dst,
IS_LONG);
4481static int zend_jit_store_const_double(
zend_jit_ctx *jit,
int var,
double val)
4489 jit_set_Z_DVAL(jit, dst, src);
4490 jit_set_Z_TYPE_INFO(jit, dst,
IS_DOUBLE);
4499 jit_set_Z_TYPE_INFO(jit, dst,
type);
4503static int zend_jit_store_reg(
zend_jit_ctx *jit, uint32_t info,
int var, int8_t reg,
bool in_mem,
bool set_type)
4511 src = zend_jit_deopt_rload(jit,
type, reg);
4514 }
else if (!in_mem) {
4515 jit_set_Z_LVAL(jit, dst, src);
4517 (
Z_REG(dst) != ZREG_FP ||
4518 !
JIT_G(current_frame) ||
4520 jit_set_Z_TYPE_INFO(jit, dst,
IS_LONG);
4525 src = zend_jit_deopt_rload(jit,
type, reg);
4528 }
else if (!in_mem) {
4529 jit_set_Z_DVAL(jit, dst, src);
4531 (
Z_REG(dst) != ZREG_FP ||
4532 !
JIT_G(current_frame) ||
4534 jit_set_Z_TYPE_INFO(jit, dst,
IS_DOUBLE);
4543static int zend_jit_store_spill_slot(
zend_jit_ctx *jit, uint32_t info,
int var, int8_t reg, int32_t
offset,
bool set_type)
4553 jit_set_Z_LVAL(jit, dst, src);
4555 (
Z_REG(dst) != ZREG_FP ||
4556 !
JIT_G(current_frame) ||
4558 jit_set_Z_TYPE_INFO(jit, dst,
IS_LONG);
4566 jit_set_Z_DVAL(jit, dst, src);
4568 (
Z_REG(dst) != ZREG_FP ||
4569 !
JIT_G(current_frame) ||
4571 jit_set_Z_TYPE_INFO(jit, dst,
IS_DOUBLE);
4580static int zend_jit_store_var_type(
zend_jit_ctx *jit,
int var, uint32_t
type)
4584 jit_set_Z_TYPE_INFO(jit, dst,
type);
4590 ir_ref if_refcounted, end1;
4592 if_refcounted = jit_if_REFCOUNTED(jit, var_addr);
4596 jit_GC_ADDREF(jit, jit_Z_PTR(jit, var_addr));
4605 return zend_jit_spill_store(jit, src, dst, info, 1);
4619 if (
JIT_G(current_frame)) {
4631 return zend_jit_spill_store(jit, src, dst, info, set_type);
4636static int zend_jit_load_var(
zend_jit_ctx *jit, uint32_t info,
int var,
int ssa_var)
4641 return zend_jit_load_reg(jit, src, dst, info);
4649 jit_set_Z_TYPE_INFO(jit, dst,
IS_UNDEF);
4656 if (!zend_jit_same_addr(src, dst)) {
4659 zend_jit_def_reg(jit, dst, zend_jit_use_reg(jit, src));
4663 if (!zend_jit_spill_store(jit, dst, var_addr, info,
4674 if (!zend_jit_spill_store(jit, src, dst, info,
4688 if (!zend_jit_load_reg(jit, src, dst, info)) {
4699 if (!zend_jit_spill_store(jit, src, dst, info,
4761 run_time_cache =
ir_PHI_2(IR_ADDR, run_time_cache, run_time_cache2);
4781 *observer_handler =
ir_PHI_2(IR_ADDR, observer_handler_internal, observer_handler_user);
4811static int zend_jit_inc_dec(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info,
zend_jit_addr op1_addr, uint32_t op1_def_info,
zend_jit_addr op1_def_addr, uint32_t res_use_info, uint32_t res_info,
zend_jit_addr res_addr,
int may_overflow,
int may_throw)
4819 if_long = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
4823 op1_lval_ref = jit_Z_LVAL(jit, op1_addr);
4824 jit_set_Z_LVAL(jit, res_addr, op1_lval_ref);
4826 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
4833 jit_set_Z_TYPE_INFO(jit, op1_def_addr,
IS_LONG);
4836 op = may_overflow ? IR_ADD_OV : IR_ADD;
4838 op = may_overflow ? IR_SUB_OV : IR_SUB;
4840 if (!op1_lval_ref) {
4841 op1_lval_ref = jit_Z_LVAL(jit, op1_addr);
4845 jit_set_Z_LVAL(jit, op1_def_addr, ref);
4851 const void *exit_addr;
4853 uint32_t old_op1_info, old_res_info = 0;
4855 stack =
JIT_G(current_frame)->stack;
4880 exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
4881 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
4886 jit_set_Z_LVAL(jit, res_addr, ref);
4888 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
4896 }
else if (may_overflow) {
4903 const void *exit_addr;
4905 uint32_t old_res_info = 0;
4907 stack =
JIT_G(current_frame)->stack;
4914 exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
4915 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
4920 jit_set_Z_LVAL(jit, res_addr, ref);
4922 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
4937 jit_set_Z_LVAL(jit, res_addr, ref);
4939 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
4952#if SIZEOF_ZEND_LONG == 4
4954 jit_set_Z_W2(jit, op1_def_addr,
ir_CONST_U32(0x41e00000));
4956 jit_set_Z_LVAL(jit, op1_def_addr,
ir_CONST_LONG(0x43e0000000000000));
4958 jit_set_Z_TYPE_INFO(jit, op1_def_addr,
IS_DOUBLE);
4964#if SIZEOF_ZEND_LONG == 4
4965 jit_set_Z_LVAL(jit, op1_def_addr,
ir_CONST_LONG(0x00200000));
4966 jit_set_Z_W2(jit, op1_def_addr,
ir_CONST_U32(0xc1e00000));
4968 jit_set_Z_LVAL(jit, op1_def_addr,
ir_CONST_LONG(0xc3e0000000000000));
4970 jit_set_Z_TYPE_INFO(jit, op1_def_addr,
IS_DOUBLE);
4979#if SIZEOF_ZEND_LONG == 4
4983 jit_set_Z_LVAL(jit, res_addr,
ir_CONST_LONG(0x43e0000000000000));
4985 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
4991#if SIZEOF_ZEND_LONG == 4
4995 jit_set_Z_LVAL(jit, res_addr,
ir_CONST_LONG(0xc3e0000000000000));
4997 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5009 jit_set_Z_LVAL(jit, res_addr, ref);
5011 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
5021 jit_SET_EX_OPLINE(jit, opline);
5025 if_def = jit_if_not_Z_TYPE(jit, op1_addr,
IS_UNDEF);
5031 jit_set_Z_TYPE_INFO(jit, op1_def_addr,
IS_NULL);
5037 ref = jit_ZVAL_ADDR(jit, op1_addr);
5044 ref2 = jit_Z_PTR_ref(jit, ref);
5046 if_typed = jit_if_TYPED_REF(jit, ref2);
5051 arg2 = jit_ZVAL_ADDR(jit, res_addr);
5068 zend_jit_check_exception(jit);
5074 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
5099 zend_jit_check_exception(jit);
5102 ref = jit_Z_DVAL(jit, op1_addr);
5104 jit_set_Z_DVAL(jit, res_addr, ref);
5105 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5113 jit_set_Z_DVAL(jit, op1_def_addr, ref);
5116 jit_set_Z_DVAL(jit, res_addr, ref);
5117 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5123 if (!zend_jit_store_var_if_necessary_ex(jit, opline->
op1.
var, op1_def_addr, op1_def_info, op1_addr, op1_info)) {
5127 if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr, res_info)) {
5141 uint32_t res_use_info,
5144 bool same_ops = zend_jit_same_addr(op1_addr, op2_addr);
5149 op = may_overflow ? IR_ADD_OV : IR_ADD;
5151 op = may_overflow ? IR_SUB_OV : IR_SUB;
5153 op = may_overflow ? IR_MUL_OV : IR_MUL;
5157 op1 = jit_Z_LVAL(jit, op1_addr);
5158 op2 = (same_ops) ?
op1 : jit_Z_LVAL(jit, op2_addr);
5165 uint32_t old_res_info;
5167 const void *exit_addr;
5174 exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
5181 exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
5184 exit_point = zend_jit_trace_get_exit_point(opline, 0);
5187 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
5194 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
5195 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
5211 jit_set_Z_LVAL(jit, res_addr, ref);
5214 if (!zend_jit_same_addr(op1_addr, res_addr)) {
5216 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
5234#if SIZEOF_ZEND_LONG == 4
5238 jit_set_Z_LVAL(jit, res_addr,
ir_CONST_LONG(0x43e0000000000000));
5240 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5253#if SIZEOF_ZEND_LONG == 4
5257 jit_set_Z_LVAL(jit, res_addr,
ir_CONST_LONG(0xc3e0000000000000));
5259 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5274 op1 = jit_Z_LVAL(jit, op1_addr);
5275 op2 = (same_ops) ?
op1 : jit_Z_LVAL(jit, op2_addr);
5288 jit_set_Z_DVAL(jit, res_addr, ref);
5290 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5305 uint32_t res_use_info)
5321 op1 = jit_Z_LVAL(jit, op1_addr);
5322 op2 = jit_Z_DVAL(jit, op2_addr);
5324 jit_set_Z_DVAL(jit, res_addr, ref);
5328 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5339 uint32_t res_use_info)
5355 op1 = jit_Z_DVAL(jit, op1_addr);
5356 op2 = jit_Z_LVAL(jit, op2_addr);
5358 jit_set_Z_DVAL(jit, res_addr, ref);
5361 if (!zend_jit_same_addr(op1_addr, res_addr)) {
5363 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5370static int zend_jit_math_double_double(
zend_jit_ctx *jit,
5375 uint32_t res_use_info)
5377 bool same_ops = zend_jit_same_addr(op1_addr, op2_addr);
5392 op1 = jit_Z_DVAL(jit, op1_addr);
5393 op2 = (same_ops) ?
op1 : jit_Z_DVAL(jit, op2_addr);
5395 jit_set_Z_DVAL(jit, res_addr, ref);
5398 if (!zend_jit_same_addr(op1_addr, res_addr)) {
5400 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
5421 uint32_t res_use_info,
5433 bool same_ops = zend_jit_same_addr(op1_addr, op2_addr);
5443 zend_jit_use_reg(jit, op1_addr);
5448 zend_jit_use_reg(jit, op2_addr);
5459 if_op1_long = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
5463 if_op1_long_op2_long = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
5466 if (!zend_jit_math_long_long(jit, opline, opcode, op1_addr, op2_addr, res_addr, res_info, res_use_info, may_overflow)) {
5469 ir_refs_add(end_inputs,
ir_END());
5474 if (if_op1_long_op2_long) {
5480 if_op1_long = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
5484 if_op1_long_op2_long = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
5488 if_op1_long_op2_double = jit_if_Z_TYPE(jit, op2_addr,
IS_DOUBLE);
5493 if (!zend_jit_math_long_double(jit, opcode, op1_addr, op2_addr, res_addr, res_use_info)) {
5496 ir_refs_add(end_inputs,
ir_END());
5502 if (!zend_jit_math_long_long(jit, opline, opcode, op1_addr, op2_addr, res_addr, res_info, res_use_info, may_overflow)) {
5505 ir_refs_add(end_inputs,
ir_END());
5513 if_op1_double = jit_if_Z_TYPE(jit, op1_addr,
IS_DOUBLE);
5520 if_op1_double_op2_double = jit_if_Z_TYPE(jit, op2_addr,
IS_DOUBLE);
5523 if (!zend_jit_math_double_double(jit, opcode, op1_addr, op2_addr, res_addr, res_use_info)) {
5526 ir_refs_add(end_inputs,
ir_END());
5527 if (if_op1_double_op2_double) {
5533 if_op1_double_op2_long = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
5538 if (!zend_jit_math_double_long(jit, opcode, op1_addr, op2_addr, res_addr, res_use_info)) {
5541 ir_refs_add(end_inputs,
ir_END());
5542 }
else if (if_op1_double_op2_double) {
5545 }
else if (if_op1_long) {
5553 if_op1_double = jit_if_Z_TYPE(jit, op1_addr,
IS_DOUBLE);
5560 if_op1_double_op2_double = jit_if_Z_TYPE(jit, op2_addr,
IS_DOUBLE);
5563 if (!zend_jit_math_double_double(jit, opcode, op1_addr, op2_addr, res_addr, res_use_info)) {
5566 ir_refs_add(end_inputs,
ir_END());
5567 if (if_op1_double_op2_double) {
5573 if_op1_double_op2_long = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
5578 if (!zend_jit_math_double_long(jit, opcode, op1_addr, op2_addr, res_addr, res_use_info)) {
5581 ir_refs_add(end_inputs,
ir_END());
5582 }
else if (if_op1_double_op2_double) {
5590 if_op2_double = jit_if_Z_TYPE(jit, op2_addr,
IS_DOUBLE);
5597 if_op1_double_op2_double = jit_if_Z_TYPE(jit, op1_addr,
IS_DOUBLE);
5600 if (!zend_jit_math_double_double(jit, opcode, op1_addr, op2_addr, res_addr, res_use_info)) {
5603 ir_refs_add(end_inputs,
ir_END());
5604 if (if_op1_double_op2_double) {
5610 if_op1_long_op2_double = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
5615 if (!zend_jit_math_long_double(jit, opcode, op1_addr, op2_addr, res_addr, res_use_info)) {
5618 ir_refs_add(end_inputs,
ir_END());
5619 }
else if (if_op1_double_op2_double) {
5634 if (!zend_jit_spill_store_inv(jit, op1_addr, real_addr, op1_info)) {
5637 op1_addr = real_addr;
5641 if (!zend_jit_spill_store_inv(jit, op2_addr, real_addr, op2_info)) {
5644 op2_addr = real_addr;
5649 arg1 = jit_ZVAL_ADDR(jit, res_addr);
5651 arg2 = jit_ZVAL_ADDR(jit, op1_addr);
5652 arg3 = jit_ZVAL_ADDR(jit, op2_addr);
5653 jit_SET_EX_OPLINE(jit, opline);
5667 jit_FREE_OP(jit, op1_type,
op1, op1_info,
NULL);
5668 jit_FREE_OP(jit, op2_type,
op2, op2_info,
NULL);
5673 jit_STUB_ADDR(jit, jit_stub_exception_handler_free_op2));
5675 zend_jit_check_exception_undef_result(jit, opline);
5677 zend_jit_check_exception(jit);
5682 if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) {
5686 ir_refs_add(end_inputs,
ir_END());
5689 if (end_inputs->
count) {
5698 if (res_inputs->
count == 1) {
5699 zend_jit_def_reg(jit, res_addr, res_inputs->refs[0]);
5702 zend_jit_def_reg(jit, res_addr, phi);
5709static int zend_jit_math(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info,
zend_jit_addr op1_addr, uint32_t op2_info,
zend_jit_addr op2_addr, uint32_t res_use_info, uint32_t res_info,
zend_jit_addr res_addr,
int may_overflow,
int may_throw)
5713 if (!zend_jit_math_helper(jit, opline, opline->
opcode, opline->
op1_type, opline->
op1, op1_addr, op1_info, opline->
op2_type, opline->
op2, op2_addr, op2_info, opline->
result.
var, res_addr, res_info, res_use_info, may_overflow, may_throw)) {
5716 if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr, res_info)) {
5729 jit_set_Z_PTR(jit, res_addr, ref);
5731 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
5732 jit_FREE_OP(jit, opline->
op2_type, opline->
op2, op2_info, opline);
5752 uint32_t res_use_info,
5758 bool same_ops = zend_jit_same_addr(op1_addr, op2_addr);
5767 zend_jit_use_reg(jit, op1_addr);
5773 zend_jit_use_reg(jit, op2_addr);
5777 if_long1 = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
5781 if_long2 = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
5793 zend_jit_invalidate_var_if_necessary(jit, op1_type, op1_addr,
op1);
5794 zend_jit_invalidate_var_if_necessary(jit, op2_type, op2_addr,
op2);
5795 jit_SET_EX_OPLINE(jit, opline);
5805 ref = jit_Z_LVAL(jit, op2_addr);
5807 op2_range->
min < 0 ||
5810 ir_ref if_wrong, cold_path, ref2, if_ok;
5811 ir_ref op1_ref = jit_Z_LVAL(jit, op1_addr);
5817 jit_SET_EX_OPLINE(jit, opline);
5818 zend_jit_invalidate_var_if_necessary(jit, op1_type, op1_addr,
op1);
5819 zend_jit_invalidate_var_if_necessary(jit, op2_type, op2_addr,
op2);
5820 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_negative_shift));
5829 ref =
ir_SHL_L(jit_Z_LVAL(jit, op1_addr), ref);
5832 }
else if (opcode ==
ZEND_SR) {
5839 jit_Z_LVAL(jit, op1_addr),
5842 zend_jit_invalidate_var_if_necessary(jit, op1_type, op1_addr,
op1);
5843 zend_jit_invalidate_var_if_necessary(jit, op2_type, op2_addr,
op2);
5844 jit_SET_EX_OPLINE(jit, opline);
5854 ref = jit_Z_LVAL(jit, op2_addr);
5856 op2_range->
min < 0 ||
5859 ir_ref if_wrong, cold_path, ref2, if_ok;
5865 jit_SET_EX_OPLINE(jit, opline);
5866 zend_jit_invalidate_var_if_necessary(jit, op1_type, op1_addr,
op1);
5867 zend_jit_invalidate_var_if_necessary(jit, op2_type, op2_addr,
op2);
5868 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_negative_shift));
5876 ref =
ir_SAR_L(jit_Z_LVAL(jit, op1_addr), ref);
5882 if (op2_lval == 0) {
5883 zend_jit_invalidate_var_if_necessary(jit, op1_type, op1_addr,
op1);
5884 zend_jit_invalidate_var_if_necessary(jit, op2_type, op2_addr,
op2);
5885 jit_SET_EX_OPLINE(jit, opline);
5890 }
else if (zend_long_is_power_of_two(op2_lval) && op1_range && op1_range->
min >= 0) {
5897 ir_ref op1_ref = jit_Z_LVAL(jit, op1_addr);
5899 ref = jit_Z_LVAL(jit, op2_addr);
5903 jit_SET_EX_OPLINE(jit, opline);
5904 zend_jit_invalidate_var_if_necessary(jit, op1_type, op1_addr,
op1);
5905 zend_jit_invalidate_var_if_necessary(jit, op2_type, op2_addr,
op2);
5906 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_mod_by_zero));
5911 if (!op2_range || (op2_range->
min <= -1 && op2_range->
max >= -1)) {
5937 op1 = jit_Z_LVAL(jit, op1_addr);
5938 op2 = (same_ops) ?
op1 : jit_Z_LVAL(jit, op2_addr);
5949 jit_set_Z_LVAL(jit, res_addr, ref);
5951 if (!zend_jit_same_addr(op1_addr, res_addr)) {
5953 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
5964 if (if_long2 && if_long1) {
5970 }
else if (if_long1) {
5972 }
else if (if_long2) {
5977 ir_ref if_def, ref, ref2;
5979 ref = jit_ZVAL_ADDR(jit, op1_addr);
5980 if_def = jit_if_not_Z_TYPE(jit, op1_addr,
IS_UNDEF);
5986 ref2 =
jit_EG(uninitialized_zval);
5988 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
5993 ir_ref if_def, ref, ref2;
5995 ref = jit_ZVAL_ADDR(jit, op2_addr);
5996 if_def = jit_if_not_Z_TYPE(jit, op2_addr,
IS_UNDEF);
6002 ref2 =
jit_EG(uninitialized_zval);
6004 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
6010 if (!zend_jit_spill_store_inv(jit, op1_addr, real_addr, op1_info)) {
6013 op1_addr = real_addr;
6017 if (!zend_jit_spill_store_inv(jit, op2_addr, real_addr, op2_info)) {
6020 op2_addr = real_addr;
6025 arg1 = jit_ZVAL_ADDR(jit, res_addr);
6027 arg2 = jit_ZVAL_ADDR(jit, op1_addr);
6028 arg3 = jit_ZVAL_ADDR(jit, op2_addr);
6029 jit_SET_EX_OPLINE(jit, opline);
6036 }
else if (opcode ==
ZEND_SL) {
6038 }
else if (opcode ==
ZEND_SR) {
6047 if (op1_addr == res_addr && (op2_info &
MAY_BE_RCN)) {
6052 jit_FREE_OP(jit, op1_type,
op1, op1_info,
NULL);
6053 jit_FREE_OP(jit, op2_type,
op2, op2_info,
NULL);
6058 jit_STUB_ADDR(jit, jit_stub_exception_handler_free_op2));
6060 zend_jit_check_exception_undef_result(jit, opline);
6062 zend_jit_check_exception(jit);
6068 if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) {
6080 if (res_inputs->
count == 1) {
6081 zend_jit_def_reg(jit, res_addr, res_inputs->refs[0]);
6084 zend_jit_def_reg(jit, res_addr, phi);
6092static int zend_jit_long_math(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info,
zend_ssa_range *op1_range,
zend_jit_addr op1_addr, uint32_t op2_info,
zend_ssa_range *op2_range,
zend_jit_addr op2_addr, uint32_t res_use_info, uint32_t res_info,
zend_jit_addr res_addr,
int may_throw)
6096 if (!zend_jit_long_math_helper(jit, opline, opline->
opcode,
6097 opline->
op1_type, opline->
op1, op1_addr, op1_info, op1_range,
6098 opline->
op2_type, opline->
op2, op2_addr, op2_info, op2_range,
6099 opline->
result.
var, res_addr, res_info, res_use_info, may_throw)) {
6102 if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr, res_info)) {
6127 if_op1_string = jit_if_Z_TYPE(jit, op1_addr,
IS_STRING);
6131 if_op2_string = jit_if_Z_TYPE(jit, op2_addr,
IS_STRING);
6134 if (zend_jit_same_addr(op1_addr, res_addr)) {
6154 jit_FREE_OP(jit, op2_type,
op2, op2_info, opline);
6155 if (if_op1_string || if_op2_string) {
6162 if (if_op1_string && if_op2_string) {
6165 }
else if (if_op1_string) {
6167 }
else if (if_op2_string) {
6175 jit_SET_EX_OPLINE(jit, opline);
6180 jit_FREE_OP(jit, op1_type,
op1, op1_info,
NULL);
6181 jit_FREE_OP(jit, op2_type,
op2, op2_info,
NULL);
6185 jit_STUB_ADDR(jit, jit_stub_exception_handler_free_op2));
6187 zend_jit_check_exception_undef_result(jit, opline);
6189 zend_jit_check_exception(jit);
6209 return zend_jit_concat_helper(jit, opline, opline->
op1_type, opline->
op1, op1_addr, op1_info, opline->
op2_type, opline->
op2, op2_addr, op2_info, res_addr, may_throw);
6217 uint32_t op1_def_info,
6219 uint32_t op1_mem_info,
6238 ref = jit_ZVAL_ADDR(jit, op1_addr);
6241 op1_noref_path =
ir_END();
6243 ref2 = jit_Z_PTR_ref(jit, ref);
6245 if_op1_typed = jit_if_TYPED_REF(jit, ref2);
6250 if (!zend_jit_spill_store_inv(jit, op2_addr, real_addr, op2_info)) {
6253 arg2 = jit_ZVAL_ADDR(jit, real_addr);
6255 arg2 = jit_ZVAL_ADDR(jit, op2_addr);
6257 jit_SET_EX_OPLINE(jit, opline);
6266 zend_jit_check_exception(jit);
6273 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
6283 result = zend_jit_math_helper(jit, opline, opline->
extended_value, opline->
op1_type, opline->
op1, op1_addr, op1_info, opline->
op2_type, opline->
op2, op2_addr, op2_info, opline->
op1.
var, op1_def_addr, op1_def_info, op1_mem_info, may_overflow, may_throw);
6292 opline->
op1_type, opline->
op1, op1_addr, op1_info, op1_range,
6293 opline->
op2_type, opline->
op2, op2_addr, op2_info, op2_range,
6294 opline->
op1.
var, op1_def_addr, op1_def_info, op1_mem_info, may_throw);
6297 result = zend_jit_concat_helper(jit, opline, opline->
op1_type, opline->
op1, op1_addr, op1_info, opline->
op2_type, opline->
op2, op2_addr, op2_info, op1_def_addr, may_throw);
6303 if (!zend_jit_store_var_if_necessary_ex(jit, opline->
op1.
var, op1_def_addr, op1_def_info, op1_addr, op1_info)) {
6322 return ir_PHI_2(IR_ADDR, ref2, ref);
6328 ref = jit_ZVAL_DEREF_ref(jit, ref);
6338 ref2 = jit_Z_PTR_ref(jit, ref);
6340 return ir_PHI_2(IR_ADDR, ref2, ref);
6346 ref = jit_ZVAL_INDIRECT_DEREF_ref(jit, ref);
6354 uint32_t var_def_info,
6359 bool check_exception)
6367 jit_ZVAL_COPY_CONST(jit,
6369 var_info, var_def_info,
6372 jit_ZVAL_COPY_CONST(jit,
6374 var_info, var_def_info,
6376 jit_ZVAL_COPY_CONST(jit,
6385 if_def = jit_if_not_Z_TYPE(jit, val_addr,
IS_UNDEF);
6388 jit_set_Z_TYPE_INFO(jit, var_addr,
IS_NULL);
6390 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
6392 jit_SET_EX_OPLINE(jit, opline);
6398 if (check_exception) {
6399 ir_GUARD(
ret, jit_STUB_ADDR(jit, jit_stub_exception_handler_undef));
6407 ir_ref ref = jit_ZVAL_ADDR(jit, val_addr);
6408 ref = jit_ZVAL_DEREF_ref(jit, ref);
6411 ir_ref ref,
type, if_ref, ref2, refcount, if_not_zero;
6413 ref = jit_ZVAL_ADDR(jit, val_addr);
6414 type = jit_Z_TYPE_ref(jit, ref);
6418 ref = jit_Z_PTR_ref(jit, ref);
6426 jit_ZVAL_COPY_2(jit,
6433 refcount = jit_GC_DELREF(jit, ref);
6434 if_not_zero =
ir_IF(refcount);
6439 jit_ZVAL_DTOR(jit, ref, val_info, opline);
6454 jit_ZVAL_COPY_2(jit,
6470static int zend_jit_assign_to_variable_call(
zend_jit_ctx *jit,
6474 uint32_t __var_info,
6475 uint32_t __var_def_info,
6480 bool __check_exception)
6488 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
6494 jit_guard_not_Z_TYPE(jit, val_addr,
IS_UNDEF, exit_addr);
6499 if_def =
ir_IF(jit_Z_TYPE(jit, val_addr));
6501 jit_SET_EX_OPLINE(jit, opline);
6505 jit_ZVAL_ADDR(jit, var_addr),
6506 jit_EG(uninitialized_zval));
6514 func = jit_stub_assign_tmp;
6516 func = jit_stub_assign_const;
6518 func = jit_stub_assign_tmp;
6521 func = jit_stub_assign_tmp;
6523 func = jit_stub_assign_var;
6527 func = jit_stub_assign_cv_noref;
6529 func = jit_stub_assign_cv;
6536 jit_SET_EX_OPLINE(jit, opline);
6540 jit_ZVAL_ADDR(jit, var_addr),
6541 jit_ZVAL_ADDR(jit, val_addr));
6550static int zend_jit_assign_to_variable(
zend_jit_ctx *jit,
6555 uint32_t var_def_info,
6561 bool check_exception)
6575 zend_jit_use_reg(jit, val_addr);
6582 real_res_addr = res_addr;
6591 ir_ref ref = 0, if_ref = 0, ref2,
arg2, if_typed, non_ref_path;
6595 ref = jit_ZVAL_ADDR(jit, var_use_addr);
6598 ref2 = jit_Z_PTR_ref(jit, ref);
6600 ref2 = jit_ZVAL_ADDR(jit, ref_addr);
6602 if_typed = jit_if_TYPED_REF(jit, ref2);
6604 jit_SET_EX_OPLINE(jit, opline);
6614 if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
6617 arg2 = jit_ZVAL_ADDR(jit, real_addr);
6619 arg2 = jit_ZVAL_ADDR(jit, val_addr);
6623 func = (uintptr_t)zend_jit_assign_const_to_typed_ref;
6625 func = (uintptr_t)zend_jit_assign_tmp_to_typed_ref;
6627 func = (uintptr_t)zend_jit_assign_var_to_typed_ref;
6629 func = (uintptr_t)zend_jit_assign_cv_to_typed_ref;
6636 func = (uintptr_t)zend_jit_assign_const_to_typed_ref2;
6638 func = (uintptr_t)zend_jit_assign_tmp_to_typed_ref2;
6640 func = (uintptr_t)zend_jit_assign_var_to_typed_ref2;
6642 func = (uintptr_t)zend_jit_assign_cv_to_typed_ref2;
6648 if (check_exception) {
6649 zend_jit_check_exception(jit);
6651 ir_refs_add(end_inputs,
ir_END());
6659 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
6667 ir_ref ref, counter, if_not_zero;
6670 if_refcounted = jit_if_REFCOUNTED(jit, var_use_addr);
6674 }
else if (RC_MAY_BE_1(var_info)) {
6677 ref = jit_Z_PTR(jit, var_use_addr);
6678 if (RC_MAY_BE_1(var_info)) {
6679 if (!zend_jit_simple_assign(jit, opline, var_addr, var_info, var_def_info,
val_type, val_addr, val_info, res_addr, 0)) {
6682 counter = jit_GC_DELREF(jit, ref);
6684 if_not_zero =
ir_IF(counter);
6686 jit_ZVAL_DTOR(jit, ref, var_info, opline);
6687 if (check_exception) {
6688 zend_jit_check_exception(jit);
6690 ir_refs_add(end_inputs,
ir_END());
6693 ir_ref if_may_leak = jit_if_GC_MAY_NOT_LEAK(jit, ref);
6696 jit_SET_EX_OPLINE(jit, opline);
6703 ir_refs_add(res_inputs, res_inputs->refs[res_inputs->
count - 1]);
6706 zend_jit_check_exception(jit);
6708 ir_refs_add(end_inputs,
ir_END());
6714 ir_refs_add(res_inputs, res_inputs->refs[res_inputs->
count - 1]);
6717 zend_jit_check_exception(jit);
6719 ir_refs_add(end_inputs,
ir_END());
6721 jit_GC_DELREF(jit, ref);
6723 ir_ref if_may_leak = jit_if_GC_MAY_NOT_LEAK(jit, ref);
6726 jit_SET_EX_OPLINE(jit, opline);
6736 if (simple_inputs) {
6741 if (!zend_jit_simple_assign(jit, opline, var_addr, var_info, var_def_info,
val_type, val_addr, val_info, res_addr, check_exception)) {
6744 if (end_inputs->
count) {
6745 ir_refs_add(end_inputs,
ir_END());
6749 if (end_inputs->
count) {
6760 if (res_inputs->
count == 1) {
6761 phi = res_inputs->refs[0];
6764 res_inputs->
count, res_inputs->refs);
6770 zend_jit_def_reg(jit, var_addr, phi);
6771 if (real_res_addr) {
6773 jit_set_Z_LVAL(jit, real_res_addr, jit_Z_LVAL(jit, var_addr));
6775 jit_set_Z_DVAL(jit, real_res_addr, jit_Z_DVAL(jit, var_addr));
6779 zend_jit_def_reg(jit, res_addr, phi);
6788 if (op1_addr != op1_def_addr) {
6789 if (!zend_jit_update_regs(jit, opline->
op1.
var, op1_addr, op1_def_addr, op1_info)) {
6793 op1_addr = op1_def_addr;
6797 if (!zend_jit_simple_assign(jit, opline, res_addr, res_use_info, res_info, opline->
op1_type, op1_addr, op1_info, 0, 1)) {
6800 if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr, res_info)) {
6810 uint32_t op1_def_info,
6822 if (op2_addr != op2_def_addr) {
6823 if (!zend_jit_update_regs(jit, opline->
op2.
var, op2_addr, op2_def_addr, op2_info)) {
6827 op2_addr = op2_def_addr;
6838 if (!zend_jit_assign_to_variable(jit, opline, op1_use_addr, op1_addr, op1_info, op1_def_info,
6839 opline->
op2_type, op2_addr, op2_info, res_addr, ref_addr, may_throw)) {
6844 if (!zend_jit_store_var_if_necessary_ex(jit, opline->
op1.
var, op1_addr, op1_def_info, op1_use_addr, op1_info)) {
6849 &&
Z_REG(op1_use_addr) == ZREG_FP
6853 jit_set_Z_TYPE_INFO(jit, op1_use_addr,
IS_LONG);
6854 if (
JIT_G(current_frame)) {
6858 jit_set_Z_TYPE_INFO(jit, op1_use_addr,
IS_DOUBLE);
6859 if (
JIT_G(current_frame)) {
6868 if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr, res_info)) {
6880 switch (opline->
opcode) {
6910 uint8_t smart_branch_opcode,
6911 uint32_t target_label,
6912 uint32_t target_label2,
6913 const void *exit_addr,
6914 bool skip_comparison)
6919 if (zend_jit_is_constant_cmp_long_long(opline, op1_range, op1_addr, op2_range, op2_addr, &
result)) {
6920 if (!smart_branch_opcode ||
6925 if (smart_branch_opcode && !exit_addr) {
6928 return jit_IF_ex(jit,
IR_FALSE,
result ? target_label : target_label2);
6929 }
else if (smart_branch_opcode ==
ZEND_JMPNZ ||
6931 return jit_IF_ex(jit,
IR_TRUE,
result ? target_label : target_label2);
6945 ref =
ir_CMP_OP(zend_jit_cmp_op(opline), jit_Z_LVAL(jit, op1_addr), jit_Z_LVAL(jit, op2_addr));
6948 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
6965 }
else if (smart_branch_opcode) {
6966 return jit_IF_ex(jit, ref,
6967 (smart_branch_opcode ==
ZEND_JMPZ || smart_branch_opcode ==
ZEND_JMPZ_EX) ? target_label2 : target_label);
6981 ir_ref ref =
ir_CMP_OP(zend_jit_cmp_op(opline),
ir_INT2D(jit_Z_LVAL(jit, op1_addr)), jit_Z_DVAL(jit, op2_addr));
6984 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
6993 }
else if (smart_branch_opcode) {
6994 return jit_IF_ex(jit, ref,
6995 (smart_branch_opcode ==
ZEND_JMPZ || smart_branch_opcode ==
ZEND_JMPZ_EX) ? target_label2 : target_label);
7002 ir_ref ref =
ir_CMP_OP(zend_jit_cmp_op(opline), jit_Z_DVAL(jit, op1_addr),
ir_INT2D(jit_Z_LVAL(jit, op2_addr)));
7005 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7014 }
else if (smart_branch_opcode) {
7015 return jit_IF_ex(jit, ref,
7016 (smart_branch_opcode ==
ZEND_JMPZ || smart_branch_opcode ==
ZEND_JMPZ_EX) ? target_label2 : target_label);
7023 ir_ref ref =
ir_CMP_OP(zend_jit_cmp_op(opline), jit_Z_DVAL(jit, op1_addr), jit_Z_DVAL(jit, op2_addr));
7026 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7043 }
else if (smart_branch_opcode) {
7044 return jit_IF_ex(jit, ref,
7045 (smart_branch_opcode ==
ZEND_JMPZ || smart_branch_opcode ==
ZEND_JMPZ_EX) ? target_label2 : target_label);
7061 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7070 }
else if (smart_branch_opcode) {
7071 return jit_IF_ex(jit, ref,
7072 (smart_branch_opcode ==
ZEND_JMPZ || smart_branch_opcode ==
ZEND_JMPZ_EX) ? target_label2 : target_label);
7088 uint8_t smart_branch_opcode,
7089 uint32_t target_label,
7090 uint32_t target_label2,
7091 const void *exit_addr,
7092 bool skip_comparison)
7103 bool same_ops = zend_jit_same_addr(op1_addr, op2_addr);
7116 zend_jit_use_reg(jit, op1_addr);
7121 zend_jit_use_reg(jit, op2_addr);
7127 if_op1_long = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
7131 if_op1_long_op2_long = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
7135 if_op1_long_op2_double = jit_if_Z_TYPE(jit, op2_addr,
IS_DOUBLE);
7140 ref = zend_jit_cmp_long_double(jit, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7144 ir_refs_add(end_inputs, ref);
7150 ref = zend_jit_cmp_long_long(jit, opline, op1_range, op1_addr, op2_range, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr, skip_comparison);
7154 ir_refs_add(end_inputs, ref);
7161 if_op1_double = jit_if_Z_TYPE(jit, op1_addr,
IS_DOUBLE);
7168 if_op1_double_op2_double = jit_if_Z_TYPE(jit, op2_addr,
IS_DOUBLE);
7171 ref = zend_jit_cmp_double_double(jit, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7175 ir_refs_add(end_inputs, ref);
7176 if (if_op1_double_op2_double) {
7182 if_op1_double_op2_long = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
7187 ref = zend_jit_cmp_double_long(jit, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7191 ir_refs_add(end_inputs, ref);
7192 }
else if (if_op1_double_op2_double) {
7195 }
else if (if_op1_long) {
7202 if_op1_double = jit_if_Z_TYPE(jit, op1_addr,
IS_DOUBLE);
7209 if_op1_double_op2_double = jit_if_Z_TYPE(jit, op2_addr,
IS_DOUBLE);
7212 ref = zend_jit_cmp_double_double(jit, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7216 ir_refs_add(end_inputs, ref);
7217 if (if_op1_double_op2_double) {
7223 if_op1_double_op2_long = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
7228 ref = zend_jit_cmp_double_long(jit, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7232 ir_refs_add(end_inputs, ref);
7233 }
else if (if_op1_double_op2_double) {
7240 if_op2_double = jit_if_Z_TYPE(jit, op2_addr,
IS_DOUBLE);
7247 if_op1_double_op2_double = jit_if_Z_TYPE(jit, op1_addr,
IS_DOUBLE);
7250 ref = zend_jit_cmp_double_double(jit, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7254 ir_refs_add(end_inputs, ref);
7255 if (if_op1_double_op2_double) {
7261 if_op1_long_op2_double = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
7266 ref = zend_jit_cmp_long_double(jit, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7270 ir_refs_add(end_inputs, ref);
7271 }
else if (if_op1_double_op2_double) {
7284 jit_SET_EX_OPLINE(jit, opline);
7288 if (!zend_jit_spill_store_inv(jit, op1_addr, real_addr, op1_info)) {
7291 op1_addr = real_addr;
7295 if (!zend_jit_spill_store_inv(jit, op2_addr, real_addr, op2_info)) {
7298 op2_addr = real_addr;
7301 op1 = jit_ZVAL_ADDR(jit, op1_addr);
7305 op2 = jit_ZVAL_ADDR(jit, op2_addr);
7315 zend_jit_check_exception_undef_result(jit, opline);
7318 ref = zend_jit_cmp_slow(jit, ref, opline, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7322 ir_refs_add(end_inputs, ref);
7325 if (end_inputs->
count) {
7326 uint32_t
n = end_inputs->
count;
7328 if (smart_branch_opcode && !exit_addr) {
7332 target_label2 : target_label;
7334 target_label : target_label2;
7351 _zend_jit_add_predecessor_ref(jit, label, jit->
b,
ir_END());
7352 }
else if (
n == 1) {
7353 ref = end_inputs->refs[0];
7354 _zend_jit_add_predecessor_ref(jit, bb->
successors[0], jit->
b, ref);
7355 _zend_jit_add_predecessor_ref(jit, bb->
successors[1], jit->
b, ref);
7361 jit_IF_TRUE_FALSE_ex(jit, end_inputs->refs[
n], label);
7363 jit_IF_TRUE_FALSE_ex(jit, end_inputs->refs[
n], label2);
7367 _zend_jit_add_predecessor_ref(jit, label, jit->
b,
ir_END());
7369 _zend_jit_add_predecessor_ref(jit, label2, jit->
b,
ir_END());
7375 }
else if (smart_branch_opcode && !exit_addr) {
7377 _zend_jit_add_predecessor_ref(jit, target_label, jit->
b,
ir_END());
7394 uint8_t smart_branch_opcode,
7395 uint32_t target_label,
7396 uint32_t target_label2,
7397 const void *exit_addr,
7398 bool skip_comparison)
7400 bool always_false = 0, always_true = 0;
7404 ir_ref op1 = jit_ZVAL_ADDR(jit, op1_addr);
7405 op1 = zend_jit_zval_check_undef(jit,
op1, opline->
op1.
var, opline, 0);
7410 ir_ref op2 = jit_ZVAL_ADDR(jit, op2_addr);
7411 op2 = zend_jit_zval_check_undef(jit,
op2, opline->
op2.
var, opline, 0);
7416 if ((op1_info & op2_info &
MAY_BE_ANY) == 0) {
7418 }
else if (has_concrete_type(op1_info)
7419 && has_concrete_type(op2_info)
7420 && concrete_type(op1_info) == concrete_type(op2_info)
7421 && concrete_type(op1_info) <=
IS_TRUE) {
7433 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
7435 jit_FREE_OP(jit, opline->
op2_type, opline->
op2, op2_info, opline);
7436 if (!smart_branch_opcode
7442 zend_jit_check_exception(jit);
7448 }
else if (smart_branch_opcode) {
7453 target_label : target_label2;
7456 target_label2 : target_label;
7458 _zend_jit_add_predecessor_ref(jit, label, jit->
b,
ir_END());
7462 }
else if (always_false) {
7464 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
7466 jit_FREE_OP(jit, opline->
op2_type, opline->
op2, op2_info, opline);
7467 if (!smart_branch_opcode
7473 zend_jit_check_exception(jit);
7479 }
else if (smart_branch_opcode) {
7484 target_label2 : target_label;
7487 target_label : target_label2;
7489 _zend_jit_add_predecessor_ref(jit, label, jit->
b,
ir_END());
7496 ref = jit_ZVAL_ADDR(jit, op1_addr);
7497 ref = jit_ZVAL_DEREF_ref(jit, ref);
7501 ref = jit_ZVAL_ADDR(jit, op2_addr);
7502 ref = jit_ZVAL_DEREF_ref(jit, ref);
7508 ref = zend_jit_cmp_long_long(jit, opline, op1_range, op1_addr, op2_range, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr, skip_comparison);
7514 ref = zend_jit_cmp_double_double(jit, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr);
7522 if (!zend_jit_spill_store_inv(jit, op1_addr, real_addr, op1_info)) {
7525 op1_addr = real_addr;
7531 if (!zend_jit_spill_store_inv(jit, op2_addr, real_addr, op2_info)) {
7548 if (!zend_jit_spill_store_inv(jit, op1_addr, real_addr, op1_info)) {
7551 op1_addr = real_addr;
7555 if (!zend_jit_spill_store_inv(jit, op2_addr, real_addr, op2_info)) {
7558 op2_addr = real_addr;
7561 jit_SET_EX_OPLINE(jit, opline);
7565 jit_ZVAL_ADDR(jit, op1_addr),
7566 jit_ZVAL_ADDR(jit, op2_addr));
7571 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7574 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7583 zend_jit_check_exception_undef_result(jit, opline);
7591 }
else if (smart_branch_opcode) {
7594 uint32_t tmp = target_label;
7595 target_label = target_label2;
7596 target_label2 = tmp;
7598 ref = jit_IF_ex(jit, ref,
7599 (smart_branch_opcode ==
ZEND_JMPZ || smart_branch_opcode ==
ZEND_JMPZ_EX) ? target_label2 : target_label);
7603 if (smart_branch_opcode && !exit_addr) {
7616 _zend_jit_add_predecessor_ref(jit, bb->
successors[0], jit->
b, ref);
7617 _zend_jit_add_predecessor_ref(jit, bb->
successors[1], jit->
b, ref);
7625static int zend_jit_bool_jmpznz(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info,
zend_jit_addr op1_addr,
zend_jit_addr res_addr, uint32_t target_label, uint32_t target_label2,
int may_throw, uint8_t branch_opcode,
const void *exit_addr)
7627 uint32_t true_label = -1;
7628 uint32_t false_label = -1;
7630 bool set_bool_not = 0;
7631 bool always_true = 0, always_false = 0;
7640 }
else if (branch_opcode ==
ZEND_JMPZ) {
7641 true_label = target_label2;
7642 false_label = target_label;
7644 true_label = target_label;
7645 false_label = target_label2;
7648 true_label = target_label2;
7649 false_label = target_label;
7652 true_label = target_label;
7653 false_label = target_label2;
7659 ref = jit_ZVAL_ADDR(jit, op1_addr);
7660 ref = jit_ZVAL_DEREF_ref(jit, ref);
7675 ref = jit_ZVAL_ADDR(jit, op1_addr);
7676 zend_jit_zval_check_undef(jit, ref, opline->
op1.
var, opline, 0);
7684 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_FALSE :
IS_TRUE);
7686 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
7688 zend_jit_check_exception(jit);
7690 if (true_label != (uint32_t)-1) {
7692 _zend_jit_add_predecessor_ref(jit, true_label, jit->
b,
ir_END());
7696 }
else if (always_false) {
7698 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_TRUE :
IS_FALSE);
7700 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
7702 zend_jit_check_exception(jit);
7704 if (false_label != (uint32_t)-1) {
7706 _zend_jit_add_predecessor_ref(jit, false_label, jit->
b,
ir_END());
7713 type = jit_Z_TYPE(jit, op1_addr);
7720 zend_jit_type_check_undef(jit,
7726 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_TRUE :
IS_FALSE);
7734 }
else if (false_label != (uint32_t)-1) {
7751 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_FALSE :
IS_TRUE);
7759 }
else if (true_label != (uint32_t)-1) {
7776 type = jit_Z_TYPE(jit, op1_addr);
7781 ref = jit_Z_LVAL(jit, op1_addr);
7785 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7788 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7792 }
else if (exit_addr) {
7794 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7807 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_FALSE :
IS_TRUE);
7812 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_TRUE :
IS_FALSE);
7827 type = jit_Z_TYPE(jit, op1_addr);
7835 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7838 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7842 }
else if (exit_addr) {
7844 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7857 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_FALSE :
IS_TRUE);
7862 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_TRUE :
IS_FALSE);
7872 jit_SET_EX_OPLINE(jit, opline);
7876 zend_jit_check_exception_undef_result(jit, opline);
7880 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7883 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7889 }
else if (exit_addr) {
7891 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
7906 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_FALSE :
IS_TRUE);
7911 jit_set_Z_TYPE_INFO(jit, res_addr, set_bool_not ?
IS_TRUE :
IS_FALSE);
7922 _zend_jit_merge_smart_branch_inputs(jit, true_label, false_label, true_inputs, false_inputs);
7928static int zend_jit_defined(
zend_jit_ctx *jit,
const zend_op *opline, uint8_t smart_branch_opcode, uint32_t target_label, uint32_t target_label2,
const void *exit_addr)
7930 uint32_t defined_label = (uint32_t)-1;
7931 uint32_t undefined_label = (uint32_t)-1;
7934 ir_ref ref, ref2, if_set, if_zero, if_set2;
7937 if (smart_branch_opcode && !exit_addr) {
7939 defined_label = target_label2;
7940 undefined_label = target_label;
7941 }
else if (smart_branch_opcode ==
ZEND_JMPNZ) {
7942 defined_label = target_label;
7943 undefined_label = target_label2;
7954 if_set =
ir_IF(ref);
7969 }
else if (smart_branch_opcode) {
7972 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_TRUE);
7978 ref2 =
jit_EG(zend_constants);
7980 if (
sizeof(
void*) == 8) {
7993 }
else if (smart_branch_opcode) {
7996 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_FALSE);
8003 jit_SET_EX_OPLINE(jit, opline);
8012 }
else if (smart_branch_opcode) {
8019 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
8024 if (!smart_branch_opcode || exit_addr) {
8029 _zend_jit_merge_smart_branch_inputs(jit, defined_label, undefined_label, true_inputs, false_inputs);
8043 if (!zend_jit_save_call_chain(jit, -1)) {
8054 zend_jit_zval_try_addref(jit, val_addr);
8057 jit_LOAD_IP_ADDR(jit, opline - 1);
8058 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_trace_escape));
8065static int zend_jit_restore_zval(
zend_jit_ctx *jit,
int var, int8_t reg)
8081 bool op1_avoid_refcounting)
8085 const void *res_exit_addr =
NULL;
8087 ir_ref ref = jit_ZVAL_ADDR(jit, val_addr);
8088 uint32_t old_op1_info = 0;
8095 if (op1_avoid_refcounting
8112 if_type = jit_if_Z_TYPE(jit, val_addr,
type);
8120 exit_point = zend_jit_trace_get_exit_point(opline+1,
flags);
8121 res_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
8122 if (!res_exit_addr) {
8126 jit_guard_Z_TYPE(jit, val_addr,
IS_REFERENCE, res_exit_addr);
8132 exit_point = zend_jit_trace_get_exit_point(opline+1,
flags);
8133 res_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
8134 if (!res_exit_addr) {
8141 jit_guard_Z_TYPE(jit, val_addr,
type, res_exit_addr);
8146 ref =
ir_PHI_2(IR_ADDR, ref, ref1);
8169 ir_ref ref, ref2, if_set, if_special, not_set_path, special_path, fast_path;
8175 if_set =
ir_IF(ref);
8177 if (!zend_jit_is_persistent_constant(
zv, opline->
op1.
num)) {
8195 jit_SET_EX_OPLINE(jit, opline);
8199 ir_GUARD(ref2, jit_STUB_ADDR(jit, jit_stub_exception_handler));
8202 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
8205 uint8_t
type = concrete_type(res_info);
8208 const_addr = zend_jit_guard_fetch_result_type(jit, opline, const_addr,
type, 0, 0, 0);
8217 jit_ZVAL_COPY(jit, res_addr,
MAY_BE_ANY, const_addr, res_info, 1);
8218 if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr, res_info)) {
8232static int zend_jit_type_check(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info, uint8_t smart_branch_opcode, uint32_t target_label, uint32_t target_label2,
const void *exit_addr)
8237 uint32_t true_label = -1, false_label = -1;
8243 if (smart_branch_opcode && !exit_addr) {
8245 true_label = target_label2;
8246 false_label = target_label;
8247 }
else if (smart_branch_opcode ==
ZEND_JMPNZ) {
8248 true_label = target_label;
8249 false_label = target_label2;
8261 if_def = jit_if_not_Z_TYPE(jit, op1_addr,
IS_UNDEF);
8265 jit_SET_EX_OPLINE(jit, opline);
8267 zend_jit_check_exception_undef_result(jit, opline);
8275 }
else if (smart_branch_opcode) {
8278 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_TRUE);
8288 }
else if (smart_branch_opcode) {
8291 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_FALSE);
8307 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
8311 }
else if (end_inputs) {
8314 }
else if (smart_branch_opcode) {
8317 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_TRUE);
8320 }
else if (!(op1_info &
MAY_BE_GUARD) && !(op1_info & mask)) {
8321 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
8325 }
else if (end_inputs) {
8328 }
else if (smart_branch_opcode) {
8331 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_FALSE);
8362 ir_ref ref = jit_ZVAL_ADDR(jit, op1_addr);
8363 ref = jit_ZVAL_DEREF_ref(jit, ref);
8368 if (!smart_branch_opcode) {
8371 }
else if (invert) {
8377 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
8388 }
else if (smart_branch_opcode) {
8395 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
8402 if (!smart_branch_opcode || exit_addr) {
8409 _zend_jit_merge_smart_branch_inputs(jit, true_label, false_label, true_inputs, false_inputs);
8415static int zend_jit_isset_isempty_cv(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info,
zend_jit_addr op1_addr, uint8_t smart_branch_opcode, uint32_t target_label, uint32_t target_label2,
const void *exit_addr)
8418 uint32_t true_label = -1, false_label = -1;
8424 if (smart_branch_opcode && !exit_addr) {
8426 true_label = target_label2;
8427 false_label = target_label;
8428 }
else if (smart_branch_opcode ==
ZEND_JMPNZ) {
8429 true_label = target_label;
8430 false_label = target_label2;
8439 ir_ref ref = jit_ZVAL_ADDR(jit, op1_addr);
8440 ref = jit_ZVAL_DEREF_ref(jit, ref);
8447 }
else if (smart_branch_opcode) {
8450 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_TRUE);
8456 }
else if (smart_branch_opcode) {
8459 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_FALSE);
8470 }
else if (smart_branch_opcode) {
8477 jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),
8483 if (!smart_branch_opcode || exit_addr) {
8488 _zend_jit_merge_smart_branch_inputs(jit, true_label, false_label, true_inputs, false_inputs);
8503static int zend_jit_stack_check(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t used_stack)
8506 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
8538 uint32_t used_stack;
8540 bool stack_check = 1;
8546 if ((
int)used_stack <= checked_stack) {
8584 if (
sizeof(
void*) == 8) {
8587 ref =
ir_SUB_A(used_stack_ref, ref);
8590 used_stack_ref =
ir_PHI_2(IR_ADDR, ref, used_stack_ref);
8593 zend_jit_start_reuse_ip(jit);
8608 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
8616 if_enough_stack =
ir_IF(ref);
8624 jit_SET_EX_OPLINE(jit, opline);
8632 jit_SET_EX_OPLINE(jit, opline);
8634 used_stack_ref, ref);
8636 jit_STORE_IP(jit, ref);
8643 ref =
jit_EG(vm_stack_top);
8645#if !OPTIMIZE_FOR_SIZE
8699 ref =
jit_CALL(rx, This.u1.type_info);
8708 jit_GC_ADDREF(jit, this_ref);
8712 ref =
jit_CALL(rx, This.u1.type_info);
8721 }
else if (!is_closure) {
8730 jit_GC_ADDREF(jit, func_ref);
8755 object_or_called_scope =
ir_PHI_2(IR_ADDR,
object, object_or_called_scope);
8758 ref =
jit_CALL(rx, This.u1.type_info);
8793 !
func->common.function_name)) {
8823 const void *exit_addr;
8833 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
8894 }
else if (
func && op_array == &
func->op_array) {
8897 || zend_jit_prefer_const_addr_load(jit, (uintptr_t)
func)) {
8903 ir_ref if_func, cache_slot_ref, ref;
8915 if_func =
ir_IF(func_ref);
8944 int32_t exit_point = zend_jit_trace_get_exit_point(opline,
8946 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
8953 }
else if (!zend_jit_func_guard(jit, ref,
func, exit_addr)) {
8957jit_SET_EX_OPLINE(jit, opline);
8958 ir_GUARD(ref, jit_STUB_ADDR(jit, jit_stub_undefined_function));
8962 func_ref =
ir_PHI_2(IR_ADDR, ref, func_ref);
8965 if (!zend_jit_push_call_frame(jit, opline, op_array,
func, 0, 0, checked_stack, func_ref,
IR_UNUSED)) {
8969 if (zend_jit_needs_call_chain(
call_info, b, op_array, ssa, ssa_op, opline, call_level, trace)) {
8970 if (!zend_jit_save_call_chain(jit, call_level)) {
8976 delayed_call_chain = 1;
8981 && trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
8982 if (!zend_jit_set_ip(jit, opline + 1)) {
9000 bool ce_is_instanceof,
9002 bool delayed_fetch_this,
9008 bool polymorphic_side_trace)
9013 zval *function_name;
9031 if (polymorphic_side_trace) {
9035 ir_ref ref, ref2, if_found, fast_path, run_time_cache, this_ref2;
9039 this_ref = jit_Z_PTR(jit, this_addr);
9044 ir_ref ref = jit_ZVAL_ADDR(jit, op1_addr);
9045 ref = jit_ZVAL_DEREF_ref(jit, ref);
9063 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
9075 jit_SET_EX_OPLINE(jit, opline);
9078 jit_ZVAL_ADDR(jit, op1_addr));
9081 jit_ZVAL_ADDR(jit, op1_addr));
9083 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
9088 this_ref = jit_Z_PTR(jit, op1_addr);
9101 if_found =
ir_IF(ref);
9110 if_found =
ir_IF(ref);
9120 jit_SET_EX_OPLINE(jit, opline);
9159 ir_GUARD(ref2, jit_STUB_ADDR(jit, jit_stub_exception_handler));
9162 func_ref =
ir_PHI_2(IR_ADDR, ref2, ref);
9163 this_ref =
ir_PHI_2(IR_ADDR, this_ref2, this_ref);
9166 if ((!
func || zend_jit_may_be_modified(
func, op_array))
9171 const void *exit_addr;
9174 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
9184 if (!zend_jit_func_guard(jit, func_ref,
func, exit_addr)) {
9213 ir_GUARD(
ret, jit_STUB_ADDR(jit, jit_stub_exception_handler));
9215 jit_STORE_IP(jit,
ret);
9224 if (!zend_jit_push_call_frame(jit, opline,
NULL,
func, 0, delayed_fetch_this, checked_stack, func_ref, this_ref)) {
9232 zend_jit_start_reuse_ip(jit);
9234 if (zend_jit_needs_call_chain(
call_info, b, op_array, ssa, ssa_op, opline, call_level, trace)) {
9235 if (!zend_jit_save_call_chain(jit, call_level)) {
9240 delayed_call_chain = 1;
9246 && trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
9247 if (!zend_jit_set_ip(jit, opline + 1)) {
9255static int zend_jit_init_closure_call(
zend_jit_ctx *jit,
9269 ref = jit_Z_PTR(jit, op2_addr);
9274 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
9299 const void *exit_addr;
9302 opcodes =
func->op_array.opcodes;
9304 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
9322 if (!zend_jit_push_call_frame(jit, opline,
NULL,
func, 1, 0, checked_stack, ref,
IR_UNUSED)) {
9326 if (zend_jit_needs_call_chain(
NULL, b, op_array, ssa, ssa_op, opline, call_level, trace)) {
9327 if (!zend_jit_save_call_chain(jit, call_level)) {
9332 delayed_call_chain = 1;
9338 && trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
9339 if (!zend_jit_set_ip(jit, opline + 1)) {
9354 if (!zend_jit_reuse_ip(jit)) {
9364 &&
JIT_G(current_frame)
9378 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
9386 if_pass_by_ref =
ir_IF(cond);
9394 jit_SET_EX_OPLINE(jit, opline);
9395 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_throw_cannot_pass_by_ref));
9407 jit_ZVAL_COPY_CONST(jit,
9415 op1_addr, op1_info, 0);
9429 if (!zend_jit_reuse_ip(jit)) {
9435 op1_addr = jit_ZVAL_INDIRECT_DEREF(jit, op1_addr);
9444 jit_set_Z_TYPE_INFO(jit,op1_addr,
IS_NULL);
9464 ref = jit_Z_PTR(jit, op1_addr);
9466 jit_GC_ADDREF(jit, ref);
9468 jit_set_Z_PTR(jit, arg_addr, ref);
9476 ref = jit_EMALLOC(jit,
sizeof(
zend_reference), op_array, opline);
9478 jit_set_GC_REFCOUNT(jit, ref, 2);
9489 op1_addr, op1_info, 0);
9492 jit_set_Z_PTR(jit, op1_addr, ref);
9496 jit_set_Z_PTR(jit, arg_addr, ref);
9504 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
9521 if (!zend_jit_reuse_ip(jit)) {
9527 &&
JIT_G(current_frame)
9531 if (!zend_jit_send_ref(jit, opline, op_array, op1_info, 0)) {
9545 if (!zend_jit_send_ref(jit, opline, op_array, op1_info, 1)) {
9554 &&
JIT_G(current_frame)
9563 op1_addr, op1_info, 0);
9571 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
9600 op1_addr, op1_info, 0);
9619 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
9625 jit_SET_EX_OPLINE(jit, opline);
9627 jit_ZVAL_ADDR(jit, arg_addr));
9628 zend_jit_check_exception(jit);
9636 &&
JIT_G(current_frame)
9640 if (!zend_jit_send_ref(jit, opline, op_array, op1_info, 0)) {
9652 if (!zend_jit_send_ref(jit, opline, op_array, op1_info, 1)) {
9665 if_def = jit_if_not_Z_TYPE(jit, op1_addr,
IS_UNDEF);
9670 jit_SET_EX_OPLINE(jit, opline);
9675 jit_set_Z_TYPE_INFO(jit, arg_addr,
IS_NULL);
9678 ir_GUARD(ref, jit_STUB_ADDR(jit, jit_stub_exception_handler));
9697 op1_addr, op1_info, 0);
9707 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
9713 jit_SET_EX_OPLINE(jit, opline);
9715 jit_ZVAL_ADDR(jit, arg_addr));
9716 zend_jit_check_exception(jit);
9724 ref = jit_ZVAL_ADDR(jit, op1_addr);
9725 ref = jit_ZVAL_DEREF_ref(jit, ref);
9732 op1_addr, op1_info, 1);
9734 ir_ref if_ref, ref, ref2, refcount, if_not_zero, if_refcounted;
9742 ref = jit_Z_PTR(jit, op1_addr);
9750 ref_addr, op1_info, 0);
9753 refcount = jit_GC_DELREF(jit, ref);
9754 if_not_zero =
ir_IF(refcount);
9758 if_refcounted = jit_if_REFCOUNTED(jit, arg_addr);
9761 jit_GC_ADDREF(jit, jit_Z_PTR(jit, arg_addr));
9778 op1_addr, op1_info, 0);
9781 if (op1_addr != op1_def_addr) {
9782 if (!zend_jit_update_regs(jit, opline->
op1.
var, op1_addr, op1_def_addr, op1_info)) {
9786 op1_addr = op1_def_addr;
9812 &&
JIT_G(current_frame)
9824 ref =
jit_CALL(ref, This.u1.type_info);
9836 ref =
jit_CALL(ref, This.u1.type_info);
9843 ir_ref rx, if_ref, cold_path;
9845 if (!zend_jit_reuse_ip(jit)) {
9854 if_ref =
ir_IF(ref);
9858 ref =
jit_CALL(rx, This.u1.type_info);
9865 ref =
jit_CALL(rx, This.u1.type_info);
9889 jit_SET_EX_OPLINE(jit, opline);
9903 uint32_t call_num_args = 0;
9904 bool unknown_num_args = 0;
9905 const void *exit_addr =
NULL;
9909 prev_opline = opline - 1;
9915 unknown_num_args = 1;
9927 && (!
JIT_G(current_frame)
9929 || !
JIT_G(current_frame)->
call->func)) {
9945 if (trace && !
func) {
9951 if (
JIT_G(current_frame) &&
9956 unknown_num_args = 1;
9963 if (
JIT_G(current_frame) &&
9968 unknown_num_args = 1;
9974 bool may_have_extra_named_params =
9979 zend_jit_start_reuse_ip(jit);
9984 zend_jit_stop_reuse_ip(jit);
9986 jit_SET_EX_OPLINE(jit, opline);
9993 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
10013 delayed_call_chain = 0;
10035 if (GCC_GLOBAL_REGS) {
10040 ir_GUARD(
ret, jit_STUB_ADDR(jit, jit_stub_exception_handler));
10046 if (GCC_GLOBAL_REGS) {
10051 ir_GUARD(
ret, jit_STUB_ADDR(jit, jit_stub_exception_handler));
10065 bool recursive_call_through_jmp = 0;
10078 if (!
func ||
func->op_array.cache_size) {
10081 if (
func && op_array == &
func->op_array) {
10090 (
JIT_G(current_frame) &&
10098 ir_ref if_odd, run_time_cache2;
10108 run_time_cache =
ir_PHI_2(IR_ADDR, run_time_cache2, run_time_cache);
10116 jit_STORE_FP(jit, rx);
10119 if (
func && !unknown_num_args) {
10121 for (i = call_num_args; i <
func->op_array.last_var; i++) {
10128 if (call_num_args <= func->op_array.
num_args) {
10130 && trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER)) {
10143 jit_LOAD_IP_ADDR(jit,
func->op_array.opcodes +
num_args);
10152 jit_LOAD_IP(jit, ip);
10157 recursive_call_through_jmp = 1;
10163 && trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER)) {
10174 jit_LOAD_IP(jit, ip);
10179 if (GCC_GLOBAL_REGS) {
10198 jit_LOAD_IP(jit, ip);
10215 if (GCC_GLOBAL_REGS) {
10236 if (
sizeof(
void*) == 8) {
10240 if (GCC_GLOBAL_REGS) {
10241 jit_STORE_IP(jit,
ir_ADD_A(jit_IP(jit), ref));
10267 if (
sizeof(
void*) == 8) {
10289 ir_ref observer_handler;
10290 ir_ref rx = jit_FP(jit);
10292 if (trace && (trace->op !=
ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) {
10294 jit_SET_EX_OPLINE(jit, trace[1].opline);
10295 }
else if (GCC_GLOBAL_REGS) {
10299 jit_observer_fcall_begin(jit, rx, observer_handler);
10304 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
10312 zend_jit_check_timeout(jit,
NULL , exit_addr);
10314 jit_observer_fcall_is_unobserved_end(jit, &unobserved_data);
10325 if (recursive_call_through_jmp) {
10333 if (insn->op == IR_BEGIN) {
10336 insn->op = IR_LOOP_BEGIN;
10337 insn->inputs_count = 2;
10340 }
else if ((insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN)
10341 && insn->inputs_count == 2) {
10344 insn->op = IR_LOOP_BEGIN;
10345 insn->inputs_count = 3;
10348 }
else if (insn->op == IR_LOOP_BEGIN && insn->inputs_count == 3) {
10359 if (GCC_GLOBAL_REGS) {
10377 || jit->
ctx.
ir_base[ref].op == IR_LOOP_END);
10381 _zend_jit_add_predecessor_ref(jit, succ, jit->
b, ref);
10400 if (may_have_observer) {
10401 ir_ref observer_handler;
10403 jit_observer_fcall_begin(jit, rx, observer_handler);
10404 jit_observer_fcall_is_unobserved_end(jit, &unobserved_data);
10429 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
10431 zend_jit_reset_last_valid_opline(jit);
10434 ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
10442#if defined(IR_TARGET_X86)
10449 if (may_have_observer) {
10450 jit_observer_fcall_end(jit, rx, res_ref);
10470 if (
func && !unknown_num_args) {
10471 for (i = 0; i < call_num_args; i++ ) {
10483 if (may_have_extra_named_params) {
10514 !
JIT_G(current_frame) ||
10530 allocated_path =
ir_END();
10536 if (allocated_path) {
10542 bool ce_is_instanceof;
10563 jit_ZVAL_PTR_DTOR(jit, res_addr, func_info, 1, opline);
10567 ir_AFREE(ir_CONST_ADDR(sizeof(zval)));
10573 jit_STUB_ADDR(jit, jit_stub_icall_throw));
10583 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
10591 zend_jit_check_timeout(jit, opline + 1, exit_addr);
10595 jit_LOAD_IP_ADDR(jit, opline + 1);
10598 && trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
10599 jit_LOAD_IP_ADDR(jit, opline + 1);
10612 ir_ref if_skip_constructor = jit_IF_ex(jit, jit_CMP_IP(jit, IR_NE, opline), next_block);
10617 if (!zend_jit_tail_handler(jit, opline)) {
10621 if (!zend_jit_do_fcall(jit, opline, op_array, ssa, call_level, next_block,
NULL)) {
10651 ref = jit_ZVAL_ADDR(jit, res_addr);
10653 &&
JIT_G(current_frame)
10665 ref = jit_ZVAL_DEREF_ref(jit, ref);
10667 ref = jit_Z_PTR_ref(jit, ref);
10672 if (type_mask != 0) {
10673 if (is_power_of_two(type_mask)) {
10674 uint32_t type_code = concrete_type(type_mask);
10689 jit_SET_EX_OPLINE(jit, opline);
10693 if (check_exception) {
10694 ir_GUARD(ref, jit_STUB_ADDR(jit, jit_stub_exception_handler));
10720 if (arg_info || (opline+1)->opcode !=
ZEND_RECV) {
10722 if (!
JIT_G(current_frame) ||
10726 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
10738 jit_SET_EX_OPLINE(jit, opline);
10740 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
10746 if (!zend_jit_verify_arg_type(jit, opline, arg_info, 1)) {
10762 &&
JIT_G(current_frame)
10765 jit_ZVAL_COPY_CONST(jit,
10778 jit_ZVAL_COPY_CONST(jit,
10785 jit_SET_EX_OPLINE(jit, opline);
10787 jit_ZVAL_ADDR(jit, res_addr),
10790 if_fail =
ir_IF(ref);
10793 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
10815 if (!zend_jit_verify_arg_type(jit, opline, arg_info, may_throw)) {
10829 bool needs_slow_check = 1;
10833 if (type_mask != 0) {
10834 if (((op1_info &
MAY_BE_ANY) & type_mask) == 0) {
10836 }
else if (((op1_info &
MAY_BE_ANY) | type_mask) == type_mask) {
10837 needs_slow_check = 0;
10838 }
else if (is_power_of_two(type_mask)) {
10839 uint32_t type_code = concrete_type(type_mask);
10840 ir_ref if_ok = jit_if_Z_TYPE(jit, op1_addr, type_code);
10855 if (needs_slow_check) {
10858 jit_SET_EX_OPLINE(jit, opline);
10859 ref = jit_ZVAL_ADDR(jit, op1_addr);
10861 ref = zend_jit_zval_check_undef(jit, ref, opline->
op1.
var,
NULL, 1);
10870 zend_jit_check_exception(jit);
10897static int zend_jit_free_cv(
zend_jit_ctx *jit, uint32_t info, uint32_t var)
10902 jit_ZVAL_PTR_DTOR(jit, var_addr, info, 1,
NULL);
10907static int zend_jit_free_op(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t info, uint32_t var_offset)
10922 int indirect_var_access,
10925 bool may_be_top_frame =
10927 !
JIT_G(current_frame) ||
10929 bool may_need_call_helper =
10930 indirect_var_access ||
10932 may_be_top_frame ||
10935 !
JIT_G(current_frame) ||
10938 bool may_need_release_this =
10943 !
JIT_G(current_frame) ||
10947 if (may_need_call_helper) {
10950 if (!zend_jit_leave_frame(jit)) {
10962 if (!GCC_GLOBAL_REGS) {
10968 if (may_be_top_frame) {
10976 }
else if (GCC_GLOBAL_REGS) {
10977 ir_GUARD(jit_IP(jit), jit_STUB_ADDR(jit, jit_stub_trace_halt));
10983 if (!GCC_GLOBAL_REGS) {
10990 ir_GUARD_NOT(ref, jit_STUB_ADDR(jit, jit_stub_leave_function_handler));
10997 if (!zend_jit_leave_frame(jit)) {
11003 }
else if (may_need_release_this) {
11008 if (!zend_jit_leave_frame(jit)) {
11045 zend_jit_reset_last_valid_opline(jit);
11047 if (GCC_GLOBAL_REGS) {
11075 const zend_op *next_opline = trace->opline;
11088 next_opline = trace->opline;
11092 && trace->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
11095 ir_ref if_eq =
ir_IF(jit_CMP_IP(jit, IR_EQ, next_opline));
11103#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE
11106 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_trace_escape));
11109 ir_GUARD(jit_CMP_IP(jit, IR_EQ, next_opline), jit_STUB_ADDR(jit, jit_stub_trace_escape));
11112 zend_jit_set_last_valid_opline(jit, trace->opline);
11115 }
else if (may_throw ||
11129 if (GCC_GLOBAL_REGS) {
11139 if (GCC_GLOBAL_REGS) {
11159 int8_t return_value_used = -1;
11167 if (
JIT_G(current_frame)) {
11169 return_value_used = 1;
11171 return_value_used = 0;
11173 return_value_used = -1;
11182 if (!zend_jit_spill_store_inv(jit, op1_addr, dst, op1_info)) {
11187 jit_observer_fcall_end(jit, jit_FP(jit), jit_ZVAL_ADDR(jit, op1_addr));
11195 if (return_value_used == -1) {
11199 if (return_value_used != 1) {
11201 ir_ref if_refcounted = jit_if_REFCOUNTED(jit, op1_addr);
11206 ref = jit_Z_PTR(jit, op1_addr);
11207 refcount = jit_GC_DELREF(jit, ref);
11209 if (RC_MAY_BE_1(op1_info)) {
11210 if (RC_MAY_BE_N(op1_info)) {
11216 jit_ZVAL_DTOR(jit, ref, op1_info, opline);
11218 if (return_value_used == -1) {
11222 }
else if (return_value_used == -1) {
11228 if (if_return_value_used) {
11232 if (return_value_used == 0) {
11247 jit_ZVAL_COPY(jit, ret_addr,
MAY_BE_ANY, op1_addr, op1_info, 0);
11250 ref = jit_ZVAL_ADDR(jit, op1_addr);
11251 ref = jit_ZVAL_DEREF_ref(jit, ref);
11259 jit_ZVAL_COPY(jit, ret_addr,
MAY_BE_ANY, op1_addr, op1_info, 1);
11260 }
else if (return_value_used != 1) {
11261 jit_ZVAL_COPY(jit, ret_addr,
MAY_BE_ANY, op1_addr, op1_info, 0);
11263 jit_set_Z_TYPE_INFO(jit, op1_addr,
IS_NULL);
11265 jit_ZVAL_COPY(jit, ret_addr,
MAY_BE_ANY, op1_addr, op1_info, 0);
11268 jit_ZVAL_COPY(jit, ret_addr,
MAY_BE_ANY, op1_addr, op1_info, 0);
11272 ir_ref if_ref, ref2, if_non_zero;
11279 ref = jit_Z_PTR(jit, op1_addr);
11284 jit_ZVAL_COPY(jit, ret_addr,
MAY_BE_ANY, ref_addr, op1_info, 0);
11285 ref2 = jit_GC_DELREF(jit, ref);
11286 if_non_zero =
ir_IF(ref2);
11290 ir_ref if_refcounted = jit_if_REFCOUNTED(jit, ret_addr);
11296 ref2 = jit_Z_PTR(jit, ret_addr);
11297 jit_GC_ADDREF(jit, ref2);
11307 jit_ZVAL_COPY(jit, ret_addr,
MAY_BE_ANY, op1_addr, op1_info, 0);
11324static int zend_jit_bind_global(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info)
11328 ir_ref cache_slot_ref, idx_ref, num_used_ref, bucket_ref, ref, ref2;
11329 ir_ref if_fit, if_reference, if_same_key, fast_path;
11339 if (
sizeof(
void*) == 8) {
11340 num_used_ref =
ir_ZEXT_A(num_used_ref);
11361 ref = jit_Z_PTR_ref(jit, bucket_ref);
11362 jit_GC_ADDREF(jit, ref);
11372 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
11375 ir_ref if_refcounted =
IR_UNUSED, refcount, if_non_zero, if_may_not_leak;
11379 if_refcounted = jit_if_REFCOUNTED(jit, op1_addr);
11384 ref2 = jit_Z_PTR(jit, op1_addr);
11387 jit_set_Z_PTR(jit, op1_addr, ref);
11391 refcount = jit_GC_DELREF(jit, ref2);
11392 if_non_zero =
ir_IF(refcount);
11399 jit_ZVAL_DTOR(jit, ref2, op1_info, opline);
11405 if_may_not_leak = jit_if_GC_MAY_NOT_LEAK(jit, ref2);
11410 jit_SET_EX_OPLINE(jit, opline);
11422 jit_set_Z_PTR(jit, op1_addr, ref);
11434static int zend_jit_free(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info,
int may_throw)
11440 jit_SET_EX_OPLINE(jit, opline);
11446 if_array = jit_if_Z_TYPE(jit, op1_addr,
IS_ARRAY);
11463 jit_ZVAL_PTR_DTOR(jit, op1_addr, op1_info, 0, opline);
11466 zend_jit_check_exception(jit);
11486 jit_SET_EX_OPLINE(jit, opline);
11490 zend_jit_check_exception(jit);
11498 jit_SET_EX_OPLINE(jit, opline);
11500 ref = jit_Z_PTR(jit, op1_addr);
11506 jit_ZVAL_PTR_DTOR(jit, op1_addr, op1_info, 0, opline);
11509 zend_jit_check_exception(jit);
11526 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
11527 }
else if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr,
MAY_BE_LONG)) {
11535 ref = jit_Z_PTR(jit, op1_addr);
11537 jit_set_Z_LVAL(jit, res_addr, ref);
11544 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
11546 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
11563 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
11564 }
else if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr,
MAY_BE_LONG)) {
11573 ref = jit_Z_PTR(jit, op1_addr);
11574 if (
sizeof(
void*) == 8) {
11580 jit_set_Z_LVAL(jit, res_addr, ref);
11587 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
11589 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
11593 zend_jit_check_exception(jit);
11598static int zend_jit_in_array(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info,
zend_jit_addr op1_addr, uint8_t smart_branch_opcode, uint32_t target_label, uint32_t target_label2,
const void *exit_addr)
11611 jit_Z_PTR(jit, op1_addr));
11620 if (smart_branch_opcode ==
ZEND_JMPZ) {
11625 }
else if (smart_branch_opcode) {
11631 ref = jit_IF_ex(jit, ref,
11632 (smart_branch_opcode ==
ZEND_JMPZ) ? target_label2 : target_label);
11633 _zend_jit_add_predecessor_ref(jit, bb->
successors[0], jit->
b, ref);
11634 _zend_jit_add_predecessor_ref(jit, bb->
successors[1], jit->
b, ref);
11637 jit_set_Z_TYPE_INFO_ex(jit, res_addr,
11653 zval *zv = RT_CONSTANT(opline, opline->op2);
11656 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
11659 ir_STORE(ir_ADD_OFFSET(jit_FP(jit), offset), ir_CONST_ADDR(str));
11661 zend_jit_addr op2_addr = OP2_ADDR();
11664 ZEND_ASSERT((op2_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_STRING);
11666 ref = jit_Z_PTR(jit, op2_addr);
11667 ir_STORE(ir_ADD_OFFSET(jit_FP(jit), offset), ref);
11668 if (opline->op2_type == IS_CV) {
11669 ir_ref if_refcounted, long_path;
11671 if_refcounted = jit_if_REFCOUNTED(jit, op2_addr);
11672 ir_IF_TRUE(if_refcounted);
11673 jit_GC_ADDREF(jit, ref);
11674 long_path = ir_END();
11676 ir_IF_FALSE(if_refcounted);
11677 ir_MERGE_WITH(long_path);
11682 zend_jit_addr res_addr = RES_ADDR();
11685 ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_rope_end),
11686 ir_ADD_OFFSET(jit_FP(jit), opline->op1.var),
11687 ir_CONST_U32(opline->extended_value));
11689 jit_set_Z_PTR(jit, res_addr, ref);
11690 jit_set_Z_TYPE_INFO(jit, res_addr, IS_STRING_EX);
11703 val = jit_ZVAL_ADDR(jit, val_addr);
11711 val = jit_ZVAL_ADDR(jit, val_addr);
11726#if SIZEOF_ZEND_LONG == 4
11727 ir_ref val = jit_ZVAL_ADDR(jit, val_addr);
11734#if SIZEOF_ZEND_LONG == 4
11739 ptr = jit_Z_PTR(jit, val_addr);
11744 ir_refs_add(merge_inputs,
ir_END());
11746 ir_refs_add(ptrs,
ptr);
11747#if SIZEOF_ZEND_LONG == 4
11748 ir_refs_add(values,
val);
11760 type2 = jit_Z_TYPE_INFO_ref(jit, val2);
11761 ptr2 = jit_Z_PTR_ref(jit, val2);
11766 ir_refs_add(merge_inputs,
ir_END());
11768 ir_refs_add(ptrs,
ptr2);
11769#if SIZEOF_ZEND_LONG == 4
11770 ir_refs_add(values, val2);
11777#if SIZEOF_ZEND_LONG == 4
11782 jit_GC_ADDREF(jit,
ptr);
11783 ir_refs_add(merge_inputs,
ir_END());
11785 ir_refs_add(ptrs,
ptr);
11786#if SIZEOF_ZEND_LONG == 4
11787 ir_refs_add(values,
val);
11793#if SIZEOF_ZEND_LONG == 4
11799 jit_set_Z_PTR(jit, res_addr,
ptr);
11800#if SIZEOF_ZEND_LONG == 4
11801 jit_set_Z_W2(jit, res_addr, jit_Z_W2(jit, val_addr));
11803 jit_set_Z_TYPE_INFO_ex(jit, res_addr,
type);
11808static int zend_jit_fetch_dimension_address_inner(
zend_jit_ctx *jit,
11816 const void *found_exit_addr,
11817 const void *not_found_exit_addr,
11818 const void *exit_addr,
11819 bool result_type_guard,
11824 ir_ref *not_found_inputs)
11829 ir_refs *test_zval_inputs, *test_zval_values;
11838 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
11845 bool op2_loaded = 0;
11846 bool packed_loaded = 0;
11847 bool bad_packed_key = 0;
11854 if_type = jit_if_Z_TYPE(jit, op2_addr,
IS_LONG);
11859 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
11875 h = jit_Z_LVAL(jit, op2_addr);
11883 if (
val >= 0 &&
val < HT_MAX_SIZE) {
11886 bad_packed_key = 1;
11892 h = jit_Z_LVAL(jit, op2_addr);
11903 if (packed_loaded) {
11914#if SIZEOF_ZEND_LONG == 8
11925 if (
type == BP_JIT_IS) {
11926 if (not_found_exit_addr) {
11955 if (
type == BP_JIT_IS) {
11956 ir_refs_add(test_zval_values, ref);
11957 ir_refs_add(test_zval_inputs,
ir_END());
11970 h = jit_Z_LVAL(jit, op2_addr);
11973 if (packed_loaded) {
11978 if (not_found_exit_addr) {
11981 if_found =
ir_IF(ref);
11986 ir_refs_add(test_zval_values, ref);
11987 ir_refs_add(test_zval_inputs,
ir_END());
11988 }
else if (!not_found_exit_addr && !packed_loaded) {
11995 if (packed_loaded) {
11996 ir_ref type_ref = jit_Z_TYPE_ref(jit, ref);
11998 if (result_type_guard) {
12010 ir_refs_add(found_inputs,
ir_END());
12011 ir_refs_add(found_vals, ref);
12020 h = jit_Z_LVAL(jit, op2_addr);
12023 if (packed_loaded) {
12033 if_found =
ir_IF(ref);
12038 if_found =
ir_IF(ref);
12043 ir_refs_add(found_inputs,
ir_END());
12044 ir_refs_add(found_vals, ref);
12045 }
else if (!packed_loaded) {
12057 if (idx_not_found_inputs) {
12064 jit_SET_EX_OPLINE(jit, opline);
12068 h = jit_Z_LVAL(jit, op2_addr);
12070 if (GCC_GLOBAL_REGS) {
12082 if (!not_found_exit_addr) {
12084 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
12094 if (packed_loaded) {
12095 if (not_found_exit_addr) {
12096 ir_refs_add(found_inputs,
ir_END());
12097 ir_refs_add(found_vals, ref);
12101 ir_refs_add(found_inputs,
ir_END());
12102 ir_refs_add(found_vals, ref);
12107 if (!packed_loaded ||
12108 !not_found_exit_addr ||
12114 }
else if (!packed_loaded) {
12121 h = jit_Z_LVAL(jit, op2_addr);
12123 if (packed_loaded) {
12129 if (not_found_exit_addr) {
12132 if_found =
ir_IF(ref);
12137 ir_refs_add(found_inputs,
ir_END());
12138 ir_refs_add(found_vals, ref);
12142 if (packed_loaded) {
12145 ir_refs_add(found_inputs,
ir_END());
12146 ir_refs_add(found_vals, ref);
12155 }
else if (!packed_loaded) {
12161 h = jit_Z_LVAL(jit, op2_addr);
12164 ir_refs_add(found_inputs,
ir_END());
12165 ir_refs_add(found_vals, ref);
12183 if_type = jit_if_Z_TYPE(jit, op2_addr,
IS_STRING);
12188 key = jit_Z_PTR(jit, op2_addr);
12194 ir_ref if_num, end1, ref2;
12206 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
12210 if (not_found_exit_addr) {
12213 if_found =
ir_IF(ref);
12218 ir_refs_add(test_zval_values, ref);
12219 ir_refs_add(test_zval_inputs,
ir_END());
12225 ir_ref if_num, end1, ref2;
12237 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
12246 if_found =
ir_IF(ref);
12251 if_found =
ir_IF(ref);
12256 jit_SET_EX_OPLINE(jit, opline);
12264 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
12272 ir_refs_add(found_inputs,
ir_END());
12273 ir_refs_add(found_vals, ref);
12281 if (not_found_exit_addr) {
12284 if_found =
ir_IF(ref);
12289 ir_refs_add(found_inputs,
ir_END());
12290 ir_refs_add(found_vals, ref);
12298 ir_refs_add(found_inputs,
ir_END());
12299 ir_refs_add(found_vals, ref);
12312 jit_SET_EX_OPLINE(jit, opline);
12314 ref = jit_ZVAL_ADDR(jit, op2_addr);
12320 jit_ZVAL_ADDR(jit, res_addr));
12325 if (not_found_exit_addr) {
12327 ir_refs_add(found_inputs,
ir_END());
12328 }
else if (found_exit_addr) {
12332 if_found =
ir_IF(ref);
12334 ir_refs_add(found_inputs,
ir_END());
12344 jit_ZVAL_ADDR(jit, res_addr));
12349 if_found =
ir_IF(ref);
12351 ir_refs_add(found_inputs,
ir_END());
12352 ir_refs_add(found_vals, ref);
12358 if_found =
ir_IF(ref);
12360 ir_refs_add(found_inputs,
ir_END());
12361 ir_refs_add(found_vals, ref);
12370 if (
type == BP_JIT_IS
12374 }
else if (
type == BP_JIT_IS
12377 && test_zval_inputs->
count) {
12380 ref =
ir_PHI_N(IR_ADDR, test_zval_values->
count, test_zval_values->refs);
12383 ref = jit_ZVAL_DEREF_ref(jit, ref);
12386 if (not_found_exit_addr) {
12388 ir_refs_add(found_inputs,
ir_END());
12389 }
else if (found_exit_addr) {
12397 ir_refs_add(found_inputs,
ir_END());
12410 bool op1_avoid_refcounting,
12419 const void *exit_addr =
NULL;
12420 const void *not_found_exit_addr =
NULL;
12421 bool result_type_guard = 0;
12422 bool result_avoid_refcounting = 0;
12433 && !has_concrete_type(op1_info)) {
12435 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
12442 &&
JIT_G(current_frame)
12446 result_type_guard = 1;
12454 || op1_avoid_refcounting)
12456 && (ssa_op+1)->op1_use == ssa_op->
result_def
12458 && zend_jit_may_avoid_refcounting(opline+1, res_info)) {
12459 result_avoid_refcounting = 1;
12465 uint32_t
flags = 0;
12466 uint32_t old_op1_info = 0;
12469 int32_t exit_point;
12472 && !op1_avoid_refcounting) {
12480 if (op1_avoid_refcounting) {
12488 exit_point = zend_jit_trace_get_exit_point(opline+1,
flags);
12490 not_found_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
12491 if (!not_found_exit_addr) {
12495 if (op1_avoid_refcounting) {
12502 ir_ref ref = jit_ZVAL_ADDR(jit, op1_addr);
12503 ref = jit_ZVAL_DEREF_ref(jit, ref);
12510 ir_refs *found_inputs, *found_vals;
12516 if (exit_addr && !(op1_info & (
MAY_BE_OBJECT|may_be_string))) {
12517 jit_guard_Z_TYPE(jit, op1_addr,
IS_ARRAY, exit_addr);
12519 if_type = jit_if_Z_TYPE(jit, op1_addr,
IS_ARRAY);
12524 ht_ref = jit_Z_PTR(jit, op1_addr);
12531 if (!zend_jit_fetch_dimension_address_inner(jit, opline,
12533 op1_info, op2_info, op2_addr, op2_range, dim_type,
NULL, not_found_exit_addr, exit_addr,
12534 result_type_guard, ht_ref, found_inputs, found_vals,
12535 &end_inputs, ¬_found_inputs)) {
12539 if (found_inputs->
count) {
12541 ref =
ir_PHI_N(IR_ADDR, found_vals->
count, found_vals->refs);
12544 if (result_type_guard) {
12545 uint8_t
type = concrete_type(res_info);
12546 uint32_t
flags = 0;
12550 && !op1_avoid_refcounting) {
12558 val_addr = zend_jit_guard_fetch_result_type(jit, opline, val_addr,
type,
12564 if (not_found_inputs) {
12570 jit_ZVAL_COPY(jit, res_addr, -1, val_addr, res_info, !result_avoid_refcounting);
12572 }
else if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr, res_info)) {
12577 ir_ref type_info = jit_Z_TYPE_INFO(jit, val_addr);
12578 if (!zend_jit_zval_copy_deref(jit, res_addr, val_addr, type_info)) {
12583 jit_ZVAL_COPY(jit, res_addr, -1, val_addr, res_info, 1);
12587 }
else if (not_found_inputs) {
12589 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
12591 }
else if (!end_inputs && jit->
ctx.
control) {
12608 jit_guard_Z_TYPE(jit, op1_addr,
IS_STRING, exit_addr);
12610 if_type = jit_if_Z_TYPE(jit, op1_addr,
IS_STRING);
12614 jit_SET_EX_OPLINE(jit, opline);
12615 str_ref = jit_Z_PTR(jit, op1_addr);
12621 str_ref, jit_Z_LVAL(jit, op2_addr));
12624 str_ref, jit_ZVAL_ADDR(jit, op2_addr));
12626 jit_set_Z_PTR(jit, res_addr, ref);
12627 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_STRING);
12631 jit_ZVAL_ADDR(jit, op2_addr),
12632 jit_ZVAL_ADDR(jit, res_addr));
12648 jit_guard_Z_TYPE(jit, op1_addr,
IS_OBJECT, exit_addr);
12650 if_type = jit_if_Z_TYPE(jit, op1_addr,
IS_OBJECT);
12655 jit_SET_EX_OPLINE(jit, opline);
12660 arg2 = jit_ZVAL_ADDR(jit, op2_addr);
12665 jit_ZVAL_ADDR(jit, op1_addr),
12667 jit_ZVAL_ADDR(jit, res_addr));
12670 jit_ZVAL_ADDR(jit, op1_addr),
12672 jit_ZVAL_ADDR(jit, res_addr));
12687 jit_SET_EX_OPLINE(jit, opline);
12690 zend_jit_type_check_undef(jit, jit_Z_TYPE(jit, op1_addr), opline->
op1.
var,
NULL, 0, 1, 0);
12695 zend_jit_type_check_undef(jit, jit_Z_TYPE(jit, op2_addr), opline->
op2.
var,
NULL, 0, 1, 0);
12704 ref = jit_ZVAL_ADDR(jit, orig_op1_addr);
12706 jit_SET_EX_OPLINE(jit, opline);
12707 ref = jit_ZVAL_ADDR(jit, op1_addr);
12712 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
12720#ifdef ZEND_JIT_USE_RC_INFERENCE
12731 jit_FREE_OP(jit, opline->
op2_type, opline->
op2, op2_info, opline);
12738 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
12743 zend_jit_check_exception(jit);
12767 ref = jit_ZVAL_ADDR(jit, op1_addr);
12769 ir_ref if_reference, if_array, end1, ref2;
12772 if_reference = jit_if_Z_TYPE(jit, op1_addr,
IS_REFERENCE);
12779 array_reference_end =
ir_END();
12782 jit_SET_EX_OPLINE(jit, opline);
12785 ir_GUARD(ref2, jit_STUB_ADDR(jit, jit_stub_exception_handler_undef));
12788 ref =
ir_PHI_2(IR_ADDR, ref2, ref);
12796 *if_type = jit_if_Z_TYPE(jit, op1_addr,
IS_ARRAY);
12799 if (array_reference_end) {
12801 op1_ref =
ir_PHI_2(IR_ADDR, ref, array_reference_ref);
12804 ref = jit_Z_PTR_ref(jit, op1_ref);
12805 if (RC_MAY_BE_N(op1_info)) {
12806 if (RC_MAY_BE_1(op1_info)) {
12809 ir_refs_add(array_inputs,
ir_END());
12816 ir_refs_add(array_inputs,
ir_END());
12836 ir_ref if_def =
ir_IF(jit_Z_TYPE(jit, op1_addr));
12849 jit_ZVAL_ADDR(jit, op1_addr));
12850 if (array_inputs->
count) {
12851 ir_refs_add(array_inputs,
ir_END());
12856 if (array_inputs->
count) {
12880 jit_SET_EX_OPLINE(jit, opline);
12883 op1_addr = zend_jit_prepare_array_update(jit, opline, op1_info, op1_addr, &if_type, &ht_ref, &may_throw);
12886 ir_refs *found_inputs, *found_vals;
12897 ht_ref,
jit_EG(uninitialized_zval));
12900 if_ok =
ir_IF(ref);
12903 jit_SET_EX_OPLINE(jit, opline);
12909 jit_set_Z_PTR(jit, res_addr, ref);
12916 switch (opline->
opcode) {
12935 if (!zend_jit_fetch_dimension_address_inner(jit, opline,
type, op1_info,
12936 op2_info, op2_addr, op2_range, dim_type,
NULL,
NULL,
NULL,
12937 0, ht_ref, found_inputs, found_vals, &end_inputs,
NULL)) {
12944 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
12954 if (found_inputs->
count) {
12956 ref =
ir_PHI_N(IR_ADDR, found_vals->
count, found_vals->refs);
12957 jit_set_Z_PTR(jit, res_addr, ref);
12976 jit_SET_EX_OPLINE(jit, opline);
12985 arg2 = jit_ZVAL_ADDR(jit, op2_addr);
12988 switch (opline->
opcode) {
12992 jit_ZVAL_ADDR(jit, op1_addr),
12994 jit_ZVAL_ADDR(jit, res_addr));
12998 jit_ZVAL_ADDR(jit, op1_addr),
13000 jit_ZVAL_ADDR(jit, res_addr));
13014#ifdef ZEND_JIT_USE_RC_INFERENCE
13031 jit_FREE_OP(jit, opline->
op2_type, opline->
op2, op2_info, opline);
13034 zend_jit_check_exception(jit);
13040static int zend_jit_isset_isempty_dim(
zend_jit_ctx *jit,
13044 bool op1_avoid_refcounting,
13050 uint8_t smart_branch_opcode,
13051 uint32_t target_label,
13052 uint32_t target_label2,
13053 const void *exit_addr)
13068 ir_ref ref = jit_ZVAL_ADDR(jit, op1_addr);
13069 ref = jit_ZVAL_DEREF_ref(jit, ref);
13074 const void *found_exit_addr =
NULL;
13075 const void *not_found_exit_addr =
NULL;
13079 if_type = jit_if_Z_TYPE(jit, op1_addr,
IS_ARRAY);
13083 ht_ref = jit_Z_PTR(jit, op1_addr);
13091 found_exit_addr = exit_addr;
13093 not_found_exit_addr = exit_addr;
13096 if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_JIT_IS, op1_info,
13097 op2_info, op2_addr, op2_range, dim_type, found_exit_addr, not_found_exit_addr,
NULL,
13098 0, ht_ref, true_inputs,
NULL, &false_inputs,
NULL)) {
13102 if (found_exit_addr) {
13105 }
else if (not_found_exit_addr) {
13120 jit_SET_EX_OPLINE(jit, opline);
13121 arg1 = jit_ZVAL_ADDR(jit, op1_addr);
13126 arg2 = jit_ZVAL_ADDR(jit, op2_addr);
13129 if_true =
ir_IF(ref);
13131 ir_refs_add(true_inputs,
ir_END());
13139 ir_ref if_def =
ir_IF(jit_Z_TYPE(jit, op2_addr));
13144 jit_SET_EX_OPLINE(jit, opline);
13154#ifdef ZEND_JIT_USE_RC_INFERENCE
13161 if (true_inputs->
count) {
13164 jit_FREE_OP(jit, opline->
op2_type, opline->
op2, op2_info, opline);
13165 if (!op1_avoid_refcounting) {
13166 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
13169 zend_jit_check_exception_undef_result(jit, opline);
13178 }
else if (smart_branch_opcode) {
13179 if (smart_branch_opcode ==
ZEND_JMPZ) {
13180 _zend_jit_add_predecessor_ref(jit, target_label2, jit->
b,
ir_END());
13181 }
else if (smart_branch_opcode ==
ZEND_JMPNZ) {
13182 _zend_jit_add_predecessor_ref(jit, target_label, jit->
b,
ir_END());
13187 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_TRUE);
13196 jit_FREE_OP(jit, opline->
op2_type, opline->
op2, op2_info, opline);
13197 if (!op1_avoid_refcounting) {
13198 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
13201 zend_jit_check_exception_undef_result(jit, opline);
13205 if (smart_branch_opcode ==
ZEND_JMPZ) {
13210 }
else if (smart_branch_opcode) {
13211 if (smart_branch_opcode ==
ZEND_JMPZ) {
13212 _zend_jit_add_predecessor_ref(jit, target_label, jit->
b,
ir_END());
13213 }
else if (smart_branch_opcode ==
ZEND_JMPNZ) {
13214 _zend_jit_add_predecessor_ref(jit, target_label2, jit->
b,
ir_END());
13219 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_FALSE);
13226 if (!exit_addr && smart_branch_opcode) {
13252 if (op3_addr != op3_def_addr && op3_def_addr) {
13253 if (!zend_jit_update_regs(jit, (opline+1)->
op1.var, op3_addr, op3_def_addr, val_info)) {
13257 op3_addr = op3_def_addr;
13263 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
13269 jit_guard_not_Z_TYPE(jit, op3_addr,
IS_UNDEF, exit_addr);
13274 op1_addr = zend_jit_prepare_array_update(jit, opline, op1_info, op1_addr, &if_type, &ht_ref, &may_throw);
13284 ht_ref,
jit_EG(uninitialized_zval));
13287 if_ok =
ir_IF(ref);
13291 jit_SET_EX_OPLINE(jit, opline);
13298 if (!zend_jit_simple_assign(jit, opline, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0)) {
13305 ir_refs *found_inputs, *found_values;
13310 if (!zend_jit_fetch_dimension_address_inner(jit, opline,
BP_VAR_W, op1_info,
13311 op2_info, op2_addr, op2_range, dim_type,
NULL,
NULL,
NULL,
13312 0, ht_ref, found_inputs, found_values, &end_inputs,
NULL)) {
13323 if (found_inputs->
count) {
13325 ref =
ir_PHI_N(IR_ADDR, found_values->
count, found_values->refs);
13333 if (!zend_jit_assign_to_variable_call(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0)) {
13337 if (!zend_jit_assign_to_variable(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0, 0)) {
13355 jit_SET_EX_OPLINE(jit, opline);
13363 arg2 = jit_ZVAL_ADDR(jit, op2_addr);
13369 arg4 = jit_ZVAL_ADDR(jit, res_addr);
13372 jit_ZVAL_ADDR(jit, op1_addr),
13374 jit_ZVAL_ADDR(jit, op3_addr),
13377#ifdef ZEND_JIT_USE_RC_INFERENCE
13384 jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->
op1, val_info,
NULL);
13389#ifdef ZEND_JIT_USE_RC_INFERENCE
13397 jit_FREE_OP(jit, opline->
op2_type, opline->
op2, op2_info, opline);
13400 zend_jit_check_exception(jit);
13409 uint32_t op1_def_info,
13414 uint32_t op1_data_info,
13421 const void *not_found_exit_addr =
NULL;
13425 bool emit_fast_path = 1;
13430 jit_SET_EX_OPLINE(jit, opline);
13433 op1_addr = zend_jit_prepare_array_update(jit, opline, op1_info, op1_addr, &if_type, &ht_ref, &may_throw);
13439 zend_jit_use_reg(jit, op3_addr);
13452 ht_ref,
jit_EG(uninitialized_zval));
13455 if_ok =
ir_IF(ref);
13467 ir_refs *found_inputs, *found_values;
13485 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
13486 not_found_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
13487 if (!not_found_exit_addr) {
13492 if (!zend_jit_fetch_dimension_address_inner(jit, opline,
BP_VAR_RW, op1_info,
13493 op2_info, op2_addr, op2_range, dim_type,
NULL, not_found_exit_addr,
NULL,
13494 0, ht_ref, found_inputs, found_values, &end_inputs,
NULL)) {
13498 if (found_inputs->
count) {
13500 ref =
ir_PHI_N(IR_ADDR, found_values->
count, found_values->refs);
13503 if (not_found_exit_addr && dim_type !=
IS_REFERENCE) {
13504 jit_guard_Z_TYPE(jit, var_addr, dim_type, not_found_exit_addr);
13509 ir_ref if_ref, if_typed, noref_path, ref_path, ref, reference, ref2,
arg2;
13511 ref = jit_ZVAL_ADDR(jit, var_addr);
13517 reference = jit_Z_PTR_ref(jit, ref);
13519 if_typed = jit_if_TYPED_REF(jit, reference);
13526 if (!zend_jit_spill_store_inv(jit, op3_addr, real_addr, op1_data_info)) {
13529 op3_addr = real_addr;
13531 arg2 = jit_ZVAL_ADDR(jit, op3_addr);
13538 ref =
ir_PHI_2(IR_ADDR, ref, ref2);
13542 emit_fast_path = 0;
13546 if (emit_fast_path) {
13547 uint8_t val_op_type = (opline+1)->op1_type;
13551 val_op_type =
IS_CV;
13559 if (!zend_jit_math_helper(jit, opline, opline->
extended_value,
IS_CV, opline->
op1, var_addr, var_info, val_op_type, (opline+1)->op1, op3_addr, op1_data_info, 0, var_addr, var_def_info, var_info,
13570 if (!zend_jit_long_math_helper(jit, opline, opline->
extended_value,
13572 val_op_type, (opline+1)->op1, op3_addr, op1_data_info,
13574 0, var_addr, var_def_info, var_info, may_throw)) {
13579 if (!zend_jit_concat_helper(jit, opline,
IS_CV, opline->
op1, var_addr, var_info, val_op_type, (opline+1)->op1, op3_addr, op1_data_info, var_addr,
13607 arg2 = jit_ZVAL_ADDR(jit, op2_addr);
13611 jit_ZVAL_ADDR(jit, op1_addr),
13613 jit_ZVAL_ADDR(jit, op3_addr),
13622 jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->
op1, op1_data_info,
NULL);
13625 zend_jit_check_exception(jit);
13643 jit_ZVAL_COPY(jit, res_addr, -1, op1_addr, op1_info, opline->
op1_type ==
IS_CV);
13652static int zend_jit_packed_guard(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t var, uint32_t op_info)
13655 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
13675static int zend_jit_fe_fetch(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info, uint32_t op2_info,
unsigned int target_label, uint8_t exit_opcode,
const void *exit_addr)
13701 ht_ref = jit_Z_PTR(jit, op1_addr);
13704 if (!zend_jit_packed_guard(jit, opline, opline->
op1.
var, op1_info)) {
13713 ir_ref loop_ref, pos2_ref, p2_ref;
13719 if_packed =
ir_IF(ref);
13724 if (
sizeof(
void*) == 8) {
13738 ref =
ir_ULT(hash_pos_ref,
13765 if (!exit_addr || exit_opcode ==
ZEND_JMP) {
13766 if_def_hash =
ir_IF(jit_Z_TYPE_ref(jit, hash_p_ref));
13784 ir_ref loop_ref, pos2_ref, p2_ref;
13787 if (
sizeof(
void*) == 8) {
13801 ref =
ir_ULT(packed_pos_ref,
13827 if (!exit_addr || exit_opcode ==
ZEND_JMP) {
13828 if_def_packed =
ir_IF(jit_Z_TYPE_ref(jit, packed_p_ref));
13842 if (!exit_addr || exit_opcode ==
ZEND_JMP) {
13867 if_key =
ir_IF(key_ref);
13871 ir_ref if_interned, interned_path;
13874 jit_set_Z_PTR(jit, res_addr, key_ref);
13878 if_interned =
ir_IF(ref);
13881 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_STRING);
13883 interned_path =
ir_END();
13886 jit_GC_ADDREF(jit, key_ref);
13901 jit_set_Z_LVAL(jit, res_addr, ref);
13902 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
13911 p_ref = hash_p_ref;
13924 packed_pos_ref =
ir_ZEXT_L(packed_pos_ref);
13928 jit_set_Z_LVAL(jit, res_addr, packed_pos_ref);
13929 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
13933 p_ref =
ir_PHI_2(IR_ADDR, packed_p_ref, hash_p_ref);
13935 p_ref = packed_p_ref;
13941 if (if_def_hash && if_def_packed) {
13944 pos_ref =
ir_PHI_2(IR_U32, hash_pos_ref, packed_pos_ref);
13945 p_ref =
ir_PHI_2(IR_ADDR, hash_p_ref, packed_p_ref);
13946 }
else if (if_def_hash) {
13948 pos_ref = hash_pos_ref;
13949 p_ref = hash_p_ref;
13950 }
else if (if_def_packed) {
13952 pos_ref = packed_pos_ref;
13953 p_ref = packed_p_ref;
13977 if (!zend_jit_assign_to_variable(jit, opline, var_addr, var_addr, op2_info, -1,
IS_CV, val_addr, val_info, 0, 0, 1)) {
13982 jit_ZVAL_COPY(jit, var_addr, -1, val_addr, val_info, 1);
13998 _zend_jit_add_predecessor_ref(jit, bb->
successors[0], jit->
b, ref);
14009static int zend_jit_load_this(
zend_jit_ctx *jit, uint32_t var)
14013 ir_ref ref = jit_Z_PTR(jit, this_addr);
14015 jit_set_Z_PTR(jit, var_addr, ref);
14017 jit_GC_ADDREF(jit, ref);
14024 if (!op_array->
scope ||
14028 if (!
JIT_G(current_frame) ||
14033 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
14039 jit_guard_Z_TYPE(jit, this_addr,
IS_OBJECT, exit_addr);
14041 if (
JIT_G(current_frame)) {
14050 jit_SET_EX_OPLINE(jit, opline);
14051 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_invalid_this));
14058 if (!zend_jit_load_this(jit, opline->
result.
var)) {
14068 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
14069 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
14090 bool ce_is_instanceof,
14092 bool delayed_fetch_this,
14093 bool op1_avoid_refcounting,
14101 bool may_be_dynamic = 1;
14120 obj_ref = jit_Z_PTR(jit, this_addr);
14125 &&
Z_REG(op1_addr) == ZREG_FP) {
14126 op1_addr = jit_ZVAL_INDIRECT_DEREF(jit, op1_addr);
14129 op1_addr = jit_ZVAL_DEREF(jit, op1_addr);
14134 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
14139 jit_guard_Z_TYPE(jit, op1_addr,
IS_OBJECT, exit_addr);
14147 jit_SET_EX_OPLINE(jit, opline);
14153 ir_ref if_def =
ir_IF(jit_Z_TYPE(jit, op1_addr));
14163 op1_ref = jit_ZVAL_ADDR(jit, orig_op1_addr);
14165 op1_ref = jit_ZVAL_ADDR(jit, op1_addr);
14170 jit_set_Z_TYPE_INFO(jit, res_addr,
_IS_ERROR);
14174 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
14177 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
14184 obj_ref = jit_Z_PTR(jit, op1_addr);
14192 ce_is_instanceof = 0;
14194 if (on_this &&
JIT_G(current_frame)
14197 }
else if (zend_jit_class_guard(jit, opline, obj_ref, ce)) {
14198 if (on_this &&
JIT_G(current_frame)) {
14199 JIT_G(current_frame)->ce = ce;
14228 if (may_be_dynamic) {
14235 jit_SET_EX_OPLINE(jit, opline);
14240 obj_ref, offset_ref);
14244 obj_ref, offset_ref);
14250 obj_ref, offset_ref);
14254 obj_ref, offset_ref);
14261 prop_ref =
ir_ADD_A(obj_ref, offset_ref);
14262 prop_type_ref = jit_Z_TYPE_ref(jit, prop_ref);
14306 ref = jit_Z_PTR(jit, prop_addr);
14307 jit_GC_ADDREF(jit, ref);
14308 jit_set_Z_PTR(jit, res_addr, ref);
14314 jit_SET_EX_OPLINE(jit, opline);
14318 jit_set_Z_TYPE_INFO(jit, res_addr,
_IS_ERROR);
14324 jit_set_Z_TYPE_INFO(jit, res_addr,
_IS_ERROR);
14330 jit_SET_EX_OPLINE(jit, opline);
14332 prop_ref, prop_info_ref);
14339 jit_ZVAL_ADDR(jit, res_addr));
14354 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
14359 prop_type_ref = jit_Z_TYPE_INFO(jit, prop_addr);
14363 prop_type_ref = jit_Z_TYPE_INFO(jit, prop_addr);
14372 ir_ref ref = jit_Z_PTR(jit, prop_addr);
14373 jit_GC_ADDREF(jit, ref);
14374 jit_set_Z_PTR(jit, res_addr, ref);
14379 jit_SET_EX_OPLINE(jit, opline);
14381 jit_set_Z_TYPE_INFO(jit, res_addr,
_IS_ERROR);
14384 goto result_fetched;
14395 ir_ref ref = jit_Z_PTR(jit, prop_addr);
14396 jit_GC_ADDREF(jit, ref);
14397 jit_set_Z_PTR(jit, res_addr, ref);
14416 if (!prop_type_ref) {
14417 prop_type_ref = jit_Z_TYPE_INFO(jit, prop_addr);
14421 jit_SET_EX_OPLINE(jit, opline);
14430 if (!prop_type_ref) {
14431 prop_type_ref = jit_Z_TYPE_INFO(jit, prop_addr);
14439 int prop_info_offset =
14449 jit_ZVAL_ADDR(jit, res_addr));
14460 jit_set_Z_PTR(jit, res_addr, prop_ref);
14472 prop_type_ref = jit_Z_TYPE_INFO(jit, prop_addr);
14474 if (!zend_jit_zval_copy_deref_reg(jit, res_addr, res_info & ~
MAY_BE_GUARD, prop_addr, prop_type_ref, &end_values)) {
14478 prop_type_ref = jit_Z_TYPE_INFO(jit, prop_addr);
14480 if (!zend_jit_zval_copy_deref(jit, res_addr, prop_addr, prop_type_ref)) {
14488 if (op1_avoid_refcounting) {
14494 jit_SET_EX_OPLINE(jit, opline);
14517 bool result_avoid_refcounting = 0;
14524 uint8_t
type = concrete_type(res_info);
14528 && !delayed_fetch_this
14529 && !op1_avoid_refcounting) {
14536 && (ssa_op+1)->op1_use == ssa_op->
result_def
14537 && zend_jit_may_avoid_refcounting(opline+1, res_info)) {
14538 result_avoid_refcounting = 1;
14542 val_addr = zend_jit_guard_fetch_result_type(jit, opline, val_addr,
type,
14543 1,
flags, op1_avoid_refcounting);
14553 jit_ZVAL_COPY(jit, res_addr, -1, val_addr, res_info, !result_avoid_refcounting);
14555 if (!zend_jit_store_var_if_necessary(jit, opline->
result.
var, res_addr, res_info)) {
14567 ir_ref if_refcounted,
ptr, refcount, if_non_zero;
14570 if_refcounted = jit_if_REFCOUNTED(jit, orig_op1_addr);
14574 ptr = jit_Z_PTR(jit, orig_op1_addr);
14575 refcount = jit_GC_DELREF(jit,
ptr);
14576 if_non_zero =
ir_IF(refcount);
14580 jit_SET_EX_OPLINE(jit, opline);
14584 }
else if (!op1_avoid_refcounting) {
14588 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
14603 zend_jit_check_exception_undef_result(jit, opline);
14605 zend_jit_check_exception(jit);
14625 bool ce_is_instanceof,
14627 bool delayed_fetch_this,
14643 if (val_addr != val_def_addr && val_def_addr) {
14644 if (!zend_jit_update_regs(jit, (opline+1)->
op1.var, val_addr, val_def_addr, val_info)) {
14648 val_addr = val_def_addr;
14662 obj_ref = jit_Z_PTR(jit, this_addr);
14666 &&
Z_REG(op1_addr) == ZREG_FP) {
14667 op1_addr = jit_ZVAL_INDIRECT_DEREF(jit, op1_addr);
14670 op1_addr = jit_ZVAL_DEREF(jit, op1_addr);
14675 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
14680 jit_guard_Z_TYPE(jit, op1_addr,
IS_OBJECT, exit_addr);
14685 jit_SET_EX_OPLINE(jit, opline);
14687 jit_ZVAL_ADDR(jit, op1_addr),
14691 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
14699 obj_ref = jit_Z_PTR(jit, op1_addr);
14707 ce_is_instanceof = 0;
14709 if (on_this &&
JIT_G(current_frame)
14712 }
else if (zend_jit_class_guard(jit, opline, obj_ref, ce)) {
14713 if (on_this &&
JIT_G(current_frame)) {
14714 JIT_G(current_frame)->ce = ce;
14751 prop_ref =
ir_ADD_A(obj_ref, offset_ref);
14752 ir_ref if_def =
ir_IF(jit_Z_TYPE_ref(jit, prop_ref));
14768 if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14771 arg3 = jit_ZVAL_ADDR(jit, real_addr);
14773 arg3 = jit_ZVAL_ADDR(jit, val_addr);
14780 arg4 = jit_ZVAL_ADDR(jit, real_addr);
14782 arg4 = jit_ZVAL_ADDR(jit, res_addr);
14785 jit_SET_EX_OPLINE(jit, opline);
14792 if ((opline+1)->op1_type ==
IS_CONST) {
14813 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
14820 ir_ref if_def =
ir_IF(jit_Z_TYPE_INFO(jit, prop_addr));
14829 jit_SET_EX_OPLINE(jit, opline);
14833 int prop_info_offset =
14842 if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14845 arg3 = jit_ZVAL_ADDR(jit, real_addr);
14847 arg3 = jit_ZVAL_ADDR(jit, val_addr);
14853 arg4 = jit_ZVAL_ADDR(jit, real_addr);
14855 arg4 = jit_ZVAL_ADDR(jit, res_addr);
14871 if (!zend_jit_assign_to_variable_call(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, res_addr, 0)) {
14880 real_res_addr = res_addr;
14882 if (!zend_jit_assign_to_variable(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, real_res_addr, 0, 0)) {
14886 if (end_inputs || slow_inputs) {
14890 delayed_end_input =
ir_END();
14903 jit_SET_EX_OPLINE(jit, opline);
14907 if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14910 arg3 = jit_ZVAL_ADDR(jit, real_addr);
14912 arg3 = jit_ZVAL_ADDR(jit, val_addr);
14918 arg5 = jit_ZVAL_ADDR(jit, real_addr);
14920 arg5 = jit_ZVAL_ADDR(jit, res_addr);
14941 jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->
op1, val_info, opline);
14943 if (delayed_end_input) {
14949 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
14954 if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) {
14960 zend_jit_check_exception(jit);
14978 bool ce_is_instanceof,
14980 bool delayed_fetch_this,
14988 bool use_prop_guard = 0;
14989 bool may_throw = 0;
15007 obj_ref = jit_Z_PTR(jit, this_addr);
15011 &&
Z_REG(op1_addr) == ZREG_FP) {
15012 op1_addr = jit_ZVAL_INDIRECT_DEREF(jit, op1_addr);
15015 op1_addr = jit_ZVAL_DEREF(jit, op1_addr);
15020 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
15025 jit_guard_Z_TYPE(jit, op1_addr,
IS_OBJECT, exit_addr);
15030 jit_SET_EX_OPLINE(jit, opline);
15035 jit_ZVAL_ADDR(jit, op1_addr),
15044 obj_ref = jit_Z_PTR(jit, op1_addr);
15052 ce_is_instanceof = 0;
15054 if (on_this &&
JIT_G(current_frame)
15057 }
else if (zend_jit_class_guard(jit, opline, obj_ref, ce)) {
15058 if (on_this &&
JIT_G(current_frame)) {
15059 JIT_G(current_frame)->ce = ce;
15088 zend_jit_use_reg(jit, val_addr);
15118 prop_ref =
ir_ADD_A(obj_ref, offset_ref);
15119 if (!use_prop_guard) {
15120 ir_ref if_def =
ir_IF(jit_Z_TYPE_ref(jit, prop_ref));
15134 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
15141 ir_ref if_def =
ir_IF(jit_Z_TYPE_INFO(jit, prop_addr));
15148 ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref,
arg2;
15152 jit_SET_EX_OPLINE(jit, opline);
15156 if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
15159 arg2 = jit_ZVAL_ADDR(jit, real_addr);
15161 arg2 = jit_ZVAL_ADDR(jit, val_addr);
15169 reference = jit_Z_PTR(jit, prop_addr);
15171 if_typed = jit_if_TYPED_REF(jit, reference);
15184 prop_ref =
ir_PHI_2(IR_ADDR, prop_ref, ref);
15191 int prop_info_offset =
15214 if (use_prop_guard) {
15215 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
15216 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
15221 jit_guard_Z_TYPE(jit, prop_addr, prop_type, exit_addr);
15226 ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref,
arg2;
15235 reference = jit_Z_PTR(jit, var_addr);
15237 if_typed = jit_if_TYPED_REF(jit, reference);
15242 jit_SET_EX_OPLINE(jit, opline);
15246 if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
15249 arg2 = jit_ZVAL_ADDR(jit, real_addr);
15251 arg2 = jit_ZVAL_ADDR(jit, val_addr);
15261 prop_ref =
ir_PHI_2(IR_ADDR, prop_ref, ref);
15267 uint8_t val_op_type = (opline+1)->op1_type;
15270 val_op_type =
IS_CV;
15285 if (!zend_jit_math_helper(jit, opline, opline->
extended_value,
IS_CV, opline->
op1, var_addr, var_info, val_op_type, (opline+1)->op1, val_addr, val_info, 0, var_addr, var_def_info, var_info,
15324 if (!zend_jit_long_math_helper(jit, opline, opline->
extended_value,
15326 val_op_type, (opline+1)->op1, val_addr, val_info,
15328 0, var_addr, var_def_info, var_info, 1)) {
15334 if (!zend_jit_concat_helper(jit, opline,
IS_CV, opline->
op1, var_addr, var_info, val_op_type, (opline+1)->op1, val_addr, val_info, var_addr,
15342 if (end_inputs || slow_inputs) {
15356 if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
15359 arg3 = jit_ZVAL_ADDR(jit, real_addr);
15361 arg3 = jit_ZVAL_ADDR(jit, val_addr);
15363 jit_SET_EX_OPLINE(jit, opline);
15384 jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->
op1, val_info, opline);
15390 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
15394 zend_jit_check_exception(jit);
15409 bool ce_is_instanceof,
15411 bool delayed_fetch_this,
15420 bool use_prop_guard = 0;
15421 bool may_throw = 0;
15442 obj_ref = jit_Z_PTR(jit, this_addr);
15446 &&
Z_REG(op1_addr) == ZREG_FP) {
15447 op1_addr = jit_ZVAL_INDIRECT_DEREF(jit, op1_addr);
15450 op1_addr = jit_ZVAL_DEREF(jit, op1_addr);
15455 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
15460 jit_guard_Z_TYPE(jit, op1_addr,
IS_OBJECT, exit_addr);
15465 jit_SET_EX_OPLINE(jit, opline);
15467 jit_ZVAL_ADDR(jit, op1_addr),
15470 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
15474 obj_ref = jit_Z_PTR(jit, op1_addr);
15482 ce_is_instanceof = 0;
15484 if (on_this &&
JIT_G(current_frame)
15487 }
else if (zend_jit_class_guard(jit, opline, obj_ref, ce)) {
15488 if (on_this &&
JIT_G(current_frame)) {
15489 JIT_G(current_frame)->ce = ce;
15541 prop_ref =
ir_ADD_A(obj_ref, offset_ref);
15542 if (!use_prop_guard) {
15543 ir_ref if_def =
ir_IF(jit_Z_TYPE_ref(jit, prop_ref));
15557 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
15564 ir_ref if_def =
ir_IF(jit_Z_TYPE_INFO(jit, prop_addr));
15576 jit_SET_EX_OPLINE(jit, opline);
15581 int prop_info_offset =
15590 switch (opline->
opcode) {
15593 func = zend_jit_inc_typed_prop;
15597 func = zend_jit_dec_typed_prop;
15605 switch (opline->
opcode) {
15607 func = zend_jit_pre_inc_typed_prop;
15610 func = zend_jit_pre_dec_typed_prop;
15613 func = zend_jit_post_inc_typed_prop;
15616 func = zend_jit_post_dec_typed_prop;
15624 jit_ZVAL_ADDR(jit, res_addr));
15636 if (use_prop_guard) {
15637 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
15638 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
15643 jit_guard_Z_TYPE(jit, prop_addr, prop_type, exit_addr);
15649 ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref;
15656 reference = jit_Z_PTR(jit, var_addr);
15658 if_typed = jit_if_TYPED_REF(jit, reference);
15663 switch (opline->
opcode) {
15665 func = zend_jit_pre_inc_typed_ref;
15668 func = zend_jit_pre_dec_typed_ref;
15671 func = zend_jit_post_inc_typed_ref;
15674 func = zend_jit_post_dec_typed_ref;
15681 jit_SET_EX_OPLINE(jit, opline);
15689 prop_ref =
ir_PHI_2(IR_ADDR, prop_ref, ref);
15699 if_long = jit_if_Z_TYPE(jit, var_addr,
IS_LONG);
15703 addr = jit_ZVAL_ADDR(jit, var_addr);
15707 jit_set_Z_LVAL(jit, res_addr, ref);
15708 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
15723 jit_set_Z_LVAL(jit, res_addr, ref);
15724 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_LONG);
15738 jit_ZVAL_COPY(jit, res_addr, -1, var_addr, var_info, 1);
15743 jit_ZVAL_ADDR(jit, var_addr),
15744 jit_ZVAL_ADDR(jit, res_addr));
15747 jit_ZVAL_ADDR(jit, var_addr));
15752 jit_ZVAL_ADDR(jit, var_addr),
15753 jit_ZVAL_ADDR(jit, res_addr));
15756 jit_ZVAL_ADDR(jit, var_addr));
15765#if SIZEOF_ZEND_LONG == 4
15767 jit_set_Z_W2(jit, var_addr,
ir_CONST_U32(0x41e00000));
15769 jit_set_Z_LVAL(jit, var_addr,
ir_CONST_LONG(0x43e0000000000000));
15771 jit_set_Z_TYPE_INFO(jit, var_addr,
IS_DOUBLE);
15773#if SIZEOF_ZEND_LONG == 4
15775 jit_set_Z_W2(jit, res_addr,
ir_CONST_U32(0x41e00000));
15777 jit_set_Z_LVAL(jit, res_addr,
ir_CONST_LONG(0x43e0000000000000));
15779 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
15782#if SIZEOF_ZEND_LONG == 4
15784 jit_set_Z_W2(jit, var_addr,
ir_CONST_U32(0xc1e00000));
15786 jit_set_Z_LVAL(jit, var_addr,
ir_CONST_LONG(0xc3e0000000000000));
15788 jit_set_Z_TYPE_INFO(jit, var_addr,
IS_DOUBLE);
15790#if SIZEOF_ZEND_LONG == 4
15792 jit_set_Z_W2(jit, res_addr,
ir_CONST_U32(0xc1e00000));
15794 jit_set_Z_LVAL(jit, res_addr,
ir_CONST_LONG(0xc3e0000000000000));
15796 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_DOUBLE);
15807 int32_t exit_point;
15808 const void *exit_addr;
15811 exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
15812 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
15831 switch (opline->
opcode) {
15833 func = zend_jit_pre_inc_obj_helper;
15836 func = zend_jit_pre_dec_obj_helper;
15839 func = zend_jit_post_inc_obj_helper;
15842 func = zend_jit_post_dec_obj_helper;
15849 jit_SET_EX_OPLINE(jit, opline);
15868 jit_FREE_OP(jit, opline->
op1_type, opline->
op1, op1_info, opline);
15872 zend_jit_check_exception(jit);
15889 next_opline = trace->opline;
15917 if (jump_zv !=
NULL) {
15924 if (jump_zv !=
NULL) {
15929 _zend_jit_add_predecessor_ref(jit, b, jit->
b,
ir_END());
15938 int default_b = next_opline ? -1 : ssa->
cfg.
map[default_opline - op_array->
opcodes];
15940 int32_t exit_point;
15941 const void *exit_addr;
15942 const void *default_label =
NULL;
15946 if (next_opline != default_opline) {
15947 exit_point = zend_jit_trace_get_exit_point(default_opline, 0);
15948 default_label = zend_jit_trace_get_exit_addr(exit_point);
15949 if (!default_label) {
15957 const void *fallback_label =
NULL;
15960 if (next_opline != opline + 1) {
15961 exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
15962 fallback_label = zend_jit_trace_get_exit_addr(exit_point);
15963 if (!fallback_label) {
15969 ir_ref ref, if_long, fast_path, ref2;
15971 ref = jit_ZVAL_ADDR(jit, op1_addr);
15972 if_long = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
15978 if (fallback_label) {
15979 jit_guard_Z_TYPE(jit, op1_addr,
IS_REFERENCE, fallback_label);
15983 ir_refs_add(slow_inputs,
ir_END());
15990 if (fallback_label) {
15991 jit_guard_Z_TYPE(jit, op1_addr,
IS_LONG, fallback_label);
15993 if_long = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
15995 ir_refs_add(slow_inputs,
ir_END());
16000 ref =
ir_PHI_2(IR_ADDR, ref, ref2);
16003 if (fallback_label) {
16004 jit_guard_Z_TYPE(jit, op1_addr,
IS_LONG, fallback_label);
16008 ir_refs_add(slow_inputs,
ir_END());
16012 ir_ref ref = jit_Z_LVAL(jit, op1_addr);
16019 if (
sizeof(
Bucket) == 32) {
16040 if (target == next_opline) {
16043 exit_point = zend_jit_trace_get_exit_point(target, 0);
16044 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16053 if (next_opline == default_opline) {
16058 if (continue_list) {
16068 _zend_jit_add_predecessor_ref(jit, b, jit->
b, ref);
16071 _zend_jit_add_predecessor_ref(jit, default_b, jit->
b, ref);
16072 if (slow_inputs->
count) {
16074 _zend_jit_add_predecessor_ref(jit, jit->
b + 1, jit->
b,
ir_END());
16078 }
else if (!next_opline) {
16079 _zend_jit_add_predecessor_ref(jit, jit->
b + 1, jit->
b,
ir_END());
16084 const void *fallback_label =
NULL;
16087 if (next_opline != opline + 1) {
16088 exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
16089 fallback_label = zend_jit_trace_get_exit_addr(exit_point);
16090 if (!fallback_label) {
16096 ir_ref ref, if_string, fast_path, ref2;
16098 ref = jit_ZVAL_ADDR(jit, op1_addr);
16099 if_string = jit_if_Z_TYPE(jit, op1_addr,
IS_STRING);
16105 if (fallback_label) {
16106 jit_guard_Z_TYPE(jit, op1_addr,
IS_REFERENCE, fallback_label);
16110 ir_refs_add(slow_inputs,
ir_END());
16117 if (fallback_label) {
16118 jit_guard_Z_TYPE(jit, op1_addr,
IS_LONG, fallback_label);
16120 if_string = jit_if_Z_TYPE(jit, op1_addr,
IS_STRING);
16122 ir_refs_add(slow_inputs,
ir_END());
16127 ref =
ir_PHI_2(IR_ADDR, ref, ref2);
16130 if (fallback_label) {
16131 jit_guard_Z_TYPE(jit, op1_addr,
IS_STRING, fallback_label);
16135 ir_refs_add(slow_inputs,
ir_END());
16140 ir_ref ref = jit_Z_PTR(jit, op1_addr);
16145 if (
sizeof(
Bucket) == 32) {
16165 if (target == next_opline) {
16168 exit_point = zend_jit_trace_get_exit_point(target, 0);
16169 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16178 if (next_opline == default_opline) {
16183 if (continue_list) {
16193 _zend_jit_add_predecessor_ref(jit, b, jit->
b, ref);
16195 _zend_jit_add_predecessor_ref(jit, default_b, jit->
b, ref);
16196 if (slow_inputs->
count) {
16198 _zend_jit_add_predecessor_ref(jit, jit->
b + 1, jit->
b,
ir_END());
16202 }
else if (!next_opline) {
16203 _zend_jit_add_predecessor_ref(jit, jit->
b + 1, jit->
b,
ir_END());
16214 op1_addr = jit_ZVAL_DEREF(jit, op1_addr);
16219 if_type = jit_if_Z_TYPE(jit, op1_addr,
IS_LONG);
16221 }
else if (default_label) {
16222 jit_guard_Z_TYPE(jit, op1_addr,
IS_LONG, default_label);
16223 }
else if (next_opline) {
16235 ref = jit_Z_LVAL(jit, op1_addr);
16249 if_type = jit_if_Z_TYPE(jit, op1_addr,
IS_STRING);
16251 }
else if (default_label) {
16252 jit_guard_Z_TYPE(jit, op1_addr,
IS_STRING, default_label);
16253 }
else if (next_opline) {
16265 ir_ref ref2 = jit_Z_PTR(jit, op1_addr);
16282 if (
sizeof(
Bucket) == 32) {
16301 if (target == next_opline) {
16304 exit_point = zend_jit_trace_get_exit_point(target, 0);
16305 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16314 if (next_opline == default_opline) {
16323 _zend_jit_add_predecessor_ref(jit, b, jit->
b, ref);
16325 _zend_jit_add_predecessor_ref(jit, default_b, jit->
b, ref);
16329 if (next_opline == default_opline) {
16335 _zend_jit_add_predecessor_ref(jit, default_b, jit->
b,
ir_END());
16345 if (default_label) {
16346 jit_guard_Z_TYPE(jit, op1_addr,
IS_UNDEF, default_label);
16347 }
else if (next_opline) {
16348 ir_ref if_def =
ir_IF(jit_Z_TYPE(jit, op1_addr));
16353 ir_ref if_def =
ir_IF(jit_Z_TYPE(jit, op1_addr));
16360 jit_SET_EX_OPLINE(jit, opline);
16363 zend_jit_check_exception_undef_result(jit, opline);
16364 if (default_label) {
16366 }
else if (next_opline) {
16376 if (default_input_list) {
16377 if (jit->
ctx.
ir_base[ref].op == IR_SWITCH) {
16379 jit->
ctx.
ir_base[ref].op3 = default_input_list;
16382 _zend_jit_add_predecessor_ref(jit, default_b, jit->
b,
ir_END());
16409 for (i = 0, bb = ssa->
cfg.
blocks; i < ssa->cfg.blocks_count; i++, bb++) {
16415 if (!GCC_GLOBAL_REGS) {
16417 jit_STORE_FP(jit, ref);
16434 str = zend_string_copy(jit->
name);
16436 str = zend_jit_func_name(jit->
op_array);
16442 _zend_jit_fix_merges(jit);
16443#if defined(IR_TARGET_AARCH64)
16444 }
else if (jit->
trace) {
16446 jit->
ctx.get_exit_addr = zend_jit_trace_get_exit_addr;
16449#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
16457#ifdef HAVE_CAPSTONE
16465 &jit->
ctx, stderr);
16471 uintptr_t sp_offset = 0;
16476#if !defined(ZEND_WIN32) && !defined(IR_TARGET_AARCH64)
16477 sp_offset = zend_jit_hybrid_vm_sp_adj;
16479 sp_offset =
sizeof(
void*);
16482 sp_offset =
sizeof(
void*);
16515 op_array->
opcodes[insn->op2].
handler = (
char*)entry + insn->op3;
16534 zend_jit_trace_add_code(entry,
size);
16539 zend_string_release(str);
16545static const void *zend_jit_trace_allocate_exit_group(uint32_t
n)
16551 code_buffer.
start = dasm_buf;
16552 code_buffer.
end = dasm_end;
16553 code_buffer.
pos = *dasm_ptr;
16556 &code_buffer, &
size);
16558 *dasm_ptr = code_buffer.
pos;
16561#ifdef HAVE_CAPSTONE
16579 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
16580 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16591static int zend_jit_scalar_type_guard(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t var)
16593 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
16594 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16607 uint32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
16608 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16620 uint32_t exit_point = zend_jit_trace_get_exit_point(
NULL, 0);
16621 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16628 zend_jit_set_last_valid_opline(jit, opline);
16633static bool zend_jit_guard_reference(
zend_jit_ctx *jit,
16637 bool add_ref_guard)
16640 const void *exit_addr =
NULL;
16643 if (add_ref_guard) {
16644 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
16646 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16651 ref = jit_Z_TYPE(jit, var_addr);
16655 ref = jit_Z_PTR(jit, var_addr);
16659 *var_addr_ptr = var_addr;
16664static bool zend_jit_fetch_reference(
zend_jit_ctx *jit,
16667 uint32_t *var_info_ptr,
16669 bool add_ref_guard,
16670 bool add_type_guard)
16673 uint32_t var_info = *var_info_ptr;
16674 const void *exit_addr =
NULL;
16677 if (add_ref_guard || add_type_guard) {
16678 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
16680 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16686 if (add_ref_guard) {
16687 ref = jit_Z_TYPE(jit, var_addr);
16693 jit_ZVAL_ADDR(jit, var_addr));
16694 *var_addr_ptr = var_addr;
16696 ref = jit_Z_PTR(jit, var_addr);
16699 *var_addr_ptr = var_addr;
16708 ref = jit_Z_TYPE(jit, var_addr);
16713 var_info = (1 << var_type);
16714 }
else if (var_type !=
IS_ARRAY) {
16720 *var_info_ptr = var_info;
16723 *var_info_ptr = var_info;
16730static bool zend_jit_fetch_indirect_var(
zend_jit_ctx *jit,
const zend_op *opline, uint8_t var_type, uint32_t *var_info_ptr,
zend_jit_addr *var_addr_ptr,
bool add_indirect_guard)
16733 uint32_t var_info = *var_info_ptr;
16734 int32_t exit_point;
16735 const void *exit_addr;
16738 if (add_indirect_guard) {
16739 int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
16740 const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16745 jit_guard_Z_TYPE(jit, var_addr,
IS_INDIRECT, exit_addr);
16746 ref = jit_Z_PTR(jit, var_addr);
16750 ref = jit_Z_PTR(jit, var_addr);
16754 *var_addr_ptr = var_addr;
16762 exit_point = zend_jit_trace_get_exit_point(opline, 0);
16763 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16769 jit_guard_Z_TYPE(jit, var_addr, var_type, exit_addr);
16774 var_info = (1 << var_type);
16775 }
else if (var_type !=
IS_ARRAY) {
16781 *var_info_ptr = var_info;
16796 zend_jit_set_ip(jit, opline);
16797 if (GCC_GLOBAL_REGS) {
16806 zend_jit_check_exception(jit);
16813 if (!GCC_GLOBAL_REGS
16814 && (trace->op !=
ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_RETURN)) {
16828 if (zend_jit_trace_may_exit(op_array, opline)) {
16835 (trace->stop != ZEND_JIT_TRACE_STOP_RETURN &&
16836 trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) {
16839 jit_STUB_ADDR(jit, jit_stub_trace_halt));
16841 }
else if (GCC_GLOBAL_REGS) {
16842 ir_GUARD(jit_IP(jit), jit_STUB_ADDR(jit, jit_stub_trace_halt));
16849 ir_IJMP(jit_STUB_ADDR(jit, jit_stub_trace_halt));
16853 (trace->stop != ZEND_JIT_TRACE_STOP_RETURN &&
16854 trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) {
16856 const zend_op *next_opline = trace->opline;
16858 uint32_t exit_point;
16859 const void *exit_addr;
16860 uint32_t old_info = 0;
16861 uint32_t old_res_info = 0;
16865 bool exit_if_true = 0;
16866 exit_opline = zend_jit_trace_get_exit_opline(trace, opline + 1, &exit_if_true);
16868 switch (opline->
opcode) {
16878 exit_opline = (trace->opline == opline + 1) ?
16884 exit_opline = (trace->opline == opline + 1) ?
16892 switch (opline->
opcode) {
16911 exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
16912 exit_addr = zend_jit_trace_get_exit_addr(exit_point);
16917 switch (opline->
opcode) {
16938 zend_jit_set_last_valid_opline(jit, trace->opline);
16943static int zend_jit_deoptimizer_start(
zend_jit_ctx *jit,
16945 uint32_t trace_num,
16954 jit->
name = zend_string_copy(
name);
16965 uint32_t trace_num,
16976 jit->
name = zend_string_copy(
name);
16978 if (!GCC_GLOBAL_REGS) {
16981 jit_STORE_FP(jit, ref);
16992 int parent_vars_count = parent->exit_info[exit_num].stack_size;
16994 parent->stack_map +
16995 parent->exit_info[exit_num].stack_offset;
16998 for (i = 0; i < parent_vars_count; i++) {
17001 int32_t reg =
STACK_REG(parent_stack, i);
17033 ZEND_ASSERT(parent->exit_info[exit_num].poly_func.reg >= 0 && parent->exit_info[exit_num].poly_this.reg >= 0);
17034 if (!
IR_REG_SPILLED(parent->exit_info[exit_num].poly_func.reg)) {
17035 ir_RLOAD_A(parent->exit_info[exit_num].poly_func.reg);
17037 if (!
IR_REG_SPILLED(parent->exit_info[exit_num].poly_this.reg)) {
17038 ir_RLOAD_A(parent->exit_info[exit_num].poly_this.reg);
17047static int zend_jit_trace_begin_loop(
zend_jit_ctx *jit)
17055 int src_var = phi->
sources[0];
17072static int zend_jit_trace_end_loop(
zend_jit_ctx *jit,
int loop_ref,
const void *timeout_exit_addr)
17074 if (timeout_exit_addr) {
17075 zend_jit_check_timeout(jit,
NULL, timeout_exit_addr);
17082static int zend_jit_trace_return(
zend_jit_ctx *jit,
bool original_handler,
const zend_op *opline)
17084 if (GCC_GLOBAL_REGS) {
17085 if (!original_handler) {
17091 if (original_handler) {
17093 ir_ref addr = zend_jit_orig_opline_handler(jit);
17095#if defined(IR_TARGET_X86)
17115static int zend_jit_link_side_trace(
const void *code,
size_t size, uint32_t jmp_table_size, uint32_t exit_num,
const void *
addr)
17117 return ir_patch(code,
size, jmp_table_size, zend_jit_trace_get_exit_addr(exit_num),
addr);
17122 const void *link_addr;
17125 ZEND_ASSERT(zend_jit_trace_prologue_size != (
size_t)-1);
17126 link_addr = (
const void*)((
const char*)t->
code_start + zend_jit_trace_prologue_size);
17128 if (timeout_exit_addr) {
17129 zend_jit_check_timeout(jit,
NULL, timeout_exit_addr);
17138 uint32_t op1_info, op2_info;
17140 switch (opline->
opcode) {
17164 return zend_jit_supported_binary_op(opline->
extended_value, op1_info, op2_info);
17173 if (trace && trace->op1_type !=
IS_UNKNOWN) {
17176 if (trace && trace->op2_type !=
IS_UNKNOWN) {
17191 if (trace && trace->op1_type !=
IS_UNKNOWN) {
17194 if (trace && trace->op2_type !=
IS_UNKNOWN) {
17270 && (opline+1)->op1_type ==
IS_CV
17271 && (opline+1)->op1.var == opline->
op1.
var) {
17315static bool zend_jit_var_supports_reg(
zend_ssa *ssa,
int var)
17335 phi = zend_ssa_next_use_phi(ssa, var, phi);
17351 if (!zend_jit_var_supports_reg(ssa, var)) {
17357 if (!zend_jit_opline_supports_reg(op_array, ssa, op_array->
opcodes + def, ssa->
ops + def,
NULL)) {
17366 if (!zend_ssa_is_no_val_use(op_array->
opcodes + use, ssa->
ops + use, var) &&
17367 !zend_jit_opline_supports_reg(op_array, ssa, op_array->
opcodes + use, ssa->
ops + use,
NULL)) {
17370 use = zend_ssa_next_use(ssa->
ops, var, use);
17371 }
while (use >= 0);
17375 int def_block, use_block, b, use,
j;
17395 use_block = ssa->
cfg.
map[use];
17396 if (use_block != def_block) {
17397 zend_worklist_push(&worklist, use_block);
17399 use = zend_ssa_next_use(ssa->
ops, var, use);
17400 }
while (use >= 0);
17405 use_block =
p->block;
17406 if (use_block != def_block) {
17409 if (
p->sources[
j] == var) {
17411 if (use_block != def_block) {
17412 zend_worklist_push(&worklist, use_block);
17417 p = zend_ssa_next_use_phi(ssa, var,
p);
17420 while (zend_worklist_len(&worklist) != 0) {
17421 b = zend_worklist_pop(&worklist);
17429 if (b != def_block) {
17430 zend_worklist_push(&worklist, b);
17445 ir_ref observer_handler;
17460 jit_SET_EX_OPLINE(jit, opline);
17464 ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
17465 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
17469 skip_observer = jit_frameless_observer(jit, opline);
17478 zend_jit_check_exception(jit);
17481static void jit_frameless_icall1(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info)
17483 jit_SET_EX_OPLINE(jit, opline);
17493 ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
17494 ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr);
17495 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
17497 op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->
op1.
var, opline, 1);
17503 op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref);
17508 skip_observer = jit_frameless_observer(jit, opline);
17518 zend_jit_check_exception(jit);
17521static void jit_frameless_icall2(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info, uint32_t op2_info)
17523 jit_SET_EX_OPLINE(jit, opline);
17537 ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
17538 ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr);
17539 ir_ref op2_ref = jit_ZVAL_ADDR(jit, op2_addr);
17540 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
17542 op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->
op1.
var, opline, 1);
17548 op2_ref = zend_jit_zval_check_undef(jit, op2_ref, opline->
op2.
var, opline, 1);
17554 op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref);
17557 op2_ref = jit_ZVAL_DEREF_ref(jit, op2_ref);
17562 skip_observer = jit_frameless_observer(jit, opline);
17577 jit_set_Z_TYPE_INFO(jit, op1_addr,
IS_UNDEF);
17578 if (
JIT_G(current_frame)) {
17584 zend_jit_check_exception(jit);
17587static void jit_frameless_icall3(
zend_jit_ctx *jit,
const zend_op *opline, uint32_t op1_info, uint32_t op2_info, uint32_t op1_data_info)
17589 jit_SET_EX_OPLINE(jit, opline);
17603 uint8_t op_data_type = (opline + 1)->op1_type;
17608 ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr);
17609 ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr);
17610 ir_ref op2_ref = jit_ZVAL_ADDR(jit, op2_addr);
17611 ir_ref op3_ref = jit_ZVAL_ADDR(jit, op3_addr);
17612 jit_set_Z_TYPE_INFO(jit, res_addr,
IS_NULL);
17614 op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->
op1.
var, opline, 1);
17620 op2_ref = zend_jit_zval_check_undef(jit, op2_ref, opline->
op2.
var, opline, 1);
17626 op3_ref = zend_jit_zval_check_undef(jit, op3_ref, (opline+1)->
op1.var, opline, 1);
17632 op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref);
17635 op2_ref = jit_ZVAL_DEREF_ref(jit, op2_ref);
17638 op3_ref = jit_ZVAL_DEREF_ref(jit, op3_ref);
17643 skip_observer = jit_frameless_observer(jit, opline);
17654 bool op1_undef =
false;
17663 jit_set_Z_TYPE_INFO(jit, op1_addr,
IS_UNDEF);
17664 if (
JIT_G(current_frame)) {
17677 jit_set_Z_TYPE_INFO(jit, op2_addr,
IS_UNDEF);
17678 if (
JIT_G(current_frame)) {
17683 jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->
op1, op1_data_info,
NULL);
17684 zend_jit_check_exception(jit);
sizeof(Countable|array $value, int $mode=COUNT_NORMAL)
fprintf($stream, string $format, mixed ... $values)
array_values(array $array)
prev(array|object &$array)
header(string $header, bool $replace=true, int $response_code=0)
count(Countable|array $value, int $mode=COUNT_NORMAL)
strstr(string $haystack, string $needle, bool $before_needle=false)
memset(ptr, 0, type->size)
ir_ref ir_binding_find(const ir_ctx *ctx, ir_ref ref)
void ir_free(ir_ctx *ctx)
ir_ref ir_bind(ir_ctx *ctx, ir_ref var, ir_ref def)
ir_ref ir_emit2(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2)
void ir_build_def_use_lists(ir_ctx *ctx)
ir_ref ir_emit1(ir_ctx *ctx, uint32_t opt, ir_ref op1)
ir_ref ir_emit_N(ir_ctx *ctx, uint32_t opt, int32_t count)
ir_ref ir_unique_const_addr(ir_ctx *ctx, uintptr_t addr)
void ir_set_op(ir_ctx *ctx, ir_ref ref, int32_t n, ir_ref val)
void ir_init(ir_ctx *ctx, uint32_t flags, ir_ref consts_limit, ir_ref insns_limit)
ir_ref ir_proto_2(ir_ctx *ctx, uint8_t flags, ir_type ret_type, ir_type t1, ir_type t2)
ir_ref ir_proto_0(ir_ctx *ctx, uint8_t flags, ir_type ret_type)
#define IR_REG_SPILLED(r)
#define IR_USE_FRAME_POINTER
#define IR_START_BR_TARGET
int ir_match(ir_ctx *ctx)
#define IR_NO_STACK_COMBINE
bool ir_reg_is_int(int32_t reg)
int ir_coalesce(ir_ctx *ctx)
int ir_assign_virtual_registers(ir_ctx *ctx)
#define IR_GEN_CACHE_DEMOTE
int ir_schedule_blocks(ir_ctx *ctx)
#define IR_ENTRY_BR_TARGET
void ir_disasm_free(void)
int32_t ir_get_spill_slot_offset(ir_ctx *ctx, ir_ref ref)
int ir_find_loops(ir_ctx *ctx)
int ir_disasm(const char *name, const void *start, size_t size, bool asm_addr, ir_ctx *ctx, FILE *f)
const void * ir_emit_exitgroup(uint32_t first_exit_point, uint32_t exit_points_per_group, const void *exit_addr, ir_code_buffer *code_buffer, size_t *size_ptr)
int ir_gdb_register(const char *name, const void *start, size_t size, uint32_t sp_offset, uint32_t sp_adjustment)
void ir_dump_live_ranges(const ir_ctx *ctx, FILE *f)
int ir_build_dominators_tree(ir_ctx *ctx)
int ir_build_cfg(ir_ctx *ctx)
IR_ALWAYS_INLINE ir_ref ir_insn_op(const ir_insn *insn, int32_t n)
void ir_disasm_add_symbol(const char *name, uint64_t addr, uint64_t size)
#define IR_IS_CONST_REF(ref)
void * ir_emit_code(ir_ctx *ctx, size_t *size)
int ir_perf_jitdump_register(const char *name, const void *start, size_t size)
const char * ir_disasm_find_symbol(uint64_t addr, int64_t *offset)
IR_ALWAYS_INLINE void ir_insn_set_op(ir_insn *insn, int32_t n, ir_ref val)
int ir_compute_live_ranges(ir_ctx *ctx)
bool ir_check(const ir_ctx *ctx)
int ir_patch(const void *code, size_t size, uint32_t jmp_table_size, const void *from_addr, const void *to_addr)
void(* ir_snapshot_create_t)(ir_ctx *ctx, ir_ref addr)
struct _ir_code_buffer ir_code_buffer
#define IR_REG_SPILL_LOAD
int ir_perf_jitdump_open(void)
const char * ir_reg_name(int8_t reg, ir_type type)
#define IR_REG_SPILL_SPECIAL
void ir_gdb_unregister_all(void)
int ir_perf_jitdump_close(void)
int ir_reg_alloc(ir_ctx *ctx)
void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f)
int ir_schedule(ir_ctx *ctx)
void ir_dump_codegen(const ir_ctx *ctx, FILE *f)
void ir_perf_map_register(const char *name, const void *start, size_t size)
#define IR_MERGE_EMPTY_ENTRIES
#define IR_REGSET_PRESERVED
#define ir_RLOAD_U32(_reg)
#define ir_CONST_DOUBLE(_val)
#define ir_LOAD_U8(_addr)
#define ir_ULE(_op1, _op2)
#define ir_CASE_DEFAULT(_switch)
#define ir_END_PHI_list(_list, _val)
#define ir_MIN_U32(_op1, _op2)
#define ir_SUB_I16(_op1, _op2)
#define ir_IF(_condition)
#define ir_LE(_op1, _op2)
#define ir_PHI_N(type, _n, _inputs)
#define ir_TAILCALL(type, func)
#define ir_CONST_U8(_val)
#define ir_TRUNC_U32(_op1)
#define ir_LOAD_U32(_addr)
#define ir_MERGE_WITH(_src2)
#define ir_MERGE_2(_src1, _src2)
#define ir_LOOP_BEGIN(_src1)
#define ir_CALL(type, func)
#define ir_PHI_2(type, _src1, _src2)
#define ir_UGE(_op1, _op2)
#define ir_MERGE_WITH_EMPTY_FALSE(_if)
#define ir_UGT(_op1, _op2)
#define ir_MERGE_SET_OP(_ref, _pos, _src)
#define ir_END_list(_list)
#define ir_SHL_U32(_op1, _op2)
#define ir_OR_U32(_op1, _op2)
#define ir_RSTORE(_reg, _val)
#define ir_GUARD(_condition, _addr)
#define ir_IF_FALSE_cold(_if)
#define ir_ENTRY(_src, _num)
#define ir_STORE(_addr, _val)
#define ir_SUB_A(_op1, _op2)
#define ir_MERGE_WITH_EMPTY_TRUE(_if)
#define ir_MUL_A(_op1, _op2)
#define ir_EQ(_op1, _op2)
#define ir_AND_A(_op1, _op2)
#define ir_MERGE_N(_n, _inputs)
#define ir_AND_U32(_op1, _op2)
#define ir_CALL_4(type, func, a1, a2, a3, a4)
#define ir_BINARY_OP_D(_op, _op1, _op2)
#define ir_EXITCALL(_func)
#define ir_LOAD(_type, _addr)
#define ir_ADD_A(_op1, _op2)
#define ir_TAILCALL_1(type, func, a1)
#define ir_SHR_A(_op1, _op2)
#define ir_GT(_op1, _op2)
#define ir_ULT(_op1, _op2)
#define ir_TAILCALL_2(type, func, a1, a2)
#define ir_CALL_1(type, func, a1)
#define ir_CONST_I16(_val)
#define ir_SUB_U32(_op1, _op2)
#define ir_IF_TRUE_cold(_if)
#define ir_MUL_U32(_op1, _op2)
#define ir_CALL_2(type, func, a1, a2)
#define ir_PHI_SET_OP(_ref, _pos, _src)
#define ir_SNAPSHOT_SET_OP(_s, _pos, _v)
#define ir_OVERFLOW(_op1)
#define ir_HARD_COPY_A(_op1)
#define ir_CONST_U32(_val)
#define ir_CONST_CHAR(_val)
#define ir_ADD_U32(_op1, _op2)
#define ir_PHI_list(_list)
#define ir_GE(_op1, _op2)
#define ir_TLS(_index, _offset)
#define ir_PARAM(_type, _name, _num)
#define ir_GUARD_NOT(_condition, _addr)
#define ir_AND_U8(_op1, _op2)
#define ir_CASE_VAL(_switch, _val)
#define ir_ZEXT_U32(_op1)
#define ir_MERGE_list(_list)
#define ir_LT(_op1, _op2)
#define ir_NE(_op1, _op2)
#define ir_LOAD_I16(_addr)
#define ir_CALL_3(type, func, a1, a2, a3)
#define ir_CONST_I32(_val)
#define ir_BITCAST_A(_op1)
#define ir_RLOAD(_type, _reg)
#define ir_CALL_5(type, func, a1, a2, a3, a4, a5)
#define ir_CONST_ADDR(_val)
#define ir_DIV_A(_op1, _op2)
#define ir_CMP_OP(_op, _op1, _op2)
unsigned const char * end
#define offsetof(STRUCTURE, FIELD)
unsigned char key[REFLECTION_KEY_LEN]
int32_t fixed_stack_red_zone
int32_t fixed_stack_frame_size
ir_snapshot_create_t snapshot_create
ir_code_buffer * code_buffer
uint64_t fixed_save_regset
int32_t fixed_call_stack_size
ir_ref refs[] ZEND_ELEMENT_COUNT(count)
zend_basic_block * blocks
zend_class_entry * called_scope
zif_handler orig_internal_handler
zend_call_info * callee_info
const zend_op_array * op_array
zend_jit_trace_info * trace
bool track_last_valid_opline
bool use_last_valid_opline
const zend_op * last_valid_opline
ir_ref stub_addr[jit_last_stub]
const zend_op_array * current_op_array
uint32_t delayed_call_level
int(* stub)(zend_jit_ctx *jit)
zend_jit_ref_snapshot poly_this
zend_jit_ref_snapshot poly_func
zend_jit_exit_const * constants
zend_jit_trace_exit_info * exit_info
zend_jit_trace_stack * stack_map
uint32_t required_num_args
zend_string * function_name
zend_ssa_phi * definition_phi
zend_ssa_phi * phi_use_chain
zend_ssa_var_info * var_info
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format,...)
ZEND_API void(* zend_interrupt_function)(zend_execute_data *execute_data)
ZEND_API zend_write_func_t zend_write
ZEND_NORETURN void zend_accel_error_noreturn(int type, const char *format,...)
ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
ZEND_API void *ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
#define ZEND_MM_ALIGNED_SIZE_EX(size, alignment)
#define erealloc(ptr, size)
struct _zend_basic_block zend_basic_block
#define ZEND_BB_REACHABLE
#define RETURN_VALUE_USED(opline)
#define ZEND_BB_LOOP_HEADER
#define ZEND_BB_RECV_ENTRY
ZEND_API zend_class_entry * zend_ce_closure
struct _zend_closure zend_closure
ZEND_API bool zend_is_smart_branch(const zend_op *opline)
zend_result(ZEND_FASTCALL * binary_op_type)(zval *, zval *, zval *)
#define ZEND_CALL_CLOSURE
#define ZEND_USER_CODE(type)
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num)
#define ZEND_ACC_FAKE_CLOSURE
#define ZEND_CALL_ALLOCATED
#define ZEND_ACC_IMMUTABLE
#define ZEND_ACC_HAS_TYPE_HINTS
#define IS_SMART_BRANCH_JMPNZ
#define ZEND_INTERNAL_FUNCTION
#define ZEND_CALL_FRAME_SLOT
#define ZEND_SEND_PREFER_REF
#define ZEND_ACC_TRAIT_CLONE
#define ZEND_ACC_READONLY
#define IS_SMART_BRANCH_JMPZ
#define ZEND_ARG_SEND_MODE(arg_info)
#define ZEND_ACC_PPP_SET_MASK
ZEND_API binary_op_type get_binary_op(int opcode)
#define ZEND_CALL_NESTED_FUNCTION
#define ZEND_USER_FUNCTION
#define ZEND_CALL_HAS_SYMBOL_TABLE
#define ZEND_ACC_CALL_VIA_TRAMPOLINE
#define ZEND_ACC_GENERATOR
struct _zend_op_array zend_op_array
#define ZEND_CALL_HAS_THIS
#define ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS
struct _zend_property_info zend_property_info
#define ZEND_CALL_HAS_EXTRA_NAMED_PARAMS
#define ZEND_FETCH_DIM_WRITE
#define RT_CONSTANT(opline, node)
struct _zend_arg_info zend_arg_info
#define OP_JMP_ADDR(opline, node)
#define ZEND_CALL_DYNAMIC
#define ZEND_FETCH_OBJ_FLAGS
#define ZEND_CALL_SEND_ARG_BY_REF
#define ZEND_ACC_VARIADIC
#define ZEND_CALL_FREE_EXTRA_ARGS
#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num)
#define ZEND_CALL_MAY_HAVE_UNDEF
struct _zend_internal_function zend_internal_function
#define ZEND_ACC_DEPRECATED
#define ZEND_CALL_RELEASE_THIS
void(ZEND_FASTCALL * zif_handler)(INTERNAL_FUNCTION_PARAMETERS)
#define ARG_MAY_BE_SENT_BY_REF(zf, arg_num)
#define ZEND_OFFSET_TO_OPLINE(base, offset)
#define ZEND_CALL_FAKE_CLOSURE
ZEND_API zend_class_entry * zend_ce_arithmetic_error
ZEND_API zend_class_entry * zend_ce_division_by_zero_error
ZEND_API void ZEND_FASTCALL zend_free_extra_named_params(zend_array *extra_named_params)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(const zend_property_info *info)
ZEND_API void zend_frameless_observed_call(zend_execute_data *execute_data)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *call)
ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *execute_data)
ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *call)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_asymmetric_visibility_property_modification_error(const zend_property_info *prop_info, const char *operation)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_cannot_pass_by_reference(uint32_t arg_num)
ZEND_API void(* zend_execute_internal)(zend_execute_data *execute_data, zval *return_value)
ZEND_API void execute_ex(zend_execute_data *execute_data)
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope)
ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void)
ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_property_info *prop_info)
union _zend_function zend_function
#define ZEND_FLF_HANDLER(opline)
#define ZEND_FLF_FUNC(opline)
ZEND_API int zend_func_info_rid
ZEND_API uint32_t zend_get_func_info(const zend_call_info *call_info, const zend_ssa *ssa, zend_class_entry **ce, bool *ce_is_instanceof)
#define ZEND_FUNC_RECURSIVE_DIRECTLY
struct _zend_call_info zend_call_info
#define ZEND_FUNC_INFO(op_array)
struct _zend_func_info zend_func_info
ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
ZEND_API HashTable *ZEND_FASTCALL _zend_new_array_0(void)
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_lookup(HashTable *ht, zend_ulong h)
ZEND_API zval *ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key)
ZEND_API zval *ZEND_FASTCALL zend_hash_find_known_hash(const HashTable *ht, const zend_string *key)
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
ZEND_API zval *ZEND_FASTCALL _zend_hash_index_find(const HashTable *ht, zend_ulong h)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx)
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
#define ZEND_HASH_FOREACH_END()
#define ZEND_HASH_FOREACH_VAL(ht, _val)
ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, int write, int insert)
#define MAY_BE_PACKED_GUARD
#define MAY_BE_CLASS_GUARD
#define ZEND_JIT_LEVEL_INLINE
#define ZEND_JIT_DEBUG_PERF_DUMP
struct _zend_jit_trace_rec zend_jit_trace_rec
#define ZEND_JIT_DEBUG_IR_AFTER_SCHEDULE
#define ZEND_JIT_DEBUG_IR_AFTER_SCCP
#define ZEND_JIT_DEBUG_ASM_ADDR
#define ZEND_JIT_DEBUG_IR_FINAL
#define ZEND_JIT_DEBUG_PERF
#define ZEND_JIT_DEBUG_IR_AFTER_REGS
#define ZEND_JIT_COUNTER_INIT
#define ZEND_JIT_DEBUG_ASM_STUBS
#define ZEND_JIT_ON_HOT_TRACE
#define ZEND_JIT_DEBUG_IR_AFTER_GCM
#define ZEND_JIT_DEBUG_GDB
#define ZEND_JIT_REG_ALLOC_GLOBAL
#define ZEND_JIT_DEBUG_IR_AFTER_CFG
#define ZEND_JIT_TRACE_MAX_EXITS
#define ZEND_JIT_DEBUG_ASM
#define ZEND_JIT_DEBUG_IR_SRC
#define ZEND_JIT_DEBUG_IR_CODEGEN
#define TRACE_FRAME_IS_UNKNOWN_RETURN(frame)
#define TRACE_FRAME_IS_NESTED(frame)
#define ZEND_JIT_EXIT_CHECK_EXCEPTION
#define TRACE_FRAME_NO_NEED_RELEASE_THIS(frame)
void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend_op *opline)
#define ZEND_JIT_EXIT_CLOSURE_CALL
#define TRACE_FRAME_SET_THIS_CLASS_CHECKED(frame)
#define TRACE_FRAME_SET_THIS_CHECKED(frame)
#define ZEND_JIT_EXIT_METHOD_CALL
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(EXECUTE_DATA_D)
#define TRACE_FRAME_IS_LAST_SEND_BY_REF(frame)
zend_ulong zend_jit_profile_counter
void ZEND_FASTCALL zend_jit_undefined_string_key(EXECUTE_DATA_D)
struct _zend_jit_trace_exit_info zend_jit_trace_exit_info
#define STACK_FLAGS(_stack, _slot)
#define ZEND_JIT_EXIT_PACKED_GUARD
#define IS_TRACE_REFERENCE
zend_constant *ZEND_FASTCALL zend_jit_get_constant(const zval *key, uint32_t flags)
void ZEND_FASTCALL zend_jit_undefined_long_key(EXECUTE_DATA_D)
#define TRACE_FRAME_IS_LAST_SEND_BY_VAL(frame)
#define TRACE_FRAME_IS_CLOSURE_CALL(frame)
void ZEND_FASTCALL zend_jit_undefined_long_key_ex(zend_long key EXECUTE_DATA_DC)
#define TRACE_FRAME_SET_LAST_SEND_BY_VAL(frame)
#define TRACE_FRAME_ALWAYS_RELEASE_THIS(frame)
struct _zend_jit_trace_info zend_jit_trace_info
#define ZEND_ADDR_MEM_ZVAL(reg, offset)
bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D)
#define CLEAR_STACK_REF(_stack, _slot)
struct _zend_jit_ref_snapshot zend_jit_ref_snapshot
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(uint32_t call_info EXECUTE_DATA_DC)
@ ZEND_JIT_TRACE_DO_ICALL
@ ZEND_JIT_TRACE_INIT_CALL
int zend_jit_profile_counter_rid
#define TRACE_FRAME_IS_THIS_CHECKED(frame)
struct _zend_jit_op_array_trace_extension zend_jit_op_array_trace_extension
#define STACK_REG(_stack, _slot)
#define SET_STACK_REG_EX(_stack, _slot, _reg, _flags)
#define STACK_TYPE(_stack, _slot)
#define ZEND_JIT_EXIT_TO_VM
#define TRACE_FRAME_IS_RETURN_VALUE_USED(frame)
void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D)
#define IS_TRACE_INDIRECT
const zend_op * zend_jit_halt_op
void ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(EXECUTE_DATA_D)
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(uint32_t call_info EXECUTE_DATA_DC)
#define TRACE_FRAME_IS_RETURN_VALUE_UNUSED(frame)
#define ZEND_ADDR_REF_ZVAL(ref)
#define ZEND_JIT_EXIT_FIXED
#define ZEND_ADDR_REG(reg)
#define STACK_REF(_stack, _slot)
union _zend_jit_exit_const zend_jit_exit_const
ZEND_OPCODE_HANDLER_RET(ZEND_FASTCALL * zend_vm_opcode_handler_t)(ZEND_OPCODE_HANDLER_ARGS)
#define SET_STACK_INFO(_stack, _slot, _info)
#define ZEND_OP_TRACE_INFO(opline, offset)
struct _zend_jit_trace_stack zend_jit_trace_stack
#define TRACE_FRAME_NUM_ARGS(frame)
#define SET_STACK_REG(_stack, _slot, _reg)
#define ZEND_JIT_EXIT_FREE_OP1
struct _zend_jit_op_array_hot_extension zend_jit_op_array_hot_extension
#define STACK_MEM_TYPE(_stack, _slot)
zend_constant *ZEND_FASTCALL zend_jit_check_constant(const zval *key)
#define ZEND_JIT_EXIT_RESTORE_CALL
#define ZEND_JIT_TRACE_LOOP
#define ZEND_JIT_EXIT_POLYMORPHISM
#define TRACE_FRAME_IS_THIS_CLASS_CHECKED(frame)
#define STACK_INFO(_stack, _slot)
#define SET_STACK_REF_EX(_stack, _slot, _ref, _flags)
#define SET_STACK_REF(_stack, _slot, _ref)
#define ZEND_JIT_EXIT_FREE_OP2
#define ZEND_JIT_EXIT_INVALIDATE
struct _zend_jit_op_array_extension zend_jit_op_array_extension
#define TRACE_FRAME_SET_LAST_SEND_BY_REF(frame)
union _zend_op_trace_info zend_op_trace_info
int ZEND_FASTCALL zend_jit_trace_hot_root(zend_execute_data *execute_data, const zend_op *opline)
#define SET_STACK_TYPE(_stack, _slot, _type, _set_mem_type)
#define JIT_STUB_FORWARD(name, flags)
void * zend_jit_snapshot_handler(ir_ctx *ctx, ir_ref snapshot_ref, ir_insn *snapshot, void *addr)
#define jit_CALL(_call, _field)
struct _zend_jit_ctx zend_jit_ctx
#define ir_CONST_FUNC(_addr)
int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf *regs)
uint32_t zend_jit_duplicate_exit_point(ir_ctx *ctx, zend_jit_trace_info *t, uint32_t exit_point, ir_ref snapshot_ref)
void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
struct _Unwind_Context _Unwind_Context
#define REGISTER_HELPER(n)
#define ZEND_JIT_EXIT_POINTS_SPACING
#define JIT_STUB(name, flags)
struct _zend_jit_unwind_arg zend_jit_unwind_arg
#define ir_CAST_FC_FUNC(_addr)
struct _zend_jit_reg_var zend_jit_reg_var
struct _zend_jit_stub zend_jit_stub
#define ir_ADD_OFFSET(_addr, _offset)
uintptr_t _Unwind_GetCFA(_Unwind_Context *)
#define ir_refs_init(_name, _n)
#define JIT_STUB_ID(name, flags)
#define ir_CONST_FUNC_PROTO(_addr, _proto)
enum _jit_stub_id jit_stub_id
int _Unwind_Backtrace(_Unwind_Trace_Fn, void *)
#define ir_CONST_ADDR(_addr)
#define ir_CONST_FC_FUNC(_addr)
struct _zend_jit_registers_buf zend_jit_registers_buf
#define ZEND_JIT_EXIT_POINTS_PER_GROUP
int(* _Unwind_Trace_Fn)(_Unwind_Context *, void *)
struct _zend_string zend_string
#define ZEND_MAP_PTR_IS_OFFSET(ptr)
#define ZEND_MAP_PTR(ptr)
#define ZEND_FIRST_PROPERTY_OFFSET
ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object)
ZEND_API void ZEND_FASTCALL zend_observer_fcall_end_prechecked(zend_execute_data *execute_data, zval *return_value)
int zend_observer_fcall_op_array_extension
int zend_observer_fcall_internal_function_extension
ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin_prechecked(zend_execute_data *execute_data, zend_observer_fcall_begin_handler *handler)
#define ZEND_OBSERVER_NONE_OBSERVED
#define ZEND_OBSERVER_ENABLED
#define ZEND_OBSERVER_HANDLE(function)
ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1)
ZEND_API bool ZEND_FASTCALL zend_is_identical(const zval *op1, const zval *op2)
ZEND_API zend_result ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op2)
ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *op2)
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1)
ZEND_API zend_result ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2)
#define ALLOCA_FLAG(name)
#define zend_never_inline
#define EXPECTED(condition)
#define do_alloca(p, use_heap)
#define ZEND_UNREACHABLE()
#define free_alloca(p, use_heap)
#define UNEXPECTED(condition)
struct _zend_array zend_array
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
bool zend_accel_in_shm(void *ptr)
struct _zend_ssa_range zend_ssa_range
struct _zend_ssa zend_ssa
struct _zend_ssa_phi zend_ssa_phi
struct _zend_ssa_op zend_ssa_op
#define MAY_BE_ARRAY_OF_ANY
#define MAY_BE_ARRAY_PACKED
#define MAY_BE_ARRAY_OF_ARRAY
#define MAY_BE_ARRAY_OF_OBJECT
#define MAY_BE_ARRAY_SHIFT
#define MAY_BE_ARRAY_KEY_STRING
#define MAY_BE_ARRAY_OF_REF
#define MAY_BE_ARRAY_OF_RESOURCE
#define MAY_BE_ARRAY_KEY_LONG
#define MAY_BE_ARRAY_KEY_ANY
#define MAY_BE_ARRAY_NUMERIC_HASH
#define MAY_BE_ARRAY_OF_STRING
#define ZEND_TYPE_PURE_MASK(t)
#define Z_STRVAL_P(zval_p)
#define Z_ARRVAL_P(zval_p)
#define Z_REFCOUNTED_P(zval_p)
struct _zend_array HashTable
#define IS_TYPE_COLLECTABLE
#define Z_TYPE_INFO_P(zval_p)
#define ZEND_TYPE_FULL_MASK(t)
#define Z_STRLEN_P(zval_p)
#define Z_CONSTANT_P(zval_p)
#define Z_TYPE_FLAGS_MASK
#define ZEND_TYPE_IS_SET(t)
struct _zend_refcounted zend_refcounted
#define Z_TYPE_FLAGS_P(zval_p)
#define GC_NOT_COLLECTABLE
struct _zend_execute_data zend_execute_data
#define Z_EXTRA_P(zval_p)
struct _zend_reference zend_reference
ZEND_API void ZEND_FASTCALL rc_dtor_func(zend_refcounted *p)
ZEND_API const void *ZEND_FASTCALL zend_get_opcode_handler_func(const zend_op *op)
ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler(zend_op *opcode)
ZEND_API int zend_vm_kind(void)
zend_property_info * prop_info
fbc internal_function handler(call, ret)
function(EX_VAR(opline->result.var))
#define ZEND_IS_IDENTICAL
#define ZEND_FETCH_CONSTANT
#define ZEND_ASSIGN_DIM_OP
#define ZEND_ASSIGN_STATIC_PROP_REF
#define ZEND_FETCH_LIST_R
#define ZEND_INCLUDE_OR_EVAL
#define ZEND_GENERATOR_CREATE
#define ZEND_FETCH_LIST_W
#define ZEND_RETURN_BY_REF
#define ZEND_SWITCH_STRING
#define ZEND_FETCH_OBJ_FUNC_ARG
#define ZEND_ASSIGN_STATIC_PROP_OP
#define ZEND_EXT_FCALL_BEGIN
#define ZEND_HANDLE_EXCEPTION
#define ZEND_IS_NOT_EQUAL
#define ZEND_IS_NOT_IDENTICAL
#define ZEND_FETCH_OBJ_IS
#define ZEND_POST_DEC_OBJ
#define ZEND_VM_KIND_HYBRID
#define ZEND_FRAMELESS_ICALL_3
#define ZEND_INIT_NS_FCALL_BY_NAME
#define ZEND_ASSIGN_STATIC_PROP
#define ZEND_IS_SMALLER_OR_EQUAL
#define ZEND_INIT_FCALL_BY_NAME
#define ZEND_SEND_VAR_NO_REF_EX
#define ZEND_SEND_FUNC_ARG
#define ZEND_CHECK_UNDEF_ARGS
#define ZEND_ISSET_ISEMPTY_DIM_OBJ
#define ZEND_BIND_INIT_STATIC_OR_JMP
#define ZEND_GENERATOR_RETURN
#define ZEND_ASSIGN_OBJ_OP
#define ZEND_ASSIGN_OBJ_REF
#define ZEND_FETCH_DIM_IS
#define ZEND_VERIFY_NEVER_TYPE
#define ZEND_FETCH_DIM_UNSET
#define ZEND_SEND_VAR_NO_REF
#define ZEND_POST_INC_OBJ
#define ZEND_DO_FCALL_BY_NAME
#define ZEND_INIT_METHOD_CALL
#define ZEND_FETCH_DIM_RW
#define ZEND_VM_KIND_CALL
#define ZEND_WORKLIST_ALLOCA(w, _len, use_heap)
struct _zend_worklist zend_worklist
#define ZEND_WORKLIST_FREE_ALLOCA(w, use_heap)