diff options
author | Andi Gutmans <andi@php.net> | 2004-08-12 05:41:01 +0000 |
---|---|---|
committer | Andi Gutmans <andi@php.net> | 2004-08-12 05:41:01 +0000 |
commit | de25255b6dffbcb8f6add7a685fb938e59b7dbb2 (patch) | |
tree | c4d668d3ef9582825dcbc3e7a2ea85a35059231a /Zend/zend_compile.c | |
parent | 5310de975c887a74d85899746eb3d7c6d6b404fd (diff) | |
download | php-git-de25255b6dffbcb8f6add7a685fb938e59b7dbb2.tar.gz |
- Significantly improve performance of foreach($arr as $data). (Marcus)
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 8af1de9bff..37ec35fa16 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3340,7 +3340,7 @@ void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brack void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *foreach_token TSRMLS_DC) { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_op *opline; znode result_value, result_key, dummy; zend_bool assign_by_ref=0; @@ -3351,6 +3351,9 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore tmp = key; key = value; value = tmp; + + /* Mark extended_value in case both key and value are being used */ + CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= 2; } if ((key->op_type != IS_UNUSED) && (key->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE)) { @@ -3362,20 +3365,10 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore if (!CG(active_op_array)->opcodes[foreach_token->u.opline_num-1].extended_value) { zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression"); } - CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value = 1; + /* Mark extended_value for assign-by-reference */ + CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= 1; } - opline->opcode = ZEND_FETCH_DIM_TMP_VAR; - opline->result.op_type = IS_VAR; - opline->result.u.EA.type = 0; - opline->result.u.opline_num = get_temporary_variable(CG(active_op_array)); - opline->op1 = *as_token; - opline->op2.op_type = IS_CONST; - opline->op2.u.constant.type = IS_LONG; - opline->op2.u.constant.value.lval = 0; - opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */ - result_value = opline->result; - if (key->op_type != IS_UNUSED) { opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_FETCH_DIM_TMP_VAR; @@ -3385,13 +3378,33 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore opline->op1 = *as_token; opline->op2.op_type = IS_CONST; opline->op2.u.constant.type = IS_LONG; + opline->op2.u.constant.value.lval = 0; + opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */ + result_value = opline->result; + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_FETCH_DIM_TMP_VAR; + opline->result.op_type = IS_VAR; + opline->result.u.EA.type = 0; + opline->result.u.opline_num = get_temporary_variable(CG(active_op_array)); + opline->op1 = *as_token; + opline->op2.op_type = IS_CONST; + opline->op2.u.constant.type = IS_LONG; opline->op2.u.constant.value.lval = 1; opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */ result_key = opline->result; + } else { + result_value = CG(active_op_array)->opcodes[foreach_token->u.opline_num].result; } if (assign_by_ref) { - zend_do_assign_ref(&dummy, value, &result_value TSRMLS_CC); + if (key->op_type == IS_UNUSED) { + /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */ + CG(active_op_array)->opcodes[foreach_token->u.opline_num].result.op_type = IS_VAR; + zend_do_assign_ref(NULL, value, &CG(active_op_array)->opcodes[foreach_token->u.opline_num].result TSRMLS_CC); + } else { + zend_do_assign_ref(NULL, value, &result_value TSRMLS_CC); + } } else { zend_do_assign(&dummy, value, &result_value TSRMLS_CC); } @@ -3399,8 +3412,8 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore if (key->op_type != IS_UNUSED) { zend_do_assign(&dummy, key, &result_key TSRMLS_CC); CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED; + zend_do_free(as_token TSRMLS_CC); } - zend_do_free(as_token TSRMLS_CC); do_begin_loop(TSRMLS_C); INC_BPC(CG(active_op_array)); |