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_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);
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;
}
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
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,"\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");
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");
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");
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");
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");
}
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");
}
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");
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");