if (old_function->type == ZEND_USER_FUNCTION
&& old_function->op_array.last > 0) {
zend_error_noreturn(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
- ZSTR_VAL(op_array->function_name),
+ op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name),
ZSTR_VAL(old_function->op_array.filename),
old_function->op_array.opcodes[0].lineno);
} else {
- zend_error_noreturn(error_level, "Cannot redeclare %s()", ZSTR_VAL(op_array->function_name));
+ zend_error_noreturn(error_level, "Cannot redeclare %s()",
+ op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name));
}
}
ZEND_API int do_bind_function(zval *lcname) /* {{{ */
{
- zend_function *function, *new_function;
+ zend_function *function;
zval *rtd_key, *zv;
rtd_key = lcname + 1;
zv = zend_hash_find_ex(EG(function_table), Z_STR_P(rtd_key), 1);
- new_function = function = (zend_function*)Z_PTR_P(zv);
- if (function->op_array.static_variables
- && !(function->op_array.fn_flags & ZEND_ACC_IMMUTABLE)) {
- new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
- memcpy(new_function, function, sizeof(zend_op_array));
- function->op_array.static_variables = NULL; /* NULL out the unbound function */
- if (function->op_array.refcount) {
- (*function->op_array.refcount)++;
- }
- }
- if (UNEXPECTED(zend_hash_add_ptr(EG(function_table), Z_STR_P(lcname), new_function) == NULL)) {
- do_bind_function_error(Z_STR_P(lcname), &new_function->op_array, 0);
+ if (UNEXPECTED(!zv)) {
+ do_bind_function_error(Z_STR_P(lcname), NULL, 0);
+ return FAILURE;
+ }
+ function = (zend_function*)Z_PTR_P(zv);
+ zv = zend_hash_set_bucket_key(EG(function_table), (Bucket*)zv, Z_STR_P(lcname));
+ if (UNEXPECTED(!zv)) {
+ do_bind_function_error(Z_STR_P(lcname), &function->op_array, 0);
return FAILURE;
}
return SUCCESS;
rtd_key = lcname + 1;
zv = zend_hash_find_ex(EG(class_table), Z_STR_P(rtd_key), 1);
- ZEND_ASSERT(zv);
- ce = (zend_class_entry*)Z_PTR_P(zv);
+ if (UNEXPECTED(!zv)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s, because the name is already in use", Z_STRVAL_P(lcname));
+ return FAILURE;
+ }
- if (UNEXPECTED(zend_hash_add_ptr(EG(class_table), Z_STR_P(lcname), ce) == NULL)) {
- /* If we're in compile time, in practice, it's quite possible
- * that we'll never reach this class declaration at runtime,
- * so we shut up about it. This allows the if (!defined('FOO')) { return; }
- * approach to work.
- */
+ ce = (zend_class_entry*)Z_PTR_P(zv);
+ zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
+ if (UNEXPECTED(!zv)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
return FAILURE;
- } else {
- ce->refcount++;
- zend_do_link_class(ce, NULL);
- return SUCCESS;
}
+
+ zend_do_link_class(ce, NULL);
+ return SUCCESS;
}
/* }}} */
zv = zend_hash_find_ex(EG(class_table), Z_STR_P(rtd_key), 1);
- if (!zv) {
+ if (UNEXPECTED(!zv)) {
/* If we're in compile time, in practice, it's quite possible
* that we'll never reach this class declaration at runtime,
* so we shut up about it. This allows the if (!defined('FOO')) { return; }
return FAILURE;
}
- ce = (zend_class_entry*)Z_PTR_P(zv);
-
- ce->refcount++;
-
/* Register the derived class */
- if (zend_hash_add_ptr(EG(class_table), Z_STR_P(lcname), ce) == NULL) {
+ ce = (zend_class_entry*)Z_PTR_P(zv);
+ zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
+ if (UNEXPECTED(!zv)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
+ return FAILURE;
}
zend_do_link_class(ce, parent_ce);
-
return SUCCESS;
}
/* }}} */
return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEW | HASH_ADD_NEXT);
}
+ZEND_API zval* ZEND_FASTCALL zend_hash_set_bucket_key(HashTable *ht, Bucket *b, zend_string *key)
+{
+ uint32_t nIndex;
+ uint32_t idx, i;
+ Bucket *p, *arData;
+
+ IS_CONSISTENT(ht);
+ HT_ASSERT_RC1(ht);
+ ZEND_ASSERT(!(HT_FLAGS(ht) & HASH_FLAG_PACKED));
+
+ p = zend_hash_find_bucket(ht, key, 0);
+ if (UNEXPECTED(p)) {
+ return (p == b) ? &p->val : NULL;
+ }
+
+ if (!ZSTR_IS_INTERNED(key)) {
+ zend_string_addref(key);
+ HT_FLAGS(ht) &= ~HASH_FLAG_STATIC_KEYS;
+ }
+
+ arData = ht->arData;
+
+ /* del from hash */
+ idx = HT_IDX_TO_HASH(b - arData);
+ nIndex = b->h | ht->nTableMask;
+ i = HT_HASH_EX(arData, nIndex);
+ if (i == idx) {
+ HT_HASH_EX(arData, nIndex) = Z_NEXT(b->val);
+ } else {
+ p = HT_HASH_TO_BUCKET_EX(arData, i);
+ while (Z_NEXT(p->val) != idx) {
+ i = Z_NEXT(p->val);
+ p = HT_HASH_TO_BUCKET_EX(arData, i);
+ }
+ Z_NEXT(p->val) = Z_NEXT(b->val);
+ }
+ zend_string_release(b->key);
+
+ /* add to hash */
+ idx = b - arData;
+ b->key = key;
+ b->h = ZSTR_H(key);
+ nIndex = b->h | ht->nTableMask;
+ Z_NEXT(b->val) = HT_HASH_EX(arData, nIndex);
+ HT_HASH_EX(arData, nIndex) = HT_IDX_TO_HASH(idx);
+
+ return &b->val;
+}
+
static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
{