diff options
author | Andi Gutmans <andi@php.net> | 2000-07-06 22:08:22 +0000 |
---|---|---|
committer | Andi Gutmans <andi@php.net> | 2000-07-06 22:08:22 +0000 |
commit | 5f893e68ff1a3c07927bd3ad70f4ab54cd4a08f7 (patch) | |
tree | c7acd9a9830d21b2e12d1d4db2742a54c354235c | |
parent | 4aef5ef83055780782e76e33371821112590a8aa (diff) | |
download | php-git-5f893e68ff1a3c07927bd3ad70f4ab54cd4a08f7.tar.gz |
- Complex fix for solving a problem with objects & method calls.
- Previous version is tagged PRE_METHOD_CALL_SEPERATE_FIX_PATCH.
- I need to check this fix on a server so if it doesn't work I will revert
- it.
-rw-r--r-- | Zend/zend-parser.y | 4 | ||||
-rw-r--r-- | Zend/zend_compile.c | 47 | ||||
-rw-r--r-- | Zend/zend_execute.c | 13 |
3 files changed, 45 insertions, 19 deletions
diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index 523bdc149a..2d964f3844 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -489,10 +489,10 @@ expr_without_variable: function_call: - T_STRING '(' { do_extended_fcall_begin(CLS_C); $2.u.opline_num = do_begin_function_call(&$1 CLS_CC); } + T_STRING '(' { $2.u.opline_num = do_begin_function_call(&$1 CLS_CC); } function_call_parameter_list ')' { do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num CLS_CC); do_extended_fcall_end(CLS_C); } - | r_cvar '(' { do_extended_fcall_begin(CLS_C); do_begin_dynamic_function_call(&$1 CLS_CC); } + | cvar '(' { do_begin_dynamic_function_call(&$1 CLS_CC); } function_call_parameter_list ')' { do_end_function_call(&$1, &$$, &$4, 0, 1 CLS_CC); do_extended_fcall_end(CLS_C);} | T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_class_member_function_call(&$1, &$3 CLS_CC); } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index abfc8d3723..3d8e576e81 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -567,6 +567,27 @@ void do_end_variable_parse(int type, int arg_offset CLS_DC) } +zend_bool is_method_call(CLS_D) +{ + zend_llist *fetch_list_ptr; + zend_llist_element *cur; + zend_op *cur_opline; + + zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); + + cur = fetch_list_ptr->head; + /* There is always at least one node in the list */ + while (cur->next) { + cur = cur->next; + } + cur_opline = (zend_op *)cur->data; + if (cur_opline->opcode == ZEND_FETCH_OBJ_R) { + return 1; + } + return 0; +} + + void do_init_string(znode *result CLS_DC) { zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); @@ -815,6 +836,7 @@ int do_begin_function_call(znode *function_name CLS_DC) } break; } + do_extended_fcall_begin(CLS_C); return 0; } @@ -822,29 +844,28 @@ int do_begin_function_call(znode *function_name CLS_DC) void do_begin_dynamic_function_call(znode *function_name CLS_DC) { unsigned char *ptr = NULL; - int last_op_number = get_next_op_number(CG(active_op_array))-1; - zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; - - if ((last_op_number >= 1) && (last_op->opcode == ZEND_EXT_FCALL_BEGIN) && ((last_op-1)->opcode == ZEND_FETCH_OBJ_R)) { - zend_op tmp; + int last_op_number; + zend_op *last_op; - tmp = *last_op; - *last_op = *(last_op-1); - *(last_op-1) = tmp; - last_op->opcode = ZEND_INIT_FCALL_BY_NAME; - last_op->extended_value = ZEND_MEMBER_FUNC_CALL; - } else if (last_op_number>=0 && last_op->opcode == ZEND_FETCH_OBJ_R) { + if (function_name->op_type != IS_CONST && is_method_call(CLS_C)) { + do_end_variable_parse(BP_VAR_W, 0 CLS_CC); + last_op_number = get_next_op_number(CG(active_op_array))-1; + last_op = &CG(active_op_array)->opcodes[last_op_number]; last_op->opcode = ZEND_INIT_FCALL_BY_NAME; last_op->extended_value = ZEND_MEMBER_FUNC_CALL; } else { - zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); - + zend_op *opline; + + do_end_variable_parse(BP_VAR_R, 0 CLS_CC); + + opline = get_next_op(CG(active_op_array) CLS_CC); opline->opcode = ZEND_INIT_FCALL_BY_NAME; opline->op2 = *function_name; opline->extended_value = 0; SET_UNUSED(opline->op1); } zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); + do_extended_fcall_begin(CLS_C); } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c3a08c2735..7918e97e22 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -65,12 +65,13 @@ static void zend_extension_statement_handler(zend_extension *extension, zend_op_ static void zend_extension_fcall_begin_handler(zend_extension *extension, zend_op_array *op_array); static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_array *op_array); - +/* #define SEPARATE_ON_READ_OBJECT(obj, _type) \ if ((obj) && ((_type) == BP_VAR_R) && ((*(obj))->type == IS_OBJECT)) { \ SEPARATE_ZVAL_IF_NOT_REF((obj)); \ (*(obj))->is_ref = 1; \ } +*/ #define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED)) @@ -502,7 +503,7 @@ static void zend_fetch_var_address(znode *result, znode *op1, znode *op2, temp_v zval_dtor(varname); } Ts[result->u.var].var.ptr_ptr = retval; - SEPARATE_ON_READ_OBJECT(retval, type); +// SEPARATE_ON_READ_OBJECT(retval, type); SELECTIVE_PZVAL_LOCK(*retval, result); } @@ -680,7 +681,7 @@ static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, } else { *retval = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, type ELS_CC); } - SEPARATE_ON_READ_OBJECT(*retval, type); + //SEPARATE_ON_READ_OBJECT(*retval, type); SELECTIVE_PZVAL_LOCK(**retval, result); break; case IS_NULL: @@ -871,7 +872,7 @@ static void zend_fetch_property_address(znode *result, znode *op1, znode *op2, t zendi_zval_copy_ctor(*container); } *retval = zend_fetch_property_address_inner(container->value.obj.properties, op2, Ts, type ELS_CC); - SEPARATE_ON_READ_OBJECT(*retval, type); + //SEPARATE_ON_READ_OBJECT(*retval, type); SELECTIVE_PZVAL_LOCK(**retval, result); } @@ -1513,6 +1514,10 @@ binary_assign_op_addr: { if (!object.ptr || object.ptr->type != IS_OBJECT) { zend_error(E_ERROR, "Call to a member function on a non-object"); } + if (!object.ptr->is_ref && object.ptr->refcount > 1) { + zend_error(E_ERROR, "Bug: Problem in method call\n"); + } + object.ptr->is_ref=1; object.ptr->refcount++; /* For $this pointer */ active_function_table = &(object.ptr->value.obj.ce->function_table); } |