mirror of
https://github.com/php/php-src.git
synced 2024-09-21 18:07:23 +00:00
Reduce overhead of extra-specialization for opcode handler selection.
This commit is contained in:
parent
d7f2dc4ec6
commit
1735e29b7f
@ -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_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_handler_funcs[(spec & SPEC_START_MASK) + offset];
|
||||
|
@ -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");
|
||||
|
||||
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");
|
||||
}
|
||||
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");
|
||||
|
Loading…
Reference in New Issue
Block a user