]> granicus.if.org Git - php/commitdiff
Reduce overhead of extra-specialization for opcode handler selection.
authorDmitry Stogov <dmitry@zend.com>
Thu, 22 Mar 2018 08:33:17 +0000 (11:33 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 22 Mar 2018 08:33:17 +0000 (11:33 +0300)
Zend/zend_vm_execute.h
Zend/zend_vm_gen.php

index 34fdcbd6bb428a0ceb9e52d7ebb8c4aae33a3365..66915b5ab821d2b0901e130d084083f080634749 100644 (file)
@@ -307,6 +307,7 @@ static zend_uchar zend_user_opcodes[256] = {0,
 };
 
 #define SPEC_START_MASK        0x0000ffff
+#define SPEC_EXTRA_MASK        0xfffc0000
 #define SPEC_RULE_OP1          0x00010000
 #define SPEC_RULE_OP2          0x00020000
 #define SPEC_RULE_OP_DATA      0x00040000
@@ -64350,23 +64351,25 @@ static const void *zend_vm_get_opcode_handler_ex(uint32_t spec, const zend_op* o
        uint32_t offset = 0;
        if (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];
        if (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];
-       if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];
-       if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);
-       if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);
-       if (spec & SPEC_RULE_SMART_BRANCH) {
-               offset = offset * 3;
-               if ((op+1)->opcode == ZEND_JMPZ) {
-                       offset += 1;
-               } else if ((op+1)->opcode == ZEND_JMPNZ) {
-                       offset += 2;
+       if (spec & SPEC_EXTRA_MASK) {
+               if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];
+               else if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);
+               else if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);
+               else if (spec & SPEC_RULE_SMART_BRANCH) {
+                       offset = offset * 3;
+                       if ((op+1)->opcode == ZEND_JMPZ) {
+                               offset += 1;
+                       } else if ((op+1)->opcode == ZEND_JMPNZ) {
+                               offset += 2;
+                       }
                }
-       }
-       if (spec & SPEC_RULE_DIM_OBJ) {
-               offset = offset * 3;
-               if (op->extended_value == ZEND_ASSIGN_DIM) {
-                       offset += 1;
-               } else if (op->extended_value == ZEND_ASSIGN_OBJ) {
-                       offset += 2;
+               else if (spec & SPEC_RULE_DIM_OBJ) {
+                       offset = offset * 3;
+                       if (op->extended_value == ZEND_ASSIGN_DIM) {
+                               offset += 1;
+                       } else if (op->extended_value == ZEND_ASSIGN_OBJ) {
+                               offset += 2;
+                       }
                }
        }
        return zend_opcode_handlers[(spec & SPEC_START_MASK) + offset];
@@ -64397,23 +64400,25 @@ static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend
        uint32_t offset = 0;
        if (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];
        if (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];
-       if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];
-       if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);
-       if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);
-       if (spec & SPEC_RULE_SMART_BRANCH) {
-               offset = offset * 3;
-               if ((op+1)->opcode == ZEND_JMPZ) {
-                       offset += 1;
-               } else if ((op+1)->opcode == ZEND_JMPNZ) {
-                       offset += 2;
-               }
-       }
-       if (spec & SPEC_RULE_DIM_OBJ) {
-               offset = offset * 3;
-               if (op->extended_value == ZEND_ASSIGN_DIM) {
-                       offset += 1;
-               } else if (op->extended_value == ZEND_ASSIGN_OBJ) {
-                       offset += 2;
+       if (spec & SPEC_EXTRA_MASK) {
+               if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];
+               else if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);
+               else if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);
+               else if (spec & SPEC_RULE_SMART_BRANCH) {
+                       offset = offset * 3;
+                       if ((op+1)->opcode == ZEND_JMPZ) {
+                               offset += 1;
+                       } else if ((op+1)->opcode == ZEND_JMPNZ) {
+                               offset += 2;
+                       }
+               }
+               else if (spec & SPEC_RULE_DIM_OBJ) {
+                       offset = offset * 3;
+                       if (op->extended_value == ZEND_ASSIGN_DIM) {
+                               offset += 1;
+                       } else if (op->extended_value == ZEND_ASSIGN_OBJ) {
+                               offset += 2;
+                       }
                }
        }
        return zend_opcode_handler_funcs[(spec & SPEC_START_MASK) + offset];
index 03b964b278783d956612ddcc6d1fed9a5867c792..74beb1af1daf6f56a119ab0a6015225b909e1ffd 100644 (file)
@@ -1698,6 +1698,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
                        switch ($m[2]) {
                                case "DEFINES":
                                        out($f,"#define SPEC_START_MASK        0x0000ffff\n");
+                                       out($f,"#define SPEC_EXTRA_MASK        0xfffc0000\n");
                                        out($f,"#define SPEC_RULE_OP1          0x00010000\n");
                                        out($f,"#define SPEC_RULE_OP2          0x00020000\n");
                                        out($f,"#define SPEC_RULE_OP_DATA      0x00040000\n");
@@ -2564,33 +2565,50 @@ function gen_vm($def, $skel) {
                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");
+
+               if (isset($used_extra_spec["OP_DATA"]) ||
+                   isset($used_extra_spec["RETVAL"]) ||
+                   isset($used_extra_spec["QUICK_ARG"]) ||
+                   isset($used_extra_spec["SMART_BRANCH"]) ||
+                   isset($used_extra_spec["DIM_OBJ"])) {
+
+                       $else = "";
+                       out($f, "\tif (spec & SPEC_EXTRA_MASK) {\n");
+
+                       if (isset($used_extra_spec["OP_DATA"])) {
+                               out($f, "\t\t{$else}if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n");
+                               $else = "else ";
+                       }
+                       if (isset($used_extra_spec["RETVAL"])) {
+                               out($f, "\t\t{$else}if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);\n");
+                               $else = "else ";
+                       }
+                       if (isset($used_extra_spec["QUICK_ARG"])) {
+                               out($f, "\t\t{$else}if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);\n");
+                               $else = "else ";
+                       }
+                       if (isset($used_extra_spec["SMART_BRANCH"])) {
+                               out($f, "\t\t{$else}if (spec & SPEC_RULE_SMART_BRANCH) {\n");
+                               out($f, "\t\t\toffset = offset * 3;\n");
+                               out($f, "\t\t\tif ((op+1)->opcode == ZEND_JMPZ) {\n");
+                               out($f, "\t\t\t\toffset += 1;\n");
+                               out($f, "\t\t\t} else if ((op+1)->opcode == ZEND_JMPNZ) {\n");
+                               out($f, "\t\t\t\toffset += 2;\n");
+                               out($f, "\t\t\t}\n");
+                               out($f, "\t\t}\n");
+                               $else = "else ";
+                       }
+                       if (isset($used_extra_spec["DIM_OBJ"])) {
+                               out($f, "\t\t{$else}if (spec & SPEC_RULE_DIM_OBJ) {\n");
+                               out($f, "\t\t\toffset = offset * 3;\n");
+                               out($f, "\t\t\tif (op->extended_value == ZEND_ASSIGN_DIM) {\n");
+                               out($f, "\t\t\t\toffset += 1;\n");
+                               out($f, "\t\t\t} else if (op->extended_value == ZEND_ASSIGN_OBJ) {\n");
+                               out($f, "\t\t\t\toffset += 2;\n");
+                               out($f, "\t\t\t}\n");
+                               out($f, "\t\t}\n");
+                               $else = "else ";
+                       }
                        out($f, "\t}\n");
                }
                out($f, "\treturn zend_opcode_handlers[(spec & SPEC_START_MASK) + offset];\n");
@@ -2630,35 +2648,53 @@ function gen_vm($def, $skel) {
                        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");
+
+                       if (isset($used_extra_spec["OP_DATA"]) ||
+                           isset($used_extra_spec["RETVAL"]) ||
+                           isset($used_extra_spec["QUICK_ARG"]) ||
+                           isset($used_extra_spec["SMART_BRANCH"]) ||
+                           isset($used_extra_spec["DIM_OBJ"])) {
+
+                               $else = "";
+                               out($f, "\tif (spec & SPEC_EXTRA_MASK) {\n");
+
+                               if (isset($used_extra_spec["OP_DATA"])) {
+                                       out($f, "\t\t{$else}if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n");
+                                       $else = "else ";
+                               }
+                               if (isset($used_extra_spec["RETVAL"])) {
+                                       out($f, "\t\t{$else}if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);\n");
+                                       $else = "else ";
+                               }
+                               if (isset($used_extra_spec["QUICK_ARG"])) {
+                                       out($f, "\t\t{$else}if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);\n");
+                                       $else = "else ";
+                               }
+                               if (isset($used_extra_spec["SMART_BRANCH"])) {
+                                       out($f, "\t\t{$else}if (spec & SPEC_RULE_SMART_BRANCH) {\n");
+                                       out($f, "\t\t\toffset = offset * 3;\n");
+                                       out($f, "\t\t\tif ((op+1)->opcode == ZEND_JMPZ) {\n");
+                                       out($f, "\t\t\t\toffset += 1;\n");
+                                       out($f, "\t\t\t} else if ((op+1)->opcode == ZEND_JMPNZ) {\n");
+                                       out($f, "\t\t\t\toffset += 2;\n");
+                                       out($f, "\t\t\t}\n");
+                                       out($f, "\t\t}\n");
+                                       $else = "else ";
+                               }
+                               if (isset($used_extra_spec["DIM_OBJ"])) {
+                                       out($f, "\t\t{$else}if (spec & SPEC_RULE_DIM_OBJ) {\n");
+                                       out($f, "\t\t\toffset = offset * 3;\n");
+                                       out($f, "\t\t\tif (op->extended_value == ZEND_ASSIGN_DIM) {\n");
+                                       out($f, "\t\t\t\toffset += 1;\n");
+                                       out($f, "\t\t\t} else if (op->extended_value == ZEND_ASSIGN_OBJ) {\n");
+                                       out($f, "\t\t\t\toffset += 2;\n");
+                                       out($f, "\t\t\t}\n");
+                                       out($f, "\t\t}\n");
+                                       $else = "else ";
+                               }
                                out($f, "\t}\n");
-                       }
+               }
+
                        out($f, "\treturn zend_opcode_handler_funcs[(spec & SPEC_START_MASK) + offset];\n");
                }
                out($f, "}\n\n");