From: Zeev Suraski Date: Wed, 15 Dec 1999 20:15:32 +0000 (+0000) Subject: - Implement return by reference: X-Git-Tag: PRE_LIBZEND_TO_ZEND~71 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ced9cee10cf943568b487dc1204f95290b19de80;p=php - Implement return by reference: - In function declaration instead of the return statement - In the assignment phase - Implement ability to turn off support for call-time pass by reference --- diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index 1a8f3e6fdb..1b543abf2a 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -180,7 +180,8 @@ statement: | T_CONTINUE ';' { do_brk_cont(ZEND_CONT, NULL CLS_CC); } | T_CONTINUE expr ';' { do_brk_cont(ZEND_CONT, &$2 CLS_CC); } | T_RETURN ';' { do_return(NULL CLS_CC); } - | T_RETURN expr ';' { do_return(&$2 CLS_CC); } + | T_RETURN expr_without_variable ';' { do_return(&$2 CLS_CC); } + | T_RETURN cvar ';' { do_return(&$2 CLS_CC); } | T_GLOBAL global_var_list | T_STATIC static_var_list | T_ECHO echo_expr_list ';' @@ -201,9 +202,9 @@ use_filename: declaration_statement: - T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); } + T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 0, $3.op_type CLS_CC); } '(' parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); } - | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); } + | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 0, $3.op_type CLS_CC); } parameter_list '(' inner_statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); } | T_CLASS T_STRING { do_begin_class_declaration(&$2, NULL CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); } | T_CLASS T_STRING T_EXTENDS T_STRING { do_begin_class_declaration(&$2, &$4 CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); } @@ -347,13 +348,16 @@ class_statement_list: class_statement: T_VAR class_variable_decleration ';' - | T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); } '(' + | T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 1, $3.op_type CLS_CC); } '(' parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); } - | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); } + | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 1, $3.op_type CLS_CC); } parameter_list '(' inner_statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); } ; +is_reference: + /* empty */ { $$.op_type = ZEND_RETURN_VAL; } + | '&' { $$.op_type = ZEND_RETURN_REF; } class_variable_decleration: class_variable_decleration ',' T_VARIABLE { do_declare_property(&$3, NULL CLS_CC); } @@ -384,6 +388,7 @@ expr_without_variable: T_LIST '(' { do_list_init(CLS_C); } assignment_list ')' '=' expr { do_list_end(&$$, &$7 CLS_CC); } | cvar '=' expr { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign(&$$, &$1, &$3 CLS_CC); } | cvar '=' '&' w_cvar { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign_ref(&$$, &$1, &$4 CLS_CC); } + | cvar '=' '&' function_call { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign_ref(&$$, &$1, &$4 CLS_CC); } | T_NEW class_name { do_extended_fcall_begin(CLS_C); do_begin_new_object(&$1, &$2 CLS_CC); } ctor_arguments { do_end_new_object(&$$, &$2, &$1, &$4 CLS_CC); do_extended_fcall_end(CLS_C);} | cvar T_PLUS_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 CLS_CC); } | cvar T_MINUS_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 CLS_CC); } @@ -431,15 +436,7 @@ expr_without_variable: | expr '?' { do_begin_qm_op(&$1, &$2 CLS_CC); } expr ':' { do_qm_true(&$4, &$2, &$5 CLS_CC); } expr { do_qm_false(&$$, &$7, &$2, &$5 CLS_CC); } - | T_STRING '(' { do_extended_fcall_begin(CLS_C); $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); } - 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); } - function_call_parameter_list - ')' { do_end_function_call(&$3, &$$, &$6, 1, 1 CLS_CC); do_extended_fcall_end(CLS_C);} + | function_call { $$ = $1; } | internal_functions_in_yacc { $$ = $1; } | T_INT_CAST expr { do_cast(&$$, &$2, IS_LONG CLS_CC); } | T_DOUBLE_CAST expr { do_cast(&$$, &$2, IS_DOUBLE CLS_CC); } @@ -456,6 +453,19 @@ expr_without_variable: ; +function_call: + T_STRING '(' { do_extended_fcall_begin(CLS_C); $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); } + 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); } + function_call_parameter_list + ')' { do_end_function_call(&$3, &$$, &$6, 1, 1 CLS_CC); do_extended_fcall_end(CLS_C);} +; + + exit_expr: /* empty */ { $$.op_type = IS_UNUSED; } | '(' ')' { $$.op_type = IS_UNUSED; } diff --git a/Zend/zend.h b/Zend/zend.h index 2129970352..0ef98ee46a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -187,8 +187,9 @@ typedef struct _zend_utility_functions { typedef struct _zend_utility_values { - unsigned char short_tags; - unsigned char asp_tags; + zend_bool short_tags; + zend_bool asp_tags; + zend_bool allow_call_time_pass_reference; char *import_use_extension; uint import_use_extension_length; } zend_utility_values; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index b56bd50f13..879e676406 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -98,6 +98,7 @@ void init_compiler(CLS_D ELS_DC) zend_llist_init(&CG(filenames_list), sizeof(char *), free_filename, 0); CG(short_tags) = ZEND_UV(short_tags); CG(asp_tags) = ZEND_UV(asp_tags); + CG(allow_call_time_pass_reference) = ZEND_UV(allow_call_time_pass_reference); CG(handle_op_arrays) = 1; zend_hash_apply(&module_registry, (int (*)(void *)) module_registry_request_startup); init_resource_list(ELS_C); @@ -667,7 +668,7 @@ void do_free(znode *op1 CLS_DC) } -void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method CLS_DC) +void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference CLS_DC) { zend_op_array op_array; char *name = function_name->u.constant.value.str.val; @@ -678,8 +679,10 @@ void do_begin_function_declaration(znode *function_token, znode *function_name, zend_str_tolower(name, name_len); init_op_array(&op_array, INITIAL_OP_ARRAY_SIZE); + op_array.function_name = name; op_array.arg_types = NULL; + op_array.return_reference = return_reference; if (is_method) { zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)); @@ -839,7 +842,7 @@ void do_end_function_call(znode *function_name, znode *result, znode *argument_l } opline->op1 = *function_name; opline->result.u.var = get_temporary_variable(CG(active_op_array)); - opline->result.op_type = IS_TMP_VAR; + opline->result.op_type = IS_VAR; *result = opline->result; SET_UNUSED(opline->op2); opline->op2.u.constant.value.lval = is_method; @@ -855,8 +858,22 @@ void do_pass_param(znode *param, int op, int offset CLS_DC) int original_op=op; zend_function **function_ptr_ptr, *function_ptr; + zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr); function_ptr = *function_ptr_ptr; + + if (original_op==ZEND_SEND_REF + && !CG(allow_call_time_pass_reference)) { + zend_error(E_COMPILE_WARNING, + "Call-time pass-by-reference has been deprecated - argument passed by value; " + "If you would like to pass it by reference, modify the declaration of %s(). " + "If you would like to enable call-time pass-by-reference, you can set" + "allow_call_time_pass_reference to true in your INI file. " + "However, future versions may not support this any longer.", + (function_ptr?function_ptr->common.function_name:"[runtime function name]"), + offset+1); + } + if (function_ptr) { arg_types = function_ptr->common.arg_types; } else { @@ -952,6 +969,13 @@ void do_return(znode *expr CLS_DC) { zend_op *opline; + if (expr->op_type==IS_VAR) { + if (CG(active_op_array)->return_reference) { + do_end_variable_parse(BP_VAR_W, 0 CLS_CC); + } else { + do_end_variable_parse(BP_VAR_R, 0 CLS_CC); + } + } #ifdef ZTS zend_stack_apply_with_argument(&CG(switch_cond_stack), (int (*)(void *element, void *)) generate_free_switch_expr, ZEND_STACK_APPLY_TOPDOWN CLS_CC); zend_stack_apply_with_argument(&CG(foreach_copy_stack), (int (*)(void *element, void *)) generate_free_foreach_copy, ZEND_STACK_APPLY_TOPDOWN CLS_CC); @@ -963,6 +987,7 @@ void do_return(znode *expr CLS_DC) opline = get_next_op(CG(active_op_array) CLS_CC); opline->opcode = ZEND_RETURN; + if (expr) { opline->op1 = *expr; } else { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index b76d107ba6..a026b2c4b0 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -115,6 +115,7 @@ struct _zend_op_array { int last_executed_op_number; int backpatch_count; #endif + zend_bool return_reference; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; @@ -260,7 +261,7 @@ void do_add_char(znode *result, znode *op1, znode *op2 CLS_DC); void do_add_string(znode *result, znode *op1, znode *op2 CLS_DC); void do_add_variable(znode *result, znode *op1, znode *op2 CLS_DC); -void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method CLS_DC); +void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference CLS_DC); void do_end_function_declaration(znode *function_token CLS_DC); void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, unsigned char pass_type CLS_DC); int do_begin_function_call(znode *function_name CLS_DC); @@ -573,21 +574,24 @@ int zendlex(znode *zendlval CLS_DC); #define PZVAL_IS_REF(z) ((z)->is_ref) #define PZVAL_LOCK(z) ((z)->refcount++) -#define PZVAL_UNLOCK(z) { ((z)->refcount--); \ - if (!(z)->refcount) { \ - EG(garbage)[EG(garbage_ptr)++] = (z); \ - if (EG(garbage_ptr) == 4) { \ - zval_dtor(EG(garbage)[0]); \ - efree(EG(garbage)[0]); \ - zval_dtor(EG(garbage)[1]); \ - efree(EG(garbage)[1]); \ - EG(garbage)[0] = EG(garbage)[2]; \ - EG(garbage)[1] = EG(garbage)[3]; \ - EG(garbage_ptr) -= 2; \ - } \ - } \ +#define PZVAL_UNLOCK(z) { ((z)->refcount--); \ + if (!(z)->refcount && !EG(suspend_garbage)) { \ + EG(garbage)[EG(garbage_ptr)++] = (z); \ + if (EG(garbage_ptr) == 4) { \ + zval_dtor(EG(garbage)[0]); \ + efree(EG(garbage)[0]); \ + zval_dtor(EG(garbage)[1]); \ + efree(EG(garbage)[1]); \ + EG(garbage)[0] = EG(garbage)[2]; \ + EG(garbage)[1] = EG(garbage)[3]; \ + EG(garbage_ptr) -= 2; \ + } \ + } \ } +#define SUSPEND_GARBAGE() (EG(suspend_garbage)=1) +#define RESUME_GARBAGE() (EG(suspend_garbage)=0) + #define SELECTIVE_PZVAL_LOCK(pzv, pzn) if (!((pzn)->u.EA.type & EXT_TYPE_UNUSED)) { PZVAL_LOCK(pzv); } @@ -609,4 +613,7 @@ int zendlex(znode *zendlval CLS_DC); ) \ ) +#define ZEND_RETURN_VAL 0 +#define ZEND_RETURN_REF 1 + #endif /* _COMPILE_H */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index b1ebfb0b86..78982c85c4 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -378,7 +378,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2 */ /* break missing intentionally */ case IS_CONST: - if (PZVAL_IS_REF(value)) { + if (PZVAL_IS_REF(value) && value->refcount > 0) { variable_ptr = *variable_ptr_ptr = (zval *) emalloc(sizeof(zval)); *variable_ptr = *value; zval_copy_ctor(variable_ptr); @@ -1218,14 +1218,19 @@ binary_assign_op_addr: { AI_USE_PTR(Ts[opline->result.u.var].var); break; case ZEND_ASSIGN: { - zval *value = get_zval_ptr(&opline->op2, Ts, &EG(free_op2), BP_VAR_R); + zval *value; + SUSPEND_GARBAGE(); + value = get_zval_ptr(&opline->op2, Ts, &EG(free_op2), BP_VAR_R); + RESUME_GARBAGE(); zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (EG(free_op2)?IS_TMP_VAR:opline->op2.op_type), Ts ELS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ } break; case ZEND_ASSIGN_REF: + SUSPEND_GARBAGE(); zend_assign_to_variable_reference(&opline->result, get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W), get_zval_ptr_ptr(&opline->op2, Ts, BP_VAR_W), Ts ELS_CC); + RESUME_GARBAGE(); break; case ZEND_JMP: #if DEBUG_ZEND>=2 @@ -1467,16 +1472,23 @@ overloaded_function_call_cont: } do_fcall_common: { - zval *original_return_value; + zval **original_return_value; int return_value_not_used = (opline->result.u.EA.type & EXT_TYPE_UNUSED); zend_ptr_stack_push(&EG(argument_stack), (void *) opline->extended_value); - var_uninit(&Ts[opline->result.u.var].tmp_var); + Ts[opline->result.u.var].var.ptr = (zval *)emalloc(sizeof(zval)); + Ts[opline->result.u.var].var.ptr_ptr = &Ts[opline->result.u.var].var.ptr; + var_uninit(Ts[opline->result.u.var].var.ptr); + Ts[opline->result.u.var].var.ptr->is_ref = 0; + Ts[opline->result.u.var].var.ptr->refcount = 1; + if (function_state.function->type==ZEND_INTERNAL_FUNCTION) { - ((zend_internal_function *) function_state.function)->handler(opline->extended_value, &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list), object.ptr, !return_value_not_used); + ((zend_internal_function *) function_state.function)->handler(opline->extended_value, Ts[opline->result.u.var].var.ptr, &EG(regular_list), &EG(persistent_list), object.ptr, !return_value_not_used); if (object.ptr) { object.ptr->refcount--; } + Ts[opline->result.u.var].var.ptr->is_ref = 0; + Ts[opline->result.u.var].var.ptr->refcount = 1; } else if (function_state.function->type==ZEND_USER_FUNCTION) { HashTable *calling_symbol_table; @@ -1502,13 +1514,13 @@ do_fcall_common: *this_ptr = object.ptr; object.ptr = NULL; } - original_return_value = EG(return_value); - EG(return_value) = &Ts[opline->result.u.var].tmp_var; + original_return_value = EG(return_value_ptr_ptr); + EG(return_value_ptr_ptr) = Ts[opline->result.u.var].var.ptr_ptr; EG(active_op_array) = (zend_op_array *) function_state.function; zend_execute(EG(active_op_array) ELS_CC); EG(opline_ptr) = &opline; EG(active_op_array) = op_array; - EG(return_value)=original_return_value; + EG(return_value_ptr_ptr)=original_return_value; if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { zend_hash_destroy(function_state.function_symbol_table); efree(function_state.function_symbol_table); @@ -1518,11 +1530,11 @@ do_fcall_common: } EG(active_symbol_table) = calling_symbol_table; } else { /* ZEND_OVERLOADED_FUNCTION */ - call_overloaded_function(opline->extended_value, &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list) ELS_CC); + call_overloaded_function(opline->extended_value, Ts[opline->result.u.var].var.ptr, &EG(regular_list), &EG(persistent_list) ELS_CC); efree(fbc); } if (return_value_not_used) { - zendi_zval_dtor(Ts[opline->result.u.var].tmp_var); + zval_ptr_dtor(&Ts[opline->result.u.var].var.ptr); } object.ptr = zend_ptr_stack_pop(&EG(arg_types_stack)); if (opline->opcode == ZEND_DO_FCALL_BY_NAME) { @@ -1534,11 +1546,41 @@ do_fcall_common: } break; case ZEND_RETURN: { - zval *retval = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); + zval *retval_ptr; + zval **retval_ptr_ptr; - *EG(return_value) = *retval; - if (!EG(free_op1)) { - zendi_zval_copy_ctor(*EG(return_value)); + if ((EG(active_op_array)->return_reference == ZEND_RETURN_REF) && + (opline->op1.op_type != IS_CONST) && + (opline->op1.op_type != IS_TMP_VAR)) { + + retval_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W); + + if (!PZVAL_IS_REF(*retval_ptr_ptr)) { + SEPARATE_ZVAL(retval_ptr_ptr); + (*retval_ptr_ptr)->is_ref = 1; + } + (*retval_ptr_ptr)->refcount++; + efree(*EG(return_value_ptr_ptr)); + (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr); + } else { + retval_ptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); + + if (!EG(free_op1)) { /* Not a temp var */ + if (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0) { + **EG(return_value_ptr_ptr) = *retval_ptr; + (*EG(return_value_ptr_ptr))->is_ref = 0; + (*EG(return_value_ptr_ptr))->refcount = 1; + zval_copy_ctor(*EG(return_value_ptr_ptr)); + } else { + efree(*EG(return_value_ptr_ptr)); + *EG(return_value_ptr_ptr) = retval_ptr; + retval_ptr->refcount++; + } + } else { + **EG(return_value_ptr_ptr) = *retval_ptr; + (*EG(return_value_ptr_ptr))->refcount = 1; + (*EG(return_value_ptr_ptr))->is_ref = 0; + } } #if SUPPORT_INTERACTIVE op_array->last_executed_op_number = opline-op_array->opcodes; @@ -1566,7 +1608,10 @@ do_fcall_common: goto send_by_ref; } { - zval *varptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); + zval *varptr; + SUSPEND_GARBAGE(); + varptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); + RESUME_GARBAGE(); if (varptr == &EG(uninitialized_zval)) { varptr = (zval *) emalloc(sizeof(zval)); @@ -1589,8 +1634,13 @@ do_fcall_common: break; send_by_ref: case ZEND_SEND_REF: { - zval **varptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W); - zval *varptr = *varptr_ptr; + zval **varptr_ptr; + zval *varptr; + SUSPEND_GARBAGE(); + varptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W); + RESUME_GARBAGE(); + + varptr = *varptr_ptr; if (!PZVAL_IS_REF(varptr)) { /* code to break away this variable */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 40bea67381..536e63f9c0 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -115,6 +115,7 @@ void init_executor(CLS_D ELS_DC) zend_llist_apply(&zend_extensions, (void (*)(void *)) zend_extension_activator); EG(opline_ptr) = NULL; EG(garbage_ptr) = 0; + EG(suspend_garbage) = 0; zend_hash_init(&EG(imported_files), 5, NULL, NULL, 0); } diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 947fc0044d..f4b20ee875 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -90,6 +90,7 @@ struct _zend_compiler_globals { zend_bool short_tags; zend_bool asp_tags; + zend_bool allow_call_time_pass_reference; /* For extensions support */ zend_bool extended_info; /* generate extension information for debugger/profiler */ @@ -110,6 +111,7 @@ struct _zend_compiler_globals { struct _zend_executor_globals { zval *return_value; + zval **return_value_ptr_ptr; zval uninitialized_zval; zval *uninitialized_zval_ptr; @@ -160,6 +162,7 @@ struct _zend_executor_globals { zval *garbage[4]; int garbage_ptr; + zend_bool suspend_garbage; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; #if SUPPORT_INTERACTIVE diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 5aa107305b..53d066ac09 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -99,6 +99,8 @@ void init_op_array(zend_op_array *op_array, int initial_ops_size) op_array->uses_globals = 0; + op_array->return_reference = 0; + zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_op_array_ctor_handler, op_array); }