diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index a1b8b98baa7..9de9de384e1 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -602,6 +602,8 @@ struct _zend_jit_trace_stack_frame { uint32_t call_level; uint32_t _info; int used_stack; + int old_checked_stack; + int old_peek_checked_stack; zend_jit_trace_stack stack[1]; }; diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index cae233c684e..88ce671b861 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -6603,7 +6603,8 @@ done: op_array_ssa = &jit_extension->func_info.ssa; top = frame; if (frame->prev) { - checked_stack -= frame->used_stack; + checked_stack = frame->old_checked_stack; + peek_checked_stack = frame->old_peek_checked_stack; frame = frame->prev; stack = frame->stack; ZEND_ASSERT(&frame->func->op_array == op_array); @@ -6762,24 +6763,40 @@ done: } } } + call->old_checked_stack = checked_stack; + call->old_peek_checked_stack = peek_checked_stack; if (p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL) { frame->call_level++; - call->used_stack = 0; + call->used_stack = checked_stack = peek_checked_stack = 0; } else { if (p->func) { call->used_stack = zend_vm_calc_used_stack(init_opline->extended_value, (zend_function*)p->func); } else { call->used_stack = (ZEND_CALL_FRAME_SLOT + init_opline->extended_value) * sizeof(zval); } - checked_stack += call->used_stack; - if (checked_stack > peek_checked_stack) { - peek_checked_stack = checked_stack; + switch (init_opline->opcode) { + case ZEND_INIT_FCALL: + case ZEND_INIT_FCALL_BY_NAME: + case ZEND_INIT_NS_FCALL_BY_NAME: + case ZEND_INIT_METHOD_CALL: + case ZEND_INIT_DYNAMIC_CALL: + //case ZEND_INIT_STATIC_METHOD_CALL: + //case ZEND_INIT_USER_CALL: + //case ZEND_NEW: + checked_stack += call->used_stack; + if (checked_stack > peek_checked_stack) { + peek_checked_stack = checked_stack; + } + break; + default: + checked_stack = peek_checked_stack = 0; } } } else if (p->op == ZEND_JIT_TRACE_DO_ICALL) { call = frame->call; if (call) { - checked_stack -= call->used_stack; + checked_stack = call->old_checked_stack; + peek_checked_stack = call->old_peek_checked_stack; top = call; frame->call = call->prev; }