Skip to content

Commit 37a7046

Browse files
committed
Merge branch 'identical-handler' into HEAD
2 parents 1abea33 + dea62d4 commit 37a7046

File tree

3 files changed

+381
-250
lines changed

3 files changed

+381
-250
lines changed

Zend/zend_vm_def.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8799,6 +8799,35 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info
87998799
ZEND_VM_SMART_BRANCH(result, 0);
88008800
}
88018801

8802+
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF)), ZEND_IS_IDENTICAL_NOTHROW, CV, CONST|CV, SPEC(COMMUTATIVE))
8803+
{
8804+
/* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */
8805+
/* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */
8806+
/* (Infinite recursion when comparing arrays is an uncatchable fatal error) */
8807+
USE_OPLINE
8808+
zval *op1, *op2;
8809+
zend_bool result;
8810+
8811+
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
8812+
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
8813+
result = fast_is_identical_function(op1, op2);
8814+
/* Free is a no-op for const/cv */
8815+
ZEND_VM_SMART_BRANCH(result, 0);
8816+
}
8817+
8818+
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_IDENTICAL, op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF)), ZEND_IS_NOT_IDENTICAL_NOTHROW, CV, CONST|CV, SPEC(COMMUTATIVE))
8819+
{
8820+
USE_OPLINE
8821+
zval *op1, *op2;
8822+
zend_bool result;
8823+
8824+
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
8825+
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
8826+
result = fast_is_identical_function(op1, op2);
8827+
/* Free is a no-op for const/cv */
8828+
ZEND_VM_SMART_BRANCH(!result, 0);
8829+
}
8830+
88028831
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
88038832
{
88048833
USE_OPLINE

Zend/zend_vm_execute.h

Lines changed: 120 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40258,6 +40258,35 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER
4025840258
ZEND_VM_SMART_BRANCH(result, 1);
4025940259
}
4026040260

40261+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
40262+
{
40263+
/* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */
40264+
/* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */
40265+
/* (Infinite recursion when comparing arrays is an uncatchable fatal error) */
40266+
USE_OPLINE
40267+
zval *op1, *op2;
40268+
zend_bool result;
40269+
40270+
op1 = EX_VAR(opline->op1.var);
40271+
op2 = RT_CONSTANT(opline, opline->op2);
40272+
result = fast_is_identical_function(op1, op2);
40273+
/* Free is a no-op for const/cv */
40274+
ZEND_VM_SMART_BRANCH(result, 0);
40275+
}
40276+
40277+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
40278+
{
40279+
USE_OPLINE
40280+
zval *op1, *op2;
40281+
zend_bool result;
40282+
40283+
op1 = EX_VAR(opline->op1.var);
40284+
op2 = RT_CONSTANT(opline, opline->op2);
40285+
result = fast_is_identical_function(op1, op2);
40286+
/* Free is a no-op for const/cv */
40287+
ZEND_VM_SMART_BRANCH(!result, 0);
40288+
}
40289+
4026140290
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
4026240291
{
4026340292
USE_OPLINE
@@ -48385,6 +48414,35 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_
4838548414
ZEND_VM_RETURN();
4838648415
}
4838748416

48417+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
48418+
{
48419+
/* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */
48420+
/* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */
48421+
/* (Infinite recursion when comparing arrays is an uncatchable fatal error) */
48422+
USE_OPLINE
48423+
zval *op1, *op2;
48424+
zend_bool result;
48425+
48426+
op1 = EX_VAR(opline->op1.var);
48427+
op2 = EX_VAR(opline->op2.var);
48428+
result = fast_is_identical_function(op1, op2);
48429+
/* Free is a no-op for const/cv */
48430+
ZEND_VM_SMART_BRANCH(result, 0);
48431+
}
48432+
48433+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
48434+
{
48435+
USE_OPLINE
48436+
zval *op1, *op2;
48437+
zend_bool result;
48438+
48439+
op1 = EX_VAR(opline->op1.var);
48440+
op2 = EX_VAR(opline->op2.var);
48441+
result = fast_is_identical_function(op1, op2);
48442+
/* Free is a no-op for const/cv */
48443+
ZEND_VM_SMART_BRANCH(!result, 0);
48444+
}
48445+
4838848446
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
4838948447
{
4839048448
USE_OPLINE
@@ -51265,6 +51323,16 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5126551323
(void*)&&ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_LABEL,
5126651324
(void*)&&ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_LABEL,
5126751325
(void*)&&ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_LABEL,
51326+
(void*)&&ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_LABEL,
51327+
(void*)&&ZEND_NULL_LABEL,
51328+
(void*)&&ZEND_NULL_LABEL,
51329+
(void*)&&ZEND_NULL_LABEL,
51330+
(void*)&&ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_LABEL,
51331+
(void*)&&ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_LABEL,
51332+
(void*)&&ZEND_NULL_LABEL,
51333+
(void*)&&ZEND_NULL_LABEL,
51334+
(void*)&&ZEND_NULL_LABEL,
51335+
(void*)&&ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_LABEL,
5126851336
(void*)&&ZEND_NULL_LABEL,
5126951337
(void*)&&ZEND_NULL_LABEL,
5127051338
(void*)&&ZEND_NULL_LABEL,
@@ -55291,6 +55359,14 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5529155359
VM_TRACE(ZEND_IN_ARRAY_SPEC_CV_CONST)
5529255360
ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
5529355361
HYBRID_BREAK();
55362+
HYBRID_CASE(ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST):
55363+
VM_TRACE(ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST)
55364+
ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
55365+
HYBRID_BREAK();
55366+
HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST):
55367+
VM_TRACE(ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST)
55368+
ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
55369+
HYBRID_BREAK();
5529455370
HYBRID_CASE(ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST):
5529555371
VM_TRACE(ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST)
5529655372
ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -55863,6 +55939,14 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5586355939
VM_TRACE(ZEND_YIELD_SPEC_CV_CV)
5586455940
ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
5586555941
HYBRID_BREAK();
55942+
HYBRID_CASE(ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV):
55943+
VM_TRACE(ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV)
55944+
ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
55945+
HYBRID_BREAK();
55946+
HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV):
55947+
VM_TRACE(ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV)
55948+
ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
55949+
HYBRID_BREAK();
5586655950
HYBRID_CASE(HYBRID_HALT):
5586755951
#ifdef ZEND_VM_FP_GLOBAL_REG
5586855952
execute_data = orig_execute_data;
@@ -58775,6 +58859,16 @@ void zend_vm_init(void)
5877558859
ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER,
5877658860
ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER,
5877758861
ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER,
58862+
ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER,
58863+
ZEND_NULL_HANDLER,
58864+
ZEND_NULL_HANDLER,
58865+
ZEND_NULL_HANDLER,
58866+
ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER,
58867+
ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER,
58868+
ZEND_NULL_HANDLER,
58869+
ZEND_NULL_HANDLER,
58870+
ZEND_NULL_HANDLER,
58871+
ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER,
5877858872
ZEND_NULL_HANDLER,
5877958873
ZEND_NULL_HANDLER,
5878058874
ZEND_NULL_HANDLER,
@@ -59339,7 +59433,7 @@ void zend_vm_init(void)
5933959433
2280,
5934059434
2281 | SPEC_RULE_OP1,
5934159435
2286 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
59342-
3204
59436+
3214
5934359437
};
5934459438
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
5934559439
zend_opcode_handler_funcs = labels;
@@ -59574,6 +59668,8 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
5957459668
break;
5957559669
}
5957659670
spec = 2613 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
59671+
} else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) {
59672+
spec = 2838 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
5957759673
}
5957859674
break;
5957959675
case ZEND_IS_NOT_IDENTICAL:
@@ -59590,6 +59686,8 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
5959059686
break;
5959159687
}
5959259688
spec = 2763 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH | SPEC_RULE_COMMUTATIVE;
59689+
} else if (op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF))) {
59690+
spec = 2843 | SPEC_RULE_OP2 | SPEC_RULE_COMMUTATIVE;
5959359691
}
5959459692
break;
5959559693
case ZEND_IS_EQUAL:
@@ -59629,62 +59727,62 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
5962959727
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
5963059728
break;
5963159729
}
59632-
spec = 2838 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
59730+
spec = 2848 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
5963359731
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
5963459732
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
5963559733
break;
5963659734
}
59637-
spec = 2913 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
59735+
spec = 2923 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
5963859736
}
5963959737
break;
5964059738
case ZEND_IS_SMALLER_OR_EQUAL:
5964159739
if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
5964259740
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
5964359741
break;
5964459742
}
59645-
spec = 2988 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
59743+
spec = 2998 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
5964659744
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
5964759745
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
5964859746
break;
5964959747
}
59650-
spec = 3063 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
59748+
spec = 3073 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
5965159749
}
5965259750
break;
5965359751
case ZEND_QM_ASSIGN:
5965459752
if (op1_info == MAY_BE_LONG) {
59655-
spec = 3150 | SPEC_RULE_OP1;
59753+
spec = 3160 | SPEC_RULE_OP1;
5965659754
} else if (op1_info == MAY_BE_DOUBLE) {
59657-
spec = 3155 | SPEC_RULE_OP1;
59755+
spec = 3165 | SPEC_RULE_OP1;
5965859756
} else if ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) {
59659-
spec = 3160 | SPEC_RULE_OP1;
59757+
spec = 3170 | SPEC_RULE_OP1;
5966059758
}
5966159759
break;
5966259760
case ZEND_PRE_INC:
5966359761
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
59664-
spec = 3138 | SPEC_RULE_RETVAL;
59762+
spec = 3148 | SPEC_RULE_RETVAL;
5966559763
} else if (op1_info == MAY_BE_LONG) {
59666-
spec = 3140 | SPEC_RULE_RETVAL;
59764+
spec = 3150 | SPEC_RULE_RETVAL;
5966759765
}
5966859766
break;
5966959767
case ZEND_PRE_DEC:
5967059768
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
59671-
spec = 3142 | SPEC_RULE_RETVAL;
59769+
spec = 3152 | SPEC_RULE_RETVAL;
5967259770
} else if (op1_info == MAY_BE_LONG) {
59673-
spec = 3144 | SPEC_RULE_RETVAL;
59771+
spec = 3154 | SPEC_RULE_RETVAL;
5967459772
}
5967559773
break;
5967659774
case ZEND_POST_INC:
5967759775
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
59678-
spec = 3146;
59776+
spec = 3156;
5967959777
} else if (op1_info == MAY_BE_LONG) {
59680-
spec = 3147;
59778+
spec = 3157;
5968159779
}
5968259780
break;
5968359781
case ZEND_POST_DEC:
5968459782
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
59685-
spec = 3148;
59783+
spec = 3158;
5968659784
} else if (op1_info == MAY_BE_LONG) {
59687-
spec = 3149;
59785+
spec = 3159;
5968859786
}
5968959787
break;
5969059788
case ZEND_JMP:
@@ -59699,35 +59797,35 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
5969959797
break;
5970059798
case ZEND_SEND_VAL:
5970159799
if (op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
59702-
spec = 3200;
59800+
spec = 3210;
5970359801
}
5970459802
break;
5970559803
case ZEND_SEND_VAR_EX:
5970659804
if (op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
59707-
spec = 3195 | SPEC_RULE_OP1;
59805+
spec = 3205 | SPEC_RULE_OP1;
5970859806
}
5970959807
break;
5971059808
case ZEND_FE_FETCH_R:
5971159809
if (op->op2_type == IS_CV && (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) {
59712-
spec = 3202 | SPEC_RULE_RETVAL;
59810+
spec = 3212 | SPEC_RULE_RETVAL;
5971359811
}
5971459812
break;
5971559813
case ZEND_FETCH_DIM_R:
5971659814
if (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) {
5971759815
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
5971859816
break;
5971959817
}
59720-
spec = 3165 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
59818+
spec = 3175 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
5972159819
}
5972259820
break;
5972359821
case ZEND_SEND_VAL_EX:
5972459822
if (op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
59725-
spec = 3201;
59823+
spec = 3211;
5972659824
}
5972759825
break;
5972859826
case ZEND_SEND_VAR:
5972959827
if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
59730-
spec = 3190 | SPEC_RULE_OP1;
59828+
spec = 3200 | SPEC_RULE_OP1;
5973159829
}
5973259830
break;
5973359831
case ZEND_BW_OR:

0 commit comments

Comments
 (0)