PHP Internals folks--
I'm working on the opcode cache part of Wincache, and I believe that Wincache isn't properly handling the scope and prototype fields of the zend_op_array struct when copying it into shared memory.
I tried looking at the Zend Opcache code to figure out what The Right Way(TM) to handle these fields, and I'm curious about how these fields are used by the Zend engine.
From what I can tell, Zend Opcache has a per-process HashTable where it keeps track of which items is has copied into shared memory (xlat_table).
It looks like the xlat_table is cleared out before each compilation. When persisting, Zend persists things in the following order:
- function_table
- class_table
- zend_op_array (for the main zend_op_array produced by compile)
My questions:
- Is there some guarantee that the scope and prototype on the main zend_op_array exist in the function_table and class_table for the compilation?
- Does the scope and prototype fields really matter for the main zend_op_array? Wincache has been setting them to
NULL
since day 1, and everything seems to work just fine... - The xlat_table key is a ulong. Zend Opcache uses the pointer of an object as the key. On Windows, a ulong is 32 bits. How does this even work on an x64 Windows box?
Thx!
--E.
Hi Eric,
On Tue, Jun 24, 2014 at 11:08 PM, Eric Stenson ericsten@microsoft.com
wrote:
PHP Internals folks--
I'm working on the opcode cache part of Wincache, and I believe that
Wincache isn't properly handling the scope and prototype fields of the
zend_op_array struct when copying it into shared memory.I tried looking at the Zend Opcache code to figure out what The Right
Way(TM) to handle these fields, and I'm curious about how these fields are
used by the Zend engine.From what I can tell, Zend Opcache has a per-process HashTable where it
keeps track of which items is has copied into shared memory (xlat_table).It looks like the xlat_table is cleared out before each compilation. When
persisting, Zend persists things in the following order:
- function_table
- class_table
- zend_op_array (for the main zend_op_array produced by compile)
My questions:
- Is there some guarantee that the scope and prototype on the main
zend_op_array exist in the function_table and class_table for the
compilation?
OPcache makes a trick to compile each file completely independent from
others, so op_arrays may refer only to classes and functions from the same
script or to internal ones.
- Does the scope and prototype fields really matter for the main
zend_op_array? Wincache has been setting them toNULL
since day 1, and
everything seems to work just fine...
scope and prototype make sense only for methods. top_level code and regular
functions always have them as NULL.
- The xlat_table key is a ulong. Zend Opcache uses the pointer of an
object as the key. On Windows, a ulong is 32 bits. How does this even
work on an x64 Windows box?
#if SIZEOF_SIZE_T <= SIZEOF_LONG
/* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */
define accel_xlat_set(old, new)
zend_hash_index_update(&ZCG(bind_hash), (ulong)(zend_uintptr_t)(old),
&(new), sizeof(void*), NULL)
define accel_xlat_get(old, new) zend_hash_index_find(&ZCG(bind_hash),
(ulong)(zend_uintptr_t)(old), (void**)&(new))
#else
define accel_xlat_set(old, new) zend_hash_quick_add(&ZCG(bind_hash),
(char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new),
sizeof(void*), NULL)
define accel_xlat_get(old, new) zend_hash_quick_find(&ZCG(bind_hash),
(char*)&(old), sizeof(void*), (ulong)(zend_uintptr_t)(old), (void**)&(new))
#endif
So on x64 Windows we use "string" keys. It's less efficient but safe.
Thanks. Dmitry.
Thx!
--E.