summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Gutmans <andi@php.net>2000-01-24 19:04:07 +0000
committerAndi Gutmans <andi@php.net>2000-01-24 19:04:07 +0000
commit58a0844b1c37d2975461f7c0f4337b8657ce580e (patch)
tree36735571e156631b51dffd669f9ae90eced19385
parent97f64988e21134ef987de6232918c38b1bd7d2cd (diff)
downloadphp-git-58a0844b1c37d2975461f7c0f4337b8657ce580e.tar.gz
- Make foreach() now copy the array but use the original array. It can
still be optimized A LOT but it's only a performance issue and not a feature issue.
-rw-r--r--Zend/zend_compile.c8
-rw-r--r--Zend/zend_execute.c22
2 files changed, 23 insertions, 7 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 664141093d..87fe4886d0 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -950,6 +950,7 @@ static int generate_free_switch_expr(zend_switch_entry *switch_entry CLS_DC)
opline->opcode = ZEND_SWITCH_FREE;
opline->op1 = switch_entry->cond;
SET_UNUSED(opline->op2);
+ opline->extended_value = 0;
return 0;
}
@@ -963,9 +964,10 @@ static int generate_free_foreach_copy(znode *foreach_copy CLS_DC)
opline = get_next_op(CG(active_op_array) CLS_CC);
- opline->opcode = ZEND_FREE;
+ opline->opcode = ZEND_SWITCH_FREE;
opline->op1 = *foreach_copy;
SET_UNUSED(opline->op2);
+ opline->extended_value = 1;
return 0;
}
@@ -1950,7 +1952,7 @@ void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_t
/* Preform array reset */
opline->opcode = ZEND_FE_RESET;
- opline->result.op_type = IS_TMP_VAR;
+ opline->result.op_type = IS_VAR;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
opline->op1 = *array;
SET_UNUSED(opline->op2);
@@ -2036,7 +2038,7 @@ void do_foreach_end(znode *foreach_token, znode *open_brackets_token CLS_DC)
do_end_loop(foreach_token->u.opline_num CLS_CC);
- do_free(open_brackets_token CLS_CC);
+ generate_free_foreach_copy(open_brackets_token CLS_CC);
zend_stack_del_top(&CG(foreach_copy_stack));
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 0b15b0f881..380ba61627 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -255,6 +255,9 @@ static inline void zend_switch_free(zend_op *opline, temp_variable *Ts ELS_DC)
FREE_OP(&opline->op1, EG(free_op1));
} else {
zval_ptr_dtor(&Ts[opline->op1.u.var].var.ptr);
+ if (opline->extended_value) { /* foreach() free */
+ zval_ptr_dtor(&Ts[opline->op1.u.var].var.ptr);
+ }
}
break;
case IS_TMP_VAR:
@@ -2093,11 +2096,20 @@ send_by_ref:
case ZEND_FE_RESET: {
zval *array = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
- Ts[opline->result.u.var].tmp_var = *array;
- array = &Ts[opline->result.u.var].tmp_var;
- if (!EG(free_op1)) {
- zval_copy_ctor(array);
+ if (EG(free_op1)) { /* If TMP_VAR then make it a VAR */
+ zval *tmp;
+
+ ALLOC_ZVAL(tmp);
+ *tmp = *array;
+ INIT_PZVAL(tmp);
+ array = tmp;
+ } else {
+ array->refcount++;
}
+ PZVAL_LOCK(array);
+ Ts[opline->result.u.var].var.ptr = array;
+ Ts[opline->result.u.var].var.ptr_ptr = &Ts[opline->result.u.var].var.ptr;
+
if (array->type == IS_ARRAY) {
/* probably redundant */
zend_hash_internal_pointer_reset(array->value.ht);
@@ -2113,6 +2125,8 @@ send_by_ref:
char *str_key;
ulong int_key;
+ PZVAL_LOCK(array);
+
if (array->type != IS_ARRAY) {
zend_error(E_WARNING, "Non array argument supplied for foreach()");
opline = op_array->opcodes+opline->op2.u.opline_num;