Skip to content

Commit 05a6fc3

Browse files
committed
Use a helper for frameless observer dispatching
1 parent ddd1a8f commit 05a6fc3

File tree

8 files changed

+166
-225
lines changed

8 files changed

+166
-225
lines changed

Zend/Optimizer/zend_optimizer.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,9 +1154,6 @@ static void zend_revert_pass_two(zend_op_array *op_array)
11541154
}
11551155
/* reset smart branch flags IS_SMART_BRANCH_JMP[N]Z */
11561156
opline->result_type &= (IS_TMP_VAR|IS_VAR|IS_CV|IS_CONST);
1157-
if (opline->opcode == ZEND_FRAMELESS_ICALL_3) {
1158-
(opline+1)->result_type = IS_UNUSED;
1159-
}
11601157
opline++;
11611158
}
11621159
#if !ZEND_USE_ABS_CONST_ADDR
@@ -1276,10 +1273,6 @@ static void zend_redo_pass_two(zend_op_array *op_array)
12761273
}
12771274
}
12781275
break;
1279-
case ZEND_FRAMELESS_ICALL_3:
1280-
(opline+1)->result.var = opline->result.var;
1281-
(opline+1)->result_type = opline->result_type;
1282-
break;
12831276
}
12841277
ZEND_VM_SET_OPCODE_HANDLER(opline);
12851278
opline++;
@@ -1402,10 +1395,6 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
14021395
}
14031396
}
14041397
break;
1405-
case ZEND_FRAMELESS_ICALL_3:
1406-
(opline+1)->result.var = opline->result.var;
1407-
(opline+1)->result_type = opline->result_type;
1408-
break;
14091398
}
14101399
#ifdef ZEND_VERIFY_TYPE_INFERENCE
14111400
if (ssa_op->op1_use >= 0) {

Zend/zend_opcode.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -940,8 +940,16 @@ static void zend_calc_live_ranges(
940940
if (EXPECTED(last_use[var_num] != (uint32_t) -1)) {
941941
/* Skip trivial live-range */
942942
if (opnum + 1 != last_use[var_num]) {
943-
/* OP_DATA is really part of the previous opcode. E.g. result for ZEND_FRAMELESS_ICALL_3. */
944-
uint32_t num = opnum - (opline->opcode == ZEND_OP_DATA);
943+
uint32_t num;
944+
945+
#if 1
946+
/* OP_DATA uses only op1 operand */
947+
ZEND_ASSERT(opline->opcode != ZEND_OP_DATA);
948+
num = opnum;
949+
#else
950+
/* OP_DATA is really part of the previous opcode. */
951+
num = opnum - (opline->opcode == ZEND_OP_DATA);
952+
#endif
945953
emit_live_range(op_array, var_num, num, last_use[var_num], needs_live_range);
946954
}
947955
last_use[var_num] = (uint32_t) -1;
@@ -1122,11 +1130,6 @@ ZEND_API void pass_two(zend_op_array *op_array)
11221130
case ZEND_JMP_FRAMELESS:
11231131
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
11241132
break;
1125-
case ZEND_FRAMELESS_ICALL_3:
1126-
// Copy result to OP_DATA to ensure dispatch in observer fallback can be aligned with the last opcode of the call
1127-
opline[1].result.var = opline->result.var;
1128-
opline[1].result_type = opline->result_type;
1129-
break;
11301133
case ZEND_ASSERT_CHECK:
11311134
{
11321135
/* If result of assert is unused, result of check is unused as well */

Zend/zend_vm_def.h

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9599,25 +9599,59 @@ ZEND_VM_C_LABEL(try_again):
95999599
}
96009600
}
96019601

9602+
ZEND_VM_HELPER(zend_frameless_observed_call, ANY, ANY, uint8_t num_args, zend_function *fbc, zval *op1, zval *op2, zval *op3, zval *result)
9603+
{
9604+
USE_OPLINE
9605+
9606+
zend_execute_data *call = zend_vm_stack_push_call_frame_ex(zend_vm_calc_used_stack(num_args, fbc), ZEND_CALL_NESTED_FUNCTION, fbc, num_args, NULL);
9607+
call->prev_execute_data = execute_data;
9608+
EG(current_execute_data) = call;
9609+
9610+
switch (num_args) {
9611+
case 3: ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 2), op3); if ((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op3); ZVAL_UNDEF(op3); } ZEND_FALLTHROUGH;
9612+
case 2: ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 1), op2); if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op2); ZVAL_UNDEF(op2); } ZEND_FALLTHROUGH;
9613+
case 1: ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 0), op1); if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { zval_ptr_dtor_nogc(op1); ZVAL_UNDEF(op1); }
9614+
}
9615+
9616+
zend_observer_fcall_begin_prechecked(call, ZEND_OBSERVER_DATA(fbc));
9617+
fbc->internal_function.handler(call, result);
9618+
zend_observer_fcall_end(call, result);
9619+
9620+
EG(current_execute_data) = execute_data;
9621+
zend_vm_stack_free_args(call);
9622+
9623+
uint32_t call_info = ZEND_CALL_INFO(call);
9624+
if (UNEXPECTED(call_info & ZEND_CALL_ALLOCATED)) {
9625+
zend_vm_stack_free_call_frame_ex(call_info, call);
9626+
} else {
9627+
EG(vm_stack_top) = (zval*)call;
9628+
}
9629+
9630+
if (UNEXPECTED(EG(exception) != NULL)) {
9631+
zend_rethrow_exception(execute_data);
9632+
HANDLE_EXCEPTION();
9633+
}
9634+
9635+
ZEND_VM_SET_OPCODE(opline + 1 + (num_args == 3));
9636+
ZEND_VM_CONTINUE();
9637+
}
9638+
96029639
ZEND_VM_HANDLER(204, ZEND_FRAMELESS_ICALL_0, UNUSED, UNUSED, SPEC(OBSERVER))
96039640
{
96049641
USE_OPLINE
96059642
SAVE_OPLINE();
96069643

9644+
zval *result = EX_VAR(opline->result.var);
9645+
ZVAL_NULL(result);
96079646
#if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
96089647
if (ZEND_OBSERVER_ENABLED) {
96099648
zend_function *fbc = ZEND_FLF_FUNC(opline);
96109649
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9611-
zend_execute_data *call = _zend_vm_stack_push_call_frame_ex(zend_vm_calc_used_stack(0, fbc), ZEND_CALL_NESTED_FUNCTION, fbc, 0, NULL);
9612-
call->prev_execute_data = EX(call);
9613-
EX(call) = call;
9614-
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_DO_ICALL);
9650+
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call, args, 0, fbc, fbc, op1, NULL, op2, NULL, op3, NULL, result, result);
96159651
}
96169652
}
96179653
#endif
96189654
zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline);
9619-
zval *result = EX_VAR(opline->result.var);
9620-
ZVAL_NULL(result);
96219655
function(EX_VAR(opline->result.var));
96229656
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
96239657
}
@@ -9638,12 +9672,7 @@ ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED, SPEC(OBSERVER))
96389672
if (ZEND_OBSERVER_ENABLED) {
96399673
zend_function *fbc = ZEND_FLF_FUNC(opline);
96409674
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9641-
zend_execute_data *call = _zend_vm_stack_push_call_frame_ex(zend_vm_calc_used_stack(1, fbc), ZEND_CALL_NESTED_FUNCTION, fbc, 1, NULL);
9642-
call->prev_execute_data = EX(call);
9643-
ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 0), arg1);
9644-
FREE_OP1();
9645-
EX(call) = call;
9646-
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_DO_ICALL);
9675+
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call, args, 1, fbc, fbc, op1, arg1, op2, NULL, op3, NULL, result, result);
96479676
}
96489677
}
96499678
#endif
@@ -9670,14 +9699,7 @@ ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
96709699
if (ZEND_OBSERVER_ENABLED) {
96719700
zend_function *fbc = ZEND_FLF_FUNC(opline);
96729701
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9673-
zend_execute_data *call = _zend_vm_stack_push_call_frame_ex(zend_vm_calc_used_stack(2, fbc), ZEND_CALL_NESTED_FUNCTION, fbc, 2, NULL);
9674-
call->prev_execute_data = EX(call);
9675-
ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 0), arg1);
9676-
ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 1), arg2);
9677-
FREE_OP1();
9678-
FREE_OP2();
9679-
EX(call) = call;
9680-
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_DO_ICALL);
9702+
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call, args, 2, fbc, fbc, op1, arg1, op2, arg2, op3, NULL, result, result);
96819703
}
96829704
}
96839705
#endif
@@ -9711,17 +9733,7 @@ ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
97119733
if (ZEND_OBSERVER_ENABLED) {
97129734
zend_function *fbc = ZEND_FLF_FUNC(opline);
97139735
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9714-
zend_execute_data *call = _zend_vm_stack_push_call_frame_ex(zend_vm_calc_used_stack(3, fbc), ZEND_CALL_NESTED_FUNCTION, fbc, 3, NULL);
9715-
call->prev_execute_data = EX(call);
9716-
ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 0), arg1);
9717-
ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 1), arg2);
9718-
ZVAL_COPY(ZEND_CALL_VAR_NUM(call, 2), arg3);
9719-
FREE_OP1();
9720-
FREE_OP2();
9721-
FREE_OP_DATA();
9722-
EX(call) = call;
9723-
ZEND_VM_INC_OPCODE(); // Jump over OP_DATA
9724-
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_DO_ICALL);
9736+
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call, args, 3, fbc, fbc, op1, arg1, op2, arg2, op3, arg3, result, result);
97259737
}
97269738
}
97279739
#endif

0 commit comments

Comments
 (0)