}
/* }}} */
-static void zend_std_call_getter(zend_object *zobj, zval *member, zval *retval) /* {{{ */
+static void zend_std_call_getter(zend_object *zobj, zend_string *prop_name, zval *retval) /* {{{ */
{
zend_class_entry *ce = zobj->ce;
zend_class_entry *orig_fake_scope = EG(fake_scope);
zend_fcall_info fci;
zend_fcall_info_cache fcic;
+ zval member;
EG(fake_scope) = NULL;
it should return whether the call was successful or not
*/
+ ZVAL_STR(&member, prop_name);
+
fci.size = sizeof(fci);
fci.object = zobj;
fci.retval = retval;
fci.param_count = 1;
- fci.params = member;
+ fci.params = &member;
fci.no_separation = 1;
ZVAL_UNDEF(&fci.function_name); /* Unused */
}
/* }}} */
-static void zend_std_call_setter(zend_object *zobj, zval *member, zval *value) /* {{{ */
+static void zend_std_call_setter(zend_object *zobj, zend_string *prop_name, zval *value) /* {{{ */
{
zend_class_entry *ce = zobj->ce;
zend_class_entry *orig_fake_scope = EG(fake_scope);
value to be set
*/
- ZVAL_COPY_VALUE(&args[0], member);
+ ZVAL_STR(&args[0], prop_name);
ZVAL_COPY_VALUE(&args[1], value);
ZVAL_UNDEF(&ret);
}
/* }}} */
-static void zend_std_call_unsetter(zend_object *zobj, zval *member) /* {{{ */
+static void zend_std_call_unsetter(zend_object *zobj, zend_string *prop_name) /* {{{ */
{
zend_class_entry *ce = zobj->ce;
zend_class_entry *orig_fake_scope = EG(fake_scope);
zend_fcall_info fci;
zend_fcall_info_cache fcic;
- zval ret;
+ zval ret, member;
EG(fake_scope) = NULL;
property name
*/
+ ZVAL_STR(&member, prop_name);
ZVAL_UNDEF(&ret);
fci.size = sizeof(fci);
fci.object = zobj;
fci.retval = &ret;
fci.param_count = 1;
- fci.params = member;
+ fci.params = &member;
fci.no_separation = 1;
ZVAL_UNDEF(&fci.function_name); /* Unused */
}
/* }}} */
-static void zend_std_call_issetter(zend_object *zobj, zval *member, zval *retval) /* {{{ */
+static void zend_std_call_issetter(zend_object *zobj, zend_string *prop_name, zval *retval) /* {{{ */
{
zend_class_entry *ce = zobj->ce;
zend_class_entry *orig_fake_scope = EG(fake_scope);
zend_fcall_info fci;
zend_fcall_info_cache fcic;
+ zval member;
EG(fake_scope) = NULL;
it should return whether the property is set or not
*/
+ ZVAL_STR(&member, prop_name);
+
fci.size = sizeof(fci);
fci.object = zobj;
fci.retval = retval;
fci.param_count = 1;
- fci.params = member;
+ fci.params = &member;
fci.no_separation = 1;
ZVAL_UNDEF(&fci.function_name); /* Unused */
ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */
{
zend_object *zobj;
- zval tmp_member;
+ zend_string *name, *tmp_name;
zval *retval;
uintptr_t property_offset;
uint32_t *guard = NULL;
zobj = Z_OBJ_P(object);
-
- ZVAL_UNDEF(&tmp_member);
- if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
- ZVAL_STR(&tmp_member, zval_get_string_func(member));
- member = &tmp_member;
- cache_slot = NULL;
- }
+ name = zval_get_tmp_string(member, &tmp_name);
#if DEBUG_OBJECT_HANDLERS
- fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
+ fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name));
#endif
/* make zend_get_property_info silent if we have getter - we may want to use it */
- property_offset = zend_get_property_offset(zobj->ce, Z_STR_P(member), (type == BP_VAR_IS) || (zobj->ce->__get != NULL), cache_slot);
+ property_offset = zend_get_property_offset(zobj->ce, name, (type == BP_VAR_IS) || (zobj->ce->__get != NULL), cache_slot);
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
retval = OBJ_PROP(zobj, property_offset);
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
- (EXPECTED(p->key == Z_STR_P(member)) ||
- (EXPECTED(p->h == ZSTR_H(Z_STR_P(member))) &&
+ (EXPECTED(p->key == name) ||
+ (EXPECTED(p->h == ZSTR_H(name)) &&
EXPECTED(p->key != NULL) &&
- EXPECTED(zend_string_equal_content(p->key, Z_STR_P(member)))))) {
+ EXPECTED(zend_string_equal_content(p->key, name))))) {
retval = &p->val;
goto exit;
}
}
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
}
- retval = zend_hash_find(zobj->properties, Z_STR_P(member));
+ retval = zend_hash_find(zobj->properties, name);
if (EXPECTED(retval)) {
if (cache_slot) {
uintptr_t idx = (char*)retval - (char*)zobj->properties->arData;
/* magic isset */
if ((type == BP_VAR_IS) && zobj->ce->__isset) {
zval tmp_result;
- guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ guard = zend_get_property_guard(zobj, name);
if (!((*guard) & IN_ISSET)) {
- if (Z_TYPE(tmp_member) == IS_UNDEF) {
- ZVAL_COPY(&tmp_member, member);
- member = &tmp_member;
+ if (!tmp_name && !ZSTR_IS_INTERNED(name)) {
+ tmp_name = zend_string_copy(name);
}
GC_ADDREF(zobj);
ZVAL_UNDEF(&tmp_result);
*guard |= IN_ISSET;
- zend_std_call_issetter(zobj, member, &tmp_result);
+ zend_std_call_issetter(zobj, name, &tmp_result);
*guard &= ~IN_ISSET;
if (!zend_is_true(&tmp_result)) {
}
} else if (zobj->ce->__get) {
/* magic get */
- guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ guard = zend_get_property_guard(zobj, name);
if (!((*guard) & IN_GET)) {
/* have getter - try with it! */
call_getter_addref:
GC_ADDREF(zobj);
call_getter:
*guard |= IN_GET; /* prevent circular getting */
- zend_std_call_getter(zobj, member, rv);
+ zend_std_call_getter(zobj, name, rv);
*guard &= ~IN_GET;
if (Z_TYPE_P(rv) != IS_UNDEF) {
if (!Z_ISREF_P(rv) &&
(type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET)) {
if (UNEXPECTED(Z_TYPE_P(rv) != IS_OBJECT)) {
- zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", ZSTR_VAL(zobj->ce->name), Z_STRVAL_P(member));
+ zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
}
}
} else {
}
OBJ_RELEASE(zobj);
goto exit;
- } else if (Z_STRVAL_P(member)[0] == '\0' && Z_STRLEN_P(member) != 0) {
+ } else if (ZSTR_VAL(name)[0] == '\0' && ZSTR_LEN(name) != 0) {
zend_throw_error(NULL, "Cannot access property started with '\\0'");
retval = &EG(uninitialized_zval);
goto exit;
}
if ((type != BP_VAR_IS)) {
- zend_error(E_NOTICE,"Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), Z_STRVAL_P(member));
+ zend_error(E_NOTICE,"Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name));
}
retval = &EG(uninitialized_zval);
exit:
- if (UNEXPECTED(Z_REFCOUNTED(tmp_member))) {
- zval_ptr_dtor(&tmp_member);
- }
+ zend_tmp_string_release(tmp_name);
return retval;
}
ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */
{
zend_object *zobj;
- zval tmp_member;
+ zend_string *name, *tmp_name;
zval *variable_ptr;
uintptr_t property_offset;
zobj = Z_OBJ_P(object);
+ name = zval_get_tmp_string(member, &tmp_name);
- ZVAL_UNDEF(&tmp_member);
- if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
- ZVAL_STR(&tmp_member, zval_get_string_func(member));
- member = &tmp_member;
- cache_slot = NULL;
- }
-
- property_offset = zend_get_property_offset(zobj->ce, Z_STR_P(member), (zobj->ce->__set != NULL), cache_slot);
+ property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__set != NULL), cache_slot);
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
variable_ptr = OBJ_PROP(zobj, property_offset);
}
zobj->properties = zend_array_dup(zobj->properties);
}
- if ((variable_ptr = zend_hash_find(zobj->properties, Z_STR_P(member))) != NULL) {
+ if ((variable_ptr = zend_hash_find(zobj->properties, name)) != NULL) {
found:
zend_assign_to_variable(variable_ptr, value, IS_CV);
goto exit;
/* magic set */
if (zobj->ce->__set) {
- uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ uint32_t *guard = zend_get_property_guard(zobj, name);
if (!((*guard) & IN_SET)) {
GC_ADDREF(zobj);
(*guard) |= IN_SET; /* prevent circular setting */
- zend_std_call_setter(zobj, member, value);
+ zend_std_call_setter(zobj, name, value);
(*guard) &= ~IN_SET;
OBJ_RELEASE(zobj);
} else if (EXPECTED(!IS_WRONG_PROPERTY_OFFSET(property_offset))) {
goto write_std_property;
} else {
- if (Z_STRVAL_P(member)[0] == '\0' && Z_STRLEN_P(member) != 0) {
+ if (ZSTR_VAL(name)[0] == '\0' && ZSTR_LEN(name) != 0) {
zend_throw_error(NULL, "Cannot access property started with '\\0'");
goto exit;
}
if (!zobj->properties) {
rebuild_object_properties(zobj);
}
- zend_hash_add_new(zobj->properties, Z_STR_P(member), value);
+ zend_hash_add_new(zobj->properties, name, value);
}
}
exit:
- if (UNEXPECTED(Z_REFCOUNTED(tmp_member))) {
- zval_ptr_dtor(&tmp_member);
- }
+ zend_tmp_string_release(tmp_name);
}
/* }}} */
ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */
{
zend_object *zobj;
- zval tmp_member;
+ zend_string *name, *tmp_name;
uintptr_t property_offset;
zobj = Z_OBJ_P(object);
+ name = zval_get_tmp_string(member, &tmp_name);
- ZVAL_UNDEF(&tmp_member);
- if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
- ZVAL_STR(&tmp_member, zval_get_string_func(member));
- member = &tmp_member;
- cache_slot = NULL;
- }
-
- property_offset = zend_get_property_offset(zobj->ce, Z_STR_P(member), (zobj->ce->__unset != NULL), cache_slot);
+ property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__unset != NULL), cache_slot);
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
zval *slot = OBJ_PROP(zobj, property_offset);
}
zobj->properties = zend_array_dup(zobj->properties);
}
- if (EXPECTED(zend_hash_del(zobj->properties, Z_STR_P(member)) != FAILURE)) {
+ if (EXPECTED(zend_hash_del(zobj->properties, name) != FAILURE)) {
goto exit;
}
} else if (UNEXPECTED(EG(exception))) {
/* magic unset */
if (zobj->ce->__unset) {
- uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ uint32_t *guard = zend_get_property_guard(zobj, name);
if (!((*guard) & IN_UNSET)) {
/* have unseter - try with it! */
(*guard) |= IN_UNSET; /* prevent circular unsetting */
- zend_std_call_unsetter(zobj, member);
+ zend_std_call_unsetter(zobj, name);
(*guard) &= ~IN_UNSET;
} else {
- if (Z_STRVAL_P(member)[0] == '\0' && Z_STRLEN_P(member) != 0) {
+ if (ZSTR_VAL(name)[0] == '\0' && ZSTR_LEN(name) != 0) {
zend_throw_error(NULL, "Cannot access property started with '\\0'");
goto exit;
}
}
exit:
- if (UNEXPECTED(Z_REFCOUNTED(tmp_member))) {
- zval_ptr_dtor(&tmp_member);
- }
+ zend_tmp_string_release(tmp_name);
}
/* }}} */
zend_object *zobj;
int result;
zval *value = NULL;
- zval tmp_member;
+ zend_string *name, *tmp_name;
uintptr_t property_offset;
zobj = Z_OBJ_P(object);
+ name = zval_get_tmp_string(member, &tmp_name);
- ZVAL_UNDEF(&tmp_member);
- if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
- ZVAL_STR(&tmp_member, zval_get_string_func(member));
- member = &tmp_member;
- cache_slot = NULL;
- }
-
- property_offset = zend_get_property_offset(zobj->ce, Z_STR_P(member), 1, cache_slot);
+ property_offset = zend_get_property_offset(zobj->ce, name, 1, cache_slot);
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) {
value = OBJ_PROP(zobj, property_offset);
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
- (EXPECTED(p->key == Z_STR_P(member)) ||
- (EXPECTED(p->h == ZSTR_H(Z_STR_P(member))) &&
+ (EXPECTED(p->key == name) ||
+ (EXPECTED(p->h == ZSTR_H(name)) &&
EXPECTED(p->key != NULL) &&
- EXPECTED(zend_string_equal_content(p->key, Z_STR_P(member)))))) {
+ EXPECTED(zend_string_equal_content(p->key, name))))) {
value = &p->val;
goto found;
}
}
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
}
- value = zend_hash_find(zobj->properties, Z_STR_P(member));
+ value = zend_hash_find(zobj->properties, name);
if (value) {
if (cache_slot) {
uintptr_t idx = (char*)value - (char*)zobj->properties->arData;
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
}
found:
- switch (has_set_exists) {
- case ZEND_PROPERTY_ISSET:
- ZVAL_DEREF(value);
- result = (Z_TYPE_P(value) != IS_NULL);
- break;
- case ZEND_PROPERTY_EXISTS:
- result = 1;
- break;
- case ZEND_PROPERTY_NOT_EMPTY:
- default:
- result = zend_is_true(value);
- break;
+ if (has_set_exists == ZEND_PROPERTY_NOT_EMPTY) {
+ result = zend_is_true(value);
+ } else if (has_set_exists < ZEND_PROPERTY_NOT_EMPTY) {
+ ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_ISSET);
+ ZVAL_DEREF(value);
+ result = (Z_TYPE_P(value) != IS_NULL);
+ } else {
+ ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_EXISTS);
+ result = 1;
}
goto exit;
}
result = 0;
if ((has_set_exists != ZEND_PROPERTY_EXISTS) && zobj->ce->__isset) {
- uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ uint32_t *guard = zend_get_property_guard(zobj, name);
if (!((*guard) & IN_ISSET)) {
zval rv;
/* have issetter - try with it! */
- if (Z_TYPE(tmp_member) == IS_UNDEF) {
- ZVAL_COPY(&tmp_member, member);
- member = &tmp_member;
+ if (!tmp_name && !ZSTR_IS_INTERNED(name)) {
+ tmp_name = zend_string_copy(name);
}
GC_ADDREF(zobj);
(*guard) |= IN_ISSET; /* prevent circular getting */
- zend_std_call_issetter(zobj, member, &rv);
+ zend_std_call_issetter(zobj, name, &rv);
result = zend_is_true(&rv);
zval_ptr_dtor(&rv);
if (has_set_exists == ZEND_PROPERTY_NOT_EMPTY && result) {
if (EXPECTED(!EG(exception)) && zobj->ce->__get && !((*guard) & IN_GET)) {
(*guard) |= IN_GET;
- zend_std_call_getter(zobj, member, &rv);
+ zend_std_call_getter(zobj, name, &rv);
(*guard) &= ~IN_GET;
result = i_zend_is_true(&rv);
zval_ptr_dtor(&rv);
}
exit:
- if (UNEXPECTED(Z_REFCOUNTED(tmp_member))) {
- zval_ptr_dtor(&tmp_member);
- }
+ zend_tmp_string_release(tmp_name);
return result;
}
/* }}} */