]> granicus.if.org Git - php/commitdiff
Fixed USER_OPCODE handling in HYBRID VM.
authorDmitry Stogov <dmitry@zend.com>
Mon, 15 May 2017 18:17:58 +0000 (21:17 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 15 May 2017 18:17:58 +0000 (21:17 +0300)
Zend/zend_vm_execute.h
Zend/zend_vm_gen.php

index 0fd86818626607327ebc6573e0e87902bc343296..f6e91b17bc5d1bb33620043cda107fc2367ceb1a 100644 (file)
@@ -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);
index 92185743804c6989a2eca72614b7fb3d4f16224b..fc51425e890cb328083ed8eda3e08eecbd070f2a 100644 (file)
@@ -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");