Good Morning, PHP Internals Folks!
I have a design question about caching of IS_REFERENCE zval values, and want to understand the most correct way to implement a memory Cache for zvals in PHP7.
Background:
WinCache's user cache does a 'deep copy' of zvals into a shared memory segment that can start at different offsets in the processes which share the memory segment. This means that all internal pointers must be converted into offsets relative to the starting address of the shared memory segment. Further, flags are altered such that the cached zval is considered immutable and not ref counted.
So, for example, with an IS_STRING zval, a zval in shared memory is created (zv_cached), the zend_string is cached, and then the Z_STR_P(zv_cached) is set to the offset of the cached zend_string.
When the user fetches the cached IS_STRING zval, the reverse is performed: a zval is created in request-temporary memory (zv_fetched), and initialized from zv_cached. Z_STR_P(zv_fetched) is translated back into a pointer (to the cached zend_string) which is correct in the current process. The caller won't attempt to free or modify the cached zend_string since the type flags were modified when it was cached.
For IS_REFERENCE objects, I'm not clear on what I should do. Should I cache the zend_reference struct, with its included zval? Or should I "flatten" the IS_REFERENCE, and just convert it to the zval that's in the zend_reference struct?
Consider the following:
<?php
$bar = "BAR";
$arr2 = array('black' => &$bar, 'black2' => &$bar );
wincache_ucache_add('foo', $arr2);
$fetched_arr = wincache_ucache_get('foo');
?>
The $fetched_arr won't have the internal references between elements (e.g. $fetched_arr['black'] and $fetched_arr['black2'] won't point at the same actual value).
Questions:
- How should one persist/intern an IS_REFERENCE zval?
- Is it acceptable to "flatten" IS_REFERENCE zvals when persisting/interning them? If not, what's the reason for not doing so?
- If IS_REFERENCE zvals have to be maintained, does that mean that the zend_reference will need to be copied out of the shared memory cache each time it's fetched?
- Is there an example of a PHP7 extension which is doing something similar? APC doesn't appear to have been updated for PHP7.
Thx!
--E.