diff options
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r-- | Zend/zend_vm_execute.h | 8665 |
1 files changed, 6548 insertions, 2117 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4abe6503cd..c077d5d2a5 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -326,79 +326,25 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o #define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC -#undef EX -#define EX(element) execute_data->element -#undef EX_CV -#define EX_CV(var) EX(CVs)[var] -#undef EX_CVs -#define EX_CVs() EX(CVs) -#undef EX_T -#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) -#undef EX_Ts -#define EX_Ts() EX(Ts) - - -ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) +ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) { DCL_OPLINE - zend_execute_data *execute_data; - zend_bool nested = 0; - zend_bool original_in_execution = EG(in_execution); + zend_bool original_in_execution; - if (EG(exception)) { - return; - } + original_in_execution = EG(in_execution); EG(in_execution) = 1; + if (0) { zend_vm_enter: - /* Initialize execute_data */ - execute_data = (zend_execute_data *)zend_vm_stack_alloc( - ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + - ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) + - ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC); - - EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))); - memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); - EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2))); - EX(fbc) = NULL; - EX(called_scope) = NULL; - EX(object) = NULL; - EX(old_error_reporting) = NULL; - EX(op_array) = op_array; - EX(symbol_table) = EG(active_symbol_table); - EX(prev_execute_data) = EG(current_execute_data); - EG(current_execute_data) = execute_data; - EX(nested) = nested; - nested = 1; - - LOAD_REGS(); - - if (!op_array->run_time_cache && op_array->last_cache_slot) { - op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); + execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); } - if (op_array->this_var != -1 && EG(This)) { - Z_ADDREF_P(EG(This)); /* For $this pointer */ - if (!EG(active_symbol_table)) { - EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var); - *EX_CV(op_array->this_var) = EG(This); - } else { - if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) { - Z_DELREF_P(EG(This)); - } - } - } - - EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes; - EG(opline_ptr) = &EX(opline); + LOAD_REGS(); LOAD_OPLINE(); - EX(function_state).function = (zend_function *) op_array; - EX(function_state).arguments = NULL; - while (1) { int ret; #ifdef ZEND_WIN32 @@ -413,10 +359,11 @@ zend_vm_enter: EG(in_execution) = original_in_execution; return; case 2: - op_array = EG(active_op_array); goto zend_vm_enter; + break; case 3: execute_data = EG(current_execute_data); + break; default: break; } @@ -426,31 +373,12 @@ zend_vm_enter: zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen"); } -static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC) { - USE_OPLINE - -#if DEBUG_ZEND>=2 - printf("Jumping to %d\n", opline->op1.opline_num); -#endif - ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); - ZEND_VM_CONTINUE(); /* CHECK_ME */ -} - -static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *tmp = &EX_T(opline->result.var).tmp_var; - - SAVE_OPLINE(); - tmp->value.str.val = emalloc(1); - tmp->value.str.val[0] = 0; - tmp->value.str.len = 0; - Z_SET_REFCOUNT_P(tmp, 1); - tmp->type = IS_STRING; - Z_UNSET_ISREF_P(tmp); - /*CHECK_EXCEPTION();*/ - ZEND_VM_NEXT_OPCODE(); + if (EG(exception)) { + return; + } + zend_execute_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); } static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) @@ -461,14 +389,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EG(current_execute_data) = EX(prev_execute_data); EG(opline_ptr) = NULL; if (!EG(active_symbol_table)) { - zval ***cv = EX_CVs(); - zval ***end = cv + op_array->last_var; - while (cv != end) { - if (*cv) { - zval_ptr_dtor(*cv); - } - cv++; - } + i_free_compiled_variables(execute_data); } if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { @@ -477,7 +398,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) nested = EX(nested); - zend_vm_stack_free(execute_data TSRMLS_CC); + zend_vm_stack_free((char*)execute_data - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T) TSRMLS_CC); if (nested) { execute_data = EG(current_execute_data); @@ -491,7 +412,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EX(function_state).function = (zend_function *) EX(op_array); EX(function_state).arguments = NULL; - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -501,34 +421,16 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION_LEAVE(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } ZEND_VM_INC_OPCODE(); ZEND_VM_LEAVE(); } else { - EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr) = EX(original_return_value); if (EG(active_symbol_table)) { - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); - } + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); } EG(active_symbol_table) = EX(symbol_table); @@ -536,8 +438,8 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EX(function_state).arguments = NULL; if (EG(This)) { - if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { Z_DELREF_P(EG(This)); } if (Z_REFCOUNT_P(EG(This)) == 1) { @@ -550,10 +452,9 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EG(scope) = EX(current_scope); EG(called_scope) = EX(current_called_scope); - EX(object) = EX(current_object); - EX(called_scope) = DECODE_CTOR(EX(called_scope)); + EX(call)--; - zend_vm_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_clear_multiple(1 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); @@ -577,6 +478,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR zend_function *fbc = EX(function_state).function; SAVE_OPLINE(); + EX(object) = EX(call)->object; if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name); @@ -611,11 +513,11 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR EX(current_called_scope) = EG(called_scope); EG(This) = EX(object); EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL; - EG(called_scope) = EX(called_scope); + EG(called_scope) = EX(call)->called_scope; } - zend_arg_types_stack_3_pop(&EG(arg_types_stack), &EX(called_scope), &EX(current_object), &EX(fbc)); - EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC); + EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); + zend_vm_stack_push((void*)(zend_uintptr_t)opline->extended_value TSRMLS_CC); LOAD_OPLINE(); if (fbc->type == ZEND_INTERNAL_FUNCTION) { @@ -641,7 +543,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); } else { - zend_execute_internal(execute_data, RETURN_VALUE_USED(opline) TSRMLS_CC); + zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); } if (!RETURN_VALUE_USED(opline)) { @@ -661,7 +563,11 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; } - if (EXPECTED(zend_execute == execute)) { + if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (RETURN_VALUE_USED(opline)) { + EX_T(opline->result.var).var.ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC); + } + } else if (EXPECTED(zend_execute_ex == execute_ex)) { if (EXPECTED(EG(exception) == NULL)) { ZEND_VM_ENTER(); } @@ -673,22 +579,14 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr) = EX(original_return_value); if (EG(active_symbol_table)) { - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); - } + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); } EG(active_symbol_table) = EX(symbol_table); } else { /* ZEND_OVERLOADED_FUNCTION */ MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr); ZVAL_NULL(EX_T(opline->result.var).var.ptr); - /* Not sure what should be done here if it's a static method */ + /* Not sure what should be done here if it's a static method */ if (EXPECTED(EX(object) != NULL)) { Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); } else { @@ -715,8 +613,8 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR if (should_change_scope) { if (EG(This)) { - if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { Z_DELREF_P(EG(This)); } if (Z_REFCOUNT_P(EG(This)) == 1) { @@ -730,10 +628,9 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR EG(called_scope) = EX(current_called_scope); } - EX(object) = EX(current_object); - EX(called_scope) = DECODE_CTOR(EX(called_scope)); + EX(call)--; - zend_vm_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_clear_multiple(1 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); @@ -746,12 +643,51 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + +#if DEBUG_ZEND>=2 + printf("Jumping to %d\n", opline->op1.opline_num); +#endif + ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); + ZEND_VM_CONTINUE(); +} + +static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *tmp = &EX_T(opline->result.var).tmp_var; + + SAVE_OPLINE(); + tmp->value.str.val = emalloc(1); + tmp->value.str.val[0] = 0; + tmp->value.str.len = 0; + Z_SET_REFCOUNT_P(tmp, 1); + tmp->type = IS_STRING; + Z_UNSET_ISREF_P(tmp); + /*CHECK_EXCEPTION();*/ + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - EX(function_state).function = EX(fbc); + EX(function_state).function = EX(call)->fbc; return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1 TSRMLS_CC); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -783,7 +719,7 @@ static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval **var_ptr; zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); Z_DELREF_PP(var_ptr); *var_ptr = *param; Z_ADDREF_PP(var_ptr); @@ -823,17 +759,20 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.opline_num); } else { + call_slot *call = EX(call_slots) + opline->extended_value; + if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(object_zval); AI_SET_PTR(&EX_T(opline->result.var), object_zval); } - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline))); - /* We are not handling overloaded classes right now */ - EX(object) = object_zval; - EX(fbc) = constructor; - EX(called_scope) = EX_T(opline->op1.var).class_entry; + call->fbc = constructor; + call->object = object_zval; + call->called_scope = EX_T(opline->op1.var).class_entry; + call->is_ctor_call = 1; + call->is_ctor_result_used = RETURN_VALUE_USED(opline); + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1033,13 +972,15 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER { zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes; int i; - zend_uint catch_op_num = 0; - int catched = 0; - zval restored_error_reporting; + zend_uint catch_op_num = 0, finally_op_num = 0; + void **stack_frame; - void **stack_frame = (void**)(((char*)EX_Ts()) + - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T)); + /* Figure out where the next stack frame (which maybe contains pushed + * arguments that have to be dtor'ed) starts */ + stack_frame = zend_vm_stack_frame_base(execute_data); + /* If the exception was thrown during a function call there might be + * arguments pushed to the stack that have to be dtor'ed. */ while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); zval_ptr_dtor(&stack_zval_p); @@ -1049,27 +990,32 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER if (EG(active_op_array)->try_catch_array[i].try_op > op_num) { /* further blocks will not be relevant... */ break; - } else if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { + } + if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { catch_op_num = EX(op_array)->try_catch_array[i].catch_op; - catched = 1; + } + if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) { + finally_op_num = EX(op_array)->try_catch_array[i].finally_op; } } - while (EX(fbc)) { - EX(called_scope) = (zend_class_entry*)zend_ptr_stack_pop(&EG(arg_types_stack)); - if (EX(object)) { - if (IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { - Z_DELREF_P(EX(object)); - } - if (Z_REFCOUNT_P(EX(object)) == 1) { - zend_object_store_ctor_failed(EX(object) TSRMLS_CC); + if (EX(call) >= EX(call_slots)) { + call_slot *call = EX(call); + do { + if (call->object) { + if (call->is_ctor_call) { + if (call->is_ctor_result_used) { + Z_DELREF_P(call->object); + } + if (Z_REFCOUNT_P(call->object) == 1) { + zend_object_store_ctor_failed(call->object TSRMLS_CC); + } } + zval_ptr_dtor(&call->object); } - zval_ptr_dtor(&EX(object)); - } - EX(called_scope) = DECODE_CTOR(EX(called_scope)); - zend_arg_types_stack_2_pop(&EG(arg_types_stack), &EX(object), &EX(fbc)); + call--; + } while (call >= EX(call_slots)); + EX(call) = NULL; } for (i=0; i<EX(op_array)->last_brk_cont; i++) { @@ -1079,7 +1025,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER /* further blocks will not be relevant... */ break; } else if (op_num < EX(op_array)->brk_cont_array[i].brk) { - if (!catched || + if (!catch_op_num || catch_op_num >= EX(op_array)->brk_cont_array[i].brk) { zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk]; @@ -1101,6 +1047,8 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER /* restore previous error_reporting value */ if (!EG(error_reporting) && EX(old_error_reporting) != NULL && Z_LVAL_P(EX(old_error_reporting)) != 0) { + zval restored_error_reporting; + Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL_P(EX(old_error_reporting)); convert_to_string(&restored_error_reporting); @@ -1109,12 +1057,21 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER } EX(old_error_reporting) = NULL; - if (!catched) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { + if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { + zend_exception_save(TSRMLS_C); + EX(fast_ret) = NULL; + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); + ZEND_VM_CONTINUE(); + } else if (catch_op_num) { ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); - ZEND_VM_CONTINUE(); - } + ZEND_VM_CONTINUE(); + } else { + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + } } static int ZEND_FASTCALL ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -1140,7 +1097,11 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS case ZEND_USER_OPCODE_CONTINUE: ZEND_VM_CONTINUE(); case ZEND_USER_OPCODE_RETURN: - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } case ZEND_USER_OPCODE_ENTER: ZEND_VM_ENTER(); case ZEND_USER_OPCODE_LEAVE: @@ -1152,12 +1113,66 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS } } +static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EG(prev_exception) != NULL) { + /* discard the previously thrown exception */ + zval_ptr_dtor(&EG(prev_exception)); + EG(prev_exception) = NULL; + } + + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (opline->extended_value && + UNEXPECTED(EG(prev_exception) != NULL)) { + /* in case of unhandled exception jump to catch block instead of finally */ + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } + EX(fast_ret) = opline + 1; + ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); + ZEND_VM_CONTINUE(); +} + +static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EX(fast_ret)) { + ZEND_VM_SET_OPCODE(EX(fast_ret)); + ZEND_VM_CONTINUE(); + } else { + /* special case for unhandled exceptions */ + USE_OPLINE + + if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { + zend_exception_restore(TSRMLS_C); + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + zend_exception_restore(TSRMLS_C); + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + zend_exception_restore(TSRMLS_C); + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + } +} + static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_CONST == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); @@ -1190,19 +1205,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (IS_CONST == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1222,28 +1240,33 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (IS_CONST == IS_VAR && 0 && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && @@ -1274,46 +1297,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -1323,25 +1349,27 @@ static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC { USE_OPLINE zend_literal *func_name; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; func_name = opline->op2.literal + 1; if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &call->fbc)==FAILURE) { func_name++; - if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) { + if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &call->fbc)==FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; ZEND_VM_NEXT_OPCODE(); } @@ -1371,7 +1399,7 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ } zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); Z_DELREF_PP(var_ptr); *var_ptr = assignment_value; @@ -1386,7 +1414,7 @@ static int ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); ZEND_VM_JMP(EX(op_array)->opcodes + el->brk); } @@ -1398,7 +1426,7 @@ static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); ZEND_VM_JMP(EX(op_array)->opcodes + el->cont); } @@ -1411,7 +1439,7 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); brk_opline = EX(op_array)->opcodes + el->brk; @@ -1462,14 +1490,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_TMP_VAR == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_op2; - zval *class_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *class_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR == IS_CONST) { if (CACHED_PTR(opline->op2.literal->cache_slot)) { @@ -1496,19 +1526,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (IS_TMP_VAR == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1517,7 +1550,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H zend_free_op free_op2; SAVE_OPLINE(); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { function_name_strval = Z_STRVAL_P(function_name); @@ -1528,28 +1561,33 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); zval_dtor(free_op2.var); - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (IS_TMP_VAR == IS_VAR && 1 && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { zval_dtor(free_op2.var); } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && @@ -1580,46 +1618,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -1630,14 +1671,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_VAR == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_op2; - zval *class_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *class_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_CONST) { if (CACHED_PTR(opline->op2.literal->cache_slot)) { @@ -1664,19 +1707,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (IS_VAR == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1685,7 +1731,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H zend_free_op free_op2; SAVE_OPLINE(); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { function_name_strval = Z_STRVAL_P(function_name); @@ -1696,28 +1742,33 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (IS_VAR == IS_VAR && (free_op2.var != NULL) && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && @@ -1748,46 +1799,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -1798,7 +1852,9 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDL USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_UNUSED == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); @@ -1832,14 +1888,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_CV == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - zval *class_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *class_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_CONST) { if (CACHED_PTR(opline->op2.literal->cache_slot)) { @@ -1865,19 +1923,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (IS_CV == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1886,7 +1947,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { function_name_strval = Z_STRVAL_P(function_name); @@ -1897,28 +1958,33 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (IS_CV == IS_VAR && 0 && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && @@ -1949,46 +2015,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -2219,8 +2288,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A USE_OPLINE zval *fname = opline->op1.zv; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->op2.num; if (CACHED_PTR(opline->op1.literal->cache_slot)) { EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot); @@ -2230,7 +2298,11 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } else { CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function); } - EX(object) = NULL; + call->fbc = EX(function_state).function; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -2249,6 +2321,9 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG } } else if (!0) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (IS_CONST == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -2270,6 +2345,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -2288,6 +2367,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -2378,7 +2461,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num); } { @@ -2542,7 +2625,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA zend_op_array *new_op_array=NULL; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); @@ -2634,8 +2717,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -2643,14 +2724,13 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -2660,15 +2740,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -3377,7 +3448,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCO { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -3390,6 +3461,36 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HAN return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_CONST != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_CONST == IS_TMP_VAR || IS_CONST == IS_CONST) { + zval *container = opline->op1.zv; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3419,9 +3520,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -3435,24 +3536,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_CONST == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_CONST == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_CONST != IS_UNUSED) { char *function_name_strval = NULL; @@ -3475,20 +3576,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -3502,29 +3603,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -3940,6 +4043,160 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3948,7 +4205,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -3963,7 +4220,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -3978,7 +4235,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -3993,7 +4250,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4008,7 +4265,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4023,7 +4280,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4038,7 +4295,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4053,7 +4310,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4068,7 +4325,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4084,7 +4341,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); is_identical_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op2.var); @@ -4101,7 +4358,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4117,7 +4374,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4133,7 +4390,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4149,7 +4406,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_O SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4164,7 +4421,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4179,7 +4436,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4194,7 +4451,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4209,21 +4466,51 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_CONST != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_CONST == IS_TMP_VAR || IS_CONST == IS_CONST) { + zval *container = opline->op1.zv; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -4237,24 +4524,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_TMP_VAR == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_TMP_VAR == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_TMP_VAR != IS_UNUSED) { char *function_name_strval = NULL; @@ -4265,7 +4552,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -4277,20 +4564,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -4304,29 +4591,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -4343,7 +4632,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_A } is_equal_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4388,7 +4677,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -4450,6 +4739,160 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4458,7 +4901,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4473,7 +4916,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4488,7 +4931,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4503,7 +4946,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4518,7 +4961,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4533,7 +4976,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4548,7 +4991,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4563,7 +5006,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4578,7 +5021,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4594,7 +5037,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); is_identical_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -4611,7 +5054,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4627,7 +5070,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4643,7 +5086,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4659,7 +5102,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_O SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4674,7 +5117,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4689,7 +5132,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4704,7 +5147,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4719,7 +5162,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4877,7 +5320,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -4890,14 +5333,44 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_CONST != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_CONST == IS_TMP_VAR || IS_CONST == IS_CONST) { + zval *container = opline->op1.zv; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -4911,24 +5384,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_VAR == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_VAR == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_VAR != IS_UNUSED) { char *function_name_strval = NULL; @@ -4939,7 +5412,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -4951,20 +5424,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -4978,29 +5451,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5017,7 +5492,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_A } is_equal_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -5062,7 +5537,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -5285,6 +5760,161 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5436,7 +6066,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPC { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -5454,9 +6084,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -5470,24 +6100,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_UNUSED == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_UNUSED == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_UNUSED != IS_UNUSED) { char *function_name_strval = NULL; @@ -5510,20 +6140,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_UNUSED == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -5537,29 +6167,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5838,12 +6470,166 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER zend_error_noreturn(E_ERROR, "Base lambda function for closure not found"); } - zend_create_closure(&EX_T(opline->result.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC); + zend_create_closure(&EX_T(opline->result.var).tmp_var, (zend_function *) op_array, EG(scope), EG(This) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5852,7 +6638,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5867,7 +6653,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5882,7 +6668,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5897,7 +6683,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5912,7 +6698,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5927,7 +6713,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5942,7 +6728,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5957,7 +6743,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5972,7 +6758,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5988,7 +6774,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); is_identical_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); @@ -6005,7 +6791,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -6021,7 +6807,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -6037,7 +6823,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -6053,7 +6839,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OP SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -6068,7 +6854,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -6083,7 +6869,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -6098,7 +6884,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -6113,21 +6899,51 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_CONST != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_CONST == IS_TMP_VAR || IS_CONST == IS_CONST) { + zval *container = opline->op1.zv; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -6141,24 +6957,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_CV == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_CV == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_CV != IS_UNUSED) { char *function_name_strval = NULL; @@ -6169,7 +6985,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -6181,20 +6997,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -6208,29 +7024,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6280,7 +7098,7 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A if (EX_CV(opline->op2.var)) { zval_ptr_dtor(EX_CV(opline->op2.var)); } - EX_CV(opline->op2.var) = (zval**)EX_CVs() + (EX(op_array)->last_var + opline->op2.var); + EX_CV(opline->op2.var) = (zval**)EX_CV_NUM(execute_data, EX(op_array)->last_var + opline->op2.var); *EX_CV(opline->op2.var) = EG(exception); } else { zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.var); @@ -6307,7 +7125,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_AR } is_equal_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6351,7 +7169,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -6413,6 +7231,160 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAND } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -6420,7 +7392,7 @@ static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); bitwise_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6433,7 +7405,7 @@ static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); boolean_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6447,7 +7419,7 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + z = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && @@ -6486,7 +7458,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -6516,7 +7488,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -6546,7 +7518,7 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int retval; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -6580,7 +7552,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS int retval; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -6611,7 +7583,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG int retval; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -6655,13 +7627,16 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_TMP_VAR == IS_TMP_VAR) { zval_dtor(free_op1.var); } } else if (!1) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (IS_TMP_VAR == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -6683,6 +7658,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -6701,11 +7680,15 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_TMP_VAR == IS_TMP_VAR) { zval_dtor(free_op1.var); @@ -6766,7 +7749,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Can only throw objects"); @@ -6791,7 +7774,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num); } { @@ -6799,7 +7782,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value; zend_free_op free_op1; - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ALLOC_ZVAL(valptr); INIT_PZVAL_COPY(valptr, value); @@ -6821,7 +7804,7 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC))); + ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC))); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -6838,7 +7821,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + obj = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { @@ -6899,7 +7882,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *result = &EX_T(opline->result.var).tmp_var; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); @@ -6956,11 +7939,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND zend_op_array *new_op_array=NULL; zend_free_op free_op1; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + inc_filename = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (inc_filename->type!=IS_STRING) { MAKE_STD_ZVAL(tmp_inc_filename); @@ -7048,8 +8031,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -7057,14 +8038,13 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -7074,15 +8054,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -7137,7 +8108,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG Z_ADDREF_P(array_ptr); } } else { - array_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* IS_TMP_VAR */ zval *tmp; @@ -7246,7 +8217,7 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op1; - zval *ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval *ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); @@ -7296,7 +8267,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); @@ -7322,7 +8293,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (i_zend_is_true(value)) { if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { @@ -7357,7 +8328,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); if (!1) { @@ -7375,7 +8346,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { Z_ADDREF_P(value); @@ -7403,7 +8374,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC); @@ -7423,7 +8394,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7438,7 +8409,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7453,7 +8424,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7468,7 +8439,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7483,7 +8454,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7498,7 +8469,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7513,7 +8484,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7528,7 +8499,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7543,7 +8514,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7559,7 +8530,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op1.var); @@ -7576,7 +8547,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); zval_dtor(free_op1.var); @@ -7592,7 +8563,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); zval_dtor(free_op1.var); @@ -7608,7 +8579,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); zval_dtor(free_op1.var); @@ -7624,7 +8595,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_O SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); zval_dtor(free_op1.var); @@ -7639,7 +8610,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7654,7 +8625,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7669,7 +8640,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7684,7 +8655,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7703,7 +8674,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -7843,7 +8814,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7856,6 +8827,36 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_TMP_VAR != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_TMP_VAR == IS_TMP_VAR || IS_TMP_VAR == IS_CONST) { + zval *container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + zval_dtor(free_op1.var); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7863,7 +8864,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) { PZVAL_LOCK(&EG(uninitialized_zval)); @@ -7933,9 +8934,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO char *function_name_strval; int function_name_strlen; zend_free_op free_op1; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = opline->op2.zv; @@ -7947,49 +8948,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CONST != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -8006,7 +9009,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_A PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); @@ -8030,7 +9033,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -8137,7 +9140,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -8213,7 +9216,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -8274,6 +9277,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8281,8 +9438,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8296,8 +9453,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8311,8 +9468,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8326,8 +9483,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8341,8 +9498,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8356,8 +9513,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8371,8 +9528,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8386,8 +9543,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8401,8 +9558,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8417,8 +9574,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op1.var); zval_dtor(free_op2.var); @@ -8434,8 +9591,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8450,8 +9607,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8466,8 +9623,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8482,8 +9639,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPC SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8497,8 +9654,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8512,8 +9669,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8527,8 +9684,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8542,14 +9699,44 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_TMP_VAR != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_TMP_VAR == IS_TMP_VAR || IS_TMP_VAR == IS_CONST) { + zval *container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + zval_dtor(free_op1.var); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8560,7 +9747,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + var = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -8602,11 +9789,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -8616,49 +9803,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_TMP_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); @@ -8676,8 +9865,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8701,7 +9890,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -8722,7 +9911,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -8784,6 +9973,160 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8791,8 +10134,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8806,8 +10149,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8821,8 +10164,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8836,8 +10179,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8851,8 +10194,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8866,8 +10209,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8881,8 +10224,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8896,8 +10239,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8911,8 +10254,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8927,8 +10270,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -8944,8 +10287,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8960,8 +10303,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8976,8 +10319,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8992,8 +10335,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPC SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9007,8 +10350,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9022,8 +10365,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9037,8 +10380,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9052,8 +10395,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9071,7 +10414,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -9211,7 +10554,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_H { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -9224,6 +10567,36 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_TMP_VAR != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_TMP_VAR == IS_TMP_VAR || IS_TMP_VAR == IS_CONST) { + zval *container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + zval_dtor(free_op1.var); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -9234,7 +10607,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -9276,11 +10649,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -9290,49 +10663,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -9350,8 +10725,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9375,7 +10750,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -9396,7 +10771,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -9482,7 +10857,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -9558,7 +10933,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -9619,6 +10994,161 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -9630,7 +11160,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -9770,7 +11300,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCOD { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -9800,7 +11330,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -9907,7 +11437,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -9983,7 +11513,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -10044,6 +11574,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10051,8 +11735,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10066,8 +11750,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10081,8 +11765,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10096,8 +11780,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10111,8 +11795,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10126,8 +11810,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10141,8 +11825,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10156,8 +11840,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10171,8 +11855,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10187,8 +11871,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op1.var); @@ -10204,8 +11888,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10220,8 +11904,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10236,8 +11920,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10252,8 +11936,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10267,8 +11951,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10282,8 +11966,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10297,8 +11981,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10312,14 +11996,44 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_TMP_VAR != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_TMP_VAR == IS_TMP_VAR || IS_TMP_VAR == IS_CONST) { + zval *container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + zval_dtor(free_op1.var); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10330,7 +12044,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_A int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -10371,11 +12085,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ char *function_name_strval; int function_name_strlen; zend_free_op free_op1; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -10385,49 +12099,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CV != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -10444,8 +12160,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10468,7 +12184,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -10489,7 +12205,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -10551,6 +12267,160 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10558,7 +12428,7 @@ static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); bitwise_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10571,7 +12441,7 @@ static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); boolean_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10584,7 +12454,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval **var_ptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -10631,7 +12501,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval **var_ptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -10678,7 +12548,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval **var_ptr, *retval; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -10721,7 +12591,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval **var_ptr, *retval; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -10765,7 +12635,7 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + z = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && @@ -10804,7 +12674,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -10834,7 +12704,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -10864,7 +12734,7 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int retval; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -10898,7 +12768,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS int retval; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -10929,7 +12799,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG int retval; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -10973,13 +12843,16 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_VAR == IS_TMP_VAR) { if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; } } else if (!0) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (IS_VAR == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -11001,6 +12874,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -11019,11 +12896,15 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_VAR == IS_TMP_VAR) { if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -11045,7 +12926,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE break; } - retval_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); @@ -11085,7 +12966,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Can only throw objects"); @@ -11109,7 +12990,7 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_AR USE_OPLINE zval *varptr; zend_free_op free_op1; - varptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (varptr == &EG(uninitialized_zval)) { ALLOC_ZVAL(varptr); @@ -11143,7 +13024,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) { return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -11154,7 +13035,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND varptr = EX_T(opline->op1.var).var.ptr; PZVAL_UNLOCK_EX(varptr, &free_op1, 0); } else { - varptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); } if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || EX_T(opline->op1.var).var.fcall_returned_reference) && @@ -11169,7 +13050,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error(E_STRICT, "Only variables should be passed by reference"); } ALLOC_ZVAL(valptr); @@ -11192,7 +13073,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *varptr; SAVE_OPLINE(); - varptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(varptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); @@ -11205,7 +13086,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ZEND_VM_NEXT_OPCODE(); } - if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -11224,7 +13105,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG USE_OPLINE if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } SAVE_OPLINE(); @@ -11239,7 +13120,7 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC))); + ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC))); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -11266,7 +13147,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + obj = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { @@ -11327,7 +13208,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *result = &EX_T(opline->result.var).tmp_var; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); @@ -11384,11 +13265,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND zend_op_array *new_op_array=NULL; zend_free_op free_op1; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + inc_filename = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (inc_filename->type!=IS_STRING) { MAKE_STD_ZVAL(tmp_inc_filename); @@ -11476,8 +13357,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -11485,14 +13364,13 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -11502,15 +13380,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -11538,7 +13407,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && (opline->extended_value & ZEND_FE_RESET_VARIABLE)) { - array_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + array_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) { MAKE_STD_ZVAL(array_ptr); ZVAL_NULL(array_ptr); @@ -11565,7 +13434,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG Z_ADDREF_P(array_ptr); } } else { - array_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + array_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* IS_TMP_VAR */ zval *tmp; @@ -11817,7 +13686,7 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); if (IS_VAR != IS_UNUSED) { zend_free_op free_op1; - zval *ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval *ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); @@ -11838,7 +13707,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); @@ -11864,7 +13733,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (i_zend_is_true(value)) { if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { @@ -11899,7 +13768,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); if (!0) { @@ -11917,7 +13786,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { Z_ADDREF_P(value); @@ -11946,7 +13815,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC); @@ -11966,7 +13835,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -11981,7 +13850,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -11996,7 +13865,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12011,7 +13880,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12026,7 +13895,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12041,7 +13910,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12056,7 +13925,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12071,7 +13940,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12086,7 +13955,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12102,7 +13971,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12119,7 +13988,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12135,7 +14004,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12151,7 +14020,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12167,7 +14036,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_O SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12182,7 +14051,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12197,7 +14066,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12212,7 +14081,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12227,7 +14096,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12239,10 +14108,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b { USE_OPLINE zend_free_op free_op1, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; zval *property = opline->op2.zv; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -12360,7 +14229,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -12373,14 +14242,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar zval *dim = opline->op2.zv; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: value = opline->op2.zv; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -12502,7 +14371,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = opline->op2.zv; retval = &EX_T(opline->result.var).var.ptr; @@ -12606,7 +14475,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = opline->op2.zv; retval = &EX_T(opline->result.var).tmp_var; @@ -12708,7 +14577,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -12848,7 +14717,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12874,10 +14743,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + if (IS_VAR == IS_TMP_VAR || IS_VAR == IS_CONST) { + zval *container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } else { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12889,7 +14767,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -12923,7 +14801,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -12945,7 +14823,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_IS TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12961,8 +14839,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -12974,7 +14852,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (IS_CONST == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); } @@ -12990,7 +14868,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -13008,6 +14886,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -13032,7 +14911,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST( zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || @@ -13089,7 +14968,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -13129,7 +15008,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); property = opline->op2.zv; - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -13160,7 +15039,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || @@ -13197,7 +15076,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -13205,7 +15084,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP SAVE_OPLINE(); property = opline->op2.zv; - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -13238,7 +15117,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = opline->op2.zv; if (IS_VAR == IS_CV) { @@ -13281,7 +15160,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property_name = opline->op2.zv; if (0) { @@ -13290,7 +15169,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -13310,7 +15189,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -13322,7 +15201,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -13336,8 +15215,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CONST, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -13392,7 +15271,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); value = opline->op2.zv; - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CONST TSRMLS_CC)) { @@ -13445,9 +15324,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO char *function_name_strval; int function_name_strlen; zend_free_op free_op1; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = opline->op2.zv; @@ -13459,49 +15338,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CONST != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -13514,9 +15395,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -13530,24 +15411,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_CONST == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_CONST == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_CONST != IS_UNUSED) { char *function_name_strval = NULL; @@ -13570,20 +15451,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -13597,29 +15478,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -13635,7 +15518,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_A PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); @@ -13742,7 +15625,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -13751,7 +15634,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -13858,7 +15741,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -13919,7 +15802,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -14018,7 +15901,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; if (IS_VAR != IS_VAR || container) { @@ -14075,7 +15958,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -14147,7 +16030,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST( zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; @@ -14290,6 +16173,162 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -14297,8 +16336,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14312,8 +16351,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14327,8 +16366,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14342,8 +16381,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14357,8 +16396,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14372,8 +16411,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14387,8 +16426,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14402,8 +16441,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14417,8 +16456,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14433,8 +16472,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); @@ -14450,8 +16489,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14466,8 +16505,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14482,8 +16521,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14498,8 +16537,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPC SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14513,8 +16552,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14528,8 +16567,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14543,8 +16582,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14558,8 +16597,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14570,10 +16609,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin { USE_OPLINE zend_free_op free_op1, free_op2, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -14691,7 +16730,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -14701,17 +16740,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ } return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -14834,8 +16873,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -14938,8 +16977,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -15042,10 +17081,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); - zval_dtor(free_op2.var); - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + + if (IS_VAR == IS_TMP_VAR || IS_VAR == IS_CONST) { + zval *container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } else { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -15057,12 +17105,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -15091,12 +17139,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); zval_dtor(free_op2.var); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -15113,8 +17161,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -15129,12 +17177,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -15142,8 +17190,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); } zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -15158,7 +17206,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -15168,7 +17216,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC); zval_dtor(free_op2.var); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -15176,6 +17224,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -15200,8 +17249,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZE zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -15247,7 +17296,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -15257,7 +17306,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND if (1) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -15296,8 +17345,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property); @@ -15328,8 +17377,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -15365,15 +17414,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property); @@ -15406,8 +17455,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -15449,8 +17498,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); @@ -15458,7 +17507,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -15478,19 +17527,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; - zval *property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -15499,14 +17548,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL } else { zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -15560,8 +17609,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_TMP_VAR TSRMLS_CC)) { @@ -15614,11 +17663,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -15628,49 +17677,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_TMP_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -15684,9 +17735,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -15700,24 +17751,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_TMP_VAR == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_TMP_VAR == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_TMP_VAR != IS_UNUSED) { char *function_name_strval = NULL; @@ -15728,7 +17779,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -15740,20 +17791,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -15767,29 +17818,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -15805,8 +17858,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -15821,7 +17874,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -15830,7 +17883,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -15851,7 +17904,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -15922,11 +17975,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -16021,8 +18074,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -16065,9 +18118,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(in zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -16208,6 +18261,162 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_ return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -16215,8 +18424,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16230,8 +18439,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16245,8 +18454,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16260,8 +18469,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16275,8 +18484,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16290,8 +18499,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16305,8 +18514,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16320,8 +18529,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16335,8 +18544,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16351,8 +18560,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -16368,8 +18577,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16384,8 +18593,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16400,8 +18609,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16416,8 +18625,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPC SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16431,8 +18640,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16446,8 +18655,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16461,8 +18670,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16476,8 +18685,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16488,10 +18697,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin { USE_OPLINE zend_free_op free_op1, free_op2, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -16609,7 +18818,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -16619,17 +18828,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ } return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -16752,8 +18961,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -16856,8 +19065,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -16958,7 +19167,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -17098,7 +19307,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_H { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17124,10 +19333,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + + if (IS_VAR == IS_TMP_VAR || IS_VAR == IS_CONST) { + zval *container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } else { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -17139,12 +19357,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -17173,12 +19391,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -17195,8 +19413,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -17211,12 +19429,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -17224,8 +19442,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO if (IS_VAR == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -17240,7 +19458,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -17250,7 +19468,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -17258,6 +19476,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -17282,8 +19501,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZE zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -17329,7 +19548,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -17339,7 +19558,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -17378,8 +19597,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -17410,8 +19629,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -17447,15 +19666,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -17488,8 +19707,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -17531,8 +19750,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -17540,7 +19759,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -17560,19 +19779,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; - zval *property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -17581,14 +19800,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL } else { zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_VAR, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -17642,8 +19861,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_VAR TSRMLS_CC)) { @@ -17698,7 +19917,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zval **value_ptr_ptr; SAVE_OPLINE(); - value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_VAR && value_ptr_ptr && @@ -17721,7 +19940,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) || (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); @@ -17751,11 +19970,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -17765,49 +19984,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -17821,9 +20042,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -17837,24 +20058,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_VAR == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_VAR == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_VAR != IS_UNUSED) { char *function_name_strval = NULL; @@ -17865,7 +20086,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -17877,20 +20098,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -17904,29 +20125,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -17942,8 +20165,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -17958,7 +20181,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -17967,7 +20190,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -17988,7 +20211,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -18074,7 +20297,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -18135,11 +20358,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -18234,8 +20457,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -18291,7 +20514,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -18363,9 +20586,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(in zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -18506,14 +20729,171 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_ return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; zval *property = NULL; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -18631,7 +21011,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -18644,14 +21024,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina zval *dim = NULL; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: value = NULL; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -18773,7 +21153,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -18913,7 +21293,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCOD { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18933,7 +21313,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -18967,7 +21347,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -18990,8 +21370,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -19003,7 +21383,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O if (IS_UNUSED == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_R TSRMLS_CC); } @@ -19019,7 +21399,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -19031,7 +21411,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -19045,8 +21425,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_UNUSED, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -19097,9 +21477,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -19113,24 +21493,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_UNUSED == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_UNUSED == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_UNUSED != IS_UNUSED) { char *function_name_strval = NULL; @@ -19153,20 +21533,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_UNUSED == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -19180,29 +21560,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -19216,7 +21598,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -19225,7 +21607,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -19332,7 +21714,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -19408,7 +21790,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -19477,8 +21859,8 @@ static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); var_ptr = EX_T(opline->op1.var).var.ptr; if (Z_TYPE_P(var_ptr) != IS_OBJECT && - !PZVAL_IS_REF(var_ptr) && - Z_REFCOUNT_P(var_ptr) > 1) { + !PZVAL_IS_REF(var_ptr) && + Z_REFCOUNT_P(var_ptr) > 1) { Z_DELREF_P(var_ptr); ALLOC_ZVAL(new_zv); @@ -19490,6 +21872,162 @@ static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -19497,8 +22035,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19512,8 +22050,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19527,8 +22065,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19542,8 +22080,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19557,8 +22095,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19572,8 +22110,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19587,8 +22125,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19602,8 +22140,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19617,8 +22155,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19633,8 +22171,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -19650,8 +22188,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19666,8 +22204,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19682,8 +22220,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19698,8 +22236,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19713,8 +22251,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19728,8 +22266,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19743,8 +22281,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19758,8 +22296,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19770,10 +22308,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina { USE_OPLINE zend_free_op free_op1, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -19891,7 +22429,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -19901,17 +22439,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o } return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -20033,8 +22571,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -20137,8 +22675,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -20241,10 +22779,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + if (IS_VAR == IS_TMP_VAR || IS_VAR == IS_CONST) { + zval *container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } else { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -20256,12 +22803,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -20290,12 +22837,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -20312,8 +22859,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -20328,12 +22875,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -20341,8 +22888,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (IS_CV == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -20357,7 +22904,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -20367,7 +22914,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -20375,6 +22922,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -20399,8 +22947,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -20446,7 +22994,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -20456,7 +23004,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -20495,8 +23043,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -20527,8 +23075,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -20564,15 +23112,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -20605,8 +23153,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -20648,8 +23196,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -20657,7 +23205,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -20677,19 +23225,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zval *property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -20698,13 +23246,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE } else { zend_free_op free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CV, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -20758,8 +23306,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CV TSRMLS_CC)) { @@ -20813,7 +23361,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zval **value_ptr_ptr; SAVE_OPLINE(); - value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op2.var TSRMLS_CC); + value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_VAR && value_ptr_ptr && @@ -20836,7 +23384,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) || (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); @@ -20865,11 +23413,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ char *function_name_strval; int function_name_strlen; zend_free_op free_op1; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -20879,49 +23427,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CV != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -20934,9 +23484,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -20950,24 +23500,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_CV == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_CV == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_CV != IS_UNUSED) { char *function_name_strval = NULL; @@ -20978,7 +23528,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -20990,20 +23540,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -21017,29 +23567,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -21055,8 +23607,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -21070,7 +23622,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -21079,7 +23631,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -21100,7 +23652,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -21171,11 +23723,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -21270,8 +23822,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -21314,9 +23866,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -21457,6 +24009,162 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CV_HANDLER(ZEND_O return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -21549,7 +24257,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; zval *property = opline->op2.zv; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -21679,8 +24387,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi zval *dim = opline->op2.zv; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; @@ -22174,7 +24882,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -22266,7 +24974,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -22332,9 +25040,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O char *function_name_strval; int function_name_strlen; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = opline->op2.zv; @@ -22346,49 +25054,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + call->object = _get_obj_zval_ptr_unused(TSRMLS_C); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CONST != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -22792,14 +25502,168 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER( return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2, free_op_data1; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; - zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -22926,16 +25790,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = NULL; /* do nothing */ break; @@ -23060,7 +25924,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -23164,7 +26028,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -23264,7 +26128,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -23309,7 +26173,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -23357,7 +26221,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (1) { @@ -23390,7 +26254,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -23425,14 +26289,14 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (1) { @@ -23467,7 +26331,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -23509,7 +26373,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); @@ -23517,7 +26381,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -23540,7 +26404,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDL int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + var = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -23582,11 +26446,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC char *function_name_strval; int function_name_strlen; zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -23596,49 +26460,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + call->object = _get_obj_zval_ptr_unused(TSRMLS_C); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_TMP_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); @@ -23673,7 +26539,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -23768,7 +26634,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -23812,7 +26678,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -23951,14 +26817,168 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZE return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2, free_op_data1; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; - zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -24085,16 +27105,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = NULL; /* do nothing */ break; @@ -24219,7 +27239,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -24323,7 +27343,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -24423,7 +27443,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -24468,7 +27488,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -24516,7 +27536,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (0) { @@ -24549,7 +27569,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -24584,14 +27604,14 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (0) { @@ -24626,7 +27646,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -24668,7 +27688,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -24676,7 +27696,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -24699,7 +27719,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDL int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -24741,11 +27761,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC char *function_name_strval; int function_name_strlen; zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -24755,49 +27775,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + call->object = _get_obj_zval_ptr_unused(TSRMLS_C); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -24832,7 +27854,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -24927,7 +27949,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -24971,7 +27993,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -25110,6 +28132,161 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_VAR_HANDLER(ZE return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -25117,7 +28294,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; zval *property = NULL; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -25247,8 +28424,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b zval *dim = NULL; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; @@ -25379,14 +28556,168 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op_data1; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; - zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -25513,16 +28844,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = NULL; /* do nothing */ break; @@ -25646,7 +28977,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -25750,7 +29081,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -25850,7 +29181,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV( SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -25895,7 +29226,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -25943,7 +29274,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (0) { @@ -25976,7 +29307,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -26011,14 +29342,14 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (0) { @@ -26053,7 +29384,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -26095,7 +29426,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -26103,7 +29434,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -26126,7 +29457,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLE int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -26167,11 +29498,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO char *function_name_strval; int function_name_strlen; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -26181,49 +29512,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + call->object = _get_obj_zval_ptr_unused(TSRMLS_C); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CV != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -26257,7 +29590,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -26352,7 +29685,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -26396,7 +29729,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV( SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -26535,6 +29868,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEN return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26542,7 +30029,7 @@ static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); bitwise_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -26555,7 +30042,7 @@ static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); boolean_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -26568,7 +30055,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval **var_ptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -26614,7 +30101,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval **var_ptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -26660,7 +30147,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval **var_ptr, *retval; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -26702,7 +30189,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval **var_ptr, *retval; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -26745,7 +30232,7 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + z = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && @@ -26783,7 +30270,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -26813,7 +30300,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -26843,7 +30330,7 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int retval; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -26877,7 +30364,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int retval; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -26908,7 +30395,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS int retval; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -26938,13 +30425,16 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_CV == IS_TMP_VAR) { } } else if (!0) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (IS_CV == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -26966,6 +30456,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -26984,11 +30478,15 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_CV == IS_TMP_VAR) { @@ -27010,7 +30508,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER break; } - retval_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + retval_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); @@ -27049,7 +30547,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Can only throw objects"); @@ -27073,7 +30571,7 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARG USE_OPLINE zval *varptr; - varptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (varptr == &EG(uninitialized_zval)) { ALLOC_ZVAL(varptr); @@ -27107,7 +30605,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) { return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -27118,7 +30616,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL varptr = EX_T(opline->op1.var).var.ptr; PZVAL_UNLOCK_EX(varptr, &free_op1, 0); } else { - varptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); } if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || EX_T(opline->op1.var).var.fcall_returned_reference) && @@ -27133,7 +30631,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error(E_STRICT, "Only variables should be passed by reference"); } ALLOC_ZVAL(valptr); @@ -27156,7 +30654,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval *varptr; SAVE_OPLINE(); - varptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + varptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(varptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); @@ -27169,7 +30667,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZEND_VM_NEXT_OPCODE(); } - if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -27187,7 +30685,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS USE_OPLINE if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } SAVE_OPLINE(); @@ -27202,7 +30700,7 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC))); + ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC))); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -27218,7 +30716,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + obj = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { @@ -27279,7 +30777,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *result = &EX_T(opline->result.var).tmp_var; SAVE_OPLINE(); - expr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); @@ -27336,11 +30834,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL zend_op_array *new_op_array=NULL; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + inc_filename = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (inc_filename->type!=IS_STRING) { MAKE_STD_ZVAL(tmp_inc_filename); @@ -27428,8 +30926,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -27437,14 +30933,13 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -27454,15 +30949,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -27490,7 +30976,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS if ((IS_CV == IS_CV || IS_CV == IS_VAR) && (opline->extended_value & ZEND_FE_RESET_VARIABLE)) { - array_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + array_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) { MAKE_STD_ZVAL(array_ptr); ZVAL_NULL(array_ptr); @@ -27517,7 +31003,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS Z_ADDREF_P(array_ptr); } } else { - array_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* IS_TMP_VAR */ zval *tmp; @@ -27626,7 +31112,7 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); if (IS_CV != IS_UNUSED) { - zval *ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + zval *ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); @@ -27647,7 +31133,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); @@ -27672,7 +31158,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (i_zend_is_true(value)) { if (IS_CV == IS_VAR || IS_CV == IS_CV) { @@ -27706,7 +31192,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); if (!0) { @@ -27724,7 +31210,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR || IS_CV == IS_CV) { Z_ADDREF_P(value); @@ -27752,7 +31238,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC); @@ -27772,7 +31258,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27787,7 +31273,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27802,7 +31288,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27817,7 +31303,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27832,7 +31318,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27847,7 +31333,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27862,7 +31348,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27877,7 +31363,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27892,7 +31378,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27908,7 +31394,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); @@ -27925,7 +31411,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC)); @@ -27941,7 +31427,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC)); @@ -27957,7 +31443,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC)); @@ -27973,7 +31459,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OP SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC)); @@ -27988,7 +31474,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -28003,7 +31489,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -28018,7 +31504,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -28033,7 +31519,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -28045,10 +31531,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi { USE_OPLINE zend_free_op free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; zval *property = opline->op2.zv; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -28165,7 +31651,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -28178,14 +31664,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary zval *dim = opline->op2.zv; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: value = opline->op2.zv; - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -28307,7 +31793,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); property = opline->op2.zv; retval = &EX_T(opline->result.var).var.ptr; @@ -28411,7 +31897,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); property = opline->op2.zv; retval = &EX_T(opline->result.var).tmp_var; @@ -28513,7 +31999,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -28653,7 +32139,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_ { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -28679,9 +32165,18 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + if (IS_CV == IS_TMP_VAR || IS_CV == IS_CONST) { + zval *container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } else { + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -28694,7 +32189,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -28727,7 +32222,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -28749,7 +32244,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_IS TSRMLS_CC); @@ -28765,8 +32260,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -28778,7 +32273,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (IS_CONST == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); } @@ -28794,7 +32289,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -28812,6 +32307,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -28836,7 +32332,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(Z zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || @@ -28892,7 +32388,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -28931,7 +32427,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); property = opline->op2.zv; - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -28962,7 +32458,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || @@ -28998,7 +32494,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -29006,7 +32502,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); property = opline->op2.zv; - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -29039,7 +32535,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); property = opline->op2.zv; if (IS_CV == IS_CV) { @@ -29081,7 +32577,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); property_name = opline->op2.zv; if (0) { @@ -29090,7 +32586,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -29110,7 +32606,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -29122,7 +32618,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -29136,8 +32632,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CONST, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -29192,7 +32688,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); value = opline->op2.zv; - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CONST TSRMLS_CC)) { @@ -29243,9 +32739,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD char *function_name_strval; int function_name_strlen; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = opline->op2.zv; @@ -29257,49 +32753,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + call->object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CONST != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -29316,7 +32814,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); @@ -29331,7 +32829,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -29340,7 +32838,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -29447,7 +32945,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -29508,7 +33006,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -29606,7 +33104,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; if (IS_CV != IS_VAR || container) { @@ -29662,7 +33160,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO } else { HashTable *target_symbol_table; - zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -29734,7 +33232,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(i zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; @@ -29875,6 +33373,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -29882,8 +33534,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29897,8 +33549,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29912,8 +33564,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29927,8 +33579,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29942,8 +33594,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29957,8 +33609,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29972,8 +33624,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29987,8 +33639,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30002,8 +33654,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30018,8 +33670,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op2.var); @@ -30035,8 +33687,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30051,8 +33703,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30067,8 +33719,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30083,8 +33735,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30098,8 +33750,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30113,8 +33765,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30128,8 +33780,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30143,8 +33795,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30155,10 +33807,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina { USE_OPLINE zend_free_op free_op2, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -30275,7 +33927,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -30285,17 +33937,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o } return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -30418,8 +34070,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -30522,8 +34174,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -30626,9 +34278,18 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); - zval_dtor(free_op2.var); + + if (IS_CV == IS_TMP_VAR || IS_CV == IS_CONST) { + zval *container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } else { + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -30641,12 +34302,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -30674,12 +34335,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); zval_dtor(free_op2.var); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -30696,8 +34357,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30712,12 +34373,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -30725,8 +34386,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD if (IS_TMP_VAR == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); } zval_dtor(free_op2.var); @@ -30741,7 +34402,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -30751,7 +34412,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC); zval_dtor(free_op2.var); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -30759,6 +34420,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -30783,8 +34445,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -30829,7 +34491,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -30839,7 +34501,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL if (1) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -30877,8 +34539,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property); @@ -30909,8 +34571,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -30945,15 +34607,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property); @@ -30986,8 +34648,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -31028,8 +34690,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); @@ -31037,7 +34699,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -31057,19 +34719,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; - zval *property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -31078,14 +34740,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE } else { zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -31139,8 +34801,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_TMP_VAR TSRMLS_CC)) { @@ -31191,11 +34853,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ char *function_name_strval; int function_name_strlen; zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -31205,49 +34867,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + call->object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_TMP_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); @@ -31265,8 +34929,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -31281,7 +34945,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -31290,7 +34954,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -31311,7 +34975,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -31382,11 +35046,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -31480,8 +35144,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -31523,9 +35187,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -31664,6 +35328,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER(ZEND_O return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -31671,8 +35489,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31686,8 +35504,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31701,8 +35519,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31716,8 +35534,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31731,8 +35549,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31746,8 +35564,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31761,8 +35579,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31776,8 +35594,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31791,8 +35609,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31807,8 +35625,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -31824,8 +35642,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31840,8 +35658,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31856,8 +35674,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31872,8 +35690,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31887,8 +35705,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31902,8 +35720,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31917,8 +35735,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31932,8 +35750,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31944,10 +35762,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina { USE_OPLINE zend_free_op free_op2, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -32064,7 +35882,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -32074,17 +35892,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o } return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -32207,8 +36025,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -32311,8 +36129,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -32413,7 +36231,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -32553,7 +36371,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HA { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -32579,9 +36397,18 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + if (IS_CV == IS_TMP_VAR || IS_CV == IS_CONST) { + zval *container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } else { + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -32594,12 +36421,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -32627,12 +36454,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -32649,8 +36476,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -32665,12 +36492,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -32678,8 +36505,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD if (IS_VAR == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -32694,7 +36521,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -32704,7 +36531,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -32712,6 +36539,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -32736,8 +36564,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -32782,7 +36610,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -32792,7 +36620,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -32830,8 +36658,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -32862,8 +36690,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -32898,15 +36726,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -32939,8 +36767,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -32981,8 +36809,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -32990,7 +36818,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -33010,19 +36838,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; - zval *property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -33031,14 +36859,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE } else { zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_VAR, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -33092,8 +36920,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_VAR TSRMLS_CC)) { @@ -33146,7 +36974,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zval **value_ptr_ptr; SAVE_OPLINE(); - value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_VAR && value_ptr_ptr && @@ -33169,7 +36997,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) || (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); @@ -33198,11 +37026,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ char *function_name_strval; int function_name_strlen; zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -33212,49 +37040,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + call->object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -33272,8 +37102,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -33288,7 +37118,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -33297,7 +37127,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -33318,7 +37148,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -33404,7 +37234,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -33465,11 +37295,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -33563,8 +37393,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -33619,7 +37449,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE } else { HashTable *target_symbol_table; - zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -33691,9 +37521,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -33832,14 +37662,169 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER(ZEND_O return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; zval *property = NULL; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -33956,7 +37941,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -33969,14 +37954,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar zval *dim = NULL; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: value = NULL; - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -34098,7 +38083,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -34238,7 +38223,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -34258,7 +38243,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -34291,7 +38276,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -34314,8 +38299,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -34327,7 +38312,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP if (IS_UNUSED == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_R TSRMLS_CC); } @@ -34343,7 +38328,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -34355,7 +38340,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -34369,8 +38354,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_UNUSED, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -34424,7 +38409,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -34433,7 +38418,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -34540,7 +38525,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -34616,7 +38601,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC } else { HashTable *target_symbol_table; - zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -34677,6 +38662,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -34684,8 +38823,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34699,8 +38838,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34714,8 +38853,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34729,8 +38868,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34744,8 +38883,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34759,8 +38898,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34774,8 +38913,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34789,8 +38928,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34804,8 +38943,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34820,8 +38959,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); @@ -34837,8 +38976,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -34853,8 +38992,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -34869,8 +39008,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -34885,8 +39024,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -34900,8 +39039,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34915,8 +39054,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34930,8 +39069,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34945,8 +39084,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34957,10 +39096,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar { USE_OPLINE zend_free_op free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -35077,7 +39216,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -35087,17 +39226,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op } return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -35219,8 +39358,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -35323,8 +39462,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -35427,10 +39566,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + if (IS_CV == IS_TMP_VAR || IS_CV == IS_CONST) { + zval *container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + + } else { + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -35442,12 +39590,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -35475,12 +39623,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -35497,8 +39645,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); CHECK_EXCEPTION(); @@ -35513,12 +39661,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -35526,8 +39674,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); } @@ -35542,7 +39690,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -35552,7 +39700,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -35560,6 +39708,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -35584,8 +39733,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -35630,7 +39779,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -35640,7 +39789,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -35678,8 +39827,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -35710,8 +39859,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -35746,15 +39895,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -35787,8 +39936,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -35829,8 +39978,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -35838,7 +39987,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -35858,19 +40007,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zval *property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -35879,13 +40028,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER } else { zend_free_op free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CV, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -35939,8 +40088,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CV TSRMLS_CC)) { @@ -35992,7 +40141,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zval **value_ptr_ptr; SAVE_OPLINE(); - value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op2.var TSRMLS_CC); + value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_VAR && value_ptr_ptr && @@ -36015,7 +40164,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) || (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); @@ -36043,11 +40192,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H char *function_name_strval; int function_name_strlen; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -36057,49 +40206,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + call->object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CV != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -36116,8 +40267,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -36131,7 +40282,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -36140,7 +40291,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -36161,7 +40312,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -36232,11 +40383,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -36330,8 +40481,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -36373,9 +40524,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -36514,9 +40665,164 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OP return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + Z_ADDREF(EG(uninitialized_zval)); + AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } @@ -38548,16 +42854,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_R_SPEC_CV_VAR_HANDLER, ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER, ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER, @@ -40498,6 +44804,131 @@ void zend_init_opcodes_handlers(void) ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_YIELD_SPEC_CONST_CONST_HANDLER, + ZEND_YIELD_SPEC_CONST_TMP_HANDLER, + ZEND_YIELD_SPEC_CONST_VAR_HANDLER, + ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER, + ZEND_YIELD_SPEC_CONST_CV_HANDLER, + ZEND_YIELD_SPEC_TMP_CONST_HANDLER, + ZEND_YIELD_SPEC_TMP_TMP_HANDLER, + ZEND_YIELD_SPEC_TMP_VAR_HANDLER, + ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER, + ZEND_YIELD_SPEC_TMP_CV_HANDLER, + ZEND_YIELD_SPEC_VAR_CONST_HANDLER, + ZEND_YIELD_SPEC_VAR_TMP_HANDLER, + ZEND_YIELD_SPEC_VAR_VAR_HANDLER, + ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER, + ZEND_YIELD_SPEC_VAR_CV_HANDLER, + ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER, + ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER, + ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_YIELD_SPEC_UNUSED_CV_HANDLER, + ZEND_YIELD_SPEC_CV_CONST_HANDLER, + ZEND_YIELD_SPEC_CV_TMP_HANDLER, + ZEND_YIELD_SPEC_CV_VAR_HANDLER, + ZEND_YIELD_SPEC_CV_UNUSED_HANDLER, + ZEND_YIELD_SPEC_CV_CV_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; |