]> granicus.if.org Git - php/commitdiff
Fix so that extensions like xdebug, can overload opcodes in all execution modes inclu...
authorDmitry Stogov <dmitry@php.net>
Fri, 10 Jun 2005 09:54:38 +0000 (09:54 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 10 Jun 2005 09:54:38 +0000 (09:54 +0000)
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_extensions.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_gen.php
Zend/zend_vm_opcodes.h

index ffae16f5774fbd83100e7f3e6b54d38fa1066e97..d3ae96caf514598f68c599ea945cf2d0961ddd00 100644 (file)
@@ -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
index 7e96ecc39fc955deb447038b6f047162b2eb325b..509d624b4f191af3e1a2c9fbde87fc2c116218a1 100644 (file)
@@ -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 */
index 19584341ba8b2b8a48682abc9af40788c1805391..a937430d88e17aa0d2f48f3d885a4289720e8243 100644 (file)
@@ -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;
index e8d5e71c59226010f060efd3818e2ec0dbf60edf..8d5d81a54cd439564cb6357a7fc2e781570315cd 100644 (file)
@@ -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));
+       }
+}
+
index cdc4adbd07294667682d3435960e3b07635a56d9..74e74430cf5c1a9ec7e4beeb03b7498d7c96a022 100644 (file)
 
 /* $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);
+}
+
index 4d6c0f3611514f911632970dd8f66376d8b7bf3d..03d0ae1211a98671313d373d7fc90ea873cae9c3 100644 (file)
@@ -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";
 }
index 36dee54f3d66100cd8fdf83a2db6b24485c2f48d..4a907d4ec31b19bffd76c78015ae551c6f75d367 100644 (file)
 #define ZEND_ASSIGN_DIM              147
 #define ZEND_ISSET_ISEMPTY_PROP_OBJ  148
 #define ZEND_HANDLE_EXCEPTION        149
+#define ZEND_USER_OPCODE             150