[Git][ghc/ghc][wip/gc/misc-rts] 7 commits: rts/GC: Add an obvious assertion during block initialization
Ben Gamari
gitlab at gitlab.haskell.org
Wed Jun 19 18:28:02 UTC 2019
Ben Gamari pushed to branch wip/gc/misc-rts at Glasgow Haskell Compiler / GHC
Commits:
673a0e41 by Ömer Sinan Ağacan at 2019-06-19T18:17:47Z
rts/GC: Add an obvious assertion during block initialization
Namely ensure that block descriptors are initialized with valid
generation numbers.
Co-Authored-By: Ben Gamari <ben at well-typed.com>
- - - - -
1baa6967 by Ben Gamari at 2019-06-19T18:17:48Z
rts: Add Note explaining applicability of selector optimisation depth limit
This was slightly non-obvious so a note seems deserved.
- - - - -
4c866b4f by Ben Gamari at 2019-06-19T18:17:48Z
rts/Capability: A few documentation comments
- - - - -
d930ba9b by Ben Gamari at 2019-06-19T18:17:48Z
rts: Give stack flags proper macros
This were previously quite unclear and will change a bit under the
non-moving collector so let's clear this up now.
- - - - -
5f8f04b7 by Ben Gamari at 2019-06-19T18:17:48Z
rts/GC: Refactor gcCAFs
- - - - -
c8ee5c5f by Ben Gamari at 2019-06-19T18:17:48Z
rts: Fix macro parenthesisation
- - - - -
4f65be60 by Ben Gamari at 2019-06-19T18:17:48Z
rts: Fix CPP linter issues
- - - - -
14 changed files:
- includes/Rts.h
- includes/rts/Flags.h
- includes/rts/storage/GC.h
- includes/rts/storage/InfoTables.h
- includes/rts/storage/TSO.h
- rts/Capability.c
- rts/Capability.h
- rts/PrimOps.cmm
- rts/Threads.c
- rts/sm/Evac.c
- rts/sm/GC.c
- rts/sm/Sanity.c
- rts/sm/Storage.c
- utils/deriveConstants/Main.hs
Changes:
=====================================
includes/Rts.h
=====================================
@@ -273,26 +273,27 @@ TICK_VAR(2)
#define IF_RTSFLAGS(c,s) if (RtsFlags.c) { s; } doNothing()
#if defined(DEBUG)
+/* See Note [RtsFlags is a pointer in STG code] */
#if IN_STG_CODE
#define IF_DEBUG(c,s) if (RtsFlags[0].DebugFlags.c) { s; } doNothing()
#else
#define IF_DEBUG(c,s) if (RtsFlags.DebugFlags.c) { s; } doNothing()
-#endif
+#endif /* IN_STG_CODE */
#else
#define IF_DEBUG(c,s) doNothing()
-#endif
+#endif /* DEBUG */
#if defined(DEBUG)
#define DEBUG_ONLY(s) s
#else
#define DEBUG_ONLY(s) doNothing()
-#endif
+#endif /* DEBUG */
#if defined(DEBUG)
#define DEBUG_IS_ON 1
#else
#define DEBUG_IS_ON 0
-#endif
+#endif /* DEBUG */
/* -----------------------------------------------------------------------------
Useful macros and inline functions
=====================================
includes/rts/Flags.h
=====================================
@@ -267,7 +267,11 @@ typedef struct _RTS_FLAGS {
#if defined(COMPILING_RTS_MAIN)
extern DLLIMPORT RTS_FLAGS RtsFlags;
#elif IN_STG_CODE
-/* Hack because the C code generator can't generate '&label'. */
+/* Note [RtsFlags is a pointer in STG code]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * When compiling with IN_STG_CODE the RtsFlags symbol is defined as a pointer.
+ * This is necessary because the C code generator can't generate '&label'.
+ */
extern RTS_FLAGS RtsFlags[];
#else
extern RTS_FLAGS RtsFlags;
=====================================
includes/rts/storage/GC.h
=====================================
@@ -240,9 +240,17 @@ void dirty_MUT_VAR(StgRegTable *reg, StgClosure *p);
/* (needed when dynamic libraries are used). */
extern bool keepCAFs;
+#include "rts/Flags.h"
+
INLINE_HEADER void initBdescr(bdescr *bd, generation *gen, generation *dest)
{
bd->gen = gen;
bd->gen_no = gen->no;
bd->dest_no = dest->no;
+
+#if !IN_STG_CODE
+ /* See Note [RtsFlags is a pointer in STG code] */
+ ASSERT(gen->no < RtsFlags.GcFlags.generations);
+ ASSERT(dest->no < RtsFlags.GcFlags.generations);
+#endif
}
=====================================
includes/rts/storage/InfoTables.h
=====================================
@@ -355,7 +355,7 @@ typedef struct StgConInfoTable_ {
*/
#if defined(TABLES_NEXT_TO_CODE)
#define GET_CON_DESC(info) \
- ((const char *)((StgWord)((info)+1) + (info->con_desc)))
+ ((const char *)((StgWord)((info)+1) + ((info)->con_desc)))
#else
#define GET_CON_DESC(info) ((const char *)(info)->con_desc)
#endif
=====================================
includes/rts/storage/TSO.h
=====================================
@@ -185,6 +185,11 @@ typedef struct StgTSO_ {
} *StgTSOPtr; // StgTSO defined in rts/Types.h
+
+#define STACK_DIRTY 1
+// used by sanity checker to verify that all dirty stacks are on the mutable list
+#define STACK_SANE 64
+
typedef struct StgStack_ {
StgHeader header;
StgWord32 stack_size; // stack size in *words*
=====================================
rts/Capability.c
=====================================
@@ -748,6 +748,8 @@ static Capability * waitForReturnCapability (Task *task)
* result of the external call back to the Haskell thread that
* made it.
*
+ * pCap is strictly an output.
+ *
* ------------------------------------------------------------------------- */
void waitForCapability (Capability **pCap, Task *task)
@@ -840,9 +842,12 @@ void waitForCapability (Capability **pCap, Task *task)
* SYNC_GC_PAR), either to do a sequential GC, forkProcess, or
* setNumCapabilities. We should give up the Capability temporarily.
*
+ * When yieldCapability returns *pCap will have been updated to the new
+ * capability held by the caller.
+ *
* ------------------------------------------------------------------------- */
-#if defined (THREADED_RTS)
+#if defined(THREADED_RTS)
/* See Note [GC livelock] in Schedule.c for why we have gcAllowed
and return the bool */
@@ -948,7 +953,7 @@ yieldCapability (Capability** pCap, Task *task, bool gcAllowed)
* get every Capability into the GC.
* ------------------------------------------------------------------------- */
-#if defined (THREADED_RTS)
+#if defined(THREADED_RTS)
void
prodCapability (Capability *cap, Task *task)
@@ -970,7 +975,7 @@ prodCapability (Capability *cap, Task *task)
*
* ------------------------------------------------------------------------- */
-#if defined (THREADED_RTS)
+#if defined(THREADED_RTS)
bool
tryGrabCapability (Capability *cap, Task *task)
=====================================
rts/Capability.h
=====================================
@@ -160,7 +160,7 @@ struct Capability_ {
} // typedef Capability is defined in RtsAPI.h
// We never want a Capability to overlap a cache line with anything
// else, so round it up to a cache line size:
-#ifndef mingw32_HOST_OS
+#if !defined(mingw32_HOST_OS)
ATTRIBUTE_ALIGNED(64)
#endif
;
=====================================
rts/PrimOps.cmm
=====================================
@@ -1720,7 +1720,7 @@ loop:
// indicate that the MVar operation has now completed.
StgTSO__link(tso) = stg_END_TSO_QUEUE_closure;
- if (TO_W_(StgStack_dirty(stack)) == 0) {
+ if ((TO_W_(StgStack_dirty(stack)) & STACK_DIRTY) == 0) {
ccall dirty_STACK(MyCapability() "ptr", stack "ptr");
}
@@ -1801,7 +1801,7 @@ loop:
// indicate that the MVar operation has now completed.
StgTSO__link(tso) = stg_END_TSO_QUEUE_closure;
- if (TO_W_(StgStack_dirty(stack)) == 0) {
+ if ((TO_W_(StgStack_dirty(stack)) & STACK_DIRTY) == 0) {
ccall dirty_STACK(MyCapability() "ptr", stack "ptr");
}
=====================================
rts/Threads.c
=====================================
@@ -85,7 +85,7 @@ createThread(Capability *cap, W_ size)
SET_HDR(stack, &stg_STACK_info, cap->r.rCCCS);
stack->stack_size = stack_size - sizeofW(StgStack);
stack->sp = stack->stack + stack->stack_size;
- stack->dirty = 1;
+ stack->dirty = STACK_DIRTY;
tso = (StgTSO *)allocate(cap, sizeofW(StgTSO));
TICK_ALLOC_TSO();
@@ -788,7 +788,7 @@ loop:
// indicate that the MVar operation has now completed.
tso->_link = (StgTSO*)&stg_END_TSO_QUEUE_closure;
- if (stack->dirty == 0) {
+ if ((stack->dirty & STACK_DIRTY) == 0) {
dirty_STACK(cap, stack);
}
=====================================
rts/sm/Evac.c
=====================================
@@ -39,7 +39,19 @@
copy_tag(p, info, src, size, stp, tag)
#endif
-/* Used to avoid long recursion due to selector thunks
+/* Note [Selector optimisation depth limit]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * MAX_THUNK_SELECTOR_DEPTH is used to avoid long recursion of
+ * eval_thunk_selector due to nested selector thunks. Note that this *only*
+ * counts nested selector thunks, e.g. `fst (fst (... (fst x)))`. The collector
+ * will traverse interleaved selector-constructor pairs without limit, e.g.
+ *
+ * a = (fst b, _)
+ * b = (fst c, _)
+ * c = (fst d, _)
+ * d = (x, _)
+ *
*/
#define MAX_THUNK_SELECTOR_DEPTH 16
@@ -1252,6 +1264,7 @@ selector_loop:
// recursively evaluate this selector. We don't want to
// recurse indefinitely, so we impose a depth bound.
+ // See Note [Selector optimisation depth limit].
if (gct->thunk_selector_depth >= MAX_THUNK_SELECTOR_DEPTH) {
goto bale_out;
}
=====================================
rts/sm/GC.c
=====================================
@@ -1843,21 +1843,16 @@ resize_nursery (void)
#if defined(DEBUG)
-static void gcCAFs(void)
+void gcCAFs(void)
{
- StgIndStatic *p, *prev;
+ uint32_t i = 0;
+ StgIndStatic *prev = NULL;
- const StgInfoTable *info;
- uint32_t i;
-
- i = 0;
- p = debug_caf_list;
- prev = NULL;
-
- for (p = debug_caf_list; p != (StgIndStatic*)END_OF_CAF_LIST;
- p = (StgIndStatic*)p->saved_info) {
-
- info = get_itbl((StgClosure*)p);
+ for (StgIndStatic *p = debug_caf_list;
+ p != (StgIndStatic*) END_OF_CAF_LIST;
+ p = (StgIndStatic*) p->saved_info)
+ {
+ const StgInfoTable *info = get_itbl((StgClosure*)p);
ASSERT(info->type == IND_STATIC);
// See Note [STATIC_LINK fields] in Storage.h
=====================================
rts/sm/Sanity.c
=====================================
@@ -619,9 +619,9 @@ checkGlobalTSOList (bool checkTSOs)
stack = tso->stackobj;
while (1) {
- if (stack->dirty & 1) {
- ASSERT(Bdescr((P_)stack)->gen_no == 0 || (stack->dirty & TSO_MARKED));
- stack->dirty &= ~TSO_MARKED;
+ if (stack->dirty & STACK_DIRTY) {
+ ASSERT(Bdescr((P_)stack)->gen_no == 0 || (stack->dirty & STACK_SANE));
+ stack->dirty &= ~STACK_SANE;
}
frame = (StgUnderflowFrame*) (stack->stack + stack->stack_size
- sizeofW(StgUnderflowFrame));
@@ -656,7 +656,7 @@ checkMutableList( bdescr *mut_bd, uint32_t gen )
((StgTSO *)p)->flags |= TSO_MARKED;
break;
case STACK:
- ((StgStack *)p)->dirty |= TSO_MARKED;
+ ((StgStack *)p)->dirty |= STACK_SANE;
break;
}
}
=====================================
rts/sm/Storage.c
=====================================
@@ -1133,8 +1133,8 @@ dirty_TSO (Capability *cap, StgTSO *tso)
void
dirty_STACK (Capability *cap, StgStack *stack)
{
- if (stack->dirty == 0) {
- stack->dirty = 1;
+ if (! (stack->dirty & STACK_DIRTY)) {
+ stack->dirty = STACK_DIRTY;
recordClosureMutated(cap,(StgClosure*)stack);
}
}
=====================================
utils/deriveConstants/Main.hs
=====================================
@@ -307,6 +307,9 @@ wanteds os = concat
"sizeofW(StgHeader) - sizeofW(StgProfHeader)"
,constantWord Both "PROF_HDR_SIZE" "sizeofW(StgProfHeader)"
+ -- Stack flags for C--
+ ,constantWord C "STACK_DIRTY" "STACK_DIRTY"
+
-- Size of a storage manager block (in bytes).
,constantWord Both "BLOCK_SIZE" "BLOCK_SIZE"
,constantWord C "MBLOCK_SIZE" "MBLOCK_SIZE"
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/compare/65b2736909158061b024eb6dc0db60cfdb433700...4f65be60b81cd70c41fd14dd73a18fb68478dd84
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/compare/65b2736909158061b024eb6dc0db60cfdb433700...4f65be60b81cd70c41fd14dd73a18fb68478dd84
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20190619/b8f399a3/attachment-0001.html>
More information about the ghc-commits
mailing list