]> granicus.if.org Git - php/commitdiff
foreash($a as $key => $val) optimization
authorDmitry Stogov <dmitry@php.net>
Mon, 7 Feb 2005 16:09:54 +0000 (16:09 +0000)
committerDmitry Stogov <dmitry@php.net>
Mon, 7 Feb 2005 16:09:54 +0000 (16:09 +0000)
Removed temorary array creation on each iteration.

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index b893b12fb1d706cfe038649f2098168ef0cd0647..ca4171e8b8254466e9175571e71a3e5cb8168fcc 100644 (file)
@@ -3343,7 +3343,7 @@ void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type
 }
 
 
-void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC)
+void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, int variable TSRMLS_DC)
 {
        zend_op *opline;
        zend_bool is_variable;
@@ -3398,21 +3398,27 @@ void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brack
 
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_FE_FETCH;
-       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 = *open_brackets_token;
        opline->extended_value = 0;
        SET_UNUSED(opline->op2);
-       *as_token = opline->result;
+
+       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+       opline->opcode = ZEND_OP_DATA;
+       opline->op1.op_type = IS_UNUSED;
+       opline->op2.op_type = IS_UNUSED;
+       opline->result.op_type = IS_UNUSED;
 }
 
 
-void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *foreach_token TSRMLS_DC)
+void zend_do_foreach_cont(znode *value, znode *key, znode *foreach_token TSRMLS_DC)
 {
        zend_op *opline;
-       znode result_value, result_key, dummy;
+       znode dummy;
        zend_bool assign_by_ref=0;
 
+       opline = &CG(active_op_array)->opcodes[foreach_token->u.opline_num];
        if (key->op_type != IS_UNUSED) {
                znode *tmp;
 
@@ -3422,66 +3428,38 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore
                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 |= ZEND_FE_FETCH_WITH_KEY;
+               opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
        }
 
        if ((key->op_type != IS_UNUSED) && (key->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE)) {
                zend_error(E_COMPILE_ERROR, "Key element cannot be a reference");
        }
-       
+
        if (value->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE) {
                assign_by_ref = 1;
-               if (!CG(active_op_array)->opcodes[foreach_token->u.opline_num-1].extended_value) {
+               if (!(opline-1)->extended_value) {
                        zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression");
                }
                /* Mark extended_value for assign-by-reference */
-               CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_FETCH_BYREF;
-       }
-
-       if (key->op_type != IS_UNUSED) {
-               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 = 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;
+               opline->extended_value |= ZEND_FE_FETCH_BYREF;
        }
 
        if (assign_by_ref) {
-               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);
-               }
+               /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
+               zend_do_assign_ref(NULL, value, &opline->result TSRMLS_CC);
        } else {
-               zend_do_assign(&dummy, value, &result_value TSRMLS_CC);
+               zend_do_assign(&dummy, value, &opline->result TSRMLS_CC);
+               zend_do_free(&dummy TSRMLS_CC);
        }
-       CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
+
        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);
+               ++opline;
+               opline->result.op_type = IS_TMP_VAR;
+               opline->result.u.EA.type = 0;
+               opline->result.u.opline_num = get_temporary_variable(CG(active_op_array));
+
+               zend_do_assign(&dummy, key, &opline->result TSRMLS_CC);
+               zend_do_free(&dummy TSRMLS_CC);
        }
 
        do_begin_loop(TSRMLS_C);
@@ -3489,7 +3467,7 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore
 }
 
 
-void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC)
+void zend_do_foreach_end(znode *foreach_token TSRMLS_DC)
 {
        zend_op *container_ptr;
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
index 825ffca75899bdb23b45d176ed3055c525248c72..2bf075317d711a4f3081028f6c7fb8e27e94c78b 100644 (file)
@@ -461,9 +461,9 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
 
 void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC);
 
-void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC);
-void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *foreach_token TSRMLS_DC);
-void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC);
+void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, int variable TSRMLS_DC);
+void zend_do_foreach_cont(znode *value, znode *key, znode *foreach_token TSRMLS_DC);
+void zend_do_foreach_end(znode *foreach_token TSRMLS_DC);
 
 void zend_do_declare_begin(TSRMLS_D);
 void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC);
index 7dd066fb0afd7935ec79bc19f8bf74d4d5518ba6..353d712eda0b302b0d6a5d759b2ed29a5d0cf5bf 100644 (file)
@@ -209,8 +209,8 @@ unticked_statement:
        |       expr ';'                                { zend_do_free(&$1 TSRMLS_CC); }
        |       T_USE use_filename ';'          { zend_error(E_COMPILE_ERROR,"use: Not yet supported. Please use include_once() or require_once()");  zval_dtor(&$2.u.constant); }
        |       T_UNSET '(' unset_variables ')' ';'
-       |       T_FOREACH '(' variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 1 TSRMLS_CC); } foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4, &$1 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); }
-       |       T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 0 TSRMLS_CC); } w_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4, &$1 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); }
+       |       T_FOREACH '(' variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, 1 TSRMLS_CC); } foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$1 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1 TSRMLS_CC); }
+       |       T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, 0 TSRMLS_CC); } w_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$1 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1 TSRMLS_CC); }
        |       T_DECLARE { $1.u.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
        |       ';'             /* empty statement */
        |       T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
index eb1becd4d13c7cc0f28d6374f1d1cbec94075768..31c41658ba433afb6fc4ca9650ce5103a02bb9c9 100644 (file)
@@ -2930,7 +2930,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
        zend_op *opline = EX(opline);
        zend_free_op free_op1;
        zval *array = GET_OP1_ZVAL_PTR(BP_VAR_R);
-       zval **value, *key;
+       zval **value;
        char *str_key;
        uint str_key_len;
        ulong int_key;
@@ -3018,29 +3018,17 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
        if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
                SEPARATE_ZVAL_IF_NOT_REF(value);
                (*value)->is_ref = 1;
-       }
-
-       if (!use_key) {
-               if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
-                       EX_T(opline->result.u.var).var.ptr_ptr = value;
-                       (*value)->refcount++;
-               } else {
-                       zval *result = &EX_T(opline->result.u.var).tmp_var;
-
-                       *result = **value;
-                       zval_copy_ctor(result);
-               }
-       } else {
-               zval *result = &EX_T(opline->result.u.var).tmp_var;
-
+               EX_T(opline->result.u.var).var.ptr_ptr = value;
                (*value)->refcount++;
+       } else {
+               EX_T(opline->result.u.var).var.ptr_ptr = value;
+               PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+               AI_USE_PTR(EX_T(opline->result.u.var).var);
+       }
 
-               array_init(result);
-
-               zend_hash_index_update(result->value.ht, 0, value, sizeof(zval *), NULL);
-
-               ALLOC_ZVAL(key);
-               INIT_PZVAL(key);
+       if (use_key) {
+               zend_op *op_data = opline+1;
+               zval *key = &EX_T(op_data->result.u.var).tmp_var;
 
                switch (key_type) {
                        case HASH_KEY_IS_STRING:
@@ -3054,9 +3042,9 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
                                break;
                        EMPTY_SWITCH_DEFAULT_CASE()
                }
-               zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL);
        }
 
+       ZEND_VM_INC_OPCODE();
        ZEND_VM_NEXT_OPCODE();
 }
 
index 08e0611cc8f21066f84f5bb7b326d37fcd80e6e2..29d5101c0ab4d118303fe25db60547cf1a774994 100644 (file)
@@ -7550,7 +7550,7 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zend_op *opline = EX(opline);
        zend_free_op free_op1;
        zval *array = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-       zval **value, *key;
+       zval **value;
        char *str_key;
        uint str_key_len;
        ulong int_key;
@@ -7638,29 +7638,17 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
                SEPARATE_ZVAL_IF_NOT_REF(value);
                (*value)->is_ref = 1;
-       }
-
-       if (!use_key) {
-               if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
-                       EX_T(opline->result.u.var).var.ptr_ptr = value;
-                       (*value)->refcount++;
-               } else {
-                       zval *result = &EX_T(opline->result.u.var).tmp_var;
-
-                       *result = **value;
-                       zval_copy_ctor(result);
-               }
-       } else {
-               zval *result = &EX_T(opline->result.u.var).tmp_var;
-
+               EX_T(opline->result.u.var).var.ptr_ptr = value;
                (*value)->refcount++;
+       } else {
+               EX_T(opline->result.u.var).var.ptr_ptr = value;
+               PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+               AI_USE_PTR(EX_T(opline->result.u.var).var);
+       }
 
-               array_init(result);
-
-               zend_hash_index_update(result->value.ht, 0, value, sizeof(zval *), NULL);
-
-               ALLOC_ZVAL(key);
-               INIT_PZVAL(key);
+       if (use_key) {
+               zend_op *op_data = opline+1;
+               zval *key = &EX_T(op_data->result.u.var).tmp_var;
 
                switch (key_type) {
                        case HASH_KEY_IS_STRING:
@@ -7674,9 +7662,9 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                                break;
                        EMPTY_SWITCH_DEFAULT_CASE()
                }
-               zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL);
        }
 
+       ZEND_VM_INC_OPCODE();
        ZEND_VM_NEXT_OPCODE();
 }
 
@@ -30655,7 +30643,7 @@ static int ZEND_FE_FETCH_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        zend_op *opline = EX(opline);
        zend_free_op free_op1;
        zval *array = get_zval_ptr(&opline->op1, EX(Ts), &free_op1, BP_VAR_R);
-       zval **value, *key;
+       zval **value;
        char *str_key;
        uint str_key_len;
        ulong int_key;
@@ -30743,29 +30731,17 @@ static int ZEND_FE_FETCH_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
                SEPARATE_ZVAL_IF_NOT_REF(value);
                (*value)->is_ref = 1;
-       }
-
-       if (!use_key) {
-               if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
-                       EX_T(opline->result.u.var).var.ptr_ptr = value;
-                       (*value)->refcount++;
-               } else {
-                       zval *result = &EX_T(opline->result.u.var).tmp_var;
-
-                       *result = **value;
-                       zval_copy_ctor(result);
-               }
-       } else {
-               zval *result = &EX_T(opline->result.u.var).tmp_var;
-
+               EX_T(opline->result.u.var).var.ptr_ptr = value;
                (*value)->refcount++;
+       } else {
+               EX_T(opline->result.u.var).var.ptr_ptr = value;
+               PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+               AI_USE_PTR(EX_T(opline->result.u.var).var);
+       }
 
-               array_init(result);
-
-               zend_hash_index_update(result->value.ht, 0, value, sizeof(zval *), NULL);
-
-               ALLOC_ZVAL(key);
-               INIT_PZVAL(key);
+       if (use_key) {
+               zend_op *op_data = opline+1;
+               zval *key = &EX_T(op_data->result.u.var).tmp_var;
 
                switch (key_type) {
                        case HASH_KEY_IS_STRING:
@@ -30779,9 +30755,9 @@ static int ZEND_FE_FETCH_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                                break;
                        EMPTY_SWITCH_DEFAULT_CASE()
                }
-               zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL);
        }
 
+       ZEND_VM_INC_OPCODE();
        ZEND_VM_NEXT_OPCODE();
 }