summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_builtin_functions.c107
-rw-r--r--Zend/zend_hash.h27
-rw-r--r--Zend/zend_vm_def.h33
-rw-r--r--Zend/zend_vm_execute.h33
-rw-r--r--ext/standard/array.c33
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();
}
/* }}} */