Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up GC by prefetching during marking #10195

Merged
merged 11 commits into from
Aug 10, 2021
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ OCaml 4.13.0
platforms without AFL support.
(David Allsopp, review by Xavier Leroy)

- #10195: Speed up GC by prefetching during marking
(Stephen Dolan, review by Xavier Leroy, Guillaume Munch-Maccagnoni,
Jacques-Henri Jourdan and Damien Doligez)

* #10098: Improve command-line parsing in ocamlrun: strictly recognise options,
be more informative for `ocamlrun -I` and support `--` for terminating options
parsing.
Expand Down
23 changes: 15 additions & 8 deletions runtime/caml/major_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,28 @@
#include "freelist.h"
#include "misc.h"

/* An interval of a single object to be scanned.
The end pointer must always be one-past-the-end of a heap block,
but the start pointer is not necessarily the start of the block */
typedef struct {
value* start;
value* end;
} mark_entry;
jhjourdan marked this conversation as resolved.
Show resolved Hide resolved

damiendoligez marked this conversation as resolved.
Show resolved Hide resolved
typedef struct {
void *block; /* address of the malloced block this chunk lives in */
asize_t alloc; /* in bytes, used for compaction */
asize_t size; /* in bytes */
char *next;
value* redarken_start; /* first block in chunk to redarken */
value* redarken_end; /* last block in chunk that needs redarkening */
mark_entry redarken_first; /* first block in chunk to redarken */
value* redarken_end; /* one-past-end of last block for redarkening */
} heap_chunk_head;

#define Chunk_size(c) (((heap_chunk_head *) (c)) [-1]).size
#define Chunk_alloc(c) (((heap_chunk_head *) (c)) [-1]).alloc
#define Chunk_next(c) (((heap_chunk_head *) (c)) [-1]).next
#define Chunk_block(c) (((heap_chunk_head *) (c)) [-1]).block
#define Chunk_redarken_start(c) (((heap_chunk_head *) (c)) [-1]).redarken_start
#define Chunk_redarken_end(c) (((heap_chunk_head *) (c)) [-1]).redarken_end
#define Chunk_head(c) (((heap_chunk_head *) (c)) - 1)
#define Chunk_size(c) Chunk_head(c)->size
#define Chunk_alloc(c) Chunk_head(c)->alloc
#define Chunk_next(c) Chunk_head(c)->next
#define Chunk_block(c) Chunk_head(c)->block

extern int caml_gc_phase;
extern int caml_gc_subphase;
Expand Down
9 changes: 9 additions & 0 deletions runtime/caml/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ CAMLdeprecated_typedef(addr, char *);
#define Noreturn
#endif

/* Manually preventing inlining */
#if defined(__GNUC__)
#define Caml_noinline __attribute__ ((noinline))
#elif defined(_MSC_VER)
#define Caml_noinline __declspec(noinline)
#else
#define Caml_noinline
#endif

/* Export control (to mark primitives and to handle Windows DLL) */

#ifndef CAMLDLLIMPORT
Expand Down