ID: 33286
Updated by: [EMAIL PROTECTED]
Reported By: pumuckel at metropolis dot de
-Status: Open
+Status: Assigned
Bug Type: Arrays related
Operating System: Linux
PHP Version: 5CVS-2005-06-13
-Assigned To:
+Assigned To: andrei
Previous Comments:
------------------------------------------------------------------------
[2005-06-13 09:37:05] pumuckel at metropolis dot de
Feedback (a bigger patch) was sent to Andrei Zmievski. I required I can
post it here uuencoded.
------------------------------------------------------------------------
[2005-06-10 18:22:12] [EMAIL PROTECTED]
Can you provide a patch against HEAD? It seems that there are more uses
of BG() global that your patch doesn't cover.
------------------------------------------------------------------------
[2005-06-10 09:35:18] pumuckel at metropolis dot de
Here is the patch for using a local cache var instead of a global.
In nested loops using the global cache var only the innermost
array_walk function can effectively make use of the cache. All
outermost loops can't because cache always got cleared from innermost
and therefor functions have to be relocated.
With local cache var this is not needed and we will get better
performance with big nested arrays.
Patch:
diff -urw php-5.0.4/ext/standard/array.c
php-5.0.4.patched/ext/standard/array.c
--- php-5.0.4/ext/standard/array.c 2005-03-12 11:12:49.000000000
+0100
+++ php-5.0.4.patched/ext/standard/array.c 2005-06-10
09:25:15.000000000 +0200
@@ -1008,6 +1008,7 @@
uint string_key_len;
ulong num_key;
HashPosition pos;
+ zend_fcall_info_cache array_walk_fci_cache =
empty_fcall_info_cache;
/* Set up known arguments */
args[1] = &key;
@@ -1051,7 +1052,7 @@
fci.no_separation = 0;
/* Call the userland function */
- if (zend_call_function(&fci,
&BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) {
+ if (zend_call_function(&fci,
&array_walk_fci_cache TSRMLS_CC) == SUCCESS) {
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
}
@@ -1094,7 +1095,6 @@
HashTable *target_hash;
argc = ZEND_NUM_ARGS();
- BG(array_walk_fci_cache) = empty_fcall_info_cache;
old_walk_func_name = BG(array_walk_func_name);
if (argc < 2 || argc > 3 ||
zend_get_parameters_ex(argc, &array,
&BG(array_walk_func_name), &userdata) == FAILURE) {
@@ -1131,7 +1131,6 @@
argc = ZEND_NUM_ARGS();
old_walk_func_name = BG(array_walk_func_name);
- BG(array_walk_fci_cache) = empty_fcall_info_cache;
if (argc < 2 || argc > 3 ||
zend_get_parameters_ex(argc, &array,
&BG(array_walk_func_name), &userdata) == FAILURE) {
diff -urw php-5.0.4/ext/standard/basic_functions.h
php-5.0.4.patched/ext/standard/basic_functions.h
--- php-5.0.4/ext/standard/basic_functions.h 2004-03-27
01:50:39.000000000 +0100
+++ php-5.0.4.patched/ext/standard/basic_functions.h 2005-06-10
09:24:46.000000000 +0200
@@ -154,7 +154,6 @@
ulong strtok_len;
char str_ebuf[40];
zval **array_walk_func_name;
- zend_fcall_info_cache array_walk_fci_cache;
zval **user_compare_func_name;
zend_fcall_info_cache user_compare_fci_cache;
zend_llist *user_tick_functions;
------------------------------------------------------------------------
[2005-06-09 19:35:48] pumuckel at metropolis dot de
Description:
------------
Nested array_walk calls don't work.
Reason: BG(array_walk_fci_cache) will not get re-initialized after
inner array_walk call.
Following patch will help - better solution would be a local
array_walk_fci_cache var inside the php_walk_array function:
diff -u php-5.0.4/ext/standard/array.c
php-5.0.4.patched/ext/standard/array.c
--- php-5.0.4/ext/standard/array.c 2005-03-12 11:12:49.000000000
+0100
+++ php-5.0.4.patched/ext/standard/array.c 2005-06-09
19:31:43.000000000 +0200
@@ -1079,6 +1079,8 @@
}
zend_hash_move_forward_ex(target_hash, &pos);
}
+
+ BG(array_walk_fci_cache) = empty_fcall_info_cache;
return 0;
}
Reproduce code:
---------------
<?php
function test_subfunc(&$item1, $key, &$prefix)
{
echo " test_subfunc<br/>";
}
function test_func($item2, $key)
{
echo "test_func<br/>";
$arr = array(1, 2, 3, 4);
array_walk($arr, 'test_subfunc', 'extra_arg');
}
$x = array(5,6,7);
array_walk($x, 'test_func');
?>
Expected result:
----------------
test_func
test_subfunc
test_subfunc
test_subfunc
test_subfunc
test_func
test_subfunc
test_subfunc
test_subfunc
test_subfunc
test_func
test_subfunc
test_subfunc
test_subfunc
test_subfunc
Actual result:
--------------
test_func
test_subfunc
test_subfunc
test_subfunc
test_subfunc
Warning: Missing argument 3 for test_subfunc() in foo.php on line 3
test_subfunc
test_subfunc
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=33286&edit=1