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
#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);
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);
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");
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");
}
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");