summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/value.h3
-rw-r--r--zend/classimpl.cpp4
-rw-r--r--zend/object.cpp6
-rw-r--r--zend/objectimpl.h6
-rw-r--r--zend/parametersimpl.h2
-rw-r--r--zend/value.cpp33
6 files changed, 34 insertions, 20 deletions
diff --git a/include/value.h b/include/value.h
index 5c34406..7bdd853 100644
--- a/include/value.h
+++ b/include/value.h
@@ -110,7 +110,6 @@ public:
* Wrap object around zval
* @param zval Zval to wrap
* @param ref Force this to be a reference
- * @param tsrm_ls Optional pointer to thread safe data
*/
Value(struct _zval_struct *zval, bool ref=false);
@@ -655,7 +654,7 @@ public:
/**
* Cast to a number
- * @return uint64_t
+ * @return int64_t
*/
operator int64_t () const
{
diff --git a/zend/classimpl.cpp b/zend/classimpl.cpp
index 9c28a0a..e42605e 100644
--- a/zend/classimpl.cpp
+++ b/zend/classimpl.cpp
@@ -534,7 +534,7 @@ zend_object_value ClassImpl::cloneObject(zval *val TSRMLS_DC)
result.handlers = impl->objectHandlers();
// store the object
- ObjectImpl *new_object = new ObjectImpl(entry, cpp TSRMLS_CC);
+ ObjectImpl *new_object = new ObjectImpl(entry, cpp, 1 TSRMLS_CC);
// store the object in the object cache
result.handle = new_object->handle();
@@ -1195,7 +1195,7 @@ zend_object_value ClassImpl::createObject(zend_class_entry *entry TSRMLS_DC)
result.handlers = impl->objectHandlers();
// create the object in the zend engine
- ObjectImpl *object = new ObjectImpl(entry, cpp TSRMLS_CC);
+ ObjectImpl *object = new ObjectImpl(entry, cpp, 1 TSRMLS_CC);
// store the object in the object cache
result.handle = object->handle();
diff --git a/zend/object.cpp b/zend/object.cpp
index 4af6204..22431fe 100644
--- a/zend/object.cpp
+++ b/zend/object.cpp
@@ -40,8 +40,10 @@ Object::Object(const char *name, Base *base) : Value()
if (!entry) throw FatalError(std::string("Unknown class name ") + name);
// construct an implementation (this will also set the implementation
- // member in the base object)
- new ObjectImpl(entry, base TSRMLS_CC);
+ // member in the base object), this is a self-destructing object that
+ // will be destructed when the last reference to it has been removed,
+ // we already set the reference to zero
+ new ObjectImpl(entry, base, 0 TSRMLS_CC);
// now we can store it
operator=(Value(base));
diff --git a/zend/objectimpl.h b/zend/objectimpl.h
index d72ddbd..4d20f3c 100644
--- a/zend/objectimpl.h
+++ b/zend/objectimpl.h
@@ -62,9 +62,10 @@ public:
*
* @param entry Zend class entry
* @param base C++ object that already exists
+ * @param refcount The initial refcount for the object
* @param tsrm_ls Optional threading data
*/
- ObjectImpl(zend_class_entry *entry, Base *base TSRMLS_DC)
+ ObjectImpl(zend_class_entry *entry, Base *base, int refcount TSRMLS_DC)
{
// allocate a mixed object (for some reason this does not have to be deallocated)
_mixed = (MixedObject *)emalloc(sizeof(MixedObject));
@@ -117,6 +118,9 @@ public:
// seem to be necessary...
_handle = zend_objects_store_put(php(), (zend_objects_store_dtor_t)destructMethod, (zend_objects_free_object_storage_t)freeMethod, NULL TSRMLS_CC);
+ // set the initial refcount (if it is different than one, because one is the default)
+ if (refcount != 1) EG(objects_store).object_buckets[_handle].bucket.obj.refcount = refcount;
+
// the object may remember that we are its implementation object
base->_impl = this;
}
diff --git a/zend/parametersimpl.h b/zend/parametersimpl.h
index fd14238..2841c75 100644
--- a/zend/parametersimpl.h
+++ b/zend/parametersimpl.h
@@ -36,7 +36,7 @@ public:
zval **arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (argc-i));
// append value
- push_back(Value(*arg));
+ emplace_back(*arg);
}
}
diff --git a/zend/value.cpp b/zend/value.cpp
index 501feb7..64bdb0e 100644
--- a/zend/value.cpp
+++ b/zend/value.cpp
@@ -157,10 +157,8 @@ Value::Value(double value)
* @param ref Force this to be a reference
*/
Value::Value(struct _zval_struct *val, bool ref)
+: _val(val)
{
- // just copy the zval into this object
- _val = val;
-
// if the variable is not already a reference, and it has more than one
// variable pointing to it, we should seperate it so that any changes
// we're going to make will not change the other variable
@@ -169,13 +167,13 @@ Value::Value(struct _zval_struct *val, bool ref)
// separate the zval
SEPARATE_ZVAL_IF_NOT_REF(&_val);
}
-
+
// we see ourselves as reference too
Z_ADDREF_P(_val);
-
+
// we're ready if we do not have to force it as a reference
if (!ref || Z_ISREF_P(_val)) return;
-
+
// make this a reference
Z_SET_ISREF_P(_val);
}
@@ -188,7 +186,9 @@ Value::Value(const Base *object)
{
// there are two options: the object was constructed from user space,
// and is already linked to a handle, or it was constructed from C++
- // space, and no handle does yet exist, find the implementation object
+ // space, and no handle does yet exist. But if it was constructed from
+ // C++ space and not yet wrapped, this Value constructor should not be
+ // called directly, but first via the derived Php::Object class.
auto *impl = object->implementation();
// do we have a handle?
@@ -205,6 +205,9 @@ Value::Value(const Base *object)
// we have to lookup the object in the object-table
zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[impl->handle()];
+ // there is one more reference to the object
+ obj_bucket->bucket.obj.refcount += 1;
+
// this is copy-pasted from zend_objects.c - and it is necessary too!
if (!obj_bucket->bucket.obj.handlers) obj_bucket->bucket.obj.handlers = &std_object_handlers;
@@ -1523,18 +1526,24 @@ Value Value::clone() const
{
// the zval that will hold the copy
zval *copy;
-
+
// allocate memory
ALLOC_ZVAL(copy);
-
+
// copy the data
INIT_PZVAL_COPY(copy, _val);
-
+
// run the copy constructor to ensure that everything gets copied
zval_copy_ctor(copy);
-
+
+ // wrap it using the Value(zval*) constructor, this will +1 the refcount!!!!
+ Value output(copy);
+
+ // -1 the refcount to avoid future leaks
+ Z_DELREF_P(copy);
+
// done
- return Value(copy);
+ return output;
}
/**