diff options
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/emu/bs_instrs.tab | 1 | ||||
-rw-r--r-- | erts/emulator/beam/emu/instrs.tab | 1 | ||||
-rw-r--r-- | erts/emulator/beam/emu/macros.tab | 8 | ||||
-rw-r--r-- | erts/emulator/beam/erl_gc.c | 6 | ||||
-rw-r--r-- | erts/emulator/beam/jit/x86/beam_asm_global.cpp | 14 |
5 files changed, 29 insertions, 1 deletions
diff --git a/erts/emulator/beam/emu/bs_instrs.tab b/erts/emulator/beam/emu/bs_instrs.tab index bfb364c26b..751adfcc43 100644 --- a/erts/emulator/beam/emu/bs_instrs.tab +++ b/erts/emulator/beam/emu/bs_instrs.tab @@ -132,6 +132,7 @@ TEST_BIN_VHEAP(VNh, Nh, Live) { ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); SWAPIN; + $MAYBE_EXIT_AFTER_GC(); } HEAP_SPACE_VERIFIED(need); } diff --git a/erts/emulator/beam/emu/instrs.tab b/erts/emulator/beam/emu/instrs.tab index d86439e570..b677e99002 100644 --- a/erts/emulator/beam/emu/instrs.tab +++ b/erts/emulator/beam/emu/instrs.tab @@ -1108,6 +1108,7 @@ catch_end(Y) { ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); SWAPIN; + $MAYBE_EXIT_AFTER_GC(); } r(0) = TUPLE2(HTOP, am_EXIT, x(2)); HTOP += 3; diff --git a/erts/emulator/beam/emu/macros.tab b/erts/emulator/beam/emu/macros.tab index f7aa49634a..e7816003c7 100644 --- a/erts/emulator/beam/emu/macros.tab +++ b/erts/emulator/beam/emu/macros.tab @@ -74,6 +74,12 @@ GC_SWAPOUT() { c_p->i = I; } +MAYBE_EXIT_AFTER_GC() { + if (ERTS_PSFLG_EXITING & erts_atomic32_read_nob(&c_p->state)) { + goto context_switch3; + } +} + GC_TEST(Ns, Nh, Live) { Uint need = $Nh + $Ns; if (ERTS_UNLIKELY((E - HTOP) < (need + S_RESERVED))) { @@ -83,6 +89,7 @@ GC_TEST(Ns, Nh, Live) { ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); PROCESS_MAIN_CHK_LOCKS(c_p); SWAPIN; + $MAYBE_EXIT_AFTER_GC(); } HEAP_SPACE_VERIFIED($Nh); } @@ -98,6 +105,7 @@ GC_TEST_PRESERVE(NeedHeap, Live, PreserveTerm) { PROCESS_MAIN_CHK_LOCKS(c_p); $PreserveTerm = reg[$Live]; SWAPIN; + $MAYBE_EXIT_AFTER_GC(); } HEAP_SPACE_VERIFIED($NeedHeap); } diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 679d7f3a21..cbcf262d4a 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -454,7 +454,11 @@ erts_gc_after_bif_call_lhf(Process* p, ErlHeapFragment *live_hf_end, val[0] = result; cost = garbage_collect(p, live_hf_end, 0, val, 1, p->fcalls, 0); - result = val[0]; + if (ERTS_PROC_IS_EXITING(p)) { + result = THE_NON_VALUE; + } else { + result = val[0]; + } } BUMP_REDS(p, cost); diff --git a/erts/emulator/beam/jit/x86/beam_asm_global.cpp b/erts/emulator/beam/jit/x86/beam_asm_global.cpp index a65b254bea..a9a1da7621 100644 --- a/erts/emulator/beam/jit/x86/beam_asm_global.cpp +++ b/erts/emulator/beam/jit/x86/beam_asm_global.cpp @@ -120,6 +120,8 @@ void BeamGlobalAssembler::emit_handle_error() { /* ARG3 = (HTOP + bytes needed) !! * ARG4 = Live registers */ void BeamGlobalAssembler::emit_garbage_collect() { + Label exiting = a.newLabel(); + /* Convert ARG3 to words needed and move it to the correct argument slot */ a.sub(ARG3, HTOP); a.shr(ARG3, imm(3)); @@ -140,7 +142,19 @@ void BeamGlobalAssembler::emit_garbage_collect() { emit_leave_runtime<Update::eStack | Update::eHeap>(); +#ifdef WIN32 + a.mov(ARG1d, x86::dword_ptr(c_p, offsetof(Process, state.value))); +#else + a.mov(ARG1d, x86::dword_ptr(c_p, offsetof(Process, state.counter))); +#endif + a.test(ARG1d, imm(ERTS_PSFLG_EXITING)); + a.short_().jne(exiting); + a.ret(); + + a.bind(exiting); + emit_discard_cp(); + a.jmp(labels[do_schedule]); } /* Handles trapping to exports from C code, setting registers up in the same |