Skip to content

Commit 14bd59a

Browse files
committed
Introduce reusable handler across VM and JIT
1 parent 04f144b commit 14bd59a

File tree

6 files changed

+197
-202
lines changed

6 files changed

+197
-202
lines changed

Zend/zend_execute.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,56 @@ static zend_never_inline void zend_assign_to_object_dim(zend_object *obj, zval *
15401540
}
15411541
}
15421542

1543+
static void zend_frameless_observed_call_push(zend_execute_data *call, uint8_t arg, zval *zv, uint8_t op_type) {
1544+
ZVAL_COPY(ZEND_CALL_VAR_NUM(call, arg), zv);
1545+
if (op_type & (IS_TMP_VAR|IS_VAR)) {
1546+
zval_ptr_dtor_nogc(zv);
1547+
ZVAL_UNDEF(zv);
1548+
}
1549+
}
1550+
1551+
ZEND_API void zend_frameless_observed_call(zend_execute_data *execute_data)
1552+
{
1553+
const zend_op *opline = EX(opline);
1554+
uint8_t num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
1555+
zend_function *fbc = ZEND_FLF_FUNC(opline);
1556+
1557+
zval *result = EX_VAR(opline->result.var);
1558+
ZVAL_NULL(result);
1559+
1560+
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);
1561+
call->prev_execute_data = execute_data;
1562+
1563+
switch (num_args) {
1564+
case 3: zend_frameless_observed_call_push(call, 2, get_op_data_zval_ptr_deref_r((opline+1)->op1_type, (opline+1)->op1), (opline+1)->op1_type); ZEND_FALLTHROUGH;
1565+
case 2: zend_frameless_observed_call_push(call, 1, get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R), opline->op2_type); ZEND_FALLTHROUGH;
1566+
case 1: zend_frameless_observed_call_push(call, 0, get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R), opline->op1_type);
1567+
1568+
if (EG(exception)) {
1569+
goto free_args;
1570+
}
1571+
}
1572+
1573+
EG(current_execute_data) = call;
1574+
1575+
zend_observer_fcall_begin_prechecked(call, ZEND_OBSERVER_DATA(fbc));
1576+
fbc->internal_function.handler(call, result);
1577+
zend_observer_fcall_end(call, result);
1578+
1579+
EG(current_execute_data) = execute_data;
1580+
1581+
free_args: ;
1582+
zend_vm_stack_free_args(call);
1583+
1584+
uint32_t call_info = ZEND_CALL_INFO(call);
1585+
if (UNEXPECTED(call_info & ZEND_CALL_ALLOCATED)) {
1586+
zend_vm_stack_free_call_frame_ex(call_info, call);
1587+
} else {
1588+
EG(vm_stack_top) = (zval*)call;
1589+
}
1590+
}
1591+
1592+
15431593
static zend_always_inline int zend_binary_op(zval *ret, zval *op1, zval *op2 OPLINE_DC)
15441594
{
15451595
static const binary_op_type zend_binary_ops[] = {

Zend/zend_execute.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@ ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data,
430430
ZEND_API ZEND_ATTRIBUTE_DEPRECATED HashTable *zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer);
431431
ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield);
432432

433+
ZEND_API void zend_frameless_observed_call(zend_execute_data *execute_data);
434+
433435
zval * ZEND_FASTCALL zend_handle_named_arg(
434436
zend_execute_data **call_ptr, zend_string *arg_name,
435437
uint32_t *arg_num_ptr, void **cache_slot);

Zend/zend_vm_def.h

Lines changed: 37 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9599,40 +9599,18 @@ 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)
9602+
ZEND_VM_HELPER(zend_frameless_observed_call, ANY, ANY)
96039603
{
96049604
USE_OPLINE
96059605

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-
}
9606+
zend_frameless_observed_call(execute_data);
96299607

96309608
if (UNEXPECTED(EG(exception) != NULL)) {
96319609
zend_rethrow_exception(execute_data);
96329610
HANDLE_EXCEPTION();
96339611
}
96349612

9635-
ZEND_VM_SET_OPCODE(opline + 1 + (num_args == 3));
9613+
ZEND_VM_SET_OPCODE(opline + 1 + (opline->opcode == ZEND_FRAMELESS_ICALL_3));
96369614
ZEND_VM_CONTINUE();
96379615
}
96389616

@@ -9641,16 +9619,17 @@ ZEND_VM_HANDLER(204, ZEND_FRAMELESS_ICALL_0, UNUSED, UNUSED, SPEC(OBSERVER))
96419619
USE_OPLINE
96429620
SAVE_OPLINE();
96439621

9644-
zval *result = EX_VAR(opline->result.var);
9645-
ZVAL_NULL(result);
96469622
#if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
96479623
if (ZEND_OBSERVER_ENABLED) {
96489624
zend_function *fbc = ZEND_FLF_FUNC(opline);
96499625
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9650-
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call, args, 0, fbc, fbc, op1, NULL, op2, NULL, op3, NULL, result, result);
9626+
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call);
96519627
}
96529628
}
96539629
#endif
9630+
9631+
zval *result = EX_VAR(opline->result.var);
9632+
ZVAL_NULL(result);
96549633
zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline);
96559634
function(EX_VAR(opline->result.var));
96569635
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -9660,6 +9639,16 @@ ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED, SPEC(OBSERVER))
96609639
{
96619640
USE_OPLINE
96629641
SAVE_OPLINE();
9642+
9643+
#if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9644+
if (ZEND_OBSERVER_ENABLED) {
9645+
zend_function *fbc = ZEND_FLF_FUNC(opline);
9646+
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9647+
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call);
9648+
}
9649+
}
9650+
#endif
9651+
96639652
zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline);
96649653
zval *result = EX_VAR(opline->result.var);
96659654
ZVAL_NULL(result);
@@ -9668,14 +9657,6 @@ ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED, SPEC(OBSERVER))
96689657
FREE_OP1();
96699658
HANDLE_EXCEPTION();
96709659
}
9671-
#if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9672-
if (ZEND_OBSERVER_ENABLED) {
9673-
zend_function *fbc = ZEND_FLF_FUNC(opline);
9674-
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9675-
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call, args, 1, fbc, fbc, op1, arg1, op2, NULL, op3, NULL, result, result);
9676-
}
9677-
}
9678-
#endif
96799660
function(result, arg1);
96809661
FREE_OP1();
96819662
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -9685,6 +9666,16 @@ ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
96859666
{
96869667
USE_OPLINE
96879668
SAVE_OPLINE();
9669+
9670+
#if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9671+
if (ZEND_OBSERVER_ENABLED) {
9672+
zend_function *fbc = ZEND_FLF_FUNC(opline);
9673+
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9674+
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call);
9675+
}
9676+
}
9677+
#endif
9678+
96889679
zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline);
96899680
zval *result = EX_VAR(opline->result.var);
96909681
ZVAL_NULL(result);
@@ -9695,14 +9686,6 @@ ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
96959686
FREE_OP2();
96969687
HANDLE_EXCEPTION();
96979688
}
9698-
#if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9699-
if (ZEND_OBSERVER_ENABLED) {
9700-
zend_function *fbc = ZEND_FLF_FUNC(opline);
9701-
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9702-
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call, args, 2, fbc, fbc, op1, arg1, op2, arg2, op3, NULL, result, result);
9703-
}
9704-
}
9705-
#endif
97069689
function(result, arg1, arg2);
97079690
FREE_OP1();
97089691
/* Set OP1 to UNDEF in case FREE_OP2() throws. */
@@ -9717,6 +9700,16 @@ ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
97179700
{
97189701
USE_OPLINE
97199702
SAVE_OPLINE();
9703+
9704+
#if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9705+
if (ZEND_OBSERVER_ENABLED) {
9706+
zend_function *fbc = ZEND_FLF_FUNC(opline);
9707+
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9708+
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call);
9709+
}
9710+
}
9711+
#endif
9712+
97209713
zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline);
97219714
zval *result = EX_VAR(opline->result.var);
97229715
ZVAL_NULL(result);
@@ -9729,14 +9722,6 @@ ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
97299722
FREE_OP_DATA();
97309723
HANDLE_EXCEPTION();
97319724
}
9732-
#if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9733-
if (ZEND_OBSERVER_ENABLED) {
9734-
zend_function *fbc = ZEND_FLF_FUNC(opline);
9735-
if (UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc)) == false)) {
9736-
ZEND_VM_DISPATCH_TO_HELPER(zend_frameless_observed_call, args, 3, fbc, fbc, op1, arg1, op2, arg2, op3, arg3, result, result);
9737-
}
9738-
}
9739-
#endif
97409725
function(result, arg1, arg2, arg3);
97419726
FREE_OP1();
97429727
/* Set to UNDEF in case FREE_OP2() throws. */

0 commit comments

Comments
 (0)