facebook/hhvm — pull request #2446 by tstarling (2014-04-14 09:39:36+00:00)
Title:  EZC: Fix hashtables and resources 

As usual, the size of the pull request is determined by the amount of work it took to get the tests to pass. I considered attempting to split the hash work and the resource work into separate PRs, but the hash work is pretty badly broken without the resource work.

Allow zend_hash_*() to store non-zval data:
* Call the supplied destructor when the arbitrary data is freed. This is implemented by wrapping the data in a resource -- this was a more elegant hook into HphpArray than aggressive patching or replacement of handlers.
* Introduce a set of non-static methods to ProxyArray which provide wrapping and unwrapping of arbitrary data. Access them directly from zend_hash.cpp by casting ArrayData* to ProxyArray*.
* Fix the handling of the pDest arguments. To support pDest efficiently, it was necessary to add an "out" parameter to the ZAppend handler, giving the index inserted.
* Make Z_OBJPROP() return a ProxyArray instead of an HphpArray, per the convention that only ProxyArrays should be exposed to zend compat.
* Removed unused class TypedValueHolder.
* Used "using namespace HPHP" for brevity where possible.
* Converted some functions that were using ArrayIter to use the integer position interface instead -- otherwise a special ArrayIter subclass would have been needed to do the ZendCustomElement unwrapping.
* Added a test case for hashtables, including destructor invocation, which exposed issues with resource handling as follows:

Improve resource handling:
* Call resource destructors
* Make s_resource_dtors not be thread-local, since it is populated by MINIT. Also make it a std::vector instead of a std::unordered_map, for obvious reasons.
* Make ZendResourceData and ZendCustomElement unsweepable, since no guarantees can be made about what they will try to free in their extension-supplied destructors.
* Remove two unnecessary incRefCount() calls, which caused destructors to never be called.

Also:
* Added php_write() implementation, needed by the test case.