/* $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)
{
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);
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;
#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)
{
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()
{
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 */
_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);
+}
+
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;
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");
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]);
}
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");
// 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);
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");
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";
}