Merge pull request #9955 from damiendoligez/fix-7813

Fix #7813 (major GC fails to start)
master
Florian Angeletti 2020-11-24 16:20:53 +01:00 committed by GitHub
commit 3d6dc0fa64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 15 deletions

View File

@ -568,6 +568,9 @@ OCaml 4.12.0
- #7538, #9669: Check for misplaced attributes on module aliases
(Leo White, report by Thomas Leonard, review by Florian Angeletti)
- #7813, #9955: make sure the major GC cycle doesn't get stuck in Idle state
(Damien Doligez, report by Anders Fugmann, review by Jacques-Henri Jourdan)
- #7902, #9556: Type-checker infers recursive type, even though -rectypes is
off.
(Jacques Garrigue, report by Francois Pottier, review by Leo White)

View File

@ -603,10 +603,21 @@ cleanup:
CAMLprim value caml_gc_major_slice (value v)
{
value exn = Val_unit;
CAML_EV_BEGIN(EV_EXPLICIT_GC_MAJOR_SLICE);
CAMLassert (Is_long (v));
caml_major_collection_slice (Long_val (v));
if (caml_gc_phase == Phase_idle){
/* We need to start a new major GC cycle. Go through the pending_action
machinery. */
caml_request_major_slice ();
exn = caml_process_pending_actions_exn ();
/* Calls the major GC without passing [v] but the initial slice
ignores this parameter anyway. */
}else{
caml_major_collection_slice (Long_val (v));
}
CAML_EV_END(EV_EXPLICIT_GC_MAJOR_SLICE);
caml_raise_if_exception (exn);
return Val_long (0);
}

View File

@ -460,34 +460,39 @@ extern uintnat caml_instr_alloc_jump;
*/
void caml_gc_dispatch (void)
{
value *trigger = Caml_state->young_trigger; /* save old value of trigger */
CAML_EVENTLOG_DO({
CAML_EV_COUNTER(EV_C_ALLOC_JUMP, caml_instr_alloc_jump);
caml_instr_alloc_jump = 0;
});
if (trigger == Caml_state->young_alloc_start
|| Caml_state->requested_minor_gc) {
if (Caml_state->young_trigger == Caml_state->young_alloc_start){
/* The minor heap is full, we must do a minor collection. */
Caml_state->requested_minor_gc = 1;
}else{
/* The minor heap is half-full, do a major GC slice. */
Caml_state->requested_major_slice = 1;
}
if (caml_gc_phase == Phase_idle){
/* The major GC needs an empty minor heap in order to start a new cycle.
If a major slice was requested, we need to do a minor collection
before we can do the major slice that starts a new major GC cycle.
If a minor collection was requested, we take the opportunity to start
a new major GC cycle.
In either case, we have to do a minor cycle followed by a major slice.
*/
Caml_state->requested_minor_gc = 1;
Caml_state->requested_major_slice = 1;
}
if (Caml_state->requested_minor_gc) {
/* reset the pointers first because the end hooks might allocate */
CAML_EV_BEGIN(EV_MINOR);
Caml_state->requested_minor_gc = 0;
Caml_state->young_trigger = Caml_state->young_alloc_mid;
caml_update_young_limit();
caml_empty_minor_heap ();
/* The minor heap is empty, we can start a major collection. */
CAML_EV_END(EV_MINOR);
if (caml_gc_phase == Phase_idle)
{
CAML_EV_BEGIN(EV_MAJOR);
caml_major_collection_slice (-1);
CAML_EV_END(EV_MAJOR);
}
}
if (trigger != Caml_state->young_alloc_start
|| Caml_state->requested_major_slice) {
/* The minor heap is half-full, do a major GC slice. */
if (Caml_state->requested_major_slice) {
Caml_state->requested_major_slice = 0;
Caml_state->young_trigger = Caml_state->young_alloc_start;
caml_update_young_limit();