From: Andi Gutmans Date: Mon, 24 Jan 2000 19:04:07 +0000 (+0000) Subject: - Make foreach() now copy the array but use the original array. It can X-Git-Tag: BEFORE_SAPIFICATION_FEB_10_2000~187 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58a0844b1c37d2975461f7c0f4337b8657ce580e;p=php - 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. --- 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;