summaryrefslogtreecommitdiff
path: root/rts/sm
diff options
context:
space:
mode:
Diffstat (limited to 'rts/sm')
-rw-r--r--rts/sm/Compact.c55
-rw-r--r--rts/sm/GC.c8
-rw-r--r--rts/sm/GCThread.h3
-rw-r--r--rts/sm/MarkWeak.c41
-rw-r--r--rts/sm/MarkWeak.h1
-rw-r--r--rts/sm/Scav.c59
-rw-r--r--rts/sm/Storage.c10
7 files changed, 98 insertions, 79 deletions
diff --git a/rts/sm/Compact.c b/rts/sm/Compact.c
index 8ae72a96e0..b07a886eab 100644
--- a/rts/sm/Compact.c
+++ b/rts/sm/Compact.c
@@ -183,7 +183,7 @@ loop:
// A word-aligned memmove will be faster for small objects than libc's or gcc's.
// Remember, the two regions *might* overlap, but: to <= from.
STATIC_INLINE void
-move(StgPtr to, StgPtr from, W_ size)
+move(StgPtr to, StgPtr from, StgWord size)
{
for(; size > 0; --size) {
*to++ = *from++;
@@ -225,7 +225,7 @@ thread_static( StgClosure* p )
}
STATIC_INLINE void
-thread_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, W_ size )
+thread_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, StgWord size )
{
W_ i, b;
StgWord bitmap;
@@ -248,11 +248,25 @@ thread_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, W_ size )
}
STATIC_INLINE StgPtr
+thread_small_bitmap (StgPtr p, StgWord size, StgWord bitmap)
+{
+ while (size > 0) {
+ if ((bitmap & 1) == 0) {
+ thread((StgClosure **)p);
+ }
+ p++;
+ bitmap = bitmap >> 1;
+ size--;
+ }
+ return p;
+}
+
+STATIC_INLINE StgPtr
thread_arg_block (StgFunInfoTable *fun_info, StgClosure **args)
{
StgPtr p;
StgWord bitmap;
- W_ size;
+ StgWord size;
p = (StgPtr)args;
switch (fun_info->f.fun_type) {
@@ -269,14 +283,7 @@ thread_arg_block (StgFunInfoTable *fun_info, StgClosure **args)
bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);
small_bitmap:
- while (size > 0) {
- if ((bitmap & 1) == 0) {
- thread((StgClosure **)p);
- }
- p++;
- bitmap = bitmap >> 1;
- size--;
- }
+ p = thread_small_bitmap(p, size, bitmap);
break;
}
return p;
@@ -287,7 +294,7 @@ thread_stack(StgPtr p, StgPtr stack_end)
{
const StgRetInfoTable* info;
StgWord bitmap;
- W_ size;
+ StgWord size;
// highly similar to scavenge_stack, but we do pointer threading here.
@@ -315,19 +322,11 @@ thread_stack(StgPtr p, StgPtr stack_end)
p++;
// NOTE: the payload starts immediately after the info-ptr, we
// don't have an StgHeader in the same sense as a heap closure.
- while (size > 0) {
- if ((bitmap & 1) == 0) {
- thread((StgClosure **)p);
- }
- p++;
- bitmap = bitmap >> 1;
- size--;
- }
+ p = thread_small_bitmap(p, size, bitmap);
continue;
case RET_BCO: {
StgBCO *bco;
- nat size;
p++;
bco = (StgBCO *)*p;
@@ -395,14 +394,7 @@ thread_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size)
default:
bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
small_bitmap:
- while (size > 0) {
- if ((bitmap & 1) == 0) {
- thread((StgClosure **)p);
- }
- p++;
- bitmap = bitmap >> 1;
- size--;
- }
+ p = thread_small_bitmap(p, size, bitmap);
break;
}
@@ -773,7 +765,7 @@ update_fwd_compact( bdescr *blocks )
#endif
bdescr *bd, *free_bd;
StgInfoTable *info;
- nat size;
+ StgWord size;
StgWord iptr;
bd = blocks;
@@ -858,7 +850,8 @@ update_bkwd_compact( generation *gen )
#endif
bdescr *bd, *free_bd;
StgInfoTable *info;
- W_ size, free_blocks;
+ StgWord size;
+ W_ free_blocks;
StgWord iptr;
bd = free_bd = gen->old_blocks;
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index d22a31eccb..dabcd722d7 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -286,6 +286,9 @@ GarbageCollect (nat collect_gen,
memInventory(DEBUG_gc);
#endif
+ // do this *before* we start scavenging
+ collectFreshWeakPtrs();
+
// check sanity *before* GC
IF_DEBUG(sanity, checkSanity(rtsFalse /* before GC */, major_gc));
@@ -1038,8 +1041,6 @@ gcWorkerThread (Capability *cap)
SET_GCT(gc_threads[cap->no]);
gct->id = osThreadId();
- stat_gcWorkerThreadStart(gct);
-
// Wait until we're told to wake up
RELEASE_SPIN_LOCK(&gct->mut_spin);
// yieldThread();
@@ -1097,9 +1098,6 @@ gcWorkerThread (Capability *cap)
ACQUIRE_SPIN_LOCK(&gct->mut_spin);
debugTrace(DEBUG_gc, "GC thread %d on my way...", gct->thread_index);
- // record the time spent doing GC in the Task structure
- stat_gcWorkerThreadDone(gct);
-
SET_GCT(saved_gct);
}
diff --git a/rts/sm/GCThread.h b/rts/sm/GCThread.h
index 12ef999a9b..84ce3f0239 100644
--- a/rts/sm/GCThread.h
+++ b/rts/sm/GCThread.h
@@ -77,7 +77,7 @@
------------------------------------------------------------------------- */
typedef struct gen_workspace_ {
- generation * gen; // the gen for this workspace
+ generation * gen; // the gen for this workspace
struct gc_thread_ * my_gct; // the gc_thread that contains this workspace
// where objects to be scavenged go
@@ -184,7 +184,6 @@ typedef struct gc_thread_ {
Time gc_start_cpu; // process CPU time
Time gc_start_elapsed; // process elapsed time
- Time gc_start_thread_cpu; // thread CPU time
W_ gc_start_faults;
// -------------------
diff --git a/rts/sm/MarkWeak.c b/rts/sm/MarkWeak.c
index 4e0c1369a1..0324f3b4b9 100644
--- a/rts/sm/MarkWeak.c
+++ b/rts/sm/MarkWeak.c
@@ -25,6 +25,8 @@
#include "Storage.h"
#include "Threads.h"
+#include "sm/Sanity.h"
+
/* -----------------------------------------------------------------------------
Weak Pointers
@@ -39,10 +41,8 @@
new live weak pointers, then all the currently unreachable ones are
dead.
- For generational GC: we just don't try to finalize weak pointers in
- older generations than the one we're collecting. This could
- probably be optimised by keeping per-generation lists of weak
- pointers, but for a few weak pointers this scheme will work.
+ For generational GC: we don't try to finalize weak pointers in
+ older generations than the one we're collecting.
There are three distinct stages to processing weak pointers:
@@ -343,6 +343,39 @@ static void tidyThreadList (generation *gen)
}
}
+#ifdef DEBUG
+static void checkWeakPtrSanity(StgWeak *hd, StgWeak *tl)
+{
+ StgWeak *w, *prev;
+ for (w = hd; w != NULL; prev = w, w = w->link) {
+ ASSERT(INFO_PTR_TO_STRUCT(UNTAG_CLOSURE((StgClosure*)w)->header.info)->type == WEAK);
+ checkClosure((StgClosure*)w);
+ }
+ if (tl != NULL) {
+ ASSERT(prev == tl);
+ }
+}
+#endif
+
+void collectFreshWeakPtrs()
+{
+ nat i;
+ generation *gen = &generations[0];
+ // move recently allocated weak_ptr_list to the old list as well
+ for (i = 0; i < n_capabilities; i++) {
+ Capability *cap = capabilities[i];
+ if (cap->weak_ptr_list_tl != NULL) {
+ IF_DEBUG(sanity, checkWeakPtrSanity(cap->weak_ptr_list_hd, cap->weak_ptr_list_tl));
+ cap->weak_ptr_list_tl->link = gen->weak_ptr_list;
+ gen->weak_ptr_list = cap->weak_ptr_list_hd;
+ cap->weak_ptr_list_tl = NULL;
+ cap->weak_ptr_list_hd = NULL;
+ } else {
+ ASSERT(cap->weak_ptr_list_hd == NULL);
+ }
+ }
+}
+
/* -----------------------------------------------------------------------------
Evacuate every weak pointer object on the weak_ptr_list, and update
the link fields.
diff --git a/rts/sm/MarkWeak.h b/rts/sm/MarkWeak.h
index f9bacfa0da..bd0231d74c 100644
--- a/rts/sm/MarkWeak.h
+++ b/rts/sm/MarkWeak.h
@@ -20,6 +20,7 @@ extern StgWeak *old_weak_ptr_list;
extern StgTSO *resurrected_threads;
extern StgTSO *exception_threads;
+void collectFreshWeakPtrs ( void );
void initWeakForGC ( void );
rtsBool traverseWeakPtrList ( void );
void markWeakPtrList ( void );
diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c
index c35444bbaa..b9f8f1259b 100644
--- a/rts/sm/Scav.c
+++ b/rts/sm/Scav.c
@@ -32,7 +32,7 @@ static void scavenge_stack (StgPtr p, StgPtr stack_end);
static void scavenge_large_bitmap (StgPtr p,
StgLargeBitmap *large_bitmap,
- nat size );
+ StgWord size );
#if defined(THREADED_RTS) && !defined(PARALLEL_GC)
# define evacuate(a) evacuate1(a)
@@ -168,6 +168,20 @@ static StgPtr scavenge_mut_arr_ptrs_marked (StgMutArrPtrs *a)
return (StgPtr)a + mut_arr_ptrs_sizeW(a);
}
+STATIC_INLINE StgPtr
+scavenge_small_bitmap (StgPtr p, StgWord size, StgWord bitmap)
+{
+ while (size > 0) {
+ if ((bitmap & 1) == 0) {
+ evacuate((StgClosure **)p);
+ }
+ p++;
+ bitmap = bitmap >> 1;
+ size--;
+ }
+ return p;
+}
+
/* -----------------------------------------------------------------------------
Blocks of function args occur on the stack (at the top) and
in PAPs.
@@ -178,7 +192,7 @@ scavenge_arg_block (StgFunInfoTable *fun_info, StgClosure **args)
{
StgPtr p;
StgWord bitmap;
- nat size;
+ StgWord size;
p = (StgPtr)args;
switch (fun_info->f.fun_type) {
@@ -195,14 +209,7 @@ scavenge_arg_block (StgFunInfoTable *fun_info, StgClosure **args)
bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);
small_bitmap:
- while (size > 0) {
- if ((bitmap & 1) == 0) {
- evacuate((StgClosure **)p);
- }
- p++;
- bitmap = bitmap >> 1;
- size--;
- }
+ p = scavenge_small_bitmap(p, size, bitmap);
break;
}
return p;
@@ -234,14 +241,7 @@ scavenge_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size)
default:
bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
small_bitmap:
- while (size > 0) {
- if ((bitmap & 1) == 0) {
- evacuate((StgClosure **)p);
- }
- p++;
- bitmap = bitmap >> 1;
- size--;
- }
+ p = scavenge_small_bitmap(p, size, bitmap);
break;
}
return p;
@@ -1498,7 +1498,7 @@ scavenge_one(StgPtr p)
{
StgPtr start = gen->scan;
bdescr *start_bd = gen->scan_bd;
- nat size = 0;
+ StgWord size = 0;
scavenge(&gen);
if (start_bd != gen->scan_bd) {
size += (P_)BLOCK_ROUND_UP(start) - start;
@@ -1745,7 +1745,7 @@ scavenge_static(void)
-------------------------------------------------------------------------- */
static void
-scavenge_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, nat size )
+scavenge_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, StgWord size )
{
nat i, j, b;
StgWord bitmap;
@@ -1765,19 +1765,6 @@ scavenge_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, nat size )
}
}
-STATIC_INLINE StgPtr
-scavenge_small_bitmap (StgPtr p, nat size, StgWord bitmap)
-{
- while (size > 0) {
- if ((bitmap & 1) == 0) {
- evacuate((StgClosure **)p);
- }
- p++;
- bitmap = bitmap >> 1;
- size--;
- }
- return p;
-}
/* -----------------------------------------------------------------------------
scavenge_stack walks over a section of stack and evacuates all the
@@ -1790,7 +1777,7 @@ scavenge_stack(StgPtr p, StgPtr stack_end)
{
const StgRetInfoTable* info;
StgWord bitmap;
- nat size;
+ StgWord size;
/*
* Each time around this loop, we are looking at a chunk of stack
@@ -1874,7 +1861,7 @@ scavenge_stack(StgPtr p, StgPtr stack_end)
case RET_BCO: {
StgBCO *bco;
- nat size;
+ StgWord size;
p++;
evacuate((StgClosure **)p);
@@ -1889,7 +1876,7 @@ scavenge_stack(StgPtr p, StgPtr stack_end)
// large bitmap (> 32 entries, or > 64 on a 64-bit machine)
case RET_BIG:
{
- nat size;
+ StgWord size;
size = GET_LARGE_BITMAP(&info->i)->size;
p++;
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index 86bd1c2bb3..379d9da769 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -686,7 +686,15 @@ StgPtr allocate (Capability *cap, W_ n)
CCS_ALLOC(cap->r.rCCCS,n);
if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
- W_ req_blocks = (W_)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE;
+ // The largest number of words such that
+ // the computation of req_blocks will not overflow.
+ W_ max_words = (HS_WORD_MAX & ~(BLOCK_SIZE-1)) / sizeof(W_);
+ W_ req_blocks;
+
+ if (n > max_words)
+ req_blocks = HS_WORD_MAX; // signal overflow below
+ else
+ req_blocks = (W_)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE;
// Attempting to allocate an object larger than maxHeapSize
// should definitely be disallowed. (bug #1791)