Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | /* Copyright (C) 2011-2012,2017 Matthew Fluet. |
2 | * Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh | |
3 | * Jagannathan, and Stephen Weeks. | |
4 | * Copyright (C) 1997-2000 NEC Research Institute. | |
5 | * | |
6 | * MLton is released under a BSD-style license. | |
7 | * See the file MLton-LICENSE for details. | |
8 | */ | |
9 | ||
10 | #if ASSERT | |
11 | void assertIsObjptrInFromSpace (GC_state s, objptr *opp) { | |
12 | assert (isObjptrInFromSpace (s, *opp)); | |
13 | unless (isObjptrInFromSpace (s, *opp)) { | |
14 | displayGCState (s, stderr); | |
15 | die ("gc.c: assertIsObjptrInFromSpace " | |
16 | "opp = "FMTPTR" " | |
17 | "*opp = "FMTOBJPTR"\n", | |
18 | (uintptr_t)opp, *opp); | |
19 | } | |
20 | /* The following checks that intergenerational pointers have the | |
21 | * appropriate card marked. Unfortunately, it doesn't work because | |
22 | * for stacks, the card containing the beginning of the stack is | |
23 | * marked, but any remaining cards aren't. | |
24 | */ | |
25 | if (FALSE and s->mutatorMarksCards | |
26 | and isPointerInOldGen (s, (pointer)opp) | |
27 | and isObjptrInNursery (s, *opp) | |
28 | and not isCardMarked (s, (pointer)opp)) { | |
29 | displayGCState (s, stderr); | |
30 | die ("gc.c: intergenerational pointer from "FMTPTR" to "FMTOBJPTR" with unmarked card.\n", | |
31 | (uintptr_t)opp, *opp); | |
32 | } | |
33 | } | |
34 | ||
35 | bool invariantForGC (GC_state s) { | |
36 | if (DEBUG) | |
37 | fprintf (stderr, "invariantForGC\n"); | |
38 | /* Frame layouts */ | |
39 | for (unsigned int i = 0; i < s->frameLayoutsLength; ++i) { | |
40 | GC_frameLayout layout; | |
41 | ||
42 | layout = &(s->frameLayouts[i]); | |
43 | if (layout->size > 0) { | |
44 | GC_frameOffsets offsets; | |
45 | ||
46 | assert (layout->size <= s->maxFrameSize); | |
47 | offsets = layout->offsets; | |
48 | for (unsigned int j = 0; j < offsets[0]; ++j) | |
49 | assert (offsets[j + 1] < layout->size); | |
50 | } | |
51 | } | |
52 | /* Generational */ | |
53 | if (s->mutatorMarksCards) { | |
54 | assert (s->generationalMaps.cardMap == | |
55 | &(s->generationalMaps.cardMapAbsolute | |
56 | [pointerToCardMapIndexAbsolute(s->heap.start)])); | |
57 | assert (&(s->generationalMaps.cardMapAbsolute | |
58 | [pointerToCardMapIndexAbsolute(s->heap.start + s->heap.size - 1)]) | |
59 | < (s->generationalMaps.cardMap | |
60 | + (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE))); | |
61 | } | |
62 | assert (isAligned (s->heap.size, s->sysvals.pageSize)); | |
63 | assert (isAligned ((size_t)s->heap.start, CARD_SIZE)); | |
64 | assert (isFrontierAligned (s, s->heap.start + s->heap.oldGenSize)); | |
65 | assert (isFrontierAligned (s, s->heap.nursery)); | |
66 | assert (isFrontierAligned (s, s->frontier)); | |
67 | assert (s->heap.start + s->heap.oldGenSize <= s->heap.nursery); | |
68 | assert (s->heap.nursery <= s->heap.start + s->heap.size); | |
69 | assert (s->heap.nursery <= s->frontier); | |
70 | unless (0 == s->heap.size) { | |
71 | assert (s->frontier <= s->limitPlusSlop); | |
72 | assert (s->limit == s->limitPlusSlop - GC_HEAP_LIMIT_SLOP); | |
73 | assert (hasHeapBytesFree (s, 0, 0)); | |
74 | } | |
75 | assert (s->secondaryHeap.start == NULL | |
76 | or s->heap.size == s->secondaryHeap.size); | |
77 | /* Check that all pointers are into from space. */ | |
78 | foreachGlobalObjptr (s, assertIsObjptrInFromSpace); | |
79 | pointer back = s->heap.start + s->heap.oldGenSize; | |
80 | if (DEBUG_DETAILED) | |
81 | fprintf (stderr, "Checking old generation.\n"); | |
82 | foreachObjptrInRange (s, alignFrontier (s, s->heap.start), &back, | |
83 | assertIsObjptrInFromSpace, FALSE); | |
84 | if (DEBUG_DETAILED) | |
85 | fprintf (stderr, "Checking nursery.\n"); | |
86 | foreachObjptrInRange (s, s->heap.nursery, &s->frontier, | |
87 | assertIsObjptrInFromSpace, FALSE); | |
88 | /* Current thread. */ | |
89 | GC_stack stack = getStackCurrent(s); | |
90 | assert (isStackReservedAligned (s, stack->reserved)); | |
91 | assert (s->stackBottom == getStackBottom (s, stack)); | |
92 | assert (s->stackTop == getStackTop (s, stack)); | |
93 | assert (s->stackLimit == getStackLimit (s, stack)); | |
94 | assert (s->stackBottom <= s->stackTop); | |
95 | assert (stack->used == sizeofGCStateCurrentStackUsed (s)); | |
96 | assert (stack->used <= stack->reserved); | |
97 | if (DEBUG) | |
98 | fprintf (stderr, "invariantForGC passed\n"); | |
99 | return TRUE; | |
100 | } | |
101 | #endif | |
102 | ||
103 | bool invariantForMutatorFrontier (GC_state s) { | |
104 | GC_thread thread = getThreadCurrent(s); | |
105 | return (thread->bytesNeeded | |
106 | <= (size_t)(s->limitPlusSlop - s->frontier)); | |
107 | } | |
108 | ||
109 | bool invariantForMutatorStack (GC_state s) { | |
110 | GC_stack stack = getStackCurrent(s); | |
111 | return (getStackTop (s, stack) | |
112 | <= getStackLimit (s, stack) + getStackTopFrameSize (s, stack)); | |
113 | } | |
114 | ||
115 | #if ASSERT | |
116 | bool invariantForMutator (GC_state s, bool frontier, bool stack) { | |
117 | if (DEBUG) | |
118 | displayGCState (s, stderr); | |
119 | if (frontier) | |
120 | assert (invariantForMutatorFrontier(s)); | |
121 | if (stack) | |
122 | assert (invariantForMutatorStack(s)); | |
123 | assert (invariantForGC (s)); | |
124 | return TRUE; | |
125 | } | |
126 | #endif |