From 8a9d933a1b82fd63ce2add3f961d181337c05776 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 6 Dec 2023 22:39:23 +0100 Subject: [PATCH 1/2] Implement stackless internal function calls --- Zend/Optimizer/block_pass.c | 1 + Zend/Optimizer/compact_literals.c | 1 + Zend/Optimizer/dce.c | 5 + Zend/Optimizer/dfa_pass.c | 1 + Zend/Optimizer/pass1.c | 1 + Zend/Optimizer/sccp.c | 75 +- Zend/Optimizer/zend_call_graph.c | 27 +- Zend/Optimizer/zend_call_graph.h | 1 + Zend/Optimizer/zend_cfg.c | 2 + Zend/Optimizer/zend_dfg.c | 1 + Zend/Optimizer/zend_dump.c | 5 + Zend/Optimizer/zend_func_info.c | 2 + Zend/Optimizer/zend_inference.c | 33 + Zend/Optimizer/zend_optimizer.c | 4 + Zend/Optimizer/zend_ssa.c | 29 + Zend/tests/frameless_jmp_001.phpt | 12 + Zend/tests/frameless_jmp_002.phpt | 9 + Zend/tests/frameless_jmp_003.phpt | 8 + Zend/tests/frameless_jmp_004.phpt | 19 + Zend/tests/frameless_jmp_005.phpt | 9 + Zend/tests/frameless_throwing_destructor.phpt | 18 + Zend/tests/frameless_undefined_var.phpt | 18 + Zend/zend.c | 7 + Zend/zend_API.c | 48 +- Zend/zend_API.h | 88 +- Zend/zend_builtin_functions.c | 169 +++- Zend/zend_builtin_functions.stub.php | 9 +- Zend/zend_builtin_functions_arginfo.h | 20 +- Zend/zend_compile.c | 203 +++- Zend/zend_compile.h | 7 + Zend/zend_execute.c | 1 + Zend/zend_execute.h | 12 + Zend/zend_execute_API.c | 24 +- Zend/zend_frameless_function.c | 24 + Zend/zend_frameless_function.h | 133 +++ Zend/zend_opcode.c | 1 + Zend/zend_vm_def.h | 141 +++ Zend/zend_vm_execute.h | 368 +++++-- Zend/zend_vm_gen.php | 2 +- Zend/zend_vm_handlers.h | 921 +++++++++--------- Zend/zend_vm_opcodes.c | 14 +- Zend/zend_vm_opcodes.h | 7 +- build/gen_stub.php | 75 +- configure.ac | 1 + ext/opcache/jit/zend_jit.c | 24 + ext/opcache/jit/zend_jit_helpers.c | 8 + ext/opcache/jit/zend_jit_ir.c | 184 ++++ ext/opcache/jit/zend_jit_trace.c | 46 + ext/opcache/tests/ct_eval_frameless_001.phpt | 21 + ext/opcache/tests/ct_eval_frameless_002.phpt | 24 + ext/opcache/tests/ct_eval_frameless_003.phpt | 15 + .../tests/opt/inference_frameless.phpt | 28 + ext/pcre/php_pcre.c | 103 +- ext/pcre/php_pcre.stub.php | 6 +- ext/pcre/php_pcre_arginfo.h | 18 +- ext/standard/array.c | 139 ++- ext/standard/basic_functions.c | 1 + ext/standard/basic_functions.stub.php | 55 +- ext/standard/basic_functions_arginfo.h | 138 ++- ext/standard/math.c | 11 + ext/standard/string.c | 538 ++++++++-- ext/standard/type.c | 30 +- ext/zend_test/tests/observer_frameless.phpt | 17 + win32/build/config.w32 | 2 +- 64 files changed, 3137 insertions(+), 827 deletions(-) create mode 100644 Zend/tests/frameless_jmp_001.phpt create mode 100644 Zend/tests/frameless_jmp_002.phpt create mode 100644 Zend/tests/frameless_jmp_003.phpt create mode 100644 Zend/tests/frameless_jmp_004.phpt create mode 100644 Zend/tests/frameless_jmp_005.phpt create mode 100644 Zend/tests/frameless_throwing_destructor.phpt create mode 100644 Zend/tests/frameless_undefined_var.phpt create mode 100644 Zend/zend_frameless_function.c create mode 100644 Zend/zend_frameless_function.h create mode 100644 ext/opcache/tests/ct_eval_frameless_001.phpt create mode 100644 ext/opcache/tests/ct_eval_frameless_002.phpt create mode 100644 ext/opcache/tests/ct_eval_frameless_003.phpt create mode 100644 ext/opcache/tests/opt/inference_frameless.phpt create mode 100644 ext/zend_test/tests/observer_frameless.phpt diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index c504cdd655dad..cd6dce6a5c10a 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -1017,6 +1017,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start); break; case ZEND_CATCH: diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index 9248f0b822441..01eb37d7081bb 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -770,6 +770,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_CLASS_DELAYED: + case ZEND_JMP_FRAMELESS: opline->extended_value = cache_size; cache_size += sizeof(void *); break; diff --git a/Zend/Optimizer/dce.c b/Zend/Optimizer/dce.c index 219b139cfc874..414abe01f96ac 100644 --- a/Zend/Optimizer/dce.c +++ b/Zend/Optimizer/dce.c @@ -146,6 +146,7 @@ static inline bool may_have_side_effects( case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: /* For our purposes a jumps and branches are side effects. */ return 1; case ZEND_BEGIN_SILENCE: @@ -167,6 +168,10 @@ static inline bool may_have_side_effects( case ZEND_DO_FCALL_BY_NAME: case ZEND_DO_ICALL: case ZEND_DO_UCALL: + case ZEND_FRAMELESS_ICALL_0: + case ZEND_FRAMELESS_ICALL_1: + case ZEND_FRAMELESS_ICALL_2: + case ZEND_FRAMELESS_ICALL_3: /* For now assume all calls have side effects */ return 1; case ZEND_RECV: diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index b1f568da5d920..b43b5fb8296cb 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -653,6 +653,7 @@ static void zend_ssa_replace_control_link(zend_op_array *op_array, zend_ssa *ssa case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: if (ZEND_OP2_JMP_ADDR(opline) == op_array->opcodes + old->start) { ZEND_SET_OP_JMP_ADDR(opline, opline->op2, op_array->opcodes + dst->start); } diff --git a/Zend/Optimizer/pass1.c b/Zend/Optimizer/pass1.c index 4c8a03b4a4085..60094eee4f60b 100644 --- a/Zend/Optimizer/pass1.c +++ b/Zend/Optimizer/pass1.c @@ -355,6 +355,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) case ZEND_JMP_NULL: case ZEND_VERIFY_NEVER_TYPE: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: collect_constants = 0; break; } diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index d5486803e19a6..c86672a8dd248 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -789,14 +789,10 @@ static bool can_ct_eval_func_call(zend_function *func, zend_string *name, uint32 /* The functions chosen here are simple to implement and either likely to affect a branch, * or just happened to be commonly used with constant operands in WP (need to test other * applications as well, of course). */ -static inline zend_result ct_eval_func_call( - zend_op_array *op_array, zval *result, zend_string *name, uint32_t num_args, zval **args) { +static inline zend_result ct_eval_func_call_ex( + zend_op_array *op_array, zval *result, zend_function *func, uint32_t num_args, zval **args) { uint32_t i; - zend_function *func = zend_hash_find_ptr(CG(function_table), name); - if (!func || func->type != ZEND_INTERNAL_FUNCTION) { - return FAILURE; - } - + zend_string *name = func->common.function_name; if (num_args == 1 && Z_TYPE_P(args[0]) == IS_STRING && zend_optimizer_eval_special_func_call(result, name, Z_STR_P(args[0])) == SUCCESS) { return SUCCESS; @@ -855,6 +851,15 @@ static inline zend_result ct_eval_func_call( return retval; } +static inline zend_result ct_eval_func_call( + zend_op_array *op_array, zval *result, zend_string *name, uint32_t num_args, zval **args) { + zend_function *func = zend_hash_find_ptr(CG(function_table), name); + if (!func || func->type != ZEND_INTERNAL_FUNCTION) { + return FAILURE; + } + return ct_eval_func_call_ex(op_array, result, func, num_args, args); +} + #define SET_RESULT(op, zv) do { \ if (ssa_op->op##_def >= 0) { \ set_value(scdf, ctx, ssa_op->op##_def, zv); \ @@ -1708,6 +1713,51 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o SET_RESULT_BOT(result); break; } + case ZEND_FRAMELESS_ICALL_0: + case ZEND_FRAMELESS_ICALL_1: + case ZEND_FRAMELESS_ICALL_2: + case ZEND_FRAMELESS_ICALL_3: { + /* We already know it can't be evaluated, don't bother checking again */ + if (ssa_op->result_def < 0 || IS_BOT(&ctx->values[ssa_op->result_def])) { + break; + } + + zval *args[3] = {NULL}; + zend_function *func = ZEND_FLF_FUNC(opline); + uint32_t num_args = ZEND_FLF_NUM_ARGS(opline->opcode); + + switch (num_args) { + case 3: { + zend_op *op_data = opline + 1; + args[2] = get_op1_value(ctx, op_data, &ctx->scdf.ssa->ops[op_data - ctx->scdf.op_array->opcodes]); + ZEND_FALLTHROUGH; + } + case 2: + args[1] = get_op2_value(ctx, opline, &ctx->scdf.ssa->ops[opline - ctx->scdf.op_array->opcodes]); + ZEND_FALLTHROUGH; + case 1: + args[0] = get_op1_value(ctx, opline, &ctx->scdf.ssa->ops[opline - ctx->scdf.op_array->opcodes]); + break; + } + for (uint32_t i = 0; i < num_args; i++) { + if (!args[i]) { + SET_RESULT_BOT(result); + return; + } else if (IS_BOT(args[i]) || IS_PARTIAL_ARRAY(args[i])) { + SET_RESULT_BOT(result); + return; + } else if (IS_TOP(args[i])) { + return; + } + } + if (ct_eval_func_call_ex(scdf->op_array, &zv, func, num_args, args) == SUCCESS) { + SET_RESULT(result, &zv); + zval_ptr_dtor_nogc(&zv); + break; + } + SET_RESULT_BOT(result); + break; + } default: { /* If we have no explicit implementation return BOT */ @@ -2155,7 +2205,13 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, if (opline->opcode == ZEND_DO_ICALL) { removed_ops = remove_call(ctx, opline, ssa_op) - 1; } else { + bool has_op_data = opline->opcode == ZEND_FRAMELESS_ICALL_3; zend_ssa_remove_instr(ssa, opline, ssa_op); + removed_ops++; + if (has_op_data) { + zend_ssa_remove_instr(ssa, opline + 1, ssa_op + 1); + removed_ops++; + } } ssa_op->result_def = var_num; opline->opcode = ZEND_QM_ASSIGN; @@ -2191,8 +2247,13 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, if (opline->opcode == ZEND_DO_ICALL) { removed_ops = remove_call(ctx, opline, ssa_op); } else { + bool has_op_data = opline->opcode == ZEND_FRAMELESS_ICALL_3; zend_ssa_remove_instr(ssa, opline, ssa_op); removed_ops++; + if (has_op_data) { + zend_ssa_remove_instr(ssa, opline + 1, ssa_op + 1); + removed_ops++; + } } } } else if (ssa_op->op1_def == var_num) { diff --git a/Zend/Optimizer/zend_call_graph.c b/Zend/Optimizer/zend_call_graph.c index c2b7b00cbee13..5db8d06674b59 100644 --- a/Zend/Optimizer/zend_call_graph.c +++ b/Zend/Optimizer/zend_call_graph.c @@ -73,6 +73,7 @@ ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32 call_info->num_args = opline->extended_value; call_info->next_callee = func_info->callee_info; call_info->is_prototype = is_prototype; + call_info->is_frameless = false; func_info->callee_info = call_info; if (build_flags & ZEND_CALL_TREE) { @@ -102,6 +103,24 @@ ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32 call_info = NULL; call++; break; + case ZEND_FRAMELESS_ICALL_0: + case ZEND_FRAMELESS_ICALL_1: + case ZEND_FRAMELESS_ICALL_2: + case ZEND_FRAMELESS_ICALL_3: { + func = ZEND_FLF_FUNC(opline); + zend_call_info *call_info = zend_arena_calloc(arena, 1, sizeof(zend_call_info)); + call_info->caller_op_array = op_array; + call_info->caller_init_opline = opline; + call_info->caller_call_opline = NULL; + call_info->callee_func = func; + call_info->num_args = ZEND_FLF_NUM_ARGS(opline->opcode); + call_info->next_callee = func_info->callee_info; + call_info->is_prototype = false; + call_info->is_frameless = true; + call_info->next_caller = NULL; + func_info->callee_info = call_info; + break; + } case ZEND_DO_FCALL: case ZEND_DO_ICALL: case ZEND_DO_UCALL: @@ -260,9 +279,11 @@ ZEND_API zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info if (call->caller_call_opline) { map[call->caller_call_opline - op_array->opcodes] = call; } - for (i = 0; i < call->num_args; i++) { - if (call->arg_info[i].opline) { - map[call->arg_info[i].opline - op_array->opcodes] = call; + if (!call->is_frameless) { + for (i = 0; i < call->num_args; i++) { + if (call->arg_info[i].opline) { + map[call->arg_info[i].opline - op_array->opcodes] = call; + } } } } diff --git a/Zend/Optimizer/zend_call_graph.h b/Zend/Optimizer/zend_call_graph.h index 3a02425084d58..b2cbb6822bcf3 100644 --- a/Zend/Optimizer/zend_call_graph.h +++ b/Zend/Optimizer/zend_call_graph.h @@ -38,6 +38,7 @@ struct _zend_call_info { bool send_unpack; /* Parameters passed by SEND_UNPACK or SEND_ARRAY */ bool named_args; /* Function has named arguments */ bool is_prototype; /* An overridden child method may be called */ + bool is_frameless; /* A frameless function sends arguments through operands */ int num_args; /* Number of arguments, excluding named and variadic arguments */ zend_send_arg_info arg_info[1]; }; diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index ce7d078bb957e..4d3d62137b9e3 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -370,6 +370,7 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes); BB_START(i + 1); break; @@ -524,6 +525,7 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: block->successors_count = 2; block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]; block->successors[1] = j + 1; diff --git a/Zend/Optimizer/zend_dfg.c b/Zend/Optimizer/zend_dfg.c index 93faec6a4d86d..101523141be94 100644 --- a/Zend/Optimizer/zend_dfg.c +++ b/Zend/Optimizer/zend_dfg.c @@ -122,6 +122,7 @@ static zend_always_inline void _zend_dfg_add_use_def_op(const zend_op_array *op_ } break; case ZEND_ASSIGN_STATIC_PROP_OP: + case ZEND_FRAMELESS_ICALL_3: next = opline + 1; if (next->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { var_num = EX_VAR_TO_NUM(next->op1.var); diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index 1001a935d80a4..0c91815280098 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -462,6 +462,11 @@ ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block } else { fprintf(stderr, "OP_%d", (int)opline->opcode); } + + if (ZEND_OP_IS_FRAMELESS_ICALL(opline->opcode)) { + zend_function *func = ZEND_FLF_FUNC(opline); + fprintf(stderr, "(%s)", ZSTR_VAL(func->common.function_name)); + } if (ZEND_VM_EXT_NUM == (flags & ZEND_VM_EXT_MASK)) { fprintf(stderr, " %u", opline->extended_value); diff --git a/Zend/Optimizer/zend_func_info.c b/Zend/Optimizer/zend_func_info.c index 69238c1458bb2..7ce11c2c8772a 100644 --- a/Zend/Optimizer/zend_func_info.c +++ b/Zend/Optimizer/zend_func_info.c @@ -51,6 +51,8 @@ typedef struct _func_info_t { static uint32_t zend_range_info(const zend_call_info *call_info, const zend_ssa *ssa) { + ZEND_ASSERT(!call_info->is_frameless); + if (!call_info->send_unpack && (call_info->num_args == 2 || call_info->num_args == 3) && ssa diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 75d8183624bf7..8e0bd0e82aed7 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3849,6 +3849,38 @@ static zend_always_inline zend_result _zend_update_type_info( UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_op->result_def); } break; + case ZEND_FRAMELESS_ICALL_1: + case ZEND_FRAMELESS_ICALL_2: + case ZEND_FRAMELESS_ICALL_3: + if (ssa_op->op1_def >= 0) { + ZEND_ASSERT(ssa_op->op1_use >= 0); + tmp = ssa->var_info[ssa_op->op1_use].type; + if (tmp & MAY_BE_RC1) { + tmp |= MAY_BE_RCN; + } + UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); + } + if (ssa_op->op2_def >= 0) { + ZEND_ASSERT(ssa_op->op2_use >= 0); + tmp = ssa->var_info[ssa_op->op2_use].type; + if (tmp & MAY_BE_RC1) { + tmp |= MAY_BE_RCN; + } + UPDATE_SSA_TYPE(tmp, ssa_op->op2_def); + } + if (opline->opcode == ZEND_FRAMELESS_ICALL_3) { + zend_ssa_op *next_ssa_op = ssa_op + 1; + if (next_ssa_op->op1_def >= 0) { + ZEND_ASSERT(next_ssa_op->op1_use >= 0); + tmp = ssa->var_info[next_ssa_op->op1_use].type; + if (tmp & MAY_BE_RC1) { + tmp |= MAY_BE_RCN; + } + UPDATE_SSA_TYPE(tmp, next_ssa_op->op1_def); + } + } + ZEND_FALLTHROUGH; + case ZEND_FRAMELESS_ICALL_0: case ZEND_DO_FCALL: case ZEND_DO_ICALL: case ZEND_DO_UCALL: @@ -4989,6 +5021,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op case ZEND_COPY_TMP: case ZEND_CASE_STRICT: case ZEND_JMP_NULL: + case ZEND_JMP_FRAMELESS: return 0; case ZEND_SEND_VAR: case ZEND_SEND_VAL: diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index a489c5825e858..5816584edb173 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -721,6 +721,7 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op2, ZEND_OP2_JMP_ADDR(opline)); break; case ZEND_FE_FETCH_R: @@ -765,6 +766,7 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_ case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]); break; case ZEND_CATCH: @@ -1164,6 +1166,7 @@ static void zend_redo_pass_two(zend_op_array *op_array) case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; break; case ZEND_CATCH: @@ -1285,6 +1288,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa) case ZEND_ASSERT_CHECK: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; break; case ZEND_CATCH: diff --git a/Zend/Optimizer/zend_ssa.c b/Zend/Optimizer/zend_ssa.c index fd699620de2e7..4c09e5e105b50 100644 --- a/Zend/Optimizer/zend_ssa.c +++ b/Zend/Optimizer/zend_ssa.c @@ -766,6 +766,35 @@ static zend_always_inline int _zend_ssa_rename_op(const zend_op_array *op_array, //NEW_SSA_VAR(opline->op1.var) } break; + case ZEND_FRAMELESS_ICALL_1: + case ZEND_FRAMELESS_ICALL_2: + case ZEND_FRAMELESS_ICALL_3: { + if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op1_type == IS_CV) { + ssa_ops[k].op1_def = ssa_vars_count; + var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count; + ssa_vars_count++; + //NEW_SSA_VAR(opline->op1.var) + } + if ((build_flags & ZEND_SSA_RC_INFERENCE) && opline->op2_type == IS_CV) { + ssa_ops[k].op2_def = ssa_vars_count; + var[EX_VAR_TO_NUM(opline->op2.var)] = ssa_vars_count; + ssa_vars_count++; + //NEW_SSA_VAR(opline->op2.var) + } + if (opline->opcode == ZEND_FRAMELESS_ICALL_3) { + next = opline + 1; + if (next->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { + ssa_ops[k + 1].op1_use = var[EX_VAR_TO_NUM(next->op1.var)]; + //USE_SSA_VAR(op_array->last_var + next->op1.var); + if ((build_flags & ZEND_SSA_RC_INFERENCE) && next->op1_type == IS_CV) { + ssa_ops[k + 1].op1_def = ssa_vars_count; + var[EX_VAR_TO_NUM(next->op1.var)] = ssa_vars_count; + ssa_vars_count++; + //NEW_SSA_VAR(next->op1.var) + } + } + } + } default: break; } diff --git a/Zend/tests/frameless_jmp_001.phpt b/Zend/tests/frameless_jmp_001.phpt new file mode 100644 index 0000000000000..5e485770269ca --- /dev/null +++ b/Zend/tests/frameless_jmp_001.phpt @@ -0,0 +1,12 @@ +--TEST-- +Frameless jmp +--FILE-- + +--EXPECT-- +bool(true) diff --git a/Zend/tests/frameless_jmp_002.phpt b/Zend/tests/frameless_jmp_002.phpt new file mode 100644 index 0000000000000..62ea17a83f045 --- /dev/null +++ b/Zend/tests/frameless_jmp_002.phpt @@ -0,0 +1,9 @@ +--TEST-- +Frameless jmp +--FILE-- + +--EXPECT-- +bool(false) diff --git a/Zend/tests/frameless_jmp_003.phpt b/Zend/tests/frameless_jmp_003.phpt new file mode 100644 index 0000000000000..fd457c7c4352d --- /dev/null +++ b/Zend/tests/frameless_jmp_003.phpt @@ -0,0 +1,8 @@ +--TEST-- +Frameless jmp +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/frameless_jmp_004.phpt b/Zend/tests/frameless_jmp_004.phpt new file mode 100644 index 0000000000000..cea7348b86ae7 --- /dev/null +++ b/Zend/tests/frameless_jmp_004.phpt @@ -0,0 +1,19 @@ +--TEST-- +Frameless jmp +--FILE-- + +--EXPECT-- +bool(false) +string(16) "Foo\class_exists" +bool(true) diff --git a/Zend/tests/frameless_jmp_005.phpt b/Zend/tests/frameless_jmp_005.phpt new file mode 100644 index 0000000000000..fd57ffb5a6634 --- /dev/null +++ b/Zend/tests/frameless_jmp_005.phpt @@ -0,0 +1,9 @@ +--TEST-- +Frameless jmp +--FILE-- + +--EXPECT-- +string(0) "" diff --git a/Zend/tests/frameless_throwing_destructor.phpt b/Zend/tests/frameless_throwing_destructor.phpt new file mode 100644 index 0000000000000..ad555d860e664 --- /dev/null +++ b/Zend/tests/frameless_throwing_destructor.phpt @@ -0,0 +1,18 @@ +--TEST-- +Frameless call with throwing destructor +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:%d +Stack trace: +#0 %s(%d): Bar->__destruct() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/frameless_undefined_var.phpt b/Zend/tests/frameless_undefined_var.phpt new file mode 100644 index 0000000000000..e9c5aac58236f --- /dev/null +++ b/Zend/tests/frameless_undefined_var.phpt @@ -0,0 +1,18 @@ +--TEST-- +Undefined var in frameless call +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Undefined variable $foo diff --git a/Zend/zend.c b/Zend/zend.c index a13884e5516ab..db5caa8195089 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1131,6 +1131,13 @@ void zend_shutdown(void) /* {{{ */ /* Child classes may reuse structures from parent classes, so destroy in reverse order. */ zend_hash_graceful_reverse_destroy(GLOBAL_CLASS_TABLE); + zend_flf_capacity = 0; + zend_flf_count = 0; + free(zend_flf_functions); + free(zend_flf_handlers); + zend_flf_functions = NULL; + zend_flf_handlers = NULL; + zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE); free(GLOBAL_AUTO_GLOBALS_TABLE); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index d6f24a8f3010b..884eecc61c418 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -467,7 +467,7 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **p /* }}} */ static ZEND_COLD bool zend_null_arg_deprecated(const char *fallback_type, uint32_t arg_num) { - zend_function *func = EG(current_execute_data)->func; + zend_function *func = zend_active_function(); ZEND_ASSERT(arg_num > 0); uint32_t arg_offset = arg_num - 1; if (arg_offset >= func->common.num_args) { @@ -518,6 +518,14 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_slow(const zval *arg, bool *dest } /* }}} */ +ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_bool_slow(const zval *arg, bool *dest, uint32_t arg_num) +{ + if (UNEXPECTED(ZEND_FLF_ARG_USES_STRICT_TYPES())) { + return 0; + } + return zend_parse_arg_bool_weak(arg, dest, arg_num); +} + ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(const zval *arg, zend_long *dest, uint32_t arg_num) /* {{{ */ { if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) { @@ -597,6 +605,14 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_slow(const zval *arg, zend_long } /* }}} */ +ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_long_slow(const zval *arg, zend_long *dest, uint32_t arg_num) +{ + if (UNEXPECTED(ZEND_FLF_ARG_USES_STRICT_TYPES())) { + return 0; + } + return zend_parse_arg_long_weak(arg, dest, arg_num); +} + ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double *dest, uint32_t arg_num) /* {{{ */ { if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) { @@ -738,6 +754,14 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **des } /* }}} */ +ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num) +{ + if (UNEXPECTED(ZEND_FLF_ARG_USES_STRICT_TYPES())) { + return 0; + } + return zend_parse_arg_str_weak(arg, dest, arg_num); +} + ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num) /* {{{ */ { if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) { @@ -2828,6 +2852,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend internal_function->scope = scope; internal_function->prototype = NULL; internal_function->attributes = NULL; + internal_function->frameless_function_infos = ptr->frameless_function_infos; if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size())); } else { @@ -2931,6 +2956,27 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend zend_string_release(lowercase_name); break; } + if (reg_function->frameless_function_infos) { + const zend_frameless_function_info *flf_info = reg_function->frameless_function_infos; + while (flf_info->handler) { + if (zend_flf_count == zend_flf_capacity) { + if (!zend_flf_capacity) { + zend_flf_capacity = 8; + } else { + zend_flf_capacity *= 2; + } + /* +1 for NULL terminator */ + zend_flf_handlers = realloc(zend_flf_handlers, (zend_flf_capacity + 1) * sizeof(void *)); + zend_flf_functions = realloc(zend_flf_functions, (zend_flf_capacity + 1) * sizeof(zend_function *)); + } + zend_flf_handlers[zend_flf_count] = flf_info->handler; + zend_flf_functions[zend_flf_count] = (zend_function *)reg_function; + zend_flf_count++; + flf_info++; + } + zend_flf_handlers[zend_flf_count] = NULL; + zend_flf_functions[zend_flf_count] = NULL; + } /* Get parameter count including variadic parameter. */ uint32_t num_args = reg_function->num_args; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 6e44cdd7628b0..7583dca6f7814 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -28,7 +28,7 @@ #include "zend_variables.h" #include "zend_execute.h" #include "zend_type_info.h" - +#include "zend_frameless_function.h" BEGIN_EXTERN_C() @@ -38,6 +38,7 @@ typedef struct _zend_function_entry { const struct _zend_internal_arg_info *arg_info; uint32_t num_args; uint32_t flags; + const zend_frameless_function_info *frameless_function_infos; } zend_function_entry; typedef struct _zend_fcall_info { @@ -73,29 +74,31 @@ typedef struct _zend_fcall_info_cache { #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(zif_##name) #define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(zim_##classname##_##name) -#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags }, +#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags, NULL }, -#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags }, +#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags, frameless_function_infos) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags, frameless_function_infos }, /* Same as ZEND_NAMED_FE */ -#define ZEND_RAW_NAMED_FE(zend_name, name, arg_info) ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0) +#define ZEND_RAW_NAMED_FE(zend_name, name, arg_info) ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0, NULL) -#define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0) -#define ZEND_FE(name, arg_info) ZEND_RAW_FENTRY(#name, zif_##name, arg_info, 0) -#define ZEND_DEP_FE(name, arg_info) ZEND_RAW_FENTRY(#name, zif_##name, arg_info, ZEND_ACC_DEPRECATED) -#define ZEND_FALIAS(name, alias, arg_info) ZEND_RAW_FENTRY(#name, zif_##alias, arg_info, 0) -#define ZEND_DEP_FALIAS(name, alias, arg_info) ZEND_RAW_FENTRY(#name, zif_##alias, arg_info, ZEND_ACC_DEPRECATED) +#define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0, NULL) +#define ZEND_FE(name, arg_info) ZEND_RAW_FENTRY(#name, zif_##name, arg_info, 0, NULL) +#define ZEND_DEP_FE(name, arg_info) ZEND_RAW_FENTRY(#name, zif_##name, arg_info, ZEND_ACC_DEPRECATED, NULL) +#define ZEND_FALIAS(name, alias, arg_info) ZEND_RAW_FENTRY(#name, zif_##alias, arg_info, 0, NULL) +#define ZEND_DEP_FALIAS(name, alias, arg_info) ZEND_RAW_FENTRY(#name, zif_##alias, arg_info, ZEND_ACC_DEPRECATED, NULL) #define ZEND_NAMED_ME(zend_name, name, arg_info, flags) ZEND_FENTRY(zend_name, name, arg_info, flags) -#define ZEND_ME(classname, name, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##name, arg_info, flags) -#define ZEND_DEP_ME(classname, name, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##name, arg_info, flags | ZEND_ACC_DEPRECATED) -#define ZEND_ABSTRACT_ME(classname, name, arg_info) ZEND_RAW_FENTRY(#name, NULL, arg_info, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) -#define ZEND_ABSTRACT_ME_WITH_FLAGS(classname, name, arg_info, flags) ZEND_RAW_FENTRY(#name, NULL, arg_info, flags) -#define ZEND_MALIAS(classname, name, alias, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##alias, arg_info, flags) -#define ZEND_ME_MAPPING(name, func_name, arg_info, flags) ZEND_RAW_FENTRY(#name, zif_##func_name, arg_info, flags) - -#define ZEND_NS_FENTRY(ns, zend_name, name, arg_info, flags) ZEND_RAW_FENTRY(ZEND_NS_NAME(ns, #zend_name), name, arg_info, flags) - -#define ZEND_NS_RAW_FENTRY(ns, zend_name, name, arg_info, flags) ZEND_RAW_FENTRY(ZEND_NS_NAME(ns, zend_name), name, arg_info, flags) +#define ZEND_ME(classname, name, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##name, arg_info, flags, NULL) +#define ZEND_DEP_ME(classname, name, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##name, arg_info, flags | ZEND_ACC_DEPRECATED, NULL) +#define ZEND_ABSTRACT_ME(classname, name, arg_info) ZEND_RAW_FENTRY(#name, NULL, arg_info, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL) +#define ZEND_ABSTRACT_ME_WITH_FLAGS(classname, name, arg_info, flags) ZEND_RAW_FENTRY(#name, NULL, arg_info, flags, NULL) +#define ZEND_MALIAS(classname, name, alias, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##alias, arg_info, flags, NULL) +#define ZEND_ME_MAPPING(name, func_name, arg_info, flags) ZEND_RAW_FENTRY(#name, zif_##func_name, arg_info, flags, NULL) +#define ZEND_FRAMELESS_FE(name, arg_info, flags, frameless_function_infos) \ + { #name, zif_##name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags, frameless_function_infos }, + +#define ZEND_NS_FENTRY(ns, zend_name, name, arg_info, flags) ZEND_RAW_FENTRY(ZEND_NS_NAME(ns, #zend_name), name, arg_info, flags, NULL) + +#define ZEND_NS_RAW_FENTRY(ns, zend_name, name, arg_info, flags) ZEND_RAW_FENTRY(ZEND_NS_NAME(ns, zend_name), name, arg_info, flags, NULL) /** * Note that if you are asserting that a function is compile-time evaluable, you are asserting that * @@ -106,7 +109,7 @@ typedef struct _zend_fcall_info_cache { * 4. The function will not take an unreasonable amount of time or memory to compute on code that may be seen in practice. * (e.g. str_repeat is special cased to check the length instead of using this) */ -#define ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(name, arg_info) ZEND_RAW_FENTRY(#name, zif_##name, arg_info, ZEND_ACC_COMPILE_TIME_EVAL) +#define ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(name, arg_info) ZEND_RAW_FENTRY(#name, zif_##name, arg_info, ZEND_ACC_COMPILE_TIME_EVAL, NULL) /* Same as ZEND_NS_NAMED_FE */ #define ZEND_NS_RAW_NAMED_FE(ns, zend_name, name, arg_info) ZEND_NS_RAW_FENTRY(ns, #zend_name, name, arg_info, 0) @@ -117,7 +120,7 @@ typedef struct _zend_fcall_info_cache { #define ZEND_NS_FALIAS(ns, name, alias, arg_info) ZEND_NS_RAW_FENTRY(ns, #name, zif_##alias, arg_info, 0) #define ZEND_NS_DEP_FALIAS(ns, name, alias, arg_info) ZEND_NS_RAW_FENTRY(ns, #name, zif_##alias, arg_info, ZEND_ACC_DEPRECATED) -#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 } +#define ZEND_FE_END { NULL, NULL, NULL, 0, 0, NULL } #define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic, is_tentative) \ (((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0) | ((is_tentative) ? _ZEND_IS_TENTATIVE_BIT : 0)) @@ -2172,7 +2175,11 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, u ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_or_str_slow(zval *arg, zval **dest, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num); -static zend_always_inline bool zend_parse_arg_bool(const zval *arg, bool *dest, bool *is_null, bool check_null, uint32_t arg_num) +ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_bool_slow(const zval *arg, bool *dest, uint32_t arg_num); +ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num); +ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_long_slow(const zval *arg, zend_long *dest, uint32_t arg_num); + +static zend_always_inline bool zend_parse_arg_bool_ex(const zval *arg, bool *dest, bool *is_null, bool check_null, uint32_t arg_num, bool frameless) { if (check_null) { *is_null = 0; @@ -2185,12 +2192,21 @@ static zend_always_inline bool zend_parse_arg_bool(const zval *arg, bool *dest, *is_null = 1; *dest = 0; } else { - return zend_parse_arg_bool_slow(arg, dest, arg_num); + if (frameless) { + return zend_flf_parse_arg_bool_slow(arg, dest, arg_num); + } else { + return zend_parse_arg_bool_slow(arg, dest, arg_num); + } } return 1; } -static zend_always_inline bool zend_parse_arg_long(zval *arg, zend_long *dest, bool *is_null, bool check_null, uint32_t arg_num) +static zend_always_inline bool zend_parse_arg_bool(const zval *arg, bool *dest, bool *is_null, bool check_null, uint32_t arg_num) +{ + return zend_parse_arg_bool_ex(arg, dest, is_null, check_null, arg_num, /* frameless */ false); +} + +static zend_always_inline bool zend_parse_arg_long_ex(zval *arg, zend_long *dest, bool *is_null, bool check_null, uint32_t arg_num, bool frameless) { if (check_null) { *is_null = 0; @@ -2201,11 +2217,20 @@ static zend_always_inline bool zend_parse_arg_long(zval *arg, zend_long *dest, b *is_null = 1; *dest = 0; } else { - return zend_parse_arg_long_slow(arg, dest, arg_num); + if (frameless) { + return zend_flf_parse_arg_long_slow(arg, dest, arg_num); + } else { + return zend_parse_arg_long_slow(arg, dest, arg_num); + } } return 1; } +static zend_always_inline bool zend_parse_arg_long(zval *arg, zend_long *dest, bool *is_null, bool check_null, uint32_t arg_num) +{ + return zend_parse_arg_long_ex(arg, dest, is_null, check_null, arg_num, /* frameless */ false); +} + static zend_always_inline bool zend_parse_arg_double(const zval *arg, double *dest, bool *is_null, bool check_null, uint32_t arg_num) { if (check_null) { @@ -2246,18 +2271,27 @@ static zend_always_inline bool zend_parse_arg_number_or_str(zval *arg, zval **de return true; } -static zend_always_inline bool zend_parse_arg_str(zval *arg, zend_string **dest, bool check_null, uint32_t arg_num) +static zend_always_inline bool zend_parse_arg_str_ex(zval *arg, zend_string **dest, bool check_null, uint32_t arg_num, bool frameless) { if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) { *dest = Z_STR_P(arg); } else if (check_null && Z_TYPE_P(arg) == IS_NULL) { *dest = NULL; } else { - return zend_parse_arg_str_slow(arg, dest, arg_num); + if (frameless) { + return zend_flf_parse_arg_str_slow(arg, dest, arg_num); + } else { + return zend_parse_arg_str_slow(arg, dest, arg_num); + } } return 1; } +static zend_always_inline bool zend_parse_arg_str(zval *arg, zend_string **dest, bool check_null, uint32_t arg_num) +{ + return zend_parse_arg_str_ex(arg, dest, check_null, arg_num, /* frameless */ false); +} + static zend_always_inline bool zend_parse_arg_string(zval *arg, char **dest, size_t *dest_len, bool check_null, uint32_t arg_num) { zend_string *str; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index fbd24694081b0..c92f507a1b2a5 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -941,19 +941,11 @@ ZEND_FUNCTION(method_exists) } /* }}} */ -/* {{{ Checks if the object or class has a property */ -ZEND_FUNCTION(property_exists) +static void _property_exists(zval *return_value, zval *object, zend_string *property) { - zval *object; - zend_string *property; zend_class_entry *ce; zend_property_info *property_info; - /* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) { - RETURN_THROWS(); - } - if (Z_TYPE_P(object) == IS_STRING) { ce = zend_lookup_class(Z_STR_P(object)); if (!ce) { @@ -979,20 +971,41 @@ ZEND_FUNCTION(property_exists) } RETURN_FALSE; } + +/* {{{ Checks if the object or class has a property */ +ZEND_FUNCTION(property_exists) +{ + zval *object; + zend_string *property; + + /* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */ + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) { + RETURN_THROWS(); + } + + _property_exists(return_value, object, property); +} /* }}} */ -static inline void class_exists_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */ +ZEND_FRAMELESS_FUNCTION(property_exists, 2) +{ + zval *object; + zval property_tmp; + zend_string *property; + + Z_FLF_PARAM_ZVAL(1, object); + Z_FLF_PARAM_STR(2, property, property_tmp); + + _property_exists(return_value, object, property); + +flf_clean:; + Z_FLF_PARAM_FREE_STR(2, property_tmp) +} + +static inline void _class_exists_impl(zval *return_value, zend_string *name, bool autoload, int flags, int skip_flags) /* {{{ */ { - zend_string *name; zend_string *lcname; zend_class_entry *ce; - bool autoload = 1; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STR(name) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(autoload) - ZEND_PARSE_PARAMETERS_END(); if (ZSTR_HAS_CE_CACHE(name)) { ce = ZSTR_GET_CE_CACHE(name); @@ -1024,6 +1037,20 @@ static inline void class_exists_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, in } /* {{{ */ +static inline void class_exists_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */ +{ + zend_string *name; + bool autoload = true; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(name) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(autoload) + ZEND_PARSE_PARAMETERS_END(); + + _class_exists_impl(return_value, name, autoload, flags, skip_flags); +} + /* {{{ Checks if the class exists */ ZEND_FUNCTION(class_exists) { @@ -1031,6 +1058,34 @@ ZEND_FUNCTION(class_exists) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(class_exists, 1) +{ + zval name_tmp; + zend_string *name; + + Z_FLF_PARAM_STR(1, name, name_tmp); + + _class_exists_impl(return_value, name, /* autoload */ true, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, name_tmp); +} + +ZEND_FRAMELESS_FUNCTION(class_exists, 2) +{ + zval name_tmp; + zend_string *name; + bool autoload; + + Z_FLF_PARAM_STR(1, name, name_tmp); + Z_FLF_PARAM_BOOL(2, autoload); + + _class_exists_impl(return_value, name, autoload, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, name_tmp); +} + /* {{{ Checks if the class exists */ ZEND_FUNCTION(interface_exists) { @@ -1729,7 +1784,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int zend_string *filename; zend_string *include_filename = NULL; zval tmp; - HashTable *stack_frame; + HashTable *stack_frame, *prev_stack_frame = NULL; array_init(return_value); @@ -1781,6 +1836,81 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int prev = zend_generator_check_placeholder_frame(prev); } + /* For frameless calls we add an additional frame for the call itself. */ + if (ZEND_USER_CODE(call->func->type)) { + const zend_op *opline = call->opline; + if (!ZEND_OP_IS_FRAMELESS_ICALL(opline->opcode)) { + goto not_frameless_call; + } + int num_args = ZEND_FLF_NUM_ARGS(opline->opcode); + /* Check if any args were already freed. Skip the frame in that case. */ + if (num_args >= 1) { + zval *arg = zend_get_zval_ptr(opline, opline->op1_type, &opline->op1, call); + if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call; + } + if (num_args >= 2) { + zval *arg = zend_get_zval_ptr(opline, opline->op2_type, &opline->op2, call); + if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call; + } + if (num_args >= 3) { + const zend_op *op_data = opline + 1; + zval *arg = zend_get_zval_ptr(op_data, op_data->op1_type, &op_data->op1, call); + if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call; + } + stack_frame = zend_new_array(8); + zend_hash_real_init_mixed(stack_frame); + zend_function *func = ZEND_FLF_FUNC(opline); + zend_string *name = func->common.function_name; + ZVAL_STRINGL(&tmp, ZSTR_VAL(name), ZSTR_LEN(name)); + _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1); + /* Steal file and line from the previous frame. */ + if (call->func && ZEND_USER_CODE(call->func->common.type)) { + filename = call->func->op_array.filename; + if (call->opline->opcode == ZEND_HANDLE_EXCEPTION) { + if (EG(opline_before_exception)) { + lineno = EG(opline_before_exception)->lineno; + } else { + lineno = call->func->op_array.line_end; + } + } else { + lineno = call->opline->lineno; + } + ZVAL_STR_COPY(&tmp, filename); + _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1); + ZVAL_LONG(&tmp, lineno); + _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1); + if (prev_stack_frame) { + zend_hash_del(prev_stack_frame, ZSTR_KNOWN(ZEND_STR_FILE)); + zend_hash_del(prev_stack_frame, ZSTR_KNOWN(ZEND_STR_LINE)); + } + } + if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) { + HashTable *args = zend_new_array(8); + zend_hash_real_init_mixed(args); + if (num_args >= 1) { + zval *arg = zend_get_zval_ptr(opline, opline->op1_type, &opline->op1, call); + Z_TRY_ADDREF_P(arg); + zend_hash_next_index_insert_new(args, arg); + } + if (num_args >= 2) { + zval *arg = zend_get_zval_ptr(opline, opline->op2_type, &opline->op2, call); + Z_TRY_ADDREF_P(arg); + zend_hash_next_index_insert_new(args, arg); + } + if (num_args >= 3) { + const zend_op *op_data = opline + 1; + zval *arg = zend_get_zval_ptr(op_data, op_data->op1_type, &op_data->op1, call); + Z_TRY_ADDREF_P(arg); + zend_hash_next_index_insert_new(args, arg); + } + ZVAL_ARR(&tmp, args); + _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_ARGS), &tmp, 1); + } + ZVAL_ARR(&tmp, stack_frame); + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); + } +not_frameless_call: + /* We use _zend_hash_append*() and the array must be preallocated */ stack_frame = zend_new_array(8); zend_hash_real_init_mixed(stack_frame); @@ -1925,6 +2055,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int ZVAL_ARR(&tmp, stack_frame); zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); frameno++; + prev_stack_frame = stack_frame; skip_frame: if (UNEXPECTED(ZEND_CALL_KIND(call) == ZEND_CALL_TOP_FUNCTION) diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index b6740523d5000..b92b80b917c54 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -68,9 +68,16 @@ function get_class_methods(object|string $object_or_class): array {} /** @param object|string $object_or_class */ function method_exists($object_or_class, string $method): bool {} -/** @param object|string $object_or_class */ +/** + * @param object|string $object_or_class + * @frameless-function {"arity": 2} + */ function property_exists($object_or_class, string $property): bool {} +/** + * @frameless-function {"arity": 1} + * @frameless-function {"arity": 2} + */ function class_exists(string $class, bool $autoload = true): bool {} function interface_exists(string $interface, bool $autoload = true): bool {} diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index 636eba6188585..11fc2f254845f 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: bd3226bdeb5585333f97659a0a3b01504d830a15 */ + * Stub hash: c3bec3b17079456ef17e5c992995dcfbe62c6fe0 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -217,6 +217,20 @@ ZEND_END_ARG_INFO() #define arginfo_gc_status arginfo_func_get_args +ZEND_FRAMELESS_FUNCTION(property_exists, 2); +static const zend_frameless_function_info frameless_function_infos_property_exists[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(property_exists, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(class_exists, 1); +ZEND_FRAMELESS_FUNCTION(class_exists, 2); +static const zend_frameless_function_info frameless_function_infos_class_exists[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(class_exists, 1), 1 }, + { ZEND_FRAMELESS_FUNCTION_NAME(class_exists, 2), 2 }, + { 0 }, +}; + ZEND_FUNCTION(zend_version); ZEND_FUNCTION(func_num_args); @@ -301,8 +315,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(get_mangled_object_vars, arginfo_get_mangled_object_vars) ZEND_FE(get_class_methods, arginfo_get_class_methods) ZEND_FE(method_exists, arginfo_method_exists) - ZEND_FE(property_exists, arginfo_property_exists) - ZEND_FE(class_exists, arginfo_class_exists) + ZEND_FRAMELESS_FE(property_exists, arginfo_property_exists, 0, frameless_function_infos_property_exists) + ZEND_FRAMELESS_FE(class_exists, arginfo_class_exists, 0, frameless_function_infos_class_exists) ZEND_FE(interface_exists, arginfo_interface_exists) ZEND_FE(trait_exists, arginfo_trait_exists) ZEND_FE(enum_exists, arginfo_enum_exists) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c82f2be771215..c0cab6d8aa398 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -35,6 +35,7 @@ #include "zend_enum.h" #include "zend_observer.h" #include "zend_call_stack.h" +#include "zend_frameless_function.h" #define SET_NODE(target, src) do { \ target ## _type = (src)->op_type; \ @@ -787,7 +788,15 @@ static void zend_do_free(znode *op1) /* {{{ */ if (opline->opcode == ZEND_FETCH_THIS) { opline->opcode = ZEND_NOP; } - SET_UNUSED(opline->result); + if (!ZEND_OP_IS_FRAMELESS_ICALL(opline->opcode)) { + SET_UNUSED(opline->result); + } else { + /* Frameless calls usually use the return value, so always emit a free. This should be + * faster than checking RETURN_VALUE_USED inside the handler. */ + // FIXME: We may actually look at the function signature to determine whether a free + // is necessary. + zend_emit_op(NULL, ZEND_FREE, op1, NULL); + } } else { while (opline >= CG(active_op_array)->opcodes) { if ((opline->opcode == ZEND_FETCH_LIST_R || @@ -2352,6 +2361,7 @@ static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_t case ZEND_COALESCE: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: opline->op2.opline_num = opnum_target; break; EMPTY_SWITCH_DEFAULT_CASE() @@ -3924,19 +3934,6 @@ static bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* } /* }}} */ -static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */ -{ - zend_op *opline = get_next_op(); - opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME; - opline->op2_type = IS_CONST; - opline->op2.constant = zend_add_ns_func_name_literal( - Z_STR(name_node->u.constant)); - opline->result.num = zend_alloc_cache_slot(); - - zend_compile_call_common(result, args_ast, NULL, lineno); -} -/* }}} */ - static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */ { if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) { @@ -4529,22 +4526,156 @@ static zend_result zend_compile_func_array_slice(znode *result, zend_ast_list *a } /* }}} */ -static zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */ +static uint32_t find_frameless_function_offset(uint32_t arity, void *handler) { - if (CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS) { - return FAILURE; + void **handlers = zend_flf_handlers; + void **current = handlers; + while (current) { + if (*current == handler) { + return current - handlers; + } + current++; } - if (fbc->type != ZEND_INTERNAL_FUNCTION) { - /* If the function is part of disabled_functions, it may be redeclared as a userland - * function with a different implementation. Don't use the VM builtin in that case. */ - return FAILURE; + return (uint32_t)-1; +} + +static const zend_frameless_function_info *find_frameless_function_info(zend_ast_list *args, zend_function *fbc, uint32_t type) +{ + if (ZEND_OBSERVER_ENABLED) { + return NULL; } - if (zend_args_contain_unpack_or_named(args)) { - return FAILURE; + if (type != BP_VAR_R) { + return NULL; + } + + if (ZEND_USER_CODE(fbc->type)) { + return NULL; + } + + const zend_frameless_function_info *frameless_function_info = fbc->internal_function.frameless_function_infos; + if (!frameless_function_info) { + return NULL; + } + + if (args->children > 3) { + return NULL; + } + + while (frameless_function_info->handler) { + if (frameless_function_info->num_args >= args->children + && fbc->common.required_num_args <= args->children + && (!(fbc->common.fn_flags & ZEND_ACC_VARIADIC) + || frameless_function_info->num_args == args->children)) { + uint32_t num_args = frameless_function_info->num_args; + uint32_t offset = find_frameless_function_offset(num_args, frameless_function_info->handler); + if (offset == (uint32_t)-1) { + continue; + } + return frameless_function_info; + } + frameless_function_info++; } + return NULL; +} + +static uint32_t zend_compile_frameless_icall_ex(znode *result, zend_ast_list *args, zend_function *fbc, const zend_frameless_function_info *frameless_function_info, uint32_t type) +{ + uint32_t num_args = frameless_function_info->num_args; + uint32_t offset = find_frameless_function_offset(num_args, frameless_function_info->handler); + znode arg_zvs[3]; + for (uint32_t i = 0; i < num_args; i++) { + if (i < args->children) { + zend_compile_expr(&arg_zvs[i], args->child[i]); + } else { + zend_internal_arg_info *arg_info = (zend_internal_arg_info *)&fbc->common.arg_info[i]; + arg_zvs[i].op_type = IS_CONST; + if (zend_get_default_from_internal_arg_info(&arg_zvs[i].u.constant, arg_info) == FAILURE) { + ZEND_UNREACHABLE(); + } + } + } + uint8_t opcode = ZEND_FRAMELESS_ICALL_0 + num_args; + uint32_t opnum = get_next_op_number(); + zend_op *opline = zend_emit_op_tmp(result, opcode, NULL, NULL); + opline->extended_value = offset; + if (num_args >= 1) { + SET_NODE(opline->op1, &arg_zvs[0]); + } + if (num_args >= 2) { + SET_NODE(opline->op2, &arg_zvs[1]); + } + if (num_args >= 3) { + zend_emit_op_data(&arg_zvs[2]); + } + return opnum; +} + +static uint32_t zend_compile_frameless_icall(znode *result, zend_ast_list *args, zend_function *fbc, uint32_t type) +{ + const zend_frameless_function_info *frameless_function_info = find_frameless_function_info(args, fbc, type); + if (!frameless_function_info) { + return (uint32_t)-1; + } + + return zend_compile_frameless_icall_ex(result, args, fbc, frameless_function_info, type); +} + +static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno, uint32_t type) /* {{{ */ +{ + int name_constants = zend_add_ns_func_name_literal(Z_STR(name_node->u.constant)); + + /* Find frameless function with same name. */ + zend_function *frameless_function = NULL; + if (args_ast->kind != ZEND_AST_CALLABLE_CONVERT + && !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast))) { + zend_string *lc_func_name = Z_STR_P(CT_CONSTANT_EX(CG(active_op_array), name_constants + 2)); + frameless_function = zend_hash_find_ptr(CG(function_table), lc_func_name); + } + + /* Check whether any frameless handler may actually be used. */ + uint32_t jmp_fl_opnum = 0; + const zend_frameless_function_info *frameless_function_info = NULL; + if (frameless_function) { + frameless_function_info = find_frameless_function_info(zend_ast_get_list(args_ast), frameless_function, type); + if (frameless_function_info) { + znode op1; + op1.op_type = IS_CONST; + ZVAL_COPY(&op1.u.constant, CT_CONSTANT_EX(CG(active_op_array), name_constants + 1)); + jmp_fl_opnum = get_next_op_number(); + zend_emit_op(NULL, ZEND_JMP_FRAMELESS, &op1, NULL); + } + } + + /* Compile ns call. */ + zend_op *opline = get_next_op(); + opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME; + opline->op2_type = IS_CONST; + opline->op2.constant = name_constants; + opline->result.num = zend_alloc_cache_slot(); + zend_compile_call_common(result, args_ast, NULL, lineno); + + /* Compile frameless call. */ + if (frameless_function_info) { + uint32_t jmp_end_opnum = zend_emit_jump(0); + uint32_t jmp_fl_target = get_next_op_number(); + + uint32_t flf_icall_opnum = zend_compile_frameless_icall_ex(NULL, zend_ast_get_list(args_ast), frameless_function, frameless_function_info, type); + + zend_op *jmp_fl = &CG(active_op_array)->opcodes[jmp_fl_opnum]; + jmp_fl->op2.opline_num = jmp_fl_target; + jmp_fl->extended_value = zend_alloc_cache_slot(); + zend_op *flf_icall = &CG(active_op_array)->opcodes[flf_icall_opnum]; + SET_NODE(flf_icall->result, result); + zend_update_jump_target_to_next(jmp_end_opnum); + } +} +/* }}} */ + +static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */ +{ if (zend_string_equals_literal(lcname, "strlen")) { return zend_compile_func_strlen(result, args); } else if (zend_string_equals_literal(lcname, "is_null")) { @@ -4613,7 +4744,29 @@ static zend_result zend_try_compile_special_func(znode *result, zend_string *lcn return FAILURE; } } -/* }}} */ + +static zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */ +{ + if (CG(compiler_options) & ZEND_COMPILE_NO_BUILTINS) { + return FAILURE; + } + + if (fbc->type != ZEND_INTERNAL_FUNCTION) { + /* If the function is part of disabled_functions, it may be redeclared as a userland + * function with a different implementation. Don't use the VM builtin in that case. */ + return FAILURE; + } + + if (zend_args_contain_unpack_or_named(args)) { + return FAILURE; + } + + if (zend_try_compile_special_func_ex(result, lcname, args, fbc, type) == SUCCESS) { + return SUCCESS; + } + + return zend_compile_frameless_icall(result, args, fbc, type) != (uint32_t)-1 ? SUCCESS : FAILURE; +} static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { @@ -4636,7 +4789,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ && !is_callable_convert) { zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL, ast->lineno); } else { - zend_compile_ns_call(result, &name_node, args_ast, ast->lineno); + zend_compile_ns_call(result, &name_node, args_ast, ast->lineno, type); } return; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index ca8e654132924..64464ed999a2f 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -29,6 +29,7 @@ #include #include "zend_llist.h" +#include "zend_frameless_function.h" #define SET_UNUSED(op) do { \ op ## _type = IS_UNUSED; \ @@ -525,6 +526,7 @@ typedef struct _zend_internal_function { zif_handler handler; struct _zend_module_entry *module; + const zend_frameless_function_info *frameless_function_infos; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; } zend_internal_function; @@ -655,6 +657,11 @@ ZEND_STATIC_ASSERT(ZEND_MM_ALIGNED_SIZE(sizeof(zval)) == sizeof(zval), EG(current_execute_data)->prev_execute_data->func && \ ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)->prev_execute_data)) +#define ZEND_FLF_ARG_USES_STRICT_TYPES() \ + (EG(current_execute_data) && \ + EG(current_execute_data)->func && \ + ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))) + #define ZEND_RET_USES_STRICT_TYPES() \ ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index de9226c3519e3..0172106344acd 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -152,6 +152,7 @@ ZEND_API const zend_internal_function zend_pass_function = { 0, /* T */ ZEND_FN(pass), /* handler */ NULL, /* module */ + NULL, /* frameless_function_infos */ {NULL,NULL,NULL,NULL} /* reserved */ }; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index d0c18040ab46d..71512ccf1b122 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -372,6 +372,18 @@ ZEND_API const char *get_active_class_name(const char **space); ZEND_API const char *get_active_function_name(void); ZEND_API const char *get_active_function_arg_name(uint32_t arg_num); ZEND_API const char *get_function_arg_name(const zend_function *func, uint32_t arg_num); +ZEND_API zend_function *zend_active_function_ex(zend_execute_data *execute_data); + +static zend_always_inline zend_function *zend_active_function(void) +{ + zend_function *func = EG(current_execute_data)->func; + if (ZEND_USER_CODE(func->type)) { + return zend_active_function_ex(EG(current_execute_data)); + } else { + return func; + } +} + ZEND_API zend_string *get_active_function_or_method_name(void); ZEND_API zend_string *get_function_or_method_name(const zend_function *func); ZEND_API const char *zend_get_executed_filename(void); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index feeff659bd5f4..c297523b9249a 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -38,6 +38,7 @@ #include "zend_inheritance.h" #include "zend_observer.h" #include "zend_call_stack.h" +#include "zend_frameless_function.h" #ifdef HAVE_SYS_TIME_H #include #endif @@ -536,7 +537,7 @@ ZEND_API const char *get_active_function_name(void) /* {{{ */ return NULL; } - func = EG(current_execute_data)->func; + func = zend_active_function(); switch (func->type) { case ZEND_USER_FUNCTION: { @@ -558,11 +559,26 @@ ZEND_API const char *get_active_function_name(void) /* {{{ */ } /* }}} */ +ZEND_API zend_function *zend_active_function_ex(zend_execute_data *execute_data) +{ + zend_function *func = EX(func); + + /* Resolve function if op is a frameless call. */ + if (ZEND_USER_CODE(func->type)) { + const zend_op *op = EX(opline); + if (ZEND_OP_IS_FRAMELESS_ICALL(op->opcode)) { + func = ZEND_FLF_FUNC(op); + } + } + + return func; +} + ZEND_API zend_string *get_active_function_or_method_name(void) /* {{{ */ { ZEND_ASSERT(zend_is_executing()); - return get_function_or_method_name(EG(current_execute_data)->func); + return get_function_or_method_name(zend_active_function()); } /* }}} */ @@ -578,13 +594,11 @@ ZEND_API zend_string *get_function_or_method_name(const zend_function *func) /* ZEND_API const char *get_active_function_arg_name(uint32_t arg_num) /* {{{ */ { - zend_function *func; - if (!zend_is_executing()) { return NULL; } - func = EG(current_execute_data)->func; + zend_function *func = zend_active_function(); return get_function_arg_name(func, arg_num); } diff --git a/Zend/zend_frameless_function.c b/Zend/zend_frameless_function.c new file mode 100644 index 0000000000000..7ccda0cfb5702 --- /dev/null +++ b/Zend/zend_frameless_function.c @@ -0,0 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ +*/ + +#include + +#include "zend_frameless_function.h" + +size_t zend_flf_count = 0; +size_t zend_flf_capacity = 0; +ZEND_API void **zend_flf_handlers = NULL; +zend_function **zend_flf_functions = NULL; diff --git a/Zend/zend_frameless_function.h b/Zend/zend_frameless_function.h new file mode 100644 index 0000000000000..6821654bc424b --- /dev/null +++ b/Zend/zend_frameless_function.h @@ -0,0 +1,133 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_FRAMELESS_FUNCTION_H +#define ZEND_FRAMELESS_FUNCTION_H + +#include +#include + +#ifdef PHP_WIN32 +# include +#else +# include +#endif + +#include "zend_portability.h" + +#define ZEND_FRAMELESS_FUNCTION_PARAMETERS_0 zval *return_value +#define ZEND_FRAMELESS_FUNCTION_PARAMETERS_1 zval *return_value, zval *arg1 +#define ZEND_FRAMELESS_FUNCTION_PARAMETERS_2 zval *return_value, zval *arg1, zval *arg2 +#define ZEND_FRAMELESS_FUNCTION_PARAMETERS_3 zval *return_value, zval *arg1, zval *arg2, zval *arg3 + +#define ZEND_FRAMELESS_FUNCTION_NAME(name, arity) zflf_##name##_##arity +#define ZEND_OP_IS_FRAMELESS_ICALL(opcode) ((opcode) >= ZEND_FRAMELESS_ICALL_0 && (opcode) <= ZEND_FRAMELESS_ICALL_3) +#define ZEND_FLF_NUM_ARGS(opcode) ((opcode) - ZEND_FRAMELESS_ICALL_0) +#define ZEND_FLF_FUNC(opline) (zend_flf_functions[(opline)->extended_value]) +#define ZEND_FLF_HANDLER(opline) (zend_flf_handlers[(opline)->extended_value]) + +#define ZEND_FRAMELESS_FUNCTION(name, arity) \ + void ZEND_FRAMELESS_FUNCTION_NAME(name, arity)(ZEND_FRAMELESS_FUNCTION_PARAMETERS_##arity) + +#define Z_FLF_PARAM_ZVAL(arg_num, dest) \ + dest = arg ## arg_num; +#define Z_FLF_PARAM_ARRAY(arg_num, dest) \ + if (!zend_parse_arg_array(arg ## arg_num, &dest, /* null_check */ false, /* or_object */ false)) { \ + zend_wrong_parameter_type_error(arg_num, Z_EXPECTED_ARRAY, arg ## arg_num); \ + goto flf_clean; \ + } +#define Z_FLF_PARAM_ARRAY_OR_NULL(arg_num, dest) \ + if (!zend_parse_arg_array(arg ## arg_num, &dest, /* null_check */ true, /* or_object */ false)) { \ + zend_wrong_parameter_type_error(arg_num, Z_EXPECTED_ARRAY_OR_NULL, arg ## arg_num); \ + goto flf_clean; \ + } +#define Z_FLF_PARAM_ARRAY_HT_OR_STR(arg_num, dest_ht, dest_str, str_tmp) \ + if (Z_TYPE_P(arg ## arg_num) == IS_STRING) { \ + dest_ht = NULL; \ + dest_str = Z_STR_P(arg ## arg_num); \ + } else if (EXPECTED(Z_TYPE_P(arg ## arg_num) == IS_ARRAY)) { \ + dest_ht = Z_ARRVAL_P(arg ## arg_num); \ + dest_str = NULL; \ + } else { \ + dest_ht = NULL; \ + ZVAL_COPY(&str_tmp, arg ## arg_num); \ + arg ## arg_num = &str_tmp; \ + if (!zend_flf_parse_arg_str_slow(arg ## arg_num, &dest_str, arg_num)) { \ + zend_wrong_parameter_type_error(arg_num, Z_EXPECTED_ARRAY_OR_STRING, arg ## arg_num); \ + goto flf_clean; \ + } \ + } +#define Z_FLF_PARAM_BOOL(arg_num, dest) \ + if (!zend_parse_arg_bool_ex(arg ## arg_num, &dest, /* is_null */ NULL, /* null_check */ false, arg_num, /* frameless */ true)) { \ + zend_wrong_parameter_type_error(arg_num, Z_EXPECTED_BOOL, arg ## arg_num); \ + goto flf_clean; \ + } +#define Z_FLF_PARAM_LONG(arg_num, dest) \ + if (!zend_parse_arg_long_ex(arg ## arg_num, &dest, /* is_null */ NULL, /* null_check */ false, arg_num, /* frameless */ true)) { \ + zend_wrong_parameter_type_error(arg_num, Z_EXPECTED_LONG, arg ## arg_num); \ + goto flf_clean; \ + } +#define Z_FLF_PARAM_LONG_OR_NULL(arg_num, is_null, dest) \ + if (!zend_parse_arg_long_ex(arg ## arg_num, &dest, &is_null, /* null_check */ true, arg_num, /* frameless */ true)) { \ + zend_wrong_parameter_type_error(arg_num, Z_EXPECTED_LONG_OR_NULL, arg ## arg_num); \ + goto flf_clean; \ + } +#define Z_FLF_PARAM_STR(arg_num, dest, tmp) \ + if (Z_TYPE_P(arg ## arg_num) == IS_STRING) { \ + dest = Z_STR_P(arg ## arg_num); \ + } else { \ + ZVAL_COPY(&tmp, arg ## arg_num); \ + arg ## arg_num = &tmp; \ + if (!zend_parse_arg_str_ex(arg ## arg_num, &dest, /* null_check */ false, arg_num, /* frameless */ true)) { \ + zend_wrong_parameter_type_error(arg_num, Z_EXPECTED_STRING, arg ## arg_num); \ + goto flf_clean; \ + } \ + } +#define Z_FLF_PARAM_FREE_STR(arg_num, tmp) \ + if (UNEXPECTED(arg ## arg_num == &tmp)) { \ + zval_ptr_dtor(arg ## arg_num); \ + } + +BEGIN_EXTERN_C() + +typedef struct _zval_struct zval; +typedef struct _zend_op zend_op; +typedef union _zend_function zend_function; + +typedef void (*zend_frameless_function_0)(zval *return_value); +typedef void (*zend_frameless_function_1)(zval *return_value, zval *op1); +typedef void (*zend_frameless_function_2)(zval *return_value, zval *op1, zval *op2); +typedef void (*zend_frameless_function_3)(zval *return_value, zval *op1, zval *op2, zval *op3); + +extern size_t zend_flf_count; +extern size_t zend_flf_capacity; +ZEND_API extern void **zend_flf_handlers; +extern zend_function **zend_flf_functions; + +typedef struct { + void *handler; + uint32_t num_args; +} zend_frameless_function_info; + +typedef enum { + ZEND_JMP_FL_UNPRIMED = 0, + ZEND_JMP_FL_MISS = 1, + ZEND_JMP_FL_HIT = 2, +} zend_jmp_fl_result; + +END_EXTERN_C() + +#endif diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 93195a1be4c54..7e6c232cc459f 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -1118,6 +1118,7 @@ ZEND_API void pass_two(zend_op_array *op_array) case ZEND_FE_RESET_RW: case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); break; case ZEND_ASSERT_CHECK: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2d12dfbb95649..a33ab53a260b7 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -9556,6 +9556,147 @@ ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(208, ZEND_JMP_FRAMELESS, CONST, JMP_ADDR, NUM|CACHE_SLOT) +{ + USE_OPLINE + zend_jmp_fl_result result = (uintptr_t)CACHED_PTR(opline->extended_value); +ZEND_VM_C_LABEL(try_again): + if (EXPECTED(result == ZEND_JMP_FL_HIT)) { + OPLINE = OP_JMP_ADDR(opline, opline->op2); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(result == ZEND_JMP_FL_MISS)) { + ZEND_VM_NEXT_OPCODE(); + } else { + ZEND_ASSERT(result == ZEND_JMP_FL_UNPRIMED); + /* func_name refers to the function in the local namespace, e.g. foo\substr. */ + zval *func_name = (zval *)RT_CONSTANT(opline, opline->op1); + /* If it cannot be found locally, we must be referring to the global function. */ + zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name)); + /* ZEND_JMP_FL_MISS = 1, ZEND_JMP_FL_HIT = 2 */ + result = (func == NULL) + 1; + CACHE_PTR(opline->extended_value, (void *)result); + ZEND_VM_C_GOTO(try_again); + } +} + +ZEND_VM_HANDLER(204, ZEND_FRAMELESS_ICALL_0, UNUSED, UNUSED) +{ + USE_OPLINE + SAVE_OPLINE(); + zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline); + ZVAL_NULL(EX_VAR(opline->result.var)); + function(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED) +{ + USE_OPLINE + SAVE_OPLINE(); + zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline); + ZVAL_NULL(EX_VAR(opline->result.var)); + + zval *arg1; + if (OP1_TYPE == IS_CV) { + /* Inlined GET_OPx_ZVAL_PTR_DEREF to nest the EG(exception) check. */ + arg1 = EX_VAR(opline->op1.var); + if (UNEXPECTED(Z_TYPE_P(arg1) == IS_UNDEF)) { + arg1 = zval_undefined_cv(opline->op1.var EXECUTE_DATA_CC); + if (EG(exception)) { + FREE_OP1(); + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(arg1); + } else { + arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); + } + + function(EX_VAR(opline->result.var), arg1); + FREE_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY) +{ + USE_OPLINE + SAVE_OPLINE(); + zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline); + ZVAL_NULL(EX_VAR(opline->result.var)); + + zval *arg1; + if (OP1_TYPE == IS_CV) { + /* Inlined GET_OPx_ZVAL_PTR_DEREF to nest the EG(exception) check. */ + arg1 = EX_VAR(opline->op1.var); + if (UNEXPECTED(Z_TYPE_P(arg1) == IS_UNDEF)) { + arg1 = zval_undefined_cv(opline->op1.var EXECUTE_DATA_CC); + if (EG(exception)) { + FREE_OP1(); + FREE_OP2(); + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(arg1); + } else { + arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); + } + + zval *arg2; + if (OP2_TYPE == IS_CV) { + /* Inlined GET_OPx_ZVAL_PTR_DEREF to nest the EG(exception) check. */ + arg2 = EX_VAR(opline->op2.var); + if (UNEXPECTED(Z_TYPE_P(arg2) == IS_UNDEF)) { + arg2 = zval_undefined_cv(opline->op2.var EXECUTE_DATA_CC); + if (EG(exception)) { + FREE_OP1(); + FREE_OP2(); + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(arg2); + } else { + arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); + } + + function(EX_VAR(opline->result.var), arg1, arg2); + FREE_OP1(); + /* Set OP1 to UNDEF in case FREE_OP2() throws. */ + if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) != 0 && (OP2_TYPE & (IS_VAR|IS_TMP_VAR)) != 0) { + ZVAL_UNDEF(EX_VAR(opline->op1.var)); + } + FREE_OP2(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY) +{ + USE_OPLINE + SAVE_OPLINE(); + zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline); + ZVAL_NULL(EX_VAR(opline->result.var)); + zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); + zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); + zval *arg3 = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R); + if (EG(exception)) { + FREE_OP1(); + FREE_OP2(); + FREE_OP_DATA(); + HANDLE_EXCEPTION(); + } + function(EX_VAR(opline->result.var), arg1, arg2, arg3); + FREE_OP1(); + /* Set to UNDEF in case FREE_OP2() throws. */ + if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op1.var)); + } + FREE_OP2(); + if (OP2_TYPE & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op2.var)); + } + FREE_OP_DATA(); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_JMP, (OP_JMP_ADDR(op, op->op1) > op), ZEND_JMP_FORWARD, JMP_ADDR, ANY) { USE_OPLINE diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c48df8191efa2..27884fffdec18 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3690,6 +3690,86 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ ZEND_VM_LEAVE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_2_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline); + ZVAL_NULL(EX_VAR(opline->result.var)); + + zval *arg1; + if (opline->op1_type == IS_CV) { + /* Inlined GET_OPx_ZVAL_PTR_DEREF to nest the EG(exception) check. */ + arg1 = EX_VAR(opline->op1.var); + if (UNEXPECTED(Z_TYPE_P(arg1) == IS_UNDEF)) { + arg1 = zval_undefined_cv(opline->op1.var EXECUTE_DATA_CC); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(arg1); + } else { + arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + } + + zval *arg2; + if (opline->op2_type == IS_CV) { + /* Inlined GET_OPx_ZVAL_PTR_DEREF to nest the EG(exception) check. */ + arg2 = EX_VAR(opline->op2.var); + if (UNEXPECTED(Z_TYPE_P(arg2) == IS_UNDEF)) { + arg2 = zval_undefined_cv(opline->op2.var EXECUTE_DATA_CC); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(arg2); + } else { + arg2 = get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R); + } + + function(EX_VAR(opline->result.var), arg1, arg2); + FREE_OP(opline->op1_type, opline->op1.var); + /* Set OP1 to UNDEF in case FREE_OP(opline->op2_type, opline->op2.var) throws. */ + if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) != 0 && (opline->op2_type & (IS_VAR|IS_TMP_VAR)) != 0) { + ZVAL_UNDEF(EX_VAR(opline->op1.var)); + } + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_3_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline); + ZVAL_NULL(EX_VAR(opline->result.var)); + zval *arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + zval *arg2 = get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R); + zval *arg3 = get_op_data_zval_ptr_deref_r((opline+1)->op1_type, (opline+1)->op1); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); + } + function(EX_VAR(opline->result.var), arg1, arg2, arg3); + FREE_OP(opline->op1_type, opline->op1.var); + /* Set to UNDEF in case FREE_OP(opline->op2_type, opline->op2.var) throws. */ + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op1.var)); + } + FREE_OP(opline->op2_type, opline->op2.var); + if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op2.var)); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_FORWARD_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4061,6 +4141,34 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline); + ZVAL_NULL(EX_VAR(opline->result.var)); + + zval *arg1; + if (opline->op1_type == IS_CV) { + /* Inlined GET_OPx_ZVAL_PTR_DEREF to nest the EG(exception) check. */ + arg1 = EX_VAR(opline->op1.var); + if (UNEXPECTED(Z_TYPE_P(arg1) == IS_UNDEF)) { + arg1 = zval_undefined_cv(opline->op1.var EXECUTE_DATA_CC); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(arg1); + } else { + arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + } + + function(EX_VAR(opline->result.var), arg1); + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5738,6 +5846,29 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST } } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_FRAMELESS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_jmp_fl_result result = (uintptr_t)CACHED_PTR(opline->extended_value); +try_again: + if (EXPECTED(result == ZEND_JMP_FL_HIT)) { + OPLINE = OP_JMP_ADDR(opline, opline->op2); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(result == ZEND_JMP_FL_MISS)) { + ZEND_VM_NEXT_OPCODE(); + } else { + ZEND_ASSERT(result == ZEND_JMP_FL_UNPRIMED); + /* func_name refers to the function in the local namespace, e.g. foo\substr. */ + zval *func_name = (zval *)RT_CONSTANT(opline, opline->op1); + /* If it cannot be found locally, we must be referring to the global function. */ + zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name)); + /* ZEND_JMP_FL_MISS = 1, ZEND_JMP_FL_HIT = 2 */ + result = (func == NULL) + 1; + CACHE_PTR(opline->extended_value, (void *)result); + goto try_again; + } +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -37237,6 +37368,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALLABLE_CONVERT_SPEC_UNUSED_U ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline); + ZVAL_NULL(EX_VAR(opline->result.var)); + function(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -56068,6 +56209,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED_LABEL, (void*)&&ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED_LABEL, (void*)&&ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_CV_LABEL, + (void*)&&ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED_LABEL, + (void*)&&ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_LABEL, + (void*)&&ZEND_FRAMELESS_ICALL_2_SPEC_LABEL, + (void*)&&ZEND_FRAMELESS_ICALL_3_SPEC_LABEL, + (void*)&&ZEND_JMP_FRAMELESS_SPEC_CONST_LABEL, (void*)&&ZEND_RECV_NOTYPE_SPEC_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_LABEL, @@ -57419,6 +57565,16 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER) HYBRID_BREAK(); + HYBRID_CASE(ZEND_FRAMELESS_ICALL_2_SPEC): + VM_TRACE(ZEND_FRAMELESS_ICALL_2_SPEC) + ZEND_FRAMELESS_ICALL_2_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FRAMELESS_ICALL_2_SPEC) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FRAMELESS_ICALL_3_SPEC): + VM_TRACE(ZEND_FRAMELESS_ICALL_3_SPEC) + ZEND_FRAMELESS_ICALL_3_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FRAMELESS_ICALL_3_SPEC) + HYBRID_BREAK(); HYBRID_CASE(ZEND_JMP_FORWARD_SPEC): VM_TRACE(ZEND_JMP_FORWARD_SPEC) ZEND_JMP_FORWARD_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57464,6 +57620,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_RECV_VARIADIC_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_RECV_VARIADIC_SPEC_UNUSED) HYBRID_BREAK(); + HYBRID_CASE(ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED): + VM_TRACE(ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED) + ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED) + HYBRID_BREAK(); HYBRID_CASE(ZEND_INIT_DYNAMIC_CALL_SPEC_CV): VM_TRACE(ZEND_INIT_DYNAMIC_CALL_SPEC_CV) ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57783,6 +57944,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_DEFINED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_DEFINED_SPEC_CONST) HYBRID_BREAK(); + HYBRID_CASE(ZEND_JMP_FRAMELESS_SPEC_CONST): + VM_TRACE(ZEND_JMP_FRAMELESS_SPEC_CONST) + ZEND_JMP_FRAMELESS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_JMP_FRAMELESS_SPEC_CONST) + HYBRID_BREAK(); HYBRID_CASE(ZEND_QM_ASSIGN_LONG_SPEC_CONST): VM_TRACE(ZEND_QM_ASSIGN_LONG_SPEC_CONST) ZEND_QM_ASSIGN_LONG_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -61081,6 +61247,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); VM_TRACE_OP_END(ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED) HYBRID_BREAK(); + HYBRID_CASE(ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED): + VM_TRACE(ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED) + ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED) + HYBRID_BREAK(); HYBRID_CASE(ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV): VM_TRACE(ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV) ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -65195,6 +65366,11 @@ void zend_vm_init(void) ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED_HANDLER, ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED_HANDLER, ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_CV_HANDLER, + ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_HANDLER, + ZEND_FRAMELESS_ICALL_2_SPEC_HANDLER, + ZEND_FRAMELESS_ICALL_3_SPEC_HANDLER, + ZEND_JMP_FRAMELESS_SPEC_CONST_HANDLER, ZEND_RECV_NOTYPE_SPEC_HANDLER, ZEND_NULL_HANDLER, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_HANDLER, @@ -66151,7 +66327,7 @@ void zend_vm_init(void) 1255, 1256 | SPEC_RULE_OP1, 1261 | SPEC_RULE_OP1, - 3476, + 3481, 1266 | SPEC_RULE_OP1, 1271 | SPEC_RULE_OP1, 1276 | SPEC_RULE_OP2, @@ -66310,58 +66486,58 @@ void zend_vm_init(void) 2565, 2566, 2567, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, - 3476, + 2568, + 2569, + 2570, + 2571, + 2572, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, + 3481, }; #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) zend_opcode_handler_funcs = labels; @@ -66534,7 +66710,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2575 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2580 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -66542,7 +66718,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2600 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2605 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -66550,7 +66726,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2625 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2630 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; if (op->op1_type < op->op2_type) { zend_swap_operands(op); } @@ -66561,17 +66737,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2650 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2655 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2675 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2680 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2700 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 2705 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_MUL: @@ -66582,17 +66758,17 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2725 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2730 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2750 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2755 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2775 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 2780 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_IDENTICAL: @@ -66603,14 +66779,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2800 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2805 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2875 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2880 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { - spec = 3100 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3105 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_IDENTICAL: @@ -66621,14 +66797,14 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2950 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2955 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3025 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3030 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) { - spec = 3105 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; + spec = 3110 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_EQUAL: @@ -66639,12 +66815,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2800 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2805 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2875 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2880 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_NOT_EQUAL: @@ -66655,12 +66831,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2950 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 2955 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3025 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; + spec = 3030 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE; } break; case ZEND_IS_SMALLER: @@ -66668,12 +66844,12 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3110 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3115 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3185 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3190 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_IS_SMALLER_OR_EQUAL: @@ -66681,74 +66857,74 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3260 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3265 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3335 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3340 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_QM_ASSIGN: if (op1_info == MAY_BE_LONG) { - spec = 3422 | SPEC_RULE_OP1; - } else if (op1_info == MAY_BE_DOUBLE) { spec = 3427 | SPEC_RULE_OP1; - } else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) { + } else if (op1_info == MAY_BE_DOUBLE) { spec = 3432 | SPEC_RULE_OP1; + } else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) { + spec = 3437 | SPEC_RULE_OP1; } break; case ZEND_PRE_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3410 | SPEC_RULE_RETVAL; + spec = 3415 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3412 | SPEC_RULE_RETVAL; + spec = 3417 | SPEC_RULE_RETVAL; } break; case ZEND_PRE_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3414 | SPEC_RULE_RETVAL; + spec = 3419 | SPEC_RULE_RETVAL; } else if (op1_info == MAY_BE_LONG) { - spec = 3416 | SPEC_RULE_RETVAL; + spec = 3421 | SPEC_RULE_RETVAL; } break; case ZEND_POST_INC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3418; + spec = 3423; } else if (op1_info == MAY_BE_LONG) { - spec = 3419; + spec = 3424; } break; case ZEND_POST_DEC: if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) { - spec = 3420; + spec = 3425; } else if (op1_info == MAY_BE_LONG) { - spec = 3421; + spec = 3426; } break; case ZEND_JMP: if (OP_JMP_ADDR(op, op->op1) > op) { - spec = 2574; + spec = 2579; } break; case ZEND_RECV: if (op->op2.num == MAY_BE_ANY) { - spec = 2568; + spec = 2573; } break; case ZEND_SEND_VAL: if (op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3472; + spec = 3477; } break; case ZEND_SEND_VAR_EX: if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3467 | SPEC_RULE_OP1; + spec = 3472 | SPEC_RULE_OP1; } break; case ZEND_FE_FETCH_R: if (op->op2_type == IS_CV && (op1_info & (MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) { - spec = 3474 | SPEC_RULE_RETVAL; + spec = 3479 | SPEC_RULE_RETVAL; } break; case ZEND_FETCH_DIM_R: @@ -66756,22 +66932,22 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3437 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3442 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_SEND_VAL_EX: if (op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) { - spec = 3473; + spec = 3478; } break; case ZEND_SEND_VAR: if (op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { - spec = 3462 | SPEC_RULE_OP1; + spec = 3467 | SPEC_RULE_OP1; } break; case ZEND_COUNT: if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY) { - spec = 2569 | SPEC_RULE_OP1; + spec = 2574 | SPEC_RULE_OP1; } break; case ZEND_BW_OR: diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index ae5ef7025023d..60a4a7336b48e 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -2432,7 +2432,7 @@ function gen_vm($def, $skel) { "/^ ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_|COLD_|COLD_CONST_|COLD_CONSTCONST_)?HANDLER\( \s*([0-9]+)\s*, - \s*([A-Z_]+)\s*, + \s*([A-Z_][A-Z0-9_]*)\s*, \s*([A-Z_|]+)\s*, \s*([A-Z_|]+)\s* (,\s*([A-Z_|]+)\s*)? diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 400b5c606a88b..90b26caf88439 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1363,501 +1363,506 @@ _(2565, ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED) \ _(2566, ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED) \ _(2567, ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_CV) \ - _(2568, ZEND_RECV_NOTYPE_SPEC) \ - _(2570, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ - _(2571, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ - _(2573, ZEND_COUNT_ARRAY_SPEC_CV_UNUSED) \ - _(2574, ZEND_JMP_FORWARD_SPEC) \ - _(2580, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2581, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2582, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2584, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2568, ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED) \ + _(2569, ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED) \ + _(2570, ZEND_FRAMELESS_ICALL_2_SPEC) \ + _(2571, ZEND_FRAMELESS_ICALL_3_SPEC) \ + _(2572, ZEND_JMP_FRAMELESS_SPEC_CONST) \ + _(2573, ZEND_RECV_NOTYPE_SPEC) \ + _(2575, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ + _(2576, ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED) \ + _(2578, ZEND_COUNT_ARRAY_SPEC_CV_UNUSED) \ + _(2579, ZEND_JMP_FORWARD_SPEC) \ _(2585, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2586, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2587, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2589, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2595, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2596, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2597, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2599, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2605, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2606, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2607, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2609, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2590, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2591, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2592, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2594, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2600, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2601, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2602, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2604, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2610, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ _(2611, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2612, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2614, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2620, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ - _(2621, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2622, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2624, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2630, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2631, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2632, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2634, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2615, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ + _(2616, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2617, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2619, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2625, ZEND_ADD_LONG_SPEC_TMPVARCV_CONST) \ + _(2626, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2627, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2629, ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2635, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2636, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2637, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2639, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2645, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2646, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2647, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2649, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2651, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2652, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2654, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ - _(2655, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2656, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2657, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2659, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2640, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2641, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2642, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2644, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2650, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2651, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2652, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2654, ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2656, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2657, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ + _(2659, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV) \ _(2660, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2661, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2662, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2664, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2670, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2671, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2672, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2674, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2676, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2677, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2679, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ - _(2680, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2681, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2682, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2684, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2665, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2666, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2667, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2669, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2675, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2676, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2677, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2679, ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2681, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2682, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ + _(2684, ZEND_SUB_LONG_SPEC_CONST_TMPVARCV) \ _(2685, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ _(2686, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2687, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2689, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2695, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ - _(2696, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2697, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2699, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2701, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2702, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2704, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(2705, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2706, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2707, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2709, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2690, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ + _(2691, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2692, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2694, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2700, ZEND_SUB_LONG_SPEC_TMPVARCV_CONST) \ + _(2701, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2702, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2704, ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2706, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2707, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(2709, ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV) \ _(2710, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2711, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2712, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2714, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2720, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2721, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2722, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2724, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2730, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2731, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2732, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2734, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2715, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2716, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2717, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2719, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2725, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2726, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2727, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2729, ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2735, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ _(2736, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2737, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2739, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2745, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ - _(2746, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2747, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2749, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ - _(2755, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2756, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2757, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2759, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2740, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2741, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2742, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2744, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2750, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST) \ + _(2751, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2752, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ + _(2754, ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV) \ _(2760, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ _(2761, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2762, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2764, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2770, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ - _(2771, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2772, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2774, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2780, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2781, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2782, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2784, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2765, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ + _(2766, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2767, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2769, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2775, ZEND_MUL_LONG_SPEC_TMPVARCV_CONST) \ + _(2776, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2777, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2779, ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV) \ _(2785, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ _(2786, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2787, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ _(2789, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2795, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2796, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2797, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2799, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2815, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2816, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2817, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2818, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2819, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2820, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2821, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2822, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2823, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2827, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2828, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2829, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2830, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2831, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2832, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2833, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2834, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2835, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2836, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2837, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2842, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2843, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2844, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2860, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2861, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2862, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2863, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2864, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2865, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2866, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2867, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2868, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2872, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2873, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2874, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2890, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2891, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2892, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2893, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2894, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2895, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2896, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2897, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2898, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2902, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2903, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2904, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2905, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2906, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2907, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2908, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2909, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2910, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2911, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2912, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2917, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2918, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2919, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2935, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(2936, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2937, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2938, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2939, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2940, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2941, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2942, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2943, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2947, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(2948, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2949, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2965, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2966, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2967, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2968, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2969, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2970, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2971, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2972, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2973, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2977, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2978, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2979, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2980, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(2981, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(2982, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(2983, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2984, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2985, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2986, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2987, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(2992, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(2993, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(2994, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3010, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3011, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3012, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3013, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3014, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3015, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3016, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3017, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3018, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3022, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3023, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3024, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3040, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3041, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3042, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3043, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3044, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3045, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3046, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3047, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3048, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3052, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3053, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3054, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3055, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3056, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3057, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3058, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3059, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3060, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3061, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3062, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3067, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3068, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3069, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3085, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3086, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3087, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3088, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3089, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3090, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3091, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3092, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3093, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3097, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3098, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3099, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3100, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3104, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3105, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ - _(3109, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ - _(3113, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3114, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3115, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3116, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3117, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3118, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3122, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ - _(3123, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3124, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3125, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3126, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3127, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3128, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3129, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3130, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3131, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3132, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3133, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3137, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3138, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3139, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3140, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3141, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3144, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3145, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3146, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3147, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3153, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3154, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3170, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ - _(3171, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3172, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3173, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3174, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3175, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3176, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3177, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3178, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3182, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3183, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3184, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3188, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3189, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3190, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3191, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3192, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3193, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3197, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3198, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3199, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3200, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3201, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3204, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3205, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3206, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3207, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3208, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3212, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3213, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3214, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3215, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3216, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3219, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3220, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3221, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3222, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3228, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3229, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3245, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3246, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3247, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3248, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3249, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3250, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3251, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3252, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3253, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3257, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3258, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3259, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3263, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3264, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3265, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3266, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3267, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3268, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3272, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ - _(3273, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3274, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3275, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3276, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3279, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3280, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3281, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3282, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3283, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3287, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3288, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3289, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3290, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3291, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3294, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3295, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3296, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3297, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3303, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3304, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3320, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ - _(3321, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3322, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3323, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3324, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3325, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3326, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3327, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3328, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3332, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ - _(3333, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3334, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3338, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3339, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3340, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3341, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3342, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3343, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3347, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ - _(3348, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ - _(3349, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ - _(3350, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3351, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3354, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3355, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3356, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3357, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3358, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3362, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3363, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3364, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3365, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3366, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3369, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3370, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3371, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3372, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3378, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3379, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3395, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ - _(3396, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ - _(3397, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ - _(3398, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3399, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3400, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3401, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3402, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3403, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3407, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ - _(3408, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ - _(3409, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ - _(3410, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3411, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3412, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3413, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ - _(3414, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ - _(3415, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ - _(3416, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ - _(3417, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ - _(3418, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3419, ZEND_POST_INC_LONG_SPEC_CV) \ - _(3420, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ - _(3421, ZEND_POST_DEC_LONG_SPEC_CV) \ - _(3422, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ - _(3423, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3424, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3426, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ - _(3427, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ - _(3428, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3429, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3431, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ - _(3432, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ - _(3433, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3434, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3436, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ - _(3438, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3439, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3441, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ - _(3442, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ - _(3443, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3444, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3446, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(2790, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2791, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2792, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2794, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2800, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2801, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2802, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2804, ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2820, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2821, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2822, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2823, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2824, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2825, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2826, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2827, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2828, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2832, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2833, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2834, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2835, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2836, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2837, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2838, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2839, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2840, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2841, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2842, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2843, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2847, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2848, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2849, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2865, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2866, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2867, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2868, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2869, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2870, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2871, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2872, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2873, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2877, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2878, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2879, ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2895, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2896, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2897, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2898, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2899, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2900, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2901, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2902, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2903, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2907, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2908, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2909, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2910, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2911, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2912, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2913, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2914, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2915, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2916, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2917, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2918, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2922, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2923, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2924, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2940, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(2941, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2942, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2943, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2944, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2945, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2946, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2947, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2948, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2952, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(2953, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2954, ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2970, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2971, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2972, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2973, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2974, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2975, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2976, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2977, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2978, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2982, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2983, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2984, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2985, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(2986, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(2987, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(2988, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2989, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2990, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2991, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2992, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2993, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(2997, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(2998, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(2999, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3015, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3016, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3017, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3018, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3019, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3020, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3021, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3022, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3023, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3027, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3028, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3029, ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3045, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3046, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3047, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3048, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3049, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3050, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3051, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3052, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3053, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3057, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3058, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3059, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3060, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3061, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3062, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3063, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3064, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3065, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3066, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3067, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3068, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3072, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3073, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3074, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3090, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3091, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3092, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3093, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3094, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3095, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3096, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3097, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3098, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3102, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3103, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3104, ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3105, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3109, ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3110, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST) \ + _(3114, ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV) \ + _(3118, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3119, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3120, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3121, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3122, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3123, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3127, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV) \ + _(3128, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3129, ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3130, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3131, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3132, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3133, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3134, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3135, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3136, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3137, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3138, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3142, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3143, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3144, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3145, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3146, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3147, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3148, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3149, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3150, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3151, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3152, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3153, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3157, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3158, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3159, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3175, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST) \ + _(3176, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3177, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3178, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3179, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3180, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3181, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3182, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3183, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3187, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3188, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3189, ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3193, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3194, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3195, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3196, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3197, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3198, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3202, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3203, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3204, ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3205, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3206, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3207, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3208, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3209, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3210, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3211, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3212, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3213, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3217, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3218, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3219, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3220, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3221, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3222, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3223, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3224, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3225, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3226, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3227, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3228, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3232, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3233, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3234, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3250, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3251, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3252, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3253, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3254, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3255, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3256, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3257, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3258, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3262, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3263, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3264, ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3268, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3269, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3270, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3271, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3272, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3273, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3277, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV) \ + _(3278, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3279, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3280, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3281, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3282, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3283, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3284, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3285, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3286, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3287, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3288, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3292, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3293, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3294, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3295, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3296, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3297, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3298, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3299, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3300, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3301, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3302, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3303, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3307, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3308, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3309, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3325, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST) \ + _(3326, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3327, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3328, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3329, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3330, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3331, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3332, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3333, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3337, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV) \ + _(3338, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3339, ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3343, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3344, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3345, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3346, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3347, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3348, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3352, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV) \ + _(3353, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ) \ + _(3354, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ) \ + _(3355, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3356, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3357, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3358, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3359, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3360, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3361, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3362, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3363, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3367, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3368, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3369, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3370, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3371, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3372, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3373, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3374, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3375, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3376, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3377, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3378, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3382, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3383, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3384, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3400, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST) \ + _(3401, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ) \ + _(3402, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ) \ + _(3403, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3404, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3405, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3406, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3407, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3408, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3412, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV) \ + _(3413, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ) \ + _(3414, ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ) \ + _(3415, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3416, ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3417, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3418, ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED) \ + _(3419, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED) \ + _(3420, ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED) \ + _(3421, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED) \ + _(3422, ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED) \ + _(3423, ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3424, ZEND_POST_INC_LONG_SPEC_CV) \ + _(3425, ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV) \ + _(3426, ZEND_POST_DEC_LONG_SPEC_CV) \ + _(3427, ZEND_QM_ASSIGN_LONG_SPEC_CONST) \ + _(3428, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3429, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3431, ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV) \ + _(3432, ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST) \ + _(3433, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3434, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3436, ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV) \ + _(3437, ZEND_QM_ASSIGN_NOREF_SPEC_CONST) \ + _(3438, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3439, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3441, ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV) \ + _(3443, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3444, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ + _(3446, ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV) \ _(3447, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ _(3448, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ _(3449, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ _(3451, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ - _(3457, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ - _(3458, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3459, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3461, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ - _(3464, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ - _(3466, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ - _(3469, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ - _(3471, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ - _(3472, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ - _(3473, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ - _(3474, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ - _(3475, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ - _(3475+1, ZEND_NULL) + _(3452, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST) \ + _(3453, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3454, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3456, ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV) \ + _(3462, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST) \ + _(3463, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3464, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3466, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV) \ + _(3469, ZEND_SEND_VAR_SIMPLE_SPEC_VAR) \ + _(3471, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \ + _(3474, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED) \ + _(3476, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED) \ + _(3477, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \ + _(3478, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \ + _(3479, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \ + _(3480, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \ + _(3480+1, ZEND_NULL) diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index e94b6c7d5f0cd..218a55a8f4e8b 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -22,7 +22,7 @@ #include #include -static const char *zend_vm_opcodes_names[204] = { +static const char *zend_vm_opcodes_names[209] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -227,9 +227,14 @@ static const char *zend_vm_opcodes_names[204] = { "ZEND_VERIFY_NEVER_TYPE", "ZEND_CALLABLE_CONVERT", "ZEND_BIND_INIT_STATIC_OR_JMP", + "ZEND_FRAMELESS_ICALL_0", + "ZEND_FRAMELESS_ICALL_1", + "ZEND_FRAMELESS_ICALL_2", + "ZEND_FRAMELESS_ICALL_3", + "ZEND_JMP_FRAMELESS", }; -static uint32_t zend_vm_opcodes_flags[204] = { +static uint32_t zend_vm_opcodes_flags[209] = { 0x00000000, 0x00000b0b, 0x00000b0b, @@ -434,6 +439,11 @@ static uint32_t zend_vm_opcodes_flags[204] = { 0x00000101, 0x00000101, 0x00002001, + 0x00000101, + 0x00000100, + 0x00000000, + 0x00000000, + 0x01042003, }; ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 17453f0aed652..a273a9b7e2de0 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -286,7 +286,12 @@ END_EXTERN_C() #define ZEND_VERIFY_NEVER_TYPE 201 #define ZEND_CALLABLE_CONVERT 202 #define ZEND_BIND_INIT_STATIC_OR_JMP 203 +#define ZEND_FRAMELESS_ICALL_0 204 +#define ZEND_FRAMELESS_ICALL_1 205 +#define ZEND_FRAMELESS_ICALL_2 206 +#define ZEND_FRAMELESS_ICALL_3 207 +#define ZEND_JMP_FRAMELESS 208 -#define ZEND_VM_LAST_OPCODE 203 +#define ZEND_VM_LAST_OPCODE 208 #endif diff --git a/build/gen_stub.php b/build/gen_stub.php index 5220d1de1a7bc..eda2250723ee5 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1060,6 +1060,11 @@ public function getArgInfoName(): string { return "arginfo_$underscoreName"; } + public function getFramelessFunctionInfosName(): string { + $underscoreName = implode('_', $this->name->getParts()); + return "frameless_function_infos_$underscoreName"; + } + public function getMethodSynopsisFilename(): string { return 'functions/' . implode('/', str_replace('_', '-', $this->name->getParts())); } @@ -1217,6 +1222,7 @@ class FuncInfo { public bool $isUndocumentable; /** @var AttributeInfo[] */ public array $attributes; + public array $framelessFunctionInfos; /** * @param AttributeInfo[] $attributes @@ -1236,7 +1242,8 @@ public function __construct( int $numRequiredArgs, ?string $cond, bool $isUndocumentable, - array $attributes + array $attributes, + array $framelessFunctionInfos ) { $this->name = $name; $this->classFlags = $classFlags; @@ -1252,6 +1259,7 @@ public function __construct( $this->cond = $cond; $this->isUndocumentable = $isUndocumentable; $this->attributes = $attributes; + $this->framelessFunctionInfos = $framelessFunctionInfos; } public function isMethod(): bool @@ -1348,6 +1356,10 @@ public function getDeclaration(): ?string return $name->getDeclaration(); } + public function getFramelessFunctionInfosName(): string { + return $this->name->getFramelessFunctionInfosName(); + } + public function getFunctionEntry(): string { if ($this->name instanceof MethodName) { if ($this->alias) { @@ -1387,6 +1399,20 @@ public function getFunctionEntry(): string { $functionName = $this->name->getFunctionName(); $declarationName = $this->alias ? $this->alias->getNonNamespacedName() : $this->name->getDeclarationName(); + if (!empty($this->framelessFunctionInfos)) { + if ($namespace) { + die('Namespaced direct calls are not supported yet'); + } + if ($this->alias) { + die('Aliased direct calls are not supported yet'); + } + $flags = $this->supportsCompileTimeEval ? 'ZEND_ACC_COMPILE_TIME_EVAL' : '0'; + return sprintf( + "\tZEND_FRAMELESS_FE(%s, %s, %s, %s)\n", + $functionName, $this->getArgInfoName(), $flags, $this->getFramelessFunctionInfosName() + ); + } + if ($namespace) { // Namespaced functions are always declared as aliases to avoid name conflicts when two functions with // the same name exist in separate namespaces @@ -3819,6 +3845,18 @@ function parseDocComment(DocComment $comment): array { return $tags; } +class FramelessFunctionInfo { + public int $arity; +} + +function parseFramelessFunctionInfo(string $json): FramelessFunctionInfo { + // FIXME: Should have some validation + $json = json_decode($json, true); + $framelessFunctionInfo = new FramelessFunctionInfo(); + $framelessFunctionInfo->arity = $json["arity"]; + return $framelessFunctionInfo; +} + function parseFunctionLike( PrettyPrinterAbstract $prettyPrinter, FunctionOrMethodName $name, @@ -3840,6 +3878,7 @@ function parseFunctionLike( $tentativeReturnType = false; $docParamTypes = []; $refcount = null; + $framelessFunctionInfos = []; if ($comment) { $tags = parseDocComment($comment); @@ -3895,6 +3934,10 @@ function parseFunctionLike( case 'undocumentable': $isUndocumentable = true; break; + + case 'frameless-function': + $framelessFunctionInfos[] = parseFramelessFunctionInfo($tag->getValue()); + break; } } } @@ -3991,7 +4034,8 @@ function parseFunctionLike( $numRequiredArgs, $cond, $isUndocumentable, - createAttributes($func->attrGroups) + createAttributes($func->attrGroups), + $framelessFunctionInfos ); } catch (Exception $e) { throw new Exception($name . "(): " .$e->getMessage()); @@ -4588,6 +4632,25 @@ function findEquivalentFuncInfo(array $generatedFuncInfos, FuncInfo $funcInfo): return null; } +function framelessFunctionInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): ?string { + if (empty($funcInfo->framelessFunctionInfos)) { + return null; + } + + $code = ''; + foreach ($funcInfo->framelessFunctionInfos as $framelessFunctionInfo) { + $code .= "ZEND_FRAMELESS_FUNCTION({$funcInfo->name->getFunctionName()}, {$framelessFunctionInfo->arity});\n"; + } + + $code .= 'static const zend_frameless_function_info ' . $funcInfo->getFramelessFunctionInfosName() . "[] = {\n"; + foreach ($funcInfo->framelessFunctionInfos as $framelessFunctionInfo) { + $code .= "\t{ ZEND_FRAMELESS_FUNCTION_NAME({$funcInfo->name->getFunctionName()}, {$framelessFunctionInfo->arity}), {$framelessFunctionInfo->arity} },\n"; + } + $code .= "\t{ 0 },\n"; + $code .= "};\n"; + return $code; +} + /** * @template T * @param iterable $infos @@ -4647,6 +4710,14 @@ static function (FuncInfo $funcInfo) use (&$generatedFuncInfos, $fileInfo) { } ); + $code .= generateCodeWithConditions( + $fileInfo->getAllFuncInfos(), "\n", + static function (FuncInfo $funcInfo) use ($fileInfo) { + $code = framelessFunctionInfoToCode($fileInfo, $funcInfo); + return $code; + } + ); + if ($fileInfo->generateFunctionEntries) { $code .= "\n\n"; diff --git a/configure.ac b/configure.ac index 8792c80b30536..6590b37592851 100644 --- a/configure.ac +++ b/configure.ac @@ -1740,6 +1740,7 @@ PHP_ADD_SOURCES(Zend, \ zend_observer.c zend_system_id.c zend_enum.c zend_fibers.c zend_atomic.c \ zend_max_execution_timer.c \ zend_hrtime.c \ + zend_frameless_function.c \ Optimizer/zend_optimizer.c \ Optimizer/pass1.c \ Optimizer/pass3.c \ diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 39562696d4595..294ed1db8eaf7 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -282,6 +282,7 @@ static int zend_jit_needs_call_chain(zend_call_info *call_info, uint32_t b, cons case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: return 1; case ZEND_DO_ICALL: case ZEND_DO_UCALL: @@ -365,6 +366,7 @@ static int zend_jit_needs_call_chain(zend_call_info *call_info, uint32_t b, cons case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: case ZEND_BIND_INIT_STATIC_OR_JMP: + case ZEND_JMP_FRAMELESS: return 1; case ZEND_DO_ICALL: case ZEND_DO_UCALL: @@ -2557,6 +2559,11 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op goto jit_failure; } break; + case ZEND_JMP_FRAMELESS: + if (!zend_jit_jmp_frameless(&ctx, opline, /* exit_addr */ NULL, /* guard */ 0)) { + goto jit_failure; + } + break; case ZEND_NEW: if (!zend_jit_handler(&ctx, opline, 1)) { return 0; @@ -2594,6 +2601,23 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op call_level--; } break; + case ZEND_FRAMELESS_ICALL_0: + jit_frameless_icall0(jit, opline); + goto done; + case ZEND_FRAMELESS_ICALL_1: + op1_info = OP1_INFO(); + jit_frameless_icall1(jit, opline, op1_info); + goto done; + case ZEND_FRAMELESS_ICALL_2: + op1_info = OP1_INFO(); + op2_info = OP2_INFO(); + jit_frameless_icall2(jit, opline, op1_info, op2_info); + goto done; + case ZEND_FRAMELESS_ICALL_3: + op1_info = OP1_INFO(); + op2_info = OP2_INFO(); + jit_frameless_icall3(jit, opline, op1_info, op2_info, OP1_DATA_INFO()); + goto done; default: if (!zend_jit_handler(&ctx, opline, zend_may_throw(opline, ssa_op, op_array, ssa))) { diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index dab251056ba18..7d2c89caa08fe 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -67,6 +67,14 @@ static zend_function* ZEND_FASTCALL zend_jit_find_func_helper(zend_string *name, return fbc; } +static uint32_t ZEND_FASTCALL zend_jit_jmp_frameless_helper(zval *func_name, void **cache_slot) +{ + zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name)); + zend_jmp_fl_result result = (func == NULL) + 1; + *cache_slot = (void *)(uintptr_t)result; + return result; +} + static zend_function* ZEND_FASTCALL zend_jit_find_ns_func_helper(zval *func_name, void **cache_slot) { zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1)); diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 79e11aef1c152..f9843aadc93c6 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -2997,6 +2997,7 @@ static void zend_jit_setup_disasm(void) REGISTER_HELPER(zend_jit_init_func_run_time_cache_helper); REGISTER_HELPER(zend_jit_find_func_helper); REGISTER_HELPER(zend_jit_find_ns_func_helper); + REGISTER_HELPER(zend_jit_jmp_frameless_helper); REGISTER_HELPER(zend_jit_unref_helper); REGISTER_HELPER(zend_jit_invalid_method_call); REGISTER_HELPER(zend_jit_invalid_method_call_tmp); @@ -3776,6 +3777,45 @@ static int jit_CMP_IP(zend_jit_ctx *jit, ir_op op, const zend_op *next_opline) return ref; } +static int zend_jit_jmp_frameless( + zend_jit_ctx *jit, + const zend_op *opline, + const void *exit_addr, + zend_jmp_fl_result guard +) { + ir_ref ref, if_ref, cache_result, function_result, phi_result, cache_slot_ref; + zend_basic_block *bb; + + // JIT: CACHED_PTR(opline->extended_value) + cache_slot_ref = ir_ADD_OFFSET(ir_LOAD_A(jit_EX(run_time_cache)), opline->extended_value); + cache_result = ir_LOAD_L(cache_slot_ref); + + // JIT: if (UNEXPECTED(!result)) + if_ref = ir_IF(cache_result); + ir_IF_FALSE_cold(if_ref); + zval *func_name_zv = RT_CONSTANT(opline, opline->op1); + function_result = ir_CALL_2(IR_LONG, ir_CONST_FC_FUNC(zend_jit_jmp_frameless_helper), + ir_CONST_ADDR(func_name_zv), + cache_slot_ref); + ir_MERGE_WITH_EMPTY_TRUE(if_ref); + + phi_result = ir_PHI_2(IR_LONG, function_result, cache_result); + + if (exit_addr) { + ir_GUARD(ir_EQ(phi_result, ir_CONST_LONG(guard)), ir_CONST_ADDR(exit_addr)); + } else { + ZEND_ASSERT(jit->b >= 0); + bb = &jit->ssa->cfg.blocks[jit->b]; + // JIT: if (result == ZEND_JMP_FL_HIT) + ref = jit_IF_ex(jit, ir_EQ(phi_result, ir_CONST_LONG(ZEND_JMP_FL_HIT)), bb->successors[0]); + _zend_jit_add_predecessor_ref(jit, bb->successors[0], jit->b, ref); + _zend_jit_add_predecessor_ref(jit, bb->successors[1], jit->b, ref); + jit->b = -1; + } + + return 1; +} + static int zend_jit_cond_jmp(zend_jit_ctx *jit, const zend_op *next_opline, int target_block) { ir_ref ref; @@ -16641,6 +16681,150 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa, return 1; } +static void jit_frameless_icall0(zend_jit_ctx *jit, const zend_op *opline) +{ + jit_SET_EX_OPLINE(jit, opline); + + void *function = ZEND_FLF_HANDLER(opline); + zend_jit_addr res_addr = RES_ADDR(); + ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr); + jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); + ir_CALL_1(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref); + zend_jit_check_exception(jit); +} + +static void jit_frameless_icall1(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info) +{ + jit_SET_EX_OPLINE(jit, opline); + + /* Avoid dropping RC check in case op escapes. */ + if (op1_info & MAY_BE_RC1) { + op1_info |= MAY_BE_RCN; + } + + void *function = ZEND_FLF_HANDLER(opline); + zend_jit_addr res_addr = RES_ADDR(); + zend_jit_addr op1_addr = OP1_ADDR(); + ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr); + ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr); + jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); + if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { + zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + } + if (op1_info & MAY_BE_REF) { + op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref); + } + ir_CALL_2(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref); + jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL); + zend_jit_check_exception(jit); +} + +static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info, uint32_t op2_info) +{ + jit_SET_EX_OPLINE(jit, opline); + + /* Avoid dropping RC check in case op escapes. */ + if (op1_info & MAY_BE_RC1) { + op1_info |= MAY_BE_RCN; + } + if (op2_info & MAY_BE_RC1) { + op2_info |= MAY_BE_RCN; + } + + void *function = ZEND_FLF_HANDLER(opline); + zend_jit_addr res_addr = RES_ADDR(); + zend_jit_addr op1_addr = OP1_ADDR(); + zend_jit_addr op2_addr = OP2_ADDR(); + ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr); + ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr); + ir_ref op2_ref = jit_ZVAL_ADDR(jit, op2_addr); + jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); + if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { + zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + } + if (opline->op2_type == IS_CV && (op2_info & MAY_BE_UNDEF)) { + zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, 1); + } + if (op1_info & MAY_BE_REF) { + op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref); + } + if (op2_info & MAY_BE_REF) { + op2_ref = jit_ZVAL_DEREF_ref(jit, op2_ref); + } + ir_CALL_3(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref, op2_ref); + jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL); + /* Set OP1 to UNDEF in case FREE_OP2() throws. */ + if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) != 0 && (opline->op2_type & (IS_VAR|IS_TMP_VAR)) != 0) { + jit_set_Z_TYPE_INFO(jit, op1_addr, IS_UNDEF); + } + jit_FREE_OP(jit, opline->op2_type, opline->op2, op2_info, NULL); + zend_jit_check_exception(jit); +} + +static 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) +{ + jit_SET_EX_OPLINE(jit, opline); + + /* Avoid dropping RC check in case op escapes. */ + if (op1_info & MAY_BE_RC1) { + op1_info |= MAY_BE_RCN; + } + if (op2_info & MAY_BE_RC1) { + op2_info |= MAY_BE_RCN; + } + if (op1_data_info & MAY_BE_RC1) { + op1_data_info |= MAY_BE_RCN; + } + + void *function = ZEND_FLF_HANDLER(opline); + uint8_t op_data_type = (opline + 1)->op1_type; + zend_jit_addr res_addr = RES_ADDR(); + zend_jit_addr op1_addr = OP1_ADDR(); + zend_jit_addr op2_addr = OP2_ADDR(); + zend_jit_addr op3_addr = OP1_DATA_ADDR(); + ir_ref res_ref = jit_ZVAL_ADDR(jit, res_addr); + ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr); + ir_ref op2_ref = jit_ZVAL_ADDR(jit, op2_addr); + ir_ref op3_ref = jit_ZVAL_ADDR(jit, op3_addr); + jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); + if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { + zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + } + if (opline->op2_type == IS_CV && (op2_info & MAY_BE_UNDEF)) { + zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, 1); + } + if ((opline+1)->op1_type == IS_CV && (op1_data_info & MAY_BE_UNDEF)) { + zend_jit_zval_check_undef(jit, op3_ref, (opline+1)->op1.var, opline, 1); + } + if (op1_info & MAY_BE_REF) { + op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref); + } + if (op2_info & MAY_BE_REF) { + op2_ref = jit_ZVAL_DEREF_ref(jit, op2_ref); + } + if (op1_data_info & MAY_BE_REF) { + op3_ref = jit_ZVAL_DEREF_ref(jit, op3_ref); + } + ir_CALL_4(IR_VOID, ir_CONST_ADDR((size_t)function), res_ref, op1_ref, op2_ref, op3_ref); + jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, NULL); + /* Set OP1 to UNDEF in case FREE_OP2() throws. */ + if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) + && ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) + || (op_data_type & (IS_VAR|IS_TMP_VAR)))) { + jit_set_Z_TYPE_INFO(jit, op1_addr, IS_UNDEF); + } + jit_FREE_OP(jit, opline->op2_type, opline->op2, op2_info, NULL); + /* If OP1 is a TMP|VAR, we don't need to set OP2 to UNDEF on free because + * zend_fetch_debug_backtrace aborts when it encounters the first UNDEF TMP|VAR. */ + if (!(opline->op1_type & (IS_VAR|IS_TMP_VAR)) + && (opline->op2_type & (IS_VAR|IS_TMP_VAR)) != 0 + && (op_data_type & (IS_VAR|IS_TMP_VAR)) != 0) { + jit_set_Z_TYPE_INFO(jit, op2_addr, IS_UNDEF); + } + jit_FREE_OP(jit, (opline+1)->op1_type, (opline+1)->op1, op1_data_info, NULL); + zend_jit_check_exception(jit); +} + /* * Local variables: * tab-width: 4 diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 7f263fed93d0c..5fcc2577ab648 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -598,6 +598,7 @@ static zend_always_inline int zend_jit_trace_op_len(const zend_op *opline) case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_ASSIGN_OBJ_REF: case ZEND_ASSIGN_STATIC_PROP_REF: + case ZEND_FRAMELESS_ICALL_3: return 2; /* OP_DATA */ case ZEND_RECV_INIT: len = 1; @@ -3008,6 +3009,7 @@ static zend_jit_reg_var* zend_jit_trace_allocate_registers(zend_jit_trace_rec *t case ZEND_ASSIGN_STATIC_PROP_OP: case ZEND_ASSIGN_OBJ_REF: case ZEND_ASSIGN_STATIC_PROP_REF: + case ZEND_FRAMELESS_ICALL_3: /* OP_DATA */ ssa_op++; opline++; @@ -5560,6 +5562,33 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par goto jit_failure; } goto done; + case ZEND_JMP_FRAMELESS: + op1_info = OP1_INFO(); + ZEND_ASSERT((p+1)->op == ZEND_JIT_TRACE_VM); + const zend_op *exit_opline = NULL; + uint32_t exit_point; + zend_jmp_fl_result guard; + + if ((p+1)->opline == OP_JMP_ADDR(opline, opline->op2)) { + /* taken branch */ + guard = ZEND_JMP_FL_HIT; + exit_opline = opline + 1; + } else if ((p+1)->opline == opline + 1) { + /* not taken branch */ + guard = ZEND_JMP_FL_MISS; + exit_opline = OP_JMP_ADDR(opline, opline->op2); + } else { + ZEND_UNREACHABLE(); + } + exit_point = zend_jit_trace_get_exit_point(exit_opline, 0); + exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + goto jit_failure; + } + if (!zend_jit_jmp_frameless(&ctx, opline, exit_addr, guard)) { + goto jit_failure; + } + goto done; case ZEND_ISSET_ISEMPTY_CV: if ((opline->extended_value & ZEND_ISEMPTY)) { // TODO: support for empty() ??? @@ -6209,6 +6238,23 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par goto jit_failure; } goto done; + case ZEND_FRAMELESS_ICALL_0: + jit_frameless_icall0(jit, opline); + goto done; + case ZEND_FRAMELESS_ICALL_1: + op1_info = OP1_INFO(); + jit_frameless_icall1(jit, opline, op1_info); + goto done; + case ZEND_FRAMELESS_ICALL_2: + op1_info = OP1_INFO(); + op2_info = OP2_INFO(); + jit_frameless_icall2(jit, opline, op1_info, op2_info); + goto done; + case ZEND_FRAMELESS_ICALL_3: + op1_info = OP1_INFO(); + op2_info = OP2_INFO(); + jit_frameless_icall3(jit, opline, op1_info, op2_info, OP1_DATA_INFO()); + goto done; default: break; } diff --git a/ext/opcache/tests/ct_eval_frameless_001.phpt b/ext/opcache/tests/ct_eval_frameless_001.phpt new file mode 100644 index 0000000000000..c5ab4b3d9a934 --- /dev/null +++ b/ext/opcache/tests/ct_eval_frameless_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +Test ct eval of frameless function +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.opt_debug_level=0x20000 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=2, args=0, vars=0, tmps=0) + ; (after optimizer) + ; %sct_eval_frameless_001.php:1-4 +0000 ECHO string("%sopcache") +0001 RETURN int(1) +%sopcache diff --git a/ext/opcache/tests/ct_eval_frameless_002.phpt b/ext/opcache/tests/ct_eval_frameless_002.phpt new file mode 100644 index 0000000000000..481d3553bb124 --- /dev/null +++ b/ext/opcache/tests/ct_eval_frameless_002.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test ct eval of frameless function +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.opt_debug_level=0x20000 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=3, args=0, vars=1, tmps=0) + ; (after optimizer) + ; %sct_eval_frameless_002.php:1-4 +0000 CHECK_VAR CV0($foo) +0001 ECHO string("o") +0002 RETURN int(1) + +Warning: Undefined variable $foo in %s on line %d +o diff --git a/ext/opcache/tests/ct_eval_frameless_003.phpt b/ext/opcache/tests/ct_eval_frameless_003.phpt new file mode 100644 index 0000000000000..0a556a8087a6a --- /dev/null +++ b/ext/opcache/tests/ct_eval_frameless_003.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test ct eval of frameless function +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECT-- +1 diff --git a/ext/opcache/tests/opt/inference_frameless.phpt b/ext/opcache/tests/opt/inference_frameless.phpt new file mode 100644 index 0000000000000..9f37c3159c40e --- /dev/null +++ b/ext/opcache/tests/opt/inference_frameless.phpt @@ -0,0 +1,28 @@ +--TEST-- +Type inference of frameless functions +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.opt_debug_level=0x20000 +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=1, args=0, vars=0, tmps=0) + ; (after optimizer) + ; %sinference_frameless.php:1-6 +0000 RETURN int(1) + +_strpos: + ; (lines=4, args=1, vars=1, tmps=1) + ; (after optimizer) + ; %sinference_frameless.php:2-4 +0000 CV0($str) = RECV 1 +0001 T1 = FRAMELESS_ICALL_3(strpos) CV0($str) string("o") +0002 OP_DATA int(1) +0003 RETURN T1 diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 563dce2157c7c..c14cc524c5b3a 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1462,6 +1462,30 @@ PHP_FUNCTION(preg_match) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(preg_match, 2) +{ + zval regex_tmp, subject_tmp; + zend_string *regex, *subject; + + Z_FLF_PARAM_STR(1, regex, regex_tmp); + Z_FLF_PARAM_STR(2, subject, subject_tmp); + + /* Compile regex or get it from cache. */ + pcre_cache_entry *pce; + if ((pce = pcre_get_compiled_regex_cache(regex)) == NULL) { + RETURN_FALSE; + } + + pce->refcount++; + php_pcre_match_impl(pce, subject, return_value, /* subpats */ NULL, + /* global */ false, /* flags */ 0, /* start_offset */ 0); + pce->refcount--; + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, regex_tmp); + Z_FLF_PARAM_FREE_STR(2, subject_tmp); +} + /* {{{ Perform a Perl-style global regular expression match */ PHP_FUNCTION(preg_match_all) { @@ -2237,31 +2261,19 @@ static size_t preg_replace_func_impl(zval *return_value, } /* }}} */ -/* {{{ preg_replace_common */ -static void preg_replace_common(INTERNAL_FUNCTION_PARAMETERS, bool is_filter) -{ - zval *zcount = NULL; - zend_string *regex_str; - HashTable *regex_ht; - zend_string *replace_str; - HashTable *replace_ht; - zend_string *subject_str; - HashTable *subject_ht; - zend_long limit = -1; +static void _preg_replace_common( + zval *return_value, + HashTable *regex_ht, zend_string *regex_str, + HashTable *replace_ht, zend_string *replace_str, + HashTable *subject_ht, zend_string *subject_str, + zend_long limit, + zval *zcount, + bool is_filter +) { size_t replace_count = 0; zend_string *result; size_t old_replace_count; - /* Get function parameters and do error-checking. */ - ZEND_PARSE_PARAMETERS_START(3, 5) - Z_PARAM_ARRAY_HT_OR_STR(regex_ht, regex_str) - Z_PARAM_ARRAY_HT_OR_STR(replace_ht, replace_str) - Z_PARAM_ARRAY_HT_OR_STR(subject_ht, subject_str) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(limit) - Z_PARAM_ZVAL(zcount) - ZEND_PARSE_PARAMETERS_END(); - /* If replace is an array then the regex argument needs to also be an array */ if (replace_ht && !regex_ht) { zend_argument_type_error(1, "must be of type array when argument #2 ($replacement) is an array, string given"); @@ -2323,6 +2335,32 @@ static void preg_replace_common(INTERNAL_FUNCTION_PARAMETERS, bool is_filter) ZEND_TRY_ASSIGN_REF_LONG(zcount, replace_count); } } + +/* {{{ preg_replace_common */ +static void preg_replace_common(INTERNAL_FUNCTION_PARAMETERS, bool is_filter) +{ + zend_string *regex_str, *replace_str, *subject_str; + HashTable *regex_ht, *replace_ht, *subject_ht; + zend_long limit = -1; + zval *zcount = NULL; + + /* Get function parameters and do error-checking. */ + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_ARRAY_HT_OR_STR(regex_ht, regex_str) + Z_PARAM_ARRAY_HT_OR_STR(replace_ht, replace_str) + Z_PARAM_ARRAY_HT_OR_STR(subject_ht, subject_str) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(limit) + Z_PARAM_ZVAL(zcount) + ZEND_PARSE_PARAMETERS_END(); + + _preg_replace_common( + return_value, + regex_ht, regex_str, + replace_ht, replace_str, + subject_ht, subject_str, + limit, zcount, is_filter); +} /* }}} */ /* {{{ Perform Perl-style regular expression replacement. */ @@ -2332,6 +2370,29 @@ PHP_FUNCTION(preg_replace) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(preg_replace, 3) +{ + zend_string *regex_str, *replace_str, *subject_str; + HashTable *regex_ht, *replace_ht, *subject_ht; + zval regex_tmp, replace_tmp, subject_tmp; + + Z_FLF_PARAM_ARRAY_HT_OR_STR(1, regex_ht, regex_str, regex_tmp); + Z_FLF_PARAM_ARRAY_HT_OR_STR(2, replace_ht, replace_str, replace_tmp); + Z_FLF_PARAM_ARRAY_HT_OR_STR(3, subject_ht, subject_str, subject_tmp); + + _preg_replace_common( + return_value, + regex_ht, regex_str, + replace_ht, replace_str, + subject_ht, subject_str, + /* limit */ -1, /* zcount */ NULL, /* is_filter */ false); + +flf_clean:; + Z_FLF_PARAM_FREE_STR(1, regex_tmp); + Z_FLF_PARAM_FREE_STR(2, replace_tmp); + Z_FLF_PARAM_FREE_STR(3, subject_tmp); +} + /* {{{ Perform Perl-style regular expression replacement using replacement callback. */ PHP_FUNCTION(preg_replace_callback) { diff --git a/ext/pcre/php_pcre.stub.php b/ext/pcre/php_pcre.stub.php index 1b06075885ba6..0cd045b7efaed 100644 --- a/ext/pcre/php_pcre.stub.php +++ b/ext/pcre/php_pcre.stub.php @@ -98,7 +98,10 @@ */ const PCRE_JIT_SUPPORT = UNKNOWN; -/** @param array $matches */ +/** + * @param array $matches + * @frameless-function {"arity": 2} + */ function preg_match(string $pattern, string $subject, &$matches = null, int $flags = 0, int $offset = 0): int|false {} /** @param array $matches */ @@ -107,6 +110,7 @@ function preg_match_all(string $pattern, string $subject, &$matches = null, int /** * @param int $count * @return string|array|null + * @frameless-function {"arity": 3} */ function preg_replace(string|array $pattern, string|array $replacement, string|array $subject, int $limit = -1, &$count = null): string|array|null {} diff --git a/ext/pcre/php_pcre_arginfo.h b/ext/pcre/php_pcre_arginfo.h index a4132e28e598c..e4570e0279e54 100644 --- a/ext/pcre/php_pcre_arginfo.h +++ b/ext/pcre/php_pcre_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7f27807e45df9c9b5011aa20263c9789896acfbc */ + * Stub hash: 63de1d37ab303e1d6af7c96eaeeba09d7f35d116 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_preg_match, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, pattern, IS_STRING, 0) @@ -62,6 +62,18 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_preg_last_error_msg, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_FRAMELESS_FUNCTION(preg_match, 2); +static const zend_frameless_function_info frameless_function_infos_preg_match[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(preg_match, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(preg_replace, 3); +static const zend_frameless_function_info frameless_function_infos_preg_replace[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(preg_replace, 3), 3 }, + { 0 }, +}; + ZEND_FUNCTION(preg_match); ZEND_FUNCTION(preg_match_all); @@ -77,9 +89,9 @@ ZEND_FUNCTION(preg_last_error_msg); static const zend_function_entry ext_functions[] = { - ZEND_FE(preg_match, arginfo_preg_match) + ZEND_FRAMELESS_FE(preg_match, arginfo_preg_match, 0, frameless_function_infos_preg_match) ZEND_FE(preg_match_all, arginfo_preg_match_all) - ZEND_FE(preg_replace, arginfo_preg_replace) + ZEND_FRAMELESS_FE(preg_replace, arginfo_preg_replace, 0, frameless_function_infos_preg_replace) ZEND_FE(preg_filter, arginfo_preg_filter) ZEND_FE(preg_replace_callback, arginfo_preg_replace_callback) ZEND_FE(preg_replace_callback_array, arginfo_preg_replace_callback_array) diff --git a/ext/standard/array.c b/ext/standard/array.c index a13361bddc6a5..850e8fa4502fe 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -42,6 +42,7 @@ #include "zend_exceptions.h" #include "ext/spl/spl_array.h" #include "ext/random/php_random.h" +#include "zend_frameless_function.h" /* {{{ defines */ @@ -1285,6 +1286,45 @@ PHP_FUNCTION(min) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(min, 2) +{ + zval *lhs, *rhs; + + Z_FLF_PARAM_ZVAL(1, lhs); + Z_FLF_PARAM_ZVAL(2, rhs); + + double lhs_dval; + + if (Z_TYPE_P(lhs) == IS_LONG) { + zend_long lhs_lval = Z_LVAL_P(lhs); + + if (EXPECTED(Z_TYPE_P(rhs) == IS_LONG)) { + RETURN_COPY_VALUE(lhs_lval < Z_LVAL_P(rhs) ? lhs : rhs); + } else if (Z_TYPE_P(rhs) == IS_DOUBLE && (zend_dval_to_lval((double) lhs_lval) == lhs_lval)) { + /* if lhs_lval can be exactly represented as a double, go to double dedicated code */ + lhs_dval = (double) lhs_lval; + goto double_compare; + } else { + goto generic_compare; + } + } else if (Z_TYPE_P(lhs) == IS_DOUBLE) { + lhs_dval = Z_DVAL_P(lhs); + + if (EXPECTED(Z_TYPE_P(rhs) == IS_DOUBLE)) { +double_compare: + RETURN_COPY_VALUE(lhs_dval < Z_DVAL_P(rhs) ? lhs : rhs); + } else if (Z_TYPE_P(rhs) == IS_LONG && (zend_dval_to_lval((double) Z_LVAL_P(rhs)) == Z_LVAL_P(rhs))) { + /* if the value can be exactly represented as a double, use double dedicated code otherwise generic */ + RETURN_COPY_VALUE(lhs_dval < (double)Z_LVAL_P(rhs) ? lhs : rhs); + } else { + goto generic_compare; + } + } else { +generic_compare: + RETURN_COPY(zend_compare(lhs, rhs) < 0 ? lhs : rhs); + } +} + /* {{{ * proto mixed max(array values) * proto mixed max(mixed arg1 [, mixed arg2 [, mixed ...]]) @@ -1374,6 +1414,45 @@ PHP_FUNCTION(max) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(max, 2) +{ + zval *lhs, *rhs; + + Z_FLF_PARAM_ZVAL(1, lhs); + Z_FLF_PARAM_ZVAL(2, rhs); + + double lhs_dval; + + if (Z_TYPE_P(lhs) == IS_LONG) { + zend_long lhs_lval = Z_LVAL_P(lhs); + + if (EXPECTED(Z_TYPE_P(rhs) == IS_LONG)) { + RETURN_COPY_VALUE(lhs_lval >= Z_LVAL_P(rhs) ? lhs : rhs); + } else if (Z_TYPE_P(rhs) == IS_DOUBLE && (zend_dval_to_lval((double) lhs_lval) == lhs_lval)) { + /* if lhs_lval can be exactly represented as a double, go to double dedicated code */ + lhs_dval = (double) lhs_lval; + goto double_compare; + } else { + goto generic_compare; + } + } else if (Z_TYPE_P(lhs) == IS_DOUBLE) { + lhs_dval = Z_DVAL_P(lhs); + + if (EXPECTED(Z_TYPE_P(rhs) == IS_DOUBLE)) { +double_compare: + RETURN_COPY_VALUE(lhs_dval >= Z_DVAL_P(rhs) ? lhs : rhs); + } else if (Z_TYPE_P(rhs) == IS_LONG && (zend_dval_to_lval((double) Z_LVAL_P(rhs)) == Z_LVAL_P(rhs))) { + /* if the value can be exactly represented as a double, use double dedicated code otherwise generic */ + RETURN_COPY_VALUE(lhs_dval >= (double)Z_LVAL_P(rhs) ? lhs : rhs); + } else { + goto generic_compare; + } + } else { +generic_compare: + RETURN_COPY(zend_compare(lhs, rhs) >= 0 ? lhs : rhs); + } +} + typedef struct { zend_fcall_info fci; zend_fcall_info_cache fci_cache; @@ -1558,21 +1637,11 @@ PHP_FUNCTION(array_walk_recursive) * 0 = return boolean * 1 = return key */ -static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */ +static inline void _php_search_array(zval *return_value, zval *value, zval *array, bool strict, int behavior) /* {{{ */ { - zval *value, /* value to check for */ - *array, /* array to check in */ - *entry; /* pointer to array entry */ + zval *entry; /* pointer to array entry */ zend_ulong num_idx; zend_string *str_idx; - bool strict = 0; /* strict comparison or not */ - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_ZVAL(value) - Z_PARAM_ARRAY(array) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(strict) - ZEND_PARSE_PARAMETERS_END(); if (strict) { if (Z_TYPE_P(value) == IS_LONG) { @@ -1656,6 +1725,26 @@ static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) } /* }}} */ +/* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) + * 0 = return boolean + * 1 = return key + */ +static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) +{ + zval *value, /* value to check for */ + *array; /* array to check in */ + bool strict = 0; /* strict comparison or not */ + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_ZVAL(value) + Z_PARAM_ARRAY(array) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(strict) + ZEND_PARSE_PARAMETERS_END(); + + _php_search_array(return_value, value, array, strict, behavior); +} + /* {{{ Checks if the given value exists in the array */ PHP_FUNCTION(in_array) { @@ -1663,6 +1752,32 @@ PHP_FUNCTION(in_array) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(in_array, 2) +{ + zval *value, *array; + + Z_FLF_PARAM_ZVAL(1, value); + Z_FLF_PARAM_ARRAY(2, array); + + _php_search_array(return_value, value, array, false, 0); + +flf_clean:; +} + +ZEND_FRAMELESS_FUNCTION(in_array, 3) +{ + zval *value, *array; + bool strict; + + Z_FLF_PARAM_ZVAL(1, value); + Z_FLF_PARAM_ARRAY(2, array); + Z_FLF_PARAM_BOOL(3, strict); + + _php_search_array(return_value, value, array, strict, 0); + +flf_clean:; +} + /* {{{ Searches the array for a given value and returns the corresponding key if successful */ PHP_FUNCTION(array_search) { diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index fcfbff521967b..d62951b63ff26 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -115,6 +115,7 @@ PHPAPI php_basic_globals basic_globals; #include "php_fopen_wrappers.h" #include "streamsfuncs.h" +#include "zend_frameless_function.h" #include "basic_functions_arginfo.h" typedef struct _user_tick_function_entry { diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 02778da6e1ff4..02396691e5b94 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1632,10 +1632,16 @@ function pos(array|object $array): mixed {} function key(array|object $array): int|string|null {} -/** @compile-time-eval */ +/** + * @compile-time-eval + * @frameless-function {"arity": 2} + */ function min(mixed $value, mixed ...$values): mixed {} -/** @compile-time-eval */ +/** + * @compile-time-eval + * @frameless-function {"arity": 2} + */ function max(mixed $value, mixed ...$values): mixed {} function array_walk(array|object &$array, callable $callback, mixed $arg = UNKNOWN): true {} @@ -1644,6 +1650,8 @@ function array_walk_recursive(array|object &$array, callable $callback, mixed $a /** * @compile-time-eval + * @frameless-function {"arity": 2} + * @frameless-function {"arity": 3} */ function in_array(mixed $needle, array $haystack, bool $strict = false): bool {} @@ -2321,7 +2329,11 @@ function nl_langinfo(int $item): string|false {} function strcoll(string $string1, string $string2): int {} -/** @compile-time-eval */ +/** + * @compile-time-eval + * @frameless-function {"arity": 1} + * @frameless-function {"arity": 2} + */ function trim(string $string, string $characters = " \n\r\t\v\0"): string {} /** @compile-time-eval */ @@ -2348,6 +2360,8 @@ function explode(string $separator, string $string, int $limit = PHP_INT_MAX): a /** * @compile-time-eval + * @frameless-function {"arity": 1} + * @frameless-function {"arity": 2} */ function implode(string|array $separator, ?array $array = null): string {} @@ -2372,7 +2386,11 @@ function str_decrement(string $string): string {} /** @refcount 1 */ function basename(string $path, string $suffix = ""): string {} -/** @refcount 1 */ +/** + * @refcount 1 + * @frameless-function {"arity": 1} + * @frameless-function {"arity": 2} + */ function dirname(string $path, int $levels = 1): string {} /** @@ -2390,13 +2408,19 @@ function stristr(string $haystack, string $needle, bool $before_needle = false): /** * @compile-time-eval * @refcount 1 + * @frameless-function {"arity": 2} + * @frameless-function {"arity": 3} */ function strstr(string $haystack, string $needle, bool $before_needle = false): string|false {} /** @alias strstr */ function strchr(string $haystack, string $needle, bool $before_needle = false): string|false {} -/** @compile-time-eval */ +/** + * @compile-time-eval + * @frameless-function {"arity": 2} + * @frameless-function {"arity": 3} + */ function strpos(string $haystack, string $needle, int $offset = 0): int|false {} /** @compile-time-eval */ @@ -2414,10 +2438,16 @@ function strripos(string $haystack, string $needle, int $offset = 0): int|false */ function strrchr(string $haystack, string $needle, bool $before_needle = false): string|false {} -/** @compile-time-eval */ +/** + * @compile-time-eval + * @frameless-function {"arity": 2} + */ function str_contains(string $haystack, string $needle): bool {} -/** @compile-time-eval */ +/** + * @compile-time-eval + * @frameless-function {"arity": 2} + */ function str_starts_with(string $haystack, string $needle): bool {} /** @compile-time-eval */ @@ -2429,7 +2459,11 @@ function str_ends_with(string $haystack, string $needle): bool {} */ function chunk_split(string $string, int $length = 76, string $separator = "\r\n"): string {} -/** @compile-time-eval */ +/** + * @compile-time-eval + * @frameless-function {"arity": 2} + * @frameless-function {"arity": 3} + */ function substr(string $string, int $offset, ?int $length = null): string {} /** @@ -2467,6 +2501,8 @@ function ucwords(string $string, string $separators = " \t\r\n\f\v"): string {} /** * @compile-time-eval + * @frameless-function {"arity": 2} + * @frameless-function {"arity": 3} */ function strtr(string $string, string|array $from, ?string $to = null): string {} @@ -2505,6 +2541,7 @@ function stripslashes(string $string): string {} * @param int $count * @return string|array * @compile-time-eval + * @frameless-function {"arity": 3} */ function str_replace(array|string $search, array|string $replace, string|array $subject, &$count = null): string|array {} @@ -3202,6 +3239,7 @@ function decoct(int $num): string {} /** * @compile-time-eval * @refcount 1 + * @frameless-function {"arity": 1} */ function dechex(int $num): string {} @@ -3607,6 +3645,7 @@ function is_double(mixed $value): bool {} /** * @compile-time-eval + * @frameless-function {"arity": 1} */ function is_numeric(mixed $value): bool {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 8273c0fa9b1a3..40ce2e70d911d 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: afccfc7a2e1a52e73f3c05e4f7f3a994f86eb881 */ + * Stub hash: 7584d1aec417e84718a7a60e244cb00df2dc039f */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -2199,6 +2199,112 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sapi_windows_generate_ctrl_event ZEND_END_ARG_INFO() #endif +ZEND_FRAMELESS_FUNCTION(min, 2); +static const zend_frameless_function_info frameless_function_infos_min[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(min, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(max, 2); +static const zend_frameless_function_info frameless_function_infos_max[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(max, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(in_array, 2); +ZEND_FRAMELESS_FUNCTION(in_array, 3); +static const zend_frameless_function_info frameless_function_infos_in_array[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(in_array, 2), 2 }, + { ZEND_FRAMELESS_FUNCTION_NAME(in_array, 3), 3 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(trim, 1); +ZEND_FRAMELESS_FUNCTION(trim, 2); +static const zend_frameless_function_info frameless_function_infos_trim[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(trim, 1), 1 }, + { ZEND_FRAMELESS_FUNCTION_NAME(trim, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(implode, 1); +ZEND_FRAMELESS_FUNCTION(implode, 2); +static const zend_frameless_function_info frameless_function_infos_implode[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(implode, 1), 1 }, + { ZEND_FRAMELESS_FUNCTION_NAME(implode, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(dirname, 1); +ZEND_FRAMELESS_FUNCTION(dirname, 2); +static const zend_frameless_function_info frameless_function_infos_dirname[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(dirname, 1), 1 }, + { ZEND_FRAMELESS_FUNCTION_NAME(dirname, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(strstr, 2); +ZEND_FRAMELESS_FUNCTION(strstr, 3); +static const zend_frameless_function_info frameless_function_infos_strstr[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(strstr, 2), 2 }, + { ZEND_FRAMELESS_FUNCTION_NAME(strstr, 3), 3 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(strpos, 2); +ZEND_FRAMELESS_FUNCTION(strpos, 3); +static const zend_frameless_function_info frameless_function_infos_strpos[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(strpos, 2), 2 }, + { ZEND_FRAMELESS_FUNCTION_NAME(strpos, 3), 3 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(str_contains, 2); +static const zend_frameless_function_info frameless_function_infos_str_contains[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(str_contains, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(str_starts_with, 2); +static const zend_frameless_function_info frameless_function_infos_str_starts_with[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(str_starts_with, 2), 2 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(substr, 2); +ZEND_FRAMELESS_FUNCTION(substr, 3); +static const zend_frameless_function_info frameless_function_infos_substr[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(substr, 2), 2 }, + { ZEND_FRAMELESS_FUNCTION_NAME(substr, 3), 3 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(strtr, 2); +ZEND_FRAMELESS_FUNCTION(strtr, 3); +static const zend_frameless_function_info frameless_function_infos_strtr[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(strtr, 2), 2 }, + { ZEND_FRAMELESS_FUNCTION_NAME(strtr, 3), 3 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(str_replace, 3); +static const zend_frameless_function_info frameless_function_infos_str_replace[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(str_replace, 3), 3 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(dechex, 1); +static const zend_frameless_function_info frameless_function_infos_dechex[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(dechex, 1), 1 }, + { 0 }, +}; + +ZEND_FRAMELESS_FUNCTION(is_numeric, 1); +static const zend_frameless_function_info frameless_function_infos_is_numeric[] = { + { ZEND_FRAMELESS_FUNCTION_NAME(is_numeric, 1), 1 }, + { 0 }, +}; + ZEND_FUNCTION(set_time_limit); ZEND_FUNCTION(header_register_callback); @@ -2863,11 +2969,11 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(current, arginfo_current) ZEND_FALIAS(pos, current, arginfo_pos) ZEND_FE(key, arginfo_key) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(min, arginfo_min) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(max, arginfo_max) + ZEND_FRAMELESS_FE(min, arginfo_min, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_min) + ZEND_FRAMELESS_FE(max, arginfo_max, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_max) ZEND_FE(array_walk, arginfo_array_walk) ZEND_FE(array_walk_recursive, arginfo_array_walk_recursive) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(in_array, arginfo_in_array) + ZEND_FRAMELESS_FE(in_array, arginfo_in_array, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_in_array) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(array_search, arginfo_array_search) ZEND_FE(extract, arginfo_extract) ZEND_FE(compact, arginfo_compact) @@ -3071,13 +3177,13 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(nl_langinfo, arginfo_nl_langinfo) #endif ZEND_FE(strcoll, arginfo_strcoll) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(trim, arginfo_trim) + ZEND_FRAMELESS_FE(trim, arginfo_trim, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_trim) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(rtrim, arginfo_rtrim) ZEND_FALIAS(chop, rtrim, arginfo_chop) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(ltrim, arginfo_ltrim) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(wordwrap, arginfo_wordwrap) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(explode, arginfo_explode) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(implode, arginfo_implode) + ZEND_FRAMELESS_FE(implode, arginfo_implode, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_implode) ZEND_FALIAS(join, implode, arginfo_join) ZEND_FE(strtok, arginfo_strtok) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strtoupper, arginfo_strtoupper) @@ -3085,21 +3191,21 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(str_increment, arginfo_str_increment) ZEND_FE(str_decrement, arginfo_str_decrement) ZEND_FE(basename, arginfo_basename) - ZEND_FE(dirname, arginfo_dirname) + ZEND_FRAMELESS_FE(dirname, arginfo_dirname, 0, frameless_function_infos_dirname) ZEND_FE(pathinfo, arginfo_pathinfo) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(stristr, arginfo_stristr) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strstr, arginfo_strstr) + ZEND_FRAMELESS_FE(strstr, arginfo_strstr, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_strstr) ZEND_FALIAS(strchr, strstr, arginfo_strchr) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strpos, arginfo_strpos) + ZEND_FRAMELESS_FE(strpos, arginfo_strpos, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_strpos) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(stripos, arginfo_stripos) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strrpos, arginfo_strrpos) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strripos, arginfo_strripos) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strrchr, arginfo_strrchr) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(str_contains, arginfo_str_contains) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(str_starts_with, arginfo_str_starts_with) + ZEND_FRAMELESS_FE(str_contains, arginfo_str_contains, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_str_contains) + ZEND_FRAMELESS_FE(str_starts_with, arginfo_str_starts_with, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_str_starts_with) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(str_ends_with, arginfo_str_ends_with) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(chunk_split, arginfo_chunk_split) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(substr, arginfo_substr) + ZEND_FRAMELESS_FE(substr, arginfo_substr, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_substr) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(substr_replace, arginfo_substr_replace) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(quotemeta, arginfo_quotemeta) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(ord, arginfo_ord) @@ -3107,14 +3213,14 @@ static const zend_function_entry ext_functions[] = { ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(ucfirst, arginfo_ucfirst) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(lcfirst, arginfo_lcfirst) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(ucwords, arginfo_ucwords) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strtr, arginfo_strtr) + ZEND_FRAMELESS_FE(strtr, arginfo_strtr, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_strtr) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strrev, arginfo_strrev) ZEND_FE(similar_text, arginfo_similar_text) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(addcslashes, arginfo_addcslashes) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(addslashes, arginfo_addslashes) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(stripcslashes, arginfo_stripcslashes) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(stripslashes, arginfo_stripslashes) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(str_replace, arginfo_str_replace) + ZEND_FRAMELESS_FE(str_replace, arginfo_str_replace, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_str_replace) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(str_ireplace, arginfo_str_ireplace) ZEND_FE(hebrev, arginfo_hebrev) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(nl2br, arginfo_nl2br) @@ -3312,7 +3418,7 @@ static const zend_function_entry ext_functions[] = { ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(octdec, arginfo_octdec) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(decbin, arginfo_decbin) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(decoct, arginfo_decoct) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(dechex, arginfo_dechex) + ZEND_FRAMELESS_FE(dechex, arginfo_dechex, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_dechex) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(base_convert, arginfo_base_convert) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(number_format, arginfo_number_format) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(fmod, arginfo_fmod) @@ -3415,7 +3521,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FALIAS(is_long, is_int, arginfo_is_long) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(is_float, arginfo_is_float) ZEND_FALIAS(is_double, is_float, arginfo_is_double) - ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(is_numeric, arginfo_is_numeric) + ZEND_FRAMELESS_FE(is_numeric, arginfo_is_numeric, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_is_numeric) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(is_string, arginfo_is_string) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(is_array, arginfo_is_array) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(is_object, arginfo_is_object) diff --git a/ext/standard/math.c b/ext/standard/math.c index 4de45852c3492..a633789cf0150 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -1011,6 +1011,17 @@ PHP_FUNCTION(dechex) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(dechex, 1) +{ + zend_long arg; + + Z_FLF_PARAM_LONG(1, arg); + + RETVAL_STR(_php_math_longtobase_pwr2(arg, 4)); + +flf_clean:; +} + /* {{{ Converts a number in a string from any base <= 36 to any base <= 36 */ PHP_FUNCTION(base_convert) { diff --git a/ext/standard/string.c b/ext/standard/string.c index 0c2e0fa2452ee..e1c9f83540664 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -658,6 +658,34 @@ PHP_FUNCTION(trim) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(trim, 1) +{ + zval str_tmp; + zend_string *str; + + Z_FLF_PARAM_STR(1, str, str_tmp); + + ZVAL_STR(return_value, php_trim_int(str, /* what */ NULL, /* what_len */ 0, /* mode */ 3)); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, str_tmp); +} + +ZEND_FRAMELESS_FUNCTION(trim, 2) +{ + zval str_tmp, what_tmp; + zend_string *str, *what; + + Z_FLF_PARAM_STR(1, str, str_tmp); + Z_FLF_PARAM_STR(2, what, what_tmp); + + ZVAL_STR(return_value, php_trim_int(str, ZSTR_VAL(what), ZSTR_LEN(what), /* mode */ 3)); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, str_tmp); + Z_FLF_PARAM_FREE_STR(2, what_tmp); +} + /* {{{ Removes trailing whitespace */ PHP_FUNCTION(rtrim) { @@ -1056,6 +1084,51 @@ PHP_FUNCTION(implode) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(implode, 1) +{ + zval *pieces; + + /* Manual parsing for more accurate error message. */ + if (!zend_parse_arg_array(arg1, &pieces, /* null_check */ false, /* or_object */ false)) { \ + zend_type_error( + "%s(): If argument #1 ($separator) is of type string, " + "argument #2 ($array) must be of type array, null given", + get_active_function_name() + ); + goto flf_clean; \ + } + + zend_string *str = ZSTR_EMPTY_ALLOC(); + + php_implode(str, Z_ARR_P(pieces), return_value); + +flf_clean:; +} + +ZEND_FRAMELESS_FUNCTION(implode, 2) +{ + zval str_tmp; + zend_string *str; + zval *pieces; + + Z_FLF_PARAM_STR(1, str, str_tmp); + Z_FLF_PARAM_ARRAY_OR_NULL(2, pieces); + + if (!pieces) { + zend_type_error( + "%s(): If argument #1 ($separator) is of type string, " + "argument #2 ($array) must be of type array, null given", + get_active_function_name() + ); + goto flf_clean; + } + + php_implode(str, Z_ARR_P(pieces), return_value); + +flf_clean:; + Z_FLF_PARAM_FREE_STR(1, str_tmp); +} + #define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p] /* {{{ Tokenize a string */ @@ -1467,28 +1540,18 @@ PHPAPI size_t php_dirname(char *path, size_t len) } /* }}} */ -/* {{{ Returns the directory name component of the path */ -PHP_FUNCTION(dirname) +static inline void _zend_dirname(zval *return_value, zend_string *str, zend_long levels) { - char *str; - size_t str_len; zend_string *ret; - zend_long levels = 1; - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(str, str_len) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(levels) - ZEND_PARSE_PARAMETERS_END(); - - ret = zend_string_init(str, str_len, 0); + ret = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0); if (levels == 1) { /* Default case */ #ifdef PHP_WIN32 - ZSTR_LEN(ret) = php_win32_ioutil_dirname(ZSTR_VAL(ret), str_len); + ZSTR_LEN(ret) = php_win32_ioutil_dirname(ZSTR_VAL(ret), ZSTR_LEN(str)); #else - ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len); + ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), ZSTR_LEN(str)); #endif } else if (levels < 1) { zend_argument_value_error(2, "must be greater than or equal to 1"); @@ -1496,6 +1559,7 @@ PHP_FUNCTION(dirname) RETURN_THROWS(); } else { /* Some levels up */ + size_t str_len; do { #ifdef PHP_WIN32 ZSTR_LEN(ret) = php_win32_ioutil_dirname(ZSTR_VAL(ret), str_len = ZSTR_LEN(ret)); @@ -1507,8 +1571,51 @@ PHP_FUNCTION(dirname) RETURN_NEW_STR(ret); } + +/* {{{ Returns the directory name component of the path */ +PHP_FUNCTION(dirname) +{ + zend_string *str; + zend_long levels = 1; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(str) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(levels) + ZEND_PARSE_PARAMETERS_END(); + + _zend_dirname(return_value, str, levels); +} /* }}} */ +ZEND_FRAMELESS_FUNCTION(dirname, 1) +{ + zval str_tmp; + zend_string *str; + + Z_FLF_PARAM_STR(1, str, str_tmp); + + _zend_dirname(return_value, str, 1); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, str_tmp); +} + +ZEND_FRAMELESS_FUNCTION(dirname, 2) +{ + zval str_tmp; + zend_string *str; + zend_long levels; + + Z_FLF_PARAM_STR(1, str, str_tmp); + Z_FLF_PARAM_LONG(2, levels); + + _zend_dirname(return_value, str, levels); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, str_tmp); +} + /* {{{ Returns information about a certain string */ PHP_FUNCTION(pathinfo) { @@ -1678,20 +1785,10 @@ PHP_FUNCTION(stristr) } /* }}} */ -/* {{{ Finds first occurrence of a string within another */ -PHP_FUNCTION(strstr) +static inline void _zend_strstr(zval *return_value, zend_string *haystack, zend_string *needle, bool part) { - zend_string *haystack, *needle; const char *found = NULL; zend_long found_offset; - bool part = 0; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STR(haystack) - Z_PARAM_STR(needle) - Z_PARAM_OPTIONAL - Z_PARAM_BOOL(part) - ZEND_PARSE_PARAMETERS_END(); found = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); @@ -1704,8 +1801,56 @@ PHP_FUNCTION(strstr) } RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset); } + +/* {{{ Finds first occurrence of a string within another */ +PHP_FUNCTION(strstr) +{ + zend_string *haystack, *needle; + bool part = 0; + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(haystack) + Z_PARAM_STR(needle) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(part) + ZEND_PARSE_PARAMETERS_END(); + + _zend_strstr(return_value, haystack, needle, part); +} /* }}} */ +ZEND_FRAMELESS_FUNCTION(strstr, 2) +{ + zval haystack_tmp, needle_tmp; + zend_string *haystack, *needle; + + Z_FLF_PARAM_STR(1, haystack, haystack_tmp); + Z_FLF_PARAM_STR(2, needle, needle_tmp); + + _zend_strstr(return_value, haystack, needle, /* part */ false); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, haystack_tmp); + Z_FLF_PARAM_FREE_STR(2, needle_tmp); +} + +ZEND_FRAMELESS_FUNCTION(strstr, 3) +{ + zval haystack_tmp, needle_tmp; + zend_string *haystack, *needle; + bool part; + + Z_FLF_PARAM_STR(1, haystack, haystack_tmp); + Z_FLF_PARAM_STR(2, needle, needle_tmp); + Z_FLF_PARAM_BOOL(3, part); + + _zend_strstr(return_value, haystack, needle, part); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, haystack_tmp); + Z_FLF_PARAM_FREE_STR(2, needle_tmp); +} + /* {{{ Checks if a string contains another */ PHP_FUNCTION(str_contains) { @@ -1720,6 +1865,21 @@ PHP_FUNCTION(str_contains) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(str_contains, 2) +{ + zval haystack_tmp, needle_tmp; + zend_string *haystack, *needle; + + Z_FLF_PARAM_STR(1, haystack, haystack_tmp); + Z_FLF_PARAM_STR(2, needle, needle_tmp); + + RETVAL_BOOL(php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack))); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, haystack_tmp); + Z_FLF_PARAM_FREE_STR(2, needle_tmp); +} + /* {{{ Checks if haystack starts with needle */ PHP_FUNCTION(str_starts_with) { @@ -1734,6 +1894,21 @@ PHP_FUNCTION(str_starts_with) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(str_starts_with, 2) +{ + zval haystack_tmp, needle_tmp; + zend_string *haystack, *needle; + + Z_FLF_PARAM_STR(1, haystack, haystack_tmp); + Z_FLF_PARAM_STR(2, needle, needle_tmp); + + RETVAL_BOOL(zend_string_starts_with(haystack, needle)); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, haystack_tmp); + Z_FLF_PARAM_FREE_STR(2, needle_tmp); +} + /* {{{ Checks if haystack ends with needle */ PHP_FUNCTION(str_ends_with) { @@ -1754,19 +1929,9 @@ PHP_FUNCTION(str_ends_with) } /* }}} */ -/* {{{ Finds position of first occurrence of a string within another */ -PHP_FUNCTION(strpos) +static inline void _zend_strpos(zval *return_value, zend_string *haystack, zend_string *needle, zend_long offset) { - zend_string *haystack, *needle; const char *found = NULL; - zend_long offset = 0; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STR(haystack) - Z_PARAM_STR(needle) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(offset) - ZEND_PARSE_PARAMETERS_END(); if (offset < 0) { offset += (zend_long)ZSTR_LEN(haystack); @@ -1785,8 +1950,56 @@ PHP_FUNCTION(strpos) } RETURN_LONG(found - ZSTR_VAL(haystack)); } + +/* {{{ Finds position of first occurrence of a string within another */ +PHP_FUNCTION(strpos) +{ + zend_string *haystack, *needle; + zend_long offset = 0; + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(haystack) + Z_PARAM_STR(needle) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(offset) + ZEND_PARSE_PARAMETERS_END(); + + _zend_strpos(return_value, haystack, needle, offset); +} /* }}} */ +ZEND_FRAMELESS_FUNCTION(strpos, 2) +{ + zval haystack_tmp, needle_tmp; + zend_string *haystack, *needle; + + Z_FLF_PARAM_STR(1, haystack, haystack_tmp); + Z_FLF_PARAM_STR(2, needle, needle_tmp); + + _zend_strpos(return_value, haystack, needle, 0); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, haystack_tmp); + Z_FLF_PARAM_FREE_STR(2, needle_tmp); +} + +ZEND_FRAMELESS_FUNCTION(strpos, 3) +{ + zval haystack_tmp, needle_tmp; + zend_string *haystack, *needle; + zend_long offset; + + Z_FLF_PARAM_STR(1, haystack, haystack_tmp); + Z_FLF_PARAM_STR(2, needle, needle_tmp); + Z_FLF_PARAM_LONG(3, offset); + + _zend_strpos(return_value, haystack, needle, offset); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, haystack_tmp); + Z_FLF_PARAM_FREE_STR(2, needle_tmp); +} + /* {{{ Finds position of first occurrence of a string within another, case insensitive */ PHP_FUNCTION(stripos) { @@ -2050,20 +2263,8 @@ PHP_FUNCTION(chunk_split) } /* }}} */ -/* {{{ Returns part of a string */ -PHP_FUNCTION(substr) +static inline void _zend_substr(zval *return_value, zend_string *str, zend_long f, bool len_is_null, zend_long l) { - zend_string *str; - zend_long l = 0, f; - bool len_is_null = 1; - - ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STR(str) - Z_PARAM_LONG(f) - Z_PARAM_OPTIONAL - Z_PARAM_LONG_OR_NULL(l, len_is_null) - ZEND_PARSE_PARAMETERS_END(); - if (f < 0) { /* if "from" position is negative, count start position from the end * of the string @@ -2100,8 +2301,57 @@ PHP_FUNCTION(substr) RETURN_STRINGL_FAST(ZSTR_VAL(str) + f, l); } } + +/* {{{ Returns part of a string */ +PHP_FUNCTION(substr) +{ + zend_string *str; + zend_long l = 0, f; + bool len_is_null = 1; + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STR(str) + Z_PARAM_LONG(f) + Z_PARAM_OPTIONAL + Z_PARAM_LONG_OR_NULL(l, len_is_null) + ZEND_PARSE_PARAMETERS_END(); + + _zend_substr(return_value, str, f, len_is_null, l); +} /* }}} */ +ZEND_FRAMELESS_FUNCTION(substr, 2) +{ + zval str_tmp; + zend_string *str; + zend_long f; + + Z_FLF_PARAM_STR(1, str, str_tmp); + Z_FLF_PARAM_LONG(2, f); + + _zend_substr(return_value, str, f, /* len_is_null */ true, 0); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, str_tmp); +} + +ZEND_FRAMELESS_FUNCTION(substr, 3) +{ + zval str_tmp; + zend_string *str; + zend_long f, l; + bool len_is_null; + + Z_FLF_PARAM_STR(1, str, str_tmp); + Z_FLF_PARAM_LONG(2, f); + Z_FLF_PARAM_LONG_OR_NULL(3, len_is_null, l); + + _zend_substr(return_value, str, f, len_is_null, l); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, str_tmp); +} + /* {{{ Replaces part of a string with another string */ PHP_FUNCTION(substr_replace) { @@ -2691,8 +2941,7 @@ static zend_string *php_strtr_ex(zend_string *str, const char *str_from, const c } /* }}} */ -/* {{{ php_strtr_array */ -static void php_strtr_array(zval *return_value, zend_string *input, HashTable *pats) +static void php_strtr_array_ex(zval *return_value, zend_string *input, HashTable *pats) { const char *str = ZSTR_VAL(input); size_t slen = ZSTR_LEN(input); @@ -2826,7 +3075,6 @@ static void php_strtr_array(zval *return_value, zend_string *input, HashTable *p } efree(num_bitset); } -/* }}} */ /* {{{ count_chars */ static zend_always_inline zend_long count_chars(const char *p, zend_long length, char ch) @@ -3172,6 +3420,46 @@ PHPAPI zend_string *php_str_to_str(const char *haystack, size_t length, const ch } /* }}} */ +static void php_strtr_array(zval *return_value, zend_string *str, HashTable *from_ht) +{ + if (zend_hash_num_elements(from_ht) < 1) { + RETURN_STR_COPY(str); + } else if (zend_hash_num_elements(from_ht) == 1) { + zend_long num_key; + zend_string *str_key, *tmp_str, *replace, *tmp_replace; + zval *entry; + + ZEND_HASH_FOREACH_KEY_VAL(from_ht, num_key, str_key, entry) { + tmp_str = NULL; + if (UNEXPECTED(!str_key)) { + str_key = tmp_str = zend_long_to_str(num_key); + } + replace = zval_get_tmp_string(entry, &tmp_replace); + if (ZSTR_LEN(str_key) < 1) { + php_error_docref(NULL, E_WARNING, "Ignoring replacement of empty string"); + RETVAL_STR_COPY(str); + } else if (ZSTR_LEN(str_key) == 1) { + RETVAL_STR(php_char_to_str_ex(str, + ZSTR_VAL(str_key)[0], + ZSTR_VAL(replace), + ZSTR_LEN(replace), + /* case_sensitive */ true, + NULL)); + } else { + zend_long dummy; + RETVAL_STR(php_str_to_str_ex(str, + ZSTR_VAL(str_key), ZSTR_LEN(str_key), + ZSTR_VAL(replace), ZSTR_LEN(replace), &dummy)); + } + zend_tmp_string_release(tmp_str); + zend_tmp_string_release(tmp_replace); + return; + } ZEND_HASH_FOREACH_END(); + } else { + php_strtr_array_ex(return_value, str, from_ht); + } +} + /* {{{ Translates characters in str using given translation tables */ PHP_FUNCTION(strtr) { @@ -3199,42 +3487,7 @@ PHP_FUNCTION(strtr) } if (!to) { - if (zend_hash_num_elements(from_ht) < 1) { - RETURN_STR_COPY(str); - } else if (zend_hash_num_elements(from_ht) == 1) { - zend_long num_key; - zend_string *str_key, *tmp_str, *replace, *tmp_replace; - zval *entry; - - ZEND_HASH_FOREACH_KEY_VAL(from_ht, num_key, str_key, entry) { - tmp_str = NULL; - if (UNEXPECTED(!str_key)) { - str_key = tmp_str = zend_long_to_str(num_key); - } - replace = zval_get_tmp_string(entry, &tmp_replace); - if (ZSTR_LEN(str_key) < 1) { - php_error_docref(NULL, E_WARNING, "Ignoring replacement of empty string"); - RETVAL_STR_COPY(str); - } else if (ZSTR_LEN(str_key) == 1) { - RETVAL_STR(php_char_to_str_ex(str, - ZSTR_VAL(str_key)[0], - ZSTR_VAL(replace), - ZSTR_LEN(replace), - /* case_sensitive */ true, - NULL)); - } else { - zend_long dummy; - RETVAL_STR(php_str_to_str_ex(str, - ZSTR_VAL(str_key), ZSTR_LEN(str_key), - ZSTR_VAL(replace), ZSTR_LEN(replace), &dummy)); - } - zend_tmp_string_release(tmp_str); - zend_tmp_string_release(tmp_replace); - return; - } ZEND_HASH_FOREACH_END(); - } else { - php_strtr_array(return_value, str, from_ht); - } + php_strtr_array(return_value, str, from_ht); } else { RETURN_STR(php_strtr_ex(str, ZSTR_VAL(from_str), @@ -3244,6 +3497,48 @@ PHP_FUNCTION(strtr) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(strtr, 2) +{ + zval str_tmp; + zend_string *str; + zval *from; + + Z_FLF_PARAM_STR(1, str, str_tmp); + Z_FLF_PARAM_ARRAY(2, from); + + if (ZSTR_LEN(str) == 0) { + RETVAL_EMPTY_STRING(); + goto flf_clean; + } + + php_strtr_array(return_value, str, Z_ARR_P(from)); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, str_tmp); +} + +ZEND_FRAMELESS_FUNCTION(strtr, 3) +{ + zval str_tmp, from_tmp, to_tmp; + zend_string *str, *from, *to; + + Z_FLF_PARAM_STR(1, str, str_tmp); + Z_FLF_PARAM_STR(2, from, from_tmp); + Z_FLF_PARAM_STR(3, to, to_tmp); + + if (ZSTR_LEN(str) == 0) { + RETVAL_EMPTY_STRING(); + goto flf_clean; + } + + RETVAL_STR(php_strtr_ex(str, ZSTR_VAL(from), ZSTR_VAL(to), MIN(ZSTR_LEN(from), ZSTR_LEN(to)))); + +flf_clean: + Z_FLF_PARAM_FREE_STR(1, str_tmp); + Z_FLF_PARAM_FREE_STR(2, from_tmp); + Z_FLF_PARAM_FREE_STR(3, to_tmp); +} + /* {{{ Reverse a string */ #ifdef ZEND_INTRIN_SSSE3_NATIVE #include @@ -4202,29 +4497,20 @@ static zend_long php_str_replace_in_subject( } /* }}} */ -/* {{{ php_str_replace_common */ -static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, bool case_sensitivity) -{ - zend_string *search_str; - HashTable *search_ht; - zend_string *replace_str; - HashTable *replace_ht; - zend_string *subject_str; - HashTable *subject_ht; - zval *subject_entry, *zcount = NULL; +static void _php_str_replace_common( + zval *return_value, + HashTable *search_ht, zend_string *search_str, + HashTable *replace_ht, zend_string *replace_str, + HashTable *subject_ht, zend_string *subject_str, + zval *zcount, + bool case_sensitivity +) { + zval *subject_entry; zval result; zend_string *string_key; zend_ulong num_key; zend_long count = 0; - ZEND_PARSE_PARAMETERS_START(3, 4) - Z_PARAM_ARRAY_HT_OR_STR(search_ht, search_str) - Z_PARAM_ARRAY_HT_OR_STR(replace_ht, replace_str) - Z_PARAM_ARRAY_HT_OR_STR(subject_ht, subject_str) - Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(zcount) - ZEND_PARSE_PARAMETERS_END(); - /* Make sure we're dealing with strings and do the replacement. */ if (search_str && replace_ht) { zend_argument_type_error(2, "must be of type string when argument #1 ($search) is a string"); @@ -4258,6 +4544,28 @@ static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, bool case_sensi ZEND_TRY_ASSIGN_REF_LONG(zcount, count); } } + +/* {{{ php_str_replace_common */ +static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, bool case_sensitivity) +{ + zend_string *search_str; + HashTable *search_ht; + zend_string *replace_str; + HashTable *replace_ht; + zend_string *subject_str; + HashTable *subject_ht; + zval *zcount = NULL; + + ZEND_PARSE_PARAMETERS_START(3, 4) + Z_PARAM_ARRAY_HT_OR_STR(search_ht, search_str) + Z_PARAM_ARRAY_HT_OR_STR(replace_ht, replace_str) + Z_PARAM_ARRAY_HT_OR_STR(subject_ht, subject_str) + Z_PARAM_OPTIONAL + Z_PARAM_ZVAL(zcount) + ZEND_PARSE_PARAMETERS_END(); + + _php_str_replace_common(return_value, search_ht, search_str, replace_ht, replace_str, subject_ht, subject_str, zcount, case_sensitivity); +} /* }}} */ /* {{{ Replaces all occurrences of search in haystack with replace */ @@ -4267,6 +4575,24 @@ PHP_FUNCTION(str_replace) } /* }}} */ +ZEND_FRAMELESS_FUNCTION(str_replace, 3) +{ + zend_string *search_str, *replace_str, *subject_str; + HashTable *search_ht, *replace_ht, *subject_ht; + zval search_tmp, replace_tmp, subject_tmp; + + Z_FLF_PARAM_ARRAY_HT_OR_STR(1, search_ht, search_str, search_tmp); + Z_FLF_PARAM_ARRAY_HT_OR_STR(2, replace_ht, replace_str, replace_tmp); + Z_FLF_PARAM_ARRAY_HT_OR_STR(3, subject_ht, subject_str, subject_tmp); + + _php_str_replace_common(return_value, search_ht, search_str, replace_ht, replace_str, subject_ht, subject_str, /* zcount */ NULL, /* case_sensitivity */ true); + +flf_clean:; + Z_FLF_PARAM_FREE_STR(1, search_tmp); + Z_FLF_PARAM_FREE_STR(2, replace_tmp); + Z_FLF_PARAM_FREE_STR(3, subject_tmp); +} + /* {{{ Replaces all occurrences of search in haystack with replace / case-insensitive */ PHP_FUNCTION(str_ireplace) { diff --git a/ext/standard/type.c b/ext/standard/type.c index 6cd72fc744ca4..4f3950e278463 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -342,15 +342,8 @@ PHP_FUNCTION(is_object) } /* }}} */ -/* {{{ Returns true if value is a number or a numeric string */ -PHP_FUNCTION(is_numeric) +static inline void _zend_is_numeric(zval *return_value, zval *arg) { - zval *arg; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_ZVAL(arg) - ZEND_PARSE_PARAMETERS_END(); - switch (Z_TYPE_P(arg)) { case IS_LONG: case IS_DOUBLE: @@ -370,8 +363,29 @@ PHP_FUNCTION(is_numeric) break; } } + +/* {{{ Returns true if value is a number or a numeric string */ +PHP_FUNCTION(is_numeric) +{ + zval *arg; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ZVAL(arg) + ZEND_PARSE_PARAMETERS_END(); + + _zend_is_numeric(return_value, arg); +} /* }}} */ +ZEND_FRAMELESS_FUNCTION(is_numeric, 1) +{ + zval *arg; + + Z_FLF_PARAM_ZVAL(1, arg); + + _zend_is_numeric(return_value, arg); +} + /* {{{ Returns true if value is a scalar */ PHP_FUNCTION(is_scalar) { diff --git a/ext/zend_test/tests/observer_frameless.phpt b/ext/zend_test/tests/observer_frameless.phpt new file mode 100644 index 0000000000000..965b27881241a --- /dev/null +++ b/ext/zend_test/tests/observer_frameless.phpt @@ -0,0 +1,17 @@ +--TEST-- +Observer: Frameless calls are disabled when there are observers +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +--FILE-- + +--EXPECTF-- + + + diff --git a/win32/build/config.w32 b/win32/build/config.w32 index 2ee0d52eb33c6..ef11223c662b2 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -240,7 +240,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \ zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c zend_weakrefs.c \ zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c \ zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_observer.c zend_system_id.c \ - zend_enum.c zend_fibers.c zend_atomic.c zend_hrtime.c"); + zend_enum.c zend_fibers.c zend_atomic.c zend_hrtime.c zend_frameless_function.c"); ADD_SOURCES("Zend\\Optimizer", "zend_optimizer.c pass1.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c escape_analysis.c compact_vars.c dce.c sccp.c scdf.c"); var PHP_ASSEMBLER = PATH_PROG({ From 64ec25cc3a7c775e7d3738dc1a3cda5238b53b50 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 5 Feb 2024 14:58:31 +0100 Subject: [PATCH 2/2] Avoid nesting jmp_frameless branches Opcodes grow exponentially for nested calls. --- Zend/zend_compile.c | 8 +++++++- Zend/zend_compile.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c0cab6d8aa398..752d2dd7b11c0 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -325,6 +325,7 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */ CG(context).last_brk_cont = 0; CG(context).brk_cont_array = NULL; CG(context).labels = NULL; + CG(context).in_jmp_frameless_branch = false; } /* }}} */ @@ -4630,7 +4631,9 @@ static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args /* Find frameless function with same name. */ zend_function *frameless_function = NULL; if (args_ast->kind != ZEND_AST_CALLABLE_CONVERT - && !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast))) { + && !zend_args_contain_unpack_or_named(zend_ast_get_list(args_ast)) + /* Avoid blowing up op count with nested frameless branches. */ + && !CG(context).in_jmp_frameless_branch) { zend_string *lc_func_name = Z_STR_P(CT_CONSTANT_EX(CG(active_op_array), name_constants + 2)); frameless_function = zend_hash_find_ptr(CG(function_table), lc_func_name); } @@ -4641,6 +4644,7 @@ static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args if (frameless_function) { frameless_function_info = find_frameless_function_info(zend_ast_get_list(args_ast), frameless_function, type); if (frameless_function_info) { + CG(context).in_jmp_frameless_branch = true; znode op1; op1.op_type = IS_CONST; ZVAL_COPY(&op1.u.constant, CT_CONSTANT_EX(CG(active_op_array), name_constants + 1)); @@ -4670,6 +4674,8 @@ static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args zend_op *flf_icall = &CG(active_op_array)->opcodes[flf_icall_opnum]; SET_NODE(flf_icall->result, result); zend_update_jump_target_to_next(jmp_end_opnum); + + CG(context).in_jmp_frameless_branch = false; } } /* }}} */ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 64464ed999a2f..9cc6df022d34c 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -199,6 +199,7 @@ typedef struct _zend_oparray_context { int last_brk_cont; zend_brk_cont_element *brk_cont_array; HashTable *labels; + bool in_jmp_frameless_branch; } zend_oparray_context; /* Class, property and method flags class|meth.|prop.|const*/