Oops, the patch was wrong as the runtime occationally segfaults
in a case like:
?php
$a = 0;
$a = $a; /* is_ref=1, refcount=1 */
?
Attached is the revised patch. Please try it out.
And the result of a tiny benchmark follows:
[Before patching]
1: 0.263245
2: 0.142505
3: 0.328045
4: 0.137149
[After patching]
1: 0.273811
2: 0.141965
3: 0.699429
4: 0.137010
Moriyoshi
My proposal, was based on 2 things: fix or document. I'm sure Zeev/Andi had a
good reason not to always separate, and that probably is performance.
IF this impacts overall performance very negatively, then maybe the better
choice is to document it.
I'll try the patch though.
With kind regards,
Melvyn Sopacua
?php include(not_reflecting_employers_views.txt); ?
--
PHP Development Mailing List http://www.php.net/
To unsubscribe, visit: http://www.php.net/unsub.php
Index: zend_execute.c
===
RCS file: /repository/Zend/zend_execute.c,v
retrieving revision 1.316.2.2
diff -u -r1.316.2.2 zend_execute.c
--- zend_execute.c 17 Nov 2002 22:00:32 - 1.316.2.2
+++ zend_execute.c 15 Dec 2002 06:47:03 -
@@ -65,6 +65,7 @@
static void zend_extension_statement_handler(zend_extension *extension, zend_op_array
*op_array TSRMLS_DC);
static void zend_extension_fcall_begin_handler(zend_extension *extension,
zend_op_array *op_array TSRMLS_DC);
static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_array
*op_array TSRMLS_DC);
+static int _zval_array_disref(zval **ppz);
#define RETURN_VALUE_USED(opline) (!((opline)-result.u.EA.type EXT_TYPE_UNUSED))
@@ -1816,6 +1817,7 @@
} else if (PZVAL_IS_REF(*param)) {
zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(EX(opline)-result, EX(Ts),
BP_VAR_W), param, NULL TSRMLS_CC);
} else {
+ _zval_array_disref(param);
zend_assign_to_variable(NULL,
EX(opline)-result, NULL, *param, IS_VAR, EX(Ts) TSRMLS_CC);
}
}
@@ -2480,4 +2482,59 @@
}
}
zend_error(E_ERROR, Arrived at end of main loop which shouldn't happen);
+}
+
+static int _zval_ref_check(zval **p, void *flag)
+{
+ if ((*p)-is_ref) {
+ *(int *)flag = 1;
+ }
+ _zval_array_disref(p);
+ return ZEND_HASH_APPLY_KEEP;
+}
+
+static void zval_dis_ref(zval **p)
+{
+ if ((*p)-is_ref) {
+ zval *newzv;
+ ALLOC_ZVAL(newzv);
+ *newzv = **p;
+ zval_copy_ctor(newzv);
+ newzv-refcount = 1;
+ newzv-is_ref = 0;
+
+ if ((*p)-refcount 1) {
+ zval_dtor((*p));
+ FREE_ZVAL(*p);
+ }
+
+ *p = newzv;
+ } else {
+ ((*p))-refcount++;
+ }
+}
+
+static int _zval_array_disref(zval **ppz)
+{
+ TSRMLS_FETCH();
+ if ((*ppz)-type == IS_ARRAY) {
+ int flag = 0;
+ if ((*ppz)-value.ht == EG(symbol_table)) {
+ return SUCCESS;
+ }
+ zend_hash_apply_with_argument((*ppz)-value.ht, (apply_func_arg_t)
+_zval_ref_check, (void *)flag TSRMLS_CC);
+ if (flag) {
+ zval *newzv, *tmp;
+ ALLOC_ZVAL(newzv);
+ *newzv = **ppz;
+ ALLOC_HASHTABLE(newzv-value.ht);
+ zend_hash_init(newzv-value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_copy(newzv-value.ht, Z_ARRVAL_PP(ppz),
+(copy_ctor_func_t) zval_dis_ref, (void *) tmp, sizeof(zval *));
+ zval_ptr_dtor(ppz);
+ *ppz = newzv;
+ newzv-is_ref = 0;
+ newzv-refcount = 1;
+ }
+ }
+ return SUCCESS;
}
?php
function timediff($ts, $te) {
list($ts_usec, $ts_sec) = explode(' ', $ts);
list($te_usec, $te_sec) = explode(' ', $te);
return ((float)$te_usec - (float)$ts_usec) + (float)( (int)$te_sec -
(int)$ts_sec );
}
function test1( $ary ) {
$ary[32048] = '3';
}
function test2( $ary ) {
$ary[32048] = '3';
}
for ($i=0; $i10; ++$i) {
$ary_org[$i] = str_repeat(\\, rand( 0, 12 )).sprintf(%08x,
rand(-1,0x7fff));
}
for ($i=0; $i10; ++$i) {
$ary_ref[$i] = $ary_ref[$i];
}
$ts = microtime();
$ary = $ary_org;
test1($ary);
$te = microtime();
printf(1: %f\n, timediff($ts, $te));
$ts =