return FAILURE;
}
- ALLOC_ZVAL(new_zval);
- *new_zval = **fci->params[i];
- zval_copy_ctor(new_zval);
- Z_SET_REFCOUNT_P(new_zval, 1);
- Z_DELREF_PP(fci->params[i]);
- *fci->params[i] = new_zval;
+ ZVAL_NEW_REF(arg, arg);
}
- Z_ADDREF_PP(fci->params[i]);
- Z_SET_ISREF_PP(fci->params[i]);
- param = *fci->params[i];
- } else if (PZVAL_IS_REF(*fci->params[i]) &&
- /* don't separate references for __call */
- (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
- ALLOC_ZVAL(param);
- *param = **(fci->params[i]);
- INIT_PZVAL(param);
- zval_copy_ctor(param);
- } else if (*fci->params[i] != &EG(uninitialized_zval)) {
- Z_ADDREF_PP(fci->params[i]);
- param = *fci->params[i];
+ Z_ADDREF_P(arg);
} else {
- ALLOC_ZVAL(param);
- *param = **(fci->params[i]);
- INIT_PZVAL(param);
+ if (Z_ISREF_P(arg) &&
+ !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
+ /* don't separate references for __call */
+ arg = Z_REFVAL_P(arg);
+ }
+ if (Z_OPT_REFCOUNTED_P(arg)) {
+ Z_ADDREF_P(arg);
+ }
}
- zend_vm_stack_push(param TSRMLS_CC);
+ param = ZEND_CALL_ARG(call, i+1);
+ ZVAL_COPY_VALUE(param, arg);
}
- EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
- zend_vm_stack_push((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC);
-
- current_scope = EG(scope);
EG(scope) = calling_scope;
-
- current_this = EG(This);
-
- current_called_scope = EG(called_scope);
- if (called_scope) {
- EG(called_scope) = called_scope;
- } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) {
- EG(called_scope) = NULL;
+ if (func->common.fn_flags & ZEND_ACC_STATIC) {
+ fci->object = NULL;
}
+ Z_OBJ(call->This) = fci->object;
- if (fci->object_ptr) {
- if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
- EG(This) = NULL;
- } else {
- EG(This) = fci->object_ptr;
-
- if (!PZVAL_IS_REF(EG(This))) {
- Z_ADDREF_P(EG(This)); /* For $this pointer */
- } else {
- zval *this_ptr;
-
- ALLOC_ZVAL(this_ptr);
- *this_ptr = *EG(This);
- INIT_PZVAL(this_ptr);
- zval_copy_ctor(this_ptr);
- EG(This) = this_ptr;
- }
- }
- } else {
- EG(This) = NULL;
+ if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
+ ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT);
+ GC_REFCOUNT((zend_object*)func->op_array.prototype)++;
+ ZEND_ADD_CALL_FLAG(call, ZEND_CALL_CLOSURE);
}
- EX(prev_execute_data) = EG(current_execute_data);
- EG(current_execute_data) = &execute_data;
-
- if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
- calling_symbol_table = EG(active_symbol_table);
- EG(scope) = EX(function_state).function->common.scope;
- if (fci->symbol_table) {
- EG(active_symbol_table) = fci->symbol_table;
- } else {
- EG(active_symbol_table) = NULL;
- }
-
- original_return_value = EG(return_value_ptr_ptr);
- original_op_array = EG(active_op_array);
- EG(return_value_ptr_ptr) = fci->retval_ptr_ptr;
- EG(active_op_array) = (zend_op_array *) EX(function_state).function;
- original_opline_ptr = EG(opline_ptr);
+ /* PHP-7 doesn't support symbol_table substitution for functions */
+ ZEND_ASSERT(fci->symbol_table == NULL);
- if (EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
- *fci->retval_ptr_ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC);
- } else {
+ if (func->type == ZEND_USER_FUNCTION) {
+ int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
+ EG(scope) = func->common.scope;
+ call->symbol_table = fci->symbol_table;
+ if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) {
+ const zend_op *current_opline_before_exception = EG(opline_before_exception);
+
- zend_execute(EG(active_op_array) TSRMLS_CC);
+ zend_init_execute_data(call, &func->op_array, fci->retval);
+ zend_execute_ex(call);
+ EG(opline_before_exception) = current_opline_before_exception;
+ } else {
+ zend_generator_create_zval(call, &func->op_array, fci->retval);
}
-
- if (!fci->symbol_table && EG(active_symbol_table)) {
- zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
+ if (call_via_handler) {
+ /* We must re-initialize function again */
+ fci_cache->initialized = 0;
}
- EG(active_symbol_table) = calling_symbol_table;
- EG(active_op_array) = original_op_array;
- EG(return_value_ptr_ptr)=original_return_value;
- EG(opline_ptr) = original_opline_ptr;
- } else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
- int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
- ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
- if (EX(function_state).function->common.scope) {
- EG(scope) = EX(function_state).function->common.scope;
+ } else if (func->type == ZEND_INTERNAL_FUNCTION) {
+ int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
+ ZVAL_NULL(fci->retval);
+ if (func->common.scope) {
+ EG(scope) = func->common.scope;
}
+ call->prev_execute_data = EG(current_execute_data);
+ call->return_value = NULL; /* this is not a constructor call */
+ EG(current_execute_data) = call;
if (EXPECTED(zend_execute_internal == NULL)) {
/* saves one function call if zend_execute_internal is not used */
- EX(function_state).function->internal_function.handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
+ func->internal_function.handler(call, fci->retval);
} else {
- zend_execute_internal(&execute_data, fci, 1 TSRMLS_CC);
+ zend_execute_internal(call, fci->retval);
}
+ EG(current_execute_data) = call->prev_execute_data;
+ zend_vm_stack_free_args(call);
+
/* We shouldn't fix bad extensions here,
because it can break proper ones (Bug #34045)
if (!EX(function_state).function->common.return_reference)