Improved object property access.

This commit is contained in:
Dmitry Stogov 2014-11-06 14:50:03 +03:00
parent 6b8328de74
commit 75041379a6
9 changed files with 1290 additions and 296 deletions

View File

@ -1207,7 +1207,7 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
for (i = 0; i < class_type->default_properties_count; i++) {
if (Z_TYPE(class_type->default_properties_table[i]) != IS_UNDEF) {
zval_update_class_constant(&class_type->default_properties_table[i], 0, i TSRMLS_CC);
zval_update_class_constant(&class_type->default_properties_table[i], 0, OBJ_PROP_TO_OFFSET(i) TSRMLS_CC);
}
}
@ -1251,8 +1251,9 @@ ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properti
if (property_info != ZEND_WRONG_PROPERTY_INFO &&
property_info &&
(property_info->flags & ZEND_ACC_STATIC) == 0) {
ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop);
ZVAL_INDIRECT(prop, &object->properties_table[property_info->offset]);
zval *slot = OBJ_PROP(object, property_info->offset);
ZVAL_COPY_VALUE(slot, prop);
ZVAL_INDIRECT(prop, slot);
}
} ZEND_HASH_FOREACH_END();
}
@ -1270,11 +1271,12 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties
if (property_info != ZEND_WRONG_PROPERTY_INFO &&
property_info &&
(property_info->flags & ZEND_ACC_STATIC) == 0) {
zval_ptr_dtor(&object->properties_table[property_info->offset]);
ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop);
zval_add_ref(&object->properties_table[property_info->offset]);
zval *slot = OBJ_PROP(object, property_info->offset);
zval_ptr_dtor(slot);
ZVAL_COPY_VALUE(slot, prop);
zval_add_ref(slot);
if (object->properties) {
ZVAL_INDIRECT(&tmp, &object->properties_table[property_info->offset]);
ZVAL_INDIRECT(&tmp, slot);
zend_hash_update(object->properties, key, &tmp);
}
} else {
@ -3618,13 +3620,14 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
(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]);
zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
zend_hash_del(&ce->properties_info, name);
} else {
property_info->offset = ce->default_properties_count++;
property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
ce->default_properties_count++;
ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
}
ZVAL_COPY_VALUE(&ce->default_properties_table[property_info->offset], property);
ZVAL_COPY_VALUE(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)], property);
}
if (ce->type & ZEND_INTERNAL_CLASS) {
switch(Z_TYPE_P(property)) {

View File

@ -954,12 +954,10 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
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 (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[OBJ_PROP_TO_NUM(prop_info->offset)];
}
if (!prop || Z_TYPE_P(prop) == IS_UNDEF) {
continue;

View File

@ -227,13 +227,23 @@ typedef struct _zend_try_catch_element {
char *zend_visibility_string(uint32_t fn_flags);
typedef struct _zend_property_info {
uint32_t offset; /* property offset for object properties or
property index for static properties */
uint32_t flags;
int offset;
zend_string *name;
zend_string *doc_comment;
zend_class_entry *ce;
} zend_property_info;
#define OBJ_PROP(obj, offset) \
((zval*)((char*)(obj) + offset))
#define OBJ_PROP_NUM(obj, num) \
(&(obj)->properties_table[(num)])
#define OBJ_PROP_TO_OFFSET(num) \
((uint32_t)(zend_uintptr_t)OBJ_PROP_NUM(((zend_object*)NULL), num))
#define OBJ_PROP_TO_NUM(offset) \
((offset - OBJ_PROP_TO_OFFSET(0)) / sizeof(zval))
typedef struct _zend_arg_info {
const char *name; // TODO: convert into zend_string ???
uint32_t name_len;

View File

@ -1292,7 +1292,7 @@ ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *
zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR TSRMLS_CC);
}
static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, void **cache_slot, int type TSRMLS_DC)
static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type TSRMLS_DC)
{
if (container_op_type != IS_UNUSED) {
ZVAL_DEREF(container);
@ -1316,6 +1316,26 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
}
}
}
if (prop_op_type == IS_CONST &&
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) {
zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 1);
zend_object *zobj = Z_OBJ_P(container);
zval *retval;
if (EXPECTED(prop_info)) {
retval = OBJ_PROP(zobj, prop_info->offset);
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
ZVAL_INDIRECT(result, retval);
return;
}
} else if (EXPECTED(zobj->properties != NULL)) {
retval = zend_hash_find(zobj->properties, Z_STR_P(prop_ptr));
if (EXPECTED(retval)) {
ZVAL_INDIRECT(result, retval);
return;
}
}
}
if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot TSRMLS_CC);
if (NULL == ptr) {

View File

@ -602,9 +602,12 @@ 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)) {
zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name->val, key->val, zend_visibility_string(parent_info->flags), parent_ce->name->val, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
} else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
zval_ptr_dtor(&(ce->default_properties_table[parent_info->offset]));
ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
ZVAL_UNDEF(&ce->default_properties_table[child_info->offset]);
int parent_num = OBJ_PROP_TO_NUM(parent_info->offset);
int child_num = OBJ_PROP_TO_NUM(child_info->offset);
zval_ptr_dtor(&(ce->default_properties_table[parent_num]));
ce->default_properties_table[parent_num] = ce->default_properties_table[child_num];
ZVAL_UNDEF(&ce->default_properties_table[child_num]);
child_info->offset = parent_info->offset;
}
return 0; /* Don't copy from parent */
@ -797,7 +800,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
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;
property_info->offset += parent_ce->default_properties_count * sizeof(zval);
}
}
} ZEND_HASH_FOREACH_END();
@ -1421,8 +1424,8 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {
|| (Z_LVAL(compare_result) != 0);
} else {
not_compatible = (FAILURE == compare_function(&compare_result,
&ce->default_properties_table[coliding_prop->offset],
&ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
&ce->default_properties_table[OBJ_PROP_TO_NUM(coliding_prop->offset)],
&ce->traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)] TSRMLS_CC))
|| (Z_LVAL(compare_result) != 0);
}
} else {
@ -1454,7 +1457,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {
if (flags & ZEND_ACC_STATIC) {
prop_value = &ce->traits[i]->default_static_members_table[property_info->offset];
} else {
prop_value = &ce->traits[i]->default_properties_table[property_info->offset];
prop_value = &ce->traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
}
if (Z_REFCOUNTED_P(prop_value)) Z_ADDREF_P(prop_value);

View File

@ -80,11 +80,10 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
if (/*prop_info->ce == ce &&*/
(prop_info->flags & ZEND_ACC_STATIC) == 0 &&
prop_info->offset >= 0 &&
Z_TYPE(zobj->properties_table[prop_info->offset]) != IS_UNDEF) {
Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) != IS_UNDEF) {
zval zv;
ZVAL_INDIRECT(&zv, &zobj->properties_table[prop_info->offset]);
ZVAL_INDIRECT(&zv, OBJ_PROP(zobj, prop_info->offset));
zend_hash_add_new(zobj->properties, prop_info->name, &zv);
}
} ZEND_HASH_FOREACH_END();
@ -94,11 +93,10 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
if (prop_info->ce == ce &&
(prop_info->flags & ZEND_ACC_STATIC) == 0 &&
(prop_info->flags & ZEND_ACC_PRIVATE) != 0 &&
prop_info->offset >= 0 &&
Z_TYPE(zobj->properties_table[prop_info->offset]) != IS_UNDEF) {
Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) != IS_UNDEF) {
zval zv;
ZVAL_INDIRECT(&zv, &zobj->properties_table[prop_info->offset]);
ZVAL_INDIRECT(&zv, OBJ_PROP(zobj, prop_info->offset));
zend_hash_add(zobj->properties, prop_info->name, &zv);
}
} ZEND_HASH_FOREACH_END();
@ -288,7 +286,7 @@ static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_cla
}
/* }}} */
static zend_always_inline zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot TSRMLS_DC) /* {{{ */
static zend_always_inline zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zend_string *member, int silent, int allow_static, void **cache_slot TSRMLS_DC) /* {{{ */
{
zval *zv;
zend_property_info *property_info = NULL;
@ -324,8 +322,13 @@ static zend_always_inline zend_property_info *zend_get_property_info_quick(zend_
if (EXPECTED(zend_verify_property_access(property_info, ce TSRMLS_CC) != 0)) {
if (UNEXPECTED(!(flags & ZEND_ACC_CHANGED))
|| UNEXPECTED((flags & ZEND_ACC_PRIVATE))) {
if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0) && !silent) {
zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name->val, member->val);
if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
if (!silent) {
zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name->val, member->val);
}
if (!allow_static) {
return NULL;
}
}
goto exit;
}
@ -342,7 +345,9 @@ static zend_always_inline zend_property_info *zend_get_property_info_quick(zend_
&& (zv = zend_hash_find(&EG(scope)->properties_info, member)) != NULL
&& ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE) {
property_info = (zend_property_info*)Z_PTR_P(zv);
goto exit;
if (!allow_static && UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0)) {
return NULL;
}
} else if (UNEXPECTED(property_info == NULL)) {
exit_dynamic:
if (cache_slot) {
@ -354,9 +359,6 @@ exit_dynamic:
if (!silent) {
zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(flags), ce->name->val, member->val);
}
if (cache_slot) {
CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, ZEND_WRONG_PROPERTY_INFO);
}
return ZEND_WRONG_PROPERTY_INFO;
}
@ -370,7 +372,7 @@ exit:
ZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent TSRMLS_DC) /* {{{ */
{
return zend_get_property_info_quick(ce, member, silent, NULL TSRMLS_CC);
return zend_get_property_info_quick(ce, member, silent, 1, NULL TSRMLS_CC);
}
/* }}} */
@ -388,7 +390,7 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
} else {
member = zend_string_copy(prop_info_name);
}
property_info = zend_get_property_info_quick(zobj->ce, member, 1, NULL TSRMLS_CC);
property_info = zend_get_property_info_quick(zobj->ce, member, 1, 1, NULL TSRMLS_CC);
zend_string_release(member);
if (property_info == NULL) {
/* undefined public property */
@ -451,13 +453,11 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
#endif
/* make zend_get_property_info silent if we have getter - we may want to use it */
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (type == BP_VAR_IS) || (zobj->ce->__get != NULL), cache_slot TSRMLS_CC);
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (type == BP_VAR_IS) || (zobj->ce->__get != NULL), 0, cache_slot TSRMLS_CC);
if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
if (EXPECTED(property_info != NULL) &&
EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
retval = &zobj->properties_table[property_info->offset];
if (EXPECTED(property_info != NULL)) {
retval = OBJ_PROP(zobj, property_info->offset);
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
goto exit;
}
@ -534,13 +534,11 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, v
cache_slot = NULL;
}
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__set != NULL), cache_slot TSRMLS_CC);
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__set != NULL), 0, cache_slot TSRMLS_CC);
if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
if (EXPECTED(property_info != NULL) &&
EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
variable_ptr = &zobj->properties_table[property_info->offset];
if (EXPECTED(property_info != NULL)) {
variable_ptr = OBJ_PROP(zobj, property_info->offset);
if (Z_TYPE_P(variable_ptr) != IS_UNDEF) {
goto found;
}
@ -638,7 +636,7 @@ write_std_property:
if (EXPECTED(property_info != NULL) &&
EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
ZVAL_COPY_VALUE(&zobj->properties_table[property_info->offset], value);
ZVAL_COPY_VALUE(OBJ_PROP(zobj, property_info->offset), value);
} else {
if (!zobj->properties) {
rebuild_object_properties(zobj);
@ -754,13 +752,11 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), name->val);
#endif
property_info = zend_get_property_info_quick(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot TSRMLS_CC);
property_info = zend_get_property_info_quick(zobj->ce, name, (zobj->ce->__get != NULL), 0, cache_slot TSRMLS_CC);
if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
if (EXPECTED(property_info != NULL) &&
EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
retval = &zobj->properties_table[property_info->offset];
if (EXPECTED(property_info != NULL)) {
retval = OBJ_PROP(zobj, property_info->offset);
if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
if (EXPECTED(!zobj->ce->__get) ||
UNEXPECTED((*zend_get_property_guard(zobj, name)) & IN_GET)) {
@ -816,15 +812,15 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo
cache_slot = NULL;
}
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__unset != NULL), cache_slot TSRMLS_CC);
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__unset != NULL), 0, cache_slot TSRMLS_CC);
if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
if (EXPECTED(property_info != NULL) &&
EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
if (EXPECTED(property_info != NULL)) {
zval *slot = OBJ_PROP(zobj, property_info->offset);
if (Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) {
zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
ZVAL_UNDEF(&zobj->properties_table[property_info->offset]);
if (Z_TYPE_P(slot) != IS_UNDEF) {
zval_ptr_dtor(slot);
ZVAL_UNDEF(slot);
goto exit;
}
} else if (EXPECTED(zobj->properties != NULL) &&
@ -1413,13 +1409,11 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
cache_slot = NULL;
}
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), 1, cache_slot TSRMLS_CC);
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), 1, 0, cache_slot TSRMLS_CC);
if (EXPECTED(property_info != ZEND_WRONG_PROPERTY_INFO)) {
if (EXPECTED(property_info != NULL) &&
EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
value = &zobj->properties_table[property_info->offset];
if (EXPECTED(property_info != NULL)) {
value = OBJ_PROP(zobj, property_info->offset);
if (Z_TYPE_P(value) != IS_UNDEF) {
goto found;
}

View File

@ -1324,11 +1324,33 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zval *retval;
/* here we are sure we are dealing with an object */
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
do {
if (OP2_TYPE == IS_CONST &&
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
zend_object *zobj = Z_OBJ_P(container);
if (retval != EX_VAR(opline->result.var)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
}
if (EXPECTED(prop_info)) {
retval = OBJ_PROP(zobj, prop_info->offset);
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
break;
}
} else if (EXPECTED(zobj->properties != NULL)) {
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
if (EXPECTED(retval)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
break;
}
}
}
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
if (retval != EX_VAR(opline->result.var)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
}
} while (0);
}
FREE_OP2();
@ -1352,7 +1374,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1376,7 +1398,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1393,6 +1415,8 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV
zval *container;
zend_free_op free_op2;
zval *offset;
zval *retval;
zend_property_info *prop_info;
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_IS);
@ -1405,11 +1429,33 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV
zval *retval;
/* here we are sure we are dealing with an object */
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
do {
if (OP2_TYPE == IS_CONST &&
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
zend_object *zobj = Z_OBJ_P(container);
if (retval != EX_VAR(opline->result.var)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
}
if (EXPECTED(prop_info)) {
retval = OBJ_PROP(zobj, prop_info->offset);
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
break;
}
} else if (EXPECTED(zobj->properties != NULL)) {
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
if (EXPECTED(retval)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
break;
}
}
}
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
if (retval != EX_VAR(opline->result.var)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
}
} while (0);
}
FREE_OP2();
@ -1438,7 +1484,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1464,7 +1510,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));

File diff suppressed because it is too large Load Diff

View File

@ -3363,7 +3363,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
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];
prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
}
}
if (!prop) {