Skip to content

Commit

Permalink
Move zend_object->guards into additional slot of zend_object->propert…
Browse files Browse the repository at this point in the history
…ies_table[]. As result size of objects without __get/__set/__unset/__isset magic methods is reduced.
  • Loading branch information
dstogov committed Feb 4, 2015
1 parent 87377c1 commit 9e70d76
Show file tree
Hide file tree
Showing 39 changed files with 95 additions and 55 deletions.
4 changes: 4 additions & 0 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -2086,12 +2086,16 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
__tostring = reg_function;
} else if (zend_string_equals_literal(lowercase_name, ZEND_GET_FUNC_NAME)) {
__get = reg_function;
scope->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lowercase_name, ZEND_SET_FUNC_NAME)) {
__set = reg_function;
scope->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lowercase_name, ZEND_UNSET_FUNC_NAME)) {
__unset = reg_function;
scope->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lowercase_name, ZEND_ISSET_FUNC_NAME)) {
__isset = reg_function;
scope->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME)) {
__debugInfo = reg_function;
} else {
Expand Down
4 changes: 4 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4130,24 +4130,28 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo
"public visibility and cannot be static");
}
ce->__get = (zend_function *) op_array;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
if (!is_public || is_static) {
zend_error(E_WARNING, "The magic method __set() must have "
"public visibility and cannot be static");
}
ce->__set = (zend_function *) op_array;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
if (!is_public || is_static) {
zend_error(E_WARNING, "The magic method __unset() must have "
"public visibility and cannot be static");
}
ce->__unset = (zend_function *) op_array;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
if (!is_public || is_static) {
zend_error(E_WARNING, "The magic method __isset() must have "
"public visibility and cannot be static");
}
ce->__isset = (zend_function *) op_array;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
if (!is_public || is_static) {
zend_error(E_WARNING, "The magic method __toString() must have "
Expand Down
3 changes: 3 additions & 0 deletions Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ typedef struct _zend_try_catch_element {
#define ZEND_ACC_RETURN_REFERENCE 0x4000000
#define ZEND_ACC_DONE_PASS_TWO 0x8000000

/* class has magic methods __get/__set/__unset/__isset that use guards */
#define ZEND_ACC_USE_GUARDS 0x1000000

/* function has arguments with type hinting */
#define ZEND_ACC_HAS_TYPE_HINTS 0x10000000

Expand Down
6 changes: 5 additions & 1 deletion Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
/* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
zend_verify_abstract_class(ce);
}
ce->ce_flags |= parent_ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS;
ce->ce_flags |= parent_ce->ce_flags & (ZEND_HAS_STATIC_IN_METHODS | ZEND_ACC_USE_GUARDS);
}
/* }}} */

Expand Down Expand Up @@ -1044,14 +1044,18 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
} else if (!strncmp(mname->val, ZEND_GET_FUNC_NAME, mname->len)) {
ce->__get = fe;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (!strncmp(mname->val, ZEND_SET_FUNC_NAME, mname->len)) {
ce->__set = fe;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (!strncmp(mname->val, ZEND_CALL_FUNC_NAME, mname->len)) {
ce->__call = fe;
} else if (!strncmp(mname->val, ZEND_UNSET_FUNC_NAME, mname->len)) {
ce->__unset = fe;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (!strncmp(mname->val, ZEND_ISSET_FUNC_NAME, mname->len)) {
ce->__isset = fe;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (!strncmp(mname->val, ZEND_CALLSTATIC_FUNC_NAME, mname->len)) {
ce->__callstatic = fe;
} else if (!strncmp(mname->val, ZEND_TOSTRING_FUNC_NAME, mname->len)) {
Expand Down
22 changes: 16 additions & 6 deletions Zend/zend_object_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,17 +482,27 @@ static void zend_property_guard_dtor(zval *el) /* {{{ */ {

static zend_long *zend_get_property_guard(zend_object *zobj, zend_string *member) /* {{{ */
{
HashTable *guards;
zend_long stub, *guard;
zval tmp;

if (!zobj->guards) {
ALLOC_HASHTABLE(zobj->guards);
zend_hash_init(zobj->guards, 8, NULL, zend_property_guard_dtor, 0);
} else if ((guard = (zend_long *)zend_hash_find_ptr(zobj->guards, member)) != NULL) {
return guard;
ZEND_ASSERT(GC_FLAGS(zobj) & IS_OBJ_USE_GUARDS);
if (GC_FLAGS(zobj) & IS_OBJ_HAS_GUARDS) {
guards = Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]);
ZEND_ASSERT(guards != NULL);
if ((guard = (zend_long *)zend_hash_find_ptr(guards, member)) != NULL) {
return guard;
}
} else {
ALLOC_HASHTABLE(guards);
zend_hash_init(guards, 8, NULL, zend_property_guard_dtor, 0);
ZVAL_PTR(&tmp, guards);
Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]) = guards;
GC_FLAGS(zobj) |= IS_OBJ_HAS_GUARDS;
}

stub = 0;
return (zend_long *)zend_hash_add_mem(zobj->guards, member, &stub, sizeof(zend_ulong));
return (zend_long *)zend_hash_add_mem(guards, member, &stub, sizeof(zend_ulong));
}
/* }}} */

Expand Down
19 changes: 13 additions & 6 deletions Zend/zend_objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce)
GC_TYPE_INFO(object) = IS_OBJECT;
object->ce = ce;
object->properties = NULL;
object->guards = NULL;
zend_objects_store_put(object);
if (EXPECTED(ce->default_properties_count != 0)) {
zval *p = object->properties_table;
Expand All @@ -43,16 +42,17 @@ ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce)
p++;
} while (p != end);
}
if (ce->ce_flags & ZEND_ACC_USE_GUARDS) {
GC_FLAGS(object) |= IS_OBJ_USE_GUARDS;
ZVAL_UNDEF(&object->properties_table[ce->default_properties_count]);
Z_PTR(object->properties_table[ce->default_properties_count]) = NULL;
}
}

ZEND_API void zend_object_std_dtor(zend_object *object)
{
int i, count;

if (object->guards) {
zend_hash_destroy(object->guards);
FREE_HASHTABLE(object->guards);
}
if (object->properties) {
zend_array_destroy(object->properties);
FREE_HASHTABLE(object->properties);
Expand All @@ -61,6 +61,13 @@ ZEND_API void zend_object_std_dtor(zend_object *object)
for (i = 0; i < count; i++) {
i_zval_ptr_dtor(&object->properties_table[i] ZEND_FILE_LINE_CC);
}
if (GC_FLAGS(object) & IS_OBJ_HAS_GUARDS) {
HashTable *guards = Z_PTR(object->properties_table[count]);

ZEND_ASSERT(guards != NULL);
zend_hash_destroy(guards);
FREE_HASHTABLE(guards);
}
}

ZEND_API void zend_objects_destroy_object(zend_object *object)
Expand Down Expand Up @@ -131,7 +138,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)

ZEND_API zend_object *zend_objects_new(zend_class_entry *ce)
{
zend_object *object = emalloc(sizeof(zend_object) + sizeof(zval) * (ce->default_properties_count - 1));
zend_object *object = emalloc(sizeof(zend_object) + zend_object_properties_size(ce));

zend_object_std_init(object, ce);
object->handlers = &std_object_handlers;
Expand Down
8 changes: 8 additions & 0 deletions Zend/zend_objects_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define ZEND_OBJECTS_API_H

#include "zend.h"
#include "zend_compile.h"

#define OBJ_BUCKET_INVALID (1<<0)

Expand Down Expand Up @@ -80,6 +81,13 @@ static zend_always_inline void zend_object_release(zend_object *obj)
}
}

static zend_always_inline size_t zend_object_properties_size(zend_class_entry *ce)
{
return sizeof(zval) *
(ce->default_properties_count -
((ce->ce_flags & ZEND_ACC_USE_GUARDS) ? 0 : 1));
}

#endif /* ZEND_OBJECTS_H */

/*
Expand Down
3 changes: 2 additions & 1 deletion Zend/zend_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ struct _zend_object {
zend_class_entry *ce;
const zend_object_handlers *handlers;
HashTable *properties;
HashTable *guards; /* protects from __get/__set ... recursion */
zval properties_table[1];
};

Expand Down Expand Up @@ -325,6 +324,8 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define IS_OBJ_APPLY_COUNT 0x07
#define IS_OBJ_DESTRUCTOR_CALLED (1<<3)
#define IS_OBJ_FREE_CALLED (1<<4)
#define IS_OBJ_USE_GUARDS (1<<5)
#define IS_OBJ_HAS_GUARDS (1<<6)

#define Z_OBJ_APPLY_COUNT(zval) \
(Z_GC_FLAGS(zval) & IS_OBJ_APPLY_COUNT)
Expand Down
8 changes: 4 additions & 4 deletions ext/date/php_date.c
Original file line number Diff line number Diff line change
Expand Up @@ -2069,7 +2069,7 @@ static inline zend_object *date_object_new_date_ex(zend_class_entry *class_type,
{
php_date_obj *intern;

intern = ecalloc(1, sizeof(php_date_obj) + sizeof(zval) * (class_type->default_properties_count - 1));
intern = ecalloc(1, sizeof(php_date_obj) + zend_object_properties_size(class_type));

zend_object_std_init(&intern->std, class_type);
if (init_props) {
Expand Down Expand Up @@ -2200,7 +2200,7 @@ static inline zend_object *date_object_new_timezone_ex(zend_class_entry *class_t
{
php_timezone_obj *intern;

intern = ecalloc(1, sizeof(php_timezone_obj) + sizeof(zval) * (class_type->default_properties_count - 1));
intern = ecalloc(1, sizeof(php_timezone_obj) + zend_object_properties_size(class_type));

zend_object_std_init(&intern->std, class_type);
if (init_props) {
Expand Down Expand Up @@ -2291,7 +2291,7 @@ static inline zend_object *date_object_new_interval_ex(zend_class_entry *class_t
{
php_interval_obj *intern;

intern = ecalloc(1, sizeof(php_interval_obj) + sizeof(zval) * (class_type->default_properties_count - 1));
intern = ecalloc(1, sizeof(php_interval_obj) + zend_object_properties_size(class_type));

zend_object_std_init(&intern->std, class_type);
if (init_props) {
Expand Down Expand Up @@ -2372,7 +2372,7 @@ static inline zend_object *date_object_new_period_ex(zend_class_entry *class_typ
{
php_period_obj *intern;

intern = ecalloc(1, sizeof(php_period_obj) + sizeof(zval) * (class_type->default_properties_count - 1));
intern = ecalloc(1, sizeof(php_period_obj) + zend_object_properties_size(class_type));

zend_object_std_init(&intern->std, class_type);
if (init_props) {
Expand Down
4 changes: 2 additions & 2 deletions ext/dom/php_dom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,7 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml

static dom_object* dom_objects_set_class(zend_class_entry *class_type, zend_bool hash_copy) /* {{{ */
{
dom_object *intern = ecalloc(1, sizeof(dom_object) + sizeof(zval) * (class_type->default_properties_count - 1));
dom_object *intern = ecalloc(1, sizeof(dom_object) + zend_object_properties_size(class_type));

zend_class_entry *base_class = class_type;
while (base_class->type != ZEND_INTERNAL_CLASS && base_class->parent != NULL) {
Expand Down Expand Up @@ -1112,7 +1112,7 @@ zend_object *dom_objects_new(zend_class_entry *class_type)
/* {{{ zend_object_value dom_xpath_objects_new(zend_class_entry *class_type) */
zend_object *dom_xpath_objects_new(zend_class_entry *class_type)
{
dom_xpath_object *intern = ecalloc(1, sizeof(dom_xpath_object) + sizeof(zval) * (class_type->default_properties_count - 1));
dom_xpath_object *intern = ecalloc(1, sizeof(dom_xpath_object) + zend_object_properties_size(class_type));

ALLOC_HASHTABLE(intern->registered_phpfunctions);
zend_hash_init(intern->registered_phpfunctions, 0, NULL, ZVAL_PTR_DTOR, 0);
Expand Down
2 changes: 1 addition & 1 deletion ext/fileinfo/fileinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ PHP_FILEINFO_API zend_object *finfo_objects_new(zend_class_entry *class_type)
{
finfo_object *intern;

intern = ecalloc(1, sizeof(finfo_object) + sizeof(zval) * (class_type->default_properties_count - 1));
intern = ecalloc(1, sizeof(finfo_object) + zend_object_properties_size(class_type));

zend_object_std_init(&intern->zo, class_type);
object_properties_init(&intern->zo, class_type);
Expand Down
3 changes: 1 addition & 2 deletions ext/gmp/gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,7 @@ static void gmp_free_object_storage(zend_object *obj) /* {{{ */

static inline zend_object *gmp_create_object_ex(zend_class_entry *ce, mpz_ptr *gmpnum_target) /* {{{ */
{
gmp_object *intern = emalloc(sizeof(gmp_object)
+ sizeof(zval) * (ce->default_properties_count - 1));
gmp_object *intern = emalloc(sizeof(gmp_object) + zend_object_properties_size(ce));

zend_object_std_init(&intern->std, ce);
object_properties_init(&intern->std, ce);
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/collator/collator_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ zend_object *Collator_object_create(zend_class_entry *ce )
{
Collator_object* intern;

intern = ecalloc(1, sizeof(Collator_object) + sizeof(zval) * (ce->default_properties_count - 1));
intern = ecalloc(1, sizeof(Collator_object) + zend_object_properties_size(ce));
intl_error_init(COLLATOR_ERROR_P(intern));
zend_object_std_init(&intern->zo, ce );
object_properties_init(&intern->zo, ce);
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/converter/converter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@ static void php_converter_dtor_object(zend_object *obj) {
static zend_object *php_converter_object_ctor(zend_class_entry *ce, php_converter_object **pobjval) {
php_converter_object *objval;

objval = ecalloc(1, sizeof(php_converter_object) + sizeof(zval) * (ce->default_properties_count - 1));
objval = ecalloc(1, sizeof(php_converter_object) + zend_object_properties_size(ce));

zend_object_std_init(&objval->obj, ce );
intl_error_init(&(objval->error));
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/dateformat/dateformat_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ zend_object *IntlDateFormatter_object_create(zend_class_entry *ce)
{
IntlDateFormatter_object* intern;

intern = ecalloc( 1, sizeof(IntlDateFormatter_object) + sizeof(zval) * (ce->default_properties_count - 1) );
intern = ecalloc( 1, sizeof(IntlDateFormatter_object) + zend_object_properties_size(ce));
dateformat_data_init( &intern->datef_data );
zend_object_std_init( &intern->zo, ce );
object_properties_init(&intern->zo, ce);
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/formatter/formatter_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ zend_object *NumberFormatter_object_create(zend_class_entry *ce)
{
NumberFormatter_object* intern;

intern = ecalloc( 1, sizeof(NumberFormatter_object) + sizeof(zval) * (ce->default_properties_count - 1) );
intern = ecalloc( 1, sizeof(NumberFormatter_object) + zend_object_properties_size(ce));
formatter_data_init( &intern->nf_data );
zend_object_std_init( &intern->zo, ce );
object_properties_init(&intern->zo, ce);
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/msgformat/msgformat_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ zend_object *MessageFormatter_object_create(zend_class_entry *ce)
{
MessageFormatter_object* intern;

intern = ecalloc( 1, sizeof(MessageFormatter_object) + sizeof(zval) * (ce->default_properties_count - 1));
intern = ecalloc( 1, sizeof(MessageFormatter_object) + zend_object_properties_size(ce));
msgformat_data_init( &intern->mf_data );
zend_object_std_init( &intern->zo, ce );
object_properties_init(&intern->zo, ce);
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/resourcebundle/resourcebundle_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static zend_object *ResourceBundle_object_create( zend_class_entry *ce )
{
ResourceBundle_object *rb;

rb = ecalloc( 1, sizeof(ResourceBundle_object) + sizeof(zval) * (ce->default_properties_count - 1) );
rb = ecalloc( 1, sizeof(ResourceBundle_object) + zend_object_properties_size(ce));

zend_object_std_init( &rb->zend, ce );
object_properties_init( &rb->zend, ce);
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/spoofchecker/spoofchecker_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ zend_object *Spoofchecker_object_create(
{
Spoofchecker_object* intern;

intern = ecalloc(1, sizeof(Spoofchecker_object) + sizeof(zval) * (ce->default_properties_count - 1));
intern = ecalloc(1, sizeof(Spoofchecker_object) + zend_object_properties_size(ce));
intl_error_init(SPOOFCHECKER_ERROR_P(intern));
zend_object_std_init(&intern->zo, ce);
object_properties_init(&intern->zo, ce);
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/transliterator/transliterator_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static zend_object *Transliterator_object_create(
{
Transliterator_object* intern;

intern = ecalloc( 1, sizeof( Transliterator_object ) + sizeof(zval) * (ce->default_properties_count - 1));
intern = ecalloc( 1, sizeof( Transliterator_object ) + zend_object_properties_size(ce));

zend_object_std_init( &intern->zo, ce );
object_properties_init( &intern->zo, ce );
Expand Down
2 changes: 1 addition & 1 deletion ext/mysqli/mysqli.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ PHP_MYSQLI_EXPORT(zend_object *) mysqli_objects_new(zend_class_entry *class_type
zend_class_entry *mysqli_base_class;
zend_object_handlers *handlers;

intern = ecalloc(1, sizeof(mysqli_object) + sizeof(zval) * (class_type->default_properties_count - 1));
intern = ecalloc(1, sizeof(mysqli_object) + zend_object_properties_size(class_type));

mysqli_base_class = class_type;
while (mysqli_base_class->type != ZEND_INTERNAL_CLASS &&
Expand Down
2 changes: 1 addition & 1 deletion ext/pdo/pdo_dbh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1544,7 +1544,7 @@ zend_object *pdo_dbh_new(zend_class_entry *ce)
{
pdo_dbh_object_t *dbh;

dbh = ecalloc(1, sizeof(pdo_dbh_object_t) + sizeof(zval) * (ce->default_properties_count - 1));
dbh = ecalloc(1, sizeof(pdo_dbh_object_t) + zend_object_properties_size(ce));
zend_object_std_init(&dbh->std, ce);
object_properties_init(&dbh->std, ce);
rebuild_object_properties(&dbh->std);
Expand Down
4 changes: 2 additions & 2 deletions ext/pdo/pdo_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2254,7 +2254,7 @@ static zend_object *dbstmt_clone_obj(zval *zobject)
pdo_stmt_t *stmt;
pdo_stmt_t *old_stmt;

stmt = ecalloc(1, sizeof(pdo_stmt_t) + sizeof(zval) * (Z_OBJCE_P(zobject)->default_properties_count - 1));
stmt = ecalloc(1, sizeof(pdo_stmt_t) + zend_object_properties_size(Z_OBJCE_P(zobject)));
zend_object_std_init(&stmt->std, Z_OBJCE_P(zobject));
object_properties_init(&stmt->std, Z_OBJCE_P(zobject));

Expand Down Expand Up @@ -2357,7 +2357,7 @@ zend_object *pdo_dbstmt_new(zend_class_entry *ce)
{
pdo_stmt_t *stmt;

stmt = ecalloc(1, sizeof(pdo_stmt_t) + sizeof(zval) * (ce->default_properties_count - 1));
stmt = ecalloc(1, sizeof(pdo_stmt_t) + zend_object_properties_size(ce));
zend_object_std_init(&stmt->std, ce);
object_properties_init(&stmt->std, ce);

Expand Down
Loading

0 comments on commit 9e70d76

Please sign in to comment.