]> granicus.if.org Git - php/commitdiff
Executor cleanup: fix GOTO and SWITCH VMs, remove aility to build additional PHP...
authorDmitry Stogov <dmitry@zend.com>
Thu, 12 Mar 2015 17:39:04 +0000 (20:39 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 12 Mar 2015 17:39:04 +0000 (20:39 +0300)
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_gen.php
ext/opcache/Optimizer/zend_optimizer_internal.h

index 8e4148795e8437f6e998f1ea7970bab5101404c9..42f55f952172094017ac075ef588ec398728ee5a 100644 (file)
@@ -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;
index 59e585e35b06e23346107f31c92bcb573cfc3ca9..4a8b4694b7b097a6b256eb959fff3db5d4d46672 100644 (file)
@@ -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);
index d33735291a267f5f50cea745bcab9dcc3aa2da04..0149da692990835d68cefe6add19e35779630111 100644 (file)
@@ -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);
 
index ffb737d2a2d00d305bbf42c609b52cb50b51309d..09de8b2f4c4cba6d92e27cbeb057220a15e9a486 100644 (file)
@@ -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)
index 66cbf0453ab490d097a5a5690283966a97c3319b..b66e724358f25412a6ecfc13bb487322e7869e03 100644 (file)
@@ -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);
-}
-
index 65b1c72c067df3b2078943126dd391f7557c0f6c..244080c3a47ed05a855c129dc2997a969a0cf363 100644 (file)
@@ -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);
index 2bdffcaac35a2e9f33424c0c3292927faf7f6d95..05e1e09ca5bbae581fcfc76f58b40ad046427895 100644 (file)
@@ -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)