com php-src: HYBRID VM cleanup: Zend/zend_vm.h Zend/zend _vm_execute.h Zend/zend_vm_execute.skl Zend/zen d_vm_gen.php

[email protected] (Dmitry Stogov)
Newsgroups php.cvs
Message-ID <[email protected]>
Commit:    7640e0a5f97ee51ad62580b017ddefb60af5af15
Author:    Dmitry Stogov <[email protected]>         Tue, 16 May 2017 09:24:23 +0300
Parents:   0722a0188f24a68c18364e2a2bf1443ca2011763
Branches:  master

Link:       http://git.php.net/?p=php-src.git;a=commitdiff;h=7640e0a5f97ee51ad62580b017ddefb60af5af15

Log:
HYBRID VM cleanup

Changed paths:
  M  Zend/zend_vm.h
  M  Zend/zend_vm_execute.h
  M  Zend/zend_vm_execute.skl
  M  Zend/zend_vm_gen.php
diff_7640e0a5f97ee51ad62580b017ddefb60af5af15.txt (text/plain, 14.6 KB)
diff --git a/Zend/zend_vm.h b/Zend/zend_vm.h
index cff9487..caa896d 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 f6e91b1..1183d93 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 81397ce..eb60787 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 fc51425..2b49d20 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");
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.