Commit:    08567145763f25aae3882f682d41d1b50cd9e666
Author:    Nikita Popov <ni...@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);
                        }


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to