mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master: Don't make difference between undefined and unaccessible properies when call __get() and family Don't make useless CSE array_pop/array_shift optimization
This commit is contained in:
commit
83b8e281db
@ -423,41 +423,19 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_long *zend_get_property_guard(zend_object *zobj, zend_property_info *property_info, zval *member) /* {{{ */
|
||||
static zend_long *zend_get_property_guard(zend_object *zobj, zval *member) /* {{{ */
|
||||
{
|
||||
zend_property_info info;
|
||||
zval stub, *guard;
|
||||
zend_string *str = NULL;
|
||||
|
||||
if (!property_info) {
|
||||
property_info = &info;
|
||||
info.name = Z_STR_P(member);
|
||||
} else if(property_info->name->val[0] == '\0'){
|
||||
const char *class_name = NULL, *prop_name = NULL;
|
||||
size_t prop_name_len;
|
||||
zend_unmangle_property_name_ex(property_info->name, &class_name,
|
||||
&prop_name, &prop_name_len);
|
||||
if (class_name) {
|
||||
/* use unmangled name for protected properties */
|
||||
str = info.name = zend_string_init(prop_name, prop_name_len, 0);
|
||||
property_info = &info;
|
||||
}
|
||||
}
|
||||
if (!zobj->guards) {
|
||||
ALLOC_HASHTABLE(zobj->guards);
|
||||
zend_hash_init(zobj->guards, 8, NULL, NULL, 0);
|
||||
} else if ((guard = zend_hash_find(zobj->guards, property_info->name)) != NULL) {
|
||||
if (str) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if ((guard = zend_hash_find(zobj->guards, Z_STR_P(member))) != NULL) {
|
||||
return &Z_LVAL_P(guard);
|
||||
}
|
||||
|
||||
ZVAL_LONG(&stub, 0);
|
||||
guard = zend_hash_add_new(zobj->guards, property_info->name, &stub);
|
||||
if (str) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
guard = zend_hash_add_new(zobj->guards, Z_STR_P(member), &stub);
|
||||
return &Z_LVAL_P(guard);
|
||||
}
|
||||
/* }}} */
|
||||
@ -468,9 +446,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
|
||||
zval tmp_member;
|
||||
zval *retval;
|
||||
zend_property_info *property_info;
|
||||
int silent;
|
||||
|
||||
silent = (type == BP_VAR_IS);
|
||||
zobj = Z_OBJ_P(object);
|
||||
|
||||
ZVAL_UNDEF(&tmp_member);
|
||||
@ -485,7 +461,7 @@ 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), silent || (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), cache_slot TSRMLS_CC);
|
||||
|
||||
if (EXPECTED(property_info != NULL)) {
|
||||
if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
|
||||
@ -502,7 +478,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
|
||||
|
||||
/* magic get */
|
||||
if (zobj->ce->__get) {
|
||||
zend_long *guard = zend_get_property_guard(zobj, property_info, member);
|
||||
zend_long *guard = zend_get_property_guard(zobj, member);
|
||||
if (!((*guard) & IN_GET)) {
|
||||
zval tmp_object;
|
||||
|
||||
@ -533,13 +509,13 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
|
||||
zend_error(E_ERROR, "Cannot access property started with '\\0'");
|
||||
}
|
||||
}
|
||||
if (!silent) {
|
||||
if (type != BP_VAR_IS) {
|
||||
zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member));
|
||||
}
|
||||
retval = &EG(uninitialized_zval);
|
||||
}
|
||||
} else {
|
||||
if (!silent) {
|
||||
if ((type != BP_VAR_IS)) {
|
||||
zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name->val, Z_STRVAL_P(member));
|
||||
}
|
||||
retval = &EG(uninitialized_zval);
|
||||
@ -635,7 +611,7 @@ found:
|
||||
|
||||
/* magic set */
|
||||
if (zobj->ce->__set) {
|
||||
zend_long *guard = zend_get_property_guard(zobj, property_info, member);
|
||||
zend_long *guard = zend_get_property_guard(zobj, member);
|
||||
|
||||
if (!((*guard) & IN_SET)) {
|
||||
zval tmp_object;
|
||||
@ -809,7 +785,7 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
|
||||
}
|
||||
|
||||
if (!zobj->ce->__get ||
|
||||
(guard = zend_get_property_guard(zobj, property_info, member)) == NULL ||
|
||||
(guard = zend_get_property_guard(zobj, member)) == NULL ||
|
||||
(property_info && ((*guard) & IN_GET))) {
|
||||
|
||||
ZVAL_NULL(&tmp);
|
||||
@ -875,7 +851,7 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo
|
||||
|
||||
/* magic unset */
|
||||
if (zobj->ce->__unset) {
|
||||
zend_long *guard = zend_get_property_guard(zobj, property_info, member);
|
||||
zend_long *guard = zend_get_property_guard(zobj, member);
|
||||
if (!((*guard) & IN_UNSET)) {
|
||||
zval tmp_object;
|
||||
|
||||
@ -1483,7 +1459,7 @@ found:
|
||||
|
||||
result = 0;
|
||||
if ((has_set_exists != 2) && zobj->ce->__isset) {
|
||||
zend_long *guard = zend_get_property_guard(zobj, property_info, member);
|
||||
zend_long *guard = zend_get_property_guard(zobj, member);
|
||||
|
||||
if (!((*guard) & IN_ISSET)) {
|
||||
zval rv;
|
||||
|
@ -1992,13 +1992,14 @@ PHP_FUNCTION(array_push)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) */
|
||||
static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end)
|
||||
/* {{{ proto mixed array_pop(array stack)
|
||||
Pops an element off the end of the array */
|
||||
PHP_FUNCTION(array_pop)
|
||||
{
|
||||
zval *stack, /* Input stack */
|
||||
*val; /* Value to be popped */
|
||||
zend_string *key = NULL;
|
||||
zend_ulong index;
|
||||
uint32_t idx;
|
||||
Bucket *p;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &stack) == FAILURE) {
|
||||
@ -2014,56 +2015,118 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the first or last value and copy it into the return value */
|
||||
if (off_the_end) {
|
||||
zend_hash_internal_pointer_end(Z_ARRVAL_P(stack));
|
||||
while (1) {
|
||||
val = zend_hash_get_current_data(Z_ARRVAL_P(stack));
|
||||
if (!val) {
|
||||
return;
|
||||
} else if (Z_TYPE_P(val) == IS_INDIRECT) {
|
||||
val = Z_INDIRECT_P(val);
|
||||
if (Z_TYPE_P(val) == IS_UNDEF) {
|
||||
zend_hash_move_backwards(Z_ARRVAL_P(stack));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* Get the last value and copy it into the return value */
|
||||
idx = Z_ARRVAL_P(stack)->nNumUsed;
|
||||
while (1) {
|
||||
if (idx == 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
|
||||
while (1) {
|
||||
val = zend_hash_get_current_data(Z_ARRVAL_P(stack));
|
||||
if (!val) {
|
||||
return;
|
||||
} else if (Z_TYPE_P(val) == IS_INDIRECT) {
|
||||
val = Z_INDIRECT_P(val);
|
||||
if (Z_TYPE_P(val) == IS_UNDEF) {
|
||||
zend_hash_move_forward(Z_ARRVAL_P(stack));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
idx--;
|
||||
p = Z_ARRVAL_P(stack)->arData + idx;
|
||||
val = &p->val;
|
||||
if (Z_TYPE_P(val) == IS_INDIRECT) {
|
||||
val = Z_INDIRECT_P(val);
|
||||
}
|
||||
if (Z_TYPE_P(val) != IS_UNDEF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
RETVAL_ZVAL_FAST(val);
|
||||
ZVAL_DEREF(val);
|
||||
ZVAL_COPY(return_value, val);
|
||||
|
||||
/* Delete the first or last value */
|
||||
zend_hash_get_current_key(Z_ARRVAL_P(stack), &key, &index, 0);
|
||||
if (key && Z_ARRVAL_P(stack) == &EG(symbol_table).ht) {
|
||||
zend_delete_global_variable(key TSRMLS_CC);
|
||||
} else if (key) {
|
||||
zend_hash_del(Z_ARRVAL_P(stack), key);
|
||||
} else {
|
||||
zend_hash_index_del(Z_ARRVAL_P(stack), index);
|
||||
if (!p->key && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && p->h >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) {
|
||||
Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
|
||||
}
|
||||
|
||||
/* If we did a shift... re-index like it did before */
|
||||
if (!off_the_end) {
|
||||
unsigned int k = 0;
|
||||
/* Delete the last value */
|
||||
if (p->key) {
|
||||
if (Z_ARRVAL_P(stack) == &EG(symbol_table).ht) {
|
||||
zend_delete_global_variable(p->key TSRMLS_CC);
|
||||
} else {
|
||||
zend_hash_del(Z_ARRVAL_P(stack), p->key);
|
||||
}
|
||||
} else {
|
||||
zend_hash_index_del(Z_ARRVAL_P(stack), p->h);
|
||||
}
|
||||
|
||||
zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed array_shift(array stack)
|
||||
Pops an element off the beginning of the array */
|
||||
PHP_FUNCTION(array_shift)
|
||||
{
|
||||
zval *stack, /* Input stack */
|
||||
*val; /* Value to be popped */
|
||||
uint32_t idx;
|
||||
Bucket *p;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &stack) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_ARRAY_EX(stack, 0, 1)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the first value and copy it into the return value */
|
||||
idx = 0;
|
||||
while (1) {
|
||||
if (idx == Z_ARRVAL_P(stack)->nNumUsed) {
|
||||
return;
|
||||
}
|
||||
p = Z_ARRVAL_P(stack)->arData + idx;
|
||||
val = &p->val;
|
||||
if (Z_TYPE_P(val) == IS_INDIRECT) {
|
||||
val = Z_INDIRECT_P(val);
|
||||
}
|
||||
if (Z_TYPE_P(val) != IS_UNDEF) {
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
ZVAL_DEREF(val);
|
||||
ZVAL_COPY(return_value, val);
|
||||
|
||||
/* Delete the first value */
|
||||
if (p->key) {
|
||||
if (Z_ARRVAL_P(stack) == &EG(symbol_table).ht) {
|
||||
zend_delete_global_variable(p->key TSRMLS_CC);
|
||||
} else {
|
||||
zend_hash_del(Z_ARRVAL_P(stack), p->key);
|
||||
}
|
||||
} else {
|
||||
zend_hash_index_del(Z_ARRVAL_P(stack), p->h);
|
||||
}
|
||||
|
||||
/* re-index like it did before */
|
||||
if (Z_ARRVAL_P(stack)->u.flags & HASH_FLAG_PACKED) {
|
||||
uint32_t k = 0;
|
||||
|
||||
for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) {
|
||||
p = Z_ARRVAL_P(stack)->arData + idx;
|
||||
if (Z_TYPE(p->val) == IS_UNDEF) continue;
|
||||
if (idx != k) {
|
||||
Bucket *q = Z_ARRVAL_P(stack)->arData + k;
|
||||
q->h = k;
|
||||
q->key = NULL;
|
||||
ZVAL_COPY_VALUE(&q->val, &p->val);
|
||||
ZVAL_UNDEF(&p->val);
|
||||
}
|
||||
k++;
|
||||
}
|
||||
Z_ARRVAL_P(stack)->nNumUsed = k;
|
||||
Z_ARRVAL_P(stack)->nNextFreeElement = k;
|
||||
} else {
|
||||
uint32_t k = 0;
|
||||
int should_rehash = 0;
|
||||
uint idx;
|
||||
Bucket *p;
|
||||
|
||||
for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) {
|
||||
p = Z_ARRVAL_P(stack)->arData + idx;
|
||||
@ -2079,36 +2142,14 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end)
|
||||
}
|
||||
Z_ARRVAL_P(stack)->nNextFreeElement = k;
|
||||
if (should_rehash) {
|
||||
if (Z_ARRVAL_P(stack)->u.flags & HASH_FLAG_PACKED) {
|
||||
zend_hash_packed_to_hash(Z_ARRVAL_P(stack));
|
||||
} else {
|
||||
zend_hash_rehash(Z_ARRVAL_P(stack));
|
||||
}
|
||||
zend_hash_rehash(Z_ARRVAL_P(stack));
|
||||
}
|
||||
} else if (!key && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && index >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) {
|
||||
Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
|
||||
}
|
||||
|
||||
zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed array_pop(array stack)
|
||||
Pops an element off the end of the array */
|
||||
PHP_FUNCTION(array_pop)
|
||||
{
|
||||
_phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed array_shift(array stack)
|
||||
Pops an element off the beginning of the array */
|
||||
PHP_FUNCTION(array_shift)
|
||||
{
|
||||
_phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int array_unshift(array stack, mixed var [, mixed ...])
|
||||
Pushes elements onto the beginning of the array */
|
||||
PHP_FUNCTION(array_unshift)
|
||||
|
Loading…
Reference in New Issue
Block a user