summaryrefslogtreecommitdiff
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/emu/bs_instrs.tab1
-rw-r--r--erts/emulator/beam/emu/instrs.tab1
-rw-r--r--erts/emulator/beam/emu/macros.tab8
-rw-r--r--erts/emulator/beam/erl_gc.c6
-rw-r--r--erts/emulator/beam/jit/x86/beam_asm_global.cpp14
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