diff options
-rw-r--r-- | Zend/zend_builtin_functions.c | 107 | ||||
-rw-r--r-- | Zend/zend_hash.h | 27 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 33 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 33 | ||||
-rw-r--r-- | ext/standard/array.c | 33 |
5 files changed, 139 insertions, 94 deletions
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 3e66e9275c..6ba0965ede 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -456,7 +456,7 @@ ZEND_FUNCTION(func_get_arg) Get an array of the arguments that were passed to the function */ ZEND_FUNCTION(func_get_args) { - zval *p; + zval *p, *q; uint32_t arg_count, first_extra_arg; uint32_t i; zend_execute_data *ex = EX(prev_execute_data); @@ -470,44 +470,47 @@ ZEND_FUNCTION(func_get_args) array_init_size(return_value, arg_count); if (arg_count) { - Bucket *q; - first_extra_arg = ex->func->op_array.num_args; zend_hash_real_init(Z_ARRVAL_P(return_value), 1); - i = 0; - q = Z_ARRVAL_P(return_value)->arData; - p = ZEND_CALL_ARG(ex, 1); - if (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg) { - while (i < first_extra_arg) { - q->h = i; - q->key = NULL; - if (!Z_ISREF_P(p)) { - ZVAL_COPY(&q->val, p); - } else { - ZVAL_DUP(&q->val, Z_REFVAL_P(p)); - } + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + i = 0; + p = ZEND_CALL_ARG(ex, 1); + if (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg) { + while (i < first_extra_arg) { + q = p; + ZVAL_DEREF(q); + if (Z_OPT_REFCOUNTED_P(q)) Z_ADDREF_P(q); + ZEND_HASH_FILL_ADD(q); +// q->h = i; +// q->key = NULL; +// if (!Z_ISREF_P(p)) { +// ZVAL_COPY(&q->val, p); +// } else { +// ZVAL_COPY(&q->val, Z_REFVAL_P(p)); +// } + p++; +// q++; + i++; + } + p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T); + } + while (i < arg_count) { + q = p; + ZVAL_DEREF(q); + if (Z_OPT_REFCOUNTED_P(q)) Z_ADDREF_P(q); + ZEND_HASH_FILL_ADD(q); +// q->h = i; +// q->key = NULL; +// if (!Z_ISREF_P(p)) { +// ZVAL_COPY(&q->val, p); +// } else { +// ZVAL_COPY(&q->val, Z_REFVAL_P(p)); +// } p++; - q++; +// q++; i++; } - p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T); - } - while (i < arg_count) { - q->h = i; - q->key = NULL; - if (!Z_ISREF_P(p)) { - ZVAL_COPY(&q->val, p); - } else { - ZVAL_DUP(&q->val, Z_REFVAL_P(p)); - } - p++; - q++; - i++; - } - Z_ARRVAL_P(return_value)->nNumUsed = i; - Z_ARRVAL_P(return_value)->nNumOfElements = i; - Z_ARRVAL_P(return_value)->nNextFreeElement = i + 1; - Z_ARRVAL_P(return_value)->nInternalPointer = 0; + } ZEND_HASH_FILL_END(); } } /* }}} */ @@ -2133,26 +2136,30 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / uint32_t i = 0; zval *p = ZEND_CALL_ARG(call, 1); - if (call->func->type == ZEND_USER_FUNCTION) { - uint32_t first_extra_arg = call->func->op_array.num_args; + zend_hash_real_init(Z_ARRVAL_P(arg_array), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(arg_array)) { + if (call->func->type == ZEND_USER_FUNCTION) { + uint32_t first_extra_arg = call->func->op_array.num_args; - if (ZEND_CALL_NUM_ARGS(call) > first_extra_arg) { - while (i < first_extra_arg) { - if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p); - zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p); - p++; - i++; + if (ZEND_CALL_NUM_ARGS(call) > first_extra_arg) { + while (i < first_extra_arg) { + if (Z_OPT_REFCOUNTED_P(p)) Z_ADDREF_P(p); + ZEND_HASH_FILL_ADD(p); + zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p); + p++; + i++; + } + p = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T); } - p = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T); } - } - while (i < num_args) { - if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p); - zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p); - p++; - i++; - } + while (i < num_args) { + if (Z_OPT_REFCOUNTED_P(p)) Z_ADDREF_P(p); + ZEND_HASH_FILL_ADD(p); + p++; + i++; + } + } ZEND_HASH_FILL_END(); } } /* }}} */ diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 81b933289f..3d76b56b21 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -759,6 +759,33 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht, #define ZEND_HASH_INC_APPLY_COUNT(ht) ((ht)->u.flags += (1 << ZEND_HASH_APPLY_SHIFT)) #define ZEND_HASH_DEC_APPLY_COUNT(ht) ((ht)->u.flags -= (1 << ZEND_HASH_APPLY_SHIFT)) + +/* The following macros are useful to insert a sequence of new elements + * of packed array. They may be use insted of series of + * zend_hash_next_index_insert_new() + * (HashTable must have enough free buckets). + */ +#define ZEND_HASH_FILL_PACKED(ht) do { \ + HashTable *__fill_ht = (ht); \ + Bucket *__fill_bkt = __fill_ht->arData + __fill_ht->nNumUsed; \ + uint32_t __fill_idx = __fill_ht->nNumUsed; \ + ZEND_ASSERT(__fill_ht->u.flags & HASH_FLAG_PACKED); + +#define ZEND_HASH_FILL_ADD(_val) do { \ + ZVAL_COPY_VALUE(&__fill_bkt->val, _val); \ + __fill_bkt->h = (__fill_idx); \ + __fill_bkt->key = NULL; \ + __fill_bkt++; \ + __fill_idx++; \ + } while (0) + +#define ZEND_HASH_FILL_END() \ + __fill_ht->nNumUsed = __fill_idx; \ + __fill_ht->nNumOfElements = __fill_idx; \ + __fill_ht->nNextFreeElement = __fill_idx + 1; \ + __fill_ht->nInternalPointer = 0; \ + } while (0) + #endif /* ZEND_HASH_H */ /* diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 45e8b09c40..c3f3546b57 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3698,21 +3698,24 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY) zval *param; array_init_size(params, arg_count - arg_num + 1); - param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); - if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - do { - zend_verify_arg_type(EX(func), arg_num, param, NULL); - zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param); - if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param); - param++; - } while (++arg_num <= arg_count); - } else { - do { - zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param); - if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param); - param++; - } while (++arg_num <= arg_count); - } + zend_hash_real_init(Z_ARRVAL_P(params), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) { + param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); + if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { + do { + zend_verify_arg_type(EX(func), arg_num, param, NULL); + if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); + ZEND_HASH_FILL_ADD(param); + param++; + } while (++arg_num <= arg_count); + } else { + do { + if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); + ZEND_HASH_FILL_ADD(param); + param++; + } while (++arg_num <= arg_count); + } + } ZEND_HASH_FILL_END(); } else { array_init(params); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d087b05d89..5e67528f87 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1006,21 +1006,24 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR zval *param; array_init_size(params, arg_count - arg_num + 1); - param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); - if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - do { - zend_verify_arg_type(EX(func), arg_num, param, NULL); - zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param); - if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param); - param++; - } while (++arg_num <= arg_count); - } else { - do { - zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param); - if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param); - param++; - } while (++arg_num <= arg_count); - } + zend_hash_real_init(Z_ARRVAL_P(params), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) { + param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); + if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { + do { + zend_verify_arg_type(EX(func), arg_num, param, NULL); + if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); + ZEND_HASH_FILL_ADD(param); + param++; + } while (++arg_num <= arg_count); + } else { + do { + if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); + ZEND_HASH_FILL_ADD(param); + param++; + } while (++arg_num <= arg_count); + } + } ZEND_HASH_FILL_END(); } else { array_init(params); } diff --git a/ext/standard/array.c b/ext/standard/array.c index b9ccf5bd56..d2367385e0 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2724,16 +2724,18 @@ PHP_FUNCTION(array_keys) } } else { array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input))); - - /* Go through input array and add keys to the return array */ - ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) { - if (str_idx) { - ZVAL_STR_COPY(&new_val, str_idx); - } else { - ZVAL_LONG(&new_val, num_idx); - } - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &new_val); - } ZEND_HASH_FOREACH_END(); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + /* Go through input array and add keys to the return array */ + ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) { + if (str_idx) { + ZVAL_STR_COPY(&new_val, str_idx); + } else { + ZVAL_LONG(&new_val, num_idx); + } + ZEND_HASH_FILL_ADD(&new_val); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); } } /* }}} */ @@ -2751,12 +2753,15 @@ PHP_FUNCTION(array_values) /* Initialize return array */ array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input))); + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); /* Go through input array and add values to the return array */ - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) { - zval_add_ref(entry); - zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), entry); - } ZEND_HASH_FOREACH_END(); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) { + zval_add_ref(entry); + ZEND_HASH_FILL_ADD(entry); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); } /* }}} */ |