Skip to content

Commit 004a056

Browse files
committed
Eliminated REFCOUNTED checks on persistent constant operands in SEND_VAL[_EX] and QM_ASSIGN.
1 parent 177c7e3 commit 004a056

File tree

5 files changed

+105
-11
lines changed

5 files changed

+105
-11
lines changed

Zend/zend_vm_def.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8651,7 +8651,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_
86518651
ZEND_VM_NEXT_OPCODE();
86528652
}
86538653

8654-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))), ZEND_QM_ASSIGN_NOREF, CONST|TMPVARCV, ANY)
8654+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, ((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))))), ZEND_QM_ASSIGN_NOREF, CONST|TMPVARCV, ANY)
86558655
{
86568656
USE_OPLINE
86578657
zend_free_op free_op1;
@@ -8756,6 +8756,34 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, op->op2.num <= MAX_ARG_FLAG_NUM
87568756
ZEND_VM_NEXT_OPCODE();
87578757
}
87588758

8759+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAL, op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)), ZEND_SEND_VAL_SIMPLE, CONST, NUM)
8760+
{
8761+
USE_OPLINE
8762+
zval *value, *arg;
8763+
zend_free_op free_op1;
8764+
8765+
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
8766+
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
8767+
ZVAL_COPY_VALUE(arg, value);
8768+
ZEND_VM_NEXT_OPCODE();
8769+
}
8770+
8771+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAL_EX, op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)), ZEND_SEND_VAL_EX_SIMPLE, CONST, NUM)
8772+
{
8773+
USE_OPLINE
8774+
zval *value, *arg;
8775+
zend_free_op free_op1;
8776+
uint32_t arg_num = opline->op2.num;
8777+
8778+
if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
8779+
ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper);
8780+
}
8781+
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
8782+
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
8783+
ZVAL_COPY_VALUE(arg, value);
8784+
ZEND_VM_NEXT_OPCODE();
8785+
}
8786+
87598787
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FE_FETCH_R, op->op2_type == IS_CV && (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY, ZEND_FE_FETCH_R_SIMPLE, VAR, CV, JMP_ADDR, SPEC(RETVAL))
87608788
{
87618789
USE_OPLINE

Zend/zend_vm_execute.h

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3905,6 +3905,34 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SP
39053905
ZEND_VM_NEXT_OPCODE();
39063906
}
39073907

3908+
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SIMPLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
3909+
{
3910+
USE_OPLINE
3911+
zval *value, *arg;
3912+
3913+
3914+
value = RT_CONSTANT(opline, opline->op1);
3915+
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
3916+
ZVAL_COPY_VALUE(arg, value);
3917+
ZEND_VM_NEXT_OPCODE();
3918+
}
3919+
3920+
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
3921+
{
3922+
USE_OPLINE
3923+
zval *value, *arg;
3924+
3925+
uint32_t arg_num = opline->op2.num;
3926+
3927+
if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
3928+
ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
3929+
}
3930+
value = RT_CONSTANT(opline, opline->op1);
3931+
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
3932+
ZVAL_COPY_VALUE(arg, value);
3933+
ZEND_VM_NEXT_OPCODE();
3934+
}
3935+
39083936
static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
39093937
{
39103938
USE_OPLINE
@@ -54618,6 +54646,8 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5461854646
(void*)&&ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_LABEL,
5461954647
(void*)&&ZEND_NULL_LABEL,
5462054648
(void*)&&ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_LABEL,
54649+
(void*)&&ZEND_SEND_VAL_SIMPLE_SPEC_CONST_LABEL,
54650+
(void*)&&ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_LABEL,
5462154651
(void*)&&ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_LABEL,
5462254652
(void*)&&ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_LABEL,
5462354653
(void*)&&ZEND_NULL_LABEL
@@ -55143,6 +55173,14 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5514355173
VM_TRACE(ZEND_QM_ASSIGN_NOREF_SPEC_CONST)
5514455174
ZEND_QM_ASSIGN_NOREF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
5514555175
HYBRID_BREAK();
55176+
HYBRID_CASE(ZEND_SEND_VAL_SIMPLE_SPEC_CONST):
55177+
VM_TRACE(ZEND_SEND_VAL_SIMPLE_SPEC_CONST)
55178+
ZEND_SEND_VAL_SIMPLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
55179+
HYBRID_BREAK();
55180+
HYBRID_CASE(ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST):
55181+
VM_TRACE(ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST)
55182+
ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
55183+
HYBRID_BREAK();
5514655184
HYBRID_CASE(ZEND_ADD_SPEC_CONST_CONST):
5514755185
VM_TRACE(ZEND_ADD_SPEC_CONST_CONST)
5514855186
ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -64143,6 +64181,8 @@ void zend_vm_init(void)
6414364181
ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER,
6414464182
ZEND_NULL_HANDLER,
6414564183
ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_HANDLER,
64184+
ZEND_SEND_VAL_SIMPLE_SPEC_CONST_HANDLER,
64185+
ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_HANDLER,
6414664186
ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER,
6414764187
ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_HANDLER,
6414864188
ZEND_NULL_HANDLER
@@ -64347,7 +64387,7 @@ void zend_vm_init(void)
6434764387
3019,
6434864388
3020 | SPEC_RULE_ISSET,
6434964389
3022 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
64350-
3938
64390+
3940
6435164391
};
6435264392
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
6435364393
zend_opcode_handler_funcs = labels;
@@ -64670,7 +64710,7 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
6467064710
case ZEND_QM_ASSIGN:
6467164711
if (op1_info == MAY_BE_DOUBLE) {
6467264712
spec = 3891 | SPEC_RULE_OP1;
64673-
} else if (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))) {
64713+
} 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))))) {
6467464714
spec = 3896 | SPEC_RULE_OP1;
6467564715
}
6467664716
break;
@@ -64715,14 +64755,19 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
6471564755
spec = 3047;
6471664756
}
6471764757
break;
64758+
case ZEND_SEND_VAL:
64759+
if (op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
64760+
spec = 3936;
64761+
}
64762+
break;
6471864763
case ZEND_SEND_VAR_EX:
6471964764
if (op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
6472064765
spec = 3931 | SPEC_RULE_OP1;
6472164766
}
6472264767
break;
6472364768
case ZEND_FE_FETCH_R:
6472464769
if (op->op2_type == IS_CV && (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) {
64725-
spec = 3936 | SPEC_RULE_RETVAL;
64770+
spec = 3938 | SPEC_RULE_RETVAL;
6472664771
}
6472764772
break;
6472864773
case ZEND_FETCH_DIM_R:
@@ -64733,6 +64778,11 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t
6473364778
spec = 3901 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
6473464779
}
6473564780
break;
64781+
case ZEND_SEND_VAL_EX:
64782+
if (op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1))) {
64783+
spec = 3937;
64784+
}
64785+
break;
6473664786
case ZEND_SEND_VAR:
6473764787
if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
6473864788
spec = 3926 | SPEC_RULE_OP1;

Zend/zend_vm_handlers.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,8 @@
20562056
_(3930, ZEND_SEND_VAR_SIMPLE_SPEC_CV) \
20572057
_(3933, ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR) \
20582058
_(3935, ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV) \
2059-
_(3936, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \
2060-
_(3937, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \
2061-
_(3937+1, ZEND_NULL)
2059+
_(3936, ZEND_SEND_VAL_SIMPLE_SPEC_CONST) \
2060+
_(3937, ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST) \
2061+
_(3938, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED) \
2062+
_(3939, ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED) \
2063+
_(3939+1, ZEND_NULL)

ext/opcache/Optimizer/zend_optimizer.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,21 +1306,24 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
13061306
opline = op_array->opcodes;
13071307
end = opline + op_array->last;
13081308
while (opline < end) {
1309-
zend_vm_set_opcode_handler_ex(opline,
1310-
opline->op1_type == IS_UNUSED ? 0 : (OP1_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)),
1311-
opline->op2_type == IS_UNUSED ? 0 : (OP2_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)),
1309+
uint32_t op1_info = opline->op1_type == IS_UNUSED ? 0 : (OP1_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY));
1310+
uint32_t op2_info = opline->op1_type == IS_UNUSED ? 0 : (OP2_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY));
1311+
uint32_t res_info =
13121312
(opline->opcode == ZEND_PRE_INC ||
13131313
opline->opcode == ZEND_PRE_DEC ||
13141314
opline->opcode == ZEND_POST_INC ||
13151315
opline->opcode == ZEND_POST_DEC) ?
13161316
((ssa->ops[opline - op_array->opcodes].op1_def >= 0) ? (OP1_DEF_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)) : MAY_BE_ANY) :
1317-
(opline->result_type == IS_UNUSED ? 0 : (RES_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY))));
1317+
(opline->result_type == IS_UNUSED ? 0 : (RES_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)));
1318+
13181319
if (opline->op1_type == IS_CONST) {
13191320
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1);
13201321
}
13211322
if (opline->op2_type == IS_CONST) {
13221323
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op2);
13231324
}
1325+
1326+
zend_vm_set_opcode_handler_ex(opline, op1_info, op2_info, res_info);
13241327
#if ZEND_USE_ABS_JMP_ADDR && !ZEND_USE_ABS_CONST_ADDR
13251328
if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
13261329
/* fix jumps to point to new array */

ext/opcache/zend_persist.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,12 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
432432
#if ZEND_USE_ABS_CONST_ADDR
433433
if (opline->op1_type == IS_CONST) {
434434
opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
435+
if (opline->opcode == ZEND_SEND_VAL
436+
|| opline->opcode == ZEND_SEND_VAL_EX
437+
|| opline->opcode == ZEND_QM_ASSIGN) {
438+
/* Update handlers to eliminate REFCOUNTED check */
439+
zend_vm_set_opcode_handler_ex(opline, 0, 0, 0);
440+
}
435441
}
436442
if (opline->op2_type == IS_CONST) {
437443
opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
@@ -443,6 +449,11 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
443449
((zval*)((char*)(op_array->opcodes + (opline - new_opcodes)) +
444450
(int32_t)opline->op1.constant) - orig_literals)) -
445451
(char*)opline;
452+
if (opline->opcode == ZEND_SEND_VAL
453+
|| opline->opcode == ZEND_SEND_VAL_EX
454+
|| opline->opcode == ZEND_QM_ASSIGN) {
455+
zend_vm_set_opcode_handler_ex(opline, 0, 0, 0);
456+
}
446457
}
447458
if (opline->op2_type == IS_CONST) {
448459
opline->op2.constant =

0 commit comments

Comments
 (0)