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 -0000 1.316.2.2
+++ zend_execute.c 15 Dec 2002 06:47:03 -0000
@@ -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; $i<100000; ++$i) {
$ary_org[$i] = str_repeat("\\", rand( 0, 12 )).sprintf("%08x",
rand(-1,0x7fffffff));
}
for ($i=0; $i<100000; ++$i) {
$ary_ref[$i] = &$ary_ref[$i];
}
$ts = microtime();
$ary = $ary_org;
test1($ary);
$te = microtime();
printf("1: %f\n", timediff($ts, $te));
$ts = microtime();
$ary = $ary_org;
test2($ary);
$te = microtime();
printf("2: %f\n", timediff($ts, $te));
$ts = microtime();
$ary = $ary_ref;
test1($ary);
$te = microtime();
printf("3: %f\n", timediff($ts, $te));
$ts = microtime();
$ary = $ary_ref;
test2($ary);
$te = microtime();
printf("4: %f\n", timediff($ts, $te));
?>
--
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php