mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Remove ZEND_OVERLOADED_FUNCTION and corresponding call_method object handler
This commit is contained in:
parent
2306c855ab
commit
f45e0ce928
18 changed files with 94 additions and 259 deletions
|
@ -2,6 +2,7 @@ PHP 8.0 INTERNALS UPGRADE NOTES
|
||||||
|
|
||||||
1. Internal API changes
|
1. Internal API changes
|
||||||
a. Object Handlers API
|
a. Object Handlers API
|
||||||
|
b. ZEND_OVERLOADED_FUNCTION and corresponding call_method() object handler
|
||||||
|
|
||||||
2. Build system changes
|
2. Build system changes
|
||||||
a. Abstract
|
a. Abstract
|
||||||
|
@ -14,10 +15,15 @@ PHP 8.0 INTERNALS UPGRADE NOTES
|
||||||
1. Internal API changes
|
1. Internal API changes
|
||||||
========================
|
========================
|
||||||
|
|
||||||
a. Object Handlers API and some related functions, e.g. zend_call_method() and
|
a. Object Handlers API and some related functions, e.g. zend_call_method() and
|
||||||
zend_objects_clone_obj() were changed to receive zend_object* instead of
|
zend_objects_clone_obj() were changed to receive zend_object* instead of
|
||||||
zval* and zend_string* instead of zval* for property names.
|
zval* and zend_string* instead of zval* for property names.
|
||||||
|
|
||||||
|
b. ZEND_OVERLOADED_FUNCTION and corresponding call_method() object handler
|
||||||
|
were removed. ZEND_INTERNAL_FUNCTION with ZEND_ACC_CALL_VIA_HANDLER and
|
||||||
|
defined "handler" callback should be used instead. This "handler" callback
|
||||||
|
should also take care about function cleanup. See ext/zend_test/test.c
|
||||||
|
for example.
|
||||||
|
|
||||||
========================
|
========================
|
||||||
2. Build system changes
|
2. Build system changes
|
||||||
|
|
|
@ -6,10 +6,10 @@ if (!extension_loaded('zend-test')) die('skip zend-test extension not loaded');
|
||||||
?>
|
?>
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
$o = new _ZendTestChildClass();
|
||||||
|
var_dump($o->test());
|
||||||
var_dump(_ZendTestClass::test());
|
var_dump(_ZendTestClass::test());
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECT--
|
||||||
Fatal error: Uncaught Error: Cannot call overloaded function for non-object in %soverloaded_func_001.php:%d
|
string(4) "test"
|
||||||
Stack trace:
|
string(4) "test"
|
||||||
#0 {main}
|
|
||||||
thrown in %soverloaded_func_001.php on line %d
|
|
||||||
|
|
|
@ -3014,8 +3014,7 @@ get_function_via_handler:
|
||||||
(!fcc->function_handler->common.scope ||
|
(!fcc->function_handler->common.scope ||
|
||||||
!instanceof_function(ce_org, 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_TRAMPOLINE) {
|
if (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
|
||||||
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION &&
|
if (fcc->function_handler->common.function_name) {
|
||||||
fcc->function_handler->common.function_name) {
|
|
||||||
zend_string_release_ex(fcc->function_handler->common.function_name, 0);
|
zend_string_release_ex(fcc->function_handler->common.function_name, 0);
|
||||||
}
|
}
|
||||||
zend_free_trampoline(fcc->function_handler);
|
zend_free_trampoline(fcc->function_handler);
|
||||||
|
@ -3206,11 +3205,8 @@ check_func:
|
||||||
ret = zend_is_callable_check_func(check_flags, callable, fcc, strict_class, error);
|
ret = zend_is_callable_check_func(check_flags, callable, fcc, strict_class, error);
|
||||||
if (fcc == &fcc_local &&
|
if (fcc == &fcc_local &&
|
||||||
fcc->function_handler &&
|
fcc->function_handler &&
|
||||||
((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
|
(fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
|
if (fcc->function_handler->common.function_name) {
|
||||||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
|
|
||||||
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION &&
|
|
||||||
fcc->function_handler->common.function_name) {
|
|
||||||
zend_string_release_ex(fcc->function_handler->common.function_name, 0);
|
zend_string_release_ex(fcc->function_handler->common.function_name, 0);
|
||||||
}
|
}
|
||||||
zend_free_trampoline(fcc->function_handler);
|
zend_free_trampoline(fcc->function_handler);
|
||||||
|
@ -3322,12 +3318,8 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam
|
||||||
add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
|
add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
|
||||||
}
|
}
|
||||||
if (fcc.function_handler &&
|
if (fcc.function_handler &&
|
||||||
((fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
|
(fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||||
fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
|
zend_string_release_ex(fcc.function_handler->common.function_name, 0);
|
||||||
fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
|
|
||||||
if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
|
|
||||||
zend_string_release_ex(fcc.function_handler->common.function_name, 0);
|
|
||||||
}
|
|
||||||
zend_free_trampoline(fcc.function_handler);
|
zend_free_trampoline(fcc.function_handler);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -875,9 +875,7 @@ void zend_assert_valid_class_name(const zend_string *const_name);
|
||||||
|
|
||||||
#define ZEND_INTERNAL_FUNCTION 1
|
#define ZEND_INTERNAL_FUNCTION 1
|
||||||
#define ZEND_USER_FUNCTION 2
|
#define ZEND_USER_FUNCTION 2
|
||||||
#define ZEND_OVERLOADED_FUNCTION 3
|
|
||||||
#define ZEND_EVAL_CODE 4
|
#define ZEND_EVAL_CODE 4
|
||||||
#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5
|
|
||||||
|
|
||||||
/* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */
|
/* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */
|
||||||
#define ZEND_USER_CODE(type) ((type & 1) == 0)
|
#define ZEND_USER_CODE(type) ((type & 1) == 0)
|
||||||
|
|
|
@ -4069,43 +4069,6 @@ already_compiled:
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret) /* {{{ */
|
|
||||||
{
|
|
||||||
zend_function *fbc = call->func;
|
|
||||||
zend_object *object;
|
|
||||||
|
|
||||||
/* Not sure what should be done here if it's a static method */
|
|
||||||
if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) {
|
|
||||||
zend_vm_stack_free_args(call);
|
|
||||||
if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
|
||||||
zend_string_release_ex(fbc->common.function_name, 0);
|
|
||||||
}
|
|
||||||
efree(fbc);
|
|
||||||
zend_vm_stack_free_call_frame(call);
|
|
||||||
|
|
||||||
zend_throw_error(NULL, "Cannot call overloaded function for non-object");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
object = Z_OBJ(call->This);
|
|
||||||
|
|
||||||
ZVAL_NULL(ret);
|
|
||||||
|
|
||||||
EG(current_execute_data) = call;
|
|
||||||
object->handlers->call_method(fbc->common.function_name, object, call, ret);
|
|
||||||
EG(current_execute_data) = call->prev_execute_data;
|
|
||||||
|
|
||||||
zend_vm_stack_free_args(call);
|
|
||||||
|
|
||||||
if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
|
||||||
zend_string_release_ex(fbc->common.function_name, 0);
|
|
||||||
}
|
|
||||||
efree(fbc);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
static zend_never_inline zend_bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
|
static zend_never_inline zend_bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
zend_class_entry *ce = Z_OBJCE_P(array_ptr);
|
zend_class_entry *ce = Z_OBJCE_P(array_ptr);
|
||||||
|
|
|
@ -375,8 +375,6 @@ ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table);
|
||||||
ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data);
|
ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data);
|
||||||
ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num);
|
ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num);
|
||||||
|
|
||||||
ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret);
|
|
||||||
|
|
||||||
#define CACHE_ADDR(num) \
|
#define CACHE_ADDR(num) \
|
||||||
((void**)((char*)EX_RUN_TIME_CACHE() + (num)))
|
((void**)((char*)EX_RUN_TIME_CACHE() + (num)))
|
||||||
|
|
||||||
|
|
|
@ -772,8 +772,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
|
||||||
/* We must re-initialize function again */
|
/* We must re-initialize function again */
|
||||||
fci_cache->function_handler = NULL;
|
fci_cache->function_handler = NULL;
|
||||||
}
|
}
|
||||||
} else if (func->type == ZEND_INTERNAL_FUNCTION) {
|
} else {
|
||||||
int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
|
int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
|
||||||
|
|
||||||
|
ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION);
|
||||||
ZVAL_NULL(fci->retval);
|
ZVAL_NULL(fci->retval);
|
||||||
call->prev_execute_data = EG(current_execute_data);
|
call->prev_execute_data = EG(current_execute_data);
|
||||||
call->return_value = NULL; /* this is not a constructor call */
|
call->return_value = NULL; /* this is not a constructor call */
|
||||||
|
@ -796,30 +798,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
|
||||||
/* We must re-initialize function again */
|
/* We must re-initialize function again */
|
||||||
fci_cache->function_handler = NULL;
|
fci_cache->function_handler = NULL;
|
||||||
}
|
}
|
||||||
} else { /* ZEND_OVERLOADED_FUNCTION */
|
|
||||||
ZVAL_NULL(fci->retval);
|
|
||||||
|
|
||||||
/* Not sure what should be done here if it's a static method */
|
|
||||||
if (fci->object) {
|
|
||||||
call->prev_execute_data = EG(current_execute_data);
|
|
||||||
EG(current_execute_data) = call;
|
|
||||||
fci->object->handlers->call_method(func->common.function_name, fci->object, call, fci->retval);
|
|
||||||
EG(current_execute_data) = call->prev_execute_data;
|
|
||||||
} else {
|
|
||||||
zend_throw_error(NULL, "Cannot call overloaded function for non-object");
|
|
||||||
}
|
|
||||||
|
|
||||||
zend_vm_stack_free_args(call);
|
|
||||||
|
|
||||||
if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
|
||||||
zend_string_release_ex(func->common.function_name, 0);
|
|
||||||
}
|
|
||||||
efree(func);
|
|
||||||
|
|
||||||
if (EG(exception)) {
|
|
||||||
zval_ptr_dtor(fci->retval);
|
|
||||||
ZVAL_UNDEF(fci->retval);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_vm_stack_free_call_frame(call);
|
zend_vm_stack_free_call_frame(call);
|
||||||
|
|
|
@ -44,7 +44,6 @@ static const zend_object_handlers iterator_object_handlers = {
|
||||||
NULL, /* unset dim */
|
NULL, /* unset dim */
|
||||||
NULL, /* props get */
|
NULL, /* props get */
|
||||||
NULL, /* method get */
|
NULL, /* method get */
|
||||||
NULL, /* call */
|
|
||||||
NULL, /* get ctor */
|
NULL, /* get ctor */
|
||||||
NULL, /* get class name */
|
NULL, /* get class name */
|
||||||
NULL, /* compare */
|
NULL, /* compare */
|
||||||
|
|
|
@ -1845,7 +1845,6 @@ ZEND_API const zend_object_handlers std_object_handlers = {
|
||||||
zend_std_unset_dimension, /* unset_dimension */
|
zend_std_unset_dimension, /* unset_dimension */
|
||||||
zend_std_get_properties, /* get_properties */
|
zend_std_get_properties, /* get_properties */
|
||||||
zend_std_get_method, /* get_method */
|
zend_std_get_method, /* get_method */
|
||||||
NULL, /* call_method */
|
|
||||||
zend_std_get_constructor, /* get_constructor */
|
zend_std_get_constructor, /* get_constructor */
|
||||||
zend_std_get_class_name, /* get_class_name */
|
zend_std_get_class_name, /* get_class_name */
|
||||||
zend_std_compare_objects, /* compare_objects */
|
zend_std_compare_objects, /* compare_objects */
|
||||||
|
|
|
@ -120,7 +120,6 @@ typedef zend_array *(*zend_object_get_properties_for_t)(zend_object *object, zen
|
||||||
/* args on stack! */
|
/* args on stack! */
|
||||||
/* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this.
|
/* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this.
|
||||||
*/
|
*/
|
||||||
typedef int (*zend_object_call_method_t)(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS);
|
|
||||||
typedef zend_function *(*zend_object_get_method_t)(zend_object **object, zend_string *method, const zval *key);
|
typedef zend_function *(*zend_object_get_method_t)(zend_object **object, zend_string *method, const zval *key);
|
||||||
typedef zend_function *(*zend_object_get_constructor_t)(zend_object *object);
|
typedef zend_function *(*zend_object_get_constructor_t)(zend_object *object);
|
||||||
|
|
||||||
|
@ -171,7 +170,6 @@ struct _zend_object_handlers {
|
||||||
zend_object_unset_dimension_t unset_dimension; /* required */
|
zend_object_unset_dimension_t unset_dimension; /* required */
|
||||||
zend_object_get_properties_t get_properties; /* required */
|
zend_object_get_properties_t get_properties; /* required */
|
||||||
zend_object_get_method_t get_method; /* required */
|
zend_object_get_method_t get_method; /* required */
|
||||||
zend_object_call_method_t call_method; /* optional */
|
|
||||||
zend_object_get_constructor_t get_constructor; /* required */
|
zend_object_get_constructor_t get_constructor; /* required */
|
||||||
zend_object_get_class_name_t get_class_name; /* required */
|
zend_object_get_class_name_t get_class_name; /* required */
|
||||||
zend_object_compare_t compare_objects; /* optional */
|
zend_object_compare_t compare_objects; /* optional */
|
||||||
|
|
|
@ -4019,9 +4019,10 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
|
||||||
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
||||||
zend_execute_ex(call);
|
zend_execute_ex(call);
|
||||||
}
|
}
|
||||||
} else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
|
} else {
|
||||||
zval retval;
|
zval retval;
|
||||||
|
|
||||||
|
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
|
||||||
call->prev_execute_data = execute_data;
|
call->prev_execute_data = execute_data;
|
||||||
EG(current_execute_data) = call;
|
EG(current_execute_data) = call;
|
||||||
|
|
||||||
|
@ -4053,22 +4054,6 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
|
||||||
EG(current_execute_data) = execute_data;
|
EG(current_execute_data) = execute_data;
|
||||||
zend_vm_stack_free_args(call);
|
zend_vm_stack_free_args(call);
|
||||||
|
|
||||||
if (!RETURN_VALUE_USED(opline)) {
|
|
||||||
zval_ptr_dtor(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { /* ZEND_OVERLOADED_FUNCTION */
|
|
||||||
zval retval;
|
|
||||||
|
|
||||||
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
|
||||||
|
|
||||||
call->prev_execute_data = execute_data;
|
|
||||||
|
|
||||||
if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) {
|
|
||||||
UNDEF_RESULT();
|
|
||||||
HANDLE_EXCEPTION();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RETURN_VALUE_USED(opline)) {
|
if (!RETURN_VALUE_USED(opline)) {
|
||||||
zval_ptr_dtor(ret);
|
zval_ptr_dtor(ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -963,9 +963,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
||||||
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
||||||
zend_execute_ex(call);
|
zend_execute_ex(call);
|
||||||
}
|
}
|
||||||
} else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
|
} else {
|
||||||
zval retval;
|
zval retval;
|
||||||
|
|
||||||
|
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
|
||||||
call->prev_execute_data = execute_data;
|
call->prev_execute_data = execute_data;
|
||||||
EG(current_execute_data) = call;
|
EG(current_execute_data) = call;
|
||||||
|
|
||||||
|
@ -997,22 +998,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
||||||
EG(current_execute_data) = execute_data;
|
EG(current_execute_data) = execute_data;
|
||||||
zend_vm_stack_free_args(call);
|
zend_vm_stack_free_args(call);
|
||||||
|
|
||||||
if (!0) {
|
|
||||||
zval_ptr_dtor(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { /* ZEND_OVERLOADED_FUNCTION */
|
|
||||||
zval retval;
|
|
||||||
|
|
||||||
ret = 0 ? EX_VAR(opline->result.var) : &retval;
|
|
||||||
|
|
||||||
call->prev_execute_data = execute_data;
|
|
||||||
|
|
||||||
if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) {
|
|
||||||
UNDEF_RESULT();
|
|
||||||
HANDLE_EXCEPTION();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!0) {
|
if (!0) {
|
||||||
zval_ptr_dtor(ret);
|
zval_ptr_dtor(ret);
|
||||||
}
|
}
|
||||||
|
@ -1084,9 +1069,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
||||||
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
||||||
zend_execute_ex(call);
|
zend_execute_ex(call);
|
||||||
}
|
}
|
||||||
} else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
|
} else {
|
||||||
zval retval;
|
zval retval;
|
||||||
|
|
||||||
|
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
|
||||||
call->prev_execute_data = execute_data;
|
call->prev_execute_data = execute_data;
|
||||||
EG(current_execute_data) = call;
|
EG(current_execute_data) = call;
|
||||||
|
|
||||||
|
@ -1118,22 +1104,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
||||||
EG(current_execute_data) = execute_data;
|
EG(current_execute_data) = execute_data;
|
||||||
zend_vm_stack_free_args(call);
|
zend_vm_stack_free_args(call);
|
||||||
|
|
||||||
if (!1) {
|
|
||||||
zval_ptr_dtor(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { /* ZEND_OVERLOADED_FUNCTION */
|
|
||||||
zval retval;
|
|
||||||
|
|
||||||
ret = 1 ? EX_VAR(opline->result.var) : &retval;
|
|
||||||
|
|
||||||
call->prev_execute_data = execute_data;
|
|
||||||
|
|
||||||
if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) {
|
|
||||||
UNDEF_RESULT();
|
|
||||||
HANDLE_EXCEPTION();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!1) {
|
if (!1) {
|
||||||
zval_ptr_dtor(ret);
|
zval_ptr_dtor(ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,11 +246,42 @@ static void function_dtor(zval *zv)
|
||||||
static PHP_FUNCTION(com_method_handler)
|
static PHP_FUNCTION(com_method_handler)
|
||||||
{
|
{
|
||||||
zval *object = getThis();
|
zval *object = getThis();
|
||||||
|
zend_string *method = EX(func)->common.function_name;
|
||||||
|
zval *args = NULL;
|
||||||
|
php_com_dotnet_object *obj = CDNO_FETCH(object);
|
||||||
|
int nargs;
|
||||||
|
VARIANT v;
|
||||||
|
int ret = FAILURE;
|
||||||
|
|
||||||
Z_OBJ_HANDLER_P(object, call_method)(
|
if (V_VT(&obj->v) != VT_DISPATCH) {
|
||||||
((zend_internal_function*)EX(func))->function_name,
|
goto exit;
|
||||||
Z_OBJ_P(object),
|
}
|
||||||
INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
||||||
|
nargs = ZEND_NUM_ARGS();
|
||||||
|
|
||||||
|
if (nargs) {
|
||||||
|
args = (zval *)safe_emalloc(sizeof(zval), nargs, 0);
|
||||||
|
zend_get_parameters_array_ex(nargs, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
VariantInit(&v);
|
||||||
|
|
||||||
|
if (SUCCESS == php_com_do_invoke_byref(obj, (zend_internal_function*)EX(func), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args)) {
|
||||||
|
php_com_zval_from_variant(return_value, &v, obj->code_page);
|
||||||
|
ret = SUCCESS;
|
||||||
|
VariantClear(&v);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args) {
|
||||||
|
efree(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup trampoline */
|
||||||
|
ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE);
|
||||||
|
zend_string_release(EX(func)->common.function_name);
|
||||||
|
zend_free_trampoline(EX(func));
|
||||||
|
EX(func) = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static zend_function *com_method_get(zend_object **object_ptr, zend_string *name, const zval *key)
|
static zend_function *com_method_get(zend_object **object_ptr, zend_string *name, const zval *key)
|
||||||
|
@ -270,7 +301,8 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name
|
||||||
|
|
||||||
/* check cache */
|
/* check cache */
|
||||||
if (obj->method_cache == NULL || NULL == (fptr = zend_hash_find_ptr(obj->method_cache, name))) {
|
if (obj->method_cache == NULL || NULL == (fptr = zend_hash_find_ptr(obj->method_cache, name))) {
|
||||||
f.type = ZEND_OVERLOADED_FUNCTION;
|
memset(&f, 0, sizeof(zend_internal_function));
|
||||||
|
f.type = ZEND_INTERNAL_FUNCTION;
|
||||||
f.num_args = 0;
|
f.num_args = 0;
|
||||||
f.arg_info = NULL;
|
f.arg_info = NULL;
|
||||||
f.scope = obj->ce;
|
f.scope = obj->ce;
|
||||||
|
@ -345,6 +377,7 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name
|
||||||
if (fptr) {
|
if (fptr) {
|
||||||
/* duplicate this into a new chunk of emalloc'd memory,
|
/* duplicate this into a new chunk of emalloc'd memory,
|
||||||
* since the engine will efree it */
|
* since the engine will efree it */
|
||||||
|
zend_string_addref(fptr->function_name);
|
||||||
func = emalloc(sizeof(*fptr));
|
func = emalloc(sizeof(*fptr));
|
||||||
memcpy(func, fptr, sizeof(*fptr));
|
memcpy(func, fptr, sizeof(*fptr));
|
||||||
|
|
||||||
|
@ -354,40 +387,6 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int com_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS)
|
|
||||||
{
|
|
||||||
zval *args = NULL;
|
|
||||||
php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
|
|
||||||
int nargs;
|
|
||||||
VARIANT v;
|
|
||||||
int ret = FAILURE;
|
|
||||||
|
|
||||||
if (V_VT(&obj->v) != VT_DISPATCH) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nargs = ZEND_NUM_ARGS();
|
|
||||||
|
|
||||||
if (nargs) {
|
|
||||||
args = (zval *)safe_emalloc(sizeof(zval), nargs, 0);
|
|
||||||
zend_get_parameters_array_ex(nargs, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantInit(&v);
|
|
||||||
|
|
||||||
if (SUCCESS == php_com_do_invoke_byref(obj, (zend_internal_function*)EX(func), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args)) {
|
|
||||||
php_com_zval_from_variant(return_value, &v, obj->code_page);
|
|
||||||
ret = SUCCESS;
|
|
||||||
VariantClear(&v);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args) {
|
|
||||||
efree(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static zend_function *com_constructor_get(zend_object *object)
|
static zend_function *com_constructor_get(zend_object *object)
|
||||||
{
|
{
|
||||||
php_com_dotnet_object *obj = (php_com_dotnet_object *) object;
|
php_com_dotnet_object *obj = (php_com_dotnet_object *) object;
|
||||||
|
@ -554,7 +553,6 @@ zend_object_handlers php_com_object_handlers = {
|
||||||
com_dimension_delete,
|
com_dimension_delete,
|
||||||
com_properties_get,
|
com_properties_get,
|
||||||
com_method_get,
|
com_method_get,
|
||||||
com_call_method,
|
|
||||||
com_constructor_get,
|
com_constructor_get,
|
||||||
com_class_name_get,
|
com_class_name_get,
|
||||||
com_objects_compare,
|
com_objects_compare,
|
||||||
|
|
|
@ -319,11 +319,6 @@ static zend_function *saproxy_method_get(zend_object **object, zend_string *name
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int saproxy_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS)
|
|
||||||
{
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static zend_function *saproxy_constructor_get(zend_object *object)
|
static zend_function *saproxy_constructor_get(zend_object *object)
|
||||||
{
|
{
|
||||||
/* user cannot instantiate */
|
/* user cannot instantiate */
|
||||||
|
@ -410,7 +405,6 @@ zend_object_handlers php_com_saproxy_handlers = {
|
||||||
saproxy_dimension_delete,
|
saproxy_dimension_delete,
|
||||||
saproxy_properties_get,
|
saproxy_properties_get,
|
||||||
saproxy_method_get,
|
saproxy_method_get,
|
||||||
saproxy_call_method,
|
|
||||||
saproxy_constructor_get,
|
saproxy_constructor_get,
|
||||||
saproxy_class_name_get,
|
saproxy_class_name_get,
|
||||||
saproxy_objects_compare,
|
saproxy_objects_compare,
|
||||||
|
|
|
@ -2656,11 +2656,6 @@ static zend_function *row_method_get(
|
||||||
return fbc;
|
return fbc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int row_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS)
|
|
||||||
{
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static zend_function *row_get_ctor(zend_object *object)
|
static zend_function *row_get_ctor(zend_object *object)
|
||||||
{
|
{
|
||||||
zend_throw_exception_ex(php_pdo_get_exception(), 0, "You may not create a PDORow manually");
|
zend_throw_exception_ex(php_pdo_get_exception(), 0, "You may not create a PDORow manually");
|
||||||
|
@ -2739,7 +2734,6 @@ void pdo_stmt_init(void)
|
||||||
pdo_row_object_handlers.unset_dimension = row_dim_delete;
|
pdo_row_object_handlers.unset_dimension = row_dim_delete;
|
||||||
pdo_row_object_handlers.get_properties_for = row_get_properties_for;
|
pdo_row_object_handlers.get_properties_for = row_get_properties_for;
|
||||||
pdo_row_object_handlers.get_method = row_method_get;
|
pdo_row_object_handlers.get_method = row_method_get;
|
||||||
pdo_row_object_handlers.call_method = row_call_method;
|
|
||||||
pdo_row_object_handlers.get_constructor = row_get_ctor;
|
pdo_row_object_handlers.get_constructor = row_get_ctor;
|
||||||
pdo_row_object_handlers.get_class_name = row_get_classname;
|
pdo_row_object_handlers.get_class_name = row_get_classname;
|
||||||
pdo_row_object_handlers.compare_objects = row_compare;
|
pdo_row_object_handlers.compare_objects = row_compare;
|
||||||
|
|
|
@ -2341,9 +2341,7 @@ ZEND_METHOD(reflection_parameter, __construct)
|
||||||
position= (int)Z_LVAL_P(parameter);
|
position= (int)Z_LVAL_P(parameter);
|
||||||
if (position < 0 || (uint32_t)position >= num_args) {
|
if (position < 0 || (uint32_t)position >= num_args) {
|
||||||
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
|
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
|
||||||
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
|
zend_string_release_ex(fptr->common.function_name, 0);
|
||||||
zend_string_release_ex(fptr->common.function_name, 0);
|
|
||||||
}
|
|
||||||
zend_free_trampoline(fptr);
|
zend_free_trampoline(fptr);
|
||||||
}
|
}
|
||||||
if (is_closure) {
|
if (is_closure) {
|
||||||
|
@ -2380,9 +2378,7 @@ ZEND_METHOD(reflection_parameter, __construct)
|
||||||
}
|
}
|
||||||
if (position == -1) {
|
if (position == -1) {
|
||||||
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
|
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
|
||||||
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
|
zend_string_release_ex(fptr->common.function_name, 0);
|
||||||
zend_string_release_ex(fptr->common.function_name, 0);
|
|
||||||
}
|
|
||||||
zend_free_trampoline(fptr);
|
zend_free_trampoline(fptr);
|
||||||
}
|
}
|
||||||
if (is_closure) {
|
if (is_closure) {
|
||||||
|
|
|
@ -1367,47 +1367,6 @@ static zend_function *spl_dual_it_get_method(zend_object **object, zend_string *
|
||||||
return function_handler;
|
return function_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MBO_0
|
|
||||||
int spl_dual_it_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
|
|
||||||
{
|
|
||||||
zval ***func_params, func;
|
|
||||||
zval retval;
|
|
||||||
int arg_count;
|
|
||||||
int current = 0;
|
|
||||||
int success;
|
|
||||||
void **p;
|
|
||||||
spl_dual_it_object *intern;
|
|
||||||
|
|
||||||
intern = Z_SPLDUAL_IT_P(ZEND_THIS);
|
|
||||||
|
|
||||||
ZVAL_STRING(&func, method, 0);
|
|
||||||
|
|
||||||
p = EG(argument_stack).top_element-2;
|
|
||||||
arg_count = (zend_ulong) *p;
|
|
||||||
|
|
||||||
func_params = safe_emalloc(sizeof(zval **), arg_count, 0);
|
|
||||||
|
|
||||||
current = 0;
|
|
||||||
while (arg_count-- > 0) {
|
|
||||||
func_params[current] = (zval **) p - (arg_count-current);
|
|
||||||
current++;
|
|
||||||
}
|
|
||||||
arg_count = current; /* restore */
|
|
||||||
|
|
||||||
if (call_user_function_ex(EG(function_table), NULL, &func, &retval, arg_count, func_params, 0, NULL) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
|
|
||||||
RETURN_ZVAL(&retval, 0, 0);
|
|
||||||
|
|
||||||
success = SUCCESS;
|
|
||||||
} else {
|
|
||||||
zend_throw_error(NULL, "Unable to call %s::%s()", intern->inner.ce->name, method);
|
|
||||||
success = FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
efree(func_params);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SPL_CHECK_CTOR(intern, classname) \
|
#define SPL_CHECK_CTOR(intern, classname) \
|
||||||
if (intern->dit_type == DIT_Unknown) { \
|
if (intern->dit_type == DIT_Unknown) { \
|
||||||
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Classes derived from %s must call %s::__construct()", \
|
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Classes derived from %s must call %s::__construct()", \
|
||||||
|
@ -3682,7 +3641,6 @@ PHP_MINIT_FUNCTION(spl_iterators)
|
||||||
memcpy(&spl_handlers_dual_it, &std_object_handlers, sizeof(zend_object_handlers));
|
memcpy(&spl_handlers_dual_it, &std_object_handlers, sizeof(zend_object_handlers));
|
||||||
spl_handlers_dual_it.offset = XtOffsetOf(spl_dual_it_object, std);
|
spl_handlers_dual_it.offset = XtOffsetOf(spl_dual_it_object, std);
|
||||||
spl_handlers_dual_it.get_method = spl_dual_it_get_method;
|
spl_handlers_dual_it.get_method = spl_dual_it_get_method;
|
||||||
/*spl_handlers_dual_it.call_method = spl_dual_it_call_method;*/
|
|
||||||
spl_handlers_dual_it.clone_obj = NULL;
|
spl_handlers_dual_it.clone_obj = NULL;
|
||||||
spl_handlers_dual_it.dtor_obj = spl_dual_it_dtor;
|
spl_handlers_dual_it.dtor_obj = spl_dual_it_dtor;
|
||||||
spl_handlers_dual_it.free_obj = spl_dual_it_free_storage;
|
spl_handlers_dual_it.free_obj = spl_dual_it_free_storage;
|
||||||
|
|
|
@ -50,7 +50,13 @@ ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
ZEND_FUNCTION(zend_test_func)
|
ZEND_FUNCTION(zend_test_func)
|
||||||
{
|
{
|
||||||
/* dummy */
|
RETVAL_STR_COPY(EX(func)->common.function_name);
|
||||||
|
|
||||||
|
/* Cleanup trampoline */
|
||||||
|
ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE);
|
||||||
|
zend_string_release(EX(func)->common.function_name);
|
||||||
|
zend_free_trampoline(EX(func));
|
||||||
|
EX(func) = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_FUNCTION(zend_test_array_return)
|
ZEND_FUNCTION(zend_test_array_return)
|
||||||
|
@ -144,41 +150,45 @@ static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ {
|
static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ {
|
||||||
zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
|
zend_internal_function *fptr;
|
||||||
fptr->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY;
|
|
||||||
|
if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
|
||||||
|
fptr = &EG(trampoline);
|
||||||
|
} else {
|
||||||
|
fptr = emalloc(sizeof(zend_internal_function));
|
||||||
|
}
|
||||||
|
memset(fptr, 0, sizeof(zend_internal_function));
|
||||||
|
fptr->type = ZEND_INTERNAL_FUNCTION;
|
||||||
fptr->num_args = 1;
|
fptr->num_args = 1;
|
||||||
fptr->arg_info = NULL;
|
|
||||||
fptr->scope = (*object)->ce;
|
fptr->scope = (*object)->ce;
|
||||||
fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
|
fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
|
||||||
fptr->function_name = zend_string_copy(name);
|
fptr->function_name = zend_string_copy(name);
|
||||||
fptr->handler = ZEND_FN(zend_test_func);
|
fptr->handler = ZEND_FN(zend_test_func);
|
||||||
zend_set_function_arg_flags((zend_function*)fptr);
|
|
||||||
|
|
||||||
return (zend_function*)fptr;
|
return (zend_function*)fptr;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ {
|
static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ {
|
||||||
zend_internal_function *fptr = emalloc(sizeof(zend_internal_function));
|
zend_internal_function *fptr;
|
||||||
fptr->type = ZEND_OVERLOADED_FUNCTION;
|
|
||||||
|
if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
|
||||||
|
fptr = &EG(trampoline);
|
||||||
|
} else {
|
||||||
|
fptr = emalloc(sizeof(zend_internal_function));
|
||||||
|
}
|
||||||
|
memset(fptr, 0, sizeof(zend_internal_function));
|
||||||
|
fptr->type = ZEND_INTERNAL_FUNCTION;
|
||||||
fptr->num_args = 1;
|
fptr->num_args = 1;
|
||||||
fptr->arg_info = NULL;
|
|
||||||
fptr->scope = ce;
|
fptr->scope = ce;
|
||||||
fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
|
fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC;
|
||||||
fptr->function_name = name;
|
fptr->function_name = zend_string_copy(name);
|
||||||
fptr->handler = ZEND_FN(zend_test_func);
|
fptr->handler = ZEND_FN(zend_test_func);
|
||||||
zend_set_function_arg_flags((zend_function*)fptr);
|
|
||||||
|
|
||||||
return (zend_function*)fptr;
|
return (zend_function*)fptr;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
static int zend_test_class_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ {
|
|
||||||
RETVAL_STR(zend_string_copy(method));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
static ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ {
|
static ZEND_METHOD(_ZendTestTrait, testMethod) /* {{{ */ {
|
||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -239,7 +249,6 @@ PHP_MINIT_FUNCTION(zend_test)
|
||||||
|
|
||||||
memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
||||||
zend_test_class_handlers.get_method = zend_test_class_method_get;
|
zend_test_class_handlers.get_method = zend_test_class_method_get;
|
||||||
zend_test_class_handlers.call_method = zend_test_class_call_method;
|
|
||||||
|
|
||||||
INIT_CLASS_ENTRY(class_entry, "_ZendTestTrait", zend_test_trait_methods);
|
INIT_CLASS_ENTRY(class_entry, "_ZendTestTrait", zend_test_trait_methods);
|
||||||
zend_test_trait = zend_register_internal_class(&class_entry);
|
zend_test_trait = zend_register_internal_class(&class_entry);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue