diff options
-rw-r--r-- | Zend/zend.c | 4 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 5 | ||||
-rw-r--r-- | Zend/zend_closures.c | 4 | ||||
-rw-r--r-- | Zend/zend_compile.c | 3 | ||||
-rw-r--r-- | Zend/zend_hash.c | 141 | ||||
-rw-r--r-- | Zend/zend_hash.h | 9 | ||||
-rw-r--r-- | Zend/zend_operators.c | 3 | ||||
-rw-r--r-- | Zend/zend_variables.c | 3 | ||||
-rw-r--r-- | ext/dom/php_dom.c | 3 | ||||
-rw-r--r-- | ext/gmp/gmp.c | 3 | ||||
-rw-r--r-- | ext/soap/soap.c | 6 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 16 | ||||
-rw-r--r-- | ext/spl/spl_directory.c | 3 | ||||
-rw-r--r-- | ext/spl/spl_observer.c | 4 | ||||
-rw-r--r-- | ext/standard/array.c | 20 | ||||
-rw-r--r-- | ext/standard/browscap.c | 4 |
16 files changed, 170 insertions, 61 deletions
diff --git a/Zend/zend.c b/Zend/zend.c index eccd477f77..f7f78f30df 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1166,8 +1166,8 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ if (!EG(active_symbol_table)) { ZVAL_NULL(¶ms[4]); } else { - array_init_size(¶ms[4], zend_hash_num_elements(&EG(active_symbol_table)->ht)); - zend_hash_copy(Z_ARRVAL(params[4]), &EG(active_symbol_table)->ht, zval_add_ref); + ZVAL_NEW_ARR(¶ms[4]); + zend_array_dup(Z_ARRVAL(params[4]), &EG(active_symbol_table)->ht); } ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler)); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index d8b828763f..77743fbd32 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1713,9 +1713,8 @@ ZEND_FUNCTION(get_defined_vars) zend_rebuild_symbol_table(TSRMLS_C); } - array_init_size(return_value, zend_hash_num_elements(&EG(active_symbol_table)->ht)); - - zend_hash_copy(Z_ARRVAL_P(return_value), &EG(active_symbol_table)->ht, zval_add_ref); + ZVAL_NEW_ARR(return_value); + zend_array_dup(Z_ARRVAL_P(return_value), &EG(active_symbol_table)->ht); } /* }}} */ diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 1eae481829..96252e8be0 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -297,8 +297,8 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_ if (closure->debug_info->u.v.nApplyCount == 0) { if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) { HashTable *static_variables = closure->func.op_array.static_variables; - array_init(&val); - zend_hash_copy(Z_ARRVAL(val), static_variables, zval_add_ref); + ZVAL_NEW_ARR(&val); + zend_array_dup(Z_ARRVAL(val), static_variables); zend_hash_str_update(closure->debug_info, "static", sizeof("static")-1, &val); } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5f2cbbfde4..20e4b5f341 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3076,8 +3076,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */ HashTable *static_variables = op_array->static_variables; ALLOC_HASHTABLE(op_array->static_variables); - 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, zval_add_ref); + zend_array_dup(op_array->static_variables, static_variables); } op_array->run_time_cache = NULL; } else if (function->type == ZEND_INTERNAL_FUNCTION) { diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 695f05d225..ee1dcb2501 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -1070,6 +1070,131 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun } +ZEND_API void zend_array_dup(HashTable *target, HashTable *source) +{ + uint idx, target_idx; + uint nIndex; + Bucket *p, *q; + zval *data; + + IS_CONSISTENT(source); + + target->nTableMask = source->nTableMask; + target->nTableSize = source->nTableSize; + target->pDestructor = source->pDestructor; + target->nInternalPointer = INVALID_IDX; + target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT); + + target_idx = 0; + if (target->nTableMask) { + if (target->u.flags & HASH_FLAG_PACKED) { + target->nNumUsed = source->nNumUsed; + target->nNumOfElements = source->nNumOfElements; + target->nNextFreeElement = source->nNextFreeElement; + target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket), 0, 0); + target->arHash = (zend_uint*)&uninitialized_bucket; + target->nInternalPointer = source->nInternalPointer; + + for (idx = 0; idx < source->nNumUsed; idx++) { + p = source->arData + idx; + q = target->arData + idx; + if (Z_TYPE(p->val) == IS_UNDEF) { + q->h = 0; + q->key = NULL; + ZVAL_UNDEF(&q->val); + continue; + } + /* INDIRECT element may point to UNDEF-ined slots */ + data = &p->val; + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + if (Z_TYPE_P(data) == IS_UNDEF) { + q->h = 0; + q->key = NULL; + ZVAL_UNDEF(&q->val); + continue; + } + } + + q->h = p->h; + q->key = NULL; + if (Z_OPT_REFCOUNTED_P(data)) { + if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) { + ZVAL_DUP(&q->val, Z_REFVAL_P(data)); + } else { + ZVAL_COPY(&q->val, data); + } + } else { + ZVAL_COPY_VALUE(&q->val, data); + } + } + if (target->nNumOfElements > 0 && + target->nInternalPointer == INVALID_IDX) { + idx = 0; + while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) { + idx++; + } + target->nInternalPointer = idx; + } + } else { + target->nNextFreeElement = source->nNextFreeElement; + target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket) + sizeof(zend_uint), 0, 0); + target->arHash = (zend_uint*)(target->arData + target->nTableSize); + memset(target->arHash, INVALID_IDX, target->nTableSize * sizeof(zend_uint)); + + for (idx = 0; idx < source->nNumUsed; idx++) { + p = source->arData + idx; + if (Z_TYPE(p->val) == IS_UNDEF) continue; + /* INDIRECT element may point to UNDEF-ined slots */ + data = &p->val; + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + if (Z_TYPE_P(data) == IS_UNDEF) { + continue; + } + } + + if (source->nInternalPointer == idx) { + target->nInternalPointer = target_idx; + } + + q = target->arData + target_idx; + q->h = p->h; + q->key = p->key; + if (q->key) { + STR_ADDREF(q->key); + } + nIndex = q->h & target->nTableMask; + Z_NEXT(q->val) = target->arHash[nIndex]; + target->arHash[nIndex] = target_idx; + if (Z_OPT_REFCOUNTED_P(data)) { + if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) { + ZVAL_DUP(&q->val, Z_REFVAL_P(data)); + } else { + ZVAL_COPY(&q->val, data); + } + } else { + ZVAL_COPY_VALUE(&q->val, data); + } + target_idx++; + } + target->nNumUsed = target_idx; + target->nNumOfElements = target_idx; + if (target->nNumOfElements > 0 && + target->nInternalPointer == INVALID_IDX) { + target->nInternalPointer = 0; + } + } + } else { + target->nNumUsed = 0; + target->nNumOfElements = 0; + target->nNextFreeElement = 0; + target->arData = NULL; + target->arHash = (zend_uint*)&uninitialized_bucket; + } +} + + ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite ZEND_FILE_LINE_DC) { uint idx; @@ -1251,14 +1376,6 @@ ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h) } -ZEND_API int zend_hash_num_elements(const HashTable *ht) -{ - IS_CONSISTENT(ht); - - return ht->nNumOfElements; -} - - ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr) { ptr->pos = ht->nInternalPointer; @@ -1673,14 +1790,6 @@ ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, int return &res->val; } -ZEND_API ulong zend_hash_next_free_element(const HashTable *ht) -{ - IS_CONSISTENT(ht); - - return ht->nNextFreeElement; - -} - /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 6f6d9f0ec7..04fc311a52 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -134,7 +134,6 @@ ZEND_API zval *zend_hash_index_find(const HashTable *ht, ulong h); ZEND_API int zend_hash_exists(const HashTable *ht, zend_string *key); ZEND_API int zend_hash_str_exists(const HashTable *ht, const char *str, int len); ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h); -ZEND_API ulong zend_hash_next_free_element(const HashTable *ht); /* traversing */ #define zend_hash_has_more_elements_ex(ht, pos) \ @@ -187,10 +186,16 @@ ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, int #define zend_hash_merge(target, source, pCopyConstructor, overwrite) \ _zend_hash_merge(target, source, pCopyConstructor, overwrite ZEND_FILE_LINE_CC) -ZEND_API int zend_hash_num_elements(const HashTable *ht); +#define zend_hash_num_elements(ht) \ + (ht)->nNumOfElements + +#define zend_hash_next_free_element(ht) \ + (ht)->nNextFreeElement ZEND_API int zend_hash_rehash(HashTable *ht); +ZEND_API void zend_array_dup(HashTable *target, HashTable *source); + #if ZEND_DEBUG /* debug */ void zend_hash_display_pListTail(const HashTable *ht); diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index b8ab22fc06..a1554164a0 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -671,8 +671,7 @@ ZEND_API void convert_to_array(zval *op) /* {{{ */ if (obj_ht) { zval arr; ZVAL_NEW_ARR(&arr); - zend_hash_init(Z_ARRVAL(arr), zend_hash_num_elements(obj_ht), NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(Z_ARRVAL(arr), obj_ht, zval_add_ref); + zend_array_dup(Z_ARRVAL(arr), obj_ht); zval_dtor(op); ZVAL_COPY_VALUE(op, &arr); return; diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index ccdef2246c..ac65d9d18c 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -245,8 +245,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC) } ht = Z_ARRVAL_P(zvalue); ZVAL_NEW_ARR(zvalue); - zend_hash_init(Z_ARRVAL_P(zvalue), zend_hash_num_elements(ht), NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(Z_ARRVAL_P(zvalue), ht, zval_add_ref); + zend_array_dup(Z_ARRVAL_P(zvalue), ht); } break; case IS_CONSTANT_AST: { diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 77bf91920f..7120a7ee08 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -425,10 +425,9 @@ static HashTable* dom_get_debug_info_helper(zval *object, int *is_temp TSRMLS_DC *is_temp = 1; ALLOC_HASHTABLE(debug_info); - ZEND_INIT_SYMTABLE_EX(debug_info, 32, 0); std_props = zend_std_get_properties(object TSRMLS_CC); - zend_hash_copy(debug_info, std_props, (copy_ctor_func_t) zval_add_ref); + zend_array_dup(debug_info, std_props); if (!prop_handlers) { return debug_info; diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index e2ece55869..17ec39d087 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -429,8 +429,7 @@ static HashTable *gmp_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ * *is_temp = 1; ALLOC_HASHTABLE(ht); - ZEND_INIT_SYMTABLE_EX(ht, zend_hash_num_elements(props) + 1, 0); - zend_hash_copy(ht, props, (copy_ctor_func_t) zval_add_ref); + zend_array_dup(ht, props); gmp_strval(&zv, gmpnum, 10); zend_hash_str_update(ht, "num", sizeof("num")-1, &zv); diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 9660c32e24..5d2eaae9aa 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -1178,8 +1178,7 @@ PHP_METHOD(SoapServer, SoapServer) if ((tmp = zend_hash_str_find(ht, "classmap", sizeof("classmap")-1)) != NULL && Z_TYPE_P(tmp) == IS_ARRAY) { ALLOC_HASHTABLE(service->class_map); - zend_hash_init(service->class_map, zend_hash_num_elements(Z_ARRVAL_P(tmp)), NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(service->class_map, Z_ARRVAL_P(tmp), zval_add_ref); + zend_array_dup(service->class_map, Z_ARRVAL_P(tmp)); } if ((tmp = zend_hash_str_find(ht, "typemap", sizeof("typemap")-1)) != NULL && @@ -2904,8 +2903,7 @@ PHP_METHOD(SoapClient, __call) if (soap_headers) { if (!free_soap_headers) { HashTable *t = emalloc(sizeof(HashTable)); - zend_hash_init(t, 0, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(t, soap_headers, zval_add_ref); + zend_array_dup(t, soap_headers); soap_headers = t; free_soap_headers = 1; } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 5c873f36a4..2fa7a53dd3 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -198,8 +198,8 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval * if (clone_orig) { intern->array = other->array; if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayObject) { - array_init(&intern->array); - zend_hash_copy(HASH_OF(&intern->array), HASH_OF(&other->array), (copy_ctor_func_t) zval_add_ref); + ZVAL_NEW_ARR(&intern->array); + zend_array_dup(Z_ARRVAL(intern->array), HASH_OF(&other->array)); } if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayIterator) { Z_ADDREF_P(&other->array); @@ -824,8 +824,8 @@ SPL_METHOD(Array, getArrayCopy) zval *object = getThis(); spl_array_object *intern = Z_SPLARRAY_P(object); - array_init(return_value); - zend_hash_copy(Z_ARRVAL_P(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC), (copy_ctor_func_t) zval_add_ref); + ZVAL_NEW_ARR(return_value); + zend_array_dup(Z_ARRVAL_P(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC)); } /* }}} */ static HashTable *spl_array_get_properties(zval *object TSRMLS_DC) /* {{{ */ @@ -1323,8 +1323,8 @@ SPL_METHOD(Array, exchangeArray) zval *object = getThis(), *array; spl_array_object *intern = Z_SPLARRAY_P(object); - array_init(return_value); - zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC), (copy_ctor_func_t)zval_add_ref); + ZVAL_NEW_ARR(return_value); + zend_array_dup(Z_ARRVAL_P(return_value), spl_array_get_hash_table(intern, 0 TSRMLS_CC)); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &array) == FAILURE) { return; } @@ -1745,8 +1745,8 @@ SPL_METHOD(Array, serialize) rebuild_object_properties(&intern->std); } - array_init(&members); - zend_hash_copy(Z_ARRVAL(members), intern->std.properties, (copy_ctor_func_t)zval_add_ref); + ZVAL_NEW_ARR(&members); + zend_array_dup(Z_ARRVAL(members), intern->std.properties); php_var_serialize(&buf, &members, &var_hash TSRMLS_CC); /* finishes the string */ diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index ca7baf2226..9405dafa0d 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -589,9 +589,8 @@ static HashTable *spl_filesystem_object_get_debug_info(zval *object, int *is_tem } ALLOC_HASHTABLE(rv); - ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0); - zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref); + zend_array_dup(rv, intern->std.properties); pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1 TSRMLS_CC); path = spl_filesystem_object_get_pathname(intern, &path_len TSRMLS_CC); diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 52279c3429..4ccd345df1 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -772,8 +772,8 @@ SPL_METHOD(SplObjectStorage, serialize) /* members */ smart_str_appendl(&buf, "m:", 2); - array_init(&members); - zend_hash_copy(Z_ARRVAL(members), zend_std_get_properties(getThis() TSRMLS_CC), (copy_ctor_func_t) zval_add_ref); + ZVAL_NEW_ARR(&members); + zend_array_dup(Z_ARRVAL(members), zend_std_get_properties(getThis() TSRMLS_CC)); php_var_serialize(&buf, &members, &var_hash TSRMLS_CC); /* finishes the string */ zval_ptr_dtor(&members); diff --git a/ext/standard/array.c b/ext/standard/array.c index b8e0409d06..97ab2583f6 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2811,8 +2811,8 @@ PHP_FUNCTION(array_unique) php_set_compare_func(sort_type TSRMLS_CC); - array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array))); - zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array), zval_add_ref); + ZVAL_NEW_ARR(return_value); + zend_array_dup(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array)); if (Z_ARRVAL_P(array)->nNumOfElements <= 1) { /* nothing to do */ return; @@ -3164,8 +3164,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int HashTable *old_ht = Z_ARRVAL_P(return_value); ZVAL_NEW_ARR(return_value); - zend_hash_init(Z_ARRVAL_P(return_value), zend_hash_num_elements(old_ht), NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(Z_ARRVAL_P(return_value), old_ht, zval_add_ref); + zend_array_dup(Z_ARRVAL_P(return_value), old_ht); } /* go through the lists and look for common values */ @@ -3584,8 +3583,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ HashTable *old_ht = Z_ARRVAL_P(return_value); ZVAL_NEW_ARR(return_value); - zend_hash_init(Z_ARRVAL_P(return_value), zend_hash_num_elements(old_ht), NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(Z_ARRVAL_P(return_value), old_ht, zval_add_ref); + zend_array_dup(Z_ARRVAL_P(return_value), old_ht); } /* go through the lists and look for values of ptr[0] that are not in the others */ @@ -3942,17 +3940,23 @@ PHP_FUNCTION(array_multisort) /* Restructure the arrays based on sorted indirect - this is mostly taken from zend_hash_sort() function. */ HANDLE_BLOCK_INTERRUPTIONS(); for (i = 0; i < num_arrays; i++) { + int repack; + hash = Z_ARRVAL_P(arrays[i]); hash->nNumUsed = array_size; hash->nInternalPointer = 0; + repack = !(hash->u.flags & HASH_FLAG_PACKED); for (n = 0, k = 0; k < array_size; k++) { hash->arData[k] = indirect[k][i]; - if (hash->arData[k].key == NULL) + if (hash->arData[k].key == NULL) { hash->arData[k].h = n++; + } else { + repack = 0; + } } hash->nNextFreeElement = array_size; - if (!(hash->u.flags & HASH_FLAG_PACKED)) { + if (repack) { zend_hash_to_packed(hash); } } diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c index 186c30cc90..fc68a34f8c 100644 --- a/ext/standard/browscap.c +++ b/ext/standard/browscap.c @@ -494,8 +494,8 @@ PHP_FUNCTION(get_browser) } if (return_array) { - array_init(return_value); - zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(agent), (copy_ctor_func_t) browscap_zval_copy_ctor); + ZVAL_NEW_ARR(return_value); + zend_array_dup(Z_ARRVAL_P(return_value), Z_ARRVAL_P(agent)); } else { object_init(return_value); |