summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2017-05-16 09:24:23 +0300
committerDmitry Stogov <dmitry@zend.com>2017-05-16 09:24:23 +0300
commit7640e0a5f97ee51ad62580b017ddefb60af5af15 (patch)
treee78b3a7857c608e1b82c57ab900fad34437f1eb1
parent0722a0188f24a68c18364e2a2bf1443ca2011763 (diff)
downloadphp-git-7640e0a5f97ee51ad62580b017ddefb60af5af15.tar.gz
HYBRID VM cleanup
-rw-r--r--Zend/zend_vm.h4
-rw-r--r--Zend/zend_vm_execute.h28
-rw-r--r--Zend/zend_vm_execute.skl8
-rw-r--r--Zend/zend_vm_gen.php119
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");