Skip to content

Commit ec1d9eb

Browse files
committed
Improve performance by using prealloated op_arrray
1 parent df7fbbf commit ec1d9eb

File tree

9 files changed

+82
-41
lines changed

9 files changed

+82
-41
lines changed

Zend/zend.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "zend_list.h"
2727
#include "zend_API.h"
2828
#include "zend_exceptions.h"
29+
#include "zend_objects_API.h"
2930
#include "zend_builtin_functions.h"
3031
#include "zend_ini.h"
3132
#include "zend_vm.h"
@@ -531,6 +532,8 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{
531532
#ifdef ZEND_WIN32
532533
zend_get_windows_version_info(&executor_globals->windows_version_info);
533534
#endif
535+
memset(&EG(proxy_call_func), 0, sizeof(zend_op_array));
536+
zend_init_proxy_call_func(&EG(proxy_call_func), &EG(proxy_call_op));
534537
}
535538
/* }}} */
536539

@@ -722,6 +725,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
722725
#ifndef ZTS
723726
zend_init_rsrc_plist();
724727
zend_init_exception_op();
728+
zend_init_proxy_call_func(&EG(proxy_call_func), &EG(proxy_call_op));
725729
#endif
726730

727731
zend_ini_startup();

Zend/zend_builtin_functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,7 @@ ZEND_FUNCTION(method_exists)
12921292

12931293
zend_string_release(lcname);
12941294
zend_string_release(func->common.function_name);
1295-
efree(func);
1295+
zend_free_proxy_call_func(func);
12961296
return;
12971297
}
12981298
zend_string_release(lcname);

Zend/zend_globals.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ struct _zend_executor_globals {
237237
XPFPA_CW_DATATYPE saved_fpu_cw;
238238
#endif
239239

240+
zend_op_array proxy_call_func;
241+
zend_op proxy_call_op;
242+
240243
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
241244
};
242245

Zend/zend_object_handlers.c

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "zend_interfaces.h"
3030
#include "zend_closures.h"
3131
#include "zend_compile.h"
32-
#include "zend_vm.h"
3332
#include "zend_hash.h"
3433

3534
#define DEBUG_OBJECT_HANDLERS 0
@@ -1035,39 +1034,9 @@ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope)
10351034
}
10361035
/* }}} */
10371036

1038-
static inline zend_op_array *zend_get_proxy_call_function(zend_class_entry *ce, zend_string *method_name, int is_static) /* {{{ */ {
1039-
zend_op_array *call_user_call = ecalloc(1, ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array)) + sizeof(zend_op));
1040-
zend_function *fbc = is_static? ce->__callstatic : ce->__call;
1041-
1042-
ZEND_ASSERT(fbc);
1043-
1044-
call_user_call->type = ZEND_USER_FUNCTION;
1045-
call_user_call->scope = ce;
1046-
call_user_call->prototype = fbc;
1047-
call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER | (is_static? (ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) : 0);
1048-
call_user_call->this_var = -1;
1049-
call_user_call->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : STR_EMPTY_ALLOC();
1050-
call_user_call->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
1051-
call_user_call->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0;
1052-
call_user_call->opcodes = (zend_op *)((char *)call_user_call + ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array)));
1053-
call_user_call->opcodes[0].opcode = ZEND_PROXY_CALL;
1054-
call_user_call->opcodes[0].op1_type = IS_UNUSED;
1055-
call_user_call->opcodes[0].op2_type = IS_UNUSED;
1056-
call_user_call->opcodes[0].result_type = IS_UNUSED;
1057-
ZEND_VM_SET_OPCODE_HANDLER(&call_user_call->opcodes[0]);
1058-
if (UNEXPECTED(strlen(method_name->val) != method_name->len)) {
1059-
call_user_call->function_name = zend_string_init(method_name->val, strlen(method_name->val), 0);
1060-
} else {
1061-
call_user_call->function_name = zend_string_copy(method_name);
1062-
}
1063-
1064-
return call_user_call;
1065-
}
1066-
/* }}} */
1067-
10681037
static inline union _zend_function *zend_get_user_call_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
10691038
{
1070-
return (union _zend_function *)zend_get_proxy_call_function(ce, method_name, 0);
1039+
return (union _zend_function *)zend_get_proxy_call_func(ce, method_name, 0);
10711040
}
10721041
/* }}} */
10731042

@@ -1198,7 +1167,7 @@ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{
11981167

11991168
static inline union _zend_function *zend_get_user_callstatic_function(zend_class_entry *ce, zend_string *method_name) /* {{{ */
12001169
{
1201-
return (union _zend_function *)zend_get_proxy_call_function(ce, method_name, 1);
1170+
return (union _zend_function *)zend_get_proxy_call_func(ce, method_name, 1);
12021171
}
12031172
/* }}} */
12041173

Zend/zend_objects_API.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "zend.h"
2323
#include "zend_globals.h"
2424
#include "zend_variables.h"
25+
#include "zend_vm.h"
2526
#include "zend_API.h"
2627
#include "zend_objects_API.h"
2728

@@ -224,6 +225,57 @@ ZEND_API zend_object_handlers *zend_get_std_object_handlers(void)
224225
return &std_object_handlers;
225226
}
226227

228+
ZEND_API void zend_init_proxy_call_func(zend_op_array *func, zend_op *opline)
229+
{
230+
func->type = ZEND_USER_FUNCTION;
231+
232+
func->fn_flags = ZEND_ACC_CALL_VIA_HANDLER | ZEND_ACC_PUBLIC;
233+
func->this_var = -1;
234+
235+
opline->opcode = ZEND_PROXY_CALL;
236+
opline->op1_type = IS_UNUSED;
237+
opline->op2_type = IS_UNUSED;
238+
opline->result_type = IS_UNUSED;
239+
240+
ZEND_VM_SET_OPCODE_HANDLER(opline);
241+
242+
func->opcodes = opline;
243+
}
244+
245+
ZEND_API zend_op_array *zend_get_proxy_call_func(zend_class_entry *ce, zend_string *method_name, int is_static)
246+
{
247+
zend_op_array *func;
248+
zend_function *fbc = is_static? ce->__callstatic : ce->__call;
249+
250+
ZEND_ASSERT(fbc);
251+
252+
if (EXPECTED(EG(proxy_call_func).function_name == NULL)) {
253+
func = &EG(proxy_call_func);
254+
} else {
255+
func = ecalloc(1, ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array)) + sizeof(zend_op));
256+
zend_init_proxy_call_func(func, (zend_op *)((char *)func + ZEND_MM_ALIGNED_SIZE(sizeof(zend_op_array))));
257+
}
258+
259+
if (is_static) {
260+
func->fn_flags |= ZEND_ACC_STATIC;
261+
} else {
262+
func->fn_flags &= ~ZEND_ACC_STATIC;
263+
}
264+
265+
func->scope = ce;
266+
func->prototype = fbc;
267+
func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : STR_EMPTY_ALLOC();
268+
func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
269+
func->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0;
270+
if (UNEXPECTED(strlen(method_name->val) != method_name->len)) {
271+
func->function_name = zend_string_init(method_name->val, strlen(method_name->val), 0);
272+
} else {
273+
func->function_name = zend_string_copy(method_name);
274+
}
275+
276+
return func;
277+
}
278+
227279
/*
228280
* Local variables:
229281
* tab-width: 4

Zend/zend_objects_API.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,21 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects
7070
ZEND_API zend_object *zend_object_create_proxy(zval *object, zval *member);
7171

7272
ZEND_API zend_object_handlers *zend_get_std_object_handlers(void);
73+
74+
ZEND_API void zend_init_proxy_call_func(zend_op_array *func, zend_op *opline);
75+
76+
ZEND_API zend_op_array *zend_get_proxy_call_func(zend_class_entry *ce, zend_string *method_name, int is_static);
77+
7378
END_EXTERN_C()
7479

80+
#define zend_free_proxy_call_func(func) do { \
81+
if (((zend_op_array *)func) == &EG(proxy_call_func)) { \
82+
((zend_op_array *)func)->function_name = NULL; \
83+
} else { \
84+
efree(func); \
85+
} \
86+
} while (0)
87+
7588
static zend_always_inline void zend_object_release(zend_object *obj)
7689
{
7790
if (--GC_REFCOUNT(obj) == 0) {

Zend/zend_vm_def.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6940,7 +6940,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
69406940
}
69416941
if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
69426942
zend_string_release(call->func->common.function_name);
6943-
efree(call->func);
6943+
zend_free_proxy_call_func(call->func);
69446944
}
69456945

69466946
EX(call) = call->prev_execute_data;
@@ -7596,7 +7596,7 @@ ZEND_VM_HANDLER(158, ZEND_PROXY_CALL, ANY, ANY)
75967596
i_init_func_execute_data(call, &call->func->op_array,
75977597
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
75987598

7599-
efree(fbc);
7599+
zend_free_proxy_call_func(fbc);
76007600

76017601
ZEND_VM_ENTER();
76027602
} else {
@@ -7618,7 +7618,7 @@ ZEND_VM_HANDLER(158, ZEND_PROXY_CALL, ANY, ANY)
76187618

76197619
execute_data = EG(current_execute_data) = call->prev_execute_data;
76207620

7621-
efree(fbc);
7621+
zend_free_proxy_call_func(fbc);
76227622

76237623
zend_vm_stack_free_args(call);
76247624
zend_vm_stack_free_call_frame(call);

Zend/zend_vm_execute.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,7 +1554,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
15541554
}
15551555
if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
15561556
zend_string_release(call->func->common.function_name);
1557-
efree(call->func);
1557+
zend_free_proxy_call_func(call->func);
15581558
}
15591559

15601560
EX(call) = call->prev_execute_data;
@@ -1810,7 +1810,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PROXY_CALL_SPEC_HANDLER(ZEND_O
18101810
i_init_func_execute_data(call, &call->func->op_array,
18111811
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
18121812

1813-
efree(fbc);
1813+
zend_free_proxy_call_func(fbc);
18141814

18151815
ZEND_VM_ENTER();
18161816
} else {
@@ -1832,7 +1832,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PROXY_CALL_SPEC_HANDLER(ZEND_O
18321832

18331833
execute_data = EG(current_execute_data) = call->prev_execute_data;
18341834

1835-
efree(fbc);
1835+
zend_free_proxy_call_func(fbc);
18361836

18371837
zend_vm_stack_free_args(call);
18381838
zend_vm_stack_free_call_frame(call);

ext/reflection/php_reflection.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2242,7 +2242,7 @@ ZEND_METHOD(reflection_parameter, __construct)
22422242
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
22432243
zend_string_release(fptr->common.function_name);
22442244
}
2245-
efree(fptr);
2245+
zend_free_proxy_call_func(fptr);
22462246
}
22472247
if (is_closure) {
22482248
zval_ptr_dtor(reference);

0 commit comments

Comments
 (0)