diff options
author | Toon Schoenmakers <toon.schoenmakers@copernica.com> | 2014-08-22 15:23:05 +0200 |
---|---|---|
committer | Toon Schoenmakers <toon.schoenmakers@copernica.com> | 2014-08-22 15:23:05 +0200 |
commit | 97bc6757346d394a4b7d5898983be298e0b0ea98 (patch) | |
tree | 511b8d22e86fe2f44ecc4d2250d2a71329a25b95 | |
parent | 36ab68bd25aaedc81fdf6745faf5f3a14474c53f (diff) |
Store the impl pointer for ClassImpl after the name in the zend_class_entry on php5.3
Turns out the apache reload issue from f57607d2d58f6e7689a3550c84ba68ce42c6a7b3 was
never actually fixed. This commit however does finally fix it. The previously comment
trick however is still used with php 5.4 and php 5.5 as this 'new' trick doesn't work
with these versions of php as char* name in the zend_class_entry is a const char* and
is no longer internally copied and all (meaning we can't realloc it).
-rw-r--r-- | zend/classimpl.cpp | 65 | ||||
-rw-r--r-- | zend/classimpl.h | 6 |
2 files changed, 33 insertions, 38 deletions
diff --git a/zend/classimpl.cpp b/zend/classimpl.cpp index b2acc24..9c28a0a 100644 --- a/zend/classimpl.cpp +++ b/zend/classimpl.cpp @@ -20,11 +20,6 @@ ClassImpl::~ClassImpl() { // destruct the entries if (_entries) delete[] _entries; - - // php 5.3 deallocates the doc_comment by iself -#if PHP_VERSION_ID >= 50400 - if (_comment) free(_comment); -#endif } /** @@ -41,18 +36,21 @@ static ClassImpl *self(zend_class_entry *entry) // we need the base class (in user space the class may have been overridden, // but we are not interested in these user space classes) while (entry->parent) entry = entry->parent; - + #if PHP_VERSION_ID >= 50400 // retrieve the comment (it has a pointer hidden in it to the ClassBase object) const char *comment = entry->info.user.doc_comment; -#else - // retrieve the comment php5.3 style (it has a pointer hidden in it to the ClassBase object) - const char *comment = entry->doc_comment; -#endif - + // the first byte of the comment is an empty string (null character), but // the next bytes contain a pointer to the ClassBase class return *((ClassImpl **)(comment + 1)); +#else + // on php 5.3 we store the pointer to impl after the name in the entry + ClassImpl** impl = (ClassImpl**)(entry->name + 1 + entry->name_length); + + // return the actual implementation + return *impl; +#endif } /** @@ -1411,34 +1409,37 @@ void ClassImpl::initialize(ClassBase *base, const std::string &prefix TSRMLS_DC) // otherwise report an error else std::cerr << "Derived class " << name() << " is initialized before base class " << interface->name() << ": interface is ignored" << std::endl; } - + + // this pointer has to be copied to temporary pointer, as &this causes compiler error + ClassImpl *impl = this; + +#if PHP_VERSION_ID >= 50400 + // allocate doc comment to contain an empty string + a hidden pointer - if (!_comment) - { - // allocate now - _comment = (char *)malloc(1 + sizeof(ClassBase *)); - - // empty string on first position - _comment[0] = '\0'; - - // this pointer has to be copied to temporary pointer, as &this causes compiler error - ClassImpl *impl = this; - - // copy the 'this' pointer to the doc-comment - memcpy(_comment+1, &impl, sizeof(ClassImpl *)); - } - - // store pointer to the class in the unused doc_comment member -#if PHP_VERSION_ID >= 50400 + char *_comment = (char *)malloc(1 + sizeof(ClassImpl *)); + + // empty string on first position + _comment[0] = '\0'; + + // copy the 'this' pointer to the doc-comment + memcpy(_comment+1, &impl, sizeof(ClassImpl *)); + + // set our comment in the actual class entry _entry->info.user.doc_comment = _comment; + #else - // and store the wrapper inside the comment - _entry->doc_comment = _comment; + + // Reallocate some extra space in the name in the zend_class_entry so we can fit a pointer behind it + _entry->name = (char *) realloc(_entry->name, _entry->name_length + 1 + sizeof(ClassImpl *)); + + // Copy the pointer after it + memcpy(_entry->name + _entry->name_length + 1, &impl, sizeof(ClassImpl *)); + #endif // set access types flags for class _entry->ce_flags = (int)_type; - + // declare all member variables for (auto &member : _members) member->initialize(_entry TSRMLS_CC); } diff --git a/zend/classimpl.h b/zend/classimpl.h index bd631b8..26cf030 100644 --- a/zend/classimpl.h +++ b/zend/classimpl.h @@ -32,12 +32,6 @@ private: std::string _name; /** - * The comment for reflexion, with a stored pointer to ourselves - * @var char* - */ - char *_comment = nullptr; - - /** * The class type (this can be values like Php::Abstract and Php::Final) * @var ClassType */ |