com php-src: Always pass return_value_ptr to internal functions: UPGRADING.INTERNALS Zend/zend_API.h Zend/zend_execute.c Zend/zend_execute_API.c Ze
nd/zend_vm_def.h Zend/zend_vm_execute.h
| From: | Nikita Popov | Date: | Sat, 31 Aug 2013 11:16:41 +0000 |
| Subject: | com php-src: Always pass return_value_ptr to internal functions: UPGRADING.INTERNALS Zend/zend_API.h Zend/zend_execute.c Zend/zend_execute_API.c Ze nd/zend_vm_def.h Zend/zend_vm_execute.h |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-73144@lists.php.net to get a copy of this message | ||
Commit: 08567145763f25aae3882f682d41d1b50cd9e666
Author: Nikita Popov <nikic@php.net> Mon, 26 Aug 2013 19:06:36 +0200
Parents: d7ffca590b4ee188a5dcdbafb036e6541f3c79be
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=08567145763f25aae3882f682d41d1b50cd9e666
Log:
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.
Changed paths:
M UPGRADING.INTERNALS
M Zend/zend_API.h
M Zend/zend_execute.c
M Zend/zend_execute_API.c
M Zend/zend_vm_def.h
M Zend/zend_vm_execute.h
Diff:
diff --git a/UPGRADING..INTERNALS b/UPGRADING.INTERNALS
index 566f310..7cb5539 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -4,6 +4,7 @@ UPGRADE NOTES - PHP X.Y
1. Internal API changes
a. Addition of do_operation and compare object handlers
+ b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros
2. Build system changes
a. Unix build system changes
@@ -43,6 +44,20 @@ UPGRADE NOTES - PHP X.Y
Further docs in the RFC: https://wiki.php.net/rfc/operator_overloading_gmp
+ b. return_value_ptr now always available, RETVAL_ZVAL_FAST macros
+
+ The return_value_ptr argument to internal functions is now always set..
+ Previously it was only available for functions returning by-reference.
+ return_value_ptr can now be used to return zvals without copying them.
+ For this purpose two new macros are provided:
+
+ RETVAL_ZVAL_FAST(zv); /* analog to RETVAL_ZVAL(zv, 1, 0) */
+ RETURN_ZVAL_FAST(zv); /* analog to RETURN_ZVAL(zv, 1, 0) */
+
+ The macros behave similarly to the non-FAST variants with copy=1 and
+ dtor=0, but will try to return the zval without making a copy by utilizing
+ return_value_ptr.
+
========================
2. Build system changes
========================
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 1a7c66e..16e766d 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -636,6 +636,18 @@ END_EXTERN_C()
#define RETURN_FALSE { RETVAL_FALSE; return; }
#define RETURN_TRUE { RETVAL_TRUE; return; }
+#define RETVAL_ZVAL_FAST(z) do { \
+ zval *_z = (z); \
+ if (Z_ISREF_P(_z)) { \
+ RETVAL_ZVAL(_z, 1, 0); \
+ } else { \
+ zval_ptr_dtor(&return_value); \
+ Z_ADDREF_P(_z); \
+ *return_value_ptr = _z; \
+ } \
+} while (0)
+#define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); return; }
+
#define SET_VAR_STRING(n, v) { \
{ \
zval *var; \
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 3c3dd8e..048c1fc 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -1487,15 +1487,17 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int
return_value_used TSRMLS_DC)
{
- if(fci != NULL) {
- ((zend_internal_function *)
execute_data_ptr->function_state.function)->handler(fci->param_count,
- *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
-
+ if (fci != NULL) {
+ execute_data_ptr->function_state.function->internal_function.handler(
+ fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr,
+ fci->object_ptr, 1 TSRMLS_CC
+ );
} else {
zval **return_value_ptr = &EX_TMP_VAR(execute_data_ptr,
execute_data_ptr->opline->result.var)->var.ptr;
- ((zend_internal_function *)
execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value,
*return_value_ptr,
- (execute_data_ptr->function_state.function->common.fn_flags &
ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL,
- execute_data_ptr->object, return_value_used TSRMLS_CC);
+ execute_data_ptr->function_state.function->internal_function.handler(
+ execute_data_ptr->opline->extended_value, *return_value_ptr, return_value_ptr,
+ execute_data_ptr->object, return_value_used TSRMLS_CC
+ );
}
}
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 83c2217..0b29086 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -952,9 +952,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
if (EX(function_state).function->common.scope) {
EG(scope) = EX(function_state).function->common.scope;
}
- if(EXPECTED(zend_execute_internal == NULL)) {
+ if (EXPECTED(zend_execute_internal == NULL)) {
/* saves one function call if zend_execute_internal is not used */
- ((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);
+ EX(function_state).function->internal_function.handler(fci->param_count,
*fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
} else {
zend_execute_internal(&execute_data, fci, 1 TSRMLS_CC);
}
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 7e4f7a8..4ab2129 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1990,7 +1990,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
- 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);
+ fbc->internal_function.handler(opline->extended_value, ret->var.ptr,
&ret->var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute..h
index 5f2c805..0ea5fc4 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -551,7 +551,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
- 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);
+ fbc->internal_function.handler(opline->extended_value, ret->var.ptr,
&ret->var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
}