diff options
author | Dmitry Stogov <dmitry@zend.com> | 2017-05-16 09:24:23 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2017-05-16 09:24:23 +0300 |
commit | 7640e0a5f97ee51ad62580b017ddefb60af5af15 (patch) | |
tree | e78b3a7857c608e1b82c57ab900fad34437f1eb1 | |
parent | 0722a0188f24a68c18364e2a2bf1443ca2011763 (diff) | |
download | php-git-7640e0a5f97ee51ad62580b017ddefb60af5af15.tar.gz |
HYBRID VM cleanup
-rw-r--r-- | Zend/zend_vm.h | 4 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 28 | ||||
-rw-r--r-- | Zend/zend_vm_execute.skl | 8 | ||||
-rw-r--r-- | Zend/zend_vm_gen.php | 119 |
4 files changed, 98 insertions, 61 deletions
diff --git a/Zend/zend_vm.h b/Zend/zend_vm.h index cff9487ed3..caa896d3e1 100644 --- a/Zend/zend_vm.h +++ b/Zend/zend_vm.h @@ -28,8 +28,8 @@ ZEND_API void zend_vm_set_opcode_handler(zend_op* opcode); ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* opcode, uint32_t op1_info, uint32_t op2_info, uint32_t res_info); ZEND_API void zend_serialize_opcode_handler(zend_op *op); ZEND_API void zend_deserialize_opcode_handler(zend_op *op); -ZEND_API const void *zend_get_real_opcode_handler(const zend_op *op); -ZEND_API const zend_op *zend_get_real_exit_op(void); +ZEND_API const void *zend_get_opcode_handler_func(const zend_op *op); +ZEND_API const zend_op *zend_get_halt_op(void); ZEND_API int zend_vm_call_opcode_handler(zend_execute_data *ex); ZEND_API int zend_vm_kind(void); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index f6e91b17bc..1183d93062 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -319,7 +319,6 @@ 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 @@ -400,7 +399,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_real_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_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS); @@ -59223,7 +59222,7 @@ ZEND_API void zend_deserialize_opcode_handler(zend_op *op) op->handler = zend_opcode_handlers[(zend_uintptr_t)op->handler]; } -ZEND_API const void *zend_get_real_opcode_handler(const zend_op *op) +ZEND_API const void *zend_get_opcode_handler_func(const zend_op *op) { #if ZEND_VM_KIND == ZEND_VM_KIND_CALL return op->handler; @@ -59235,16 +59234,16 @@ ZEND_API const void *zend_get_real_opcode_handler(const zend_op *op) } zv = zend_hash_index_find(zend_handlers_table, (zend_long)(zend_uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); - return zend_opcode_real_handlers[Z_LVAL_P(zv)]; + return zend_opcode_handler_funcs[Z_LVAL_P(zv)]; #else return NULL; #endif } -ZEND_API const zend_op *zend_get_real_exit_op(void) +ZEND_API const zend_op *zend_get_halt_op(void) { #if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID - return &hybrid_return_op; + return &hybrid_halt_op; #else return NULL; #endif @@ -59306,23 +59305,6 @@ 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_execute.skl b/Zend/zend_vm_execute.skl index 81397ce20b..eb60787042 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -83,7 +83,7 @@ ZEND_API void zend_deserialize_opcode_handler(zend_op *op) op->handler = zend_opcode_handlers[(zend_uintptr_t)op->handler]; } -ZEND_API const void *zend_get_real_opcode_handler(const zend_op *op) +ZEND_API const void *zend_get_opcode_handler_func(const zend_op *op) { #if ZEND_VM_KIND == ZEND_VM_KIND_CALL return op->handler; @@ -95,16 +95,16 @@ ZEND_API const void *zend_get_real_opcode_handler(const zend_op *op) } zv = zend_hash_index_find(zend_handlers_table, (zend_long)(zend_uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); - return zend_opcode_real_handlers[Z_LVAL_P(zv)]; + return zend_opcode_handler_funcs[Z_LVAL_P(zv)]; #else return NULL; #endif } -ZEND_API const zend_op *zend_get_real_exit_op(void) +ZEND_API const zend_op *zend_get_halt_op(void) { #if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID - return &hybrid_return_op; + return &hybrid_halt_op; #else return NULL; #endif diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index fc51425e89..2b49d20a4d 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -1540,7 +1540,7 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n"); break; case ZEND_VM_KIND_HYBRID: - out($f,"\t\t\tHYBRID_CASE(HYBRID_RETURN):\n"); + out($f,"\t\t\tHYBRID_CASE(HYBRID_HALT):\n"); out($f,"\t\t\t\texecute_data = orig_execute_data;\n"); out($f,"\t\t\t\topline = orig_opline;\n"); out($f,"\t\t\t\treturn;\n"); @@ -1583,12 +1583,18 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"static int zend_handlers_count;\n"); if ($kind == ZEND_VM_KIND_HYBRID) { out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f,"static const void **zend_opcode_real_handlers;\n"); - out($f,"static zend_op hybrid_return_op;\n"); + out($f,"static const void **zend_opcode_handler_funcs;\n"); + out($f,"static zend_op hybrid_halt_op;\n"); out($f,"#endif\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"); + out($f,"static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n"); + if ($kind == ZEND_VM_KIND_HYBRID) { + out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); + out($f,"static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op);\n"); + out($f,"#else\n"); + out($f,"# define zend_vm_get_opcode_handler_func zend_vm_get_opcode_handler\n"); + out($f,"#endif\n\n"); + } switch ($kind) { case ZEND_VM_KIND_HYBRID: out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); @@ -1634,7 +1640,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"# endif\n"); if ($kind == ZEND_VM_KIND_HYBRID) { out($f,"# if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f,"# define ZEND_VM_RETURN() opline = &hybrid_return_op; return\n"); + out($f,"# define ZEND_VM_RETURN() opline = &hybrid_halt_op; return\n"); out($f,"# define ZEND_VM_HOT zend_always_inline\n"); out($f,"# else\n"); out($f,"# define ZEND_VM_RETURN() opline = NULL; return\n"); @@ -1691,7 +1697,11 @@ 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_real_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); + if ($kind == ZEND_VM_KIND_HYBRID) { + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler_func(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); + } else { + 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,"\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);"); out($f,"\n"); @@ -1812,9 +1822,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,$prolog."\tzend_opcode_handlers = (const void **) labels;\n"); out($f,$prolog."\tzend_handlers_count = sizeof(labels) / sizeof(void*);\n"); if ($kind == ZEND_VM_KIND_HYBRID) { - out($f,$prolog."\tmemset(&hybrid_return_op, 0, sizeof(hybrid_return_op));\n"); - out($f,$prolog."\thybrid_return_op.handler = (void*)&&HYBRID_RETURN_LABEL;\n"); - out($f,$prolog."\tgoto HYBRID_RETURN_LABEL;\n"); + out($f,$prolog."\tmemset(&hybrid_halt_op, 0, sizeof(hybrid_halt_op));\n"); + out($f,$prolog."\thybrid_halt_op.handler = (void*)&&HYBRID_HALT_LABEL;\n"); + out($f,$prolog."\tgoto HYBRID_HALT_LABEL;\n"); } else { out($f,$prolog."\treturn;\n"); } @@ -1929,7 +1939,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,$prolog."};\n"); if ($kind == ZEND_VM_KIND_HYBRID) { out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f,$prolog."zend_opcode_real_handlers = labels;\n"); + out($f,$prolog."zend_opcode_handler_funcs = labels;\n"); out($f,$prolog."zend_spec_handlers = specs;\n"); out($f,$prolog.$executor_name."_ex(NULL);\n"); out($f,"#else\n"); @@ -2455,26 +2465,71 @@ 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"); + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { + // Generate zend_vm_get_opcode_handler_func() function + out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID\n"); + out($f,"static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op)\n"); + out($f, "{\n"); + out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n"); + if (!ZEND_VM_SPEC) { + out($f, "\treturn zend_opcode_handler_funcs[spec];\n"); + } else { + out($f, "\tstatic const int zend_vm_decode[] = {\n"); + out($f, "\t\t_UNUSED_CODE, /* 0 */\n"); + out($f, "\t\t_CONST_CODE, /* 1 = IS_CONST */\n"); + out($f, "\t\t_TMP_CODE, /* 2 = IS_TMP_VAR */\n"); + out($f, "\t\t_UNUSED_CODE, /* 3 */\n"); + out($f, "\t\t_VAR_CODE, /* 4 = IS_VAR */\n"); + out($f, "\t\t_UNUSED_CODE, /* 5 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 6 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 7 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 8 = IS_UNUSED */\n"); + out($f, "\t\t_UNUSED_CODE, /* 9 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 10 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 11 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 12 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 13 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 14 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 15 */\n"); + out($f, "\t\t_CV_CODE /* 16 = IS_CV */\n"); + out($f, "\t};\n"); + out($f, "\tuint32_t offset = 0;\n"); + out($f, "\tif (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];\n"); + out($f, "\tif (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];\n"); + if (isset($used_extra_spec["OP_DATA"])) { + out($f, "\tif (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n"); + } + if (isset($used_extra_spec["RETVAL"])) { + out($f, "\tif (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);\n"); + } + if (isset($used_extra_spec["QUICK_ARG"])) { + out($f, "\tif (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);\n"); + } + if (isset($used_extra_spec["SMART_BRANCH"])) { + out($f, "\tif (spec & SPEC_RULE_SMART_BRANCH) {\n"); + out($f, "\t\toffset = offset * 3;\n"); + out($f, "\t\tif ((op+1)->opcode == ZEND_JMPZ) {\n"); + out($f, "\t\t\toffset += 1;\n"); + out($f, "\t\t} else if ((op+1)->opcode == ZEND_JMPNZ) {\n"); + out($f, "\t\t\toffset += 2;\n"); + out($f, "\t\t}\n"); + out($f, "\t}\n"); + } + if (isset($used_extra_spec["DIM_OBJ"])) { + out($f, "\tif (spec & SPEC_RULE_DIM_OBJ) {\n"); + out($f, "\t\toffset = offset * 3;\n"); + out($f, "\t\tif (op->extended_value == ZEND_ASSIGN_DIM) {\n"); + out($f, "\t\t\toffset += 1;\n"); + out($f, "\t\t} else if (op->extended_value == ZEND_ASSIGN_OBJ) {\n"); + out($f, "\t\t\toffset += 2;\n"); + out($f, "\t\t}\n"); + out($f, "\t}\n"); + } + out($f, "\treturn zend_opcode_handler_funcs[(spec & SPEC_START_MASK) + offset];\n"); + } + out($f, "}\n\n"); + out($f, "#endif\n\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"); @@ -2556,9 +2611,9 @@ function gen_vm($def, $skel) { out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n"); if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f, "\thandler = (opcode_handler_t)zend_get_real_opcode_handler(opline);\n"); + out($f, "\thandler = (opcode_handler_t)zend_vm_get_opcode_handler_func(opline->opcode, opline);\n"); out($f, "\thandler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); - out($f, "\tif (EXPECTED(opline != &hybrid_return_op)) {\n"); + out($f, "\tif (EXPECTED(opline != &hybrid_halt_op)) {\n"); out($f,"#else\n"); } out($f, "\t((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); |