Skip to content

Commit a758089

Browse files
TysonAndredstogov
authored andcommitted
Support the same handler for multiple opcodes
1 parent e8525c2 commit a758089

File tree

3 files changed

+55
-32
lines changed

3 files changed

+55
-32
lines changed

Zend/zend_vm_def.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,7 +1496,7 @@ ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY)
14961496

14971497
SAVE_OPLINE();
14981498
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1499-
ZVAL_NULL(var_ptr);
1499+
ZVAL_NULL(var_ptr);
15001500
ZVAL_UNDEFINED_OP1();
15011501
}
15021502

@@ -2234,7 +2234,7 @@ ZEND_VM_C_LABEL(fetch_obj_is_fast_copy):
22342234
}
22352235

22362236
retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var));
2237-
2237+
22382238
if (OP2_TYPE != IS_CONST) {
22392239
zend_tmp_string_release(tmp_name);
22402240
}
@@ -5528,10 +5528,10 @@ ZEND_VM_HANDLER(147, ZEND_ADD_ARRAY_UNPACK, ANY, ANY)
55285528
{
55295529
USE_OPLINE
55305530
zval *op1;
5531-
5531+
55325532
SAVE_OPLINE();
55335533
op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
5534-
5534+
55355535
ZEND_VM_C_LABEL(add_unpack_again):
55365536
if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) {
55375537
HashTable *ht = Z_ARRVAL_P(op1);
@@ -5572,11 +5572,11 @@ ZEND_VM_C_LABEL(add_unpack_again):
55725572
}
55735573
HANDLE_EXCEPTION();
55745574
}
5575-
5575+
55765576
if (iter->funcs->rewind) {
55775577
iter->funcs->rewind(iter);
55785578
}
5579-
5579+
55805580
for (; iter->funcs->valid(iter) == SUCCESS; ) {
55815581
zval *val;
55825582

@@ -5625,7 +5625,7 @@ ZEND_VM_C_LABEL(add_unpack_again):
56255625
} else {
56265626
zend_throw_error(NULL, "Only arrays and Traversables can be unpacked");
56275627
}
5628-
5628+
56295629
FREE_OP1();
56305630
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
56315631
}
@@ -8677,7 +8677,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info =
86778677
ZEND_VM_NEXT_OPCODE();
86788678
}
86798679

8680-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
8680+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL|ZEND_IS_IDENTICAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
86818681
{
86828682
USE_OPLINE
86838683
zval *op1, *op2;
@@ -8689,7 +8689,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_LONG && op2_inf
86898689
ZEND_VM_SMART_BRANCH(result, 0);
86908690
}
86918691

8692-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
8692+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL|ZEND_IS_IDENTICAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
86938693
{
86948694
USE_OPLINE
86958695
zval *op1, *op2;
@@ -8701,7 +8701,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_i
87018701
ZEND_VM_SMART_BRANCH(result, 0);
87028702
}
87038703

8704-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
8704+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
87058705
{
87068706
USE_OPLINE
87078707
zval *op1, *op2;
@@ -8713,7 +8713,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_LONG && op2
87138713
ZEND_VM_SMART_BRANCH(result, 0);
87148714
}
87158715

8716-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
8716+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
87178717
{
87188718
USE_OPLINE
87198719
zval *op1, *op2;

Zend/zend_vm_execute.h

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59193,7 +59193,6 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
5919359193
spec = 2512 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
5919459194
}
5919559195
break;
59196-
case ZEND_IS_EQUAL:
5919759196
case ZEND_IS_IDENTICAL:
5919859197
if (op->op1_type < op->op2_type) {
5919959198
zend_swap_operands(op);
@@ -59210,7 +59209,6 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
5921059209
spec = 2612 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
5921159210
}
5921259211
break;
59213-
case ZEND_IS_NOT_EQUAL:
5921459212
case ZEND_IS_NOT_IDENTICAL:
5921559213
if (op->op1_type < op->op2_type) {
5921659214
zend_swap_operands(op);
@@ -59227,6 +59225,38 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
5922759225
spec = 2762 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
5922859226
}
5922959227
break;
59228+
case ZEND_IS_EQUAL:
59229+
if (op->op1_type < op->op2_type) {
59230+
zend_swap_operands(op);
59231+
}
59232+
if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
59233+
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
59234+
break;
59235+
}
59236+
spec = 2537 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
59237+
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
59238+
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
59239+
break;
59240+
}
59241+
spec = 2612 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
59242+
}
59243+
break;
59244+
case ZEND_IS_NOT_EQUAL:
59245+
if (op->op1_type < op->op2_type) {
59246+
zend_swap_operands(op);
59247+
}
59248+
if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
59249+
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
59250+
break;
59251+
}
59252+
spec = 2687 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
59253+
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
59254+
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
59255+
break;
59256+
}
59257+
spec = 2762 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
59258+
}
59259+
break;
5923059260
case ZEND_IS_SMALLER:
5923159261
if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
5923259262
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {

Zend/zend_vm_gen.php

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,19 +2394,22 @@ function gen_vm($def, $skel) {
23942394
strpos($line,"ZEND_VM_HOT_OBJ_TYPE_SPEC_HANDLER(") === 0) {
23952395
// Parsing opcode handler's definition
23962396
if (preg_match(
2397-
"/^ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_)?TYPE_SPEC_HANDLER\(\s*([A-Z_]+)\s*,\s*((?:[^(,]|\([^()]*|(?R)*\))*),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
2397+
"/^ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_)?TYPE_SPEC_HANDLER\(\s*([A-Z_|]+)\s*,\s*((?:[^(,]|\([^()]*|(?R)*\))*),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
23982398
$line,
23992399
$m) == 0) {
24002400
die("ERROR ($def:$lineno): Invalid ZEND_VM_TYPE_HANDLER_HANDLER definition.\n");
24012401
}
24022402
$hot = !empty($m[1]) ? $m[1] : false;
2403-
$orig_op = $m[2];
2404-
if (!isset($opnames[$orig_op])) {
2405-
die("ERROR ($def:$lineno): Opcode with name '$orig_op' is not defined.\n");
2406-
}
2407-
$orig_code = $opnames[$orig_op];
2408-
$condition = $m[3];
2403+
$orig_op_list = $m[2];
24092404
$code = $extra_num++;
2405+
foreach (explode('|', $orig_op_list) as $orig_op) {
2406+
if (!isset($opnames[$orig_op])) {
2407+
die("ERROR ($def:$lineno): Opcode with name '$orig_op' is not defined.\n");
2408+
}
2409+
$orig_code = $opnames[$orig_op];
2410+
$condition = $m[3];
2411+
$opcodes[$orig_code]['type_spec'][$code] = $condition;
2412+
}
24102413
$op = $m[4];
24112414
$op1 = parse_operand_spec($def, $lineno, $m[5], $flags1);
24122415
$op2 = parse_operand_spec($def, $lineno, $m[6], $flags2);
@@ -2418,7 +2421,6 @@ function gen_vm($def, $skel) {
24182421
if (isset($opcodes[$code])) {
24192422
die("ERROR ($def:$lineno): Opcode with name '$code' is already defined.\n");
24202423
}
2421-
$opcodes[$orig_code]['type_spec'][$code] = $condition;
24222424
$used_extra_spec["TYPE"] = 1;
24232425
$opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags,"hot"=>$hot,"is_type_spec"=>true);
24242426
if (isset($m[10])) {
@@ -2818,13 +2820,6 @@ function gen_vm($def, $skel) {
28182820
if (isset($dsc['type_spec'])) {
28192821
$orig_op = $dsc['op'];
28202822
out($f, "\t\tcase $orig_op:\n");
2821-
// XXX: Copy the specializations for LONG == LONG and DOUBLE != DOUBLE to work for ===/!== as well.
2822-
// (Those are currently the only specializations)
2823-
if ($orig_op === 'ZEND_IS_EQUAL') {
2824-
out($f, "\t\tcase ZEND_IS_IDENTICAL:\n");
2825-
} elseif ($orig_op === 'ZEND_IS_NOT_EQUAL') {
2826-
out($f, "\t\tcase ZEND_IS_NOT_IDENTICAL:\n");
2827-
}
28282823
if (isset($dsc["spec"]["COMMUTATIVE"])) {
28292824
out($f, "\t\t\tif (op->op1_type < op->op2_type) {\n");
28302825
out($f, "\t\t\t\tzend_swap_operands(op);\n");
@@ -2864,10 +2859,8 @@ function gen_vm($def, $skel) {
28642859
!isset($dsc['type_spec']) &&
28652860
isset($dsc["spec"]["COMMUTATIVE"])) {
28662861
$orig_op = $dsc['op'];
2867-
if (!in_array($orig_op, ['ZEND_IS_IDENTICAL', 'ZEND_IS_NOT_IDENTICAL'])) {
2868-
out($f, "\t\tcase $orig_op:\n");
2869-
$has_commutative = true;
2870-
}
2862+
out($f, "\t\tcase $orig_op:\n");
2863+
$has_commutative = true;
28712864
}
28722865
}
28732866
if ($has_commutative) {

0 commit comments

Comments
 (0)