Added caches to eliminate repeatable run-time bindings of functions, classes, constants, methods and properties

This commit is contained in:
Dmitry Stogov 2010-05-24 14:11:39 +00:00
parent 1cabc8cd3a
commit c5237d82bf
45 changed files with 2487 additions and 723 deletions

2
NEWS
View file

@ -4,6 +4,8 @@
- Upgraded bundled sqlite to version 3.6.23.1. (Ilia) - Upgraded bundled sqlite to version 3.6.23.1. (Ilia)
- Upgraded bundled PCRE to version 8.02. (Ilia) - Upgraded bundled PCRE to version 8.02. (Ilia)
- Added caches to eliminate repeatable run-time bindings of functions, classes,
constants, methods and properties (Dmitry)
- Added a number of small performance tweaks and optimizations (Dmitry) - Added a number of small performance tweaks and optimizations (Dmitry)
. ZEND_RECV now always has IS_CV as its result . ZEND_RECV now always has IS_CV as its result
. ZEND_CATCH now has to be used only with constant class names . ZEND_CATCH now has to be used only with constant class names

View file

@ -3,7 +3,6 @@ if (function_exists("date_default_timezone_set")) {
date_default_timezone_set("UTC"); date_default_timezone_set("UTC");
} }
date_default_timezone_set('UTC');
function simple() { function simple() {
$a = 0; $a = 0;
for ($i = 0; $i < 1000000; $i++) for ($i = 0; $i < 1000000; $i++)

View file

@ -298,6 +298,7 @@ typedef struct _zend_guard {
typedef struct _zend_object { typedef struct _zend_object {
zend_class_entry *ce; zend_class_entry *ce;
HashTable *properties; HashTable *properties;
zval **properties_table;
HashTable *guards; /* protects from __get/__set ... recursion */ HashTable *guards; /* protects from __get/__set ... recursion */
} zend_object; } zend_object;
@ -468,11 +469,13 @@ struct _zend_class_entry {
zend_uint ce_flags; zend_uint ce_flags;
HashTable function_table; HashTable function_table;
HashTable default_properties;
HashTable properties_info; HashTable properties_info;
HashTable default_static_members; zval **default_properties_table;
HashTable *static_members; zval **default_static_members_table;
zval **static_members_table;
HashTable constants_table; HashTable constants_table;
int default_properties_count;
int default_static_members_count;
const struct _zend_function_entry *builtin_functions; const struct _zend_function_entry *builtin_functions;
union _zend_function *constructor; union _zend_function *constructor;

View file

@ -1005,45 +1005,41 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{ {
if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) { if (!class_type->constants_updated || (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count)) {
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
zend_class_entry *old_scope = *scope; zend_class_entry *old_scope = *scope;
int i;
*scope = class_type; *scope = class_type;
zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC); zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
if (!CE_STATIC_MEMBERS(class_type)) { for (i = 0; i < class_type->default_properties_count; i++) {
HashPosition pos; if (class_type->default_properties_table[i]) {
zval_update_constant(&class_type->default_properties_table[i], (void**)1 TSRMLS_CC);
}
}
if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
zval **p; zval **p;
if (class_type->parent) { if (class_type->parent) {
zend_update_class_constants(class_type->parent TSRMLS_CC); zend_update_class_constants(class_type->parent TSRMLS_CC);
} }
#if ZTS #if ZTS
ALLOC_HASHTABLE(CG(static_members)[(zend_intptr_t)(class_type->static_members)]); CG(static_members)[(zend_intptr_t)(class_type->static_members)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
#else #else
ALLOC_HASHTABLE(class_type->static_members); class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
#endif #endif
zend_hash_init(CE_STATIC_MEMBERS(class_type), zend_hash_num_elements(&class_type->default_static_members), NULL, ZVAL_PTR_DTOR, 0); for (i = 0; i < class_type->default_static_members_count; i++) {
p = &class_type->default_static_members_table[i];
zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos);
while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) {
char *str_index;
uint str_length;
ulong num_index;
zval **q;
zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos);
if (Z_ISREF_PP(p) && if (Z_ISREF_PP(p) &&
class_type->parent && class_type->parent &&
zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS && class_type->parent->default_static_members_count < i &&
*p == *q && *p == class_type->parent->default_static_members_table[i]
zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS
) { ) {
Z_ADDREF_PP(q); Z_ADDREF_PP(p);
Z_SET_ISREF_PP(q); Z_SET_ISREF_PP(p);
zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL); class_type->static_members_table[i] = *p;
} else { } else {
zval *r; zval *r;
@ -1051,12 +1047,14 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
*r = **p; *r = **p;
INIT_PZVAL(r); INIT_PZVAL(r);
zval_copy_ctor(r); zval_copy_ctor(r);
zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)&r, sizeof(zval*), NULL); class_type->static_members_table[i] = r;
} }
zend_hash_move_forward_ex(&class_type->default_static_members, &pos);
} }
} }
zend_hash_apply_with_argument(CE_STATIC_MEMBERS(class_type), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
for (i = 0; i < class_type->default_static_members_count; i++) {
zval_update_constant(&CE_STATIC_MEMBERS(class_type)[i], (void**)1 TSRMLS_CC);
}
*scope = old_scope; *scope = old_scope;
class_type->constants_updated = 1; class_type->constants_updated = 1;
@ -1064,13 +1062,29 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
} }
/* }}} */ /* }}} */
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
{
int i;
if (class_type->default_properties_count) {
object->properties_table = emalloc(sizeof(zval*) * class_type->default_properties_count);
for (i = 0; i < class_type->default_properties_count; i++) {
object->properties_table[i] = class_type->default_properties_table[i];
if (class_type->default_properties_table[i]) {
Z_ADDREF_P(object->properties_table[i]);
}
}
object->properties = NULL;
}
}
/* }}} */
/* This function requires 'properties' to contain all props declared in the /* This function requires 'properties' to contain all props declared in the
* class and all props being public. If only a subset is given or the class * class and all props being public. If only a subset is given or the class
* has protected members then you need to merge the properties seperately by * has protected members then you need to merge the properties seperately by
* calling zend_merge_properties(). */ * calling zend_merge_properties(). */
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
{ {
zval *tmp;
zend_object *object; zend_object *object;
if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
@ -1085,10 +1099,9 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC); Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC);
if (properties) { if (properties) {
object->properties = properties; object->properties = properties;
object->properties_table = NULL;
} else { } else {
ALLOC_HASHTABLE_REL(object->properties); object_properties_init(object, class_type);
zend_hash_init(object->properties, zend_hash_num_elements(&class_type->default_properties), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
} }
} else { } else {
Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC); Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC);
@ -2315,8 +2328,6 @@ static zend_object_value display_disabled_class(zend_class_entry *class_type TSR
zend_object_value retval; zend_object_value retval;
zend_object *intern; zend_object *intern;
retval = zend_objects_new(&intern, class_type TSRMLS_CC); retval = zend_objects_new(&intern, class_type TSRMLS_CC);
ALLOC_HASHTABLE(intern->properties);
zend_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name); zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name);
return retval; return retval;
} }
@ -3076,17 +3087,38 @@ ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
{ {
zend_property_info property_info; zend_property_info property_info, *property_info_ptr;
HashTable *target_symbol_table;
char *interned_name; char *interned_name;
ulong h = zend_get_hash_value(name, name_length+1);
if (!(access_type & ZEND_ACC_PPP_MASK)) { if (!(access_type & ZEND_ACC_PPP_MASK)) {
access_type |= ZEND_ACC_PUBLIC; access_type |= ZEND_ACC_PUBLIC;
} }
if (access_type & ZEND_ACC_STATIC) { if (access_type & ZEND_ACC_STATIC) {
target_symbol_table = &ce->default_static_members; if (zend_hash_quick_find(&ce->properties_info, name, name_length + 1, h, (void**)&property_info_ptr) == SUCCESS &&
(property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
property_info.offset = property_info_ptr->offset;
zval_ptr_dtor(&ce->default_static_members_table[property_info.offset]);
zend_hash_quick_del(&ce->properties_info, name, name_length + 1, h);
} else {
property_info.offset = ce->default_static_members_count++;
ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
}
ce->default_static_members_table[property_info.offset] = property;
if (ce->type == ZEND_USER_CLASS) {
ce->static_members_table = ce->default_static_members_table;
}
} else { } else {
target_symbol_table = &ce->default_properties; if (zend_hash_quick_find(&ce->properties_info, name, name_length + 1, h, (void**)&property_info_ptr) == SUCCESS &&
(property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
property_info.offset = property_info_ptr->offset;
zval_ptr_dtor(&ce->default_properties_table[property_info.offset]);
zend_hash_quick_del(&ce->properties_info, name, name_length + 1, h);
} else {
property_info.offset = ce->default_properties_count++;
ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
}
ce->default_properties_table[property_info.offset] = property;
} }
if (ce->type & ZEND_INTERNAL_CLASS) { if (ce->type & ZEND_INTERNAL_CLASS) {
switch(Z_TYPE_P(property)) { switch(Z_TYPE_P(property)) {
@ -3120,14 +3152,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
} }
break; break;
case ZEND_ACC_PUBLIC: case ZEND_ACC_PUBLIC:
if (ce->parent) {
char *prot_name;
int prot_name_length;
zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
}
if (IS_INTERNED(name)) { if (IS_INTERNED(name)) {
property_info.name = (char*)name; property_info.name = (char*)name;
} else { } else {
@ -3147,17 +3171,15 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
property_info.name = interned_name; property_info.name = interned_name;
} }
zend_hash_update(target_symbol_table, property_info.name, property_info.name_length+1, &property, sizeof(zval *), NULL);
property_info.flags = access_type; property_info.flags = access_type;
property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1); property_info.h = (access_type & ZEND_ACC_PUBLIC) ? h : zend_get_hash_value(property_info.name, property_info.name_length+1);
property_info.doc_comment = doc_comment; property_info.doc_comment = doc_comment;
property_info.doc_comment_len = doc_comment_len; property_info.doc_comment_len = doc_comment_len;
property_info.ce = ce; property_info.ce = ce;
zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL); zend_hash_quick_update(&ce->properties_info, name, name_length + 1, h, &property_info, sizeof(zend_property_info), NULL);
return SUCCESS; return SUCCESS;
} }

View file

@ -208,9 +208,9 @@ typedef struct _zend_fcall_info_cache {
INIT_OVERLOADED_CLASS_ENTRY(class_container, ZEND_NS_NAME(ns, class_name), functions, handle_fcall, handle_propget, handle_propset) INIT_OVERLOADED_CLASS_ENTRY(class_container, ZEND_NS_NAME(ns, class_name), functions, handle_fcall, handle_propget, handle_propset)
#ifdef ZTS #ifdef ZTS
# define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members:CG(static_members)[(zend_intptr_t)(ce)->static_members]) # define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members:CG(static_members_table)[(zend_intptr_t)(ce)->static_members_table])
#else #else
# define CE_STATIC_MEMBERS(ce) ((ce)->static_members) # define CE_STATIC_MEMBERS(ce) ((ce)->static_members_table)
#endif #endif
#define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0) #define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0)
@ -347,6 +347,7 @@ ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC);
ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC); ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC);
ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC TSRMLS_DC); ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC TSRMLS_DC);
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC); ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC);
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type);
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC); ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC);

View file

@ -888,49 +888,53 @@ ZEND_FUNCTION(is_a)
/* {{{ add_class_vars */ /* {{{ add_class_vars */
static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *return_value TSRMLS_DC) static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC)
{ {
if (zend_hash_num_elements(properties) > 0) { HashPosition pos;
HashPosition pos; zend_property_info *prop_info;
zval **prop; zval *prop, *prop_copy;
char *key;
uint key_len;
ulong num_index;
zend_hash_internal_pointer_reset_ex(properties, &pos); zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) { while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) {
char *key, *class_name, *prop_name; zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos);
uint key_len; zend_hash_move_forward_ex(&ce->properties_info, &pos);
ulong num_index; if (((prop_info->flags & ZEND_ACC_SHADOW) &&
int prop_name_len = 0; prop_info->ce != EG(scope)) ||
zval *prop_copy; ((prop_info->flags & ZEND_ACC_PROTECTED) &&
zend_property_info *property_info; !zend_check_protected(prop_info->ce, EG(scope))) ||
zval zprop_name; ((prop_info->flags & ZEND_ACC_PRIVATE) &&
ce != EG(scope) &&
zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos); prop_info->ce != EG(scope))) {
zend_hash_move_forward_ex(properties, &pos); continue;
zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
prop_name_len = strlen(prop_name);
ZVAL_STRINGL(&zprop_name, prop_name, prop_name_len, 0);
property_info = zend_get_property_info(ce, &zprop_name, 1 TSRMLS_CC);
if (!property_info || property_info == &EG(std_property_info)) {
continue;
}
/* copy: enforce read only access */
ALLOC_ZVAL(prop_copy);
*prop_copy = **prop;
zval_copy_ctor(prop_copy);
INIT_PZVAL(prop_copy);
/* this is necessary to make it able to work with default array
* properties, returned to user */
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
add_assoc_zval(return_value, prop_name, prop_copy);
} }
prop = NULL;
if (prop_info->offset >= 0) {
if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
prop = ce->default_static_members_table[prop_info->offset];
} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
prop = ce->default_properties_table[prop_info->offset];
}
}
if (!prop) {
continue;
}
/* copy: enforce read only access */
ALLOC_ZVAL(prop_copy);
*prop_copy = *prop;
zval_copy_ctor(prop_copy);
INIT_PZVAL(prop_copy);
/* this is necessary to make it able to work with default array
* properties, returned to user */
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
add_assoc_zval(return_value, key, prop_copy);
} }
} }
/* }}} */ /* }}} */
@ -953,8 +957,8 @@ ZEND_FUNCTION(get_class_vars)
} else { } else {
array_init(return_value); array_init(return_value);
zend_update_class_constants(*pce TSRMLS_CC); zend_update_class_constants(*pce TSRMLS_CC);
add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC); add_class_vars(*pce, 0, return_value TSRMLS_CC);
add_class_vars(*pce, CE_STATIC_MEMBERS(*pce), return_value TSRMLS_CC); add_class_vars(*pce, 1, return_value TSRMLS_CC);
} }
} }
/* }}} */ /* }}} */

View file

@ -70,6 +70,25 @@
} \ } \
} while (0) } while (0)
#define GET_CACHE_SLOT(literal) do { \
CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot++; \
} while (0)
#define POLYMORPHIC_CACHE_SLOT_SIZE 2
#define GET_POLYMORPHIC_CACHE_SLOT(literal) do { \
CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot; \
CG(active_op_array)->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE; \
} while (0)
#define FREE_POLYMORPHIC_CACHE_SLOT(literal) do { \
if (CG(active_op_array)->literals[literal].cache_slot == \
CG(active_op_array)->last_cache_slot - POLYMORPHIC_CACHE_SLOT_SIZE) { \
CG(active_op_array)->literals[literal].cache_slot = -1; \
CG(active_op_array)->last_cache_slot -= POLYMORPHIC_CACHE_SLOT_SIZE; \
} \
} while (0)
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC); ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
@ -361,6 +380,7 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv) /* {{{ */
Z_SET_REFCOUNT(CONSTANT_EX(op_array, i), 2); Z_SET_REFCOUNT(CONSTANT_EX(op_array, i), 2);
Z_SET_ISREF(CONSTANT_EX(op_array, i)); Z_SET_ISREF(CONSTANT_EX(op_array, i));
op_array->literals[i].hash_value = 0; op_array->literals[i].hash_value = 0;
op_array->literals[i].cache_slot = -1;
return i; return i;
} }
/* }}} */ /* }}} */
@ -373,7 +393,8 @@ int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC
int lc_literal; int lc_literal;
if (op_array->last_literal > 0 && if (op_array->last_literal > 0 &&
&op_array->literals[op_array->last_literal - 1].constant == zv) { &op_array->literals[op_array->last_literal - 1].constant == zv &&
op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
/* we already have function name as last literal (do nothing) */ /* we already have function name as last literal (do nothing) */
ret = op_array->last_literal - 1; ret = op_array->last_literal - 1;
} else { } else {
@ -398,7 +419,8 @@ int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS
int lc_literal; int lc_literal;
if (op_array->last_literal > 0 && if (op_array->last_literal > 0 &&
&op_array->literals[op_array->last_literal - 1].constant == zv) { &op_array->literals[op_array->last_literal - 1].constant == zv &&
op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
/* we already have function name as last literal (do nothing) */ /* we already have function name as last literal (do nothing) */
ret = op_array->last_literal - 1; ret = op_array->last_literal - 1;
} else { } else {
@ -430,7 +452,8 @@ int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_D
int lc_literal; int lc_literal;
if (op_array->last_literal > 0 && if (op_array->last_literal > 0 &&
&op_array->literals[op_array->last_literal - 1].constant == zv) { &op_array->literals[op_array->last_literal - 1].constant == zv &&
op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
/* we already have function name as last literal (do nothing) */ /* we already have function name as last literal (do nothing) */
ret = op_array->last_literal - 1; ret = op_array->last_literal - 1;
} else { } else {
@ -448,6 +471,8 @@ int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_D
lc_literal = zend_add_literal(CG(active_op_array), &c); lc_literal = zend_add_literal(CG(active_op_array), &c);
CALCULATE_LITERAL_HASH(lc_literal); CALCULATE_LITERAL_HASH(lc_literal);
GET_CACHE_SLOT(ret);
return ret; return ret;
} }
/* }}} */ /* }}} */
@ -460,7 +485,8 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq
zval c; zval c;
if (op_array->last_literal > 0 && if (op_array->last_literal > 0 &&
&op_array->literals[op_array->last_literal - 1].constant == zv) { &op_array->literals[op_array->last_literal - 1].constant == zv &&
op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
/* we already have function name as last literal (do nothing) */ /* we already have function name as last literal (do nothing) */
ret = op_array->last_literal - 1; ret = op_array->last_literal - 1;
} else { } else {
@ -710,6 +736,7 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /*
opline.op1_type = IS_CONST; opline.op1_type = IS_CONST;
LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0); LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0);
CALCULATE_LITERAL_HASH(opline.op1.constant); CALCULATE_LITERAL_HASH(opline.op1.constant);
GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
if (class_node.op_type == IS_CONST) { if (class_node.op_type == IS_CONST) {
opline.op2_type = IS_CONST; opline.op2_type = IS_CONST;
opline.op2.constant = opline.op2.constant =
@ -734,6 +761,7 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /*
opline.op1_type = IS_CONST; opline.op1_type = IS_CONST;
LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[opline_ptr->op1.var].name), CG(active_op_array)->vars[opline_ptr->op1.var].name_len, 0); LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[opline_ptr->op1.var].name), CG(active_op_array)->vars[opline_ptr->op1.var].name_len, 0);
CALCULATE_LITERAL_HASH(opline.op1.constant); CALCULATE_LITERAL_HASH(opline.op1.constant);
GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
if (class_node.op_type == IS_CONST) { if (class_node.op_type == IS_CONST) {
opline.op2_type = IS_CONST; opline.op2_type = IS_CONST;
opline.op2.constant = opline.op2.constant =
@ -746,6 +774,9 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /*
zend_llist_prepend_element(fetch_list_ptr, &opline); zend_llist_prepend_element(fetch_list_ptr, &opline);
} else { } else {
if (opline_ptr->op1_type == IS_CONST) {
GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
}
if (class_node.op_type == IS_CONST) { if (class_node.op_type == IS_CONST) {
opline_ptr->op2_type = IS_CONST; opline_ptr->op2_type = IS_CONST;
opline_ptr->op2.constant = opline_ptr->op2.constant =
@ -1921,8 +1952,16 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
if (last_op->opcode == ZEND_FETCH_OBJ_R) { if (last_op->opcode == ZEND_FETCH_OBJ_R) {
if (last_op->op2_type == IS_CONST) { if (last_op->op2_type == IS_CONST) {
zval name;
name = CONSTANT(last_op->op2.constant);
if (!IS_INTERNED(Z_STRVAL(name))) {
Z_STRVAL(name) = estrndup(Z_STRVAL(name), Z_STRLEN(name));
}
FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
last_op->op2.constant = last_op->op2.constant =
zend_add_func_name_literal(CG(active_op_array), &CONSTANT(last_op->op2.constant) TSRMLS_CC); zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC);
GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
} }
last_op->opcode = ZEND_INIT_METHOD_CALL; last_op->opcode = ZEND_INIT_METHOD_CALL;
SET_UNUSED(last_op->result); SET_UNUSED(last_op->result);
@ -1934,6 +1973,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
if (left_bracket->op_type == IS_CONST) { if (left_bracket->op_type == IS_CONST) {
opline->op2_type = IS_CONST; opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC); opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC);
GET_CACHE_SLOT(opline->op2.constant);
} else { } else {
SET_NODE(opline->op2, left_bracket); SET_NODE(opline->op2, left_bracket);
} }
@ -1970,12 +2010,14 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
SET_UNUSED(opline->op1); SET_UNUSED(opline->op1);
opline->op2_type = IS_CONST; opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC); opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
GET_CACHE_SLOT(opline->op2.constant);
} else { } else {
opline->opcode = ZEND_INIT_FCALL_BY_NAME; opline->opcode = ZEND_INIT_FCALL_BY_NAME;
SET_UNUSED(opline->op1); SET_UNUSED(opline->op1);
if (function_name->op_type == IS_CONST) { if (function_name->op_type == IS_CONST) {
opline->op2_type = IS_CONST; opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC); opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
GET_CACHE_SLOT(opline->op2.constant);
} else { } else {
SET_NODE(opline->op2, function_name); SET_NODE(opline->op2, function_name);
} }
@ -2341,6 +2383,11 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
opline->op2_type = IS_CONST; opline->op2_type = IS_CONST;
opline->op2.constant = opline->op2.constant =
zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC); zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC);
if (opline->op1_type == IS_CONST) {
GET_CACHE_SLOT(opline->op2.constant);
} else {
GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
}
} else { } else {
SET_NODE(opline->op2, method_name); SET_NODE(opline->op2, method_name);
} }
@ -2367,6 +2414,7 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
opline->opcode = ZEND_DO_FCALL; opline->opcode = ZEND_DO_FCALL;
SET_NODE(opline->op1, function_name); SET_NODE(opline->op1, function_name);
CALCULATE_LITERAL_HASH(opline->op1.constant); CALCULATE_LITERAL_HASH(opline->op1.constant);
GET_CACHE_SLOT(opline->op1.constant);
} else { } else {
opline->opcode = ZEND_DO_FCALL_BY_NAME; opline->opcode = ZEND_DO_FCALL_BY_NAME;
SET_UNUSED(opline->op1); SET_UNUSED(opline->op1);
@ -2727,6 +2775,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *)); zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
} }
op_array->run_time_cache = NULL;
} }
} }
/* }}} */ /* }}} */
@ -3032,42 +3081,11 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) { if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
} else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) { } else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
if (!(parent_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) { Z_DELREF_P(ce->default_properties_table[parent_info->offset]);
/* Explicitly copy the default value from the parent (if it has one) */ ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
zval **pvalue; ce->default_properties_table[child_info->offset] = NULL;
child_info->offset = parent_info->offset;
if (zend_hash_quick_find(&parent_ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
Z_ADDREF_PP(pvalue);
zend_hash_quick_del(&ce->default_properties, child_info->name, child_info->name_length+1, parent_info->h);
zend_hash_quick_update(&ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
}
}
return 1; /* Inherit from the parent */
} else if ((child_info->flags & ZEND_ACC_PUBLIC) && (parent_info->flags & ZEND_ACC_PROTECTED)) {
char *prot_name;
int prot_name_length;
zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
if (child_info->flags & ZEND_ACC_STATIC) {
zval **prop;
HashTable *ht;
if (parent_ce->type != ce->type) {
/* User class extends internal class */
TSRMLS_FETCH();
ht = CE_STATIC_MEMBERS(parent_ce);
} else {
ht = &parent_ce->default_static_members;
}
if (zend_hash_find(ht, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
zend_hash_del(&ce->default_static_members, prot_name, prot_name_length+1);
}
} else {
zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1);
}
pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
} }
return 0; /* Don't copy from parent */ return 0; /* Don't copy from parent */
} else { } else {
@ -3140,6 +3158,8 @@ static int inherit_static_prop(zval **p TSRMLS_DC, int num_args, va_list args, c
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
{ {
zend_property_info *property_info;
if ((ce->ce_flags & ZEND_ACC_INTERFACE) if ((ce->ce_flags & ZEND_ACC_INTERFACE)
&& !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) { && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name); zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
@ -3161,14 +3181,78 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC); zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
/* Inherit properties */ /* Inherit properties */
zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0); if (parent_ce->default_properties_count) {
int i = ce->default_properties_count + parent_ce->default_properties_count;
ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
if (ce->default_properties_count) {
while (i-- > parent_ce->default_properties_count) {
ce->default_properties_table[i] = ce->default_properties_table[i - parent_ce->default_properties_count];
}
}
for (i = 0; i < parent_ce->default_properties_count; i++) {
ce->default_properties_table[i] = parent_ce->default_properties_table[i];
if (ce->default_properties_table[i]) {
Z_ADDREF_P(ce->default_properties_table[i]);
}
}
ce->default_properties_count += parent_ce->default_properties_count;
}
if (parent_ce->type != ce->type) { if (parent_ce->type != ce->type) {
/* User class extends internal class */ /* User class extends internal class */
zend_update_class_constants(parent_ce TSRMLS_CC); zend_update_class_constants(parent_ce TSRMLS_CC);
zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members); if (parent_ce->default_static_members_count) {
int i = ce->default_static_members_count + parent_ce->default_static_members_count;
ce->default_static_members_table = erealloc(ce->default_static_members_table, sizeof(void*) * i);
if (ce->default_static_members_count) {
while (i-- > parent_ce->default_static_members_count) {
ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
}
}
for (i = 0; i < parent_ce->default_static_members_count; i++) {
SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
Z_ADDREF_P(ce->default_static_members_table[i]);
}
ce->default_static_members_count += parent_ce->default_static_members_count;
ce->static_members_table = ce->default_static_members_table;
}
} else { } else {
zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members); if (parent_ce->default_static_members_count) {
int i = ce->default_static_members_count + parent_ce->default_static_members_count;
ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
if (ce->default_static_members_count) {
while (i-- > parent_ce->default_static_members_count) {
ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
}
}
for (i = 0; i < parent_ce->default_static_members_count; i++) {
SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
Z_ADDREF_P(ce->default_static_members_table[i]);
}
ce->default_static_members_count += parent_ce->default_static_members_count;
if (ce->type == ZEND_USER_CLASS) {
ce->static_members_table = ce->default_static_members_table;
}
}
} }
for (zend_hash_internal_pointer_reset(&ce->properties_info);
zend_hash_get_current_data(&ce->properties_info, (void *) &property_info) == SUCCESS;
zend_hash_move_forward(&ce->properties_info)) {
if (property_info->ce == ce) {
if (property_info->flags & ZEND_ACC_STATIC) {
property_info->offset += parent_ce->default_static_members_count;
} else {
property_info->offset += parent_ce->default_properties_count;
}
}
}
zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce); zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0); zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
@ -4651,9 +4735,7 @@ void zend_do_declare_property(const znode *var_name, const znode *value, zend_ui
} }
if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) { if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) {
if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) { zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
}
} }
ALLOC_ZVAL(property); ALLOC_ZVAL(property);
@ -4748,6 +4830,7 @@ void zend_do_fetch_property(znode *result, znode *object, const znode *property
} }
if (opline_ptr->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline_ptr->op2.constant)) == IS_STRING) { if (opline_ptr->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline_ptr->op2.constant)) == IS_STRING) {
CALCULATE_LITERAL_HASH(opline_ptr->op2.constant); CALCULATE_LITERAL_HASH(opline_ptr->op2.constant);
GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op2.constant);
} }
GET_NODE(result, opline_ptr->result); GET_NODE(result, opline_ptr->result);
return; return;
@ -4762,6 +4845,7 @@ void zend_do_fetch_property(znode *result, znode *object, const znode *property
SET_NODE(opline.op2, property); SET_NODE(opline.op2, property);
if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) { if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
CALCULATE_LITERAL_HASH(opline.op2.constant); CALCULATE_LITERAL_HASH(opline.op2.constant);
GET_POLYMORPHIC_CACHE_SLOT(opline.op2.constant);
} }
GET_NODE(result, opline.result); GET_NODE(result, opline.result);
@ -4931,6 +5015,11 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
} }
SET_NODE(opline->op2, constant_name); SET_NODE(opline->op2, constant_name);
CALCULATE_LITERAL_HASH(opline->op2.constant); CALCULATE_LITERAL_HASH(opline->op2.constant);
if (opline->op1_type == IS_CONST) {
GET_CACHE_SLOT(opline->op2.constant);
} else {
GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
}
GET_NODE(result, opline->result); GET_NODE(result, opline->result);
break; break;
} }
@ -4985,6 +5074,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC); opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
} }
} }
GET_CACHE_SLOT(opline->op2.constant);
break; break;
} }
} }
@ -5016,6 +5106,7 @@ void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
LITERAL_STRINGL(opline->op1, estrndup("shell_exec", sizeof("shell_exec")-1), sizeof("shell_exec")-1, 0); LITERAL_STRINGL(opline->op1, estrndup("shell_exec", sizeof("shell_exec")-1), sizeof("shell_exec")-1, 0);
CALCULATE_LITERAL_HASH(opline->op1.constant); CALCULATE_LITERAL_HASH(opline->op1.constant);
opline->op1_type = IS_CONST; opline->op1_type = IS_CONST;
GET_CACHE_SLOT(opline->op1.constant);
opline->extended_value = 1; opline->extended_value = 1;
SET_UNUSED(opline->op2); SET_UNUSED(opline->op2);
GET_NODE(result, opline->result); GET_NODE(result, opline->result);
@ -6039,9 +6130,9 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
ce->doc_comment = NULL; ce->doc_comment = NULL;
ce->doc_comment_len = 0; ce->doc_comment_len = 0;
zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0); ce->default_properties_table = NULL;
ce->default_static_members_table = NULL;
zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0); zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
zend_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0); zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0); zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
@ -6055,14 +6146,17 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
CG(static_members) = realloc(CG(static_members), (n+1)*sizeof(HashTable*)); CG(static_members) = realloc(CG(static_members), (n+1)*sizeof(HashTable*));
CG(static_members)[n] = NULL; CG(static_members)[n] = NULL;
} }
ce->static_members = (HashTable*)(zend_intptr_t)n; ce->static_members_table = (zval**)(zend_intptr_t)n;
#else #else
ce->static_members = NULL; ce->static_members_table = NULL;
#endif #endif
} else { } else {
ce->static_members = &ce->default_static_members; ce->static_members_table = &ce->default_static_members_table;
} }
ce->default_properties_count = 0;
ce->default_static_members_count = 0;
if (nullify_handlers) { if (nullify_handlers) {
ce->constructor = NULL; ce->constructor = NULL;
ce->destructor = NULL; ce->destructor = NULL;

View file

@ -53,8 +53,9 @@ typedef struct _zend_op_array zend_op_array;
typedef struct _zend_op zend_op; typedef struct _zend_op zend_op;
typedef struct _zend_literal { typedef struct _zend_literal {
zval constant; zval constant;
ulong hash_value; zend_ulong hash_value;
zend_uint cache_slot;
} zend_literal; } zend_literal;
#define Z_HASH_P(zv) \ #define Z_HASH_P(zv) \
@ -183,6 +184,7 @@ typedef struct _zend_property_info {
char *name; char *name;
int name_length; int name_length;
ulong h; ulong h;
int offset;
char *doc_comment; char *doc_comment;
int doc_comment_len; int doc_comment_len;
zend_class_entry *ce; zend_class_entry *ce;
@ -258,6 +260,9 @@ struct _zend_op_array {
zend_literal *literals; zend_literal *literals;
int last_literal, size_literal; int last_literal, size_literal;
void **run_time_cache;
int last_cache_slot;
void *reserved[ZEND_MAX_RESERVED_RESOURCES]; void *reserved[ZEND_MAX_RESERVED_RESOURCES];
}; };

View file

@ -138,16 +138,14 @@ ZEND_API void zend_clear_exception(TSRMLS_D) /* {{{ */
static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces TSRMLS_DC) /* {{{ */ static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces TSRMLS_DC) /* {{{ */
{ {
zval tmp, obj; zval obj;
zend_object *object; zend_object *object;
zval *trace; zval *trace;
Z_OBJVAL(obj) = zend_objects_new(&object, class_type TSRMLS_CC); Z_OBJVAL(obj) = zend_objects_new(&object, class_type TSRMLS_CC);
Z_OBJ_HT(obj) = &default_exception_handlers; Z_OBJ_HT(obj) = &default_exception_handlers;
ALLOC_HASHTABLE(object->properties); object_properties_init(object, class_type);
zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
ALLOC_ZVAL(trace); ALLOC_ZVAL(trace);
Z_UNSET_ISREF_P(trace); Z_UNSET_ISREF_P(trace);

View file

@ -429,6 +429,23 @@ ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const t
ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS); ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);
#define CACHED_PTR(num) \
EG(active_op_array)->run_time_cache[(num)]
#define CACHE_PTR(num, ptr) do { \
EG(active_op_array)->run_time_cache[(num)] = (ptr); \
} while (0)
#define CACHED_POLYMORPHIC_PTR(num, ce) \
((EG(active_op_array)->run_time_cache[(num)] == (ce)) ? \
EG(active_op_array)->run_time_cache[(num) + 1] : \
NULL)
#define CACHE_POLYMORPHIC_PTR(num, ce, ptr) do { \
EG(active_op_array)->run_time_cache[(num)] = (ce); \
EG(active_op_array)->run_time_cache[(num) + 1] = (ptr); \
} while (0)
END_EXTERN_C() END_EXTERN_C()
#endif /* ZEND_EXECUTE_H */ #endif /* ZEND_EXECUTE_H */

View file

@ -32,7 +32,8 @@
#define DEBUG_OBJECT_HANDLERS 0 #define DEBUG_OBJECT_HANDLERS 0
#define Z_OBJ_P(zval_p) zend_objects_get_address(zval_p TSRMLS_CC) #define Z_OBJ_P(zval_p) \
((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].bucket.obj.object))
/* /*
__X accessors explanation: __X accessors explanation:
@ -51,10 +52,52 @@
called, we cal __call handler. called, we cal __call handler.
*/ */
ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
{
if (!zobj->properties) {
HashPosition pos;
zend_property_info *prop_info;
zend_class_entry *ce = zobj->ce;
ALLOC_HASHTABLE(zobj->properties);
zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
if (ce->default_properties_count) {
for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
if (/*prop_info->ce == ce &&*/
(prop_info->flags & ZEND_ACC_STATIC) == 0 &&
prop_info->offset >= 0 &&
zobj->properties_table[prop_info->offset]) {
zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
}
}
while (ce->parent && ce->parent->default_properties_count) {
ce = ce->parent;
for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
if (prop_info->ce == ce &&
(prop_info->flags & ZEND_ACC_STATIC) == 0 &&
(prop_info->flags & ZEND_ACC_PRIVATE) != 0 &&
prop_info->offset >= 0 &&
zobj->properties_table[prop_info->offset]) {
zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
}
}
}
}
}
}
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) /* {{{ */ ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) /* {{{ */
{ {
zend_object *zobj; zend_object *zobj;
zobj = Z_OBJ_P(object); zobj = Z_OBJ_P(object);
if (!zobj->properties) {
rebuild_object_properties(zobj);
}
return zobj->properties; return zobj->properties;
} }
/* }}} */ /* }}} */
@ -158,7 +201,7 @@ static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) /* {{{
} }
/* }}} */ /* }}} */
static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) /* {{{ */ static zend_always_inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) /* {{{ */
{ {
switch (property_info->flags & ZEND_ACC_PPP_MASK) { switch (property_info->flags & ZEND_ACC_PPP_MASK) {
case ZEND_ACC_PUBLIC: case ZEND_ACC_PUBLIC:
@ -177,7 +220,7 @@ static int zend_verify_property_access(zend_property_info *property_info, zend_c
} }
/* }}} */ /* }}} */
static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */ static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */
{ {
child_class = child_class->parent; child_class = child_class->parent;
while (child_class) { while (child_class) {
@ -191,13 +234,17 @@ static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_cla
} }
/* }}} */ /* }}} */
static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent, const zend_literal *key TSRMLS_DC) /* {{{ */ static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent, const zend_literal *key TSRMLS_DC) /* {{{ */
{ {
zend_property_info *property_info; zend_property_info *property_info;
zend_property_info *scope_property_info; zend_property_info *scope_property_info;
zend_bool denied_access = 0; zend_bool denied_access = 0;
ulong h; ulong h;
if (key && (property_info = CACHED_POLYMORPHIC_PTR(key->cache_slot, ce)) != NULL) {
return property_info;
}
if (UNEXPECTED(Z_STRVAL_P(member)[0] == '\0')) { if (UNEXPECTED(Z_STRVAL_P(member)[0] == '\0')) {
if (!silent) { if (!silent) {
if (Z_STRLEN_P(member) == 0) { if (Z_STRLEN_P(member) == 0) {
@ -223,9 +270,12 @@ static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry
* continue checking below... * continue checking below...
*/ */
} else { } else {
if (!silent && (property_info->flags & ZEND_ACC_STATIC)) { if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0) && !silent) {
zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name, Z_STRVAL_P(member)); zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name, Z_STRVAL_P(member));
} }
if (key) {
CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
}
return property_info; return property_info;
} }
} else { } else {
@ -235,10 +285,13 @@ static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry
} }
} }
if (EG(scope) != ce if (EG(scope) != ce
&& is_derived_class(ce, EG(scope))
&& EG(scope) && EG(scope)
&& is_derived_class(ce, EG(scope))
&& zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
&& scope_property_info->flags & ZEND_ACC_PRIVATE) { && scope_property_info->flags & ZEND_ACC_PRIVATE) {
if (key) {
CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, scope_property_info);
}
return scope_property_info; return scope_property_info;
} else if (property_info) { } else if (property_info) {
if (UNEXPECTED(denied_access != 0)) { if (UNEXPECTED(denied_access != 0)) {
@ -249,6 +302,9 @@ static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry
return NULL; return NULL;
} else { } else {
/* fall through, return property_info... */ /* fall through, return property_info... */
if (key) {
CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
}
} }
} else { } else {
EG(std_property_info).flags = ZEND_ACC_PUBLIC; EG(std_property_info).flags = ZEND_ACC_PUBLIC;
@ -256,6 +312,7 @@ static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry
EG(std_property_info).name_length = Z_STRLEN_P(member); EG(std_property_info).name_length = Z_STRLEN_P(member);
EG(std_property_info).h = h; EG(std_property_info).h = h;
EG(std_property_info).ce = ce; EG(std_property_info).ce = ce;
EG(std_property_info).offset = -1;
property_info = &EG(std_property_info); property_info = &EG(std_property_info);
} }
return property_info; return property_info;
@ -348,7 +405,13 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li
property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC); property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC);
if (UNEXPECTED(!property_info) || if (UNEXPECTED(!property_info) ||
UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)) { ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
property_info->offset >= 0) ?
(zobj->properties ?
((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
(*(retval = &zobj->properties_table[property_info->offset]) == NULL)) :
(UNEXPECTED(!zobj->properties) ||
UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) {
zend_guard *guard; zend_guard *guard;
if (zobj->ce->__get && if (zobj->ce->__get &&
@ -397,7 +460,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li
} }
/* }}} */ /* }}} */
static void zend_std_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
{ {
zend_object *zobj; zend_object *zobj;
zval *tmp_member = NULL; zval *tmp_member = NULL;
@ -419,7 +482,13 @@ static void zend_std_write_property(zval *object, zval *member, zval *value, con
property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__set != NULL), key TSRMLS_CC); property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__set != NULL), key TSRMLS_CC);
if (EXPECTED(property_info != NULL) && if (EXPECTED(property_info != NULL) &&
EXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS)) { ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
property_info->offset >= 0) ?
(zobj->properties ?
((variable_ptr = (zval**)zobj->properties_table[property_info->offset]) != NULL) :
(*(variable_ptr = &zobj->properties_table[property_info->offset]) != NULL)) :
(EXPECTED(zobj->properties != NULL) &&
EXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS)))) {
/* if we already have this value there, we don't actually need to do anything */ /* if we already have this value there, we don't actually need to do anything */
if (EXPECTED(*variable_ptr != value)) { if (EXPECTED(*variable_ptr != value)) {
/* if we are assigning reference, we shouldn't move it, but instead assign variable /* if we are assigning reference, we shouldn't move it, but instead assign variable
@ -462,15 +531,27 @@ static void zend_std_write_property(zval *object, zval *member, zval *value, con
guard->in_set = 0; guard->in_set = 0;
zval_ptr_dtor(&object); zval_ptr_dtor(&object);
} }
if (!setter_done && property_info) { if (!setter_done && EXPECTED(property_info != NULL)) {
zval **foo;
/* if we assign referenced variable, we should separate it */ /* if we assign referenced variable, we should separate it */
Z_ADDREF_P(value); Z_ADDREF_P(value);
if (PZVAL_IS_REF(value)) { if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value); SEPARATE_ZVAL(&value);
} }
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo); if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
property_info->offset >= 0) {
if (!zobj->properties) {
zobj->properties_table[property_info->offset] = value;
} else if (zobj->properties_table[property_info->offset]) {
*(zval**)zobj->properties_table[property_info->offset] = value;
} else {
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]);
}
} else {
if (!zobj->properties) {
rebuild_object_properties(zobj);
}
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), NULL);
}
} }
} }
@ -587,7 +668,13 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const ze
property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC); property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC);
if (UNEXPECTED(!property_info) || if (UNEXPECTED(!property_info) ||
UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)) { ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
property_info->offset >= 0) ?
(zobj->properties ?
((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
(*(retval = &zobj->properties_table[property_info->offset]) == NULL)) :
(UNEXPECTED(!zobj->properties) ||
UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) {
zval *new_zval; zval *new_zval;
zend_guard *guard; zend_guard *guard;
@ -599,7 +686,24 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const ze
/* zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */ /* zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */
Z_ADDREF_P(new_zval); Z_ADDREF_P(new_zval);
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval); if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
property_info->offset >= 0) {
if (!zobj->properties) {
zobj->properties_table[property_info->offset] = new_zval;
retval = &zobj->properties_table[property_info->offset];
} else if (zobj->properties_table[property_info->offset]) {
*(zval**)zobj->properties_table[property_info->offset] = new_zval;
retval = (zval**)zobj->properties_table[property_info->offset];
} else {
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]);
retval = (zval**)zobj->properties_table[property_info->offset];
}
} else {
if (!zobj->properties) {
rebuild_object_properties(zobj);
}
zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
}
} else { } else {
/* we do have getter - fail and let it try again with usual get/set */ /* we do have getter - fail and let it try again with usual get/set */
retval = NULL; retval = NULL;
@ -632,8 +736,16 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter
property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__unset != NULL), key TSRMLS_CC); property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__unset != NULL), key TSRMLS_CC);
if (UNEXPECTED(!property_info) || if (EXPECTED(property_info != NULL) &&
UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) { EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
!zobj->properties &&
property_info->offset >= 0 &&
EXPECTED(zobj->properties_table[property_info->offset] != NULL)) {
zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
zobj->properties_table[property_info->offset] = NULL;
} else if (UNEXPECTED(!property_info) ||
!zobj->properties ||
UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) {
zend_guard *guard; zend_guard *guard;
if (zobj->ce->__unset && if (zobj->ce->__unset &&
@ -646,6 +758,10 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter
guard->in_unset = 0; guard->in_unset = 0;
zval_ptr_dtor(&object); zval_ptr_dtor(&object);
} }
} else if (EXPECTED(property_info != NULL) &&
EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
property_info->offset >= 0) {
zobj->properties_table[property_info->offset] = NULL;
} }
if (UNEXPECTED(tmp_member != NULL)) { if (UNEXPECTED(tmp_member != NULL)) {
@ -1049,50 +1165,50 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent, const zend_literal *key TSRMLS_DC) /* {{{ */ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent, const zend_literal *key TSRMLS_DC) /* {{{ */
{ {
zval **retval = NULL;
zend_class_entry *tmp_ce = ce;
zend_property_info *property_info; zend_property_info *property_info;
zend_property_info std_property_info;
ulong hash_value; ulong hash_value;
if (EXPECTED(key != NULL)) { if (UNEXPECTED(!key) ||
hash_value = key->hash_value; (property_info = CACHED_POLYMORPHIC_PTR(key->cache_slot, ce)) == NULL) {
} else { if (EXPECTED(key != NULL)) {
hash_value = zend_hash_func(property_name, property_name_len+1); hash_value = key->hash_value;
} } else {
hash_value = zend_hash_func(property_name, property_name_len+1);
}
if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+1, hash_value, (void **) &property_info)==FAILURE)) { if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+1, hash_value, (void **) &property_info)==FAILURE)) {
std_property_info.flags = ZEND_ACC_PUBLIC; if (!silent) {
std_property_info.name = property_name; zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
std_property_info.name_length = property_name_len; }
std_property_info.h = hash_value; return NULL;
std_property_info.ce = ce; }
property_info = &std_property_info;
}
#if DEBUG_OBJECT_HANDLERS #if DEBUG_OBJECT_HANDLERS
zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags)); zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
#endif #endif
if (UNEXPECTED(!zend_verify_property_access(property_info, ce TSRMLS_CC))) { if (UNEXPECTED(!zend_verify_property_access(property_info, ce TSRMLS_CC))) {
if (!silent) { if (!silent) {
zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name); zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
}
return NULL;
}
if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
if (!silent) {
zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
}
return NULL;
}
zend_update_class_constants(ce TSRMLS_CC);
if (EXPECTED(key != NULL)) {
CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
} }
return NULL;
} }
zend_update_class_constants(tmp_ce TSRMLS_CC); return &CE_STATIC_MEMBERS(ce)[property_info->offset];
zend_hash_quick_find(CE_STATIC_MEMBERS(tmp_ce), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
if (UNEXPECTED(!retval)) {
if (!silent) {
zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
}
return NULL;
}
return retval;
} }
/* }}} */ /* }}} */
@ -1152,7 +1268,40 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
if (zobj1->ce != zobj2->ce) { if (zobj1->ce != zobj2->ce) {
return 1; /* different classes */ return 1; /* different classes */
} }
return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC); if (!zobj1->properties && !zobj2->properties) {
int i;
for (i = 0; i < zobj1->ce->default_properties_count; i++) {
if (zobj1->properties_table[i]) {
if (zobj2->properties_table[i]) {
zval result;
if (compare_function(&result, zobj1->properties_table[i], zobj2->properties_table[i] TSRMLS_CC)==FAILURE) {
return 1;
}
if (Z_LVAL(result) != 0) {
return Z_LVAL(result);
}
} else {
return 1;
}
} else {
if (zobj2->properties_table[i]) {
return 1;
} else {
return 0;
}
}
}
return 0;
} else {
if (!zobj1->properties) {
rebuild_object_properties(zobj1);
}
if (!zobj2->properties) {
rebuild_object_properties(zobj2);
}
return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC);
}
} }
/* }}} */ /* }}} */
@ -1160,7 +1309,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
{ {
zend_object *zobj; zend_object *zobj;
int result; int result;
zval **value; zval **value = NULL;
zval *tmp_member = NULL; zval *tmp_member = NULL;
zend_property_info *property_info; zend_property_info *property_info;
@ -1183,7 +1332,13 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
property_info = zend_get_property_info_quick(zobj->ce, member, 1, key TSRMLS_CC); property_info = zend_get_property_info_quick(zobj->ce, member, 1, key TSRMLS_CC);
if (UNEXPECTED(!property_info) || if (UNEXPECTED(!property_info) ||
zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) { ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
property_info->offset >= 0) ?
(zobj->properties ?
((value = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
(*(value = &zobj->properties_table[property_info->offset]) == NULL)) :
(UNEXPECTED(!zobj->properties) ||
UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE)))) {
zend_guard *guard; zend_guard *guard;
result = 0; result = 0;

View file

@ -152,6 +152,8 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC); ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC);
ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC); ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC);
ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC); ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC);
ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC);
ZEND_API void rebuild_object_properties(zend_object *zobj);
#define IS_ZEND_STD_OBJECT(z) (Z_TYPE(z) == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL)) #define IS_ZEND_STD_OBJECT(z) (Z_TYPE(z) == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL))

View file

@ -28,10 +28,9 @@
ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSRMLS_DC) ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSRMLS_DC)
{ {
ALLOC_HASHTABLE(object->properties);
zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
object->ce = ce; object->ce = ce;
object->properties = NULL;
object->properties_table = NULL;
object->guards = NULL; object->guards = NULL;
} }
@ -44,6 +43,18 @@ ZEND_API void zend_object_std_dtor(zend_object *object TSRMLS_DC)
if (object->properties) { if (object->properties) {
zend_hash_destroy(object->properties); zend_hash_destroy(object->properties);
FREE_HASHTABLE(object->properties); FREE_HASHTABLE(object->properties);
if (object->properties_table) {
efree(object->properties_table);
}
} else if (object->properties_table) {
int i;
for (i = 0; i < object->ce->default_properties_count; i++) {
if (object->properties_table[i]) {
zval_ptr_dtor(&object->properties_table[i]);
}
}
efree(object->properties_table);
} }
} }
@ -135,9 +146,11 @@ ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_ent
*object = emalloc(sizeof(zend_object)); *object = emalloc(sizeof(zend_object));
(*object)->ce = class_type; (*object)->ce = class_type;
(*object)->properties = NULL;
(*object)->properties_table = NULL;
(*object)->guards = NULL;
retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
retval.handlers = &std_object_handlers; retval.handlers = &std_object_handlers;
(*object)->guards = NULL;
return retval; return retval;
} }
@ -148,7 +161,47 @@ ZEND_API zend_object *zend_objects_get_address(const zval *zobject TSRMLS_DC)
ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC) ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC)
{ {
zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); int i;
if (old_object->properties_table) {
if (!new_object->properties_table) {
new_object->properties_table = emalloc(sizeof(zval*) * old_object->ce->default_properties_count);
memset(new_object->properties_table, 0, sizeof(zval*) * old_object->ce->default_properties_count);
}
for (i = 0; i < old_object->ce->default_properties_count; i++) {
if (!new_object->properties) {
if (new_object->properties_table[i]) {
zval_ptr_dtor(&new_object->properties_table[i]);
}
}
if (!old_object->properties) {
new_object->properties_table[i] = old_object->properties_table[i];
if (new_object->properties_table[i]) {
Z_ADDREF_P(new_object->properties_table[i]);
}
}
}
}
if (old_object->properties) {
if (!new_object->properties) {
ALLOC_HASHTABLE(new_object->properties);
zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
}
zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
if (old_object->properties_table) {
HashPosition pos;
zend_property_info *prop_info;
for (zend_hash_internal_pointer_reset_ex(&old_object->ce->properties_info, &pos);
zend_hash_get_current_data_ex(&old_object->ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
zend_hash_move_forward_ex(&old_object->ce->properties_info, &pos)) {
if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
if (zend_hash_quick_find(new_object->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&new_object->properties_table[prop_info->offset]) == FAILURE) {
new_object->properties_table[prop_info->offset] = NULL;
}
}
}
}
}
if (old_object->ce->clone) { if (old_object->ce->clone) {
zval *new_obj; zval *new_obj;
@ -176,9 +229,6 @@ ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC)
old_object = zend_objects_get_address(zobject TSRMLS_CC); old_object = zend_objects_get_address(zobject TSRMLS_CC);
new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC); new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC);
ALLOC_HASHTABLE(new_object->properties);
zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
return new_obj_val; return new_obj_val;

View file

@ -107,6 +107,9 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->last_literal = 0; op_array->last_literal = 0;
op_array->literals = NULL; op_array->literals = NULL;
op_array->run_time_cache = NULL;
op_array->last_cache_slot = 0;
memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*)); memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC); zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);
@ -163,14 +166,18 @@ ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)
/* Note that only run-time accessed data need to be cleaned up, pre-defined data can /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
not contain objects and thus are not probelmatic */ not contain objects and thus are not probelmatic */
zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC); zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
(*pce)->static_members = NULL; (*pce)->static_members_table = NULL;
} else if (CE_STATIC_MEMBERS(*pce)) { } else if (CE_STATIC_MEMBERS(*pce)) {
zend_hash_destroy(CE_STATIC_MEMBERS(*pce)); int i;
FREE_HASHTABLE(CE_STATIC_MEMBERS(*pce));
for (i = 0; i < (*pce)->default_static_members_count; i++) {
zval_ptr_dtor(&CE_STATIC_MEMBERS(*pce)[i]);
}
efree(CE_STATIC_MEMBERS(*pce));
#ifdef ZTS #ifdef ZTS
CG(static_members)[(zend_intptr_t)((*pce)->static_members)] = NULL; CG(static_members)[(zend_intptr_t)((*pce)->static_members)] = NULL;
#else #else
(*pce)->static_members = NULL; (*pce)->static_members_table = NULL;
#endif #endif
} }
return 0; return 0;
@ -234,9 +241,25 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
} }
switch (ce->type) { switch (ce->type) {
case ZEND_USER_CLASS: case ZEND_USER_CLASS:
zend_hash_destroy(&ce->default_properties); if (ce->default_properties_table) {
int i;
for (i = 0; i < ce->default_properties_count; i++) {
if (ce->default_properties_table[i]) {
zval_ptr_dtor(&ce->default_properties_table[i]);
}
}
efree(ce->default_properties_table);
}
if (ce->default_static_members_table) {
int i;
for (i = 0; i < ce->default_static_members_count; i++) {
zval_ptr_dtor(&ce->default_static_members_table[i]);
}
efree(ce->default_static_members_table);
}
zend_hash_destroy(&ce->properties_info); zend_hash_destroy(&ce->properties_info);
zend_hash_destroy(&ce->default_static_members);
efree(ce->name); efree(ce->name);
zend_hash_destroy(&ce->function_table); zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->constants_table); zend_hash_destroy(&ce->constants_table);
@ -252,9 +275,25 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
efree(ce); efree(ce);
break; break;
case ZEND_INTERNAL_CLASS: case ZEND_INTERNAL_CLASS:
zend_hash_destroy(&ce->default_properties); if (ce->default_properties_table) {
int i;
for (i = 0; i < ce->default_properties_count; i++) {
if (ce->default_properties_table[i]) {
zval_internal_ptr_dtor(&ce->default_properties_table[i]);
}
}
free(ce->default_properties_table);
}
if (ce->default_static_members_table) {
int i;
for (i = 0; i < ce->default_static_members_count; i++) {
zval_internal_ptr_dtor(&ce->default_static_members_table[i]);
}
free(ce->default_static_members_table);
}
zend_hash_destroy(&ce->properties_info); zend_hash_destroy(&ce->properties_info);
zend_hash_destroy(&ce->default_static_members);
free(ce->name); free(ce->name);
zend_hash_destroy(&ce->function_table); zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->constants_table); zend_hash_destroy(&ce->constants_table);
@ -285,6 +324,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
FREE_HASHTABLE(op_array->static_variables); FREE_HASHTABLE(op_array->static_variables);
} }
if (op_array->run_time_cache) {
efree(op_array->run_time_cache);
}
if (--(*op_array->refcount)>0) { if (--(*op_array->refcount)>0) {
return; return;
} }

View file

@ -1035,7 +1035,12 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
zend_class_entry *ce; zend_class_entry *ce;
if (OP2_TYPE == IS_CONST) { if (OP2_TYPE == IS_CONST) {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC); if (CACHED_PTR(opline->op2.literal->cache_slot)) {
ce = CACHED_PTR(opline->op2.literal->cache_slot);
} else {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
CACHE_PTR(opline->op2.literal->cache_slot, ce);
}
} else { } else {
ce = EX_T(opline->op2.var).class_entry; ce = EX_T(opline->op2.var).class_entry;
} }
@ -2145,7 +2150,12 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV)
zval *class_name = GET_OP2_ZVAL_PTR(BP_VAR_R); zval *class_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (OP2_TYPE == IS_CONST) { if (OP2_TYPE == IS_CONST) {
EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC); if (CACHED_PTR(opline->op2.literal->cache_slot)) {
EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
} else {
EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
}
} else if (Z_TYPE_P(class_name) == IS_OBJECT) { } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name); EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
} else if (Z_TYPE_P(class_name) == IS_STRING) { } else if (Z_TYPE_P(class_name) == IS_STRING) {
@ -2185,17 +2195,27 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
if (EXPECTED(EX(object) != NULL) && if (EXPECTED(EX(object) != NULL) &&
EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object)); EX(called_scope) = Z_OBJCE_P(EX(object));
if (OP2_TYPE != IS_CONST ||
(EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
zval *object = EX(object);
if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
}
if (OP2_TYPE == IS_CONST &&
EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
EXPECTED(EX(object) == object)) {
CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
}
}
} else { } else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
} }
@ -2232,21 +2252,35 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
if (OP1_TYPE == IS_CONST) { if (OP1_TYPE == IS_CONST) {
/* no function found. try a static method in class */ /* no function found. try a static method in class */
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC); if (CACHED_PTR(opline->op1.literal->cache_slot)) {
if (UNEXPECTED(ce == NULL)) { ce = CACHED_PTR(opline->op1.literal->cache_slot);
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv)); } else {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
}
CACHE_PTR(opline->op1.literal->cache_slot, ce);
} }
EX(called_scope) = ce; EX(called_scope) = ce;
} else { } else {
ce = EX_T(opline->op1.var).class_entry; ce = EX_T(opline->op1.var).class_entry;
if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope); EX(called_scope) = EG(called_scope);
} else { } else {
EX(called_scope) = ce; EX(called_scope) = ce;
} }
} }
if(OP2_TYPE != IS_UNUSED) {
if (OP1_TYPE == IS_CONST &&
OP2_TYPE == IS_CONST &&
CACHED_PTR(opline->op2.literal->cache_slot)) {
EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
} else if (OP1_TYPE != IS_CONST &&
OP2_TYPE == IS_CONST &&
(EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
/* do nothing */
} else if (OP2_TYPE != IS_UNUSED) {
char *function_name_strval = NULL; char *function_name_strval = NULL;
int function_name_strlen = 0; int function_name_strlen = 0;
zend_free_op free_op2; zend_free_op free_op2;
@ -2274,8 +2308,14 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
if (UNEXPECTED(EX(fbc) == NULL)) { if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
} }
if (OP2_TYPE == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
if (OP1_TYPE == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
} else {
CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
}
}
} }
if (OP2_TYPE != IS_CONST) { if (OP2_TYPE != IS_CONST) {
FREE_OP2(); FREE_OP2();
} }
@ -2322,9 +2362,13 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
if (OP2_TYPE == IS_CONST) { if (OP2_TYPE == IS_CONST) {
function_name = (zval*)(opline->op2.literal+1); function_name = (zval*)(opline->op2.literal+1);
if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { if (CACHED_PTR(opline->op2.literal->cache_slot)) {
EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
} else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
SAVE_OPLINE(); SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
} }
EX(object) = NULL; EX(object) = NULL;
/*CHECK_EXCEPTION();*/ /*CHECK_EXCEPTION();*/
@ -2379,12 +2423,18 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
func_name = opline->op2.literal + 1; func_name = opline->op2.literal + 1;
if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) { if (CACHED_PTR(opline->op2.literal->cache_slot)) {
EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
} else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
func_name++; func_name++;
if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) { if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) {
SAVE_OPLINE(); SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
} }
} else {
CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
} }
EX(object) = NULL; EX(object) = NULL;
@ -2694,9 +2744,13 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) { if (CACHED_PTR(opline->op1.literal->cache_slot)) {
EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot);
} else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) {
SAVE_OPLINE(); SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
} else {
CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function);
} }
EX(object) = NULL; EX(object) = NULL;
@ -2849,7 +2903,12 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */ ZEND_VM_CONTINUE(); /* CHECK_ME */
} }
catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC); if (CACHED_PTR(opline->op1.literal->cache_slot)) {
catch_ce = CACHED_PTR(opline->op1.literal->cache_slot);
} else {
catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
CACHE_PTR(opline->op1.literal->cache_slot, catch_ce);
}
ce = Z_OBJCE_P(EG(exception)); ce = Z_OBJCE_P(EG(exception));
#ifdef HAVE_DTRACE #ifdef HAVE_DTRACE
@ -3339,7 +3398,9 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
zend_constant *c; zend_constant *c;
zval *retval; zval *retval;
if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) { if (CACHED_PTR(opline->op2.literal->cache_slot)) {
c = CACHED_PTR(opline->op2.literal->cache_slot);
} else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
if(!actual) { if(!actual) {
@ -3355,6 +3416,8 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
} else { } else {
zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv)); zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
} }
} else {
CACHE_PTR(opline->op2.literal->cache_slot, c);
} }
retval = &EX_T(opline->result.var).tmp_var; retval = &EX_T(opline->result.var).tmp_var;
INIT_PZVAL_COPY(retval, &c->value); INIT_PZVAL_COPY(retval, &c->value);
@ -3367,13 +3430,29 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
zval **value; zval **value;
if (OP1_TYPE == IS_CONST) { if (OP1_TYPE == IS_CONST) {
if (CACHED_PTR(opline->op2.literal->cache_slot)) {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC); value = CACHED_PTR(opline->op2.literal->cache_slot);
if (UNEXPECTED(ce == NULL)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv)); zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
ce = CACHED_PTR(opline->op1.literal->cache_slot);
} else {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
if (UNEXPECTED(ce == NULL)) {
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
CACHE_PTR(opline->op1.literal->cache_slot, ce);
} }
} else { } else {
ce = EX_T(opline->op1.var).class_entry; ce = EX_T(opline->op1.var).class_entry;
if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
} }
if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) { if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
@ -3385,6 +3464,11 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
zval_update_constant(value, (void *) 1 TSRMLS_CC); zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope; EG(scope) = old_scope;
} }
if (OP1_TYPE == IS_CONST) {
CACHE_PTR(opline->op2.literal->cache_slot, value);
} else {
CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
}
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value); ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
zval_copy_ctor(&EX_T(opline->result.var).tmp_var); zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
} else { } else {
@ -3727,7 +3811,12 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
zend_class_entry *ce; zend_class_entry *ce;
if (OP2_TYPE == IS_CONST) { if (OP2_TYPE == IS_CONST) {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC); if (CACHED_PTR(opline->op2.literal->cache_slot)) {
ce = CACHED_PTR(opline->op2.literal->cache_slot);
} else {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
CACHE_PTR(opline->op2.literal->cache_slot, ce);
}
} else { } else {
ce = EX_T(opline->op2.var).class_entry; ce = EX_T(opline->op2.var).class_entry;
} }
@ -4227,7 +4316,12 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
zend_class_entry *ce; zend_class_entry *ce;
if (OP2_TYPE == IS_CONST) { if (OP2_TYPE == IS_CONST) {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC); if (CACHED_PTR(opline->op2.literal->cache_slot)) {
ce = CACHED_PTR(opline->op2.literal->cache_slot);
} else {
ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
CACHE_PTR(opline->op2.literal->cache_slot, ce);
}
} else { } else {
ce = EX_T(opline->op2.var).class_entry; ce = EX_T(opline->op2.var).class_entry;
} }
@ -4654,15 +4748,22 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST)
zend_class_entry *iface; zend_class_entry *iface;
SAVE_OPLINE(); SAVE_OPLINE();
iface = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, opline->extended_value TSRMLS_CC); if (CACHED_PTR(opline->op2.literal->cache_slot)) {
iface = CACHED_PTR(opline->op2.literal->cache_slot);
if (iface) { } else {
if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) { iface = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name); if (UNEXPECTED(iface == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} }
zend_do_implement_interface(ce, iface TSRMLS_CC); CACHE_PTR(opline->op2.literal->cache_slot, ce);
} }
if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
}
zend_do_implement_interface(ce, iface TSRMLS_CC);
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();
} }
@ -4671,18 +4772,27 @@ ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY)
{ {
zend_op *opline = EX(opline); zend_op *opline = EX(opline);
zend_class_entry *ce = EX_T(opline->op1.var).class_entry; zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
zend_class_entry *trait = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), zend_class_entry *trait;
Z_STRLEN_P(opline->op2.zv),
opline->op2.literal + 1, if (CACHED_PTR(opline->op2.literal->cache_slot)) {
opline->extended_value TSRMLS_CC); trait = CACHED_PTR(opline->op2.literal->cache_slot);
} else {
if (trait) { trait = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv),
Z_STRLEN_P(opline->op2.zv),
opline->op2.literal + 1,
opline->extended_value TSRMLS_CC);
if (UNEXPECTED(trait == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
if (!((trait->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)) { if (!((trait->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)) {
zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name, trait->name); zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name, trait->name);
} }
zend_do_implement_trait(ce, trait TSRMLS_CC); CACHE_PTR(opline->op2.literal->cache_slot, trait);
} }
zend_do_implement_trait(ce, trait TSRMLS_CC);
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();
} }

File diff suppressed because it is too large Load diff

View file

@ -39,6 +39,10 @@ zend_vm_enter:
LOAD_REGS(); LOAD_REGS();
if (!op_array->run_time_cache && op_array->last_cache_slot) {
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
}
if (op_array->this_var != -1 && EG(This)) { if (op_array->this_var != -1 && EG(This)) {
Z_ADDREF_P(EG(This)); /* For $this pointer */ Z_ADDREF_P(EG(This)); /* For $this pointer */
if (!EG(active_symbol_table)) { if (!EG(active_symbol_table)) {

View file

@ -2011,7 +2011,6 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_
{ {
php_date_obj *intern; php_date_obj *intern;
zend_object_value retval; zend_object_value retval;
zval *tmp;
intern = emalloc(sizeof(php_date_obj)); intern = emalloc(sizeof(php_date_obj));
memset(intern, 0, sizeof(php_date_obj)); memset(intern, 0, sizeof(php_date_obj));
@ -2020,7 +2019,7 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_
} }
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC);
retval.handlers = &date_object_handlers_date; retval.handlers = &date_object_handlers_date;
@ -2084,7 +2083,7 @@ static HashTable *date_object_get_properties(zval *object TSRMLS_DC)
dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC);
props = dateobj->std.properties; props = zend_std_get_properties(object TSRMLS_CC);
if (!dateobj->time || GC_G(gc_active)) { if (!dateobj->time || GC_G(gc_active)) {
return props; return props;
@ -2132,7 +2131,6 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl
{ {
php_timezone_obj *intern; php_timezone_obj *intern;
zend_object_value retval; zend_object_value retval;
zval *tmp;
intern = emalloc(sizeof(php_timezone_obj)); intern = emalloc(sizeof(php_timezone_obj));
memset(intern, 0, sizeof(php_timezone_obj)); memset(intern, 0, sizeof(php_timezone_obj));
@ -2141,7 +2139,7 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl
} }
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC);
retval.handlers = &date_object_handlers_timezone; retval.handlers = &date_object_handlers_timezone;
@ -2184,7 +2182,6 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl
{ {
php_interval_obj *intern; php_interval_obj *intern;
zend_object_value retval; zend_object_value retval;
zval *tmp;
intern = emalloc(sizeof(php_interval_obj)); intern = emalloc(sizeof(php_interval_obj));
memset(intern, 0, sizeof(php_interval_obj)); memset(intern, 0, sizeof(php_interval_obj));
@ -2193,7 +2190,7 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl
} }
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC);
retval.handlers = &date_object_handlers_interval; retval.handlers = &date_object_handlers_interval;
@ -2227,7 +2224,7 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
intervalobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC); intervalobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC);
props = intervalobj->std.properties; props = zend_std_get_properties(object TSRMLS_CC);
if (!intervalobj->initialized || GC_G(gc_active)) { if (!intervalobj->initialized || GC_G(gc_active)) {
return props; return props;
@ -2260,7 +2257,6 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas
{ {
php_period_obj *intern; php_period_obj *intern;
zend_object_value retval; zend_object_value retval;
zval *tmp;
intern = emalloc(sizeof(php_period_obj)); intern = emalloc(sizeof(php_period_obj));
memset(intern, 0, sizeof(php_period_obj)); memset(intern, 0, sizeof(php_period_obj));
@ -2269,7 +2265,7 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas
} }
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC);
retval.handlers = &date_object_handlers_period; retval.handlers = &date_object_handlers_period;

View file

@ -1053,7 +1053,6 @@ 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 TSRMLS_DC) /* {{{ */ static dom_object* dom_objects_set_class(zend_class_entry *class_type, zend_bool hash_copy TSRMLS_DC) /* {{{ */
{ {
zend_class_entry *base_class; zend_class_entry *base_class;
zval *tmp;
dom_object *intern; dom_object *intern;
if (instanceof_function(class_type, dom_xpath_class_entry TSRMLS_CC)) { if (instanceof_function(class_type, dom_xpath_class_entry TSRMLS_CC)) {
@ -1075,7 +1074,7 @@ static dom_object* dom_objects_set_class(zend_class_entry *class_type, zend_bool
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
if (hash_copy) { if (hash_copy) {
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
} }
return intern; return intern;

View file

@ -98,13 +98,12 @@ PHP_FILEINFO_API zend_object_value finfo_objects_new(zend_class_entry *class_typ
{ {
zend_object_value retval; zend_object_value retval;
struct finfo_object *intern; struct finfo_object *intern;
zval *tmp;
intern = emalloc(sizeof(struct finfo_object)); intern = emalloc(sizeof(struct finfo_object));
memset(intern, 0, sizeof(struct finfo_object)); memset(intern, 0, sizeof(struct finfo_object));
zend_object_std_init(&intern->zo, class_type TSRMLS_CC); zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *)); object_properties_init(&intern->zo, class_type);
intern->ptr = NULL; intern->ptr = NULL;

View file

@ -484,7 +484,6 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
{ {
zend_object_value retval; zend_object_value retval;
mysqli_object *intern; mysqli_object *intern;
zval *tmp;
zend_class_entry *mysqli_base_class; zend_class_entry *mysqli_base_class;
zend_objects_free_object_storage_t free_storage; zend_objects_free_object_storage_t free_storage;
@ -502,8 +501,7 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
(void **) &intern->prop_handler); (void **) &intern->prop_handler);
zend_object_std_init(&intern->zo, class_type TSRMLS_CC); zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, object_properties_init(&intern->zo, class_type);
(void *) &tmp, sizeof(zval *));
/* link object */ /* link object */
if (instanceof_function(class_type, mysqli_link_class_entry TSRMLS_CC)) { if (instanceof_function(class_type, mysqli_link_class_entry TSRMLS_CC)) {

View file

@ -1552,12 +1552,12 @@ zend_object_value pdo_dbh_new(zend_class_entry *ce TSRMLS_DC)
{ {
zend_object_value retval; zend_object_value retval;
pdo_dbh_t *dbh; pdo_dbh_t *dbh;
zval *tmp;
dbh = emalloc(sizeof(*dbh)); dbh = emalloc(sizeof(*dbh));
memset(dbh, 0, sizeof(*dbh)); memset(dbh, 0, sizeof(*dbh));
zend_object_std_init(&dbh->std, ce TSRMLS_CC); zend_object_std_init(&dbh->std, ce TSRMLS_CC);
zend_hash_copy(dbh->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&dbh->std, ce);
rebuild_object_properties(&dbh->std);
dbh->refcount = 1; dbh->refcount = 1;
dbh->def_stmt_ce = pdo_dbstmt_ce; dbh->def_stmt_ce = pdo_dbstmt_ce;

View file

@ -2313,14 +2313,13 @@ static int dbstmt_compare(zval *object1, zval *object2 TSRMLS_DC)
static zend_object_value dbstmt_clone_obj(zval *zobject TSRMLS_DC) static zend_object_value dbstmt_clone_obj(zval *zobject TSRMLS_DC)
{ {
zend_object_value retval; zend_object_value retval;
zval *tmp;
pdo_stmt_t *stmt; pdo_stmt_t *stmt;
pdo_stmt_t *old_stmt; pdo_stmt_t *old_stmt;
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
stmt = ecalloc(1, sizeof(*stmt)); stmt = ecalloc(1, sizeof(*stmt));
zend_object_std_init(&stmt->std, Z_OBJCE_P(zobject) TSRMLS_CC); zend_object_std_init(&stmt->std, Z_OBJCE_P(zobject) TSRMLS_CC);
zend_hash_copy(stmt->std.properties, &stmt->std.ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&stmt->std, Z_OBJCE_P(zobject));
stmt->refcount = 1; stmt->refcount = 1;
old_stmt = (pdo_stmt_t *)zend_object_store_get_object(zobject TSRMLS_CC); old_stmt = (pdo_stmt_t *)zend_object_store_get_object(zobject TSRMLS_CC);
@ -2436,13 +2435,12 @@ void pdo_dbstmt_free_storage(pdo_stmt_t *stmt TSRMLS_DC)
zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC) zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC)
{ {
zend_object_value retval; zend_object_value retval;
zval *tmp;
pdo_stmt_t *stmt; pdo_stmt_t *stmt;
stmt = emalloc(sizeof(*stmt)); stmt = emalloc(sizeof(*stmt));
memset(stmt, 0, sizeof(*stmt)); memset(stmt, 0, sizeof(*stmt));
zend_object_std_init(&stmt->std, ce TSRMLS_CC); zend_object_std_init(&stmt->std, ce TSRMLS_CC);
zend_hash_copy(stmt->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&stmt->std, ce);
stmt->refcount = 1; stmt->refcount = 1;
retval.handle = zend_objects_store_put(stmt, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_dbstmt_free_storage, (zend_objects_store_clone_t)dbstmt_clone_obj TSRMLS_CC); retval.handle = zend_objects_store_put(stmt, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_dbstmt_free_storage, (zend_objects_store_clone_t)dbstmt_clone_obj TSRMLS_CC);
@ -2680,6 +2678,9 @@ static HashTable *row_get_properties(zval *object TSRMLS_DC)
return NULL; return NULL;
} }
if (!stmt->std.properties) {
rebuild_object_properties(&stmt->std);
}
for (i = 0; i < stmt->column_count; i++) { for (i = 0; i < stmt->column_count; i++) {
zval *val; zval *val;
MAKE_STD_ZVAL(val); MAKE_STD_ZVAL(val);

View file

@ -41,6 +41,15 @@
#include "zend_closures.h" #include "zend_closures.h"
#include "zend_extensions.h" #include "zend_extensions.h"
#define reflection_update_property(object, name, value) do { \
zval *member; \
MAKE_STD_ZVAL(member); \
ZVAL_STRINGL(member, name, sizeof(name)-1, 1); \
zend_std_write_property(object, member, value, NULL TSRMLS_CC); \
Z_DELREF_P(value); \
zval_ptr_dtor(&member); \
} while (0)
/* Class entry pointers */ /* Class entry pointers */
PHPAPI zend_class_entry *reflector_ptr; PHPAPI zend_class_entry *reflector_ptr;
PHPAPI zend_class_entry *reflection_exception_ptr; PHPAPI zend_class_entry *reflection_exception_ptr;
@ -296,7 +305,6 @@ static void reflection_free_objects_storage(void *object TSRMLS_DC)
static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC) static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC)
{ {
zval tmp;
zend_object_value retval; zend_object_value retval;
reflection_object *intern; reflection_object *intern;
@ -304,7 +312,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
intern->zo.ce = class_type; intern->zo.ce = class_type;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC); zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC);
retval.handlers = &reflection_object_handlers; retval.handlers = &reflection_object_handlers;
return retval; return retval;
@ -1157,7 +1165,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSR
intern->ptr = ce; intern->ptr = ce;
intern->ref_type = REF_TYPE_OTHER; intern->ref_type = REF_TYPE_OTHER;
intern->ce = ce; intern->ce = ce;
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
} }
/* }}} */ /* }}} */
@ -1186,7 +1194,7 @@ static void reflection_extension_factory(zval *object, const char *name_str TSRM
intern->ptr = module; intern->ptr = module;
intern->ref_type = REF_TYPE_OTHER; intern->ref_type = REF_TYPE_OTHER;
intern->ce = NULL; intern->ce = NULL;
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
} }
/* }}} */ /* }}} */
@ -1217,7 +1225,7 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje
intern->ref_type = REF_TYPE_PARAMETER; intern->ref_type = REF_TYPE_PARAMETER;
intern->ce = fptr->common.scope; intern->ce = fptr->common.scope;
intern->obj = closure_object; intern->obj = closure_object;
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
} }
/* }}} */ /* }}} */
@ -1239,7 +1247,7 @@ static void reflection_function_factory(zend_function *function, zval *closure_o
intern->ref_type = REF_TYPE_FUNCTION; intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = NULL; intern->ce = NULL;
intern->obj = closure_object; intern->obj = closure_object;
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
} }
/* }}} */ /* }}} */
@ -1263,8 +1271,8 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
intern->ref_type = REF_TYPE_FUNCTION; intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = ce; intern->ce = ce;
intern->obj = closure_object; intern->obj = closure_object;
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); reflection_update_property(object, "class", classname);
} }
/* }}} */ /* }}} */
@ -1310,8 +1318,8 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
intern->ref_type = REF_TYPE_PROPERTY; intern->ref_type = REF_TYPE_PROPERTY;
intern->ce = ce; intern->ce = ce;
intern->ignore_visibility = 0; intern->ignore_visibility = 0;
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); reflection_update_property(object, "class", classname);
} }
/* }}} */ /* }}} */
@ -1556,7 +1564,7 @@ ZEND_METHOD(reflection_function, __construct)
MAKE_STD_ZVAL(name); MAKE_STD_ZVAL(name);
ZVAL_STRING(name, fptr->common.function_name, 1); ZVAL_STRING(name, fptr->common.function_name, 1);
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name TSRMLS_CC);
intern->ptr = fptr; intern->ptr = fptr;
intern->ref_type = REF_TYPE_FUNCTION; intern->ref_type = REF_TYPE_FUNCTION;
intern->obj = closure; intern->obj = closure;
@ -2185,7 +2193,7 @@ ZEND_METHOD(reflection_parameter, __construct)
} else { } else {
ZVAL_NULL(name); ZVAL_NULL(name);
} }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
ref = (parameter_reference*) emalloc(sizeof(parameter_reference)); ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
ref->arg_info = &arg_info[position]; ref->arg_info = &arg_info[position];
@ -2663,11 +2671,11 @@ ZEND_METHOD(reflection_method, __construct)
MAKE_STD_ZVAL(classname); MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, mptr->common.scope->name, mptr->common.scope->name_length, 1); ZVAL_STRINGL(classname, mptr->common.scope->name, mptr->common.scope->name_length, 1);
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); reflection_update_property(object, "class", classname);
MAKE_STD_ZVAL(name); MAKE_STD_ZVAL(name);
ZVAL_STRING(name, mptr->common.function_name, 1); ZVAL_STRING(name, mptr->common.function_name, 1);
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
intern->ptr = mptr; intern->ptr = mptr;
intern->ref_type = REF_TYPE_FUNCTION; intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = ce; intern->ce = ce;
@ -3202,7 +3210,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
if (Z_TYPE_P(argument) == IS_OBJECT) { if (Z_TYPE_P(argument) == IS_OBJECT) {
MAKE_STD_ZVAL(classname); MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1); ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL); reflection_update_property(object, "name", classname);
intern->ptr = Z_OBJCE_P(argument); intern->ptr = Z_OBJCE_P(argument);
if (is_object) { if (is_object) {
intern->obj = argument; intern->obj = argument;
@ -3219,7 +3227,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
MAKE_STD_ZVAL(classname); MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1); ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL); reflection_update_property(object, "name", classname);
intern->ptr = *ce; intern->ptr = *ce;
} }
@ -3235,14 +3243,63 @@ ZEND_METHOD(reflection_class, __construct)
} }
/* }}} */ /* }}} */
/* {{{ add_class_vars */
static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC)
{
HashPosition pos;
zend_property_info *prop_info;
zval *prop, *prop_copy;
char *key;
uint key_len;
ulong num_index;
zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) {
zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos);
zend_hash_move_forward_ex(&ce->properties_info, &pos);
if (((prop_info->flags & ZEND_ACC_SHADOW) &&
prop_info->ce != ce) ||
((prop_info->flags & ZEND_ACC_PROTECTED) &&
!zend_check_protected(prop_info->ce, ce)) ||
((prop_info->flags & ZEND_ACC_PRIVATE) &&
prop_info->ce != ce)) {
continue;
}
prop = NULL;
if (prop_info->offset >= 0) {
if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
prop = ce->default_static_members_table[prop_info->offset];
} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
prop = ce->default_properties_table[prop_info->offset];
}
}
if (!prop) {
continue;
}
/* copy: enforce read only access */
ALLOC_ZVAL(prop_copy);
*prop_copy = *prop;
zval_copy_ctor(prop_copy);
INIT_PZVAL(prop_copy);
/* this is necessary to make it able to work with default array
* properties, returned to user */
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zval_update_constant(&prop_copy, 1 TSRMLS_CC);
}
add_assoc_zval(return_value, key, prop_copy);
}
}
/* }}} */
/* {{{ proto public array ReflectionClass::getStaticProperties() /* {{{ proto public array ReflectionClass::getStaticProperties()
Returns an associative array containing all static property values of the class */ Returns an associative array containing all static property values of the class */
ZEND_METHOD(reflection_class, getStaticProperties) ZEND_METHOD(reflection_class, getStaticProperties)
{ {
reflection_object *intern; reflection_object *intern;
zend_class_entry *ce; zend_class_entry *ce;
HashPosition pos;
zval **value;
if (zend_parse_parameters_none() == FAILURE) { if (zend_parse_parameters_none() == FAILURE) {
return; return;
@ -3253,31 +3310,7 @@ ZEND_METHOD(reflection_class, getStaticProperties)
zend_update_class_constants(ce TSRMLS_CC); zend_update_class_constants(ce TSRMLS_CC);
array_init(return_value); array_init(return_value);
add_class_vars(ce, 1, return_value TSRMLS_CC);
zend_hash_internal_pointer_reset_ex(CE_STATIC_MEMBERS(ce), &pos);
while (zend_hash_get_current_data_ex(CE_STATIC_MEMBERS(ce), (void **) &value, &pos) == SUCCESS) {
uint key_len;
char *key;
ulong num_index;
if (zend_hash_get_current_key_ex(CE_STATIC_MEMBERS(ce), &key, &key_len, &num_index, 0, &pos) != FAILURE && key) {
char *prop_name, *class_name;
zval *prop_copy;
zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
/* filter privates from base classes */
if (!(class_name && class_name[0] != '*' && strcmp(class_name, ce->name))) {
/* copy: enforce read only access */
ALLOC_ZVAL(prop_copy);
MAKE_COPY_ZVAL(value, prop_copy);
add_assoc_zval(return_value, prop_name, prop_copy);
}
}
zend_hash_move_forward_ex(CE_STATIC_MEMBERS(ce), &pos);
}
} }
/* }}} */ /* }}} */
@ -3355,51 +3388,15 @@ ZEND_METHOD(reflection_class, getDefaultProperties)
{ {
reflection_object *intern; reflection_object *intern;
zend_class_entry *ce; zend_class_entry *ce;
int count, i;
HashTable *ht_list[3];
if (zend_parse_parameters_none() == FAILURE) { if (zend_parse_parameters_none() == FAILURE) {
return; return;
} }
GET_REFLECTION_OBJECT_PTR(ce); GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value); array_init(return_value);
zend_update_class_constants(ce TSRMLS_CC); zend_update_class_constants(ce TSRMLS_CC);
add_class_vars(ce, 1, return_value TSRMLS_CC);
ht_list[0] = CE_STATIC_MEMBERS(ce); add_class_vars(ce, 0, return_value TSRMLS_CC);
ht_list[1] = &ce->default_properties;
ht_list[2] = NULL;
for (i = 0; ht_list[i] != NULL; i++) {
count = zend_hash_num_elements(ht_list[i]);
if (count > 0) {
HashPosition pos;
zval **prop;
zend_hash_internal_pointer_reset_ex(ht_list[i], &pos);
while (zend_hash_get_current_data_ex(ht_list[i], (void **) &prop, &pos) == SUCCESS) {
char *key, *class_name, *prop_name;
uint key_len;
ulong num_index;
zval *prop_copy;
zend_hash_get_current_key_ex(ht_list[i], &key, &key_len, &num_index, 0, &pos);
zend_hash_move_forward_ex(ht_list[i], &pos);
zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
if (class_name && class_name[0] != '*' && strcmp(class_name, ce->name)) {
/* filter privates from base classes */
continue;
}
/* copy: enforce read only access */
ALLOC_ZVAL(prop_copy);
MAKE_COPY_ZVAL(prop, prop_copy);
add_assoc_zval(return_value, prop_name, prop_copy);
}
}
}
} }
/* }}} */ /* }}} */
@ -4564,8 +4561,8 @@ ZEND_METHOD(reflection_property, __construct)
ZVAL_STRINGL(classname, ce->name, ce->name_length, 1); ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
ZVAL_STRINGL(propname, name_str, name_len, 1); ZVAL_STRINGL(propname, name_str, name_len, 1);
} }
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL); reflection_update_property(object, "class", classname);
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL); reflection_update_property(object, "name", propname);
reference = (property_reference*) emalloc(sizeof(property_reference)); reference = (property_reference*) emalloc(sizeof(property_reference));
if (dynam_prop) { if (dynam_prop) {
@ -4690,7 +4687,7 @@ ZEND_METHOD(reflection_property, getValue)
reflection_object *intern; reflection_object *intern;
property_reference *ref; property_reference *ref;
zval *object, name; zval *object, name;
zval **member = NULL, *member_p = NULL; zval *member_p = NULL;
METHOD_NOTSTATIC(reflection_property_ptr); METHOD_NOTSTATIC(reflection_property_ptr);
GET_REFLECTION_OBJECT_PTR(ref); GET_REFLECTION_OBJECT_PTR(ref);
@ -4705,11 +4702,13 @@ ZEND_METHOD(reflection_property, getValue)
if ((ref->prop.flags & ZEND_ACC_STATIC)) { if ((ref->prop.flags & ZEND_ACC_STATIC)) {
zend_update_class_constants(intern->ce TSRMLS_CC); zend_update_class_constants(intern->ce TSRMLS_CC);
if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &member) == FAILURE) { if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name); php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
/* Bails out */ /* Bails out */
} }
MAKE_COPY_ZVAL(member, return_value); *return_value= *CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
zval_copy_ctor(return_value);
INIT_PZVAL(return_value);
} else { } else {
char *class_name, *prop_name; char *class_name, *prop_name;
@ -4738,7 +4737,6 @@ ZEND_METHOD(reflection_property, setValue)
zval *value; zval *value;
int setter_done = 0; int setter_done = 0;
zval *tmp; zval *tmp;
HashTable *prop_table;
METHOD_NOTSTATIC(reflection_property_ptr); METHOD_NOTSTATIC(reflection_property_ptr);
GET_REFLECTION_OBJECT_PTR(ref); GET_REFLECTION_OBJECT_PTR(ref);
@ -4758,33 +4756,34 @@ ZEND_METHOD(reflection_property, setValue)
} }
} }
zend_update_class_constants(intern->ce TSRMLS_CC); zend_update_class_constants(intern->ce TSRMLS_CC);
prop_table = CE_STATIC_MEMBERS(intern->ce);
if (zend_hash_quick_find(prop_table, ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &variable_ptr) == FAILURE) { if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name); php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
/* Bails out */ /* Bails out */
} }
if (*variable_ptr == value) { variable_ptr = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
setter_done = 1; if (*variable_ptr != value) {
} else {
if (PZVAL_IS_REF(*variable_ptr)) { if (PZVAL_IS_REF(*variable_ptr)) {
zval_dtor(*variable_ptr); zval garbage = **variable_ptr; /* old value should be destroyed */
(*variable_ptr)->type = value->type;
/* To check: can't *variable_ptr be some system variable like error_zval here? */
Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value);
(*variable_ptr)->value = value->value; (*variable_ptr)->value = value->value;
if (Z_REFCOUNT_P(value) > 0) { if (Z_REFCOUNT_P(value) > 0) {
zval_copy_ctor(*variable_ptr); zval_copy_ctor(*variable_ptr);
} }
setter_done = 1; zval_dtor(&garbage);
} } else {
} zval *garbage = *variable_ptr;
if (!setter_done) {
zval **foo;
Z_ADDREF_P(value); /* if we assign referenced variable, we should separate it */
if (PZVAL_IS_REF(value)) { Z_ADDREF_P(value);
SEPARATE_ZVAL(&value); if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value);
}
*variable_ptr = value;
zval_ptr_dtor(&garbage);
} }
zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo);
} }
} else { } else {
char *class_name, *prop_name; char *class_name, *prop_name;
@ -4917,7 +4916,7 @@ ZEND_METHOD(reflection_extension, __construct)
free_alloca(lcname, use_heap); free_alloca(lcname, use_heap);
MAKE_STD_ZVAL(name); MAKE_STD_ZVAL(name);
ZVAL_STRING(name, module->name, 1); ZVAL_STRING(name, module->name, 1);
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property( object, "name", name);
intern->ptr = module; intern->ptr = module;
intern->ref_type = REF_TYPE_OTHER; intern->ref_type = REF_TYPE_OTHER;
intern->ce = NULL; intern->ce = NULL;
@ -5269,7 +5268,7 @@ ZEND_METHOD(reflection_zend_extension, __construct)
} }
MAKE_STD_ZVAL(name); MAKE_STD_ZVAL(name);
ZVAL_STRING(name, extension->name, 1); ZVAL_STRING(name, extension->name, 1);
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); reflection_update_property(object, "name", name);
intern->ptr = extension; intern->ptr = extension;
intern->ref_type = REF_TYPE_OTHER; intern->ref_type = REF_TYPE_OTHER;
intern->ce = NULL; intern->ce = NULL;
@ -5783,7 +5782,7 @@ static zend_object_handlers *zend_std_obj_handlers;
static void _reflection_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) static void _reflection_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{ {
if ((Z_TYPE_P(member) == IS_STRING) if ((Z_TYPE_P(member) == IS_STRING)
&& zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1) && zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
&& ((Z_STRLEN_P(member) == sizeof("name") - 1 && !memcmp(Z_STRVAL_P(member), "name", sizeof("name"))) && ((Z_STRLEN_P(member) == sizeof("name") - 1 && !memcmp(Z_STRVAL_P(member), "name", sizeof("name")))
|| (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class"))))) || (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
{ {

View file

@ -3,6 +3,8 @@ ReflectionClass::getStaticPropertyValue()
--CREDITS-- --CREDITS--
Robin Fernandes <robinf@php.net> Robin Fernandes <robinf@php.net>
Steve Seear <stevseea@php.net> Steve Seear <stevseea@php.net>
--SKIPIF--
<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
--FILE-- --FILE--
<?php <?php
class A { class A {

View file

@ -0,0 +1,61 @@
--TEST--
ReflectionClass::getStaticPropertyValue()
--CREDITS--
Robin Fernandes <robinf@php.net>
Steve Seear <stevseea@php.net>
--SKIPIF--
<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
--FILE--
<?php
class A {
static private $privateOverridden = "original private";
static protected $protectedOverridden = "original protected";
static public $publicOverridden = "original public";
}
class B extends A {
static private $privateOverridden = "changed private";
static protected $protectedOverridden = "changed protected";
static public $publicOverridden = "changed public";
}
echo "Retrieving static values from A:\n";
$rcA = new ReflectionClass('A');
var_dump($rcA->getStaticPropertyValue("privateOverridden", "default value"));
var_dump($rcA->getStaticPropertyValue("\0A\0privateOverridden"));
var_dump($rcA->getStaticPropertyValue("protectedOverridden", "default value"));
var_dump($rcA->getStaticPropertyValue("\0*\0protectedOverridden"));
var_dump($rcA->getStaticPropertyValue("publicOverridden"));
echo "\nRetrieving static values from B:\n";
$rcB = new ReflectionClass('B');
var_dump($rcB->getStaticPropertyValue("\0A\0privateOverridden"));
var_dump($rcB->getStaticPropertyValue("\0B\0privateOverridden"));
var_dump($rcB->getStaticPropertyValue("\0*\0protectedOverridden"));
var_dump($rcB->getStaticPropertyValue("publicOverridden"));
echo "\nRetrieving non-existent values from A with no default value:\n";
try {
var_dump($rcA->getStaticPropertyValue("protectedOverridden"));
echo "you should not see this";
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
var_dump($rcA->getStaticPropertyValue("privateOverridden"));
echo "you should not see this";
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
?>
--EXPECTF--
Retrieving static values from A:
string(13) "default value"
Fatal error: Uncaught exception 'ReflectionException' with message 'Class A does not have a property named ' in %sReflectionClass_getStaticPropertyValue_001_2_4.php:%d
Stack trace:
#0 %sReflectionClass_getStaticPropertyValue_001_2_4.php(%d): ReflectionClass->getStaticPropertyValue('?A?privateOverr...')
#1 {main}
thrown in %sReflectionClass_getStaticPropertyValue_001_2_4.php on line %d

View file

@ -3,6 +3,8 @@ ReflectionClass::setStaticPropertyValue()
--CREDITS-- --CREDITS--
Robin Fernandes <robinf@php.net> Robin Fernandes <robinf@php.net>
Steve Seear <stevseea@php.net> Steve Seear <stevseea@php.net>
--SKIPIF--
<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
--FILE-- --FILE--
<?php <?php
class A { class A {

View file

@ -0,0 +1,61 @@
--TEST--
ReflectionClass::setStaticPropertyValue()
--CREDITS--
Robin Fernandes <robinf@php.net>
Steve Seear <stevseea@php.net>
--SKIPIF--
<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
--FILE--
<?php
class A {
static private $privateOverridden = "original private";
static protected $protectedOverridden = "original protected";
static public $publicOverridden = "original public";
}
class B extends A {
static private $privateOverridden = "changed private";
static protected $protectedOverridden = "changed protected";
static public $publicOverridden = "changed public";
}
echo "Set static values in A:\n";
$rcA = new ReflectionClass('A');
$rcA->setStaticPropertyValue("\0A\0privateOverridden", "new value 1");
$rcA->setStaticPropertyValue("\0*\0protectedOverridden", "new value 2");
$rcA->setStaticPropertyValue("publicOverridden", "new value 3");
print_r($rcA->getStaticProperties());
echo "\nSet static values in B:\n";
$rcB = new ReflectionClass('B');
$rcB->setStaticPropertyValue("\0A\0privateOverridden", "new value 4");
$rcB->setStaticPropertyValue("\0B\0privateOverridden", "new value 5");
$rcB->setStaticPropertyValue("\0*\0protectedOverridden", "new value 6");
$rcB->setStaticPropertyValue("publicOverridden", "new value 7");
print_r($rcA->getStaticProperties());
print_r($rcB->getStaticProperties());
echo "\nSet non-existent values from A with no default value:\n";
try {
var_dump($rcA->setStaticPropertyValue("protectedOverridden", "new value 8"));
echo "you should not see this";
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
try {
var_dump($rcA->setStaticPropertyValue("privateOverridden", "new value 9"));
echo "you should not see this";
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
?>
--EXPECTF--
Set static values in A:
Fatal error: Uncaught exception 'ReflectionException' with message 'Class A does not have a property named ' in %sReflectionClass_setStaticPropertyValue_001_2_4.php:%d
Stack trace:
#0 %sReflectionClass_setStaticPropertyValue_001_2_4.php(%d): ReflectionClass->setStaticPropertyValue('?A?privateOverr...', 'new value 1')
#1 {main}
thrown in %sReflectionClass_setStaticPropertyValue_001_2_4.php on line %d

View file

@ -81,11 +81,17 @@ typedef struct _spl_array_object {
static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) { /* {{{ */ static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) { /* {{{ */
if ((intern->ar_flags & SPL_ARRAY_IS_SELF) != 0) { if ((intern->ar_flags & SPL_ARRAY_IS_SELF) != 0) {
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
return intern->std.properties; return intern->std.properties;
} else if ((intern->ar_flags & SPL_ARRAY_USE_OTHER) && (check_std_props == 0 || (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) == 0) && Z_TYPE_P(intern->array) == IS_OBJECT) { } else if ((intern->ar_flags & SPL_ARRAY_USE_OTHER) && (check_std_props == 0 || (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) == 0) && Z_TYPE_P(intern->array) == IS_OBJECT) {
spl_array_object *other = (spl_array_object*)zend_object_store_get_object(intern->array TSRMLS_CC); spl_array_object *other = (spl_array_object*)zend_object_store_get_object(intern->array TSRMLS_CC);
return spl_array_get_hash_table(other, check_std_props TSRMLS_CC); return spl_array_get_hash_table(other, check_std_props TSRMLS_CC);
} else if ((intern->ar_flags & ((check_std_props ? SPL_ARRAY_STD_PROP_LIST : 0) | SPL_ARRAY_IS_SELF)) != 0) { } else if ((intern->ar_flags & ((check_std_props ? SPL_ARRAY_STD_PROP_LIST : 0) | SPL_ARRAY_IS_SELF)) != 0) {
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
return intern->std.properties; return intern->std.properties;
} else { } else {
return HASH_OF(intern->array); return HASH_OF(intern->array);
@ -173,7 +179,7 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
ALLOC_INIT_ZVAL(intern->retval); ALLOC_INIT_ZVAL(intern->retval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
intern->ar_flags = 0; intern->ar_flags = 0;
intern->serialize_data = NULL; intern->serialize_data = NULL;
@ -728,6 +734,10 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /*
*is_temp = 0; *is_temp = 0;
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
if (HASH_OF(intern->array) == intern->std.properties) { if (HASH_OF(intern->array) == intern->std.properties) {
return intern->std.properties; return intern->std.properties;
} else { } else {
@ -1584,6 +1594,9 @@ smart_str spl_array_serialize_helper(spl_array_object *intern, php_serialize_dat
/* members */ /* members */
smart_str_appendl(&buf, "m:", 2); smart_str_appendl(&buf, "m:", 2);
INIT_PZVAL(&members); INIT_PZVAL(&members);
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
Z_ARRVAL(members) = intern->std.properties; Z_ARRVAL(members) = intern->std.properties;
Z_TYPE(members) = IS_ARRAY; Z_TYPE(members) = IS_ARRAY;
pmembers = &members; pmembers = &members;
@ -1719,6 +1732,9 @@ void spl_array_unserialize_helper(spl_array_object *intern, const unsigned char
} }
/* copy members */ /* copy members */
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *)); zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
zval_ptr_dtor(&pmembers); zval_ptr_dtor(&pmembers);

View file

@ -136,7 +136,6 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
{ {
zend_object_value retval; zend_object_value retval;
spl_filesystem_object *intern; spl_filesystem_object *intern;
zval *tmp;
intern = emalloc(sizeof(spl_filesystem_object)); intern = emalloc(sizeof(spl_filesystem_object));
memset(intern, 0, sizeof(spl_filesystem_object)); memset(intern, 0, sizeof(spl_filesystem_object));
@ -146,7 +145,7 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
if (obj) *obj = intern; if (obj) *obj = intern;
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC);
retval.handlers = &spl_filesystem_object_handlers; retval.handlers = &spl_filesystem_object_handlers;
@ -549,6 +548,10 @@ static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp T
*is_temp = 1; *is_temp = 1;
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
ALLOC_HASHTABLE(rv); ALLOC_HASHTABLE(rv);
ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0); ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0);

View file

@ -367,7 +367,6 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type,
{ {
zend_object_value retval; zend_object_value retval;
spl_dllist_object *intern; spl_dllist_object *intern;
zval *tmp;
zend_class_entry *parent = class_type; zend_class_entry *parent = class_type;
int inherited = 0; int inherited = 0;
@ -376,7 +375,7 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type,
ALLOC_INIT_ZVAL(intern->retval); ALLOC_INIT_ZVAL(intern->retval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
intern->flags = 0; intern->flags = 0;
intern->traverse_position = 0; intern->traverse_position = 0;
@ -523,6 +522,9 @@ static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRML
INIT_PZVAL(&zrv); INIT_PZVAL(&zrv);
Z_ARRVAL(zrv) = intern->debug_info; Z_ARRVAL(zrv) = intern->debug_info;
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC); pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);

View file

@ -150,21 +150,22 @@ static void spl_fixedarray_copy(spl_fixedarray *to, spl_fixedarray *from TSRMLS_
static HashTable* spl_fixedarray_object_get_properties(zval *obj TSRMLS_DC) /* {{{{ */ static HashTable* spl_fixedarray_object_get_properties(zval *obj TSRMLS_DC) /* {{{{ */
{ {
spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC); spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC);
HashTable *ht = zend_std_get_properties(obj TSRMLS_CC);
int i = 0; int i = 0;
if (intern->array) { if (intern->array) {
for (i = 0; i < intern->array->size; i++) { for (i = 0; i < intern->array->size; i++) {
if (intern->array->elements[i]) { if (intern->array->elements[i]) {
zend_hash_index_update(intern->std.properties, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL); zend_hash_index_update(ht, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
Z_ADDREF_P(intern->array->elements[i]); Z_ADDREF_P(intern->array->elements[i]);
} else { } else {
zend_hash_index_update(intern->std.properties, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL); zend_hash_index_update(ht, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
Z_ADDREF_P(EG(uninitialized_zval_ptr)); Z_ADDREF_P(EG(uninitialized_zval_ptr));
} }
} }
} }
return intern->std.properties; return ht;
} }
/* }}}} */ /* }}}} */
@ -199,7 +200,6 @@ static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_ty
{ {
zend_object_value retval; zend_object_value retval;
spl_fixedarray_object *intern; spl_fixedarray_object *intern;
zval *tmp;
zend_class_entry *parent = class_type; zend_class_entry *parent = class_type;
int inherited = 0; int inherited = 0;
@ -208,7 +208,7 @@ static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_ty
ALLOC_INIT_ZVAL(intern->retval); ALLOC_INIT_ZVAL(intern->retval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
intern->current = 0; intern->current = 0;
intern->flags = 0; intern->flags = 0;

View file

@ -385,7 +385,6 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp
{ {
zend_object_value retval; zend_object_value retval;
spl_heap_object *intern; spl_heap_object *intern;
zval *tmp;
zend_class_entry *parent = class_type; zend_class_entry *parent = class_type;
int inherited = 0; int inherited = 0;
@ -394,7 +393,7 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp
ALLOC_INIT_ZVAL(intern->retval); ALLOC_INIT_ZVAL(intern->retval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
intern->flags = 0; intern->flags = 0;
intern->fptr_cmp = NULL; intern->fptr_cmp = NULL;
@ -529,6 +528,10 @@ static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zv
*is_temp = 0; *is_temp = 0;
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
if (intern->debug_info == NULL) { if (intern->debug_info == NULL) {
ALLOC_HASHTABLE(intern->debug_info); ALLOC_HASHTABLE(intern->debug_info);
ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0); ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);

View file

@ -810,7 +810,6 @@ static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry *
{ {
zend_object_value retval; zend_object_value retval;
spl_recursive_it_object *intern; spl_recursive_it_object *intern;
zval *tmp;
intern = emalloc(sizeof(spl_recursive_it_object)); intern = emalloc(sizeof(spl_recursive_it_object));
memset(intern, 0, sizeof(spl_recursive_it_object)); memset(intern, 0, sizeof(spl_recursive_it_object));
@ -825,7 +824,7 @@ static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry *
} }
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_RecursiveIteratorIterator_free_storage, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_RecursiveIteratorIterator_free_storage, NULL TSRMLS_CC);
retval.handlers = &spl_handlers_rec_it_it; retval.handlers = &spl_handlers_rec_it_it;
@ -1960,14 +1959,13 @@ static zend_object_value spl_dual_it_new(zend_class_entry *class_type TSRMLS_DC)
{ {
zend_object_value retval; zend_object_value retval;
spl_dual_it_object *intern; spl_dual_it_object *intern;
zval *tmp;
intern = emalloc(sizeof(spl_dual_it_object)); intern = emalloc(sizeof(spl_dual_it_object));
memset(intern, 0, sizeof(spl_dual_it_object)); memset(intern, 0, sizeof(spl_dual_it_object));
intern->dit_type = DIT_Unknown; intern->dit_type = DIT_Unknown;
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_dual_it_free_storage, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_dual_it_free_storage, NULL TSRMLS_CC);
retval.handlers = &spl_handlers_dual_it; retval.handlers = &spl_handlers_dual_it;

View file

@ -253,14 +253,13 @@ static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type,
zend_object_value retval; zend_object_value retval;
spl_SplObjectStorage *intern; spl_SplObjectStorage *intern;
zend_class_entry *parent = class_type; zend_class_entry *parent = class_type;
zval *tmp;
intern = emalloc(sizeof(spl_SplObjectStorage)); intern = emalloc(sizeof(spl_SplObjectStorage));
memset(intern, 0, sizeof(spl_SplObjectStorage)); memset(intern, 0, sizeof(spl_SplObjectStorage));
*obj = intern; *obj = intern;
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
zend_hash_init(&intern->storage, 0, NULL, (void (*)(void *))spl_object_storage_dtor, 0); zend_hash_init(&intern->storage, 0, NULL, (void (*)(void *))spl_object_storage_dtor, 0);
@ -669,7 +668,7 @@ SPL_METHOD(SplObjectStorage, serialize)
/* members */ /* members */
smart_str_appendl(&buf, "m:", 2); smart_str_appendl(&buf, "m:", 2);
INIT_PZVAL(&members); INIT_PZVAL(&members);
Z_ARRVAL(members) = intern->std.properties; Z_ARRVAL(members) = zend_std_get_properties(getThis() TSRMLS_CC);
Z_TYPE(members) = IS_ARRAY; Z_TYPE(members) = IS_ARRAY;
pmembers = &members; pmembers = &members;
php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */ php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
@ -767,6 +766,9 @@ SPL_METHOD(SplObjectStorage, unserialize)
} }
/* copy members */ /* copy members */
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *)); zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
zval_ptr_dtor(&pmembers); zval_ptr_dtor(&pmembers);

View file

@ -1154,14 +1154,13 @@ static void sqlite_object_free_storage(void *object TSRMLS_DC)
static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC) static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC)
{ {
sqlite_object *intern; sqlite_object *intern;
zval *tmp;
intern = emalloc(sizeof(sqlite_object)); intern = emalloc(sizeof(sqlite_object));
memset(intern, 0, sizeof(sqlite_object)); memset(intern, 0, sizeof(sqlite_object));
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval->handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) sqlite_object_free_storage, NULL TSRMLS_CC); retval->handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) sqlite_object_free_storage, NULL TSRMLS_CC);
retval->handlers = handlers; retval->handlers = handlers;
} }

View file

@ -1933,7 +1933,6 @@ static void php_sqlite3_result_object_free_storage(void *object TSRMLS_DC) /* {{
static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{ {
zval *tmp;
zend_object_value retval; zend_object_value retval;
php_sqlite3_db_object *intern; php_sqlite3_db_object *intern;
@ -1946,7 +1945,7 @@ static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSR
zend_llist_init(&(intern->free_list), sizeof(php_sqlite3_free_list *), (llist_dtor_func_t)php_sqlite3_free_list_dtor, 0); zend_llist_init(&(intern->free_list), sizeof(php_sqlite3_free_list *), (llist_dtor_func_t)php_sqlite3_free_list_dtor, 0);
zend_object_std_init(&intern->zo, class_type TSRMLS_CC); zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *)); object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_object_free_storage, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_object_free_storage, NULL TSRMLS_CC);
retval.handlers = (zend_object_handlers *) &sqlite3_object_handlers; retval.handlers = (zend_object_handlers *) &sqlite3_object_handlers;
@ -1957,7 +1956,6 @@ static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSR
static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{ {
zval *tmp;
zend_object_value retval; zend_object_value retval;
php_sqlite3_stmt *intern; php_sqlite3_stmt *intern;
@ -1968,7 +1966,7 @@ static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_typ
intern->db_obj_zval = NULL; intern->db_obj_zval = NULL;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC); zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *)); object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_stmt_object_free_storage, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_stmt_object_free_storage, NULL TSRMLS_CC);
retval.handlers = (zend_object_handlers *) &sqlite3_stmt_object_handlers; retval.handlers = (zend_object_handlers *) &sqlite3_stmt_object_handlers;
@ -1979,7 +1977,6 @@ static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_typ
static zend_object_value php_sqlite3_result_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ static zend_object_value php_sqlite3_result_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{ {
zval *tmp;
zend_object_value retval; zend_object_value retval;
php_sqlite3_result *intern; php_sqlite3_result *intern;
@ -1992,7 +1989,7 @@ static zend_object_value php_sqlite3_result_object_new(zend_class_entry *class_t
intern->stmt_obj_zval = NULL; intern->stmt_obj_zval = NULL;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC); zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *)); object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_result_object_free_storage, NULL TSRMLS_CC); retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_result_object_free_storage, NULL TSRMLS_CC);
retval.handlers = (zend_object_handlers *) &sqlite3_result_object_handlers; retval.handlers = (zend_object_handlers *) &sqlite3_result_object_handlers;

View file

@ -109,8 +109,6 @@ static zend_object_value php_create_incomplete_object(zend_class_entry *class_ty
value = zend_objects_new(&object, class_type TSRMLS_CC); value = zend_objects_new(&object, class_type TSRMLS_CC);
value.handlers = &php_incomplete_object_handlers; value.handlers = &php_incomplete_object_handlers;
ALLOC_HASHTABLE(object->properties);
zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
return value; return value;
} }

View file

@ -1,5 +1,7 @@
--TEST-- --TEST--
Test array_fill() function : usage variations - various object values for 'val' argument Test array_fill() function : usage variations - various object values for 'val' argument
--SKIPIF--
<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
--FILE-- --FILE--
<?php <?php
/* Prototype : array array_fill(int $start_key, int $num, mixed $val) /* Prototype : array array_fill(int $start_key, int $num, mixed $val)

View file

@ -0,0 +1,434 @@
--TEST--
Test array_fill() function : usage variations - various object values for 'val' argument
--SKIPIF--
<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
--FILE--
<?php
/* Prototype : array array_fill(int $start_key, int $num, mixed $val)
* Description: Create an array containing num elements starting with index start_key each initialized to val
* Source code: ext/standard/array.c
*/
/*
* testing array_fill() by passing various object values for 'val' argument
*/
echo "*** Testing array_fill() : usage variations ***\n";
// Initialise function arguments not being substituted
$start_key = 0;
$num = 2;
// class without a member
class Test
{
}
//class with public member, static member , constant and consturctor to initialize the public member
class Test1
{
const test1_constant = "test1";
public static $test1_static = 0;
public $member1;
var $var1 = 30;
var $var2;
function __construct($value1 , $value2)
{
$this->member1 = $value1;
$this->var2 = $value2;
}
}
// child class which inherits parent class test1
class Child_test1 extends Test1
{
public $member2;
function __construct($value1 , $value2 , $value3)
{
parent::__construct($value1 , $value2);
$this->member2 = $value3;
}
}
//class with private member, static member, constant and constructor to initialize the private member
class Test2
{
const test2_constant = "test2";
public static $test2_static = 0;
private $member1;
var $var1 = 30;
var $var2;
function __construct($value1 , $value2)
{
$this->member1 = $value1;
$this->var2 = $value2;
}
}
// child class which inherits parent class test2
class Child_test2 extends Test2
{
private $member1;
function __construct($value1 , $value2 , $value3)
{
parent::__construct($value1 , $value2);
$this->member1 = $value3;
}
}
// class with protected member, static member, constant and consturctor to initialize the protected member
class Test3
{
const test3_constant = "test3";
public static $test3_static = 0;
protected $member1;
var $var1 = 30;
var $var2;
function __construct($value1 , $value2)
{
$this->member1 = $value1;
$this->var2 = $value2;
}
}
// child class which inherits parent class test3
class Child_test3 extends Test3
{
protected $member1;
function __construct($value1 , $value2 , $value3)
{
parent::__construct($value1 , $value2);
$this->member1 = $value3;
}
}
// class with public, private, protected members, static, constant members and constructor to initialize all the members
class Test4
{
const test4_constant = "test4";
public static $test4_static = 0;
public $member1;
private $member2;
protected $member3;
function __construct($value1 , $value2 , $value3)
{
$this->member1 = $value1;
$this->member2 = $value2;
$this->member3 = $value3;
}
}
// child class which inherits parent class test4
class Child_test4 extends Test4
{
var $var1;
function __construct($value1 , $value2 , $value3 , $value4)
{
parent::__construct($value1 , $value2 , $value3);
$this->var1 = $value4;
}
}
// abstract class with public, private, protected members
abstract class AbstractClass
{
public $member1;
private $member2;
protected $member3;
var $var1 = 30;
abstract protected function display();
}
// implement abstract 'AbstractClass' class
class ConcreteClass1 extends AbstractClass
{
protected function display()
{
echo "class name is ConcreteClass1 \n";
}
}
// declarationn of the interface 'iTemplate'
interface iTemplate
{
public function display();
}
// implement the interface 'iTemplate'
class Template1 implements iTemplate
{
public function display()
{
echo "class name is Template1\n";
}
}
//array of object values for 'val' argument
$objects = array(
/* 1 */ new Test(),
new Test1(100 , 101),
new Child_test1(100 , 101 , 102),
new Test2(100 , 101),
/* 5 */ new Child_test2(100 , 101 , 102),
new Test3(100 , 101),
new Child_test3(100 , 101 , 102),
new Test4( 100 , 101 , 102),
new Child_test4(100 , 101 , 102 , 103),
new ConcreteClass1(),
/* 11 */ new Template1()
);
// loop through each element of the array for 'val' argument
// check the working of array_fill()
echo "--- Testing array_fill() with different object values for 'val' argument ---\n";
$counter = 1;
for($index = 0; $index < count($objects); $index ++)
{
echo "-- Iteration $counter --\n";
$val = $objects[$index];
var_dump( array_fill($start_key,$num,$val) );
$counter++;
}
echo "Done";
?>
--EXPECTF--
*** Testing array_fill() : usage variations ***
--- Testing array_fill() with different object values for 'val' argument ---
-- Iteration 1 --
array(2) {
[0]=>
object(Test)#%d (0) {
}
[1]=>
object(Test)#%d (0) {
}
}
-- Iteration 2 --
array(2) {
[0]=>
object(Test1)#%d (3) {
["member1"]=>
int(100)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
[1]=>
object(Test1)#%d (3) {
["member1"]=>
int(100)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
}
-- Iteration 3 --
array(2) {
[0]=>
object(Child_test1)#%d (4) {
["member2"]=>
int(102)
["member1"]=>
int(100)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
[1]=>
object(Child_test1)#%d (4) {
["member2"]=>
int(102)
["member1"]=>
int(100)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
}
-- Iteration 4 --
array(2) {
[0]=>
object(Test2)#%d (3) {
["member1":"Test2":private]=>
int(100)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
[1]=>
object(Test2)#%d (3) {
["member1":"Test2":private]=>
int(100)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
}
-- Iteration 5 --
array(2) {
[0]=>
object(Child_test2)#%d (4) {
["member1":"Child_test2":private]=>
int(102)
["var1"]=>
int(30)
["var2"]=>
int(101)
["member1":"Test2":private]=>
int(100)
}
[1]=>
object(Child_test2)#%d (4) {
["member1":"Child_test2":private]=>
int(102)
["var1"]=>
int(30)
["var2"]=>
int(101)
["member1":"Test2":private]=>
int(100)
}
}
-- Iteration 6 --
array(2) {
[0]=>
object(Test3)#%d (3) {
["member1":protected]=>
int(100)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
[1]=>
object(Test3)#%d (3) {
["member1":protected]=>
int(100)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
}
-- Iteration 7 --
array(2) {
[0]=>
object(Child_test3)#%d (3) {
["member1":protected]=>
int(102)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
[1]=>
object(Child_test3)#%d (3) {
["member1":protected]=>
int(102)
["var1"]=>
int(30)
["var2"]=>
int(101)
}
}
-- Iteration 8 --
array(2) {
[0]=>
object(Test4)#%d (3) {
["member1"]=>
int(100)
["member2":"Test4":private]=>
int(101)
["member3":protected]=>
int(102)
}
[1]=>
object(Test4)#%d (3) {
["member1"]=>
int(100)
["member2":"Test4":private]=>
int(101)
["member3":protected]=>
int(102)
}
}
-- Iteration 9 --
array(2) {
[0]=>
object(Child_test4)#%d (4) {
["var1"]=>
int(103)
["member1"]=>
int(100)
["member2":"Test4":private]=>
int(101)
["member3":protected]=>
int(102)
}
[1]=>
object(Child_test4)#%d (4) {
["var1"]=>
int(103)
["member1"]=>
int(100)
["member2":"Test4":private]=>
int(101)
["member3":protected]=>
int(102)
}
}
-- Iteration 10 --
array(2) {
[0]=>
object(ConcreteClass1)#%d (4) {
["member1"]=>
NULL
["member2":"AbstractClass":private]=>
NULL
["member3":protected]=>
NULL
["var1"]=>
int(30)
}
[1]=>
object(ConcreteClass1)#%d (4) {
["member1"]=>
NULL
["member2":"AbstractClass":private]=>
NULL
["member3":protected]=>
NULL
["var1"]=>
int(30)
}
}
-- Iteration 11 --
array(2) {
[0]=>
object(Template1)#%d (0) {
}
[1]=>
object(Template1)#%d (0) {
}
}
Done

View file

@ -676,13 +676,11 @@ static void tidy_object_new(zend_class_entry *class_type, zend_object_handlers *
zend_object_value *retval, tidy_obj_type objtype TSRMLS_DC) zend_object_value *retval, tidy_obj_type objtype TSRMLS_DC)
{ {
PHPTidyObj *intern; PHPTidyObj *intern;
zval *tmp;
intern = emalloc(sizeof(PHPTidyObj)); intern = emalloc(sizeof(PHPTidyObj));
memset(intern, 0, sizeof(PHPTidyObj)); memset(intern, 0, sizeof(PHPTidyObj));
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
object_properties_init(&intern->std, class_type);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
switch(objtype) { switch(objtype) {
case is_node: case is_node:

View file

@ -391,7 +391,6 @@ zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC)
{ {
zend_object_value retval; zend_object_value retval;
xmlreader_object *intern; xmlreader_object *intern;
zval *tmp;
intern = emalloc(sizeof(xmlreader_object)); intern = emalloc(sizeof(xmlreader_object));
memset(&intern->std, 0, sizeof(zend_object)); memset(&intern->std, 0, sizeof(zend_object));
@ -401,7 +400,7 @@ zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC)
intern->prop_handler = &xmlreader_prop_handlers; intern->prop_handler = &xmlreader_prop_handlers;
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) xmlreader_objects_free_storage, xmlreader_objects_clone TSRMLS_CC); retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) xmlreader_objects_free_storage, xmlreader_objects_clone TSRMLS_CC);
intern->handle = retval.handle; intern->handle = retval.handle;
retval.handlers = &xmlreader_object_handlers; retval.handlers = &xmlreader_object_handlers;

View file

@ -143,7 +143,6 @@ static void xmlwriter_object_free_storage(void *object TSRMLS_DC)
static zend_object_value xmlwriter_object_new(zend_class_entry *class_type TSRMLS_DC) static zend_object_value xmlwriter_object_new(zend_class_entry *class_type TSRMLS_DC)
{ {
ze_xmlwriter_object *intern; ze_xmlwriter_object *intern;
zval *tmp;
zend_object_value retval; zend_object_value retval;
intern = emalloc(sizeof(ze_xmlwriter_object)); intern = emalloc(sizeof(ze_xmlwriter_object));
@ -151,8 +150,7 @@ static zend_object_value xmlwriter_object_new(zend_class_entry *class_type TSRML
intern->xmlwriter_ptr = NULL; intern->xmlwriter_ptr = NULL;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC); zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, object_properties_init(&intern->zo, class_type);
(void *) &tmp, sizeof(zval *));
retval.handle = zend_objects_store_put(intern, retval.handle = zend_objects_store_put(intern,
NULL, NULL,

View file

@ -115,7 +115,6 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC)
{ {
zend_object_value retval; zend_object_value retval;
xsl_object *intern; xsl_object *intern;
zval *tmp;
intern = emalloc(sizeof(xsl_object)); intern = emalloc(sizeof(xsl_object));
intern->ptr = NULL; intern->ptr = NULL;
@ -129,7 +128,7 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC)
intern->profiling = NULL; intern->profiling = NULL;
zend_object_std_init(&intern->std, class_type TSRMLS_CC); zend_object_std_init(&intern->std, class_type TSRMLS_CC);
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); object_properties_init(&intern->std, class_type);
ALLOC_HASHTABLE(intern->parameter); ALLOC_HASHTABLE(intern->parameter);
zend_hash_init(intern->parameter, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(intern->parameter, 0, NULL, ZVAL_PTR_DTOR, 0);
ALLOC_HASHTABLE(intern->registered_phpfunctions); ALLOC_HASHTABLE(intern->registered_phpfunctions);

View file

@ -971,7 +971,7 @@ static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
ulong num_key; ulong num_key;
obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC); obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
props = obj->zo.properties; props = zend_std_get_properties(object TSRMLS_CC);
if (obj->prop_handler == NULL) { if (obj->prop_handler == NULL) {
return NULL; return NULL;
@ -988,7 +988,7 @@ static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL); zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
zend_hash_move_forward_ex(obj->prop_handler, &pos); zend_hash_move_forward_ex(obj->prop_handler, &pos);
} }
return obj->zo.properties; return props;
} }
/* }}} */ /* }}} */
@ -1040,7 +1040,6 @@ static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{ {
ze_zip_object *intern; ze_zip_object *intern;
zval *tmp;
zend_object_value retval; zend_object_value retval;
intern = emalloc(sizeof(ze_zip_object)); intern = emalloc(sizeof(ze_zip_object));
@ -1060,8 +1059,7 @@ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_
intern->zo.ce = class_type; intern->zo.ce = class_type;
#endif #endif
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, object_properties_init(&intern->zo, class_type);
(void *) &tmp, sizeof(zval *));
retval.handle = zend_objects_store_put(intern, retval.handle = zend_objects_store_put(intern,
NULL, NULL,