From: Dmitry Stogov Date: Mon, 15 May 2017 18:17:58 +0000 (+0300) Subject: Fixed USER_OPCODE handling in HYBRID VM. X-Git-Tag: php-7.2.0alpha2~15^2~20 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=69b4f8ed7978818b30de8840f16c753f0f634fcc;p=php Fixed USER_OPCODE handling in HYBRID VM. --- diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0fd8681862..f6e91b17bc 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -319,6 +319,7 @@ static const uint32_t *zend_spec_handlers; static const void **zend_opcode_handlers; static int zend_handlers_count; static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op); +static const void *zend_vm_get_real_opcode_handler(zend_uchar opcode, const zend_op* op); #ifdef ZEND_VM_FP_GLOBAL_REG @@ -399,7 +400,7 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H #endif #define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); #define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_real_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS); @@ -59305,6 +59306,23 @@ static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* return zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op); } +static const void *zend_vm_get_real_opcode_handler(zend_uchar opcode, const zend_op* op) +{ + const void *handler = zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op); +#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID + zval *zv; + + if (!zend_handlers_table) { + init_opcode_serialiser(); + } + zv = zend_hash_index_find(zend_handlers_table, (zend_long)(zend_uintptr_t)handler); + ZEND_ASSERT(zv != NULL); + return zend_opcode_real_handlers[Z_LVAL_P(zv)]; +#else + return handler; +#endif +} + ZEND_API void zend_vm_set_opcode_handler(zend_op* op) { op->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op); diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 9218574380..fc51425e89 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -1587,7 +1587,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"static zend_op hybrid_return_op;\n"); out($f,"#endif\n"); } - out($f,"static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n"); + out($f,"static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n"); + out($f,"static const void *zend_vm_get_real_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n"); switch ($kind) { case ZEND_VM_KIND_HYBRID: out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); @@ -1690,7 +1691,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#endif\n"); out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_real_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); out($f,"\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);"); out($f,"\n"); @@ -2454,6 +2455,27 @@ function gen_vm($def, $skel) { } out($f, "}\n\n"); + // Generate zend_vm_get_real_opcode_handler() function + out($f, "static const void *zend_vm_get_real_opcode_handler(zend_uchar opcode, const zend_op* op)\n"); + out($f, "{\n"); + if (!ZEND_VM_SPEC) { + out($f, "\tconst void *handler = zend_vm_get_opcode_handler_ex(opcode, op);\n"); + } else { + out($f, "\tconst void *handler = zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op);\n"); + } + out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID\n"); + out($f, "\tzval *zv;\n\n"); + out($f, "\tif (!zend_handlers_table) {\n"); + out($f, "\tinit_opcode_serialiser();\n"); + out($f, "\t}\n"); + out($f, "\tzv = zend_hash_index_find(zend_handlers_table, (zend_long)(zend_uintptr_t)handler);\n"); + out($f, "\tZEND_ASSERT(zv != NULL);\n"); + out($f, "\treturn zend_opcode_real_handlers[Z_LVAL_P(zv)];\n"); + out($f, "#else\n"); + out($f, "\treturn handler;\n"); + out($f, "#endif\n"); + out($f, "}\n\n"); + // Generate zend_vm_get_opcode_handler() function out($f, "ZEND_API void zend_vm_set_opcode_handler(zend_op* op)\n"); out($f, "{\n");