]> granicus.if.org Git - php/commitdiff
Use IS_CV for dirrent access to $this variable
authorDmitry Stogov <dmitry@php.net>
Wed, 7 May 2008 12:04:39 +0000 (12:04 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 7 May 2008 12:04:39 +0000 (12:04 +0000)
NEWS
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute_API.c
Zend/zend_language_parser.y
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl

diff --git a/NEWS b/NEWS
index ed5f8073b60ad0619e3fade3615e3722ccff1581..2b36bfe43d4cc10e4e4b28a0b6abd8b4a108912a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -109,6 +109,7 @@ PHP                                                                        NEWS
 - Added native support for asinh(), acosh(), atanh(), log1p() and expm1() (Kalle)
 
 - Improved PHP runtime speed and memory usage:
+  . Use IS_CV for direct access to $this variable. (Dmitry)
   . Use ZEND_FREE() opcode instead of ZEND_SWITCH_FREE(IS_TMP_VAR). (Dmitry)
   . Lazy EG(active_symbol_table) initialization. (Dmitry)
   . Optimized ZEND_RETURN opcode to not allocate and copy return value if it is
index 8b3b15af4bb8a82394dfb03d692c71c3675a1483..26e32c5dd39dcd847d80ed84991dd695907d117c 100644 (file)
@@ -562,12 +562,16 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC)
                }
        }
 
-       zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+       zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
 
        last_op_number = get_next_op_number(CG(active_op_array));
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       if (variable->op_type == IS_VAR) {
+       if (variable->op_type == IS_CV) {
+               if (variable->u.var == CG(active_op_array)->this_var) {
+                       zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+           }
+       } else if (variable->op_type == IS_VAR) {
                int n = 0;
 
                while (last_op_number - n > 0) {
@@ -632,18 +636,24 @@ static inline zend_bool zend_is_function_or_method_call(znode *variable)
 
 void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC)
 {
-       int last_op_number = get_next_op_number(CG(active_op_array));
-       zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
-       if (last_op_number > 0) {
-               zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
+       zend_op *opline;
 
-               if (lvar->op_type == IS_VAR &&
-                   opline_is_fetch_this(last_op TSRMLS_CC)) {
-                       zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
-               }
-       }
+       if (lvar->op_type == IS_CV) {
+               if (lvar->u.var == CG(active_op_array)->this_var) {
+                       zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+           }
+       } else if (lvar->op_type == IS_VAR) {
+               int last_op_number = get_next_op_number(CG(active_op_array));
+
+               if (last_op_number > 0) {
+                       opline = &CG(active_op_array)->opcodes[last_op_number-1];
+                       if (opline_is_fetch_this(opline TSRMLS_CC)) {
+                               zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+                       }
+               }
+       }
 
+       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_ASSIGN_REF;
        if (zend_is_function_or_method_call(rvar)) {
                opline->extended_value = ZEND_RETURNS_FUNCTION;
@@ -897,11 +907,13 @@ void zend_do_begin_variable_parse(TSRMLS_D)
 }
 
 
-void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC)
+void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC)
 {
        zend_llist *fetch_list_ptr;
        zend_llist_element *le;
-       zend_op *opline, *opline_ptr=NULL;
+       zend_op *opline = NULL;
+       zend_op *opline_ptr;
+       zend_uint this_var = -1;
 
        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
 
@@ -912,12 +924,36 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC)
        if (le) {
                opline_ptr = (zend_op *)le->data;
                if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
-                       CG(active_op_array)->uses_this = 1;
+                       /* convert to FETCH_?(this) into IS_CV */
+                       if (CG(active_op_array)->last == 0 ||
+                           CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
+
+                               this_var = opline_ptr->result.u.var;
+                               if (CG(active_op_array)->this_var == -1) {
+                                       CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(opline_ptr->op1.u.constant), Z_STRLEN(opline_ptr->op1.u.constant));
+                               } else {
+                                       efree(Z_STRVAL(opline_ptr->op1.u.constant));
+                               }
+                               le = le->next;
+                               if (variable->op_type == IS_VAR &&
+                                   variable->u.var == this_var) {
+                                       variable->op_type = IS_CV;
+                                       variable->u.var = CG(active_op_array)->this_var;
+                               }
+                   } else if (CG(active_op_array)->this_var == -1) {
+                               CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
+                       }
                }
 
-               while (1) {
+               while (le) {
+                       opline_ptr = (zend_op *)le->data;
                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                        memcpy(opline, opline_ptr, sizeof(zend_op));
+                       if (opline->op1.op_type == IS_VAR &&
+                           opline->op1.u.var == this_var) {
+                               opline->op1.op_type = IS_CV;
+                               opline->op1.u.var = CG(active_op_array)->this_var;
+                       }
                        switch (type) {
                                case BP_VAR_R:
                                        if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
@@ -948,10 +984,8 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC)
                                        break;
                        }
                        le = le->next;
-                       if (le == NULL) break;
-                       opline_ptr = (zend_op *)le->data;
                }
-               if (type == BP_VAR_W && arg_offset) {
+               if (opline && type == BP_VAR_W && arg_offset) {
                        opline->extended_value = ZEND_FETCH_MAKE_REF;
                }
        }
@@ -1348,7 +1382,12 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
                return;
        }
 
-       if (CG(active_op_array)->scope &&
+       if (var->op_type == IS_CV &&
+           var->u.var == CG(active_op_array)->this_var &&
+           (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
+               zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+       } else if (var->op_type == IS_VAR &&
+           CG(active_op_array)->scope &&
                ((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
                (Z_TYPE(varname->u.constant) == IS_STRING) &&
                (Z_STRLEN(varname->u.constant) == sizeof("this")-1) &&
@@ -1455,7 +1494,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
        int last_op_number;
        unsigned char *ptr = NULL;
 
-       zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+       zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
        zend_do_begin_variable_parse(TSRMLS_C);
 
        last_op_number = get_next_op_number(CG(active_op_array))-1;
@@ -1977,17 +2016,17 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC)
        if (original_op == ZEND_SEND_VAR) {
                switch (op) {
                        case ZEND_SEND_VAR_NO_REF:
-                               zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+                               zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
                                break;
                        case ZEND_SEND_VAR:
                                if (function_ptr) {
-                                       zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+                                       zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
                                } else {
-                                       zend_do_end_variable_parse(BP_VAR_FUNC_ARG, offset TSRMLS_CC);
+                                       zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, offset TSRMLS_CC);
                                }
                                break;
                        case ZEND_SEND_REF:
-                               zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+                               zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
                                break;
                }
        }
@@ -2066,9 +2105,9 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC)
 
        if (do_end_vparse) {
                if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
-                       zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+                       zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
                } else {
-                       zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+                       zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
                }
        }
 
@@ -3491,15 +3530,16 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
 {
        zend_op opline;
        zend_llist *fetch_list_ptr;
-       zend_op *opline_ptr=NULL;
 
        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
 
-       if (fetch_list_ptr->count == 1) {
-               zend_llist_element *le;
-
-               le = fetch_list_ptr->head;
-               opline_ptr = (zend_op *) le->data;
+       if (object->op_type == IS_CV) {
+               if (object->u.var == CG(active_op_array)->this_var) {
+                   SET_UNUSED(*object); /* this means $this for objects */
+           }
+       } else if (fetch_list_ptr->count == 1) {
+               zend_llist_element *le = fetch_list_ptr->head;
+               zend_op *opline_ptr = (zend_op *) le->data;
 
                if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
                        efree(Z_STRVAL(opline_ptr->op1.u.constant));
@@ -4124,7 +4164,7 @@ void zend_do_indirect_references(znode *result, znode *num_references, znode *va
 {
        int i;
 
-       zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+       zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC);
        for (i=1; i<num_references->u.constant.value.lval; i++) {
                fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
                *variable = *result;
@@ -4170,7 +4210,7 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
 {
        zend_op *last_op;
 
-       zend_do_end_variable_parse(BP_VAR_IS, 0 TSRMLS_CC);
+       zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC);
 
        zend_check_writable_variable(variable);
 
@@ -4246,7 +4286,7 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
                }
                /* save the location of FETCH_W instruction(s) */
                open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
-               zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+               zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
                if (CG(active_op_array)->last > 0 &&
                    CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
                        /* Only lock the container if we are fetching from a real container and not $this */
@@ -4356,7 +4396,7 @@ void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znod
        value_node = opline->result;
 
        if (assign_by_ref) {
-               zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+               zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
                /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
                zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
        } else {
index e6340d9dded47032daf79b73ff5b3bb814e1b536..dc2dff1a7f7a4b2e2647c297ca23ff0fdc90b0a3 100644 (file)
@@ -197,6 +197,8 @@ struct _zend_op_array {
        unsigned char return_reference;
        /* END of common elements */
 
+       zend_bool done_pass_two;
+
        zend_uint *refcount;
 
        zend_op *opcodes;
@@ -220,8 +222,7 @@ struct _zend_op_array {
        zend_op *start_op;
        int backpatch_count;
 
-       zend_bool done_pass_two;
-       zend_bool uses_this;
+       zend_uint this_var;
 
        char *filename;
        zend_uint line_start;
@@ -396,7 +397,7 @@ void zend_do_pre_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);
 void zend_do_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);
 
 void zend_do_begin_variable_parse(TSRMLS_D);
-void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC);
+void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC);
 
 void zend_check_writable_variable(znode *variable);
 
index c35d902ec589aaec611b4afb18890683d5dd5dbd..929828654baa1d4181e46895a546ba6a1dd76cf2 100644 (file)
@@ -1811,12 +1811,13 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
                }
                if (EG(current_execute_data) && EG(current_execute_data)->op_array) {
                        EG(current_execute_data)->symbol_table = EG(active_symbol_table);
-                       if (EG(current_execute_data)->op_array->uses_this && EG(This)) {
-                               Z_ADDREF_P(EG(This)); /* For $this pointer */
-                               if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) {
-                                       Z_DELREF_P(EG(This));
-                               }
-                       }
+
+                       if (EG(current_execute_data)->op_array->this_var != -1 &&
+                           !EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] &&
+                           EG(This)) {
+                               EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] = (zval**)EG(current_execute_data)->CVs + EG(current_execute_data)->op_array->last_var + EG(current_execute_data)->op_array->this_var;
+                               *EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] = EG(This);
+                       }
                        for (i = 0; i < EG(current_execute_data)->op_array->last_var; i++) {
                                if (EG(current_execute_data)->CVs[i]) {
                                        zend_hash_quick_update(EG(active_symbol_table),
index 896e786f1c6ab7b628af60926d8898b710e0d90a..fbe941937cbd9ee6e10edad4efe3f9df0fe10625 100644 (file)
@@ -275,7 +275,7 @@ unset_variables:
 ;
 
 unset_variable:
-               variable        { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
+               variable        { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
 ;
 
 function_declaration_statement:
@@ -567,21 +567,21 @@ non_empty_for_expr:
 expr_without_variable:
                T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
        |       variable '=' expr               { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
-       |       variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
-       |       variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");  zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
+       |       variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
+       |       variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");  zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
        |       T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
        |       T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
-       |       variable T_PLUS_EQUAL expr      { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_MINUS_EQUAL expr     { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_MUL_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_DIV_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_CONCAT_EQUAL expr    { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_MOD_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_AND_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_OR_EQUAL expr                { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_XOR_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_SL_EQUAL expr        { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); }
-       |       variable T_SR_EQUAL expr        { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_PLUS_EQUAL expr      { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_MINUS_EQUAL expr     { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_MUL_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_DIV_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_CONCAT_EQUAL expr    { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_MOD_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_AND_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_OR_EQUAL expr                { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_XOR_EQUAL expr               { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_SL_EQUAL expr        { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); }
+       |       variable T_SR_EQUAL expr        { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); }
        |       rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); }
        |       T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); }
        |       rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); }
@@ -647,16 +647,16 @@ function_call:
        |       class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $4.u.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
                        function_call_parameter_list
                        ')' { zend_do_end_function_call($4.u.opline_num?NULL:&$3, &$$, &$6, $4.u.opline_num, $4.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
-       |       class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+       |       class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
                        function_call_parameter_list
                        ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
        |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
                        function_call_parameter_list
                        ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
-       |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+       |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
                        function_call_parameter_list
                        ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
-       |       variable_without_objects  '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
+       |       variable_without_objects  '(' { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
                        function_call_parameter_list ')'
                        { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
 ;
@@ -680,7 +680,7 @@ fully_qualified_class_name:
 
 class_name_reference:
                class_name                                              { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
-       |       dynamic_class_name_reference    { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+       |       dynamic_class_name_reference    { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
 ;
 
 
@@ -779,17 +779,17 @@ expr:
 
 
 r_variable:
-       variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
+       variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
 ;
 
 
 w_variable:
-       variable        { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); $$ = $1;
+       variable        { zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $$ = $1;
                                  zend_check_writable_variable(&$1); }
 ;
 
 rw_variable:
-       variable        { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); $$ = $1;
+       variable        { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); $$ = $1;
                                  zend_check_writable_variable(&$1); }
 ;
 
@@ -830,7 +830,7 @@ static_member:
 ;
 
 variable_class_name:
-               reference_variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); $$=$1;; }
+               reference_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$=$1;; }
 ;
 
 base_variable_with_function_calls:
@@ -865,7 +865,7 @@ dim_offset:
 
 object_property:
                object_dim_list { $$ = $1; }
-       |       variable_without_objects { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode;  zend_do_pop_object(&tmp_znode TSRMLS_CC);  zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
+       |       variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode;  zend_do_pop_object(&tmp_znode TSRMLS_CC);  zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
 ;
 
 object_dim_list:
@@ -914,7 +914,7 @@ non_empty_array_pair_list:
 ;
 
 encaps_list:
-               encaps_list encaps_var { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);  zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
+               encaps_list encaps_var { zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC);  zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
        |       encaps_list T_ENCAPSED_AND_WHITESPACE   { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
        |       /* empty */                     { zend_do_init_string(&$$ TSRMLS_CC); }
 
index 35e85cc16fdd3000b9887e5744074908a83ac00d..fbbccb3f0c520b7077b577ca4843393378cc8a1e 100644 (file)
@@ -95,7 +95,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
        op_array->return_reference = 0;
        op_array->done_pass_two = 0;
 
-       op_array->uses_this = 0;
+       op_array->this_var = -1;
 
        op_array->start_op = NULL;
 
index 6d6761f8a67c50a96add35bc9af93ea8ad8909af..734fccec7460079d03b0267e0e1d6cd02b05559a 100644 (file)
@@ -2390,7 +2390,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, CV)
        } else {
                zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var);
                zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value,
-                   &EG(exception), sizeof(zval *), NULL);
+                   &EG(exception), sizeof(zval *), (void**)&EX(CVs)[opline->op2.u.var]);
        }
        EG(exception) = NULL;
        ZEND_VM_NEXT_OPCODE();
index 839fc93f5aaf0996c2ffedf6e746762e02192513..d08b0adc669cbfaa85b0b7b5cf7ab97ef9e06342 100644 (file)
@@ -69,10 +69,15 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
                ZEND_VM_SET_OPCODE(op_array->opcodes);
        }
 
-       if (op_array->uses_this && EG(This) && EG(active_symbol_table)) {
-               Z_ADDREF_P(EG(This)); /* For $this pointer */
-               if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) {
-                       Z_DELREF_P(EG(This));
+       if (op_array->this_var != -1 && EG(This)) {
+               Z_ADDREF_P(EG(This)); /* For $this pointer */
+               if (!EG(active_symbol_table)) {
+                       EX(CVs)[op_array->this_var] = (zval**)EX(CVs) + (op_array->last_var + op_array->this_var);
+                       *EX(CVs)[op_array->this_var] = EG(This);
+               } else {
+                       if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX(CVs)[op_array->this_var])==FAILURE) {
+                               Z_DELREF_P(EG(This));
+                       }
                }
        }
 
@@ -1080,7 +1085,7 @@ static int ZEND_CATCH_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        } else {
                zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var);
                zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value,
-                   &EG(exception), sizeof(zval *), NULL);
+                   &EG(exception), sizeof(zval *), (void**)&EX(CVs)[opline->op2.u.var]);
        }
        EG(exception) = NULL;
        ZEND_VM_NEXT_OPCODE();
index 32e26aff5614edf3960c2bed0c65409fb8fd256f..b6e8d84d29b62196cba294dab3363a628860e233 100644 (file)
@@ -37,10 +37,15 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC)
                ZEND_VM_SET_OPCODE(op_array->opcodes);
        }
 
-       if (op_array->uses_this && EG(This) && EG(active_symbol_table)) {
-               Z_ADDREF_P(EG(This)); /* For $this pointer */
-               if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) {
-                       Z_DELREF_P(EG(This));
+       if (op_array->this_var != -1 && EG(This)) {
+               Z_ADDREF_P(EG(This)); /* For $this pointer */
+               if (!EG(active_symbol_table)) {
+                       EX(CVs)[op_array->this_var] = (zval**)EX(CVs) + (op_array->last_var + op_array->this_var);
+                       *EX(CVs)[op_array->this_var] = EG(This);
+               } else {
+                       if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX(CVs)[op_array->this_var])==FAILURE) {
+                               Z_DELREF_P(EG(This));
+                       }
                }
        }