Skip to content

Commit 3a78259

Browse files
committed
JIT: Avoid too aggressive loop unrolling
This fixes tests/func/010.phpt failure with tracing JIT on ARM64.
1 parent 591dcdb commit 3a78259

File tree

6 files changed

+79
-41
lines changed

6 files changed

+79
-41
lines changed

Zend/zend_execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3483,7 +3483,7 @@ static zend_always_inline void i_free_compiled_variables(zend_execute_data *exec
34833483
}
34843484
/* }}} */
34853485

3486-
ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
3486+
ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
34873487
{
34883488
i_free_compiled_variables(execute_data);
34893489
}

Zend/zend_execute.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode);
359359
ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data);
360360

361361
ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table);
362-
ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data);
362+
ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *execute_data);
363363
ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num);
364364

365365
zval * ZEND_FASTCALL zend_handle_named_arg(

ext/opcache/jit/zend_jit.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3525,18 +3525,27 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
35253525
if (!zend_jit_label(&dasm_state, jit_return_label)) {
35263526
goto jit_failure;
35273527
}
3528-
for (j = 0 ; j < op_array->last_var; j++) {
3529-
uint32_t info = zend_ssa_cv_info(op_array, ssa, j);
3530-
3531-
if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
3532-
if (!left_frame) {
3533-
left_frame = 1;
3534-
if (!zend_jit_leave_frame(&dasm_state)) {
3528+
if (op_array->last_var > 100) {
3529+
/* To many CVs to unroll */
3530+
if (!zend_jit_free_cvs(&dasm_state)) {
3531+
goto jit_failure;
3532+
}
3533+
left_frame = 1;
3534+
}
3535+
if (!left_frame) {
3536+
for (j = 0 ; j < op_array->last_var; j++) {
3537+
uint32_t info = zend_ssa_cv_info(op_array, ssa, j);
3538+
3539+
if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
3540+
if (!left_frame) {
3541+
left_frame = 1;
3542+
if (!zend_jit_leave_frame(&dasm_state)) {
3543+
goto jit_failure;
3544+
}
3545+
}
3546+
if (!zend_jit_free_cv(&dasm_state, info, j)) {
35353547
goto jit_failure;
3536-
}
3537-
}
3538-
if (!zend_jit_free_cv(&dasm_state, info, j)) {
3539-
goto jit_failure;
3548+
}
35403549
}
35413550
}
35423551
}

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10321,6 +10321,16 @@ static int zend_jit_leave_frame(dasm_State **Dst)
1032110321
return 1;
1032210322
}
1032310323

10324+
static int zend_jit_free_cvs(dasm_State **Dst)
10325+
{
10326+
| // EG(current_execute_data) = EX(prev_execute_data);
10327+
| ldr FCARG1x, EX->prev_execute_data
10328+
| MEM_STORE_64_ZTS str, FCARG1x, executor_globals, current_execute_data, REG0
10329+
| // zend_free_compiled_variables(execute_data);
10330+
| EXT_CALL zend_free_compiled_variables, REG0
10331+
return 1;
10332+
}
10333+
1032410334
static int zend_jit_free_cv(dasm_State **Dst, uint32_t info, uint32_t var)
1032510335
{
1032610336
if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {

ext/opcache/jit/zend_jit_trace.c

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4883,36 +4883,45 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
48834883
op1_info, OP1_REG_ADDR())) {
48844884
goto jit_failure;
48854885
}
4886-
for (j = 0 ; j < op_array->last_var; j++) {
4887-
uint32_t info;
4888-
zend_uchar type;
4889-
4890-
info = zend_ssa_cv_info(op_array, op_array_ssa, j);
4891-
type = STACK_TYPE(stack, j);
4892-
info = zend_jit_trace_type_to_info_ex(type, info);
4893-
if (opline->op1_type == IS_CV
4894-
&& EX_VAR_TO_NUM(opline->op1.var) == j
4895-
&& !(op1_info & (MAY_BE_REF|MAY_BE_OBJECT))) {
4896-
if (JIT_G(current_frame)
4897-
&& TRACE_FRAME_IS_RETURN_VALUE_USED(JIT_G(current_frame))) {
4898-
continue;
4899-
} else {
4900-
info |= MAY_BE_NULL;
4901-
}
4886+
if (op_array->last_var > 100) {
4887+
/* To many CVs to unroll */
4888+
if (!zend_jit_free_cvs(&dasm_state)) {
4889+
goto jit_failure;
49024890
}
4903-
if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
4904-
if (!left_frame) {
4905-
left_frame = 1;
4906-
if (!zend_jit_leave_frame(&dasm_state)) {
4907-
goto jit_failure;
4908-
}
4909-
}
4910-
if (!zend_jit_free_cv(&dasm_state, info, j)) {
4911-
goto jit_failure;
4891+
left_frame = 1;
4892+
}
4893+
if (!left_frame) {
4894+
for (j = 0 ; j < op_array->last_var; j++) {
4895+
uint32_t info;
4896+
zend_uchar type;
4897+
4898+
info = zend_ssa_cv_info(op_array, op_array_ssa, j);
4899+
type = STACK_TYPE(stack, j);
4900+
info = zend_jit_trace_type_to_info_ex(type, info);
4901+
if (opline->op1_type == IS_CV
4902+
&& EX_VAR_TO_NUM(opline->op1.var) == j
4903+
&& !(op1_info & (MAY_BE_REF|MAY_BE_OBJECT))) {
4904+
if (JIT_G(current_frame)
4905+
&& TRACE_FRAME_IS_RETURN_VALUE_USED(JIT_G(current_frame))) {
4906+
continue;
4907+
} else {
4908+
info |= MAY_BE_NULL;
4909+
}
49124910
}
4913-
if (info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_RESOURCE)) {
4914-
if (info & MAY_BE_RC1) {
4915-
may_throw = 1;
4911+
if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
4912+
if (!left_frame) {
4913+
left_frame = 1;
4914+
if (!zend_jit_leave_frame(&dasm_state)) {
4915+
goto jit_failure;
4916+
}
4917+
}
4918+
if (!zend_jit_free_cv(&dasm_state, info, j)) {
4919+
goto jit_failure;
4920+
}
4921+
if (info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_RESOURCE)) {
4922+
if (info & MAY_BE_RC1) {
4923+
may_throw = 1;
4924+
}
49164925
}
49174926
}
49184927
}

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10931,6 +10931,16 @@ static int zend_jit_leave_frame(dasm_State **Dst)
1093110931
return 1;
1093210932
}
1093310933

10934+
static int zend_jit_free_cvs(dasm_State **Dst)
10935+
{
10936+
| // EG(current_execute_data) = EX(prev_execute_data);
10937+
| mov FCARG1a, EX->prev_execute_data
10938+
| MEM_STORE_ZTS aword, executor_globals, current_execute_data, FCARG1a, r0
10939+
| // zend_free_compiled_variables(execute_data);
10940+
| EXT_CALL zend_free_compiled_variables, r0
10941+
return 1;
10942+
}
10943+
1093410944
static int zend_jit_free_cv(dasm_State **Dst, uint32_t info, uint32_t var)
1093510945
{
1093610946
if (info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {

0 commit comments

Comments
 (0)