1
0
mirror of https://github.com/php/php-src.git synced 2026-04-26 17:38:14 +02:00

Optimization of init_func_execute_data()

This commit is contained in:
Dmitry Stogov
2017-12-06 02:53:30 +03:00
parent 9c8ffbf1af
commit d1d1aff4e5
4 changed files with 155 additions and 68 deletions
+85 -40
View File
@@ -2150,12 +2150,70 @@ ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data) /* {
* +----------------------------------------+
*/
static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
static zend_never_inline void zend_copy_extra_args(EXECUTE_DATA_D)
{
zend_op_array *op_array = &EX(func)->op_array;
uint32_t first_extra_arg = op_array->num_args;
uint32_t num_args = EX_NUM_ARGS();
zval *src;
size_t delta;
uint32_t count;
uint32_t type_flags = 0;
if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
opline += first_extra_arg;
#else
EX(opline) += first_extra_arg;
#endif
}
/* move extra args into separate array after all CV and TMP vars */
src = EX_VAR_NUM(num_args - 1);
delta = op_array->last_var + op_array->T - first_extra_arg;
count = num_args - first_extra_arg;
if (EXPECTED(delta != 0)) {
delta *= sizeof(zval);
do {
type_flags |= Z_TYPE_INFO_P(src);
ZVAL_COPY_VALUE((zval*)(((char*)src) + delta), src);
ZVAL_UNDEF(src);
src--;
} while (--count);
} else {
do {
type_flags |= Z_TYPE_INFO_P(src);
src--;
} while (--count);
}
ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
}
static zend_always_inline void zend_init_cvs(uint32_t first, uint32_t last EXECUTE_DATA_DC)
{
if (EXPECTED(first < last)) {
zval *var = EX_VAR_NUM(first);
zval *end = EX_VAR_NUM(last);
do {
ZVAL_UNDEF(var);
var++;
} while (var != end);
}
}
static zend_always_inline void i_init_func_execute_data(zend_op_array *op_array, zval *return_value, zend_bool may_be_trampoline EXECUTE_DATA_DC) /* {{{ */
{
uint32_t first_extra_arg, num_args;
ZEND_ASSERT(EX(func) == (zend_function*)op_array);
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
opline = op_array->opcodes;
#else
EX(opline) = op_array->opcodes;
#endif
EX(call) = NULL;
EX(return_value) = return_value;
@@ -2163,54 +2221,27 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
first_extra_arg = op_array->num_args;
num_args = EX_NUM_ARGS();
if (UNEXPECTED(num_args > first_extra_arg)) {
if (EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
zval *end, *src, *dst;
uint32_t type_flags = 0;
if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
EX(opline) += first_extra_arg;
}
/* move extra args into separate array after all CV and TMP vars */
end = EX_VAR_NUM(first_extra_arg - 1);
src = end + (num_args - first_extra_arg);
dst = src + (op_array->last_var + op_array->T - first_extra_arg);
if (EXPECTED(src != dst)) {
do {
type_flags |= Z_TYPE_INFO_P(src);
ZVAL_COPY_VALUE(dst, src);
ZVAL_UNDEF(src);
src--;
dst--;
} while (src != end);
} else {
do {
type_flags |= Z_TYPE_INFO_P(src);
src--;
} while (src != end);
}
ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
if (!may_be_trampoline || EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
zend_copy_extra_args(EXECUTE_DATA_C);
}
} else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
opline += num_args;
#else
EX(opline) += num_args;
#endif
}
/* Initialize CV variables (skip arguments) */
if (EXPECTED((int)num_args < op_array->last_var)) {
zval *var = EX_VAR_NUM(num_args);
zval *end = EX_VAR_NUM(op_array->last_var);
do {
ZVAL_UNDEF(var);
var++;
} while (var != end);
}
zend_init_cvs(num_args, op_array->last_var EXECUTE_DATA_CC);
EX_LOAD_RUN_TIME_CACHE(op_array);
EG(current_execute_data) = execute_data;
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
EX(opline) = opline;
#endif
}
/* }}} */
@@ -2242,14 +2273,28 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
}
/* }}} */
ZEND_API void zend_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
ZEND_API void zend_init_func_execute_data(zend_execute_data *ex, zend_op_array *op_array, zval *return_value) /* {{{ */
{
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
zend_execute_data *orig_execute_data = execute_data;
const zend_op *orig_opline = opline;
execute_data = ex;
#else
zend_execute_data *execute_data = ex;
#endif
EX(prev_execute_data) = EG(current_execute_data);
if (!op_array->run_time_cache) {
op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
memset(op_array->run_time_cache, 0, op_array->cache_size);
}
i_init_func_execute_data(execute_data, op_array, return_value);
i_init_func_execute_data(op_array, return_value, 1 EXECUTE_DATA_CC);
#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
EX(opline) = opline;
opline = orig_opline;
execute_data = orig_execute_data;
#endif
}
/* }}} */
+20 -8
View File
@@ -3556,9 +3556,11 @@ ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
LOAD_OPLINE();
ZEND_VM_ENTER();
ZEND_VM_ENTER_EX();
}
ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
@@ -3579,9 +3581,11 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
LOAD_OPLINE();
ZEND_VM_ENTER();
ZEND_VM_ENTER_EX();
} else {
zval retval;
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
@@ -3675,11 +3679,15 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
LOAD_OPLINE();
ZEND_VM_ENTER_EX();
} else {
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
}
@@ -7834,10 +7842,14 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
if (UNEXPECTED(!fbc->op_array.run_time_cache)) {
init_func_run_time_cache(&fbc->op_array);
}
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
LOAD_OPLINE();
ZEND_VM_ENTER_EX();
} else {
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
}
+39 -16
View File
@@ -400,12 +400,15 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H
#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()
#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()
#if defined(ZEND_VM_FP_GLOBAL_REG)
# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()
# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()
# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()
# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()
#elif defined(ZEND_VM_IP_GLOBAL_REG)
# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; return 1
# define ZEND_VM_ENTER_EX() return 1
# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX()
# define ZEND_VM_LEAVE() return 2
#else
# define ZEND_VM_ENTER_EX() return 1
# define ZEND_VM_ENTER() return 1
# define ZEND_VM_LEAVE() return 2
#endif
@@ -660,9 +663,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
LOAD_OPLINE();
ZEND_VM_ENTER();
ZEND_VM_ENTER_EX();
}
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -682,9 +687,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
LOAD_OPLINE();
ZEND_VM_ENTER();
ZEND_VM_ENTER_EX();
}
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -705,9 +712,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
LOAD_OPLINE();
ZEND_VM_ENTER();
ZEND_VM_ENTER_EX();
} else {
zval retval;
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
@@ -783,9 +792,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
LOAD_OPLINE();
ZEND_VM_ENTER();
ZEND_VM_ENTER_EX();
} else {
zval retval;
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
@@ -879,11 +890,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
LOAD_OPLINE();
ZEND_VM_ENTER_EX();
} else {
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
}
@@ -1002,11 +1017,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
LOAD_OPLINE();
ZEND_VM_ENTER_EX();
} else {
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
}
@@ -2000,10 +2019,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
if (UNEXPECTED(!fbc->op_array.run_time_cache)) {
init_func_run_time_cache(&fbc->op_array);
}
i_init_func_execute_data(call, &fbc->op_array, ret);
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
LOAD_OPLINE();
ZEND_VM_ENTER_EX();
} else {
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
}
+11 -4
View File
@@ -1675,12 +1675,15 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG)\n");
out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
out($f,"#elif defined(ZEND_VM_IP_GLOBAL_REG)\n");
out($f,"# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; return 1\n");
out($f,"# define ZEND_VM_ENTER_EX() return 1\n");
out($f,"# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX()\n");
out($f,"# define ZEND_VM_LEAVE() return 2\n");
out($f,"#else\n");
out($f,"# define ZEND_VM_ENTER_EX() return 1\n");
out($f,"# define ZEND_VM_ENTER() return 1\n");
out($f,"# define ZEND_VM_LEAVE() return 2\n");
out($f,"#endif\n");
@@ -1719,7 +1722,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n");
out($f,"#define ZEND_VM_RETURN() return\n");
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
out($f,"#define ZEND_VM_LOOP_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
@@ -1755,7 +1759,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
}
out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
out($f,"#define ZEND_VM_RETURN() return\n");
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
out($f,"#define ZEND_VM_LOOP_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
@@ -2658,11 +2663,13 @@ function gen_vm($def, $skel) {
out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
out($f,"#undef ZEND_VM_CONTINUE\n");
out($f,"#undef ZEND_VM_RETURN\n");
out($f,"#undef ZEND_VM_ENTER_EX\n");
out($f,"#undef ZEND_VM_ENTER\n");
out($f,"#undef ZEND_VM_LEAVE\n");
out($f,"#undef ZEND_VM_DISPATCH\n");
out($f,"#define ZEND_VM_CONTINUE() return 0\n");
out($f,"#define ZEND_VM_RETURN() return -1\n");
out($f,"#define ZEND_VM_ENTER_EX() return 1\n");
out($f,"#define ZEND_VM_ENTER() return 1\n");
out($f,"#define ZEND_VM_LEAVE() return 2\n");
out($f,"#define ZEND_VM_INTERRUPT() return zend_interrupt_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");