Improve performance by using prealloated op_arrray

This commit is contained in:
Xinchen Hui 2015-04-09 18:23:17 +08:00
parent df7fbbf949
commit ec1d9eb592
9 changed files with 82 additions and 41 deletions

View File

@ -26,6 +26,7 @@
#include "zend_list.h"
#include "zend_API.h"
#include "zend_exceptions.h"
#include "zend_objects_API.h"
#include "zend_builtin_functions.h"
#include "zend_ini.h"
#include "zend_vm.h"
@ -531,6 +532,8 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{
#ifdef ZEND_WIN32
zend_get_windows_version_info(&executor_globals->windows_version_info);
#endif
memset(&EG(proxy_call_func), 0, sizeof(zend_op_array));
zend_init_proxy_call_func(&EG(proxy_call_func), &EG(proxy_call_op));
}
/* }}} */
@ -722,6 +725,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
#ifndef ZTS
zend_init_rsrc_plist();
zend_init_exception_op();
zend_init_proxy_call_func(&EG(proxy_call_func), &EG(proxy_call_op));
#endif
zend_ini_startup();

View File

@ -1292,7 +1292,7 @@ ZEND_FUNCTION(method_exists)
zend_string_release(lcname);
zend_string_release(func->common.function_name);
efree(func);
zend_free_proxy_call_func(func);
return;
}
zend_string_release(lcname);

View File

@ -237,6 +237,9 @@ struct _zend_executor_globals {
XPFPA_CW_DATATYPE saved_fpu_cw;
#endif
zend_op_array proxy_call_func;
zend_op proxy_call_op;
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};

View File

@ -29,7 +29,6 @@
#include "zend_interfaces.h"
#include "zend_closures.h"
#include "zend_compile.h"
#include "zend_vm.h"
#include "zend_hash.h"
#define DEBUG_OBJECT_HANDLERS 0
@ -1035,39 +1034,9 @@ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope)
}
/* }}} */
static inline zend_op_array *zend_get_proxy_call_function(zend_class_entry *ce, zend_string *method_name, int is_static) /* {{{ */ {
zend_op_array *call_user_call = ecalloc(1, ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array)) + sizeof(zend_op));
zend_function *fbc = is_static? ce->__callstatic : ce->__call;
ZEND_ASSERT(fbc);
call_user_call->type = ZEND_USER_FUNCTION;
call_user_call->scope = ce;
call_user_call->prototype = fbc;
call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER | (is_static? (ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) : 0);
call_user_call->this_var = -1;
call_user_call->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : STR_EMPTY_ALLOC();
call_user_call->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
call_user_call->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0;
call_user_call->opcodes = (zend_op *)((char *)call_user_call + ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array)));
call_user_call->opcodes[0].opcode = ZEND_PROXY_CALL;
call_user_call->opcodes[0].op1_type = IS_UNUSED;
call_user_call->opcodes[0].op2_type = IS_UNUSED;
call_user_call->opcodes[0].result_type = IS_UNUSED;
ZEND_VM_SET_OPCODE_HANDLER(&call_user_call->opcodes[0]);
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);
} else {
call_user_call->function_name = zend_string_copy(method_name);
}
return call_user_call;
}
/* }}} */
static inline union _zend_function *zend_get_user_call_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
{
return (union _zend_function *)zend_get_proxy_call_function(ce, method_name, 0);
return (union _zend_function *)zend_get_proxy_call_func(ce, method_name, 0);
}
/* }}} */
@ -1198,7 +1167,7 @@ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{
static inline union _zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
{
return (union _zend_function *)zend_get_proxy_call_function(ce, method_name, 1);
return (union _zend_function *)zend_get_proxy_call_func(ce, method_name, 1);
}
/* }}} */

View File

@ -22,6 +22,7 @@
#include "zend.h"
#include "zend_globals.h"
#include "zend_variables.h"
#include "zend_vm.h"
#include "zend_API.h"
#include "zend_objects_API.h"
@ -224,6 +225,57 @@ ZEND_API zend_object_handlers *zend_get_std_object_handlers(void)
return &std_object_handlers;
}
ZEND_API void zend_init_proxy_call_func(zend_op_array *func, zend_op *opline)
{
func->type = ZEND_USER_FUNCTION;
func->fn_flags = ZEND_ACC_CALL_VIA_HANDLER | ZEND_ACC_PUBLIC;
func->this_var = -1;
opline->opcode = ZEND_PROXY_CALL;
opline->op1_type = IS_UNUSED;
opline->op2_type = IS_UNUSED;
opline->result_type = IS_UNUSED;
ZEND_VM_SET_OPCODE_HANDLER(opline);
func->opcodes = opline;
}
ZEND_API zend_op_array *zend_get_proxy_call_func(zend_class_entry *ce, zend_string *method_name, int is_static)
{
zend_op_array *func;
zend_function *fbc = is_static? ce->__callstatic : ce->__call;
ZEND_ASSERT(fbc);
if (EXPECTED(EG(proxy_call_func).function_name == NULL)) {
func = &EG(proxy_call_func);
} else {
func = ecalloc(1, ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array)) + sizeof(zend_op));
zend_init_proxy_call_func(func, (zend_op *)((char *)func + ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array))));
}
if (is_static) {
func->fn_flags |= ZEND_ACC_STATIC;
} else {
func->fn_flags &= ~ZEND_ACC_STATIC;
}
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;
if (UNEXPECTED(strlen(method_name->val) != method_name->len)) {
func->function_name = zend_string_init(method_name->val, strlen(method_name->val), 0);
} else {
func->function_name = zend_string_copy(method_name);
}
return func;
}
/*
* Local variables:
* tab-width: 4

View File

@ -70,8 +70,21 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects
ZEND_API zend_object *zend_object_create_proxy(zval *object, zval *member);
ZEND_API zend_object_handlers *zend_get_std_object_handlers(void);
ZEND_API void zend_init_proxy_call_func(zend_op_array *func, zend_op *opline);
ZEND_API zend_op_array *zend_get_proxy_call_func(zend_class_entry *ce, zend_string *method_name, int is_static);
END_EXTERN_C()
#define zend_free_proxy_call_func(func) do { \
if (((zend_op_array *)func) == &EG(proxy_call_func)) { \
((zend_op_array *)func)->function_name = NULL; \
} else { \
efree(func); \
} \
} while (0)
static zend_always_inline void zend_object_release(zend_object *obj)
{
if (--GC_REFCOUNT(obj) == 0) {

View File

@ -6940,7 +6940,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
zend_string_release(call->func->common.function_name);
efree(call->func);
zend_free_proxy_call_func(call->func);
}
EX(call) = call->prev_execute_data;
@ -7596,7 +7596,7 @@ ZEND_VM_HANDLER(158, ZEND_PROXY_CALL, ANY, ANY)
i_init_func_execute_data(call, &call->func->op_array,
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
efree(fbc);
zend_free_proxy_call_func(fbc);
ZEND_VM_ENTER();
} else {
@ -7618,7 +7618,7 @@ ZEND_VM_HANDLER(158, ZEND_PROXY_CALL, ANY, ANY)
execute_data = EG(current_execute_data) = call->prev_execute_data;
efree(fbc);
zend_free_proxy_call_func(fbc);
zend_vm_stack_free_args(call);
zend_vm_stack_free_call_frame(call);

View File

@ -1554,7 +1554,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
}
if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
zend_string_release(call->func->common.function_name);
efree(call->func);
zend_free_proxy_call_func(call->func);
}
EX(call) = call->prev_execute_data;
@ -1810,7 +1810,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PROXY_CALL_SPEC_HANDLER(ZEND_O
i_init_func_execute_data(call, &call->func->op_array,
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
efree(fbc);
zend_free_proxy_call_func(fbc);
ZEND_VM_ENTER();
} else {
@ -1832,7 +1832,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PROXY_CALL_SPEC_HANDLER(ZEND_O
execute_data = EG(current_execute_data) = call->prev_execute_data;
efree(fbc);
zend_free_proxy_call_func(fbc);
zend_vm_stack_free_args(call);
zend_vm_stack_free_call_frame(call);

View File

@ -2242,7 +2242,7 @@ ZEND_METHOD(reflection_parameter, __construct)
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
zend_string_release(fptr->common.function_name);
}
efree(fptr);
zend_free_proxy_call_func(fptr);
}
if (is_closure) {
zval_ptr_dtor(reference);