From: Dmitry Stogov Date: Thu, 12 Mar 2015 17:39:04 +0000 (+0300) Subject: Executor cleanup: fix GOTO and SWITCH VMs, remove aility to build additional PHP... X-Git-Tag: PRE_PHP7_NSAPI_REMOVAL~680 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6289f7e52f07d411bce0a0a99fe65bfbe87e4290;p=php Executor cleanup: fix GOTO and SWITCH VMs, remove aility to build additional PHP-5.0 compatible VM, hide executor implementation details. --- diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8e4148795e..42f55f9521 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -129,16 +129,10 @@ void zend_compile_var(znode *node, zend_ast *ast, uint32_t type); void zend_eval_const_expr(zend_ast **ast_ptr); void zend_const_expr_to_zval(zval *result, zend_ast *ast); -#define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data -#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data - -typedef int (*user_opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); -typedef int (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); - -extern ZEND_API opcode_handler_t *zend_opcode_handlers; +typedef int (*user_opcode_handler_t) (zend_execute_data *execute_data); struct _zend_op { - opcode_handler_t handler; + const void *handler; znode_op op1; znode_op op2; znode_op result; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 59e585e35b..4a8b4694b7 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -411,9 +411,10 @@ static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, const *should_free = NULL; if (op_type == IS_CONST) { return EX_CONSTANT(node); - } else { - ZEND_ASSERT(op_type == IS_CV); + } else if (op_type == IS_CV) { return _get_zval_ptr_cv(execute_data, node.var, type); + } else { + return NULL; } } } @@ -431,9 +432,10 @@ static zend_always_inline zval *_get_zval_ptr_deref(int op_type, znode_op node, *should_free = NULL; if (op_type == IS_CONST) { return EX_CONSTANT(node); - } else { - ZEND_ASSERT(op_type == IS_CV); + } else if (op_type == IS_CV) { return _get_zval_ptr_cv_deref(execute_data, node.var, type); + } else { + return NULL; } } } @@ -1688,8 +1690,6 @@ static int zend_check_symbol(zval *pz) #define CHECK_SYMBOL_TABLES() #endif -ZEND_API opcode_handler_t *zend_opcode_handlers; - ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value) { execute_data->func->internal_function.handler(execute_data, return_value); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index d33735291a..0149da6929 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -252,8 +252,6 @@ typedef zval* zend_free_op; ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type); -ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS); - ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table); void zend_free_compiled_variables(zend_execute_data *execute_data); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ffb737d2a2..09de8b2f4c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -353,11 +353,14 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR| { USE_OPLINE zend_free_op free_op1, free_op2, free_op_data1; - zval *object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); - zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); + property = GET_OP2_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -2805,13 +2808,15 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV) { USE_OPLINE zend_free_op free_op2; - zval *function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); + zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; zend_class_entry *called_scope; zend_object *object; + SAVE_OPLINE(); + function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { if (error) { efree(error); @@ -2929,8 +2934,6 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) SAVE_OPLINE(); EX(call) = call->prev_execute_data; - LOAD_OPLINE(); - call->called_scope = EX(called_scope); Z_OBJ(call->This) = Z_OBJ(EX(This)); @@ -2977,8 +2980,6 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY) SAVE_OPLINE(); EX(call) = call->prev_execute_data; - LOAD_OPLINE(); - EG(scope) = NULL; ret = NULL; call->symbol_table = NULL; @@ -3004,8 +3005,6 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) SAVE_OPLINE(); EX(call) = call->prev_execute_data; - LOAD_OPLINE(); - if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { EG(scope) = NULL; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { @@ -3562,6 +3561,7 @@ ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, ANY) zval *varptr, *arg; zend_free_op free_op1; + SAVE_OPLINE(); varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (Z_ISREF_P(varptr)) { @@ -3660,6 +3660,7 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, ANY) if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF); } + SAVE_OPLINE(); varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (Z_ISREF_P(varptr)) { @@ -3682,6 +3683,7 @@ ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY) int arg_num; SAVE_OPLINE(); + SAVE_OPLINE(); args = GET_OP1_ZVAL_PTR(BP_VAR_R); arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1; @@ -3846,6 +3848,7 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY) zval *args; SAVE_OPLINE(); + SAVE_OPLINE(); args = GET_OP1_ZVAL_PTR(BP_VAR_R); if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) { @@ -3969,6 +3972,7 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY) zval *arg, *param, tmp; zend_free_op free_op1; + SAVE_OPLINE(); arg = GET_OP1_ZVAL_PTR(BP_VAR_R); param = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -5289,7 +5293,6 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY) ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY) { USE_OPLINE - zend_free_op free_op1; zval *array; zval *value; HashTable *fe_ht; @@ -5449,7 +5452,6 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY) ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY) { USE_OPLINE - zend_free_op free_op1; zval *array; zval *value; HashTable *fe_ht; @@ -6485,7 +6487,7 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY) int ret; SAVE_OPLINE(); - ret = zend_user_opcode_handlers[opline->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL); + ret = zend_user_opcode_handlers[opline->opcode](execute_data); LOAD_OPLINE(); switch (ret) { @@ -6590,6 +6592,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); FREE_UNFETCHED_OP2(); @@ -6728,6 +6731,7 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) /* check for delayed exception */ if (Z_OBJ_P(fast_call) != NULL) { + SAVE_OPLINE(); /* discard the previously thrown exception */ OBJ_RELEASE(Z_OBJ_P(fast_call)); Z_OBJ_P(fast_call) = NULL; @@ -6990,4 +6994,3 @@ ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, ANY) } } -ZEND_VM_EXPORT_HANDLER(zend_do_fcall, ZEND_DO_FCALL) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 66cbf0453a..b66e724358 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -306,9 +306,15 @@ static zend_uchar zend_user_opcodes[256] = {0, 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }; -static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op); +static const void **zend_opcode_handlers; +static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op); +#define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data +#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data + +typedef int (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); + #undef OPLINE #undef DCL_OPLINE #undef USE_OPLINE @@ -329,9 +335,8 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend #define ZEND_VM_RETURN() return -1 #define ZEND_VM_ENTER() return 1 #define ZEND_VM_LEAVE() return 2 -#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +#define ZEND_VM_DISPATCH(opcode, opline) return ((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data ZEND_API void execute_ex(zend_execute_data *execute_data) { @@ -349,7 +354,7 @@ ZEND_API void execute_ex(zend_execute_data *execute_data) } #endif - if (UNEXPECTED((ret = OPLINE->handler(execute_data)) != 0)) { + if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(execute_data)) != 0)) { if (EXPECTED(ret > 0)) { execute_data = EG(current_execute_data); } else { @@ -495,8 +500,6 @@ static int ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); EX(call) = call->prev_execute_data; - LOAD_OPLINE(); - call->called_scope = EX(called_scope); Z_OBJ(call->This) = Z_OBJ(EX(This)); @@ -543,8 +546,6 @@ static int ZEND_FASTCALL ZEND_DO_UCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); EX(call) = call->prev_execute_data; - LOAD_OPLINE(); - EG(scope) = NULL; ret = NULL; call->symbol_table = NULL; @@ -570,8 +571,6 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); EX(call) = call->prev_execute_data; - LOAD_OPLINE(); - if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { EG(scope) = NULL; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { @@ -885,6 +884,7 @@ static int ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS int arg_num; SAVE_OPLINE(); + SAVE_OPLINE(); args = get_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, BP_VAR_R); arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1; @@ -1049,6 +1049,7 @@ static int ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *args; SAVE_OPLINE(); + SAVE_OPLINE(); args = get_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, BP_VAR_R); if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) { @@ -1621,7 +1622,7 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS int ret; SAVE_OPLINE(); - ret = zend_user_opcode_handlers[opline->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL); + ret = zend_user_opcode_handlers[opline->opcode](execute_data); LOAD_OPLINE(); switch (ret) { @@ -1651,6 +1652,7 @@ static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLE /* check for delayed exception */ if (Z_OBJ_P(fast_call) != NULL) { + SAVE_OPLINE(); /* discard the previously thrown exception */ OBJ_RELEASE(Z_OBJ_P(fast_call)); Z_OBJ_P(fast_call) = NULL; @@ -4685,13 +4687,15 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCO { USE_OPLINE - zval *function_name = EX_CONSTANT(opline->op2); + zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; zend_class_entry *called_scope; zend_object *object; + SAVE_OPLINE(); + function_name = EX_CONSTANT(opline->op2); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { if (error) { efree(error); @@ -4769,7 +4773,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2))); if (!actual) { - ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(EX_CONSTANT(opline->op2)))); + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2))); } else { actual++; ZVAL_STRINGL(EX_VAR(opline->result.var), @@ -5350,6 +5354,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -5533,6 +5538,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -6051,6 +6057,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -6878,6 +6885,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -7678,13 +7686,15 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_ { USE_OPLINE - zval *function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; zend_class_entry *called_scope; zend_object *object; + SAVE_OPLINE(); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { if (error) { efree(error); @@ -8083,6 +8093,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -8869,13 +8880,15 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPC { USE_OPLINE zend_free_op free_op2; - zval *function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zval *function_name; zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; zend_class_entry *called_scope; zend_object *object; + SAVE_OPLINE(); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { if (error) { efree(error); @@ -10279,6 +10292,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -10447,6 +10461,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -10615,6 +10630,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -10937,6 +10953,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -11415,6 +11432,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -12161,6 +12179,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *varptr, *arg; zend_free_op free_op1; + SAVE_OPLINE(); varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (Z_ISREF_P(varptr)) { @@ -12259,6 +12278,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } + SAVE_OPLINE(); varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (Z_ISREF_P(varptr)) { @@ -12279,6 +12299,7 @@ static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zval *arg, *param, tmp; zend_free_op free_op1; + SAVE_OPLINE(); arg = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); param = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -12796,7 +12817,6 @@ static int ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ static int ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array; zval *value; HashTable *fe_ht; @@ -12956,7 +12976,6 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A static int ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *array; zval *value; HashTable *fe_ht; @@ -13310,11 +13329,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b { USE_OPLINE zend_free_op free_op1, free_op_data1; - zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - zval *property = EX_CONSTANT(opline->op2); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + property = EX_CONSTANT(opline->op2); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -14513,7 +14535,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2))); if (!actual) { - ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(EX_CONSTANT(opline->op2)))); + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2))); } else { actual++; ZVAL_STRINGL(EX_VAR(opline->result.var), @@ -14856,6 +14878,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -15062,6 +15085,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -15328,6 +15352,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -16239,6 +16264,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -16405,11 +16431,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina { USE_OPLINE zend_free_op free_op1, free_op_data1; - zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -17913,6 +17942,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -18053,11 +18083,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(int (* { USE_OPLINE zend_free_op free_op1, free_op2, free_op_data1; - zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -19579,11 +19612,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int { USE_OPLINE zend_free_op free_op_data1; - zval *object = _get_obj_zval_ptr_unused(execute_data); - zval *property = EX_CONSTANT(opline->op2); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + property = EX_CONSTANT(opline->op2); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -20557,7 +20593,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2))); if (!actual) { - ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(EX_CONSTANT(opline->op2)))); + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2))); } else { actual++; ZVAL_STRINGL(EX_VAR(opline->result.var), @@ -20965,6 +21001,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -21102,6 +21139,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -21239,6 +21277,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -21715,6 +21754,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -21849,11 +21889,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b { USE_OPLINE zend_free_op free_op_data1; - zval *object = _get_obj_zval_ptr_unused(execute_data); - zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -23136,6 +23179,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -23270,11 +23314,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(int { USE_OPLINE zend_free_op free_op2, free_op_data1; - zval *object = _get_obj_zval_ptr_unused(execute_data); - zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -25096,6 +25143,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval *varptr, *arg; + SAVE_OPLINE(); varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (Z_ISREF_P(varptr)) { @@ -25193,6 +25241,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } + SAVE_OPLINE(); varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (Z_ISREF_P(varptr)) { @@ -25213,6 +25262,7 @@ static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *arg, *param, tmp; + SAVE_OPLINE(); arg = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); param = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -26380,11 +26430,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi { USE_OPLINE zend_free_op free_op_data1; - zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); - zval *property = EX_CONSTANT(opline->op2); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); + property = EX_CONSTANT(opline->op2); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -28480,6 +28533,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -28756,6 +28810,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -29413,6 +29468,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -30523,6 +30579,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -30948,11 +31005,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar { USE_OPLINE zend_free_op free_op_data1; - zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); - zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -32681,6 +32741,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS /* The generator object is stored in EX(return_value) */ zend_generator *generator = (zend_generator *) EX(return_value); + SAVE_OPLINE(); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); @@ -33095,11 +33156,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(int (*b { USE_OPLINE zend_free_op free_op2, free_op_data1; - zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); - zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + zval *object; + zval *property; zval *value; zval *zptr; + SAVE_OPLINE(); + object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -38408,7 +38472,7 @@ static int ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) void zend_init_opcodes_handlers(void) { - static const opcode_handler_t labels[] = { + static const void *labels[] = { ZEND_NOP_SPEC_HANDLER, ZEND_NOP_SPEC_HANDLER, ZEND_NOP_SPEC_HANDLER, @@ -42686,9 +42750,9 @@ void zend_init_opcodes_handlers(void) ZEND_SPACESHIP_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER }; - zend_opcode_handlers = (opcode_handler_t*)labels; + zend_opcode_handlers = labels; } -static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op) +static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op) { static const int zend_vm_decode[] = { _UNUSED_CODE, /* 0 */ @@ -42717,8 +42781,3 @@ ZEND_API void zend_vm_set_opcode_handler(zend_op* op) op->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op); } -ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS) -{ - return ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -} - diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 65b1c72c06..244080c3a4 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -639,7 +639,7 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno) break; case ZEND_VM_KIND_SWITCH: if ($spec) { - out($f,"case ".((string)($opnames[$name]*25+($typecode[$op1]*5)+$typecode[$op2])).": /*".$name."_SPEC".$prefix[$op1].$prefix[$op2]."_HANDLER*/"); + out($f,"case ".((string)($opnames[$name]*25+($typecode[$op1=="TMPVAR"?"TMP":$op1]*5)+$typecode[$op2=="TMPVAR"?"TMP":$op2])).": /*".$name."_SPEC".$prefix[$op1].$prefix[$op2]."_HANDLER*/"); } else { out($f,"case ".$name.":"); } @@ -717,10 +717,10 @@ function gen_labels($f, $spec, $kind, $prolog) { out($f,$prolog."ZEND_NULL_HANDLER,\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(opcode_handler_t)-1,\n"); + out($f,$prolog."(void*)(uintptr_t)-1,\n"); break; case ZEND_VM_KIND_GOTO: - out($f,$prolog."(opcode_handler_t)&&ZEND_NULL_HANDLER,\n"); + out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n"); break; } } @@ -763,10 +763,10 @@ function gen_labels($f, $spec, $kind, $prolog) { out($f,$prolog.$dsc["op"]."_SPEC".$prefix[$op1].$prefix[$op2]."_HANDLER,\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(opcode_handler_t)".((string)($num*25+$typecode[$op1]*5+$typecode[$op2])).",\n"); + out($f,$prolog."(void*)(uintptr_t)".((string)($num*25+$typecode[$op1=="TMPVAR"?"TMP":$op1]*5+$typecode[$op2=="TMPVAR"?"TMP":$op2])).",\n"); break; case ZEND_VM_KIND_GOTO: - out($f,$prolog."(opcode_handler_t)&&".$dsc["op"]."_SPEC".$prefix[$op1].$prefix[$op2]."_HANDLER,\n"); + out($f,$prolog."(void*)&&".$dsc["op"]."_SPEC".$prefix[$op1].$prefix[$op2]."_HANDLER,\n"); break; } } else { @@ -776,10 +776,10 @@ function gen_labels($f, $spec, $kind, $prolog) { out($f,$prolog."ZEND_NULL_HANDLER,\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(opcode_handler_t)-1,\n"); + out($f,$prolog."(void*)(uintptr_t)-1,\n"); break; case ZEND_VM_KIND_GOTO: - out($f,$prolog."(opcode_handler_t)&&ZEND_NULL_HANDLER,\n"); + out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n"); break; } } @@ -801,10 +801,10 @@ function gen_labels($f, $spec, $kind, $prolog) { out($f,$prolog."ZEND_NULL_HANDLER,\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(opcode_handler_t)-1,\n"); + out($f,$prolog."(void*)(uintptr_t)-1,\n"); break; case ZEND_VM_KIND_GOTO: - out($f,$prolog."(opcode_handler_t)&&ZEND_NULL_HANDLER,\n"); + out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n"); break; } $next++; @@ -816,10 +816,10 @@ function gen_labels($f, $spec, $kind, $prolog) { out($f,$prolog.$dsc["op"]."_HANDLER,\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(opcode_handler_t)".((string)$num).",\n"); + out($f,$prolog."(void*)(uintptr_t)".((string)$num).",\n"); break; case ZEND_VM_KIND_GOTO: - out($f,$prolog."(opcode_handler_t)&&".$dsc["op"]."_HANDLER,\n"); + out($f,$prolog."(void*)&&".$dsc["op"]."_HANDLER,\n"); break; } } @@ -831,10 +831,10 @@ function gen_labels($f, $spec, $kind, $prolog) { out($f,$prolog."ZEND_NULL_HANDLER\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(opcode_handler_t)-1\n"); + out($f,$prolog."(void*)(uintptr_t)-1\n"); break; case ZEND_VM_KIND_GOTO: - out($f,$prolog."(opcode_handler_t)&&ZEND_NULL_HANDLER\n"); + out($f,$prolog."(void*)&&ZEND_NULL_HANDLER\n"); break; } } @@ -942,7 +942,7 @@ function skip_blanks($f, $prolog, $epilog) { } // Generates executor from skeleton file and definition (specialized or unspecialized) -function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, $old) { +function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) { global $params, $skeleton_file, $line_no; $lineno = 0; @@ -952,13 +952,16 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, if (preg_match("/(.*)[{][%]([A-Z_]*)[%][}](.*)/", $line, $m)) { switch ($m[2]) { case "DEFINES": - if (ZEND_VM_OLD_EXECUTOR && $spec) { - out($f,"static int zend_vm_old_executor = 0;\n\n"); - } - out($f,"static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n"); + out($f,"static const void **zend_opcode_handlers;\n"); + out($f,"static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n"); switch ($kind) { case ZEND_VM_KIND_CALL: - out($f,"\n"); + out($f,"\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data\n"); + out($f,"\n"); + out($f,"typedef int (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);\n"); + out($f,"\n"); out($f,"#undef OPLINE\n"); out($f,"#undef DCL_OPLINE\n"); out($f,"#undef USE_OPLINE\n"); @@ -979,9 +982,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define ZEND_VM_RETURN() return -1\n"); out($f,"#define ZEND_VM_ENTER() return 1\n"); out($f,"#define ZEND_VM_LEAVE() return 2\n"); - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data -"); + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return ((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f,"\n"); break; case ZEND_VM_KIND_SWITCH: out($f,"\n"); @@ -1005,9 +1007,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data -"); + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n"); + out($f,"\n"); break; case ZEND_VM_KIND_GOTO: out($f,"\n"); @@ -1037,9 +1038,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define ZEND_VM_RETURN() return\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data -"); + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n"); + out($f,"\n"); break; } break; @@ -1049,7 +1049,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, case "HELPER_VARS": if ($kind != ZEND_VM_KIND_CALL) { if ($kind == ZEND_VM_KIND_SWITCH) { - out($f,$m[1]."opcode_handler_t dispatch_handler;\n"); + out($f,$m[1]."const void *dispatch_handler;\n"); } // Emit local variables those are used for helpers' parameters foreach ($params as $param => $x) { @@ -1065,10 +1065,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, // zend_opcode_handlers initialization $prolog = $m[1]; out($f,$prolog."if (execute_data == NULL) {\n"); - out($f,$prolog."\tstatic const opcode_handler_t labels[] = {\n"); + out($f,$prolog."\tstatic const void* labels[] = {\n"); gen_labels($f, $spec, $kind, $prolog."\t\t"); out($f,$prolog."\t};\n"); - out($f,$prolog."\tzend_opcode_handlers = (opcode_handler_t*)labels;\n"); + out($f,$prolog."\tzend_opcode_handlers = (const void **)labels;\n"); out($f,$prolog."\treturn;\n"); out($f,$prolog."}\n"); } else { @@ -1090,10 +1090,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, // Emit code that dispatches to opcode handler switch ($kind) { case ZEND_VM_KIND_CALL: - out($f, $m[1]."if (UNEXPECTED((ret = OPLINE->handler(execute_data)) != 0))".$m[3]."\n"); + out($f, $m[1]."if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(execute_data)) != 0))".$m[3]."\n"); break; case ZEND_VM_KIND_SWITCH: - out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)dispatch_handler)".$m[3]."\n"); + out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)(uintptr_t)dispatch_handler)".$m[3]."\n"); break; case ZEND_VM_KIND_GOTO: out($f, $m[1]."goto *(void**)(OPLINE->handler);".$m[3]."\n"); @@ -1115,12 +1115,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, break; case "EXTERNAL_EXECUTOR": if ($kind == ZEND_VM_KIND_CALL) { - // Unspecialized executor with CALL threading is the same as the - // old one, so we don't need to produce code twitch - if (!$old || ZEND_VM_SPEC || (ZEND_VM_KIND != ZEND_VM_KIND_CALL)) { - // Emit executor code - gen_executor_code($f, $spec, $kind, $m[1]); - } + gen_executor_code($f, $spec, $kind, $m[1]); } break; case "INITIALIZER_NAME": @@ -1135,20 +1130,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,$prolog.""); out($f,$prolog.$executor_name."_ex(NULL);\n"); } else { - if ($old) { - // Reserving space for user-defined opcodes - out($f,$prolog."static opcode_handler_t labels[512] = {\n"); - } else { - out($f,$prolog."static const opcode_handler_t labels[] = {\n"); - } + out($f,$prolog."static const void *labels[] = {\n"); gen_labels($f, $spec, $kind, $prolog."\t"); out($f,$prolog."};\n"); - out($f,$prolog."zend_opcode_handlers = (opcode_handler_t*)labels;\n"); - if ($old) { - // Setup old executor - out($f,$prolog."zend_vm_old_executor = 1;\n"); - out($f,$prolog."zend_execute = old_execute;\n"); - } + out($f,$prolog."zend_opcode_handlers = labels;\n"); } break; default: @@ -1391,31 +1376,14 @@ function gen_vm($def, $skel) { out($f, "255\n};\n\n"); // Generate specialized executor - gen_executor($f, $skl, ZEND_VM_SPEC, ZEND_VM_KIND, "execute", "zend_init_opcodes_handlers", 0); - - // Generate un-specialized executor - if (ZEND_VM_OLD_EXECUTOR) { - out($f,"\n/* Old executor */\n\n"); - out($f,"#undef ZEND_VM_CONTINUE\n\n"); - out($f,"#undef ZEND_VM_RETURN\n\n"); - out($f,"#undef ZEND_VM_ENTER\n\n"); - out($f,"#undef ZEND_VM_LEAVE\n\n"); - out($f,"#undef ZEND_VM_DISPATCH\n\n"); - out($f,"#undef ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL\n\n"); - gen_executor($f, $skl, 0, ZEND_VM_KIND_CALL, "old_execute", "zend_vm_use_old_executor", 1); - } + gen_executor($f, $skl, ZEND_VM_SPEC, ZEND_VM_KIND, "execute", "zend_init_opcodes_handlers"); // Generate zend_vm_get_opcode_handler() function - out($f, "static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op)\n"); + out($f, "static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op)\n"); out($f, "{\n"); if (!ZEND_VM_SPEC) { out($f, "\treturn zend_opcode_handlers[opcode];\n"); } else { - if (ZEND_VM_OLD_EXECUTOR) { - out($f, "\tif (zend_vm_old_executor) {\n"); - out($f, "\t\treturn zend_opcode_handlers[opcode];\n"); - out($f, "\t} else {\n"); - } out($f, "\t\tstatic const int zend_vm_decode[] = {\n"); out($f, "\t\t\t_UNUSED_CODE, /* 0 */\n"); out($f, "\t\t\t_CONST_CODE, /* 1 = IS_CONST */\n"); @@ -1436,9 +1404,6 @@ function gen_vm($def, $skel) { out($f, "\t\t\t_CV_CODE /* 16 = IS_CV */\n"); out($f, "\t\t};\n"); out($f, "\t\treturn zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]];\n"); - if (ZEND_VM_OLD_EXECUTOR) { - out($f, "\t}\n"); - } } out($f, "}\n\n"); @@ -1450,7 +1415,6 @@ function gen_vm($def, $skel) { // Export handlers and helpers if (count($export) > 0 && - !ZEND_VM_OLD_EXECUTOR && ZEND_VM_KIND != ZEND_VM_KIND_CALL) { out($f,"#undef OPLINE\n"); out($f,"#undef DCL_OPLINE\n"); @@ -1473,14 +1437,12 @@ function gen_vm($def, $skel) { out($f,"#undef ZEND_VM_ENTER\n"); out($f,"#undef ZEND_VM_LEAVE\n"); out($f,"#undef ZEND_VM_DISPATCH\n"); - out($f,"#undef ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL\n\n"); out($f,"#define ZEND_VM_CONTINUE() return 0\n"); out($f,"#define ZEND_VM_RETURN() return -1\n"); out($f,"#define ZEND_VM_ENTER() return 1\n"); out($f,"#define ZEND_VM_LEAVE() return 2\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n"); - out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data -\n"); + out($f,"\n"); } foreach ($export as $dsk) { list($kind, $func, $name) = $dsk; @@ -1498,15 +1460,7 @@ function gen_vm($def, $skel) { $code = $h['code']; } $done = 0; - if (ZEND_VM_OLD_EXECUTOR) { - if ($kind == "handler") { - out($f, "{\n\treturn ".$name."_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n}\n\n"); - $done = 1; - } else if ($helpers[$name]["param"] == null) { - out($f, "{\n\treturn ".$name."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n}\n\n"); - $done = 1; - } - } else if (ZEND_VM_KIND == ZEND_VM_KIND_CALL) { + if (ZEND_VM_KIND == ZEND_VM_KIND_CALL) { if ($kind == "handler") { $op = $opcodes[$opnames[$name]]; if (isset($op['op1']["ANY"]) && isset($op['op2']["ANY"])) { @@ -1535,7 +1489,6 @@ function usage() { "\nOptions:". "\n --with-vm-kind=CALL|SWITCH|GOTO - select threading model (default is CALL)". "\n --without-specializer - disable executor specialization". - "\n --with-old-executor - enable old executor". "\n --with-lines - enable #line directives". "\n\n"); } @@ -1562,9 +1515,6 @@ for ($i = 1; $i < $argc; $i++) { } else if ($argv[$i] == "--without-specializer") { // Disabling specialization define("ZEND_VM_SPEC", 0); - } else if ($argv[$i] == "--with-old-executor") { - // Disabling code for old-style executor - define("ZEND_VM_OLD_EXECUTOR", 1); } else if ($argv[$i] == "--with-lines") { // Enabling debugging using original zend_vm_def.h define("ZEND_VM_LINES", 1); @@ -1587,10 +1537,6 @@ if (!defined("ZEND_VM_SPEC")) { // Using specialized executor by default define("ZEND_VM_SPEC", 1); } -if (!defined("ZEND_VM_OLD_EXECUTOR")) { - // Include old-style executor by default - define("ZEND_VM_OLD_EXECUTOR", 0); -} if (!defined("ZEND_VM_LINES")) { // Disabling #line directives define("ZEND_VM_LINES", 0); diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index 2bdffcaac3..05e1e09ca5 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -40,7 +40,7 @@ memset(&(opline)->op1, 0, sizeof((opline)->op1)); \ memset(&(opline)->op2, 0, sizeof((opline)->op2)); \ (opline)->result_type = (opline)->op1_type = (opline)->op2_type=IS_UNUSED; \ - (opline)->handler = zend_opcode_handlers[ZEND_NOP]; \ + zend_vm_set_opcode_handler(opline); \ } while (0); #define RESULT_USED(op) (((op->result_type & IS_VAR) && !(op->result_type & EXT_TYPE_UNUSED)) || op->result_type == IS_TMP_VAR) #define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0)