Skip to content

Commit 0856714

Browse files
committed
Always pass return_value_ptr to internal functions
Previous some places passed return_value_ptr only if the function returned by reference. Now return_value_ptr is always set, even for functions returning by-value. This allows you to return zvals without copying their contents. For this purpose two new macros RETVAL_ZVAL_FAST and RETURN_ZVAL_FAST are added: RETVAL_ZVAL_FAST(zv); /* Analog to RETVAL_ZVAL(zv, 1, 0) */ RETURN_ZVAL_FAST(zv); /* Analog to RETURN_ZVAL(zv, 1, 0) */ These macros behave similarly to the non-FAST versions with copy=1 and dtor=0, with the difference that the FAST versions will try return the zval without copying by utilizing return_value_ptr.
1 parent d7ffca5 commit 0856714

File tree

6 files changed

+40
-11
lines changed

6 files changed

+40
-11
lines changed

UPGRADING.INTERNALS

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ UPGRADE NOTES - PHP X.Y
44

55
1. Internal API changes
66
a. Addition of do_operation and compare object handlers
7+
b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros
78

89
2. Build system changes
910
a. Unix build system changes
@@ -43,6 +44,20 @@ UPGRADE NOTES - PHP X.Y
4344

4445
Further docs in the RFC: https://wiki.php.net/rfc/operator_overloading_gmp
4546

47+
b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros
48+
49+
The return_value_ptr argument to internal functions is now always set.
50+
Previously it was only available for functions returning by-reference.
51+
return_value_ptr can now be used to return zvals without copying them.
52+
For this purpose two new macros are provided:
53+
54+
RETVAL_ZVAL_FAST(zv); /* analog to RETVAL_ZVAL(zv, 1, 0) */
55+
RETURN_ZVAL_FAST(zv); /* analog to RETURN_ZVAL(zv, 1, 0) */
56+
57+
The macros behave similarly to the non-FAST variants with copy=1 and
58+
dtor=0, but will try to return the zval without making a copy by utilizing
59+
return_value_ptr.
60+
4661
========================
4762
2. Build system changes
4863
========================

Zend/zend_API.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,18 @@ END_EXTERN_C()
636636
#define RETURN_FALSE { RETVAL_FALSE; return; }
637637
#define RETURN_TRUE { RETVAL_TRUE; return; }
638638

639+
#define RETVAL_ZVAL_FAST(z) do { \
640+
zval *_z = (z); \
641+
if (Z_ISREF_P(_z)) { \
642+
RETVAL_ZVAL(_z, 1, 0); \
643+
} else { \
644+
zval_ptr_dtor(&return_value); \
645+
Z_ADDREF_P(_z); \
646+
*return_value_ptr = _z; \
647+
} \
648+
} while (0)
649+
#define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); return; }
650+
639651
#define SET_VAR_STRING(n, v) { \
640652
{ \
641653
zval *var; \

Zend/zend_execute.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,15 +1487,17 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
14871487

14881488
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC)
14891489
{
1490-
if(fci != NULL) {
1491-
((zend_internal_function *) execute_data_ptr->function_state.function)->handler(fci->param_count,
1492-
*fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
1493-
1490+
if (fci != NULL) {
1491+
execute_data_ptr->function_state.function->internal_function.handler(
1492+
fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr,
1493+
fci->object_ptr, 1 TSRMLS_CC
1494+
);
14941495
} else {
14951496
zval **return_value_ptr = &EX_TMP_VAR(execute_data_ptr, execute_data_ptr->opline->result.var)->var.ptr;
1496-
((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr,
1497-
(execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL,
1498-
execute_data_ptr->object, return_value_used TSRMLS_CC);
1497+
execute_data_ptr->function_state.function->internal_function.handler(
1498+
execute_data_ptr->opline->extended_value, *return_value_ptr, return_value_ptr,
1499+
execute_data_ptr->object, return_value_used TSRMLS_CC
1500+
);
14991501
}
15001502
}
15011503

Zend/zend_execute_API.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,9 +952,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
952952
if (EX(function_state).function->common.scope) {
953953
EG(scope) = EX(function_state).function->common.scope;
954954
}
955-
if(EXPECTED(zend_execute_internal == NULL)) {
955+
if (EXPECTED(zend_execute_internal == NULL)) {
956956
/* saves one function call if zend_execute_internal is not used */
957-
((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
957+
EX(function_state).function->internal_function.handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
958958
} else {
959959
zend_execute_internal(&execute_data, fci, 1 TSRMLS_CC);
960960
}

Zend/zend_vm_def.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1990,7 +1990,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
19901990

19911991
if (!zend_execute_internal) {
19921992
/* saves one function call if zend_execute_internal is not used */
1993-
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
1993+
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, &ret->var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
19941994
} else {
19951995
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
19961996
}

Zend/zend_vm_execute.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
551551

552552
if (!zend_execute_internal) {
553553
/* saves one function call if zend_execute_internal is not used */
554-
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
554+
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, &ret->var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
555555
} else {
556556
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
557557
}

0 commit comments

Comments
 (0)