diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2012-11-30 13:39:23 +0400 | 
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2012-11-30 13:39:23 +0400 | 
| commit | 70f83f35d089d0cafae12ae231a38541f5c8e41c (patch) | |
| tree | 1dee0f4716d742a57558d59a9285392805b25a9b | |
| parent | 9f7e53fde8b0feac271230cbc6731e9de90f2a03 (diff) | |
| download | php-git-70f83f35d089d0cafae12ae231a38541f5c8e41c.tar.gz | |
. The VM stacks for passing function arguments and syntaticaly nested calls were merged into a single stack. The stack size needed for op_array execution is calculated at compile time and preallocated at once. As result all the stack push operatins don't require checks for stack overflow any more.
. Generators implementation was improved using the new VM stack. Now it's a bit more clear and faster.
| -rw-r--r-- | NEWS | 5 | ||||
| -rwxr-xr-x | UPGRADING | 21 | ||||
| -rw-r--r-- | Zend/zend.c | 4 | ||||
| -rw-r--r-- | Zend/zend_compile.c | 48 | ||||
| -rw-r--r-- | Zend/zend_compile.h | 18 | ||||
| -rw-r--r-- | Zend/zend_execute.c | 19 | ||||
| -rw-r--r-- | Zend/zend_execute.h | 84 | ||||
| -rw-r--r-- | Zend/zend_execute_API.c | 14 | ||||
| -rw-r--r-- | Zend/zend_extensions.h | 2 | ||||
| -rw-r--r-- | Zend/zend_generators.c | 304 | ||||
| -rw-r--r-- | Zend/zend_generators.h | 25 | ||||
| -rw-r--r-- | Zend/zend_globals.h | 2 | ||||
| -rw-r--r-- | Zend/zend_modules.h | 2 | ||||
| -rw-r--r-- | Zend/zend_opcode.c | 21 | ||||
| -rw-r--r-- | Zend/zend_ptr_stack.c | 17 | ||||
| -rw-r--r-- | Zend/zend_ptr_stack.h | 2 | ||||
| -rw-r--r-- | Zend/zend_vm_def.h | 294 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.h | 1799 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.skl | 102 | ||||
| -rw-r--r-- | Zend/zend_vm_opcodes.h | 1 | 
20 files changed, 1477 insertions, 1307 deletions
@@ -3,6 +3,11 @@ PHP                                                                        NEWS  ?? ??? 201?, PHP 5.5.0  - General improvements: +  . The VM stacks for passing function arguments and syntaticaly nested calls +    were merged into a single stack. The stack size needed for op_array +    execution is calculated at compile time and preallocated at once. As result +    all the stack push operatins don't require checks for stack overflow +    any more. (Dmitry)    . Added support for generators. (Nikita Popov)    . Add simplified password hashing API       (https://wiki.php.net/rfc/password_hash). (Anthony Ferrara) @@ -28,6 +28,27 @@ PHP 5.5 UPGRADE NOTES    zend_logo_guid() have been removed  - Removal of Logo GUIDs +- extensions can't override zend_execute() any more, they should override +  zend_execute_ex() instead. The EG(current_execute_data) is already +  initialized in zend_execute_ex(), so for compatibility extensions +  may need to use EG(current_execute_data)->prev_execute_data instead. +- removed EG(arg_types_stack), EX(fbc), EX(called_scope), EX(current_object) +- added op_array->nested_calls. It's calculated at compile time. +- added EX(call_slots). It is an array to store information about syntaticaly +  nested calls (e.g. foo(bar())). It's preallocated together with execute_data. +- added EX(call) - pointer to a current calling function. Actually an +  element of EX(call_slots) +- opcodes INIT_METHOD_CALL, ZEND_INIT_STATIC_METHOD_CALL, +  ZEND_INIT_FCALL_BY_NAME, ZEND_INIT_NS_FCALL_BY_NAME use result.num as +  an index in EX(call_slots) +- opcode ZEND_NEW uses extended_vallue as an index in EX(call_slots) +- opcoes ZEND_DO_FCALL and ZEND_DO_FCALL_BY_NAME use op2.num as +  an index in EX(call_slots) +- added op_array->used_stack. It's calculated at compile time and the +  corresponding stack space is preallocated together with execute_data. +  ZEND_SEND* and ZEND_DO_FCALL* don't need to check for stack overflow +  anymore. +  ========================================  2. New Features  ======================================== diff --git a/Zend/zend.c b/Zend/zend.c index 9ab879a2a4..fc6aed08cc 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -683,11 +683,11 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS  #if HAVE_DTRACE  /* build with dtrace support */  	zend_compile_file = dtrace_compile_file; -	zend_execute = dtrace_execute; +	zend_execute_ex = dtrace_execute_ex;  	zend_execute_internal = dtrace_execute_internal;  #else  	zend_compile_file = compile_file; -	zend_execute = execute; +	zend_execute_ex = execute_ex;  	zend_execute_internal = NULL;  #endif /* HAVE_SYS_SDT_H */  	zend_compile_string = compile_string; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index de77068db5..e768996272 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -179,6 +179,8 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */  	CG(context).literals_size = 0;  	CG(context).current_brk_cont = -1;  	CG(context).backpatch_count = 0; +	CG(context).nested_calls = 0; +	CG(context).used_stack = 0;  	CG(context).labels = NULL;  }  /* }}} */ @@ -1950,6 +1952,9 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace  	function_name->u.constant.value.str.val = lcname;  	zend_stack_push(&CG(function_call_stack), (void *) &function, sizeof(zend_function *)); +	if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) { +		CG(active_op_array)->nested_calls = CG(context).nested_calls + 1; +	}  	zend_do_extended_fcall_begin(TSRMLS_C);  	return 0;  } @@ -1988,11 +1993,13 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */  			GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);  		}  		last_op->opcode = ZEND_INIT_METHOD_CALL; -		SET_UNUSED(last_op->result); +		last_op->result_type = IS_UNUSED; +		last_op->result.num = CG(context).nested_calls;  		Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;  	} else {  		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);  		opline->opcode = ZEND_INIT_FCALL_BY_NAME; +		opline->result.num = CG(context).nested_calls;  		SET_UNUSED(opline->op1);  		if (left_bracket->op_type == IS_CONST) {  			opline->op2_type = IS_CONST; @@ -2004,6 +2011,9 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */  	}  	zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); +	if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) { +		CG(active_op_array)->nested_calls = CG(context).nested_calls; +	}  	zend_do_extended_fcall_begin(TSRMLS_C);  }  /* }}} */ @@ -2031,12 +2041,14 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML  		/* In run-time PHP will check for function with full name and  		   internal function with short name */  		opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME; +		opline->result.num = CG(context).nested_calls;  		SET_UNUSED(opline->op1);  		opline->op2_type = IS_CONST;  		opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);  		GET_CACHE_SLOT(opline->op2.constant);  	} else {  		opline->opcode = ZEND_INIT_FCALL_BY_NAME; +		opline->result.num = CG(context).nested_calls;  		SET_UNUSED(opline->op1);  		if (function_name->op_type == IS_CONST) {  			opline->op2_type = IS_CONST; @@ -2048,6 +2060,9 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML  	}  	zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); +	if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) { +		CG(active_op_array)->nested_calls = CG(context).nested_calls; +	}  	zend_do_extended_fcall_begin(TSRMLS_C);  }  /* }}} */ @@ -2395,6 +2410,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na  		opline->extended_value = class_node.EA	;  	}  	opline->opcode = ZEND_INIT_STATIC_METHOD_CALL; +	opline->result.num = CG(context).nested_calls;  	if (class_node.op_type == IS_CONST) {  		opline->op1_type = IS_CONST;  		opline->op1.constant = @@ -2416,6 +2432,9 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na  	}  	zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); +	if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) { +		CG(active_op_array)->nested_calls = CG(context).nested_calls; +	}  	zend_do_extended_fcall_begin(TSRMLS_C);  	return 1; /* Dynamic */  } @@ -2436,21 +2455,29 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode  		if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {  			opline->opcode = ZEND_DO_FCALL;  			SET_NODE(opline->op1, function_name); +			SET_UNUSED(opline->op2); +			opline->op2.num = CG(context).nested_calls;  			CALCULATE_LITERAL_HASH(opline->op1.constant);  			GET_CACHE_SLOT(opline->op1.constant);  		} else {  			opline->opcode = ZEND_DO_FCALL_BY_NAME;  			SET_UNUSED(opline->op1); +			SET_UNUSED(opline->op2); +			opline->op2.num = --CG(context).nested_calls;  		}  	}  	opline->result.var = get_temporary_variable(CG(active_op_array));  	opline->result_type = IS_VAR; -	GET_NODE(result, opline->result)	; -	SET_UNUSED(opline->op2); +	GET_NODE(result, opline->result);  	zend_stack_del_top(&CG(function_call_stack));  	opline->extended_value = Z_LVAL(argument_list->u.constant); + +	if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) { +		CG(active_op_array)->used_stack = CG(context).used_stack + 1; +	} +	CG(context).used_stack -= Z_LVAL(argument_list->u.constant);  }  /* }}} */ @@ -2558,6 +2585,10 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{  	SET_NODE(opline->op1, param);  	opline->op2.opline_num = offset;  	SET_UNUSED(opline->op2); + +	if (++CG(context).used_stack > CG(active_op_array)->used_stack) { +		CG(active_op_array)->used_stack = CG(context).used_stack; +	}  }  /* }}} */ @@ -5547,12 +5578,16 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*  	new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));  	opline = get_next_op(CG(active_op_array) TSRMLS_CC);  	opline->opcode = ZEND_NEW; +	opline->extended_value = CG(context).nested_calls;  	opline->result_type = IS_VAR;  	opline->result.var = get_temporary_variable(CG(active_op_array));  	SET_NODE(opline->op1, class_type);  	SET_UNUSED(opline->op2);  	zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *)); +	if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) { +		CG(active_op_array)->nested_calls = CG(context).nested_calls; +	}  }  /* }}} */ @@ -5765,6 +5800,13 @@ void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */  	opline->extended_value = 1;  	SET_UNUSED(opline->op2);  	GET_NODE(result, opline->result); + +	if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) { +		CG(active_op_array)->nested_calls = CG(context).nested_calls + 1; +	} +	if (CG(context).used_stack + 2 > CG(active_op_array)->used_stack) { +		CG(active_op_array)->used_stack = CG(context).used_stack + 2; +	}  }  /* }}} */ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index e46c1a39ce..def634175a 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -59,6 +59,8 @@ typedef struct _zend_compiler_context {  	int        literals_size;  	int        current_brk_cont;  	int        backpatch_count; +	int        nested_calls; +	int        used_stack;  	HashTable *labels;  } zend_compiler_context; @@ -279,6 +281,9 @@ struct _zend_op_array {  	zend_uint T; +	zend_uint nested_calls; +	zend_uint used_stack; +  	zend_brk_cont_element *brk_cont_array;  	int last_brk_cont; @@ -369,11 +374,17 @@ typedef struct _list_llist_element {  union _temp_variable; +typedef struct _call_slot { +	zend_function     *fbc; +	zval              *object; +	zend_class_entry  *called_scope; +	zend_bool          is_ctor_call; +	zend_bool          is_ctor_result_used; +} call_slot; +  struct _zend_execute_data {  	struct _zend_op *opline;  	zend_function_state function_state; -	zend_function *fbc; /* Function Being Called */ -	zend_class_entry *called_scope;  	zend_op_array *op_array;  	zval *object;  	union _temp_variable *Ts; @@ -386,8 +397,9 @@ struct _zend_execute_data {  	zend_class_entry *current_scope;  	zend_class_entry *current_called_scope;  	zval *current_this; -	zval *current_object;  	struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */ +	call_slot *call_slots; +	call_slot *call;  };  #define EX(element) execute_data.element diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 361afc6f13..5f04ba7465 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1570,25 +1570,6 @@ void zend_free_compiled_variables(zval ***CVs, int num) /* {{{ */  }  /* }}} */ -void** zend_copy_arguments(void **arguments_end) /* {{{ */ -{ -	int arguments_count = (int) (zend_uintptr_t) *arguments_end; -	size_t arguments_size = (arguments_count + 1) * sizeof(void **); -	void **arguments_start = arguments_end - arguments_count; -	void **copied_arguments_start = emalloc(arguments_size); -	void **copied_arguments_end = copied_arguments_start + arguments_count; -	int i; - -	memcpy(copied_arguments_start, arguments_start, arguments_size); - -	for (i = 0; i < arguments_count; i++) { -		Z_ADDREF_P((zval *) arguments_start[i]); -	} - -	return copied_arguments_end; -} -/* }}} */ -  /*   * Local variables:   * tab-width: 4 diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 4594eba9ef..fdd9f5697d 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -50,14 +50,14 @@ typedef union _temp_variable {  BEGIN_EXTERN_C()  struct _zend_fcall_info; -ZEND_API extern void (*zend_execute)(zend_op_array *op_array TSRMLS_DC); +ZEND_API extern void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);  ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC);  void init_executor(TSRMLS_D);  void shutdown_executor(TSRMLS_D);  void shutdown_destructors(TSRMLS_D);  zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC); -ZEND_API void execute(zend_op_array *op_array TSRMLS_DC); +ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC);  ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);  ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC);  ZEND_API int zend_is_true(zval *op); @@ -222,12 +222,6 @@ static zend_always_inline void **zend_vm_stack_top(TSRMLS_D)  static zend_always_inline void zend_vm_stack_push(void *ptr TSRMLS_DC)  { -	ZEND_VM_STACK_GROW_IF_NEEDED(1); -	*(EG(argument_stack)->top++) = ptr; -} - -static zend_always_inline void zend_vm_stack_push_nocheck(void *ptr TSRMLS_DC) -{  	*(EG(argument_stack)->top++) = ptr;  } @@ -235,11 +229,6 @@ static zend_always_inline void *zend_vm_stack_pop(TSRMLS_D)  {  	void *el = *(--EG(argument_stack)->top); -	if (UNEXPECTED(EG(argument_stack)->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)))) { -		zend_vm_stack p = EG(argument_stack); -		EG(argument_stack) = p->prev; -		efree(p); - 	}  	return el;  } @@ -272,6 +261,12 @@ static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)  	return ret;  } +static zend_always_inline void** zend_vm_stack_frame_base(zend_execute_data *ex) +{ +	return (void**)((char*)ex->call_slots + +		ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * ex->op_array->nested_calls); +} +  static zend_always_inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC)  {  	if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) { @@ -302,35 +297,6 @@ static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)  	}  } -static zend_always_inline void** zend_vm_stack_push_args(int count TSRMLS_DC) -{ - -	if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count)  || -		UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) { -		zend_vm_stack p = EG(argument_stack); - -		zend_vm_stack_extend(count + 1 TSRMLS_CC); - -		EG(argument_stack)->top += count; -		*(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count; -		while (count-- > 0) { -			void *data = *(--p->top); - -			if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) { -				zend_vm_stack r = p; - -				EG(argument_stack)->prev = p->prev; -				p = p->prev; -				efree(r); -			} -			*(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count) = data; -		} -		return EG(argument_stack)->top++; -	} -	*(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count; -	return EG(argument_stack)->top++; -} -  static zend_always_inline void zend_vm_stack_clear_multiple(TSRMLS_D)  {  	void **p = EG(argument_stack)->top - 1; @@ -344,9 +310,19 @@ static zend_always_inline void zend_vm_stack_clear_multiple(TSRMLS_D)  	zend_vm_stack_free_int(p TSRMLS_CC);  } -static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC) +static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex) +{ +	if (ex) { +		void **p = ex->function_state.arguments; +		return (int)(zend_uintptr_t) *p; +	} else { +		return 0;			 +	} +} + +static zend_always_inline zval** zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg)  { -	void **p = EG(current_execute_data)->prev_execute_data->function_state.arguments; +	void **p = ex->function_state.arguments;  	int arg_count = (int)(zend_uintptr_t) *p;  	if (UNEXPECTED(requested_arg > arg_count)) { @@ -355,25 +331,14 @@ static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_  	return (zval**)p - arg_count + requested_arg - 1;  } -static zend_always_inline void zend_arg_types_stack_2_pop(zend_ptr_stack *stack, zval **object, zend_function **fbc) +static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D)  { -	void *a, *b; - -	zend_ptr_stack_2_pop(stack, &a, &b); - -	*object = (zval *) a; -	*fbc = (zend_function *) b; +	return zend_vm_stack_get_args_count_ex(EG(current_execute_data)->prev_execute_data);  } -static zend_always_inline void zend_arg_types_stack_3_pop(zend_ptr_stack *stack, zend_class_entry **called_scope, zval **object, zend_function **fbc) +static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)  { -	void *a, *b, *c; - -	zend_ptr_stack_3_pop(stack, &a, &b, &c); - -	*called_scope = (zend_class_entry *) a; -	*object = (zval *) b; -	*fbc = (zend_function *) c; +	return zend_vm_stack_get_arg_ex(EG(current_execute_data)->prev_execute_data, requested_arg);  }  void execute_new_code(TSRMLS_D); @@ -436,7 +401,6 @@ ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);  void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC);  void zend_free_compiled_variables(zval ***CVs, int num); -void **zend_copy_arguments(void **arguments_end);  #define CACHED_PTR(num) \  	EG(active_op_array)->run_time_cache[(num)] diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 9787966f27..3df0ca2396 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -38,7 +38,7 @@  #include <sys/time.h>  #endif -ZEND_API void (*zend_execute)(zend_op_array *op_array TSRMLS_DC); +ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);  ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);  /* true globals */ @@ -137,7 +137,6 @@ void init_executor(TSRMLS_D) /* {{{ */  	INIT_ZVAL(EG(error_zval));  	EG(uninitialized_zval_ptr)=&EG(uninitialized_zval);  	EG(error_zval_ptr)=&EG(error_zval); -	zend_ptr_stack_init(&EG(arg_types_stack));  /* destroys stack frame, therefore makes core dumps worthless */  #if 0&&ZEND_DEBUG  	original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv); @@ -293,10 +292,10 @@ void shutdown_executor(TSRMLS_D) /* {{{ */  	} zend_end_try();  	zend_try { -		zend_vm_stack_destroy(TSRMLS_C); -  		zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC); +		zend_vm_stack_destroy(TSRMLS_C); +  		/* Destroy all op arrays */  		if (EG(full_tables_cleanup)) {  			zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function_full TSRMLS_CC); @@ -324,7 +323,6 @@ void shutdown_executor(TSRMLS_D) /* {{{ */  		zend_hash_destroy(&EG(included_files)); -		zend_ptr_stack_destroy(&EG(arg_types_stack));  		zend_stack_destroy(&EG(user_error_handlers_error_reporting));  		zend_ptr_stack_destroy(&EG(user_error_handlers));  		zend_ptr_stack_destroy(&EG(user_exception_handlers)); @@ -862,7 +860,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS  				    !ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {  					if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {  						/* hack to clean up the stack */ -						zend_vm_stack_push_nocheck((void *) (zend_uintptr_t)i TSRMLS_CC); +						zend_vm_stack_push((void *) (zend_uintptr_t)i TSRMLS_CC);  						zend_vm_stack_clear_multiple(TSRMLS_C);  					} @@ -899,11 +897,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS  			*param = **(fci->params[i]);  			INIT_PZVAL(param);  		} -		zend_vm_stack_push_nocheck(param TSRMLS_CC); +		zend_vm_stack_push(param TSRMLS_CC);  	}  	EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); -	zend_vm_stack_push_nocheck((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC); +	zend_vm_stack_push((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC);  	current_scope = EG(scope);  	EG(scope) = calling_scope; diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index 703e03c3f6..17804cb740 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -28,7 +28,7 @@  /* The first number is the engine version and the rest is the date.   * This way engine 2/3 API no. is always greater than engine 1 API no..   */ -#define ZEND_EXTENSION_API_NO	220121113 +#define ZEND_EXTENSION_API_NO	220121128  typedef struct _zend_extension_version_info {  	int zend_extension_api_no; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 1895305875..493e99dd0e 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -32,41 +32,7 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio  	if (generator->execute_data) {  		zend_execute_data *execute_data = generator->execute_data;  		zend_op_array *op_array = execute_data->op_array; - -		if (!finished_execution) { -			if (op_array->has_finally_block) { -				/* -1 required because we want the last run opcode, not the -				 * next to-be-run one. */ -				zend_uint op_num = execute_data->opline - op_array->opcodes - 1; -				zend_uint finally_op_num = 0; - -				/* Find next finally block */ -				int i; -				for (i = 0; i < op_array->last_try_catch; i++) { -					zend_try_catch_element *try_catch = &op_array->try_catch_array[i]; - -					if (op_num < try_catch->try_op) { -						break; -					} - -					if (op_num < try_catch->finally_op) { -						finally_op_num = try_catch->finally_op; -					} -				} - -				/* If a finally block was found we jump directly to it and -				 * resume the generator. Furthermore we abort this close call -				 * because the generator will already be closed somewhere in -				 * the resume. */ -				if (finally_op_num) { -					execute_data->opline = &op_array->opcodes[finally_op_num]; -					execute_data->fast_ret = NULL; -					generator->flags |= ZEND_GENERATOR_FORCED_CLOSE; -					zend_generator_resume(generator TSRMLS_CC); -					return; -				} -			} -		} +		void **stack_frame;  		if (!execute_data->symbol_table) {  			zend_free_compiled_variables(execute_data->CVs, op_array->last_var); @@ -78,10 +44,6 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio  			zval_ptr_dtor(&execute_data->current_this);  		} -		if (execute_data->object) { -			zval_ptr_dtor(&execute_data->object); -		} -  		/* If the generator is closed before it can finish execution (reach  		 * a return statement) we have to free loop variables manually, as  		 * we don't know whether the SWITCH_FREE / FREE opcodes have run */ @@ -120,32 +82,20 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio  		}  		/* Clear any backed up stack arguments */ -		if (generator->backed_up_stack) { -			zval **zvals = (zval **) generator->backed_up_stack; -			size_t zval_num = generator->backed_up_stack_size / sizeof(zval *); -			int i; - -			for (i = 0; i < zval_num; i++) { -				zval_ptr_dtor(&zvals[i]); +		if (generator->stack != EG(argument_stack)) { +			stack_frame = zend_vm_stack_frame_base(execute_data); +			while (generator->stack->top != stack_frame) { +				zval_ptr_dtor((zval**)stack_frame); +				stack_frame++;  			} - -			efree(generator->backed_up_stack);  		} -		if (generator->backed_up_arg_types_stack) { -			/* The arg types stack contains three elements per call: fbc, object -			 * and called_scope. Here we traverse the stack from top to bottom -			 * and dtor the object. */ -			int i = generator->backed_up_arg_types_stack_count / 3; -			while (i--) { -				zval *object = (zval *) generator->backed_up_arg_types_stack[3*i + 1]; -				if (object) { -					zval_ptr_dtor(&object); -				} +		while (execute_data->call >= execute_data->call_slots) { +			if (execute_data->call->object) { +				zval_ptr_dtor(&execute_data->call->object);  			} - -			efree(generator->backed_up_arg_types_stack); -		}  +			execute_data->call--; +		}  		/* We have added an additional stack frame in prev_execute_data, so we  		 * have to free it. It also contains the arguments passed to the @@ -162,11 +112,7 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio  				for (i = 0; i < arguments_count; ++i) {  					zval_ptr_dtor(arguments_start + i);  				} - -				efree(arguments_start);  			} - -			efree(prev_execute_data);  		}  		/* Free a clone of closure */ @@ -175,7 +121,11 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio  			efree(op_array);  		} -		efree(execute_data); +		efree(generator->stack); +		if (generator->stack == EG(argument_stack)) { +			/* abnormal exit for running generator */ +			EG(argument_stack) = NULL; +		}  		generator->execute_data = NULL;  	} @@ -210,27 +160,39 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator **  		zend_execute_data *execute_data = orig->execute_data;  		zend_op_array *op_array = execute_data->op_array;  		HashTable *symbol_table = execute_data->symbol_table; - -		/* Alloc separate execution context, as well as separate sections for -		 * compiled variables and temporary variables */ -		size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)); -		size_t CVs_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (symbol_table ? 1 : 2)); -		size_t Ts_size = ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T; -		size_t total_size = execute_data_size + CVs_size + Ts_size; - -		clone->execute_data = emalloc(total_size); - -		/* Copy the zend_execute_data struct */ -		memcpy(clone->execute_data, execute_data, execute_data_size); - -		/* Set the pointers to the memory segments for the compiled and -		 * temporary variables (which are located after the execute_data) */ -		clone->execute_data->CVs = (zval ***) ((char *) clone->execute_data + execute_data_size); -		clone->execute_data->Ts = (temp_variable *) ((char *) clone->execute_data->CVs + CVs_size); - -		/* Zero out the compiled variables section */ -		memset(clone->execute_data->CVs, 0, sizeof(zval **) * op_array->last_var); - +		zend_execute_data *current_execute_data; +		zend_op **opline_ptr; +		HashTable *current_symbol_table; +		zend_vm_stack current_stack; +		zval *current_this; +		void **stack_frame, **orig_stack_frame; + +		/* Create new execution context. We have to back up and restore +		 * EG(current_execute_data), EG(opline_ptr), EG(active_symbol_table) +		 * and EG(This) here because the function modifies or uses them  */ +		current_execute_data = EG(current_execute_data); +		EG(current_execute_data) = execute_data->prev_execute_data; +		opline_ptr = EG(opline_ptr); +		current_symbol_table = EG(active_symbol_table); +		EG(active_symbol_table) = execute_data->symbol_table; +		current_this = EG(This); +		EG(This) = NULL; +		current_stack = EG(argument_stack); +		clone->execute_data = zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC); +		clone->stack = EG(argument_stack); +		EG(argument_stack) = current_stack; +		EG(This) = current_this; +		EG(active_symbol_table) = current_symbol_table; +		EG(current_execute_data) = current_execute_data; +		EG(opline_ptr) = opline_ptr; + +		/* copy */ +		clone->execute_data->opline = execute_data->opline; +		clone->execute_data->function_state = execute_data->function_state; +		clone->execute_data->current_scope = execute_data->current_scope; +		clone->execute_data->current_called_scope = execute_data->current_called_scope; +		clone->execute_data->fast_ret = execute_data->fast_ret; +		  		if (!symbol_table) {  			int i; @@ -238,7 +200,7 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator **  			for (i = 0; i < op_array->last_var; i++) {  				if (execute_data->CVs[i]) {  					clone->execute_data->CVs[i] = (zval **) clone->execute_data->CVs + op_array->last_var + i; -					*clone->execute_data->CVs[i] = (zval *) orig->execute_data->CVs[op_array->last_var + i]; +					*clone->execute_data->CVs[i] = (zval *) execute_data->CVs[op_array->last_var + i];  					Z_ADDREF_PP(clone->execute_data->CVs[i]);  				}  			} @@ -259,8 +221,39 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator **  			}  		} +		/* Copy nested-calls stack */ +		if (execute_data->call) { +			clone->execute_data->call = clone->execute_data->call_slots + +				(execute_data->call - execute_data->call_slots); +		} else { +			clone->execute_data->call = NULL; +		} +		memcpy(clone->execute_data->call_slots, execute_data->call_slots, sizeof(call_slot) * op_array->nested_calls); +		if (clone->execute_data->call >= clone->execute_data->call_slots) { +			call_slot *call = clone->execute_data->call; +   +			while (call >= clone->execute_data->call_slots) { +				if (call->object) { +					Z_ADDREF_P(call->object); +				} +				call--; +			} +		} +  		/* Copy the temporary variables */ -		memcpy(clone->execute_data->Ts, orig->execute_data->Ts, Ts_size); +		memcpy(clone->execute_data->Ts, execute_data->Ts, sizeof(temp_variable) * op_array->T); + +		/* Copy arguments passed on stack */ +		stack_frame = zend_vm_stack_frame_base(clone->execute_data); +		orig_stack_frame = zend_vm_stack_frame_base(execute_data); +		clone->stack->top = stack_frame + (orig->stack->top - orig_stack_frame); +		if (clone->stack->top != stack_frame) { +			memcpy(stack_frame, orig_stack_frame, sizeof(zval*) * (orig->stack->top - orig_stack_frame)); +			while (clone->stack->top != stack_frame) { +				Z_ADDREF_PP((zval**)stack_frame); +				stack_frame++; +			} +		}  		/* Add references to loop variables */  		{ @@ -286,42 +279,6 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator **  			}  		} -		if (orig->backed_up_stack) { -			/* Copy backed up stack */ -			clone->backed_up_stack = emalloc(orig->backed_up_stack_size); -			memcpy(clone->backed_up_stack, orig->backed_up_stack, orig->backed_up_stack_size); - -			/* Add refs to stack variables */ -			{ -				zval **zvals = (zval **) orig->backed_up_stack; -				size_t zval_num = orig->backed_up_stack_size / sizeof(zval *); -				int i; - -				for (i = 0; i < zval_num; i++) { -					Z_ADDREF_P(zvals[i]); -				} -			} -		} - -		if (orig->backed_up_arg_types_stack) { -			size_t stack_size = orig->backed_up_arg_types_stack_count * sizeof(void *); - -			clone->backed_up_arg_types_stack = emalloc(stack_size); -			memcpy(clone->backed_up_arg_types_stack, orig->backed_up_arg_types_stack, stack_size); - -			/* We have to add refs to the objects in the arg types stack (the -			 * object is always the second element of a three-pack. */ -			{ -				int i, stack_frames = clone->backed_up_arg_types_stack_count / 3; -				for (i = 0; i < stack_frames; i++) { -					zval *object = (zval *) clone->backed_up_arg_types_stack[3*i + 1]; -					if (object) { -						Z_ADDREF_P(object); -					} -				} -			} -		} -  		/* Update the send_target to use the temporary variable with the same  		 * offset as the original generator, but in our temporary variable  		 * memory segment. */ @@ -334,24 +291,14 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator **  		}  		if (execute_data->current_this) { +			clone->execute_data->current_this = execute_data->current_this;  			Z_ADDREF_P(execute_data->current_this);  		}  		if (execute_data->object) { +			clone->execute_data->object = execute_data->object;  			Z_ADDREF_P(execute_data->object);  		} - -		/* Prev execute data contains an additional stack frame (for proper -		 * backtraces) which has to be copied. */ -		clone->execute_data->prev_execute_data = emalloc(sizeof(zend_execute_data)); -		memcpy(clone->execute_data->prev_execute_data, execute_data->prev_execute_data, sizeof(zend_execute_data)); - -		/* It also contains the arguments passed to the generator, which also -		 * have to be copied */ -		if (execute_data->prev_execute_data->function_state.arguments) { -			clone->execute_data->prev_execute_data->function_state.arguments -				= zend_copy_arguments(execute_data->prev_execute_data->function_state.arguments); -		}  	}  	/* The value and key are known not to be references, so simply add refs */ @@ -399,7 +346,9 @@ zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */  	zend_generator *generator;  	zend_execute_data *current_execute_data;  	zend_op **opline_ptr; +	HashTable *current_symbol_table;  	zend_execute_data *execute_data; +	zend_vm_stack current_stack = EG(argument_stack);  	/* Create a clone of closure, because it may be destroyed */  	if (op_array->fn_flags & ZEND_ACC_CLOSURE) { @@ -410,11 +359,14 @@ zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */  	}  	/* Create new execution context. We have to back up and restore -	 * EG(current_execute_data) and EG(opline_ptr) here because the function -	 * modifies it. */ +	 * EG(current_execute_data), EG(opline_ptr) and EG(active_symbol_table) +	 * here because the function modifies or uses them  */  	current_execute_data = EG(current_execute_data);  	opline_ptr = EG(opline_ptr); +	current_symbol_table = EG(active_symbol_table); +	EG(active_symbol_table) = NULL;  	execute_data = zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC); +	EG(active_symbol_table) = current_symbol_table;  	EG(current_execute_data) = current_execute_data;  	EG(opline_ptr) = opline_ptr; @@ -434,18 +386,8 @@ zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */  	/* Save execution context in generator object. */  	generator = (zend_generator *) zend_object_store_get_object(return_value TSRMLS_CC);  	generator->execute_data = execute_data; - -	/* We have to add another stack frame so the generator function shows -	 * up in backtraces and func_get_all() can access the function -	 * arguments. */ -	execute_data->prev_execute_data = emalloc(sizeof(zend_execute_data)); -	memset(execute_data->prev_execute_data, 0, sizeof(zend_execute_data)); -	execute_data->prev_execute_data->function_state.function = (zend_function *) op_array; -	if (EG(current_execute_data)) { -		execute_data->prev_execute_data->function_state.arguments = zend_copy_arguments(EG(current_execute_data)->function_state.arguments); -	} else { -		execute_data->prev_execute_data->function_state.arguments = NULL; -	} +	generator->stack = EG(argument_stack); +	EG(argument_stack) = current_stack;  	return return_value;  } @@ -487,28 +429,7 @@ void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */  		zval *original_This = EG(This);  		zend_class_entry *original_scope = EG(scope);  		zend_class_entry *original_called_scope = EG(called_scope); -		int original_arg_types_stack_count = EG(arg_types_stack).top; - -		/* Remember the current stack position so we can back up pushed args */ -		generator->original_stack_top = zend_vm_stack_top(TSRMLS_C); - -		/* If there is a backed up stack copy it to the VM stack */ -		if (generator->backed_up_stack) { -			void *stack = zend_vm_stack_alloc(generator->backed_up_stack_size TSRMLS_CC); -			memcpy(stack, generator->backed_up_stack, generator->backed_up_stack_size); -			efree(generator->backed_up_stack); -			generator->backed_up_stack = NULL; -		} - -		if (generator->backed_up_arg_types_stack) { -			zend_ptr_stack_push_from_memory( -				&EG(arg_types_stack), -				generator->backed_up_arg_types_stack_count, -				generator->backed_up_arg_types_stack -			); -			efree(generator->backed_up_arg_types_stack); -			generator->backed_up_arg_types_stack = NULL; -		} +		zend_vm_stack original_stack = EG(argument_stack);  		/* We (mis)use the return_value_ptr_ptr to provide the generator object  		 * to the executor, so YIELD will be able to set the yielded value */ @@ -522,6 +443,7 @@ void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */  		EG(This) = generator->execute_data->current_this;  		EG(scope) = generator->execute_data->current_scope;  		EG(called_scope) = generator->execute_data->current_called_scope; +		EG(argument_stack) = generator->stack;  		/* We want the backtrace to look as if the generator function was  		 * called from whatever method we are current running (e.g. next()). @@ -533,7 +455,7 @@ void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */  		/* Resume execution */  		generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING; -		execute_ex(generator->execute_data TSRMLS_CC); +		zend_execute_ex(generator->execute_data TSRMLS_CC);  		generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING;  		/* Restore executor globals */ @@ -545,27 +467,7 @@ void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */  		EG(This) = original_This;  		EG(scope) = original_scope;  		EG(called_scope) = original_called_scope; - -		/* The stack top before and after the execution differ, i.e. there are -		 * arguments pushed to the stack. */ -		if (generator->original_stack_top != zend_vm_stack_top(TSRMLS_C)) { -			generator->backed_up_stack_size = (zend_vm_stack_top(TSRMLS_C) - generator->original_stack_top) * sizeof(void *); -			generator->backed_up_stack = emalloc(generator->backed_up_stack_size); -			memcpy(generator->backed_up_stack, generator->original_stack_top, generator->backed_up_stack_size); -			zend_vm_stack_free(generator->original_stack_top TSRMLS_CC); -		} - -		if (original_arg_types_stack_count != EG(arg_types_stack).top) { -			generator->backed_up_arg_types_stack_count = -				EG(arg_types_stack).top - original_arg_types_stack_count; - -			generator->backed_up_arg_types_stack = emalloc(generator->backed_up_arg_types_stack_count * sizeof(void *)); -			zend_ptr_stack_pop_into_memory( -				&EG(arg_types_stack), -				generator->backed_up_arg_types_stack_count, -				generator->backed_up_arg_types_stack -			); -		} +		EG(argument_stack) = original_stack;  		/* If an exception was thrown in the generator we have to internally  		 * rethrow it in the parent scope. */ @@ -741,21 +643,11 @@ ZEND_METHOD(Generator, __wakeup)  /* get_iterator implementation */ -typedef struct _zend_generator_iterator { -	zend_object_iterator intern; - -	/* The generator object zval has to be stored, because the iterator is -	 * holding a ref to it, which has to be dtored. */ -	zval *object; -} zend_generator_iterator; -  static void zend_generator_iterator_dtor(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */  {  	zval *object = ((zend_generator_iterator *) iterator)->object;  	zval_ptr_dtor(&object); - -	efree(iterator);  }  /* }}} */ @@ -854,7 +746,7 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob  		return NULL;  	} -	iterator = emalloc(sizeof(zend_generator_iterator)); +	iterator = &generator->iterator;  	iterator->intern.funcs = &zend_generator_iterator_functions;  	iterator->intern.data = (void *) generator; diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 3dc3e6fecd..90f8160f71 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -25,25 +25,24 @@ BEGIN_EXTERN_C()  extern ZEND_API zend_class_entry *zend_ce_generator;  END_EXTERN_C() +typedef struct _zend_generator_iterator { +	zend_object_iterator intern; + +	/* The generator object zval has to be stored, because the iterator is +	 * holding a ref to it, which has to be dtored. */ +	zval *object; +} zend_generator_iterator; +  typedef struct _zend_generator {  	zend_object std; +	zend_generator_iterator iterator; +  	/* The suspended execution context. */  	zend_execute_data *execute_data; -	/* If the execution is suspended during a function call there may be -	 * arguments pushed to the stack, so it has to be backed up. */ -	void *backed_up_stack; -	size_t backed_up_stack_size; - -	/* For method calls PHP also pushes various type information on a second -	 * stack, which also needs to be backed up. */ -	void **backed_up_arg_types_stack; -	int backed_up_arg_types_stack_count; - -	/* The original stack top before resuming the generator. This is required -	 * for proper cleanup during exception handling. */ -	void **original_stack_top; +	/* The separate stack used by generator */ +	zend_vm_stack stack;  	/* Current value */  	zval *value; diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index e5aba0df67..6ad9768086 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -167,8 +167,6 @@ struct _zend_executor_globals {  	zval error_zval;  	zval *error_zval_ptr; -	zend_ptr_stack arg_types_stack; -  	/* symbol table cache */  	HashTable *symtable_cache[SYMTABLE_CACHE_SIZE];  	HashTable **symtable_cache_limit; diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index 442535bc68..bfea3e0d22 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -33,7 +33,7 @@  #define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module TSRMLS_DC  #define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module TSRMLS_CC -#define ZEND_MODULE_API_NO 20121113 +#define ZEND_MODULE_API_NO 20121128  #ifdef ZTS  #define USING_ZTS 1  #else diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 563c84301d..2fd8f529ef 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -70,6 +70,9 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz  	op_array->T = 0; +	op_array->nested_calls = 0; +	op_array->used_stack = 0; +  	op_array->function_name = NULL;  	op_array->filename = zend_get_compiled_filename(TSRMLS_C);  	op_array->doc_comment = NULL; @@ -541,6 +544,15 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num,  			/* generate a FAST_CALL to finaly block */  		    start_op = get_next_op_number(op_array); + +			if (op_array->opcodes[op_num].opcode == ZEND_YIELD) { +				/* Disable yield in finally block */ +				opline = get_next_op(op_array TSRMLS_CC); +				opline->opcode = ZEND_GENERATOR_FLAG; +				opline->extended_value = 1; +				SET_UNUSED(opline->op1); +				SET_UNUSED(opline->op2); +			}  			opline = get_next_op(op_array TSRMLS_CC);  			opline->opcode = ZEND_FAST_CALL;  			SET_UNUSED(opline->op1); @@ -567,6 +579,14 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num,  					opline->op1.opline_num = op_array->try_catch_array[i].finally_op;  				}  			} +			if (op_array->opcodes[op_num].opcode == ZEND_YIELD) { +				/* Re-enable yield */ +				opline = get_next_op(op_array TSRMLS_CC); +				opline->opcode = ZEND_GENERATOR_FLAG; +				opline->extended_value = 0; +				SET_UNUSED(opline->op1); +				SET_UNUSED(opline->op2); +			}  			/* Finish the sequence with original opcode */  			opline = get_next_op(op_array TSRMLS_CC); @@ -622,6 +642,7 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)  		switch (opline->opcode) {  			case ZEND_RETURN:  			case ZEND_RETURN_BY_REF: +			case ZEND_YIELD:  				zend_resolve_finally_call(op_array, i, (zend_uint)-1 TSRMLS_CC);  				break;  			case ZEND_BRK: diff --git a/Zend/zend_ptr_stack.c b/Zend/zend_ptr_stack.c index d178cc0184..9d82bba475 100644 --- a/Zend/zend_ptr_stack.c +++ b/Zend/zend_ptr_stack.c @@ -110,23 +110,6 @@ ZEND_API int zend_ptr_stack_num_elements(zend_ptr_stack *stack)  {  	return stack->top;  } - -ZEND_API void zend_ptr_stack_push_from_memory(zend_ptr_stack *stack, int count, void **pointers) -{ -	ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, count); - -	memcpy(stack->top_element, pointers, count * sizeof(void *)); -	stack->top_element += count; -	stack->top += count; -} - -ZEND_API void zend_ptr_stack_pop_into_memory(zend_ptr_stack *stack, int count, void **pointers) -{ -	memcpy(pointers, stack->top_element - count, count * sizeof(void *)); -	stack->top_element -= count; -	stack->top -= count; -} -  /*   * Local variables:   * tab-width: 4 diff --git a/Zend/zend_ptr_stack.h b/Zend/zend_ptr_stack.h index fe93e93b5a..9f6fc13161 100644 --- a/Zend/zend_ptr_stack.h +++ b/Zend/zend_ptr_stack.h @@ -41,8 +41,6 @@ ZEND_API void zend_ptr_stack_destroy(zend_ptr_stack *stack);  ZEND_API void zend_ptr_stack_apply(zend_ptr_stack *stack, void (*func)(void *));  ZEND_API void zend_ptr_stack_clean(zend_ptr_stack *stack, void (*func)(void *), zend_bool free_elements);  ZEND_API int zend_ptr_stack_num_elements(zend_ptr_stack *stack); -ZEND_API void zend_ptr_stack_push_from_memory(zend_ptr_stack *stack, int count, void **pointers); -ZEND_API void zend_ptr_stack_pop_into_memory(zend_ptr_stack *stack, int count, void **pointers);  END_EXTERN_C()  #define ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, count)		\ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 4ae4ca1267..966827d5b4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1161,7 +1161,7 @@ ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)  	USE_OPLINE  	ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, -		ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R); +		ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R);  }  ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) @@ -1283,7 +1283,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)  	SAVE_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))) {  		container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);  		if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {  			zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -1519,7 +1519,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV)  {  	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; @@ -1889,7 +1889,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)  			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); @@ -1925,8 +1924,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)  			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) { @@ -1939,8 +1938,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)  			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); @@ -1966,6 +1964,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)  	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); @@ -2000,11 +1999,11 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)  		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) { @@ -2054,7 +2053,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)  			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 == execute)) { +		} else if (EXPECTED(zend_execute_ex == execute_ex)) {  			if (EXPECTED(EG(exception) == NULL)) {  				ZEND_VM_ENTER();  			} @@ -2100,8 +2099,8 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)  	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) { @@ -2115,8 +2114,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)  		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); @@ -2463,9 +2461,9 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)  	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_OP2_ZVAL_PTR(BP_VAR_R); @@ -2477,49 +2475,51 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)  	function_name_strval = Z_STRVAL_P(function_name);  	function_name_strlen = Z_STRLEN_P(function_name); -	EX(object) = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); +	call->object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); -	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 (OP2_TYPE != 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, ((OP2_TYPE == 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, ((OP2_TYPE == 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 (OP2_TYPE == 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;  	FREE_OP2();  	FREE_OP1_IF_VAR(); @@ -2533,9 +2533,9 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS  	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 (OP1_TYPE == IS_CONST) {  		/* no function found. try a static method in class */ @@ -2549,24 +2549,24 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS  			}  			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 (OP1_TYPE == IS_CONST &&  	    OP2_TYPE == 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 (OP1_TYPE != IS_CONST &&  	           OP2_TYPE == 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 (OP2_TYPE != IS_UNUSED) {  		char *function_name_strval = NULL; @@ -2589,20 +2589,20 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS  		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, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); +				call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((OP2_TYPE == 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 (OP2_TYPE == 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 (OP1_TYPE == 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);  				}  			}  		} @@ -2616,29 +2616,31 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS  		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(); @@ -2648,19 +2650,21 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)  {  	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 (OP2_TYPE == 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->is_ctor_call = 0; +		EX(call) = call;  		/*CHECK_EXCEPTION();*/  		ZEND_VM_NEXT_OPCODE();  	} else { @@ -2680,28 +2684,32 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)  			} 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);  			FREE_OP2(); -			EX(object) = NULL; +			call->object = NULL; +			call->is_ctor_call = 0; +			EX(call) = call;  			CHECK_EXCEPTION();  			ZEND_VM_NEXT_OPCODE();  		} else if (OP2_TYPE != IS_CONST && OP2_TYPE != 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 (OP2_TYPE == IS_VAR && OP2_FREE && -			    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 {  				FREE_OP2();  			} +			call->is_ctor_call = 0; +			EX(call) = call;  			CHECK_EXCEPTION();  			ZEND_VM_NEXT_OPCODE();  		} else if (OP2_TYPE != IS_CONST && @@ -2732,41 +2740,43 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)  					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;  			FREE_OP2();  			CHECK_EXCEPTION();  			ZEND_VM_NEXT_OPCODE(); @@ -2781,31 +2791,32 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)  {  	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->is_ctor_call = 0; +	EX(call) = call;  	ZEND_VM_NEXT_OPCODE();  }  ZEND_VM_HANDLER(61, ZEND_DO_FCALL_BY_NAME, ANY, ANY)  { -	EX(function_state).function = EX(fbc); +	EX(function_state).function = EX(call)->fbc;  	ZEND_VM_DISPATCH_TO_HELPER(zend_do_fcall_common_helper);  } @@ -2814,8 +2825,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)  	USE_OPLINE  	zend_free_op free_op1;  	zval *fname = GET_OP1_ZVAL_PTR(BP_VAR_R); - -	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); @@ -2825,7 +2835,10 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)  	} 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->is_ctor_call = 0; +	EX(call) = call;  	FREE_OP1(); @@ -3052,7 +3065,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)  	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);  	}  	{ @@ -3113,7 +3126,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)  		if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {  			ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);  		} -	} 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)) {  		ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);  	} @@ -3139,7 +3152,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)  		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); @@ -3175,7 +3188,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)  		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)) {  		ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);  	} @@ -3194,7 +3207,7 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)  	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)) {  		ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);  	}  	SAVE_OPLINE(); @@ -3400,17 +3413,20 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)  		}  		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(); @@ -3829,8 +3845,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)  			EG(return_value_ptr_ptr) = NULL;  		} -		EX(current_object) = EX(object); -  		EX(function_state).function = (zend_function *) new_op_array;  		EX(object) = NULL; @@ -3838,14 +3852,13 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)  			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); @@ -5022,19 +5035,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)  	/* Figure out where the next stack frame (which maybe contains pushed  	 * arguments that have to be dtor'ed) starts */ -	if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) { -		/* The generator object is stored in return_value_ptr_ptr */ -		zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); - -		/* For generators the next stack frame is conveniently stored in the -		 * generator object. */ -		stack_frame = generator->original_stack_top; -	} else { -		/* In all other cases the next stack frame starts after the temporary -		 * variables section of the current execution context */ -		stack_frame = (void **) ((char *) EX_Ts() + -			ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T); -	} +	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. */ @@ -5056,21 +5057,23 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)  		}  	} -	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++) { @@ -5240,6 +5243,19 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)  	ZEND_VM_NEXT_OPCODE();  } +ZEND_VM_HANDLER(159, ZEND_GENERATOR_FLAG, ANY, ANY) +{ +	USE_OPLINE +	zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + +	if (opline->extended_value) { +		generator->flags |= ZEND_GENERATOR_FORCED_CLOSE; +	} else { +		generator->flags &= ~ZEND_GENERATOR_FORCED_CLOSE; +	} +	ZEND_VM_NEXT_OPCODE(); +} +  ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSED)  {  	USE_OPLINE diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 582962cfcf..921ece228b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -339,7 +339,50 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o  #define EX_Ts() EX(Ts) -zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) { +/*   + * Stack Frame Layout (the whole stack frame is allocated at once) + * ==================  + * + *                             +========================================+ + *                             | zend_execute_data                      |<---+ + *                             |     EX(function_state).arguments       |--+ | + *                             |  ...                                   |  | | + *                             | ARGUMENT [1]                           |  | | + *                             | ...                                    |  | | + *                             | ARGUMENT [ARGS_NUMBER]                 |  | | + *                             | ARGS_NUMBER                            |<-+ | + *                             +========================================+    | + *                                                                           | + *                             +========================================+    | + * EG(current_execute_data) -> | zend_execute_data                      |    | + *                             |     EX(prev_execute_data)              |----+ + *                             +----------------------------------------+ + *           EX(Ts) ---------> | EX(Ts)[0]                              | + *                             | ...                                    | + *                             | EX(Tx)[op_arrat->T]                    | + *                             +----------------------------------------+ + *           EX(CVs) --------> | EX(CVs)[0]                             |--+ + *                             | ...                                    |  | + *                             | EX(CVs)[op_array->last_var]            |  | + *                             +----------------------------------------+  | + *                             | Optional slot for CV[0] zval*          |<-+ + *                             | ...                                    | + *                             | ...  for CV [op_array->last_var] zval* | + *                             +----------------------------------------+ + *           EX(call_slots) -> | EX(call_slots)[0]                      | + *                             | ...                                    | + *                             | EX(call_slots)[op_array->nested_calls] | + *                             +----------------------------------------+ + * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0]                    | + *                             | ...                                    | + * zend_vm_stack_top --------> | ...                                    | + *                             | ...                                    | + *                             | ARGUMENTS STACK [op_array->used_stack] | + *                             +----------------------------------------+ + */ + +zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) +{  	zend_execute_data *execute_data;  	/* @@ -354,7 +397,9 @@ zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_arra  	size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));  	size_t CVs_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2));  	size_t Ts_size = ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T; -	size_t total_size = execute_data_size + CVs_size + Ts_size; +	size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls; +	size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * op_array->used_stack; +	size_t total_size = execute_data_size + Ts_size + CVs_size + call_slots_size + stack_size;  	/*  	 * Normally the execute_data is allocated on the VM stack (because it does @@ -366,23 +411,58 @@ zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_arra  	 * by replacing a pointer.  	 */  	if (op_array->fn_flags & ZEND_ACC_GENERATOR) { -		execute_data = emalloc(total_size); +		/* Prepend the regular stack frame with copy on prev_execute_data +		 * and passed arguments +		 */ +		int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data)); +		size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (args_count + 1); + +		total_size += args_size + execute_data_size; + +		EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(void*) - 1)) / sizeof(void*)); +		EG(argument_stack)->prev = NULL; +		execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size + execute_data_size); + +		/* copy prev_execute_data */ +		EX(prev_execute_data) = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size); +		memset(EX(prev_execute_data), 0, sizeof(zend_execute_data)); +		EX(prev_execute_data)->function_state.function = (zend_function*)op_array; +		EX(prev_execute_data)->function_state.arguments = (void**)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * args_count); + +		/* copy arguemnts */ +		*EX(prev_execute_data)->function_state.arguments = (void*)(zend_uintptr_t)args_count; +		if (args_count > 0) { +			zval **arg_src = (zval**)zend_vm_stack_get_arg_ex(EG(current_execute_data), 1); +			zval **arg_dst = (zval**)zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1); +			int i; + +			for (i = 0; i < args_count; i++) { +				arg_dst[i] = arg_src[i]; +				Z_ADDREF_P(arg_dst[i]); +			} +		}  	} else {  		execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC); +		EX(prev_execute_data) = EG(current_execute_data);  	} -	EX(CVs) = (zval ***) ((char *) execute_data + execute_data_size); +	EX(Ts) = (temp_variable *) ((char *) execute_data + execute_data_size); + +	EX(CVs) = (zval ***) ((char *) EX(Ts) + Ts_size);  	memset(EX(CVs), 0, sizeof(zval **) * op_array->last_var); -	EX(Ts) = (temp_variable *) ((char *) EX(CVs) + CVs_size); +	EX(call_slots) = (call_slot*)((char *) EX(CVs) + CVs_size); + + +	EX(op_array) = op_array; + +	EG(argument_stack)->top = zend_vm_stack_frame_base(execute_data); -	EX(fbc) = NULL; -	EX(called_scope) = NULL;  	EX(object) = NULL; +	EX(current_this) = 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); +	EX(call) = NULL;  	EG(current_execute_data) = execute_data;  	EX(nested) = nested; @@ -452,12 +532,12 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC)  	zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");  } -ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) +ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC)  {  	if (EG(exception)) {  		return;  	}  -	execute_ex(zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); +	zend_execute_ex(zend_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) @@ -509,7 +589,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); @@ -545,8 +624,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) { @@ -559,8 +638,7 @@ 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); @@ -586,6 +664,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); @@ -620,11 +699,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) { @@ -674,7 +753,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR  			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 == execute)) { +		} else if (EXPECTED(zend_execute_ex == execute_ex)) {  			if (EXPECTED(EG(exception) == NULL)) {  				ZEND_VM_ENTER();  			} @@ -720,8 +799,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) { @@ -735,8 +814,7 @@ 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); @@ -780,7 +858,7 @@ static int ZEND_FASTCALL  ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS  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);  } @@ -860,17 +938,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(); @@ -1075,19 +1156,7 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER  	/* Figure out where the next stack frame (which maybe contains pushed  	 * arguments that have to be dtor'ed) starts */ -	if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) { -		/* The generator object is stored in return_value_ptr_ptr */ -		zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); - -		/* For generators the next stack frame is conveniently stored in the -		 * generator object. */ -		stack_frame = generator->original_stack_top; -	} else { -		/* In all other cases the next stack frame starts after the temporary -		 * variables section of the current execution context */ -		stack_frame = (void **) ((char *) EX_Ts() + -			ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T); -	} +	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. */ @@ -1109,21 +1178,23 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER  		}  	} -	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++) { @@ -1213,6 +1284,19 @@ static int ZEND_FASTCALL  ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS  	}  } +static int ZEND_FASTCALL  ZEND_GENERATOR_FLAG_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +	USE_OPLINE +	zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + +	if (opline->extended_value) { +		generator->flags |= ZEND_GENERATOR_FORCED_CLOSE; +	} else { +		generator->flags &= ~ZEND_GENERATOR_FORCED_CLOSE; +	} +	ZEND_VM_NEXT_OPCODE(); +} +  static int ZEND_FASTCALL  ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)  {  	USE_OPLINE @@ -1291,19 +1375,21 @@ 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->is_ctor_call = 0; +		EX(call) = call;  		/*CHECK_EXCEPTION();*/  		ZEND_VM_NEXT_OPCODE();  	} else { @@ -1323,28 +1409,32 @@ 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->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 && @@ -1375,41 +1465,43 @@ 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(); @@ -1424,25 +1516,26 @@ 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->is_ctor_call = 0; +	EX(call) = call;  	ZEND_VM_NEXT_OPCODE();  } @@ -1599,19 +1692,21 @@ 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->is_ctor_call = 0; +		EX(call) = call;  		/*CHECK_EXCEPTION();*/  		ZEND_VM_NEXT_OPCODE();  	} else { @@ -1631,28 +1726,32 @@ 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->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 && @@ -1683,41 +1782,43 @@ 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(); @@ -1769,19 +1870,21 @@ 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->is_ctor_call = 0; +		EX(call) = call;  		/*CHECK_EXCEPTION();*/  		ZEND_VM_NEXT_OPCODE();  	} else { @@ -1801,28 +1904,32 @@ 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->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 && @@ -1853,41 +1960,43 @@ 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(); @@ -1974,19 +2083,21 @@ 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->is_ctor_call = 0; +		EX(call) = call;  		/*CHECK_EXCEPTION();*/  		ZEND_VM_NEXT_OPCODE();  	} else { @@ -2006,28 +2117,32 @@ 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->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 && @@ -2058,41 +2173,43 @@ 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(); @@ -2328,8 +2445,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); @@ -2339,7 +2455,10 @@ 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->is_ctor_call = 0; +	EX(call) = call;  	return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);  } @@ -2498,7 +2617,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);  	}  	{ @@ -2754,8 +2873,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; @@ -2763,14 +2880,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); @@ -3497,7 +3613,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) @@ -3569,9 +3685,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 */ @@ -3585,24 +3701,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; @@ -3625,20 +3741,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);  				}  			}  		} @@ -3652,29 +3768,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(); @@ -4555,9 +4673,9 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_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_CONST == IS_CONST) {  		/* no function found. try a static method in class */ @@ -4571,24 +4689,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; @@ -4611,20 +4729,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);  				}  			}  		} @@ -4638,29 +4756,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(); @@ -5365,7 +5485,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) @@ -5413,9 +5533,9 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_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_CONST == IS_CONST) {  		/* no function found. try a static method in class */ @@ -5429,24 +5549,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; @@ -5469,20 +5589,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);  				}  			}  		} @@ -5496,29 +5616,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(); @@ -6109,7 +6231,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) @@ -6127,9 +6249,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 */ @@ -6143,24 +6265,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; @@ -6183,20 +6305,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);  				}  			}  		} @@ -6210,29 +6332,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(); @@ -6982,9 +7106,9 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN  	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 */ @@ -6998,24 +7122,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; @@ -7038,20 +7162,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);  				}  			}  		} @@ -7065,29 +7189,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(); @@ -7813,7 +7939,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);  	}  	{ @@ -8070,8 +8196,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; @@ -8079,14 +8203,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); @@ -8865,7 +8988,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) @@ -8985,9 +9108,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; @@ -8999,49 +9122,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, EX_Ts(), &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(); @@ -9838,9 +9963,9 @@ 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); @@ -9852,49 +9977,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, EX_Ts(), &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); @@ -10601,7 +10728,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) @@ -10696,9 +10823,9 @@ 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); @@ -10710,49 +10837,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, EX_Ts(), &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);}; @@ -11345,7 +11474,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) @@ -12130,9 +12259,9 @@ 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); @@ -12144,49 +12273,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, EX_Ts(), &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(); @@ -13067,7 +13198,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);  	} @@ -13093,7 +13224,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); @@ -13129,7 +13260,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);  	} @@ -13148,7 +13279,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(); @@ -13400,8 +13531,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; @@ -13409,14 +13538,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); @@ -14772,7 +14900,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) @@ -14894,7 +15022,7 @@ 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))) { +	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, EX_Ts(), &free_op1 TSRMLS_CC);  		if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {  			zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -15130,7 +15258,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; @@ -15378,9 +15506,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; @@ -15392,49 +15520,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, EX_Ts(), &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);}; @@ -15447,9 +15577,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 */ @@ -15463,24 +15593,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; @@ -15503,20 +15633,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);  				}  			}  		} @@ -15530,29 +15660,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(); @@ -17227,7 +17359,7 @@ 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))) { +	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, EX_Ts(), &free_op1 TSRMLS_CC);  		if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {  			zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -17463,7 +17595,7 @@ 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; @@ -17712,9 +17844,9 @@ 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); @@ -17726,49 +17858,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, EX_Ts(), &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);}; @@ -17782,9 +17916,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 */ @@ -17798,24 +17932,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; @@ -17838,20 +17972,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);  				}  			}  		} @@ -17865,29 +17999,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(); @@ -19352,7 +19488,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) @@ -19474,7 +19610,7 @@ 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))) { +	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, EX_Ts(), &free_op1 TSRMLS_CC);  		if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {  			zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -19710,7 +19846,7 @@ 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; @@ -20014,9 +20150,9 @@ 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); @@ -20028,49 +20164,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, EX_Ts(), &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);}; @@ -20084,9 +20222,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 */ @@ -20100,24 +20238,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; @@ -20140,20 +20278,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);  				}  			}  		} @@ -20167,29 +20305,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(); @@ -21333,7 +21473,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) @@ -21410,7 +21550,7 @@ 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))) { +	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, EX_Ts(), &free_op1 TSRMLS_CC);  		if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {  			zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -21517,9 +21657,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 */ @@ -21533,24 +21673,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; @@ -21573,20 +21713,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);  				}  			}  		} @@ -21600,29 +21740,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(); @@ -22913,7 +23055,7 @@ 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))) { +	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, EX_Ts(), &free_op1 TSRMLS_CC);  		if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {  			zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -23149,7 +23291,7 @@ 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; @@ -23450,9 +23592,9 @@ 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); @@ -23464,49 +23606,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, EX_Ts(), &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);}; @@ -23519,9 +23663,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 */ @@ -23535,24 +23679,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; @@ -23575,20 +23719,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);  				}  			}  		} @@ -23602,29 +23746,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(); @@ -24915,7 +25061,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; @@ -25073,9 +25219,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; @@ -25087,49 +25233,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(); @@ -26320,7 +26468,7 @@ 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; @@ -26477,9 +26625,9 @@ 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); @@ -26491,49 +26639,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); @@ -27633,7 +27783,7 @@ 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; @@ -27790,9 +27940,9 @@ 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); @@ -27804,49 +27954,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);}; @@ -29369,7 +29521,7 @@ 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; @@ -29525,9 +29677,9 @@ 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); @@ -29539,49 +29691,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(); @@ -30630,7 +30784,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);  	} @@ -30656,7 +30810,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); @@ -30692,7 +30846,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);  	} @@ -30710,7 +30864,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(); @@ -30951,8 +31105,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; @@ -30960,14 +31112,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); @@ -32176,7 +32327,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) @@ -32297,7 +32448,7 @@ 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))) { +	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(EX_CVs(), 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"); @@ -32530,7 +32681,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; @@ -32775,9 +32926,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; @@ -32789,49 +32940,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(EX_CVs(), 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(); @@ -34407,7 +34560,7 @@ 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))) { +	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(EX_CVs(), 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"); @@ -34640,7 +34793,7 @@ 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; @@ -34886,9 +35039,9 @@ 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); @@ -34900,49 +35053,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(EX_CVs(), 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); @@ -36402,7 +36557,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) @@ -36523,7 +36678,7 @@ 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))) { +	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(EX_CVs(), 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"); @@ -36756,7 +36911,7 @@ 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; @@ -37056,9 +37211,9 @@ 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); @@ -37070,49 +37225,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(EX_CVs(), 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);}; @@ -38251,7 +38408,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) @@ -38327,7 +38484,7 @@ 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))) { +	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(EX_CVs(), 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"); @@ -39689,7 +39846,7 @@ 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))) { +	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(EX_CVs(), 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"); @@ -39922,7 +40079,7 @@ 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; @@ -40219,9 +40376,9 @@ 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); @@ -40233,49 +40390,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(EX_CVs(), 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(); @@ -44828,31 +44987,31 @@ 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_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_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_NULL_HANDLER, -  	ZEND_NULL_HANDLER, -  	ZEND_NULL_HANDLER, -  	ZEND_NULL_HANDLER, -  	ZEND_NULL_HANDLER, -  	ZEND_NULL_HANDLER, -  	ZEND_NULL_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER, +  	ZEND_GENERATOR_FLAG_SPEC_HANDLER,    	ZEND_YIELD_SPEC_CONST_CONST_HANDLER,    	ZEND_YIELD_SPEC_CONST_TMP_HANDLER,    	ZEND_YIELD_SPEC_CONST_VAR_HANDLER, diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index e2d5dd12b0..85d3dfb04f 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -1,6 +1,49 @@  {%DEFINES%} -zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) { +/*   + * Stack Frame Layout (the whole stack frame is allocated at once) + * ==================  + * + *                             +========================================+ + *                             | zend_execute_data                      |<---+ + *                             |     EX(function_state).arguments       |--+ | + *                             |  ...                                   |  | | + *                             | ARGUMENT [1]                           |  | | + *                             | ...                                    |  | | + *                             | ARGUMENT [ARGS_NUMBER]                 |  | | + *                             | ARGS_NUMBER                            |<-+ | + *                             +========================================+    | + *                                                                           | + *                             +========================================+    | + * EG(current_execute_data) -> | zend_execute_data                      |    | + *                             |     EX(prev_execute_data)              |----+ + *                             +----------------------------------------+ + *           EX(Ts) ---------> | EX(Ts)[0]                              | + *                             | ...                                    | + *                             | EX(Tx)[op_arrat->T]                    | + *                             +----------------------------------------+ + *           EX(CVs) --------> | EX(CVs)[0]                             |--+ + *                             | ...                                    |  | + *                             | EX(CVs)[op_array->last_var]            |  | + *                             +----------------------------------------+  | + *                             | Optional slot for CV[0] zval*          |<-+ + *                             | ...                                    | + *                             | ...  for CV [op_array->last_var] zval* | + *                             +----------------------------------------+ + *           EX(call_slots) -> | EX(call_slots)[0]                      | + *                             | ...                                    | + *                             | EX(call_slots)[op_array->nested_calls] | + *                             +----------------------------------------+ + * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0]                    | + *                             | ...                                    | + * zend_vm_stack_top --------> | ...                                    | + *                             | ...                                    | + *                             | ARGUMENTS STACK [op_array->used_stack] | + *                             +----------------------------------------+ + */ + +zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) +{  	zend_execute_data *execute_data;  	/* @@ -15,7 +58,9 @@ zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_arra  	size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));  	size_t CVs_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2));  	size_t Ts_size = ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T; -	size_t total_size = execute_data_size + CVs_size + Ts_size; +	size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls; +	size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * op_array->used_stack; +	size_t total_size = execute_data_size + Ts_size + CVs_size + call_slots_size + stack_size;  	/*  	 * Normally the execute_data is allocated on the VM stack (because it does @@ -27,23 +72,58 @@ zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_arra  	 * by replacing a pointer.  	 */  	if (op_array->fn_flags & ZEND_ACC_GENERATOR) { -		execute_data = emalloc(total_size); +		/* Prepend the regular stack frame with copy on prev_execute_data +		 * and passed arguments +		 */ +		int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data)); +		size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (args_count + 1); + +		total_size += args_size + execute_data_size; + +		EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(void*) - 1)) / sizeof(void*)); +		EG(argument_stack)->prev = NULL; +		execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size + execute_data_size); + +		/* copy prev_execute_data */ +		EX(prev_execute_data) = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size); +		memset(EX(prev_execute_data), 0, sizeof(zend_execute_data)); +		EX(prev_execute_data)->function_state.function = (zend_function*)op_array; +		EX(prev_execute_data)->function_state.arguments = (void**)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * args_count); + +		/* copy arguemnts */ +		*EX(prev_execute_data)->function_state.arguments = (void*)(zend_uintptr_t)args_count; +		if (args_count > 0) { +			zval **arg_src = (zval**)zend_vm_stack_get_arg_ex(EG(current_execute_data), 1); +			zval **arg_dst = (zval**)zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1); +			int i; + +			for (i = 0; i < args_count; i++) { +				arg_dst[i] = arg_src[i]; +				Z_ADDREF_P(arg_dst[i]); +			} +		}  	} else {  		execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC); +		EX(prev_execute_data) = EG(current_execute_data);  	} -	EX(CVs) = (zval ***) ((char *) execute_data + execute_data_size); +	EX(Ts) = (temp_variable *) ((char *) execute_data + execute_data_size); + +	EX(CVs) = (zval ***) ((char *) EX(Ts) + Ts_size);  	memset(EX(CVs), 0, sizeof(zval **) * op_array->last_var); -	EX(Ts) = (temp_variable *) ((char *) EX(CVs) + CVs_size); +	EX(call_slots) = (call_slot*)((char *) EX(CVs) + CVs_size); + + +	EX(op_array) = op_array; + +	EG(argument_stack)->top = zend_vm_stack_frame_base(execute_data); -	EX(fbc) = NULL; -	EX(called_scope) = NULL;  	EX(object) = NULL; +	EX(current_this) = 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); +	EX(call) = NULL;  	EG(current_execute_data) = execute_data;  	EX(nested) = nested; @@ -103,12 +183,12 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)  	zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");  } -ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) +ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC)  {  	if (EG(exception)) {  		return;  	}  -	{%EXECUTOR_NAME%}_ex(zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); +	zend_{%EXECUTOR_NAME%}_ex(zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC);  }  {%EXTERNAL_EXECUTOR%} diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 52f6cde59e..fcf7960b8e 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -159,6 +159,7 @@  #define ZEND_SEPARATE                        156  #define ZEND_QM_ASSIGN_VAR                   157  #define ZEND_JMP_SET_VAR                     158 +#define ZEND_GENERATOR_FLAG                  159  #define ZEND_YIELD                           160  #define ZEND_GENERATOR_RETURN                161  #define ZEND_FAST_CALL                       162  | 
