From e3028f6ea7b9d187c4fbdb185454e9ebd0fcb136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Tue, 11 Feb 2025 09:52:37 +0100 Subject: [PATCH] erts: Introduce hibernate/0 and simplify hibernate/3 Co-authored-by: Kiko Fernandez-Reyes --- erts/emulator/beam/beam_common.c | 92 +----- erts/emulator/beam/bif.c | 73 ++++- erts/emulator/beam/emu/ops.tab | 11 +- erts/emulator/beam/emu/trace_instrs.tab | 19 +- erts/emulator/beam/erl_gc.c | 280 ++++++++---------- erts/emulator/beam/global.h | 2 +- erts/emulator/beam/jit/arm/instr_trace.cpp | 19 +- erts/emulator/beam/jit/arm/ops.tab | 8 +- erts/emulator/beam/jit/x86/instr_trace.cpp | 27 +- erts/emulator/beam/jit/x86/ops.tab | 8 +- erts/emulator/test/hello_SUITE_data/hello.erl | 2 +- erts/emulator/test/hibernate_SUITE.erl | 92 +++++- erts/preloaded/ebin/erlang.beam | Bin 40368 -> 40328 bytes erts/preloaded/src/erlang.erl | 20 +- 14 files changed, 345 insertions(+), 308 deletions(-) diff --git a/erts/emulator/beam/beam_common.c b/erts/emulator/beam/beam_common.c index bc25fb280c9c..c37108d1d464 100644 --- a/erts/emulator/beam/beam_common.c +++ b/erts/emulator/beam/beam_common.c @@ -1612,88 +1612,19 @@ fixed_apply(Process* p, Eterm* reg, Uint arity, return ep; } -int -erts_hibernate(Process* c_p, Eterm* reg) -{ - int arity; - Eterm tmp; - Eterm module = reg[0]; - Eterm function = reg[1]; - Eterm args = reg[2]; - - if (is_not_atom(module) || is_not_atom(function)) { - /* - * No need to test args here -- done below. - */ - error: - c_p->freason = BADARG; - - error2: - reg[0] = module; - reg[1] = function; - reg[2] = args; - return 0; - } - - arity = 0; - tmp = args; - while (is_list(tmp)) { - if (arity < MAX_REG) { - tmp = CDR(list_val(tmp)); - arity++; - } else { - c_p->freason = SYSTEM_LIMIT; - goto error2; - } - } - if (is_not_nil(tmp)) { /* Must be well-formed list */ - goto error; - } +void erts_hibernate(Process *c_p, Eterm *regs, int arity) { + const Uint max_default_arg_reg = + sizeof(c_p->def_arg_reg) / sizeof(c_p->def_arg_reg[0]); - /* - * At this point, arguments are known to be good. - */ - - if (c_p->arg_reg != c_p->def_arg_reg) { - /* Save some memory */ - erts_free(ERTS_ALC_T_ARG_REG, c_p->arg_reg); - c_p->arg_reg = c_p->def_arg_reg; - c_p->max_arg_reg = sizeof(c_p->def_arg_reg)/sizeof(c_p->def_arg_reg[0]); + /* Save some memory if possible. */ + if (arity <= max_default_arg_reg && c_p->arg_reg != c_p->def_arg_reg) { + erts_free(ERTS_ALC_T_ARG_REG, c_p->arg_reg); + c_p->max_arg_reg = max_default_arg_reg; + c_p->arg_reg = c_p->def_arg_reg; } -#ifdef USE_VM_PROBES - if (DTRACE_ENABLED(process_hibernate)) { - ErtsCodeMFA cmfa = { module, function, arity}; - DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); - DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); - dtrace_fun_decode(c_p, &cmfa, process_name, mfa_buf); - DTRACE2(process_hibernate, process_name, mfa_buf); - } -#endif - /* - * Arrange for the process to be resumed at the given MFA with - * the stack cleared. - */ - c_p->arity = 3; - c_p->arg_reg[0] = module; - c_p->arg_reg[1] = function; - c_p->arg_reg[2] = args; - c_p->stop = c_p->hend - CP_SIZE; /* Keep first continuation pointer */ - - switch(erts_frame_layout) { - case ERTS_FRAME_LAYOUT_RA: - ASSERT(c_p->stop[0] == make_cp(beam_normal_exit)); - break; - case ERTS_FRAME_LAYOUT_FP_RA: - FRAME_POINTER(c_p) = &c_p->stop[0]; - ASSERT(c_p->stop[0] == make_cp(NULL)); - ASSERT(c_p->stop[1] == make_cp(beam_normal_exit)); - break; - } - - c_p->catches = 0; - c_p->return_trace_frames = 0; - c_p->i = beam_run_process; + sys_memcpy(c_p->arg_reg, regs, arity * sizeof(Eterm)); + c_p->arity = arity; /* * If there are no waiting messages, garbage collect and @@ -1712,10 +1643,9 @@ erts_hibernate(Process* c_p, Eterm* reg) erts_atomic32_read_band_relb(&c_p->state, ~ERTS_PSFLG_ACTIVE); ASSERT(!ERTS_PROC_IS_EXITING(c_p)); } + erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); - c_p->current = &BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa; c_p->flags |= F_HIBERNATE_SCHED; /* Needed also when woken! */ - return 1; } ErtsCodePtr diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 61dfb65ddee0..ef1c968b046e 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -54,6 +54,7 @@ #include "jit/beam_asm.h" #include "erl_global_literals.h" #include "beam_load.h" +#include "beam_common.h" Export *erts_await_result; static Export await_exit_trap; @@ -1189,26 +1190,66 @@ BIF_RETTYPE unlink_1(BIF_ALIST_1) BIF_RETTYPE hibernate_3(BIF_ALIST_3) { - /* - * hibernate/3 is usually translated to an instruction; therefore - * this function is only called when the call could not be translated. - */ - Eterm reg[3]; + Eterm module = BIF_ARG_1, function = BIF_ARG_2, args = BIF_ARG_3; + Uint arity = 0; + + /* Check for obvious errors as a courtesy to the user; while apply/3 will + * fail later on if there's anything wrong with the arguments (e.g. the + * callee does not exist), we have more helpful context now than after + * discarding the stack. */ + if (is_not_atom(module) || is_not_atom(function)) { + BIF_ERROR(BIF_P, BADARG); + } + + while (is_list(args) && arity <= MAX_ARG) { + args = CDR(list_val(args)); + arity++; + } - reg[0] = BIF_ARG_1; - reg[1] = BIF_ARG_2; - reg[2] = BIF_ARG_3; + if (is_not_nil(args)) { + if (arity > MAX_ARG) { + BIF_ERROR(BIF_P, SYSTEM_LIMIT); + } - if (erts_hibernate(BIF_P, reg)) { - /* - * If hibernate succeeded, TRAP. The process will be wait in a - * hibernated state if its state is inactive (!ERTS_PSFLG_ACTIVE); - * otherwise, continue executing (if any message was in the queue). - */ - BIF_TRAP_CODE_PTR(BIF_P, BIF_P->i, 3); + BIF_ERROR(BIF_P, BADARG); } - return THE_NON_VALUE; +#ifdef USE_VM_PROBES + if (DTRACE_ENABLED(process_hibernate)) { + ErtsCodeMFA cmfa = { module, function, arity }; + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); + dtrace_fun_decode(BIF_P, &cmfa, process_name, mfa_buf); + DTRACE2(process_hibernate, process_name, mfa_buf); + } +#endif + + /* Discard our execution state and prepare to resume with apply/3 after + * waking up from hibernation. + * + * Note that BIF_P->current has already been set to hibernate/3 as this is + * a heavy BIF. */ + BIF_P->stop = BIF_P->hend - CP_SIZE; + BIF_P->return_trace_frames = 0; + BIF_P->catches = 0; + + switch(erts_frame_layout) { + case ERTS_FRAME_LAYOUT_RA: + ASSERT(BIF_P->stop[0] == make_cp(beam_normal_exit)); + break; + case ERTS_FRAME_LAYOUT_FP_RA: + FRAME_POINTER(BIF_P) = &BIF_P->stop[0]; + ASSERT(BIF_P->stop[0] == make_cp(NULL)); + ASSERT(BIF_P->stop[1] == make_cp(beam_normal_exit)); + break; + } + + /* Normally, the X register array is filled when trapping out. We do NOT do + * this here as there is special magic involved when trapping out after + * hibernation; `erts_hibernate` populates the process' argument registers + * and then the BIF epilogue jumps straight into do_schedule. */ + erts_hibernate(BIF_P, BIF__ARGS, 3); + BIF_TRAP_CODE_PTR(BIF_P, beam_run_process, 3); } /**********************************************************************/ diff --git a/erts/emulator/beam/emu/ops.tab b/erts/emulator/beam/emu/ops.tab index 3a4ddd35ce3b..93ce0a9cbde6 100644 --- a/erts/emulator/beam/emu/ops.tab +++ b/erts/emulator/beam/emu/ops.tab @@ -879,12 +879,13 @@ call_ext u==0 u$func:erlang:yield/0 => i_yield call_ext_last u==0 u$func:erlang:yield/0 D => i_yield | deallocate_return D call_ext_only u==0 u$func:erlang:yield/0 => i_yield | return + +# The hibernate/0 BIF is an instruction # -# The hibernate/3 BIF is an instruction. -# -call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate -call_ext_last u==3 u$func:erlang:hibernate/3 _D => i_hibernate -call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate + +call_ext u==0 u$func:erlang:hibernate/0 => i_hibernate +call_ext_last u==0 u$func:erlang:hibernate/0 D => i_hibernate | deallocate_return D +call_ext_only u==0 u$func:erlang:hibernate/0 => i_hibernate | return call_ext u==0 u$func:os:perf_counter/0 => i_perf_counter diff --git a/erts/emulator/beam/emu/trace_instrs.tab b/erts/emulator/beam/emu/trace_instrs.tab index 4f109bde602f..3a4b21898e0c 100644 --- a/erts/emulator/beam/emu/trace_instrs.tab +++ b/erts/emulator/beam/emu/trace_instrs.tab @@ -120,16 +120,15 @@ i_yield() { i_hibernate() { HEAVY_SWAPOUT; - if (erts_hibernate(c_p, reg)) { - FCALLS = c_p->fcalls; - c_p->flags &= ~F_HIBERNATE_SCHED; - goto do_schedule; - } else { - HEAVY_SWAPIN; - I = handle_error(c_p, I, reg, &BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa); - goto post_error_handling; - } - //| -no_next + + erts_hibernate(c_p, reg, 0); + + c_p->arg_reg[0] = am_ok; + c_p->arity = 1; + + $SET_CP_I_ABS($NEXT_INSTRUCTION); + c_p->current = NULL; + goto do_schedule; } // This is optimised as an instruction because diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 20585d75f78a..fe78ed9cbae4 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -152,15 +152,17 @@ static int adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj); static void shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj); static void grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj); static void sweep_off_heap(Process *p, int fullsweep); -static void offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_sz); +static void offset_heap(Eterm *hp, Uint sz, Sint offs, const char* area, Uint area_sz); static void offset_stack(Eterm *stack, Uint sz, - Sint heap_offset, Sint stack_offset, - char* area, Uint area_sz); -static void offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_sz); -static void offset_rootset(Process *p, Sint heap_offs, Sint stack_offs, - char* area, Uint area_sz, Eterm* objv, int nobj); -static void offset_off_heap(Process* p, Sint offs, char* area, Uint area_sz); -static void offset_mqueue(Process *p, Sint offs, char* area, Uint area_sz); + Sint heap_offset, const char *heap_area, Uint heap_area_sz, + Sint stack_offset, const char *stack_area, Uint stack_area_sz); +static void offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, const char *area, Uint area_sz); +static void offset_rootset(Process *p, + Sint heap_offs, const char *heap_area, Uint heap_area_sz, + Sint stack_offs, const char *stack_area, Uint stack_area_sz, + Eterm* objv, int nobj); +static void offset_off_heap(Process *p, Sint offs, const char *area, Uint area_sz); +static void offset_mqueue(Process *p, Sint offs, const char *area, Uint area_sz); static int has_reached_max_heap_size(Process *p, Uint total_heap_size); static int reached_max_heap_size(Process *p, Uint total_heap_size, Uint extra_heap_size, Uint extra_old_heap_size); @@ -968,22 +970,18 @@ erts_garbage_collect(Process* p, Uint need, Eterm* objv, int nobj) static int garbage_collect_hibernate(Process* p, int check_long_gc) { - Uint heap_size; - Eterm* heap; - Eterm* htop; - Uint actual_size; - char* area; - Uint area_sz; - Sint offs; - int reds; + Eterm *collection_heap, *collection_htop, *final_heap, *final_stack; + Uint final_size, heap_size, stack_size; + Sint stack_offset, heap_offset; + const char *heap_area, *stack_area; + Uint heap_area_sz, stack_area_sz; - if (p->flags & F_DISABLE_GC) - ERTS_INTERNAL_ERROR("GC disabled"); + ERTS_ASSERT(!(p->flags & F_DISABLE_GC)); if (p->sig_qs.flags & FS_ON_HEAP_MSGQ) { erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ); erts_proc_sig_fetch(p); - erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ); + erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ); } if (ERTS_SCHEDULER_IS_DIRTY(erts_proc_sched_data(p))) { @@ -1004,131 +1002,93 @@ garbage_collect_hibernate(Process* p, int check_long_gc) p->flags = flags; } - /* - * Preliminaries. - */ erts_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC); ErtsGcQuickSanityCheck(p); - /* Only allow one continuation pointer. */ - ASSERT(p->stop == p->hend - CP_SIZE); - - switch (erts_frame_layout) { - case ERTS_FRAME_LAYOUT_RA: - ASSERT(p->stop[0] == make_cp(beam_normal_exit)); - break; - case ERTS_FRAME_LAYOUT_FP_RA: - ASSERT(p->stop[0] == make_cp(NULL)); - ASSERT(p->stop[1] == make_cp(beam_normal_exit)); - ASSERT(FRAME_POINTER(p) == &p->stop[0]); - break; - } - - /* - * Do it. - */ heap_size = p->heap_sz + (p->old_htop - p->old_heap) + p->mbuf_sz; - - /* Reserve place for continuation pointer and redzone */ - heap_size += S_RESERVED; - - heap = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_TMP_HEAP, - sizeof(Eterm)*heap_size); - htop = heap; - - htop = full_sweep_heaps(p, - ERTS_INVALID_HFRAG_PTR, - 1, - heap, - htop, - (char *) p->old_heap, - (char *) p->old_htop - (char *) p->old_heap, - p->arg_reg, - p->arity); + stack_size = STACK_START(p) - STACK_TOP(p); + + /* Allocate a new heap and move all living terms to it. Note that this + * temporary heap does not need to include space for the stack. */ + collection_heap = (Eterm*)ERTS_HEAP_ALLOC(ERTS_ALC_T_TMP_HEAP, + heap_size * sizeof(Eterm)); + collection_htop = full_sweep_heaps(p, + ERTS_INVALID_HFRAG_PTR, + 1, + collection_heap, + collection_heap, + (char*)p->old_heap, + (char*)p->old_htop - (char*)p->old_heap, + p->arg_reg, + p->arity); #ifdef HARDDEBUG disallow_heap_frag_ref_in_heap(p, heap, htop); #endif - erts_deallocate_young_generation(p); + heap_size = collection_htop - collection_heap; + final_size = heap_size + S_RESERVED + stack_size; - p->heap = heap; - p->high_water = htop; - p->htop = htop; - p->hend = p->heap + heap_size; - p->stop = p->hend - CP_SIZE; - p->heap_sz = heap_size; + /* Move the heap to its final destination, compacting it together with the + * stack. + * + * IMPORTANT: We have garbage collected to a temporary heap and then copy + * the result to a newly allocated heap of exact size. + * + * !! This is intentional !! Garbage collecting as usual and then shrinking + * the heap by reallocating it caused serious fragmentation problems when + * large amounts of processes were hibernated. */ + final_heap = ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm) * final_size); + final_stack = &final_heap[final_size - stack_size]; + sys_memcpy(final_heap, collection_heap, heap_size * sizeof(Eterm)); + sys_memcpy(final_stack, p->stop, stack_size * sizeof(Eterm)); - heap_size = actual_size = p->htop - p->heap; + stack_offset = final_stack - p->stop; + heap_offset = final_heap - collection_heap; - /* Reserve place for continuation pointer and redzone */ - heap_size += S_RESERVED; + heap_area = (const char *) collection_heap; + heap_area_sz = heap_size * sizeof(Eterm); - FLAGS(p) &= ~F_FORCE_GC; - p->live_hf_end = ERTS_INVALID_HFRAG_PTR; + stack_area = (const char *) p->stop; + stack_area_sz = stack_size * sizeof(Eterm); - /* - * Move the heap to its final destination. - * - * IMPORTANT: We have garbage collected to a temporary heap and - * then copy the result to a newly allocated heap of exact size. - * This is intentional and important! Garbage collecting as usual - * and then shrinking the heap by reallocating it caused serious - * fragmentation problems when large amounts of processes were - * hibernated. - */ + erts_deallocate_young_generation(p); + erts_free(ERTS_ALC_T_TMP_HEAP, collection_heap); - ASSERT(actual_size < p->heap_sz); + p->heap = final_heap; + p->heap_sz = final_size; + p->high_water = &final_heap[heap_size]; + p->htop = &final_heap[heap_size]; + p->hend = &final_heap[final_size]; + p->stop = final_stack; - heap = ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm)*heap_size); - sys_memcpy((void *) heap, (void *) p->heap, actual_size*sizeof(Eterm)); - ERTS_HEAP_FREE(ERTS_ALC_T_TMP_HEAP, p->heap, p->heap_sz*sizeof(Eterm)); + FLAGS(p) &= ~F_FORCE_GC; + p->live_hf_end = ERTS_INVALID_HFRAG_PTR; - p->hend = heap + heap_size; - p->stop = p->hend - CP_SIZE; - - switch (erts_frame_layout) { - case ERTS_FRAME_LAYOUT_RA: - p->stop[0] = make_cp(beam_normal_exit); - break; - case ERTS_FRAME_LAYOUT_FP_RA: - p->stop[0] = make_cp(NULL); - p->stop[1] = make_cp(beam_normal_exit); - FRAME_POINTER(p) = &p->stop[0]; - break; - } - - offs = heap - p->heap; - area = (char *) p->heap; - area_sz = ((char *) p->htop) - area; - offset_heap(heap, actual_size, offs, area, area_sz); - p->high_water = heap + (p->high_water - p->heap); - offset_rootset(p, offs, 0, area, area_sz, p->arg_reg, p->arity); - p->htop = heap + actual_size; - p->heap = heap; - p->heap_sz = heap_size; + offset_heap(final_heap, heap_size, heap_offset, heap_area, heap_area_sz); + offset_rootset(p, + heap_offset, heap_area, heap_area_sz, + stack_offset, stack_area, stack_area_sz, + p->arg_reg, p->arity); + if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) { + FRAME_POINTER(p) += stack_offset; + } #ifdef CHECK_FOR_HOLES p->last_htop = p->htop; - p->last_mbuf = 0; -#endif + p->last_mbuf = NULL; +#endif #ifdef DEBUG p->last_old_htop = NULL; #endif - /* - * Finishing. - */ - ErtsGcQuickSanityCheck(p); p->flags |= F_HIBERNATED; - erts_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC); - reds = gc_cost(actual_size, actual_size); - return reds; + return gc_cost(final_size, final_size); } void @@ -1243,7 +1203,9 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, offs = temp_lit - literals; offset_heap(temp_lit, lit_size, offs, (char *) literals, byte_lit_size); offset_heap(p->heap, p->htop - p->heap, offs, (char *) literals, byte_lit_size); - offset_rootset(p, offs, 0, (char *) literals, byte_lit_size, + offset_rootset(p, + offs, (char *) literals, byte_lit_size, + 0, NULL, 0, p->arg_reg, p->arity); if (oh) { oh = (struct erl_off_heap_header *) ((Eterm *)(void *) oh + offs); @@ -2801,8 +2763,9 @@ static void resize_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj) Sint heap_offs, stack_offs; Uint heap_used, stack_used; Uint prev_sz; - Uint area_sz; - char* area; + + const char *heap_area, *stack_area; + Uint heap_area_sz, stack_area_sz; prev_heap = HEAP_START(p); prev_sz = HEAP_SIZE(p); @@ -2854,15 +2817,22 @@ static void resize_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj) HEAP_SIZE(p) = new_sz; - area = (char *) prev_heap; - area_sz = prev_sz * sizeof(Eterm); + heap_area = (char *) prev_heap; + heap_area_sz = prev_sz * sizeof(Eterm); + + stack_area = (char *) prev_stack; + stack_area_sz = stack_used * sizeof(Eterm); if (new_heap == prev_heap) { - offset_stack(new_stack, stack_used, heap_offs, stack_offs, - area, area_sz); + offset_stack(new_stack, stack_used, + heap_offs, heap_area, heap_area_sz, + stack_offs, stack_area, stack_area_sz); } else { - offset_heap(new_heap, heap_used, heap_offs, area, area_sz); - offset_rootset(p, heap_offs, stack_offs, area, area_sz, objv, nobj); + offset_heap(new_heap, heap_used, heap_offs, heap_area, heap_area_sz); + offset_rootset(p, + heap_offs, heap_area, heap_area_sz, + stack_offs, stack_area, stack_area_sz, + objv, nobj); } } @@ -3289,7 +3259,7 @@ sweep_off_heap(Process *p, int fullsweep) */ static void -offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size) +offset_heap(Eterm* hp, Uint sz, Sint offs, const char* area, Uint area_size) { while (sz--) { Eterm val = *hp; @@ -3361,12 +3331,12 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size) /* Offset on-stack pointers to stack and heap. */ static void offset_stack(Eterm *stack, Uint sz, - Sint heap_offset, Sint stack_offset, - char* area, Uint area_sz) { + Sint heap_offset, const char *heap_area, Uint heap_area_sz, + Sint stack_offset, const char *stack_area, Uint stack_area_sz) { if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA || stack_offset == 0) { /* No need to update self-references, just update pointers to the * heap. */ - offset_heap_ptr(stack, sz, heap_offset, area, area_sz); + offset_heap_ptr(stack, sz, heap_offset, heap_area, heap_area_sz); } else { Sint i = 0; @@ -3377,7 +3347,7 @@ offset_stack(Eterm *stack, Uint sz, switch (primary_tag(val)) { case TAG_PRIMARY_HEADER: - if (ErtsInArea(val, area, area_sz)) { + if (ErtsInArea(val, stack_area, stack_area_sz)) { stack[i] = offset_ptr(val, stack_offset); } @@ -3385,7 +3355,7 @@ offset_stack(Eterm *stack, Uint sz, break; case TAG_PRIMARY_LIST: case TAG_PRIMARY_BOXED: - if (ErtsInArea(ptr_val(val), area, area_sz)) { + if (ErtsInArea(ptr_val(val), heap_area, heap_area_sz)) { stack[i] = offset_ptr(val, heap_offset); } @@ -3401,7 +3371,7 @@ offset_stack(Eterm *stack, Uint sz, /* Offset pointers to heap from a root set. */ static void -offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_sz) +offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, const char* area, Uint area_sz) { while (sz--) { Eterm val = *hp; @@ -3421,7 +3391,7 @@ offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_sz) } static void -offset_off_heap(Process* p, Sint offs, char* area, Uint area_size) +offset_off_heap(Process* p, Sint offs, const char *area, Uint area_size) { if (MSO(p).first && ErtsInArea((Eterm *)MSO(p).first, area, area_size)) { Eterm** uptr = (Eterm**) (void *) &MSO(p).first; @@ -3446,7 +3416,7 @@ offset_off_heap(Process* p, Sint offs, char* area, Uint area_size) #endif static ERTS_INLINE void -offset_message(ErtsMessage *mp, Sint offs, char* area, Uint area_size) +offset_message(ErtsMessage *mp, Sint offs, const char *area, Uint area_size) { Eterm mesg = ERL_MESSAGE_TERM(mp); if (ERTS_SIG_IS_MSG_TAG(mesg) || ERTS_SIG_IS_HEAP_ALIAS_MSG_TAG(mesg)) { @@ -3485,56 +3455,52 @@ offset_message(ErtsMessage *mp, Sint offs, char* area, Uint area_size) * Offset pointers in message queue. */ static void -offset_mqueue(Process *p, Sint offs, char* area, Uint area_size) +offset_mqueue(Process *p, Sint offs, const char *area, Uint area_size) { if ((p->sig_qs.flags & (FS_OFF_HEAP_MSGQ|FS_OFF_HEAP_MSGQ_CHNG)) != FS_OFF_HEAP_MSGQ) ERTS_FOREACH_SIG_PRIVQS(p, mp, offset_message(mp, offs, area, area_size)); } -static void ERTS_INLINE -offset_one_rootset(Process *p, Sint heap_offs, Sint stack_offs, - char* area, Uint area_sz, Eterm* objv, int nobj) +static void +offset_rootset(Process *p, + Sint heap_offs, const char *heap_area, Uint heap_area_sz, + Sint stack_offs, const char *stack_area, Uint stack_area_sz, + Eterm* objv, int nobj) { Eterm *v; Uint sz; if (p->dictionary) { offset_heap(ERTS_PD_START(p->dictionary), ERTS_PD_SIZE(p->dictionary), - heap_offs, area, area_sz); + heap_offs, heap_area, heap_area_sz); } - offset_heap_ptr(&p->fvalue, 1, heap_offs, area, area_sz); - offset_heap_ptr(&p->ftrace, 1, heap_offs, area, area_sz); - offset_heap_ptr(&p->seq_trace_token, 1, heap_offs, area, area_sz); + offset_heap_ptr(&p->fvalue, 1, heap_offs, heap_area, heap_area_sz); + offset_heap_ptr(&p->ftrace, 1, heap_offs, heap_area, heap_area_sz); + offset_heap_ptr(&p->seq_trace_token, 1, heap_offs, heap_area, heap_area_sz); #ifdef USE_VM_PROBES - offset_heap_ptr(&p->dt_utag, 1, heap_offs, area, area_sz); + offset_heap_ptr(&p->dt_utag, 1, heap_offs, heap_area, heap_area_sz); #endif - offset_heap_ptr(&p->group_leader, 1, heap_offs, area, area_sz); - offset_heap_ptr(&p->parent, 1, heap_offs, area, area_sz); + offset_heap_ptr(&p->group_leader, 1, heap_offs, heap_area, heap_area_sz); + offset_heap_ptr(&p->parent, 1, heap_offs, heap_area, heap_area_sz); if (p->sig_qs.recv_mrk_blk) { offset_heap_ptr(&p->sig_qs.recv_mrk_blk->ref[0], ERTS_RECV_MARKER_BLOCK_SIZE, heap_offs, - area, area_sz); + heap_area, heap_area_sz); } - offset_mqueue(p, heap_offs, area, area_sz); - offset_stack(p->stop, (STACK_START(p) - p->stop), heap_offs, stack_offs, - area, area_sz); + offset_mqueue(p, heap_offs, heap_area, heap_area_sz); + offset_stack(p->stop, (STACK_START(p) - p->stop), + heap_offs, heap_area, heap_area_sz, + stack_offs, stack_area, stack_area_sz); if (nobj > 0) { - offset_heap_ptr(objv, nobj, heap_offs, area, area_sz); + offset_heap_ptr(objv, nobj, heap_offs, heap_area, heap_area_sz); } - offset_off_heap(p, heap_offs, area, area_sz); + offset_off_heap(p, heap_offs, heap_area, heap_area_sz); if (erts_setup_nfunc_rootset(p, &v, &sz)) { - offset_heap_ptr(v, sz, heap_offs, area, area_sz); + offset_heap_ptr(v, sz, heap_offs, heap_area, heap_area_sz); } } -static void -offset_rootset(Process *p, Sint heap_offs, Sint stack_offs, - char* area, Uint area_sz, Eterm* objv, int nobj) -{ - offset_one_rootset(p, heap_offs, stack_offs, area, area_sz, objv, nobj); -} - static void init_gc_info(ErtsGCInfo *gcip) { diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index a46bfaff6a70..7510edd0c056 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1552,7 +1552,7 @@ Uint erts_current_reductions(Process* current, Process *p); int erts_print_system_version(fmtfn_t to, void *arg, Process *c_p); -int erts_hibernate(Process* c_p, Eterm* reg); +void erts_hibernate(Process *c_p, Eterm *regs, int arity); ERTS_GLB_FORCE_INLINE int erts_is_literal(Eterm tptr, Eterm *ptr); diff --git a/erts/emulator/beam/jit/arm/instr_trace.cpp b/erts/emulator/beam/jit/arm/instr_trace.cpp index dbb0939d8156..b8980ea3c838 100644 --- a/erts/emulator/beam/jit/arm/instr_trace.cpp +++ b/erts/emulator/beam/jit/arm/instr_trace.cpp @@ -208,26 +208,19 @@ void BeamModuleAssembler::emit_i_return_to_trace() { } void BeamModuleAssembler::emit_i_hibernate() { - Label error = a.newLabel(); - - emit_enter_runtime(3); + emit_enter_runtime(0); a.mov(ARG1, c_p); load_x_reg_array(ARG2); - runtime_call(); + mov_imm(ARG3, 0); + runtime_call(); - emit_leave_runtime(3); - - a.cbz(ARG1, error); + emit_leave_runtime(0); a.ldr(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags))); a.and_(TMP1, TMP1, imm(~F_HIBERNATE_SCHED)); a.str(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags))); - a.b(resolve_fragment(ga->get_do_schedule(), disp128MB)); - a.bind(error); - emit_raise_exception(&BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa); - mark_unreachable(); + mov_imm(XREG0, am_ok); + fragment_call(ga->get_dispatch_return()); } diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab index 79bfbc9b4c4a..4470d86bbd17 100644 --- a/erts/emulator/beam/jit/arm/ops.tab +++ b/erts/emulator/beam/jit/arm/ops.tab @@ -658,11 +658,11 @@ call_ext_last u==0 u$func:erlang:yield/0 D => i_yield | deallocate D | return call_ext_only u==0 u$func:erlang:yield/0 => i_yield | return # -# The hibernate/3 BIF is an instruction. +# The hibernate/0 BIF is an instruction. # -call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate -call_ext_last u==3 u$func:erlang:hibernate/3 _D => i_hibernate -call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate +call_ext u==0 u$func:erlang:hibernate/0 => i_hibernate +call_ext_last u==0 u$func:erlang:hibernate/0 D => i_hibernate | deallocate D | return +call_ext_only u==0 u$func:erlang:hibernate/0 => i_hibernate | return call_ext u==0 u$func:os:perf_counter/0 => i_perf_counter diff --git a/erts/emulator/beam/jit/x86/instr_trace.cpp b/erts/emulator/beam/jit/x86/instr_trace.cpp index 26cfc5ad5777..6c81ab6b0aba 100644 --- a/erts/emulator/beam/jit/x86/instr_trace.cpp +++ b/erts/emulator/beam/jit/x86/instr_trace.cpp @@ -241,23 +241,28 @@ void BeamModuleAssembler::emit_i_return_to_trace() { } void BeamModuleAssembler::emit_i_hibernate() { - Label error = a.newLabel(); - - emit_enter_runtime(); + emit_enter_runtime(); a.mov(ARG1, c_p); load_x_reg_array(ARG2); - runtime_call(); + mov_imm(ARG3, 0); + runtime_call(); - emit_leave_runtime(); - - a.test(RET, RET); - a.je(error); + emit_leave_runtime(); a.and_(x86::dword_ptr(c_p, offsetof(Process, flags)), imm(~F_HIBERNATE_SCHED)); - a.jmp(resolve_fragment(ga->get_do_schedule())); - a.bind(error); - emit_raise_exception(&BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa); + a.mov(getXRef(0), imm(am_ok)); +#ifdef NATIVE_ERLANG_STACK + fragment_call(resolve_fragment(ga->get_dispatch_return())); +#else + Label next = a.newLabel(); + + a.lea(ARG3, x86::qword_ptr(next)); + a.jmp(resolve_fragment(ga->get_dispatch_return())); + + a.align(AlignMode::kCode, 8); + a.bind(next); +#endif } diff --git a/erts/emulator/beam/jit/x86/ops.tab b/erts/emulator/beam/jit/x86/ops.tab index bd91565bb42f..087325ada0c1 100644 --- a/erts/emulator/beam/jit/x86/ops.tab +++ b/erts/emulator/beam/jit/x86/ops.tab @@ -604,11 +604,11 @@ call_ext_last u==0 u$func:erlang:yield/0 D => i_yield | deallocate D | return call_ext_only u==0 u$func:erlang:yield/0 => i_yield | return # -# The hibernate/3 BIF is an instruction. +# The hibernate/0 BIF is an instruction. # -call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate -call_ext_last u==3 u$func:erlang:hibernate/3 _D => i_hibernate -call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate +call_ext u==0 u$func:erlang:hibernate/0 => i_hibernate +call_ext_last u==0 u$func:erlang:hibernate/0 D => i_hibernate | deallocate D | return +call_ext_only u==0 u$func:erlang:hibernate/0 => i_hibernate | return call_ext u==0 u$func:os:perf_counter/0 => i_perf_counter diff --git a/erts/emulator/test/hello_SUITE_data/hello.erl b/erts/emulator/test/hello_SUITE_data/hello.erl index dc068d46215c..923067f1e392 100644 --- a/erts/emulator/test/hello_SUITE_data/hello.erl +++ b/erts/emulator/test/hello_SUITE_data/hello.erl @@ -1662,7 +1662,7 @@ test_hibernate() -> maximum_hibernate_heap_size(Term) -> %% When hibernating, a few extra words will be allocated to hold the %% continuation pointer as well as scratch space for the interpreter/jit. - erts_debug:flat_size(Term) + 8. + erts_debug:flat_size(Term) + 12. hibernate_wake_up(0, _, _) -> ok; hibernate_wake_up(N, MaxHeapSz, Child) -> diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl index 81b56ba7f84b..e0ad0a78beb2 100644 --- a/erts/emulator/test/hibernate_SUITE.erl +++ b/erts/emulator/test/hibernate_SUITE.erl @@ -25,7 +25,7 @@ -export([all/0, suite/0, basic/1,dynamic_call/1,min_heap_size/1,bad_args/1, messages_in_queue/1,undefined_mfa/1,no_heap/1, - wake_up_and_bif_trap/1]). + wake_up_and_bif_trap/1,in_place/1]). %% Used by test cases. -export([basic_hibernator/1,dynamic_call_hibernator/2,messages_in_queue_restart/2, @@ -37,7 +37,7 @@ suite() -> all() -> [basic, dynamic_call, min_heap_size, bad_args, messages_in_queue, - undefined_mfa, no_heap, wake_up_and_bif_trap]. + undefined_mfa, no_heap, wake_up_and_bif_trap, in_place]. %%% %%% Testing the basic functionality of erlang:hibernate/3. @@ -54,8 +54,9 @@ basic(Config) when is_list(Config) -> maximum_hibernate_heap_size(Term) -> %% When hibernating, a few extra words will be allocated to hold the - %% continuation pointer as well as scratch space for the interpreter/jit. - erts_debug:size(Term) + 8. + %% continuation pointer, optional frame pointer, as well as scratch space + %% for the interpreter/jit. + erts_debug:size(Term) + 12. hibernate_wake_up(0, _, _) -> ok; hibernate_wake_up(N, MaxHeapSz, Child) -> @@ -372,6 +373,89 @@ characters_to_list_trap(Parent) -> unicode:characters_to_list(Bin), Parent ! {ok, self()}. +%% Tests the in-place variant, hibernate/0 +in_place(_Config) -> + in_place_helper("Minimal test", + fun(F) -> F() end, 16), + + in_place_helper("Deep stack test", + fun(F) -> + (fun S(0) -> F(); S(N) -> S(N - 1), ok end)(512) + end, 1100), + + in_place_helper("Heavy data test", + fun(F) -> + Data = lists:seq(1, 1024), + F(), + lists:foreach(fun(_) -> ok end, Data) + end, 2100), + + in_place_helper("Heavy data and stack test", + fun(F) -> + Data = lists:seq(1, 1024), + (fun S(0) -> F(); S(N) -> S(N - 1), ok end)(512), + lists:foreach(fun(_) -> ok end, Data) + end, 3100), + + ok. + +in_place_helper(Description, Fun, Limit) -> + Parent = self(), + Token = make_ref(), + + {Reference, RefMon} = + spawn_opt(fun() -> + Fun(fun() -> + Parent ! {ready, Token}, + receive {done, Token} -> ok end + end) + end, [link, monitor]), + {Hibernator, HibMon} = + spawn_opt(fun() -> + Fun(fun() -> + Parent ! {ready, Token}, + erlang:hibernate(), + Parent ! {awoken, Token}, + receive {done, Token} -> ok end + end) + end, [link, monitor]), + + receive {ready, Token} -> ok end, + [{status, waiting}, {_, RefSize}] = + process_info(Reference, [status, total_heap_size]), + Reference ! {done, Token}, + receive {'DOWN', RefMon, _, _, _} -> ok end, + + receive {ready, Token} -> ok end, + [{status, waiting}, {_, HiberSize}] = + process_info(Hibernator, [status, total_heap_size]), + + %% Sleep a while, we have a small race between the ready message and + %% hibernation. + ct:sleep(1000), + + %% If we did not succeed in hibernating, the hibernator will have sent a + %% message saying it has awoken before we poke it with a done message. + receive + {awoken, Token} -> + ct:fail("Failed to sleep on hibernate/0") + after + 0 -> ok + end, + + Hibernator ! {done, Token}, + receive {awoken, Token} -> ok end, + + receive {'DOWN', HibMon, _, _, _} -> ok end, + + ct:log("~ts~n\tReference size ~p~n\tHibernated size ~p~n", + [Description, RefSize, HiberSize]), + + true = HiberSize < Limit, %Assertion, whitebox. + true = HiberSize =< RefSize, %Assertion. + + ok. + %% %% Misc %% diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam index 66aa14509c50ba38d57cf18c83b016d01756c9c8..f741a3604af5b0a53cc44b882b003fa84db6d1f8 100644 GIT binary patch literal 40328 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
ty}+aaVt?m|s^{|8v*M?_)%B z6!V|u)!(4z-=u2(O|s_S>{@d>`8WTi+W!*f9LU0ORQual^)`pHQ!mchSi*g8qW#Jg zbK72O@|`ddzV{DDO}^Kwe{#gCfAT0UJ++&ed(SGU{-M7I4<2Hu<@T;P^9MNz_%Wqy z>|M&c?20pgWSjZZf2qg6g^8sC|8U6kfAs2~9XLD(R{!iXPz7NgYV-f||1pLBMVMGv z@Q*+}eyy(F?r<620kKvd4pwRPZ-z(8qCG0+p(bTX<@wtV<@sl-KDG~#RGxp>D&-IK z-5&!~%C5@uch)FTWfzUIv-13X56bh8U6tpbtWma?N7Ecra7dB$>CrSFhAf}uK;c0? zphkyrTUlv)Z)^*38L5q}LBgz&?WHT00}@;ki0K?csx{DF9oU+TUVdc>bv{(jfh!Q=T zf!Mv9&u*`7YtsSMS}+gQQml;sK0GW}vfGCz&m)9+gjC>$V!6@%m4RrcqqfqmM?D@K zz5}C~C3d$PC2%v2WNTn$;*lejB%{VKN(L^lMYD`SmBKt~Ks#s2c6PYC`rmAjn^nE$DO zA=qT>n5|g*=0+zv)WCH~sCHk}=g*3cQ><~EGRK-79q;bK9_Tq+sSoIT0wggn`16G{FSO5KQc zmDxrKRxDwY(0NB#P0?V#%ovq0mJQrGO<8T=D!8;M8P$sFEIhpfqgsxt*=XV;97uz? zLA2Ob)x}Ue#RF7z4We7Kj~F;Th!)xE4qJD2if=XT@R{2btH{9p!07?7Vu|%n4*=+_ z?n0<1B-XC4tIa?~z3ENH&Naotlj>))~ z9xYL<$pKtpIjJ|bU?`WQQx#^u(3nlh06dFzlVX*WM=P49;E=SShD&p!Ga%;E_aNre zrI?pN%=cHU{R7eIp7apXRW!LhIa58+Su$W8J%tk{tbqy1&pdA2Iy!MJ`HIkoBabqu5zRjA$*A>)AORGiZz4e?@V`Z zO;zQf%Bqse|EkuFq&1o)%qHv#uqx2ACi8>(&D{Ymbqt#*qSTMC9+trVjUcdR-@QG zd6LmX26~bfm(H(sScmj`lF|8l@+6}*_E4+AP^%d*)OPVCqliQ!jvQUE%Q)M~le7-q z-IKJcW6{Im6z$BloP=4W(Ru6+4XWh1ScI*B&Go$hPh1~nbA7~r<@&Haa9y*D|7*=> z?Qr;iab*`Ir3XQ6c4?0k=2F>nx?&v_i!S6g*zx|2?G%@o%LX(-EdqeiV^Yp+ zaxx>$?9M?zYvIms^+b<020`;S4-kQ)|3^y4u=O}rm{G|#EW>enw9dD?)jpmbs}|d6 z%QqXXjnG_~(M7P#4T{ykws;Y$Cz*z$Z+#YP(5?gwkcah$mZQGJP*fwid+ZJKzUFxdA3!Rk%Ug&hp z?l)y_+myAVS~Dg`m+@|igWO_-g4bK!8DD9n?v(Rr3)wF?uQLi~9EdC9_D&S^V@iER}AJdofe3-c6)PZB2f zIQa9tip5J7Chu{umJ1Vm9Q=gTD};#+4r+yBogz%R!(joyQ>&w=Ik1sRu0zh*=GaG% zo~~G@?M3yj6lNEQjn)XIug?q>Au_z5fdPWlGQu|+>wV!oi-xQ>Om2A8-g?T25AA>5cMo`_}Piz%L z&*D()>U2GNt{wNV&O+QHdUi^??=kLSoz27U9ATa%X`)K!?mkcT@9Xoy?TribZ20@L zBeRDMR;#c+Vaq~%$1L^ylv>)c#csCkxSeMU_jwTR^9Bg_uA$Cow=LQi>>}E;cerge ziq*Y`S?YPa&Qi~3(Y_!lc?n^jgTDS9eSKl-U4!UFSa}xax#+2bk~aAwX_I@n7JIbG zJ=|JY{)wZt@IJA133`B?7Jhk>d!QR_gtuVRCr2+wZ>`CVUgju|UJ5z5v|kP!f#{{l zm5t~XigjsTbd6$NM)LP^xw2th5r|%ye6zy3a?cAFmJsH7k_+_NRlDsJGtckm;yTc~ zIyZVPxVQ#fTr-f1Yf@aSRjh0BqE{={wIqM9V=mT0*{+k@Afng9RqTbU*sEB*tcS1P zZA;iLDtDdSYcjwS>z_(P(r*yv1>oF^_PcSX_7i3Tondn0tq0pT*dTXljZrw}c-6qTn!NNGm!|gkEWC-&jEZ5ED^7~N! z9l6oFQ2w1L|IUHs-W2f)Go;Nbp&9NeGc;337jKQDTpVm(0e_d(|1p+NLu zsh;Zx&MbCO%jk!Pxho$L<|Saqhu(N}r{0izDijQmHQ?wF=4c~0dMr2k1UPye96dge zqsLPmJ*ila=S3e=tS3nRZe)(0TpNALfhjkXAg|b2Pwk~+o)+e%k{dM6GrKp=W&NzY z09KyOjXn=no&zh-4P@oH6f2t)>$$w>vx@aR$=?^4l}&4-FZQz{eToP8X=yI@w zH}9>N2Fl45kds5XO*Vs(mvf`9f{|Ci$SVUGc_qcjYl`(sUi4+fdX?nwW@hBIK=gIl zOUYe2avs`0%|~av&I0s?Ft3yh0C;n!-Vvt2SgB?n-T@D9cQFOhfIz!*1>VSLx-(9>4Ao=AG!Md4cGUPzv~Hh%oPh@EnGQmoG0yqCY^dey>>H z8|gm&J_izDH@aGbB7eXR0Qs7y-02 zihICy3F`QtK=fyiVsA3VF8o>Ob-9Jq`dNNa!+`+8FZt15JR?)^ufn_+IZM$DzvK4@gtu ziZCC9%eO#@Bk2E-1l>y9p(n7$X+8`lj!@$1duAd&SeTE%y0>|iIPc3eAC;XKA0o`h z0Jj3>eVOLt3=b9N6Ci&e$U9TMKw_9MH>SH2_^JvztqesziB3BbNXT{#;=|w?Br>FH zfRo4hX0y-vrV>XhA{1!vrW-hV<1S%7g+j_v_VBXANVq?s`82+)k?C+ubtLfrWca5f za-5xsEdSJm+dnNaLWz$s8sO!{-T2&#Ix>-)Ybc5AafwVNo@s>SgDm?&9zO^rfOw2q z@q-Q7h3B zV{1#)T)dT=Yn1qu_*nTafKjl(D6QO3;@g0=BZn+=Fmj>Z^EZ1#w+phFg&r+#F&^{Z^IH*4AEfTa1(Rv1DZ-4p9V5z;m!t+u^K)7 zqHMj2f*LgBU-7O=FM2dL6H5r*`}{N8Y75Y+x!!t!WHeM7rQEcr6T7*xk~K6LAii8)6PMz66t+h~+C4PF zCRuU~j(QwB6^aVlg`$FmQ)P*=la$1Mp@gQywPgDu&bFD0myPC-jXbb;-)v)+UE9}o zE8c5x@v|!Vi%tvVdn2f7f06qo3qV`GKA?bsZHb`uIGg$#JGJFb4JoTNF4b=X%RpQD zlVzM3OpIBL_N-lv&F_gZ3_n>*TBi3cjMJ`_kylF}l} zP%tJZRg~2D0*RpPcg8S0g6`fPZu1g+qDQv5LnV9#N~L&alvc46NCSkt47m+pWLL?jWQ`O%^Y>P3-90r%I3-fQ#3A5ZvJk+meCkyi( zXw}lBR-L>wJEcM8E@kswdzW&&M40a(FWz8`mj)91vv%4)`KpBZetKG>!WakNWGS3l z6>EU<8&e6X&<_yi2QnWz;=r;*xnq{2a>3ff0hJgHfkauYPe0ME*Hl#2^WgVSmrYbA z%)iSo9{F^%kK5t))*~idBExSB5DZW=7wl7?n5x9fOA`mkacBK9V_&(2kPR(UcqTu>dqMH?A`Rk@#4m(m19&&_zd~sg0dJIEIuS`4KSl z6Nu654cU&p@WaFl98wRZh{xStVSXwfxNF?f)k)8;^5An@m_Nm#3O++?&rVa~6*7bD zfl6V14y?+n#1VY|LiU|Q9VH(I5>+tJ{(}r>r%YId;~-&T$EzQoiHXlCOPG!u9G=pI zS?k%1XC`*w@8eAzti%yb-zrmqj`g!wfd&Bddd!UPPl{b)WO9WG4lqxB!0roEf2nSDA#xnyR)g3d+P{EVQsFQvD;zZoDjfBV6^=Got*+G- z_~x8kyYyE(>9Bj`;PrvNmYZqx8fvj{c#2v|X`nd#+fm zU9r??m$MyzjzjceVQYF~p%SmPg-e*V_V`2oB%DDmTxyd3{O^1`v~c->yS)p}uK>$CqzNJ>LlVvz&W zI(#37gNJz2-~36|UyhFgtV0%Ha2P&(g)Y&s``}nqny8mj*(gkGn)V+Bf=%!(TXNMb z|NKPMUz2F|AC_3=pO;wbuTDgq4<#)Bg2WR4;fclmBNAaH9)|xV2`sKaQ8+JwFDB0x z+%I{KRN(zuoR?O3y5xCTg{MuPn=3qAaJ0fxBkx<-^)<0qTSZT{3KN^P{rDPAysaz| zgAT?kIEi-O6dd?Ii~Md&qCHo2`xhoo^dF7mn8bb>UPo>;u;;Ha?ef+gPPmj;z)(t76C32{?De-pu1aGf3IXn?7{uKwR9(zOE2+cJ#mr}KS^>Y%L^oym-y>!^@_64E5D%&+7PpVpXiZ6 z42(8C-Tv}m{A8KU&VtMiyZq%ibt>@{rHPIt8;Cdm4mRq+#;Nw~3n~IC054*he}H^v zMLNFzldgj=>AjvV`C6$bPE+Eip+s23Ka*8PGk}M*65Ogsm*5>}+({m{^K*Q?P=3i! zJ-W8Ui?^R0?mjQRd?U>Zd<6p^#(|UM@XASGe5Ir!th6NE60VuBl$C>Z_?d`?o(d)pu~-mE!!Y z-6*@3F)$C`(+(g|AH{d|p2` zcIj}^rSuESgWB{!pGdFFo45dWA^}ntDDewR6Xz#MT_mh*kcxm*Pg&w(NvfngaS?RH zMR-RN&PfS~;Vnq8E@LcKPP(4x>ZjQQnirQQE=m%+L|7w1Y$*hAO>RMK#tONszYdrqeWbq~V^eftG6v{qT*1_NEiM!px z8jZ$VgSilT1K+=hUt_ngu*U3+Ut5|GDC0UDYlXG1U9-{NMCJw4;*Fm7$$alVjY_Bro6JjagzFWXCT9zYd*q0_T~FMm#BZypOoRV_&uV{1MWq}4Fk$83 zuHM?l9*?J@QmUbed>`xa`P_Z=Jh-9ep^^~?=xLKGXMr4=w<_`5B_+^UGj%lzQ1kqq ziMwGa`}`**?((0UxYNHJ$BM)q{!?&16~}2fR^m7v#~Fz}C4Psn3Re#9l}db#XQ$Gj zN<2GCx)aVLIMq0)uVOVGJj@TyNPq}+J@JgkU8Bp1i3jr%pM3sIS>idVpexrVo<+#d zt^4E9&I<|?&w3VMbFg%){PF(O&q@~z+jp^<&YB8s^|W-U)9p_&$Db=rJYVbUb=P}$ zGz90whOM2o(CH`Vr;sqY!usV$x zez8E}ud&7qz0FvVZpZg99;G>Att&sDXH92*Fk?mavQa%52a*PF6RQ4Kf8vG476h648 zX$wHTazSbe59%{_rT$83;)SHbeN|Wnn&3QewKH!2$M3)1fEcL9)LIYc_Hu!0tPN#Je7azv;-Hfc#d6oSvYE-yO)g z5`Ql@@d5aLAAG;RW9=&i=z+xhsY+DIN@QnBN7q-8&MtJX4|+kWc}GRMTl&=d$MT+QNszGO^@<<*zueb6Im4 z{zzB{BlSgqd7aBTgyBzwbtvE-z`V|7RWtmVu;u~27%;DMS%)$Fg|Oti5cmXGoY%Rm z`3!Fr*5QDqufpqG)&hpV78bV7`!5B|>s;2641Xi6qrhMxnwrlI-w1$-r7{;Y?!jA3MJ28=I?uIJBsSp1Ek^@D}g0$2d%M_QykV_mI7e8g173^N{NWAj42E-s z)djd0a9(Q3*pY1&+<~3@@@oLXT7_lwApG@6LHQl|(%MbABOl{EJ&My{YU!0`6R=l3URgg* zSZ5*aji5Px`W@rse`>s-qx}f^f1}Kew&9%KjLQ>n$p2b6J$aVbLvYCd_E%mH#UZoG zYXsr?aaZzM{$DF22H@GamTBdYJK#DG*D0F$1FpRTt_ufT%m3V1rkC_fain;dj_VYC z1J|iEwF7W@ox+d9bt-fsPu1{jJEDJ{}ue?s>U6#aU-cB6yPo_Vauk7nH zaV_)8G^Z!eGR=A%@=soG;43@Lt+)&Rd(jlQB`*we{Ysd2oO>cT;dWI zEiPCUMXica1W|FTTNQ11FL{Kp%!Ene5U~Y}RxK_lqKM#9@$`6*LqX!MpomscP*aLj ztzhj!tJP{1QLFuY@BChfo}-@LneY33<~P6ld-vV@yEpoWj$)ReIFIH(=H;-)qnH)u z7xOzeo&LvQ<#`gVG*--76!-0bl~eu=D88>aj@e}V2KG&3#dRIqX?%|R>gS;?r{AS! z{J2hta~#j-`Yt)e$|H&6T6`I{c)!;UzhB;k<+u59F=;;QUW$qP>N(}d`l?UM@5?Wi zKW6n+-O_yO)UOnn&c?>~0^|JNK0Ey07skrDx5bF7;CO!e!OAIrf2_^9KcEW_>=GkZ zU)I7uq{wb;hgyts-Gs>FAC9zN@O3hM9S_B?uM{IzKgDTolwUl&3y3^X~*NFxLHV zH)g%#v8Oqwd>ebZ44!X!O5xiqz67@CNK*s;Jo9U=ZZ%f7TZ)|e5^LvHN^5L;H}x58 zXItu1;^$iYC)g_E|6uKGOMPg5<|y@n`NjXD@68tfEq55uPzpJ&X+6m{>P4Cr2G!mOcV_P>9; z#Z#C55ys59m$Mk=+-o$}oDYRHhNLkcQ+#$cOa3JD9M^C1b9hLxZ*m)a5KO-$^X3mO z=1FSa4zw7}+W{7%dE4J&G;jMEYu*M~yynf;CCR+``&!Iq*yb>)c^hc)zc*&Q$rs@P z_%)tqj5Yqp;r`}d0r!Iye?O)QR?H&U&W0ql=~#ZPvuaE6ted|lto&CQE2a&f&LPE2 z!|3s!(_o&{uX1UYJztG#8cqDfMQrHcm8n>BqQS#e37xnpn9kvUSps}9INjL zSZA>MvJUY%on-Fgb2_Pg^DLe=U?Vb(ZAGK z<5|M@>|vK@G4?^@`>%Gc+U%DBv+>#3w~)qg7M3%}#hiiNgfzFKu&*In zVkDQbNO?}gZba&Pg0VhUbJ>98KgL+`Lyh&-VO%}MDA z4wn7w_;u`~h~{gp9&zaTT9b$6|CTV|H4=?m%$p7{Fh?qAeujwON)T_CC2*L%!PG!@p)s#G{SlwJ!95b zIVZt4nty_^{NrIgv-*z1-hkwU$yf8l;$? zVzuXK{&`$9Uo`(5E>}79{GVVocZxp~t8-9%I#%;29*u1?J_UO@(!GWoE9Mw@CKCS` zJHz-$>~!OySk1d)4#VmU6(5S#8i)_ZPBT6TtM!ooKx`}0efP&|ZS?Geuv!nA`)8si z0q+4=t&O-Jc8c-dSgn)%dt!6Ol~}Era_)xJ`77Q9tMyZSAM8Y=G4wW;zn3w_{SDW; zDkhB;)7;<8dI4|bX}x8?GRC;SZxL4h&yiSdJ5o)kZA0fH^1HKKtoSWRto9btdNY3a z@5bk174tgM+KV@#vyt*_M5+V%H=whS{2j*fzk*aB@~=0R|0Q$=60b$78^!31JPpaO zb5S)U{~BZYSEEyr{7)g(mUyMHVswUeLwc6Sj1}{Uv0@%VCnIsYF~*%$qpfku)jm{Ai?L#w(2tOK3fkE?ht*z{U;AdTvG$7gt^5t>0HmDS2V(hEJbT5rvteBlp8B$CI${_i5 zAF=%Uz68l%iqc4VVxRmeB&+zu=!WKV2-Cc(>3&1nCUNEeepDzc{#3Mn8@gGpLP_x# zr3<~H{G^&F&rg86h^7gAdve?O0m0G1KEa;BZb9FmPtZHqDfj`eilCQ!l?QtD?0oeI zy1u#xov%1qC7pZXE(^NxD&>{2S4r^oS33CC7sI}ck!3X-u9bpK=d}O2m#JPFP=K0RHp@*^HN7v2eoZP3;PuQTgha-wsl*_cMhH4t%h8mmw&@mddKfpE&e9m$v%F zJJ-w~k|x1DLGtizN8`F~0~8u{U)6v8+JP=~Y-as&PrjSP`%ug7bH*+IvV>l0 z6)R^#cfa@Iy2__J)W4##z90XU3;4As@cNDNk5d0B6Nj}g_O`k?sMvYeXUoTCNKkX{ zvdrcaFSMjQ1{7TU(ZSE%@PK?*AG;{HXgj^fG|p}QFmb-p$1?~lXZ}NZ!p!n3SBI*< zFtN4#%`iEC5mdkOq~f=U*&B}!(;si~LVv#tR)>lHtGqDzL?H@GMopU$dP~;b9jazS zzwwM9Oq6_49VT9SV|$oA(@-XA}l z82Tj(=zHY$C83{xesk!rclXKaI=3HLBp5{yOBlHvH80Z`cch>BP zEcD3cYIE6aRI8a&-03c^jJelfl2P`OLORGdG`AK~* has_prepared_code_on_load(_PreparedCode) -> erlang:nif_error(undefined). +%% hibernate/0 +-doc """ +Puts the calling process into a wait state where its memory allocation has been +reduced as much as possible. This is useful if the process does not expect to +receive any messages soon. + +The process is awakened when a message is sent to it, and control resumes +normally to the caller. Unlike `erlang:hibernate/3`, it does not discard the +call stack. +""". +-doc #{ since => <<"OTP @OTP-19503@">> }. +-doc #{ category => processes }. +-spec hibernate() -> ok. +hibernate() -> + %% This function is a fallback used on apply/3; the loader turns this + %% remote call of ourselves into a special instruction. + erlang:hibernate(). + %% hibernate/3 -doc """ Puts the calling process into a wait state where its memory allocation has been