goto found;
}
} else if (EXPECTED(zobj->properties != NULL)) {
+ if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(zobj->properties)--;
+ }
+ zobj->properties = zend_array_dup(zobj->properties);
+ }
if ((variable_ptr = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) {
found:
zend_assign_to_variable(variable_ptr, value, IS_CV);
}
}
} else {
- if (UNEXPECTED(!zobj->properties) ||
- UNEXPECTED((retval = zend_hash_find(zobj->properties, name)) == NULL)) {
- if (EXPECTED(!zobj->ce->__get) ||
- UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
- if (UNEXPECTED(!zobj->properties)) {
- rebuild_object_properties(zobj);
+ if (EXPECTED(zobj->properties)) {
+ if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(zobj->properties)--;
}
- retval = zend_hash_update(zobj->properties, name, &EG(uninitialized_zval));
- /* Notice is thrown after creation of the property, to avoid EG(std_property_info)
- * being overwritten in an error handler. */
- if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
- zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name->val, name->val);
+ zobj->properties = zend_array_dup(zobj->properties);
+ }
+ if (EXPECTED((retval = zend_hash_find(zobj->properties, name)) != NULL)) {
+ if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
+ zend_string_release(name);
}
- }
+ return retval;
+ }
+ }
+ if (EXPECTED(!zobj->ce->__get) ||
+ UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
+ if (UNEXPECTED(!zobj->properties)) {
+ rebuild_object_properties(zobj);
+ }
+ retval = zend_hash_update(zobj->properties, name, &EG(uninitialized_zval));
+ /* Notice is thrown after creation of the property, to avoid EG(std_property_info)
+ * being overwritten in an error handler. */
+ if (UNEXPECTED(type == BP_VAR_RW || type == BP_VAR_R)) {
+ zend_error(E_NOTICE, "Undefined property: %s::$%s", zobj->ce->name->val, name->val);
+ }
}
}
}
ZVAL_UNDEF(slot);
goto exit;
}
- } else if (EXPECTED(zobj->properties != NULL) &&
- EXPECTED(zend_hash_del(zobj->properties, Z_STR_P(member)) != FAILURE)) {
- goto exit;
+ } else if (EXPECTED(zobj->properties != NULL)) {
+ if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(zobj->properties)--;
+ }
+ zobj->properties = zend_array_dup(zobj->properties);
+ }
+ if (EXPECTED(zend_hash_del(zobj->properties, Z_STR_P(member)) != FAILURE)) {
+ goto exit;
+ }
}
} else if (UNEXPECTED(EG(exception))) {
goto exit;
zval *p, *end;
if (object->properties) {
- zend_array_destroy(object->properties);
+ if (EXPECTED(!(GC_FLAGS(object->properties) & IS_ARRAY_IMMUTABLE))) {
+ if (EXPECTED(--GC_REFCOUNT(object->properties) == 0)) {
+ zend_array_destroy(object->properties);
+ }
+ }
}
p = object->properties_table;
if (EXPECTED(object->ce->default_properties_count)) {
src++;
dst++;
} while (src != end);
+ } else if (old_object->properties && !old_object->ce->clone) {
+ /* fast copy */
+ if (EXPECTED(old_object->handlers == &std_object_handlers)) {
+ if (EXPECTED(!(GC_FLAGS(old_object->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(old_object->properties)++;
+ }
+ new_object->properties = old_object->properties;
+ return;
+ }
}
+
if (old_object->properties &&
EXPECTED(zend_hash_num_elements(old_object->properties))) {
zval *prop, new_prop;
HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op);
if (obj_ht) {
zval arr;
- ZVAL_ARR(&arr, zend_array_dup(obj_ht));
- zval_dtor(op);
- ZVAL_COPY_VALUE(op, &arr);
+
+ if (!Z_OBJCE_P(op)->default_properties_count && obj_ht == Z_OBJ_P(op)->properties) {
+ /* fast copy */
+ if (EXPECTED(Z_OBJ_P(op)->handlers == &std_object_handlers)) {
+ ZVAL_ARR(&arr, obj_ht);
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(op)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(op)->properties)++;
+ }
+ } else {
+ ZVAL_ARR(&arr, zend_array_dup(obj_ht));
+ }
+ zval_dtor(op);
+ ZVAL_COPY_VALUE(op, &arr);
+ } else {
+ ZVAL_ARR(&arr, zend_array_dup(obj_ht));
+ zval_dtor(op);
+ ZVAL_COPY_VALUE(op, &arr);
+ }
return;
}
} else {