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