summaryrefslogtreecommitdiff
path: root/rts/sm/NonMovingMark.h
diff options
context:
space:
mode:
Diffstat (limited to 'rts/sm/NonMovingMark.h')
-rw-r--r--rts/sm/NonMovingMark.h25
1 files changed, 22 insertions, 3 deletions
diff --git a/rts/sm/NonMovingMark.h b/rts/sm/NonMovingMark.h
index a3629a2e99..bff89d9e92 100644
--- a/rts/sm/NonMovingMark.h
+++ b/rts/sm/NonMovingMark.h
@@ -43,21 +43,40 @@ enum EntryType {
*/
typedef struct {
- enum EntryType type;
- // All pointers should be untagged
+ // Which kind of mark queue entry we have is determined by the low bits of
+ // the second word: they must be zero in the case of a mark_closure entry
+ // (since the second word of a mark_closure entry points to a pointer and
+ // pointers must be word-aligned). In the case of a mark_array we set them
+ // to 0x3 (the value of start_index is shifted to the left to accomodate
+ // this). null_entry where p==NULL is used to indicate the end of the queue.
union {
struct {
+ void *p; // must be NULL
+ } null_entry;
+ struct {
StgClosure *p; // the object to be marked
StgClosure **origin; // field where this reference was found.
// See Note [Origin references in the nonmoving collector]
} mark_closure;
struct {
const StgMutArrPtrs *array;
- StgWord start_index;
+ StgWord start_index; // start index is shifted to the left by 16 bits
} mark_array;
};
} MarkQueueEnt;
+INLINE_HEADER enum EntryType nonmovingMarkQueueEntryType(MarkQueueEnt *ent)
+{
+ if (ent->null_entry.p == NULL) {
+ return NULL_ENTRY;
+ } else if (((uintptr_t) ent->mark_closure.origin & TAG_BITS) == 0) {
+ return MARK_CLOSURE;
+ } else {
+ ASSERT((ent->mark_array.start_index & TAG_BITS) == 0x3);
+ return MARK_ARRAY;
+ }
+}
+
typedef struct {
// index of first *unused* queue entry
uint32_t head;