. Update the MIME type list from the one shipped by Apache HTTPD. (Adam)
- Core:
+ . Improved __call() and __callStatic() magic method handling. Now they are
+ called in a stackless way using ZEND_CALL_TRAMPOLINE opcode, without
+ additional stack frame. (Laruence, Dmitry)
. Fixed weird operators behavior. Division by zero now emits warning and
returns +/-INF, modulo by zero and intdid() throws an exception, shifts
by negative offset throw exceptions. Compile-time evaluation of division
)
[1] => Array
- (
- [file] => %s
- [line] => 13
- [function] => ThrowException
- [class] => myClass
- [type] => ::
- [args] => Array
- (
- )
-
- )
-
- [2] => Array
(
[file] => %s
[line] => 21
)
[1] => Array
- (
- [file] => %s
- [line] => 17
- [function] => foo
- [class] => myClass
- [type] => ->
- [args] => Array
- (
- )
-
- )
-
- [2] => Array
(
[file] => %s
[line] => 28
--- /dev/null
+--TEST--
+Bug #68412 (Infinite recursion with __call can make the program crash/segfault)
+--FILE--
+<?php
+class C {
+ public function __call($x, $y) {
+ global $z;
+ $z->bar();
+ }
+}
+$z = new C;
+function main() {
+ global $z;
+ $z->foo();
+}
+main();
+?>
+--EXPECTF--
+Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %sbug68412.php on line %d
}
/* }}} */
+static void zend_init_call_trampoline_op(void) /* {{{ */
+{
+ memset(&EG(call_trampoline_op), 0, sizeof(EG(call_trampoline_op)));
+ EG(call_trampoline_op).opcode = ZEND_CALL_TRAMPOLINE;
+ EG(call_trampoline_op).op1_type = IS_UNUSED;
+ EG(call_trampoline_op).op2_type = IS_UNUSED;
+ EG(call_trampoline_op).result_type = IS_UNUSED;
+ ZEND_VM_SET_OPCODE_HANDLER(&EG(call_trampoline_op));
+}
+/* }}} */
+
#ifdef ZTS
static void function_copy_ctor(zval *zv)
{
zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE);
zend_init_rsrc_plist();
zend_init_exception_op();
+ zend_init_call_trampoline_op();
+ memset(&executor_globals->trampoline, 0, sizeof(zend_op_array));
executor_globals->lambda_count = 0;
ZVAL_UNDEF(&executor_globals->user_error_handler);
ZVAL_UNDEF(&executor_globals->user_exception_handler);
#ifndef ZTS
zend_init_rsrc_plist();
zend_init_exception_op();
+ zend_init_call_trampoline_op();
#endif
zend_ini_startup();
get_function_via_handler:
if (fcc->object && fcc->calling_scope == ce_org) {
if (strict_class && ce_org->__call) {
- fcc->function_handler = emalloc(sizeof(zend_internal_function));
- fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
- fcc->function_handler->internal_function.module = (ce_org->type == ZEND_INTERNAL_CLASS) ? ce_org->info.internal.module : NULL;
- fcc->function_handler->internal_function.handler = zend_std_call_user_call;
- fcc->function_handler->internal_function.arg_info = NULL;
- fcc->function_handler->internal_function.num_args = 0;
- fcc->function_handler->internal_function.scope = ce_org;
- fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
- fcc->function_handler->internal_function.function_name = mname;
- zend_string_addref(mname);
+ fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
call_via_handler = 1;
retval = 1;
} else if (fcc->object->handlers->get_method) {
if (strict_class &&
(!fcc->function_handler->common.scope ||
!instanceof_function(ce_org, fcc->function_handler->common.scope))) {
- if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
+ if (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
zend_string_release(fcc->function_handler->common.function_name);
}
- efree(fcc->function_handler);
+ zend_free_trampoline(fcc->function_handler);
}
} else {
retval = 1;
- call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+ call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
}
}
}
}
if (fcc->function_handler) {
retval = 1;
- call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+ call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
if (call_via_handler && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) &&
instanceof_function(Z_OBJCE(EG(current_execute_data)->This), fcc->calling_scope)) {
fcc->object = Z_OBJ(EG(current_execute_data)->This);
ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error);
if (fcc == &fcc_local &&
fcc->function_handler &&
- ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
- (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
+ ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
zend_string_release(fcc->function_handler->common.function_name);
}
- efree(fcc->function_handler);
+ zend_free_trampoline(fcc->function_handler);
}
return ret;
ret = zend_is_callable_check_func(check_flags, method, fcc, strict_class, error);
if (fcc == &fcc_local &&
fcc->function_handler &&
- ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
- (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
+ ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
zend_string_release(fcc->function_handler->common.function_name);
}
- efree(fcc->function_handler);
+ zend_free_trampoline(fcc->function_handler);
}
return ret;
add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
}
if (fcc.function_handler &&
- ((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
- (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
+ ((fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
zend_string_release(fcc.function_handler->common.function_name);
}
- efree(fcc.function_handler);
+ zend_free_trampoline(fcc.function_handler);
}
return 1;
}
&& Z_OBJ_HT_P(klass)->get_method != NULL
&& (func = Z_OBJ_HT_P(klass)->get_method(&Z_OBJ_P(klass), method_name, NULL)) != NULL
) {
- if (func->type == ZEND_INTERNAL_FUNCTION
- && (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0
- ) {
+ if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
/* Returns true to the fake Closure's __invoke */
RETVAL_BOOL(func->common.scope == zend_ce_closure
&& zend_string_equals_literal(method_name, ZEND_INVOKE_FUNC_NAME));
zend_string_release(lcname);
zend_string_release(func->common.function_name);
- efree(func);
+ zend_free_trampoline(func);
return;
}
zend_string_release(lcname);
if (prev_call &&
prev_call->func &&
!ZEND_USER_CODE(prev_call->func->common.type) &&
- !(prev_call->func->common.type == ZEND_INTERNAL_FUNCTION &&
- (prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
+ !(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
break;
}
if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
#define ZEND_ACC_CLOSURE 0x100000
#define ZEND_ACC_GENERATOR 0x800000
-/* function flag for internal user call handlers __call, __callstatic */
-#define ZEND_ACC_CALL_VIA_HANDLER 0x200000
+/* call through user function trampoline. e.g. __call, __callstatic */
+#define ZEND_ACC_CALL_VIA_TRAMPOLINE 0x200000
+
+/* call through internal function handler. e.g. Closure::invoke() */
+#define ZEND_ACC_CALL_VIA_HANDLER ZEND_ACC_CALL_VIA_TRAMPOLINE
/* disable inline caching */
#define ZEND_ACC_NEVER_CACHE 0x400000
Z_ADDREF_P(arg);
} else {
if (Z_ISREF_P(arg) &&
- (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
+ !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
/* don't separate references for __call */
arg = Z_REFVAL_P(arg);
}
}
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 (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
} else {
zend_generator_create_zval(call, &func->op_array, fci->retval);
}
+ if (call_via_handler) {
+ /* We must re-initialize function again */
+ fci_cache->initialized = 0;
+ }
} else if (func->type == ZEND_INTERNAL_FUNCTION) {
- int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+ 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;
#include "zend_modules.h"
#include "zend_float.h"
#include "zend_multibyte.h"
+#include "zend_multiply.h"
#include "zend_arena.h"
/* Define ZTS if you want a thread-safe Zend */
XPFPA_CW_DATATYPE saved_fpu_cw;
#endif
+ zend_function trampoline;
+ zend_op call_trampoline_op;
+
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
}
/* }}} */
-ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
-{
- zend_internal_function *func = (zend_internal_function *)EX(func);
- zval method_name, method_args;
- zval method_result;
- zend_class_entry *ce = Z_OBJCE_P(getThis());
-
- array_init_size(&method_args, ZEND_NUM_ARGS());
-
- if (UNEXPECTED(zend_copy_parameters_array(ZEND_NUM_ARGS(), &method_args) == FAILURE)) {
- zval_dtor(&method_args);
- zend_error(E_EXCEPTION | E_ERROR, "Cannot get arguments for __call");
- RETURN_FALSE;
- }
-
- ZVAL_STR(&method_name, func->function_name); /* no dup - it's a copy */
-
- /* __call handler is called with two arguments:
- method name
- array of method parameters
-
- */
- zend_call_method_with_2_params(getThis(), ce, &ce->__call, ZEND_CALL_FUNC_NAME, &method_result, &method_name, &method_args);
-
- if (Z_TYPE(method_result) != IS_UNDEF) {
- RETVAL_ZVAL_FAST(&method_result);
- zval_ptr_dtor(&method_result);
- }
-
- /* now destruct all auxiliaries */
- zval_ptr_dtor(&method_args);
- zval_ptr_dtor(&method_name);
-
- /* destruct the function also, then - we have allocated it in get_method */
- efree_size(func, sizeof(zend_internal_function));
-#if ZEND_DEBUG
- execute_data->func = NULL;
-#endif
-}
-/* }}} */
-
/* Ensures that we're allowed to call a private method.
* Returns the function address that should be called, or NULL
* if no such function exists.
}
/* }}} */
-static inline union _zend_function *zend_get_user_call_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
+ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend_string *method_name, int is_static) /* {{{ */
{
- zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
- call_user_call->type = ZEND_INTERNAL_FUNCTION;
- call_user_call->module = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL;
- call_user_call->handler = zend_std_call_user_call;
- call_user_call->arg_info = NULL;
- call_user_call->num_args = 0;
- call_user_call->scope = ce;
- call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
+ zend_op_array *func;
+ zend_function *fbc = is_static ? ce->__callstatic : ce->__call;
+
+ ZEND_ASSERT(fbc);
+
+ if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
+ func = &EG(trampoline).op_array;
+ } else {
+ func = ecalloc(1, sizeof(zend_op_array));
+ }
+
+ func->type = ZEND_USER_FUNCTION;
+ func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC;
+ if (is_static) {
+ func->fn_flags |= ZEND_ACC_STATIC;
+ }
+ func->this_var = -1;
+ func->opcodes = &EG(call_trampoline_op);
+
+ func->scope = ce;
+ func->prototype = fbc;
+ func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : STR_EMPTY_ALLOC();
+ func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
+ func->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0;
+
//??? keep compatibility for "\0" characters
//??? see: Zend/tests/bug46238.phpt
if (UNEXPECTED(strlen(method_name->val) != method_name->len)) {
- call_user_call->function_name = zend_string_init(method_name->val, strlen(method_name->val), 0);
+ func->function_name = zend_string_init(method_name->val, strlen(method_name->val), 0);
} else {
- call_user_call->function_name = zend_string_copy(method_name);
+ func->function_name = zend_string_copy(method_name);
}
- return (union _zend_function *)call_user_call;
+ return (zend_function*)func;
+}
+/* }}} */
+
+static zend_always_inline zend_function *zend_get_user_call_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
+{
+ return zend_get_call_trampoline_func(ce, method_name, 0);
}
/* }}} */
}
/* }}} */
-ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
-{
- zend_internal_function *func = (zend_internal_function *)EX(func);
- zval method_name, method_args;
- zval method_result;
- zend_class_entry *ce = EG(scope);
-
- array_init_size(&method_args, ZEND_NUM_ARGS());
-
- if (UNEXPECTED(zend_copy_parameters_array(ZEND_NUM_ARGS(), &method_args) == FAILURE)) {
- zval_dtor(&method_args);
- zend_error(E_EXCEPTION | E_ERROR, "Cannot get arguments for " ZEND_CALLSTATIC_FUNC_NAME);
- RETURN_FALSE;
- }
-
- ZVAL_STR(&method_name, func->function_name); /* no dup - it's a copy */
-
- /* __callStatic handler is called with two arguments:
- method name
- array of method parameters
- */
- zend_call_method_with_2_params(NULL, ce, &ce->__callstatic, ZEND_CALLSTATIC_FUNC_NAME, &method_result, &method_name, &method_args);
-
- if (Z_TYPE(method_result) != IS_UNDEF) {
- RETVAL_ZVAL_FAST(&method_result);
- zval_ptr_dtor(&method_result);
- }
-
- /* now destruct all auxiliaries */
- zval_ptr_dtor(&method_args);
- zval_ptr_dtor(&method_name);
-
- /* destruct the function also, then - we have allocated it in get_method */
- efree_size(func, sizeof(zend_internal_function));
-#if ZEND_DEBUG
- execute_data->func = NULL;
-#endif
-}
-/* }}} */
-
-static inline union _zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
+static zend_always_inline zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
{
- zend_internal_function *callstatic_user_call = emalloc(sizeof(zend_internal_function));
- callstatic_user_call->type = ZEND_INTERNAL_FUNCTION;
- callstatic_user_call->module = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL;
- callstatic_user_call->handler = zend_std_callstatic_user_call;
- callstatic_user_call->arg_info = NULL;
- callstatic_user_call->num_args = 0;
- callstatic_user_call->scope = ce;
- callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER;
- //??? keep compatibility for "\0" characters
- //??? see: Zend/tests/bug46238.phpt
- if (UNEXPECTED(strlen(method_name->val) != method_name->len)) {
- callstatic_user_call->function_name = zend_string_init(method_name->val, strlen(method_name->val), 0);
- } else {
- callstatic_user_call->function_name = zend_string_copy(method_name);
- }
-
- return (zend_function *)callstatic_user_call;
+ return zend_get_call_trampoline_func(ce, method_name, 1);
}
/* }}} */
-/* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */
-
ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */
{
zend_function *fbc = NULL;
if (ce->__call &&
Z_OBJ(EG(current_execute_data)->This) &&
instanceof_function(Z_OBJCE(EG(current_execute_data)->This), ce)) {
- return zend_get_user_call_function(ce, function_name);
+ /* Call the top-level defined __call().
+ * see: tests/classes/__call_004.phpt */
+
+ zend_class_entry *call_ce = Z_OBJCE(EG(current_execute_data)->This);
+
+ while (!call_ce->__call) {
+ call_ce = call_ce->parent;
+ }
+ return zend_get_user_call_function(call_ce, function_name);
} else if (ce->__callstatic) {
return zend_get_user_callstatic_function(ce, function_name);
} else {
#ifndef ZEND_OBJECT_HANDLERS_H
#define ZEND_OBJECT_HANDLERS_H
-union _zend_function;
struct _zend_property_info;
#define ZEND_WRONG_PROPERTY_INFO \
ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_info_name);
-ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS);
+ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend_string *method_name, int is_static);
+
+#define zend_free_trampoline(func) do { \
+ if ((func) == &EG(trampoline)) { \
+ EG(trampoline).common.function_name = NULL; \
+ } else { \
+ efree(func); \
+ } \
+ } while (0)
+
END_EXTERN_C()
#endif
}
if (OP2_TYPE == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
}
if (OP2_TYPE == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (OP1_TYPE == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
Z_ADDREF_P(arg);
} else{
if (Z_ISREF_P(arg) &&
- (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
+ !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
/* don't separate references for __call */
arg = Z_REFVAL_P(arg);
}
Z_ADDREF_P(arg);
} else {
if (Z_ISREF_P(arg) &&
- (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
+ !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
/* don't separate references for __call */
arg = Z_REFVAL_P(arg);
}
}
OBJ_RELEASE(Z_OBJ(call->This));
}
- if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
+ if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
zend_string_release(call->func->common.function_name);
- efree(call->func);
+ zend_free_trampoline(call->func);
}
EX(call) = call->prev_execute_data;
ZEND_VM_NEXT_OPCODE();
}
+ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
+{
+ zend_array *args;
+ zend_function *fbc = EX(func);
+ zend_object *object = Z_OBJ(EX(This));
+ zval *ret = EX(return_value);
+ zend_call_kind call_kind = EX_CALL_KIND();
+ zend_class_entry *scope = EX(called_scope);
+ uint32_t num_args = EX_NUM_ARGS();
+ zend_execute_data *call;
+ USE_OPLINE
+
+ args = emalloc(sizeof(zend_array));
+ zend_hash_init(args, num_args, NULL, ZVAL_PTR_DTOR, 0);
+ if (num_args) {
+ zval *p = ZEND_CALL_ARG(execute_data, 1);
+ zval *end = p + num_args;
+
+ zend_hash_real_init(args, 1);
+ ZEND_HASH_FILL_PACKED(args) {
+ do {
+ ZEND_HASH_FILL_ADD(p);
+ p++;
+ } while (p != end);
+ } ZEND_HASH_FILL_END();
+ }
+
+ SAVE_OPLINE();
+ call = execute_data;
+ execute_data = EG(current_execute_data) = EX(prev_execute_data);
+ zend_vm_stack_free_call_frame(call);
+ call = zend_vm_stack_push_call_frame(call_kind, fbc->common.prototype, 2, scope, object, execute_data);
+
+ ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name);
+ ZVAL_ARR(ZEND_CALL_ARG(call, 2), args);
+ zend_free_trampoline(fbc);
+ fbc = call->func;
+
+ if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
+
+ ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_GENERATOR));
+
+ /* This must be already set on invokation of trampoline function */
+ /*EG(scope) = fbc->common.scope;*/
+ call->symbol_table = NULL;
+ i_init_func_execute_data(call, &fbc->op_array,
+ ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
+
+ if (EXPECTED(zend_execute_ex == execute_ex)) {
+ ZEND_VM_ENTER();
+ } else {
+ ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
+ zend_execute_ex(call);
+ }
+ } else {
+ zval retval;
+
+ ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
+
+ EG(scope) = object ? NULL : fbc->common.scope;
+ EG(current_execute_data) = call;
+
+ if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+ uint32_t i;
+ uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
+ zval *p = ZEND_CALL_ARG(call, 1);
+
+ EG(current_execute_data) = call;
+
+ for (i = 0; i < num_args; ++i) {
+ zend_verify_internal_arg_type(fbc, i + 1, p);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ EG(current_execute_data) = call->prev_execute_data;
+ zend_vm_stack_free_args(call);
+ zend_vm_stack_free_call_frame(call);
+ if (ret) {
+ ZVAL_UNDEF(ret);
+ }
+ ZEND_VM_C_GOTO(call_trampoline_end);
+ }
+ p++;
+ }
+ }
+
+ if (ret == NULL) {
+ ZVAL_NULL(&retval);
+ ret = &retval;
+ }
+ Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
+
+ if (!zend_execute_internal) {
+ /* saves one function call if zend_execute_internal is not used */
+ fbc->internal_function.handler(call, ret);
+ } else {
+ zend_execute_internal(call, ret);
+ }
+
+#if ZEND_DEBUG
+ ZEND_ASSERT(
+ !call->func ||
+ !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
+ zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
+#endif
+
+ EG(current_execute_data) = call->prev_execute_data;
+
+ zend_vm_stack_free_args(call);
+ zend_vm_stack_free_call_frame(call);
+
+ if (ret == &retval) {
+ zval_ptr_dtor(ret);
+ }
+ }
+
+ZEND_VM_C_LABEL(call_trampoline_end):
+ execute_data = EG(current_execute_data);
+
+ if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_kind & ZEND_CALL_TOP)) {
+ ZEND_VM_RETURN();
+ }
+
+ LOAD_OPLINE();
+
+ if (object) {
+ OBJ_RELEASE(object);
+ }
+ EG(scope) = EX(func)->op_array.scope;
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_throw_exception_internal(NULL);
+ if (RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(EX_VAR(opline->result.var));
+ }
+ HANDLE_EXCEPTION_LEAVE();
+ }
+
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+}
Z_ADDREF_P(arg);
} else{
if (Z_ISREF_P(arg) &&
- (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
+ !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
/* don't separate references for __call */
arg = Z_REFVAL_P(arg);
}
}
OBJ_RELEASE(Z_OBJ(call->This));
}
- if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
+ if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
zend_string_release(call->func->common.function_name);
- efree(call->func);
+ zend_free_trampoline(call->func);
}
EX(call) = call->prev_execute_data;
ZEND_VM_NEXT_OPCODE();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_array *args;
+ zend_function *fbc = EX(func);
+ zend_object *object = Z_OBJ(EX(This));
+ zval *ret = EX(return_value);
+ zend_call_kind call_kind = EX_CALL_KIND();
+ zend_class_entry *scope = EX(called_scope);
+ uint32_t num_args = EX_NUM_ARGS();
+ zend_execute_data *call;
+ USE_OPLINE
+
+ args = emalloc(sizeof(zend_array));
+ zend_hash_init(args, num_args, NULL, ZVAL_PTR_DTOR, 0);
+ if (num_args) {
+ zval *p = ZEND_CALL_ARG(execute_data, 1);
+ zval *end = p + num_args;
+
+ zend_hash_real_init(args, 1);
+ ZEND_HASH_FILL_PACKED(args) {
+ do {
+ ZEND_HASH_FILL_ADD(p);
+ p++;
+ } while (p != end);
+ } ZEND_HASH_FILL_END();
+ }
+
+ SAVE_OPLINE();
+ call = execute_data;
+ execute_data = EG(current_execute_data) = EX(prev_execute_data);
+ zend_vm_stack_free_call_frame(call);
+ call = zend_vm_stack_push_call_frame(call_kind, fbc->common.prototype, 2, scope, object, execute_data);
+
+ ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name);
+ ZVAL_ARR(ZEND_CALL_ARG(call, 2), args);
+ zend_free_trampoline(fbc);
+ fbc = call->func;
+
+ if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
+
+ ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_GENERATOR));
+
+ /* This must be already set on invokation of trampoline function */
+ /*EG(scope) = fbc->common.scope;*/
+ call->symbol_table = NULL;
+ i_init_func_execute_data(call, &fbc->op_array,
+ ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
+
+ if (EXPECTED(zend_execute_ex == execute_ex)) {
+ ZEND_VM_ENTER();
+ } else {
+ ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
+ zend_execute_ex(call);
+ }
+ } else {
+ zval retval;
+
+ ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
+
+ EG(scope) = object ? NULL : fbc->common.scope;
+ EG(current_execute_data) = call;
+
+ if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+ uint32_t i;
+ uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
+ zval *p = ZEND_CALL_ARG(call, 1);
+
+ EG(current_execute_data) = call;
+
+ for (i = 0; i < num_args; ++i) {
+ zend_verify_internal_arg_type(fbc, i + 1, p);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ EG(current_execute_data) = call->prev_execute_data;
+ zend_vm_stack_free_args(call);
+ zend_vm_stack_free_call_frame(call);
+ if (ret) {
+ ZVAL_UNDEF(ret);
+ }
+ goto call_trampoline_end;
+ }
+ p++;
+ }
+ }
+
+ if (ret == NULL) {
+ ZVAL_NULL(&retval);
+ ret = &retval;
+ }
+ Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
+
+ if (!zend_execute_internal) {
+ /* saves one function call if zend_execute_internal is not used */
+ fbc->internal_function.handler(call, ret);
+ } else {
+ zend_execute_internal(call, ret);
+ }
+
+#if ZEND_DEBUG
+ ZEND_ASSERT(
+ !call->func ||
+ !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
+ zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
+#endif
+
+ EG(current_execute_data) = call->prev_execute_data;
+
+ zend_vm_stack_free_args(call);
+ zend_vm_stack_free_call_frame(call);
+
+ if (ret == &retval) {
+ zval_ptr_dtor(ret);
+ }
+ }
+
+call_trampoline_end:
+ execute_data = EG(current_execute_data);
+
+ if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_kind & ZEND_CALL_TOP)) {
+ ZEND_VM_RETURN();
+ }
+
+ LOAD_OPLINE();
+
+ if (object) {
+ OBJ_RELEASE(object);
+ }
+ EG(scope) = EX(func)->op_array.scope;
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_throw_exception_internal(NULL);
+ if (RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(EX_VAR(opline->result.var));
+ }
+ HANDLE_EXCEPTION_LEAVE();
+ }
+
+ ZEND_VM_INC_OPCODE();
+ ZEND_VM_LEAVE();
+}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
}
if (IS_CONST == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (IS_CONST == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
}
if (IS_UNUSED == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (IS_CONST == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
}
if (IS_CV == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (IS_CONST == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
}
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (IS_CONST == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
Z_ADDREF_P(arg);
} else {
if (Z_ISREF_P(arg) &&
- (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
+ !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
/* don't separate references for __call */
arg = Z_REFVAL_P(arg);
}
}
if (IS_CONST == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (IS_VAR == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
}
if (IS_UNUSED == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (IS_VAR == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
}
if (IS_CV == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (IS_VAR == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
}
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
if (IS_VAR == IS_CONST) {
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
}
if (IS_CONST == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
}
if (IS_CV == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
}
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
Z_ADDREF_P(arg);
} else {
if (Z_ISREF_P(arg) &&
- (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
+ !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
/* don't separate references for __call */
arg = Z_REFVAL_P(arg);
}
}
if (IS_CONST == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
}
if (IS_CV == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
}
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
}
if (IS_CONST == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
}
if (IS_CV == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
}
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
EXPECTED(obj == orig_obj)) {
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
ZEND_FETCH_CLASS_NAME_SPEC_HANDLER,
ZEND_FETCH_CLASS_NAME_SPEC_HANDLER,
ZEND_FETCH_CLASS_NAME_SPEC_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_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
+ ZEND_CALL_TRAMPOLINE_SPEC_HANDLER,
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
"ZEND_BIND_TRAITS",
"ZEND_SEPARATE",
"ZEND_FETCH_CLASS_NAME",
- NULL,
+ "ZEND_CALL_TRAMPOLINE",
"ZEND_DISCARD_EXCEPTION",
"ZEND_YIELD",
"ZEND_GENERATOR_RETURN",
#define ZEND_BIND_TRAITS 155
#define ZEND_SEPARATE 156
#define ZEND_FETCH_CLASS_NAME 157
+#define ZEND_CALL_TRAMPOLINE 158
#define ZEND_DISCARD_EXCEPTION 159
#define ZEND_YIELD 160
#define ZEND_GENERATOR_RETURN 161
static zend_function *_copy_function(zend_function *fptr) /* {{{ */
{
if (fptr
- && fptr->type == ZEND_INTERNAL_FUNCTION
- && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
+ && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
{
zend_function *copy_fptr;
copy_fptr = emalloc(sizeof(zend_function));
static void _free_function(zend_function *fptr) /* {{{ */
{
if (fptr
- && fptr->type == ZEND_INTERNAL_FUNCTION
- && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
+ && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
{
zend_string_release(fptr->internal_function.function_name);
- efree(fptr);
+ zend_free_trampoline(fptr);
}
}
/* }}} */
if (Z_TYPE_P(parameter) == IS_LONG) {
position= (int)Z_LVAL_P(parameter);
if (position < 0 || (uint32_t)position >= num_args) {
- if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
+ if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
zend_string_release(fptr->common.function_name);
}
- efree(fptr);
+ zend_free_trampoline(fptr);
}
if (is_closure) {
zval_ptr_dtor(reference);
}
}
if (position == -1) {
- if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
+ if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
zend_string_release(fptr->common.function_name);
}
- efree(fptr);
+ zend_free_trampoline(fptr);
}
if (is_closure) {
zval_ptr_dtor(reference);
}
/* This is an original closure object and __invoke is to be called. */
- if (Z_OBJCE_P(obj) == zend_ce_closure && mptr->type == ZEND_INTERNAL_FUNCTION &&
- (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
+ if (Z_OBJCE_P(obj) == zend_ce_closure &&
+ (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
{
RETURN_ZVAL(obj, 1, 0);
} else {
/*
* Copy the zend_function when calling via handler (e.g. Closure::__invoke())
*/
- if (mptr->type == ZEND_INTERNAL_FUNCTION &&
- (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
+ if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
fcc.function_handler = _copy_function(mptr);
}