1/*
2    Title:      Multi-Threaded Garbage Collector - Mark phase
3
4    Copyright (c) 2010-12, 2015-16 David C. J. Matthews
5
6    Based on the original garbage collector code
7        Copyright 2000-2008
8        Cambridge University Technical Services Limited
9
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License version 2.1 as published by the Free Software Foundation.
13
14    This library is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    Lesser General Public License for more details.
18
19    You should have received a copy of the GNU Lesser General Public
20    License along with this library; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22
23*/
24/*
25This is the first, mark, phase of the garbage collector.  It detects all
26reachable cells in the area being collected.  At the end of the phase the
27bit-maps associated with the areas will have ones for words belonging to cells
28that must be retained and zeros for words that can be reused.
29
30This is now multi-threaded.  The mark phase involves setting a bit in the header
31of each live cell and then a pass over the memory building the bitmaps and clearing
32this bit.  It is unfortunate that we cannot use the GC-bit that is used in
33forwarding pointers but we may well have forwarded pointers left over from a
34partially completed minor GC.  Using a bit in the header avoids the need for
35locking since at worst it may involve two threads duplicating some marking.
36
37The code ensures that each reachable cell is marked at least once but with
38multiple threads a cell may be marked by more than once cell if the
39memory is not fully up to date.  Each thread has a stack on which it
40remembers cells that have been marked but not fully scanned.  If a
41thread runs out of cells of its own to scan it can pick a pointer off
42the stack of another thread and scan that.  The original thread will
43still scan it some time later but it should find that the addresses
44in it have all been marked and it can simply pop this off.  This is
45all done without locking.  Stacks are only modified by the owning
46thread and when they pop anything they write zero in its place.
47Other threads only need to search for a zero to find if they are
48at the top and if they get a pointer that has already been scanned
49then this is safe.  The only assumption made about the memory is
50that all the bits of a word are updated together so that a thread
51will always read a value that is a valid pointer.
52
53Many of the ideas are drawn from Flood, Detlefs, Shavit and Zhang 2001
54"Parallel Garbage Collection for Shared Memory Multiprocessors".
55*/
56#ifdef HAVE_CONFIG_H
57#include "config.h"
58#elif defined(_WIN32)
59#include "winconfig.h"
60#else
61#error "No configuration file"
62#endif
63
64#ifdef HAVE_ASSERT_H
65#include <assert.h>
66#define ASSERT(x)   assert(x)
67#else
68#define ASSERT(x)
69#endif
70
71#include "globals.h"
72#include "processes.h"
73#include "gc.h"
74#include "scanaddrs.h"
75#include "check_objects.h"
76#include "bitmap.h"
77#include "memmgr.h"
78#include "diagnostics.h"
79#include "gctaskfarm.h"
80#include "profiling.h"
81#include "heapsizing.h"
82
83#define MARK_STACK_SIZE 3000
84#define LARGECACHE_SIZE 20
85
86class MTGCProcessMarkPointers: public ScanAddress
87{
88public:
89    MTGCProcessMarkPointers();
90
91    virtual void ScanRuntimeAddress(PolyObject **pt, RtsStrength weak);
92    virtual PolyObject *ScanObjectAddress(PolyObject *base);
93
94    virtual void ScanAddressesInObject(PolyObject *base, POLYUNSIGNED lengthWord);
95    // Have to redefine this for some reason.
96    void ScanAddressesInObject(PolyObject *base)
97        { ScanAddressesInObject(base, base->LengthWord()); }
98
99    virtual void ScanConstant(PolyObject *base, byte *addressOfConstant, ScanRelocationKind code);
100
101    static void MarkPointersTask(GCTaskId *, void *arg1, void *arg2);
102
103    static void InitStatics(unsigned threads)
104    {
105        markStacks = new MTGCProcessMarkPointers[threads];
106        nInUse = 0;
107        nThreads = threads;
108    }
109
110    static void MarkRoots(void);
111    static bool RescanForStackOverflow();
112
113private:
114    bool TestForScan(PolyWord *pt);
115    void MarkAndTestForScan(PolyWord *pt);
116    void Reset();
117
118    void PushToStack(PolyObject *obj, PolyWord *currentPtr = 0, POLYUNSIGNED originalLength = 0)
119    {
120        // If we don't have all the threads running we start a new one but
121        // only once we have several items on the stack.  Otherwise we
122        // can end up creating a task that terminates almost immediately.
123        if (nInUse >= nThreads || msp < 2 || ! ForkNew(obj))
124        {
125            if (msp < MARK_STACK_SIZE)
126            {
127                markStack[msp++] = obj;
128                if (currentPtr != 0)
129                {
130                    locPtr++;
131                    if (locPtr == LARGECACHE_SIZE) locPtr = 0;
132                    largeObjectCache[locPtr].base = obj;
133                    largeObjectCache[locPtr].current = currentPtr;
134                }
135            }
136            else StackOverflow(obj);
137        }
138        // else the new task is processing it.
139    }
140
141    static void StackOverflow(PolyObject *obj);
142    static bool ForkNew(PolyObject *obj);
143
144    PolyObject *markStack[MARK_STACK_SIZE];
145    unsigned msp;
146    bool active;
147
148    // For the typical small cell it's easier just to rescan from the start
149    // but that can be expensive for large cells.  This caches the offset for
150    // large cells.
151    static const POLYUNSIGNED largeObjectSize = 50;
152    struct { PolyObject *base; PolyWord *current; } largeObjectCache[LARGECACHE_SIZE];
153    unsigned locPtr;
154
155    static MTGCProcessMarkPointers *markStacks;
156protected:
157    static unsigned nThreads, nInUse;
158    static PLock stackLock;
159};
160
161// There is one mark-stack for each GC thread.  markStacks[0] is used by the
162// main thread when marking the roots and rescanning after mark-stack overflow.
163// Once that work is done markStacks[0] is released and is available for a
164// worker thread.
165MTGCProcessMarkPointers *MTGCProcessMarkPointers::markStacks;
166unsigned MTGCProcessMarkPointers::nThreads, MTGCProcessMarkPointers::nInUse;
167PLock MTGCProcessMarkPointers::stackLock("GC mark stack");
168
169// It is possible to have two levels of forwarding because
170// we could have a cell in the allocation area that has been moved
171// to the immutable area and then shared with another cell.
172inline PolyObject *FollowForwarding(PolyObject *obj)
173{
174    while (obj->ContainsForwardingPtr())
175        obj = obj->GetForwardingPtr();
176    return obj;
177}
178
179MTGCProcessMarkPointers::MTGCProcessMarkPointers(): msp(0), active(false), locPtr(0)
180{
181    // Clear the mark stack
182    for (unsigned i = 0; i < MARK_STACK_SIZE; i++)
183        markStack[i] = 0;
184    // Clear the large object cache just to be sure.
185    for (unsigned j = 0; j < LARGECACHE_SIZE; j++)
186    {
187        largeObjectCache[j].base = 0;
188        largeObjectCache[j].current = 0;
189    }
190}
191
192// Clear the state at the beginning of a new GC pass.
193void MTGCProcessMarkPointers::Reset()
194{
195    locPtr = 0;
196    //largeObjectCache[locPtr].base = 0;
197    // Clear the cache completely just to be safe
198    for (unsigned j = 0; j < LARGECACHE_SIZE; j++)
199    {
200        largeObjectCache[j].base = 0;
201        largeObjectCache[j].current = 0;
202    }
203
204}
205
206// Called when the stack has overflowed.  We need to include this
207// in the range to be rescanned.
208void MTGCProcessMarkPointers::StackOverflow(PolyObject *obj)
209{
210    MarkableSpace *space = (MarkableSpace*)gMem.SpaceForAddress(obj-1);
211    ASSERT(space != 0 && (space->spaceType == ST_LOCAL || space->spaceType == ST_CODE));
212    PLocker lock(&space->spaceLock);
213    // Have to include this in the range to rescan.
214    if (space->fullGCRescanStart > ((PolyWord*)obj) - 1)
215        space->fullGCRescanStart = ((PolyWord*)obj) - 1;
216    POLYUNSIGNED n = obj->Length();
217    if (space->fullGCRescanEnd < ((PolyWord*)obj) + n)
218        space->fullGCRescanEnd = ((PolyWord*)obj) + n;
219    ASSERT(obj->LengthWord() & _OBJ_GC_MARK); // Should have been marked.
220    if (debugOptions & DEBUG_GC_ENHANCED)
221        Log("GC: Mark: Stack overflow.  Rescan for %p\n", obj);
222}
223
224// Fork a new task.  Because we've checked nInUse without taking the lock
225// we may find that we can no longer create a new task.
226bool MTGCProcessMarkPointers::ForkNew(PolyObject *obj)
227{
228    MTGCProcessMarkPointers *marker = 0;
229    {
230        PLocker lock(&stackLock);
231        if (nInUse == nThreads)
232            return false;
233        for (unsigned i = 0; i < nThreads; i++)
234        {
235            if (! markStacks[i].active)
236            {
237                marker = &markStacks[i];
238                break;
239            }
240        }
241        ASSERT(marker != 0);
242        marker->active = true;
243        nInUse++;
244    }
245    bool test = gpTaskFarm->AddWork(&MTGCProcessMarkPointers::MarkPointersTask, marker, obj);
246    ASSERT(test);
247    return true;
248}
249
250// Main marking task.  This is forked off initially to scan a specific object and
251// anything reachable from it but once that has finished it tries to find objects
252// on other stacks to scan.
253void MTGCProcessMarkPointers::MarkPointersTask(GCTaskId *, void *arg1, void *arg2)
254{
255    MTGCProcessMarkPointers *marker = (MTGCProcessMarkPointers*)arg1;
256    marker->Reset();
257
258    marker->ScanAddressesInObject((PolyObject*)arg2);
259
260    while (true)
261    {
262        // Look for a stack that has at least one item on it.
263        MTGCProcessMarkPointers *steal = 0;
264        for (unsigned i = 0; i < nThreads && steal == 0; i++)
265        {
266            if (markStacks[i].markStack[0] != 0)
267                steal = &markStacks[i];
268        }
269        // We're finished if they're all done.
270        if (steal == 0)
271            break;
272        // Look for items on this stack
273        for (unsigned j = 0; j < MARK_STACK_SIZE; j++)
274        {
275            // Pick the item off the stack.
276            // N.B. The owning thread may update this to zero
277            // at any time.
278            PolyObject *toSteal = steal->markStack[j];
279            if (toSteal == 0) break; // Nothing more on the stack
280            // The idea here is that the original thread pushed this
281            // because there were at least two addresses it needed to
282            // process.  It started down one branch but left the other.
283            // Since it will have marked cells in the branch it has
284            // followed this thread will start on the unprocessed
285            // address(es).
286            marker->ScanAddressesInObject(toSteal);
287        }
288    }
289
290    PLocker lock(&stackLock);
291    marker->active = false; // It's finished
292    nInUse--;
293    ASSERT(marker->markStack[0] == 0);
294}
295
296// Tests if this needs to be scanned.  It marks it if it has not been marked
297// unless it has to be scanned.
298bool MTGCProcessMarkPointers::TestForScan(PolyWord *pt)
299{
300    if ((*pt).IsTagged())
301        return false;
302
303    // This could contain a forwarding pointer if it points into an
304    // allocation area and has been moved by the minor GC.
305    // We have to be a little careful.  Another thread could also
306    // be following any forwarding pointers here.  However it's safe
307    // because they will update it with the same value.
308    PolyObject *obj = (*pt).AsObjPtr();
309    if (obj->ContainsForwardingPtr())
310    {
311        obj = FollowForwarding(obj);
312        *pt = obj;
313    }
314
315    MemSpace *sp = gMem.SpaceForAddress(obj-1);
316    if (sp == 0 || (sp->spaceType != ST_LOCAL && sp->spaceType != ST_CODE))
317        return false; // Ignore it if it points to a permanent area
318
319    POLYUNSIGNED L = obj->LengthWord();
320    if (L & _OBJ_GC_MARK)
321        return false; // Already marked
322
323    if (debugOptions & DEBUG_GC_DETAIL)
324        Log("GC: Mark: %p %" POLYUFMT " %u\n", obj, OBJ_OBJECT_LENGTH(L), GetTypeBits(L));
325
326    if (OBJ_IS_BYTE_OBJECT(L))
327    {
328        obj->SetLengthWord(L | _OBJ_GC_MARK); // Mark it
329        return false; // We've done as much as we need
330    }
331    return true;
332}
333
334void MTGCProcessMarkPointers::MarkAndTestForScan(PolyWord *pt)
335{
336    if (TestForScan(pt))
337    {
338        PolyObject *obj = (*pt).AsObjPtr();
339        obj->SetLengthWord(obj->LengthWord() | _OBJ_GC_MARK);
340    }
341}
342
343// The initial entry to process the roots.  These may be RTS addresses or addresses in
344// a thread stack.  Also called recursively to process the addresses of constants in
345// code segments.  This is used in situations where a scanner may return the
346// updated address of an object.
347PolyObject *MTGCProcessMarkPointers::ScanObjectAddress(PolyObject *obj)
348{
349    PolyWord val = obj;
350    MemSpace *sp = gMem.SpaceForAddress(val.AsStackAddr()-1);
351    if (!(sp->spaceType == ST_LOCAL || sp->spaceType == ST_CODE))
352        return obj; // Ignore it if it points to a permanent area
353
354    // We may have a forwarding pointer if this has been moved by the
355    // minor GC.
356    if (obj->ContainsForwardingPtr())
357    {
358        obj = FollowForwarding(obj);
359        val = obj;
360    }
361
362    ASSERT(obj->ContainsNormalLengthWord());
363
364    POLYUNSIGNED L = obj->LengthWord();
365    if (L & _OBJ_GC_MARK)
366        return obj; // Already marked
367    obj->SetLengthWord(L | _OBJ_GC_MARK); // Mark it
368
369    if (profileMode == kProfileLiveData || (profileMode == kProfileLiveMutables && obj->IsMutable()))
370        AddObjectProfile(obj);
371
372    POLYUNSIGNED n = OBJ_OBJECT_LENGTH(L);
373    if (debugOptions & DEBUG_GC_DETAIL)
374        Log("GC: Mark: %p %" POLYUFMT " %u\n", obj, n, GetTypeBits(L));
375
376    if (OBJ_IS_BYTE_OBJECT(L))
377        return obj;
378
379    // If we already have something on the stack we must being called
380    // recursively to process a constant in a code segment.  Just push
381    // it on the stack and let the caller deal with it.
382    if (msp != 0)
383        PushToStack(obj); // Can't check this because it may have forwarding ptrs.
384    else
385    {
386        MTGCProcessMarkPointers::ScanAddressesInObject(obj, L);
387        // We can only check after we've processed it because if we
388        // have addresses left over from an incomplete partial GC they
389        // may need to forwarded.
390        CheckObject (obj);
391    }
392
393    return obj;
394}
395
396// These functions are only called with pointers held by the runtime system.
397// Weak references can occur in the runtime system, eg. streams and windows.
398// Weak references are not marked and so unreferenced streams and windows
399// can be detected and closed.
400void MTGCProcessMarkPointers::ScanRuntimeAddress(PolyObject **pt, RtsStrength weak)
401{
402    if (weak == STRENGTH_WEAK) return;
403    *pt = ScanObjectAddress(*pt);
404    CheckPointer (*pt); // Check it after any forwarding pointers have been followed.
405}
406
407// This is called via ScanAddressesInRegion to process the permanent mutables.  It is
408// also called from ScanObjectAddress to process root addresses.
409// It processes all the addresses reachable from the object.
410void MTGCProcessMarkPointers::ScanAddressesInObject(PolyObject *obj, POLYUNSIGNED lengthWord)
411{
412    if (OBJ_IS_BYTE_OBJECT(lengthWord))
413        return;
414
415    while (true)
416    {
417        ASSERT (OBJ_IS_LENGTH(lengthWord));
418
419        // Get the length and base address.  N.B.  If this is a code segment
420        // these will be side-effected by GetConstSegmentForCode.
421        POLYUNSIGNED length = OBJ_OBJECT_LENGTH(lengthWord);
422
423        if (OBJ_IS_WEAKREF_OBJECT(lengthWord))
424        {
425            // Special case.
426            ASSERT(OBJ_IS_MUTABLE_OBJECT(lengthWord)); // Should be a mutable.
427            ASSERT(OBJ_IS_WORD_OBJECT(lengthWord)); // Should be a plain object.
428            // We need to mark the "SOME" values in this object but we don't mark
429            // the references contained within the "SOME".
430            PolyWord *baseAddr = (PolyWord*)obj;
431            // Mark every word but ignore the result.
432            for (POLYUNSIGNED i = 0; i < length; i++)
433                (void)MarkAndTestForScan(baseAddr+i);
434            // We've finished with this.
435            length = 0;
436        }
437
438        else if (OBJ_IS_CODE_OBJECT(lengthWord))
439        {
440            // It's better to process the whole code object in one go.
441            ScanAddress::ScanAddressesInObject(obj, lengthWord);
442            length = 0; // Finished
443        }
444
445        // else it's a normal object,
446
447        // If there are only two addresses in this cell that need to be
448        // followed we follow them immediately and treat this cell as done.
449        // If there are more than two we push the address of this cell on
450        // the stack, follow the first address and then rescan it.  That way
451        // list cells are processed once only but we don't overflow the
452        // stack by pushing all the addresses in a very large vector.
453        PolyWord *baseAddr = (PolyWord*)obj;
454        PolyWord *endWord = baseAddr + length;
455        PolyObject *firstWord = 0;
456        PolyObject *secondWord = 0;
457        PolyWord *restartAddr = 0;
458
459        if (obj == largeObjectCache[locPtr].base)
460        {
461            baseAddr = largeObjectCache[locPtr].current;
462            ASSERT(baseAddr > (PolyWord*)obj && baseAddr < ((PolyWord*)obj)+length);
463            if (locPtr == 0) locPtr = LARGECACHE_SIZE-1; else locPtr--;
464        }
465
466        while (baseAddr != endWord)
467        {
468            PolyWord wordAt = *baseAddr;
469
470            if (wordAt.IsDataPtr() && wordAt != PolyWord::FromUnsigned(0))
471            {
472                // Normal address.  We can have words of all zeros at least in the
473                // situation where we have a partially constructed code segment where
474                // the constants at the end of the code have not yet been filled in.
475                if (TestForScan(baseAddr))
476                {
477                    if (firstWord == 0)
478                        firstWord = baseAddr->AsObjPtr();
479                    else if (secondWord == 0)
480                    {
481                        // If we need to rescan because there are three or more words to do
482                        // this is the place we need to restart (or the start of the cell if it's
483                        // small).
484                        restartAddr = baseAddr;
485                        secondWord = baseAddr->AsObjPtr();
486                    }
487                    else break;  // More than two words.
488                }
489            }
490            baseAddr++;
491        }
492
493        if (baseAddr != endWord)
494            // Put this back on the stack while we process the first word
495            PushToStack(obj, length < largeObjectSize ? 0 : restartAddr, length);
496        else if (secondWord != 0)
497        {
498            // Mark it now because we will process it.
499            secondWord->SetLengthWord(secondWord->LengthWord() | _OBJ_GC_MARK);
500            // Put this on the stack.  If this is a list node we will be
501            // pushing the tail.
502            PushToStack(secondWord);
503        }
504
505        if (firstWord != 0)
506        {
507            // Mark it and process it immediately.
508            firstWord->SetLengthWord(firstWord->LengthWord() | _OBJ_GC_MARK);
509            obj = firstWord;
510        }
511        else if (msp == 0)
512        {
513            markStack[msp] = 0; // Really finished
514            return;
515        }
516        else
517        {
518            // Clear the item above the top.  This really is finished.
519            if (msp < MARK_STACK_SIZE) markStack[msp] = 0;
520            // Pop the item from the stack but don't overwrite it yet.
521            // This allows another thread to steal it if there really
522            // is nothing else to do.  This is only really important
523            // for large objects.
524            obj = markStack[--msp]; // Pop something.
525        }
526
527        lengthWord = obj->LengthWord();
528    }
529}
530
531// Process a constant within the code.  This is a direct copy of ScanAddress::ScanConstant
532// with the addition of the locking.
533void MTGCProcessMarkPointers::ScanConstant(PolyObject *base, byte *addressOfConstant, ScanRelocationKind code)
534{
535    // If we have newly compiled code the constants may be in the
536    // local heap.  MTGCProcessMarkPointers::ScanObjectAddress can
537    // return an updated address for a local address if there is a
538    // forwarding pointer.
539    // Constants can be aligned on any byte offset so another thread
540    // scanning the same code could see an invalid address if it read
541    // the constant while it was being updated.  We put a lock round
542    // this just in case.
543    MemSpace *space = gMem.SpaceForAddress(addressOfConstant);
544    PLock *lock = 0;
545    if (space->spaceType == ST_CODE)
546        lock = &((CodeSpace*)space)->spaceLock;
547
548    if (lock != 0)
549        lock->Lock();
550    PolyWord p = GetConstantValue(addressOfConstant, code);
551    if (lock != 0)
552        lock->Unlock();
553
554    if (! IS_INT(p))
555    {
556        PolyWord oldValue = p;
557        ScanAddress::ScanAddressAt(&p);
558        if (p != oldValue) // Update it if it has changed.
559        {
560            if (lock != 0)
561                lock->Lock();
562            SetConstantValue(addressOfConstant, p, code);
563            if (lock != 0)
564                lock->Unlock();
565        }
566    }
567}
568
569// Mark all the roots.  This is run in the main thread and has the effect
570// of starting new tasks as the scanning runs.
571void MTGCProcessMarkPointers::MarkRoots(void)
572{
573    ASSERT(nThreads >= 1);
574    ASSERT(nInUse == 0);
575    MTGCProcessMarkPointers *marker = &markStacks[0];
576    marker->Reset();
577    marker->active = true;
578    nInUse = 1;
579
580    // Scan the permanent mutable areas.
581    for (std::vector<PermanentMemSpace*>::iterator i = gMem.pSpaces.begin(); i < gMem.pSpaces.end(); i++)
582    {
583        PermanentMemSpace *space = *i;
584        if (space->isMutable && ! space->byteOnly)
585            marker->ScanAddressesInRegion(space->bottom, space->top);
586    }
587
588    // Scan the RTS roots.
589    GCModules(marker);
590
591    ASSERT(marker->markStack[0] == 0);
592
593    // When this has finished there may well be other tasks running.
594    PLocker lock(&stackLock);
595    marker->active = false;
596    nInUse--;
597}
598
599// This class just allows us to use ScanAddress::ScanAddressesInRegion to call
600// ScanAddressesInObject for each object in the region.
601class Rescanner: public ScanAddress
602{
603public:
604    Rescanner(MTGCProcessMarkPointers *marker): m_marker(marker) {}
605
606    virtual void ScanAddressesInObject(PolyObject *obj, POLYUNSIGNED lengthWord)
607    {
608        // If it has previously been marked it is known to be reachable but
609        // the contents may not have been scanned if the stack overflowed.
610        if (lengthWord &_OBJ_GC_MARK)
611            m_marker->ScanAddressesInObject(obj, lengthWord);
612    }
613
614    // Have to define this.
615    virtual PolyObject *ScanObjectAddress(PolyObject *base) { ASSERT(false); return 0; }
616
617    bool ScanSpace(MarkableSpace *space);
618private:
619    MTGCProcessMarkPointers *m_marker;
620};
621
622// Rescan any marked objects in the area between fullGCRescanStart and fullGCRescanEnd.
623// N.B.  We may have threads already processing other areas and they could overflow
624// their stacks and change fullGCRescanStart or fullGCRescanEnd.
625bool Rescanner::ScanSpace(MarkableSpace *space)
626{
627    PolyWord *start, *end;
628    {
629        PLocker lock(&space->spaceLock);
630        start = space->fullGCRescanStart;
631        end = space->fullGCRescanEnd;
632        space->fullGCRescanStart = space->top;
633        space->fullGCRescanEnd = space->bottom;
634    }
635    if (start < end)
636    {
637        if (debugOptions & DEBUG_GC_ENHANCED)
638            Log("GC: Mark: Rescanning from %p to %p\n", start, end);
639        ScanAddressesInRegion(start, end);
640        return true; // Require rescan
641    }
642    else return false;
643}
644
645// When the threads created by marking the roots have completed we need to check that
646// the mark stack has not overflowed.  If it has we need to rescan.  This rescanning
647// pass may result in a further overflow so if we find we have to rescan we repeat.
648bool MTGCProcessMarkPointers::RescanForStackOverflow()
649{
650    ASSERT(nThreads >= 1);
651    ASSERT(nInUse == 0);
652    MTGCProcessMarkPointers *marker = &markStacks[0];
653    marker->Reset();
654    marker->active = true;
655    nInUse = 1;
656    bool rescan = false;
657    Rescanner rescanner(marker);
658
659    for (std::vector<LocalMemSpace*>::iterator i = gMem.lSpaces.begin(); i < gMem.lSpaces.end(); i++)
660    {
661        if (rescanner.ScanSpace(*i))
662            rescan = true;
663    }
664    for (std::vector<CodeSpace *>::iterator i = gMem.cSpaces.begin(); i < gMem.cSpaces.end(); i++)
665    {
666        if (rescanner.ScanSpace(*i))
667            rescan = true;
668    }
669    {
670        PLocker lock(&stackLock);
671        nInUse--;
672        marker->active = false;
673    }
674    return rescan;
675}
676
677static void SetBitmaps(LocalMemSpace *space, PolyWord *pt, PolyWord *top)
678{
679    while (pt < top)
680    {
681        PolyObject *obj = (PolyObject*)++pt;
682        // If it has been copied by a minor collection skip it
683        if (obj->ContainsForwardingPtr())
684        {
685            obj = FollowForwarding(obj);
686            ASSERT(obj->ContainsNormalLengthWord());
687            pt += obj->Length();
688        }
689        else
690        {
691            POLYUNSIGNED L = obj->LengthWord();
692            POLYUNSIGNED n = OBJ_OBJECT_LENGTH(L);
693            if (L & _OBJ_GC_MARK)
694            {
695                obj->SetLengthWord(L & ~(_OBJ_GC_MARK));
696                POLYUNSIGNED bitno = space->wordNo(pt);
697                space->bitmap.SetBits(bitno - 1, n + 1);
698
699                if (OBJ_IS_MUTABLE_OBJECT(L))
700                    space->m_marked += n + 1;
701                else
702                    space->i_marked += n + 1;
703
704                if ((PolyWord*)obj <= space->fullGCLowerLimit)
705                    space->fullGCLowerLimit = (PolyWord*)obj-1;
706
707                if (OBJ_IS_WEAKREF_OBJECT(L))
708                {
709                    // Add this to the limits for the containing area.
710                    PolyWord *baseAddr = (PolyWord*)obj;
711                    PolyWord *startAddr = baseAddr-1; // Must point AT length word.
712                    PolyWord *endObject = baseAddr + n;
713                    if (startAddr < space->lowestWeak) space->lowestWeak = startAddr;
714                    if (endObject > space->highestWeak) space->highestWeak = endObject;
715                }
716            }
717            pt += n;
718        }
719    }
720}
721
722static void CreateBitmapsTask(GCTaskId *, void *arg1, void *arg2)
723{
724    LocalMemSpace *lSpace = (LocalMemSpace *)arg1;
725    lSpace->bitmap.ClearBits(0, lSpace->spaceSize());
726    SetBitmaps(lSpace, lSpace->bottom, lSpace->top);
727}
728
729// Parallel task to check the marks on cells in the code area and
730// turn them into byte areas if they are free.
731static void CheckMarksOnCodeTask(GCTaskId *, void *arg1, void *arg2)
732{
733    CodeSpace *space = (CodeSpace*)arg1;
734    PolyWord *pt = space->bottom;
735    PolyWord *lastFree = 0;
736    POLYUNSIGNED lastFreeSpace = 0;
737    space->largestFree = 0;
738    space->firstFree = 0;
739    while (pt < space->top)
740    {
741        PolyObject *obj = (PolyObject*)(pt+1);
742        // There should not be forwarding pointers
743        ASSERT(obj->ContainsNormalLengthWord());
744        POLYUNSIGNED L = obj->LengthWord();
745        POLYUNSIGNED length = OBJ_OBJECT_LENGTH(L);
746        if (L & _OBJ_GC_MARK)
747        {
748            // It's marked - retain it.
749            ASSERT(L & _OBJ_CODE_OBJ);
750            obj->SetLengthWord(L & ~(_OBJ_GC_MARK)); // Clear the mark bit
751            lastFree = 0;
752            lastFreeSpace = 0;
753        }
754        else { // Turn it into a byte area i.e. free.  It may already be free.
755            if (space->firstFree == 0) space->firstFree = pt;
756            space->headerMap.ClearBit(pt-space->bottom); // Remove the "header" bit
757            if (lastFree + lastFreeSpace == pt)
758                // Merge free spaces.  Speeds up subsequent scans.
759                lastFreeSpace += length + 1;
760            else
761            {
762                lastFree = pt;
763                lastFreeSpace = length + 1;
764            }
765            PolyObject *freeSpace = (PolyObject*)(lastFree+1);
766            freeSpace->SetLengthWord(lastFreeSpace-1, F_BYTE_OBJ);
767            if (lastFreeSpace > space->largestFree) space->largestFree = lastFreeSpace;
768        }
769        pt += length+1;
770    }
771}
772
773void GCMarkPhase(void)
774{
775    mainThreadPhase = MTP_GCPHASEMARK;
776
777    // Clear the mark counters and set the rescan limits.
778    for(std::vector<LocalMemSpace*>::iterator i = gMem.lSpaces.begin(); i < gMem.lSpaces.end(); i++)
779    {
780        LocalMemSpace *lSpace = *i;
781        lSpace->i_marked = lSpace->m_marked = 0;
782        lSpace->fullGCRescanStart = lSpace->top;
783        lSpace->fullGCRescanEnd = lSpace->bottom;
784    }
785    for (std::vector<CodeSpace *>::iterator i = gMem.cSpaces.begin(); i < gMem.cSpaces.end(); i++)
786    {
787        CodeSpace *space = *i;
788        space->fullGCRescanStart = space->top;
789        space->fullGCRescanEnd = space->bottom;
790    }
791
792    MTGCProcessMarkPointers::MarkRoots();
793    gpTaskFarm->WaitForCompletion();
794
795    // Do we have to rescan because the mark stack overflowed?
796    bool rescan;
797    do {
798        rescan = MTGCProcessMarkPointers::RescanForStackOverflow();
799        gpTaskFarm->WaitForCompletion();
800    } while(rescan);
801
802    gHeapSizeParameters.RecordGCTime(HeapSizeParameters::GCTimeIntermediate, "Mark");
803
804    // Turn the marks into bitmap entries.
805    for (std::vector<LocalMemSpace*>::iterator i = gMem.lSpaces.begin(); i < gMem.lSpaces.end(); i++)
806        gpTaskFarm->AddWorkOrRunNow(&CreateBitmapsTask, *i, 0);
807
808    // Process the code areas.
809    for (std::vector<CodeSpace *>::iterator i = gMem.cSpaces.begin(); i < gMem.cSpaces.end(); i++)
810        gpTaskFarm->AddWorkOrRunNow(&CheckMarksOnCodeTask, *i, 0);
811
812    gpTaskFarm->WaitForCompletion(); // Wait for completion of the bitmaps
813
814    gMem.RemoveEmptyCodeAreas();
815
816    gHeapSizeParameters.RecordGCTime(HeapSizeParameters::GCTimeIntermediate, "Bitmap");
817
818    POLYUNSIGNED totalLive = 0;
819    for(std::vector<LocalMemSpace*>::iterator i = gMem.lSpaces.begin(); i < gMem.lSpaces.end(); i++)
820    {
821        LocalMemSpace *lSpace = *i;
822        if (! lSpace->isMutable) ASSERT(lSpace->m_marked == 0);
823        totalLive += lSpace->m_marked + lSpace->i_marked;
824        if (debugOptions & DEBUG_GC_ENHANCED)
825            Log("GC: Mark: %s space %p: %" POLYUFMT " immutable words marked, %" POLYUFMT " mutable words marked\n",
826                                lSpace->spaceTypeString(), lSpace,
827                                lSpace->i_marked, lSpace->m_marked);
828    }
829    if (debugOptions & DEBUG_GC)
830        Log("GC: Mark: Total live data %" POLYUFMT " words\n", totalLive);
831}
832
833// Set up the stacks.
834void initialiseMarkerTables()
835{
836    unsigned threads = gpTaskFarm->ThreadCount();
837    if (threads == 0) threads = 1;
838    MTGCProcessMarkPointers::InitStatics(threads);
839}
840