diff options
author | Dmitry Stogov <dmitry@php.net> | 2005-06-10 09:54:38 +0000 |
---|---|---|
committer | Dmitry Stogov <dmitry@php.net> | 2005-06-10 09:54:38 +0000 |
commit | 84b96e9b03534400f155c5580f1c2fe399966bb3 (patch) | |
tree | 22c3e761370a26af46bd759b73536d1fc04af2be | |
parent | 6efa17c2a1dd3448718845b9bbd93ca7769c7068 (diff) | |
download | php-git-84b96e9b03534400f155c5580f1c2fe399966bb3.tar.gz |
Fix so that extensions like xdebug, can overload opcodes in all execution modes including goto/switch
-rw-r--r-- | Zend/zend_execute.c | 15 | ||||
-rw-r--r-- | Zend/zend_execute.h | 7 | ||||
-rw-r--r-- | Zend/zend_extensions.h | 2 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 13 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 89 | ||||
-rw-r--r-- | Zend/zend_vm_gen.php | 49 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.h | 1 |
7 files changed, 159 insertions, 17 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index ffae16f577..d3ae96caf5 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1460,6 +1460,21 @@ static int zend_vm_old_executor = 0; #include "zend_vm_execute.h" +ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, opcode_handler_t handler) +{ + if (opcode != ZEND_USER_OPCODE) { + zend_user_opcodes[opcode] = ZEND_USER_OPCODE; + zend_user_opcode_handlers[opcode] = handler; + return SUCCESS; + } + return FAILURE; +} + +ZEND_API opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode) +{ + return zend_user_opcode_handlers[opcode]; +} + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 7e96ecc39f..509d624b4f 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -176,6 +176,13 @@ void zend_shutdown_timeout_thread(); ZEND_API zval** zend_get_compiled_variable_value(zend_execute_data *execute_data_ptr, zend_uint var); +#define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */ +#define ZEND_USER_OPCODE_RETURN 1 /* exit from executor (return from function) */ +#define ZEND_USER_OPCODE_DISPATCH 2 /* call original opcode handler */ + +ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, opcode_handler_t handler); +ZEND_API opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode); + END_EXTERN_C() #endif /* ZEND_EXECUTE_H */ diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index 19584341ba..a937430d88 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -27,7 +27,7 @@ /* The first number is the engine version and the rest is the date. * This way engine 2 API no. is always greater than engine 1 API no.. */ -#define ZEND_EXTENSION_API_NO 220041031 +#define ZEND_EXTENSION_API_NO 220050610 typedef struct _zend_extension_version_info { int zend_extension_api_no; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e8d5e71c59..8d5d81a54c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3581,3 +3581,16 @@ ZEND_VM_HANDLER(146, ZEND_VERIFY_ABSTRACT_CLASS, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY) +{ + switch (zend_user_opcode_handlers[EX(opline)->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL)) { + case ZEND_USER_OPCODE_CONTINUE: + ZEND_VM_CONTINUE(); + case ZEND_USER_OPCODE_RETURN: + ZEND_VM_RETURN(); + case ZEND_USER_OPCODE_DISPATCH: + default: + ZEND_VM_DISPATCH(EX(opline)); + } +} + diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index cdc4adbd07..74e74430cf 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -18,9 +18,18 @@ /* $Id$ */ +static opcode_handler_t zend_user_opcode_handlers[256] = {(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL,(opcode_handler_t)NULL}; -#define ZEND_VM_CONTINUE() return 0 -#define ZEND_VM_RETURN() return 1 +static zend_uchar zend_user_opcodes[256] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; + +static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op); + + +#define ZEND_VM_CONTINUE() return 0 +#define ZEND_VM_RETURN() return 1 +#define ZEND_VM_DISPATCH(op) return zend_vm_get_opcode_handler(op->opcode, op)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + +#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) { @@ -544,6 +553,19 @@ static int ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } +static int ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + switch (zend_user_opcode_handlers[EX(opline)->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL)) { + case ZEND_USER_OPCODE_CONTINUE: + ZEND_VM_CONTINUE(); + case ZEND_USER_OPCODE_RETURN: + ZEND_VM_RETURN(); + case ZEND_USER_OPCODE_DISPATCH: + default: + ZEND_VM_DISPATCH(EX(opline)); + } +} + static int ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -29477,6 +29499,31 @@ void zend_init_opcodes_handlers() ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; @@ -29491,9 +29538,18 @@ void zend_init_opcodes_handlers() #undef ZEND_VM_RETURN +#undef ZEND_VM_DISPATCH + +#undef ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL + +static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op); + -#define ZEND_VM_CONTINUE() return 0 -#define ZEND_VM_RETURN() return 1 +#define ZEND_VM_CONTINUE() return 0 +#define ZEND_VM_RETURN() return 1 +#define ZEND_VM_DISPATCH(op) return zend_vm_get_opcode_handler(op->opcode, op)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + +#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC ZEND_API void old_execute(zend_op_array *op_array TSRMLS_DC) { @@ -33116,6 +33172,19 @@ static int ZEND_VERIFY_ABSTRACT_CLASS_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } +static int ZEND_USER_OPCODE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + switch (zend_user_opcode_handlers[EX(opline)->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL)) { + case ZEND_USER_OPCODE_CONTINUE: + ZEND_VM_CONTINUE(); + case ZEND_USER_OPCODE_RETURN: + ZEND_VM_RETURN(); + case ZEND_USER_OPCODE_DISPATCH: + default: + ZEND_VM_DISPATCH(EX(opline)); + } +} + void zend_vm_use_old_executor() { @@ -33270,16 +33339,17 @@ void zend_vm_use_old_executor() ZEND_ASSIGN_DIM_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_HANDLER, ZEND_HANDLE_EXCEPTION_HANDLER, + ZEND_USER_OPCODE_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; zend_vm_old_executor = 1; zend_execute = old_execute; } -void zend_vm_set_opcode_handler(zend_op* op) +static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op) { if (zend_vm_old_executor) { - op->handler = zend_opcode_handlers[op->opcode]; + return zend_opcode_handlers[opcode]; } else { static const int zend_vm_decode[] = { _UNUSED_CODE, /* 0 */ @@ -33300,7 +33370,12 @@ void zend_vm_set_opcode_handler(zend_op* op) _UNUSED_CODE, /* 15 */ _CV_CODE /* 16 = IS_CV */ }; - op->handler = zend_opcode_handlers[op->opcode * 25 + zend_vm_decode[op->op1.op_type] * 5 + zend_vm_decode[op->op2.op_type]]; + return zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1.op_type] * 5 + zend_vm_decode[op->op2.op_type]]; } } +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_gen.php b/Zend/zend_vm_gen.php index 4d6c0f3611..03d0ae1211 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -703,21 +703,28 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, if (preg_match("/(.*)[{][%]([A-Z_]*)[%][}](.*)/", $line, $m)) { switch ($m[2]) { case "DEFINES": + out($f,"static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op);\n\n"); switch ($kind) { case ZEND_VM_KIND_CALL: out($f,"\n"); - out($f,"#define ZEND_VM_CONTINUE() return 0\n"); - out($f,"#define ZEND_VM_RETURN() return 1\n"); + out($f,"#define ZEND_VM_CONTINUE() return 0\n"); + out($f,"#define ZEND_VM_RETURN() return 1\n"); + out($f,"#define ZEND_VM_DISPATCH(op) return zend_vm_get_opcode_handler(op->opcode, op)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); break; case ZEND_VM_KIND_SWITCH: out($f,"\n"); out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n"); out($f,"#define ZEND_VM_RETURN() return\n"); + out($f,"#define ZEND_VM_DISPATCH(op) dispatch_handler = zend_vm_get_opcode_handler(op->opcode, op); goto zend_vm_dispatch;\n\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL &execute_data TSRMLS_CC\n"); break; case ZEND_VM_KIND_GOTO: out($f,"\n"); out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(EX(opline)->handler)\n"); out($f,"#define ZEND_VM_RETURN() return\n"); + out($f,"#define ZEND_VM_DISPATCH(op) goto *(void**)(zend_vm_get_opcode_handler(op->opcode, op));\n\n"); + out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL &execute_data TSRMLS_CC\n"); break; } break; @@ -726,6 +733,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, break; case "HELPER_VARS": if ($kind != ZEND_VM_KIND_CALL) { + if ($kind == ZEND_VM_KIND_SWITCH) { + out($f,$m[1]."opcode_handler_t dispatch_handler;\n"); + } // Emit local variables those are used for helpers' parameters foreach ($params as $param => $x) { out($f,$m[1].$param.";\n"); @@ -753,7 +763,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, case "ZEND_VM_CONTINUE_LABEL": if ($kind == ZEND_VM_KIND_SWITCH) { // Only SWITCH dispatch method use it - out($f,$m[1]."zend_vm_continue:".$m[3]."\n"); + out($f,"zend_vm_continue:".$m[3]."\n"); } else { skip_blanks($f, $m[1], $m[3]); } @@ -765,7 +775,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f, $m[1]."if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0)".$m[3]."\n"); break; case ZEND_VM_KIND_SWITCH: - out($f, $m[1]."switch ((int)EX(opline)->handler)".$m[3]."\n"); + out($f, $m[1]."dispatch_handler = EX(opline)->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)dispatch_handler)".$m[3]."\n"); break; case ZEND_VM_KIND_GOTO: out($f, $m[1]."goto *(void**)(EX(opline)->handler);".$m[3]."\n"); @@ -974,6 +984,19 @@ function gen_vm($def, $skel) { // Insert header out($f, $GLOBALS['header_text']); + // Support for ZEND_USER_OPCODE + out($f, "static opcode_handler_t zend_user_opcode_handlers[256] = {"); + for ($i = 0; $i < 255; ++$i) { + out($f, "(opcode_handler_t)NULL,"); + } + out($f, "(opcode_handler_t)NULL};\n\n"); + + out($f, "static zend_uchar zend_user_opcodes[256] = {"); + for ($i = 0; $i < 255; ++$i) { + out($f, "$i,"); + } + out($f, "255};\n\n"); + // Generate specialized executor gen_executor($f, $skl, ZEND_VM_SPEC, ZEND_VM_KIND, "execute", "zend_init_opcodes_handlers", 0); @@ -984,18 +1007,20 @@ function gen_vm($def, $skel) { out($f,"#define EX(element) execute_data.element\n\n"); out($f,"#undef ZEND_VM_CONTINUE\n\n"); out($f,"#undef ZEND_VM_RETURN\n\n"); + out($f,"#undef ZEND_VM_DISPATCH\n\n"); + out($f,"#undef ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL\n\n"); gen_executor($f, $skl, 0, ZEND_VM_KIND_CALL, "old_execute", "zend_vm_use_old_executor", 1); } - // Generate zend_vm_set_opcode_handler() function - out($f, "void zend_vm_set_opcode_handler(zend_op* op)\n"); + // Generate zend_vm_get_opcode_handler() function + out($f, "static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op)\n"); out($f, "{\n"); if (!ZEND_VM_SPEC) { - out($f, "\top->handler = zend_opcode_handlers[op->opcode];\n"); + out($f, "\treturn zend_opcode_handlers[opcode];\n"); } else { if (ZEND_VM_OLD_EXECUTOR) { out($f, "\tif (zend_vm_old_executor) {\n"); - out($f, "\t\top->handler = zend_opcode_handlers[op->opcode];\n"); + out($f, "\t\treturn zend_opcode_handlers[opcode];\n"); out($f, "\t} else {\n"); } out($f, "\t\tstatic const int zend_vm_decode[] = {\n"); @@ -1017,13 +1042,19 @@ function gen_vm($def, $skel) { out($f, "\t\t\t_UNUSED_CODE, /* 15 */\n"); out($f, "\t\t\t_CV_CODE /* 16 = IS_CV */\n"); out($f, "\t\t};\n"); - out($f, "\t\top->handler = zend_opcode_handlers[op->opcode * 25 + zend_vm_decode[op->op1.op_type] * 5 + zend_vm_decode[op->op2.op_type]];\n"); + out($f, "\t\treturn zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1.op_type] * 5 + zend_vm_decode[op->op2.op_type]];\n"); if (ZEND_VM_OLD_EXECUTOR) { out($f, "\t}\n"); } } out($f, "}\n\n"); + // Generate zend_vm_get_opcode_handler() function + out($f, "void zend_vm_set_opcode_handler(zend_op* op)\n"); + out($f, "{\n"); + out($f, "\top->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op);\n"); + out($f, "}\n\n"); + fclose($f); echo "zend_vm_execute.h generated succesfull.\n"; } diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 36dee54f3d..4a907d4ec3 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -145,3 +145,4 @@ #define ZEND_ASSIGN_DIM 147 #define ZEND_ISSET_ISEMPTY_PROP_OBJ 148 #define ZEND_HANDLE_EXCEPTION 149 +#define ZEND_USER_OPCODE 150 |