MMgc::GC Class Reference

#include <GC.h>

Inheritance diagram for MMgc::GC:

MMgc::GCAllocObject List of all members.

Public Types

enum  { GCV_COREPLAYER, GCV_AVMCORE, GCV_COUNT }
enum  AllocFlags { kZero = 1, kContainsPointers = 2, kFinalize = 4, kRCObject = 8 }
enum  PageType { kNonGC = 0, kGCAllocPage = 1, kGCLargeAllocPageRest = 2, kGCLargeAllocPageFirst = 3 }

Public Member Functions

void * GetGCContextVariable (int var) const
void SetGCContextVariable (int var, void *val)
avmplus::AvmCorecore () const
 GC (GCHeap *heap)
 ~GC ()
void Collect ()
void MaybeGC (bool callerHasActiveRequest=false)
void * Alloc (size_t size, int flags=0)
void * AllocAlreadyLocked (size_t size, int flags=0)
void * Calloc (size_t num, size_t elsize, int flags=0)
void Free (const void *ptr)
void SetQueued (const void *item)
void * AllocBlock (int size, int pageType, bool zero=true)
void FreeBlock (void *ptr, uint32 size)
GCHeapGetGCHeap () const
bool IsPointerToGCPage (const void *item)
void IncrementalMark ()
bool IncrementalMarking ()
void writeBarrier (const void *container, const void *address, const void *value)
void writeBarrierRC (const void *container, const void *address, const void *value)
__forceinline void WriteBarrierNoSubstitute (const void *container, const void *value)
__forceinline void WriteBarrierTrap (const void *container, const void *valuePtr)
void ConservativeWriteBarrierNoSubstitute (const void *address, const void *value)
bool ContainsPointers (const void *item)
void * FindBeginning (const void *gcItem)
bool IsRCObject (const void *)
bool Collecting () const
bool IsGCMemory (const void *)
bool IsQueued (const void *item)
void DisableThreadCheck ()
void CleanStack (bool force=false)
bool Destroying ()
void ClearWeakRef (const void *obj)
uintptr GetStackTop () const
void PushWorkItem (GCWorkItem &item)
void UpdateStat (const char *key, int delta)
size_t GetBytesInUse ()

Static Public Member Functions

static size_t Size (const void *ptr)
static int GetMark (const void *item)
static int SetMark (const void *item)
static void ClearFinalized (const void *item)
static void SetFinalize (const void *item)
static int IsFinalized (const void *item)
static int HasWeakRef (const void *item)
static GCGetGC (const void *item)
static void WriteBarrier (const void *address, const void *value)
static void WriteBarrierNoSub (const void *address, const void *value)
static uint64 GetPerformanceCounter ()
static uint64 GetPerformanceFrequency ()
static double duration (uint64 start)
static uint64 ticksToMicros (uint64 ticks)
static uint64 ticksToMillis (uint64 ticks)
static GCWeakRefGetWeakRef (const void *obj)

Public Attributes

bool greedy
bool nogc
bool findUnmarkedPointers
bool validateDefRef
bool keepDRCHistory
size_t collectThreshold
bool gcstats
bool dontAddToZCTDuringCollection
bool incrementalValidation
bool incremental
const uint64 t0
uint64 bytesMarked
uint64 markTicks
uint32 lastStartMarkIncrementCount
uint32 markIncrements
uint32 marks
uint32 sweeps
uint32 numObjects
uint32 objSize
uint64 sweepStart
bool hitZeroObjects

Protected Member Functions

void CollectWithBookkeeping (bool callerHoldsLock, bool callerHasActiveRequest)

Private Member Functions

__forceinline void WriteBarrierWrite (const void *address, const void *value)
__forceinline void WriteBarrierWriteRC (const void *address, const void *value)
void * heapAlloc (size_t size, bool expand=true, bool zero=true)
void heapFree (void *ptr, size_t siz=0)
void gclog (const char *format,...)
void log_mem (const char *name, size_t s, size_t comp)
uint32GetBits (int numBytes, int sizeClass)
void FreeBits (uint32 *bits, int sizeClass)
void StartIncrementalMark ()
void FinishIncrementalMark ()
int IsWhite (const void *item)
void updateGrossMemoryStats ()
int GetPageMapValue (uintptr addr) const
int GetPageMapValueAlreadyLocked (uintptr addr) const
void SetPageMapValue (uintptr addr, int val)
void ClearPageMapValue (uintptr addr)
void MarkGCPages (void *item, uint32 numpages, int val)
void UnmarkGCPages (void *item, uint32 numpages)
void ConservativeMarkRegion (const void *base, size_t bytes)
void * AllocBlockIncremental (int size, bool zero=true)
void * AllocBlockNonIncremental (int size, bool zero=true)
void CollectImpl ()
void ClearMarks ()
void Finalize ()
void Sweep (bool force=false)
void ForceSweep ()
void Mark (GCStack< GCWorkItem > &work)
void MarkQueueAndStack (GCStack< GCWorkItem > &work)
void MarkItem (GCStack< GCWorkItem > &work)
void MarkItem (GCWorkItem &workitem, GCStack< GCWorkItem > &work)
void TrapWrite (const void *black, const void *white)
void AddToSmallEmptyBlockList (GCAlloc::GCBlock *b)
void AddToLargeEmptyBlockList (GCLargeAlloc::LargeBlock *lb)
void AddRoot (GCRoot *root)
void RemoveRoot (GCRoot *root)
void AddCallback (GCCallback *cb)
void RemoveCallback (GCCallback *cb)
void CheckThread ()
void PushWorkItem (GCStack< GCWorkItem > &stack, GCWorkItem item)

Static Private Member Functions

static const void * Pointer (const void *p)

Private Attributes

uint32m_bitsFreelists [kNumSizeClasses]
uint32m_bitsNext
GCHashtable weakRefs
bool destroying
size_t heapSizeAtLastAlloc
bool stackCleaned
const void * rememberedStackTop
const void * rememberedStackBottom
bool disableThreadCheck
bool marking
GCStack< GCWorkItemm_incrementalWork
uint64 lastMarkTicks
uint64 lastSweepTicks
void * m_contextVars [GCV_COUNT]
uintptr memStart
uintptr memEnd
size_t totalGCPages
GCHashtable stats
unsigned char * pageMap
GCAlloccontainsPointersAllocs [kNumSizeClasses]
GCAllocnoPointersAllocs [kNumSizeClasses]
GCLargeAlloclargeAlloc
GCHeapheap
unsigned int allocsSinceCollect
bool collecting
bool finalizedValue
GCAlloc::GCBlocksmallEmptyPageList
GCLargeAlloc::LargeBlocklargeEmptyPageList
GCRootm_roots
GCCallbackm_callbacks

Static Private Attributes

static const int kNumSizeClasses = 40
static const int kPageUsableSpace = 3936
static const int16 kSizeClasses [kNumSizeClasses]
static const uint8 kSizeClassIndex [246]

Friends

class GCRoot
class GCCallback
class GCAlloc
class GCLargeAlloc
class RCObject
class GCInterval
class ZCT

Detailed Description

This is a general-purpose garbage collector used by the Flash Player. Application code must implement the GCRoot interface to mark all reachable data. Unreachable data is automatically destroyed. Objects may optionally be finalized by subclassing the GCObject interface.

This garbage collector is intended to be modular, such that it can be used in other products or replaced with a different collector in the future.

Memory allocation and garbage collection strategy: Mark and sweep garbage collector using fixed size classes implemented by the GCAlloc class. Memory blocks are obtained from the OS via the GCHeap heap manager class.

When an allocation fails because a suitable memory block is not available, the garbage collector decides either to garbage collect to free up space, or to expand the heap. The heuristic used to make the decision to collect or expand is taken from the Boehm-Demers-Weiser (BDW) garbage collector and memory allocator. The BDW algorithm is (pseudo-code):

if (allocs since collect >= heap size / FSD) collect else expand(request size + heap size / FSD)

The FSD is the "Free Space Divisor." For the first cut, I'm trying 4. TODO: Try various FSD values against real Player workloads to find the optimum value.

Definition at line 545 of file GC.h.


Member Enumeration Documentation

anonymous enum
 

If you need context vars use this!

Enumerator:
GCV_COREPLAYER 
GCV_AVMCORE 
GCV_COUNT 

Definition at line 559 of file GC.h.

00560         {
00561             GCV_COREPLAYER,
00562             GCV_AVMCORE,
00563             GCV_COUNT
00564         };

enum MMgc::GC::AllocFlags
 

flags to be passed as second argument to alloc

Enumerator:
kZero 
kContainsPointers 
kFinalize 
kRCObject 

Definition at line 676 of file GC.h.

00677         {
00678             kZero=1,
00679             kContainsPointers=2,
00680             kFinalize=4,
00681             kRCObject=8
00682         };

enum MMgc::GC::PageType
 

Enumerator:
kNonGC 
kGCAllocPage 
kGCLargeAllocPageRest 
kGCLargeAllocPageFirst 

Definition at line 684 of file GC.h.

00685         {
00686             kNonGC = 0,
00687             kGCAllocPage = 1,
00688             kGCLargeAllocPageRest = 2,
00689             kGCLargeAllocPageFirst = 3
00690         };


Constructor & Destructor Documentation

MMgc::GC::GC GCHeap heap  ) 
 

Definition at line 229 of file GC.cpp.

References MMgc::GCWorkItem::_size, containsPointersAllocs, GCAlloc, util::threadpool::i, kNumSizeClasses, kSizeClasses, MMGC_STATIC_ASSERT, noPointersAllocs, MMgc::GCWorkItem::ptr, and rememberedStackBottom.

00230         :
00231 #ifdef MMGC_DRC
00232           zct(),
00233 #endif
00234           nogc(false),
00235           greedy(false),
00236           findUnmarkedPointers(false),
00237           validateDefRef(false),
00238           keepDRCHistory(false),
00239           gcstats(false),
00240 #ifdef WRITE_BARRIERS
00241           incremental(true),
00242 #else
00243           incremental(false),
00244 #endif
00245           incrementalValidation(false),
00246 #ifdef _DEBUG
00247           // check for missing write barriers at every Alloc
00248           incrementalValidationPedantic(false),
00249 #endif
00250 
00251           marking(false),
00252           memStart(MAX_UINTPTR),
00253           memEnd(0),
00254           heap(gcheap),
00255           allocsSinceCollect(0),
00256           collecting(false),
00257           m_roots(0),
00258           m_callbacks(0),
00259           markTicks(0),
00260           bytesMarked(0),
00261           markIncrements(0),
00262           marks(0),
00263           sweeps(0),
00264           totalGCPages(0),
00265           stackCleaned(true),
00266           rememberedStackTop(0),
00267           destroying(false),
00268           lastMarkTicks(0),
00269           lastSweepTicks(0),
00270           lastStartMarkIncrementCount(0),
00271           t0(GetPerformanceCounter()),
00272           dontAddToZCTDuringCollection(false),
00273           numObjects(0),
00274           hitZeroObjects(false),
00275           smallEmptyPageList(NULL),
00276           largeEmptyPageList(NULL),
00277           sweepStart(0),
00278           heapSizeAtLastAlloc(gcheap->GetTotalHeapSize()),
00279           finalizedValue(true),
00280           // Expand, don't collect, until we hit this threshold
00281           collectThreshold(256),
00282 #if MMGC_THREADSAFE
00283           m_exclusiveGCThread(NULL),
00284           m_gcRunning(false),
00285           m_condDone(m_lock),
00286           m_requestCount(0),
00287           m_condNoRequests(m_lock)
00288 #else
00289           disableThreadCheck(false)
00290 #endif
00291     {
00292         // sanity check for all our types
00293         MMGC_STATIC_ASSERT(sizeof(int8) == 1);
00294         MMGC_STATIC_ASSERT(sizeof(uint8) == 1);     
00295         MMGC_STATIC_ASSERT(sizeof(int16) == 2);
00296         MMGC_STATIC_ASSERT(sizeof(uint16) == 2);
00297         MMGC_STATIC_ASSERT(sizeof(int32) == 4);
00298         MMGC_STATIC_ASSERT(sizeof(uint32) == 4);
00299         MMGC_STATIC_ASSERT(sizeof(int64) == 8);
00300         MMGC_STATIC_ASSERT(sizeof(uint64) == 8);
00301         MMGC_STATIC_ASSERT(sizeof(sintptr) == sizeof(void *));
00302         MMGC_STATIC_ASSERT(sizeof(uintptr) == sizeof(void *));
00303         #ifdef MMGC_64BIT
00304         MMGC_STATIC_ASSERT(sizeof(sintptr) == 8);
00305         MMGC_STATIC_ASSERT(sizeof(uintptr) == 8);   
00306         #else   
00307         MMGC_STATIC_ASSERT(sizeof(sintptr) == 4);
00308         MMGC_STATIC_ASSERT(sizeof(uintptr) == 4);   
00309         #endif      
00310     
00311         {
00312             GCWorkItem item;
00313             MMGC_GET_STACK_EXTENTS(this, item.ptr, item._size);
00314             rememberedStackBottom =  (const void *)((const char *)item.ptr + item._size);
00315         }
00316 
00317 #ifdef MMGC_DRC
00318         zct.SetGC(this);
00319 #endif
00320         // Create all the allocators up front (not lazy)
00321         // so that we don't have to check the pointers for
00322         // NULL on every allocation.
00323         for (int i=0; i<kNumSizeClasses; i++) {         
00324             containsPointersAllocs[i] = new GCAlloc(this, kSizeClasses[i], true, false, i);
00325 #ifdef MMGC_DRC
00326             containsPointersRCAllocs[i] = new GCAlloc(this, kSizeClasses[i], true, true, i);
00327 #endif
00328             noPointersAllocs[i] = new GCAlloc(this, kSizeClasses[i], false, false, i);
00329         }
00330         
00331         largeAlloc = new GCLargeAlloc(this);
00332 
00333         pageMap = (unsigned char*) heapAlloc(1);
00334 
00335         memset(m_bitsFreelists, 0, sizeof(uint32*) * kNumSizeClasses);
00336         m_bitsNext = (uint32*)heapAlloc(1);
00337 
00338         // precondition for emptyPageList 
00339         GCAssert(offsetof(GCLargeAlloc::LargeBlock, next) == offsetof(GCAlloc::GCBlock, next));
00340 
00341         
00342         for(int i=0; i<GCV_COUNT; i++)
00343         {
00344             SetGCContextVariable(i, NULL);
00345         }
00346 
00347 #ifdef _DEBUG
00348         // this doens't hurt performance too much so alway leave it on in DEBUG builds
00349         // before sweeping we check for missing write barriers
00350         incrementalValidation = true;
00351 #ifdef WIN32
00352         m_gcThread = GetCurrentThreadId();
00353 #endif
00354 #endif
00355 
00356         // keep GC::Size honest
00357         GCAssert(offsetof(GCLargeAlloc::LargeBlock, usableSize) == offsetof(GCAlloc::GCBlock, size));
00358 
00359 #ifndef MMGC_PORTING_API
00360 #ifndef MMGC_ARM // TODO MMGC_ARM
00361 #ifdef _DEBUG
00362         if (!nogc)
00363             RunGCTests(this);
00364 #endif
00365 #endif
00366 #endif
00367 
00368         // keep GC::Size honest
00369         GCAssert(offsetof(GCLargeAlloc::LargeBlock, usableSize) == offsetof(GCAlloc::GCBlock, size));
00370 
00371     }

MMgc::GC::~GC  ) 
 

Definition at line 373 of file GC.cpp.

References ClearMarks(), destroying, ForceSweep(), util::threadpool::i, kNumSizeClasses, m_bitsFreelists, next, and NULL.

00374     {
00375         // Force all objects to be destroyed
00376         destroying = true;
00377         ClearMarks();
00378         ForceSweep();
00379 
00380         // Go through m_bitsFreelist and collect list of all pointers
00381         // that are on page boundaries into new list, pageList
00382         void **pageList = NULL;
00383         for(int i=0, n=kNumSizeClasses; i<n; i++) {
00384             uint32* bitsFreelist = m_bitsFreelists[i];
00385             while(bitsFreelist) {
00386                 uint32 *next = *(uint32**)bitsFreelist;
00387                 if(((uintptr)bitsFreelist & 0xfff) == 0) {
00388                     *((void**)bitsFreelist) = pageList;
00389                     pageList = (void**)bitsFreelist;
00390                 }
00391                 bitsFreelist = next;
00392             } 
00393         }
00394         
00395         // Go through page list and free all pages on it
00396         while (pageList) {
00397             void **next = (void**) *pageList;
00398             heap->Free((void*)pageList);
00399             pageList = next;
00400         }
00401 
00402         for (int i=0; i < kNumSizeClasses; i++) {
00403             delete containsPointersAllocs[i];
00404 #ifdef MMGC_DRC
00405             delete containsPointersRCAllocs[i];
00406 #endif
00407             delete noPointersAllocs[i];
00408         }
00409 
00410         if (largeAlloc) {
00411             delete largeAlloc;
00412         }
00413 
00414         // dtors for each GCAlloc will use this
00415         pageList = NULL;
00416 
00417         heap->Free(pageMap);
00418 
00419 #ifndef MMGC_THREADSAFE
00420         CheckThread();
00421 #endif
00422 
00423         GCAssert(!m_roots);
00424         GCAssert(!m_callbacks);
00425 
00426         {
00427             GCSpinLock lock(m_rootListLock);
00428             // apparently the player can't be made to clean up so keep it from crashing at least
00429             while(m_roots) {
00430                 m_roots->Destroy();
00431             }
00432         }
00433 
00434         while(m_callbacks) {
00435             m_callbacks->Destroy();         
00436         }
00437     }


Member Function Documentation

void MMgc::GC::AddCallback GCCallback cb  )  [private]
 

Definition at line 3146 of file GC.cpp.

References m_callbacks, MMgc::GCCallback::nextCB, NULL, MMgc::GCCallback::prevCB, and USING_CALLBACK_LIST.

Referenced by MMgc::GCCallback::GCCallback().

03147     {
03148         USING_CALLBACK_LIST(this);
03149 
03150         cb->prevCB = NULL;
03151         cb->nextCB = m_callbacks;
03152         if(m_callbacks)
03153             m_callbacks->prevCB = cb;
03154         m_callbacks = cb;
03155     }

void MMgc::GC::AddRoot GCRoot root  )  [private]
 

Definition at line 3120 of file GC.cpp.

References m_roots, MMgc::GCRoot::next, NULL, and MMgc::GCRoot::prev.

Referenced by MMgc::GCRoot::init().

03121     {
03122 #ifdef GCHEAP_LOCK
03123         GCAcquireSpinlock lock(m_rootListLock);
03124 #endif
03125         root->prev = NULL;
03126         root->next = m_roots;
03127         if(m_roots)
03128             m_roots->prev = root;
03129         m_roots = root;
03130     }

void MMgc::GC::AddToLargeEmptyBlockList GCLargeAlloc::LargeBlock lb  )  [inline, private]
 

Requires(exclusiveGC)

Definition at line 1412 of file GC.h.

References MMgc::GCLargeAlloc::LargeBlock::next.

Referenced by MMgc::GCLargeAlloc::Finalize().

01413         {
01414             lb->next = largeEmptyPageList;
01415             largeEmptyPageList = lb;
01416         }

void MMgc::GC::AddToSmallEmptyBlockList GCAlloc::GCBlock b  )  [inline, private]
 

Requires(exclusiveGC)

Definition at line 1399 of file GC.h.

References MMgc::GCAlloc::GCBlock::next.

01400         {
01401             b->next = smallEmptyPageList;
01402             smallEmptyPageList = b;
01403         }

void * MMgc::GC::Alloc size_t  size,
int  flags = 0
 

Main interface for allocating memory. Default flags is no finalization, contains pointers is set and zero is set.

Do not call this from a finalizer.

Requires(request)

Definition at line 655 of file GC.cpp.

References AllocAlreadyLocked(), CheckThread(), and GCAssert.

Referenced by avmplus::AvmCore::allocDouble(), Calloc(), avmplus::Toplevel::decode(), avmplus::MethodEnv::delegateInvoke(), avmplus::BitSet::grow(), avmplus::MultinameHashtable::Init(), avmplus::Hashtable::initialize(), avmplus::Traits::initTables(), avmplus::interp(), main(), MMgc::GCWeakRef::operator new(), MMgc::GCObject::operator new(), operator new(), MMgc::GCFinalizedObjectOptIn::operator new(), MMgc::GCFinalizedObject::operator new(), avmplus::BasicScriptBufferImpl::operator new(), avmplus::ArrayClass::sortOn(), avmplus::String::String(), avmplus::StringNullTerminatedUTF8::StringNullTerminatedUTF8(), avmplus::StringOutputStream::StringOutputStream(), avmplus::MethodInfo::verifyEnter(), and avmplus::StringOutputStream::write().

00656     {
00657 #ifdef MMGC_THREADSAFE
00658         GCAutoLock _lock(m_lock);
00659         GCAssert(!m_gcRunning);
00660 #else
00661         CheckThread();
00662 #endif
00663         return AllocAlreadyLocked(size, flags);
00664     }

void * MMgc::GC::AllocAlreadyLocked size_t  size,
int  flags = 0
 

Requires(request && m_lock)

Definition at line 666 of file GC.cpp.

References MMgc::GCLargeAlloc::Alloc(), MMgc::GCAlloc::Alloc(), CollectWithBookkeeping(), containsPointersAllocs, core(), DebugSize, GCAssert, GCAssertMsg, GCV_AVMCORE, GetGCContextVariable(), GetUserPointer, greedy, kContainsPointers, MMgc::kLargestAlloc, kRCObject, kSizeClassIndex, kZero, largeAlloc, marking, noPointersAllocs, NULL, SAMPLE_ALLOC, Size(), and StartIncrementalMark().

Referenced by Alloc(), and MMgc::GCWeakRef::operator new().

00667     {
00668 #ifdef FEATURE_SAMPLER
00669         avmplus::AvmCore *core = (avmplus::AvmCore*)GetGCContextVariable(GCV_AVMCORE);
00670         if(core)
00671             core->sampleCheck();
00672 #endif
00673         GCAssertMsg(size > 0, "cannot allocate a 0 sized block\n");
00674 
00675 #ifdef _DEBUG
00676         GCAssert(size + 7 > size);
00677         if (GC::greedy) {
00678             CollectWithBookkeeping(true, true);
00679         }
00680         // always be marking in pedantic mode
00681         if(incrementalValidationPedantic) {
00682             if(!marking)
00683                 StartIncrementalMark();
00684         }
00685 #endif
00686 
00687         // overflow detection
00688         if(size+7 < size)
00689             return NULL;
00690 
00691         size = (size+7)&~7; // round up to multiple of 8
00692 
00693         size += DebugSize();
00694 
00695         GCAssertMsg(size > 0, "debug overflow, adding space for Debug stuff overflowed size_t\n");
00696     
00697         GCAlloc **allocs = noPointersAllocs;
00698 #ifdef MMGC_DRC
00699         if(flags & kRCObject) {
00700             allocs = containsPointersRCAllocs;
00701         } else 
00702 #endif
00703         if(flags & kContainsPointers) {
00704             allocs = containsPointersAllocs;
00705         }
00706 
00707         void *item;
00708         // Buckets up to 128 are spaced evenly at 8 bytes.
00709         if (size <= 128) {
00710             GCAlloc *b = (GCAlloc*)allocs[(size >> 3) - 1];
00711             GCAssert(size <= b->GetItemSize());
00712             item = b->Alloc(size, flags);
00713         } else if (size <= kLargestAlloc) {             
00714             // This is the fast lookup table implementation to
00715             // find the right allocator.
00716             unsigned index = kSizeClassIndex[(size>>3)-1];
00717 
00718             // assert that I fit 
00719             GCAssert(size <= allocs[index]->GetItemSize());
00720 
00721             // assert that I don't fit (makes sure we don't waste space)
00722             GCAssert(size > allocs[index-1]->GetItemSize());
00723 
00724             item = allocs[index]->Alloc(size, flags);
00725         } else {
00726             item = largeAlloc->Alloc(size, flags);
00727         }
00728 
00729 #ifdef MEMORY_INFO
00730         if(item)
00731         item = DebugDecorate(item,  GC::Size(GetUserPointer(item)) + DebugSize(), 3);
00732 #endif
00733 
00734 #ifdef _DEBUG
00735         bool shouldZero = (flags & kZero) || incrementalValidationPedantic;
00736         
00737         // in debug mode memory is poisoned so we have to clear it here
00738         // in release builds memory is zero'd to start and on free/sweep
00739         // in pedantic mode uninitialized data can trip the write barrier 
00740         // detector, only do it for pedantic because otherwise we want the
00741         // mutator to get the poisoned data so it crashes if it relies on 
00742         // uninitialized values
00743         if((item) && (shouldZero)) {
00744             memset(item, 0, Size(item));
00745         }
00746 #endif
00747 
00748         SAMPLE_ALLOC(item, GC::Size(item));
00749 
00750         return item;
00751     }

void * MMgc::GC::AllocBlock int  size,
int  pageType,
bool  zero = true
 

Used by sub-allocators to obtain memory.

Requires(m_lock)

Definition at line 1046 of file GC.cpp.

References MMgc::GCHeap::Alloc(), AllocBlockIncremental(), AllocBlockNonIncremental(), allocsSinceCollect, collecting, collectThreshold, CollectWithBookkeeping(), MMgc::GCHeap::ExpandHeap(), GCAssert, GetPerformanceCounter(), MMgc::GCHeap::GetTotalHeapSize(), heap, heapSizeAtLastAlloc, incremental, MMgc::GCHeap::kBlockSize, MMgc::kFreeSpaceDivisor, kGCLargeAllocPageFirst, kGCLargeAllocPageRest, MMgc::kMarkSweepBurstTicks, MMgc::kMaxIncrement, lastSweepTicks, MarkGCPages(), marking, MMGC_ASSERT_GC_LOCK, nogc, runtests::now, NULL, StartIncrementalMark(), and totalGCPages.

Referenced by MMgc::GCLargeAlloc::Alloc(), and MMgc::GCAlloc::CreateChunk().

01047     {
01048         MMGC_ASSERT_GC_LOCK(this);
01049 #ifdef DEBUGGER
01050         AllocActivity(size);
01051 #endif
01052         GCAssert(size > 0);
01053     
01054         // perform gc if heap expanded due to fixed memory allocations
01055         // utilize burst logic to prevent this from happening back to back
01056         // this logic is here to apply to incremental and non-incremental
01057         uint64 now = GetPerformanceCounter();
01058         if(!marking && !collecting &&
01059             heapSizeAtLastAlloc > collectThreshold &&
01060             now - lastSweepTicks > kMarkSweepBurstTicks && 
01061             heapSizeAtLastAlloc < heap->GetTotalHeapSize()) 
01062         {
01063             if(incremental && !nogc)
01064                 StartIncrementalMark();
01065             else
01066                 CollectWithBookkeeping(true, true);
01067         }
01068 
01069         void *item;
01070 
01071         if(incremental && !nogc)
01072             item = AllocBlockIncremental(size, zero);
01073         else
01074             item = AllocBlockNonIncremental(size, zero);
01075 
01076         if(!item) {             
01077             int incr = (int)(size + totalGCPages / kFreeSpaceDivisor);
01078             if(incr > kMaxIncrement) {
01079                 incr = size < kMaxIncrement ? kMaxIncrement : size;
01080             }
01081             heap->ExpandHeap(incr);
01082             item = heap->Alloc(size, false);
01083         }
01084 
01085         GCAssert(item != NULL);
01086         if (item != NULL)
01087         {
01088             allocsSinceCollect += size;
01089 
01090             // mark GC pages in page map, small pages get marked one,
01091             // the first page of large pages is 3 and the rest are 2
01092             MarkGCPages(item, 1, pageType);
01093             if(pageType == kGCLargeAllocPageFirst) {
01094                 MarkGCPages((char*)item+GCHeap::kBlockSize, size - 1, kGCLargeAllocPageRest);
01095             }
01096             totalGCPages += size;
01097         }
01098 
01099         // do this after any heap expansions from GC
01100         heapSizeAtLastAlloc = heap->GetTotalHeapSize();
01101 
01102         return item;
01103     }

void * MMgc::GC::AllocBlockIncremental int  size,
bool  zero = true
[private]
 

Requires(m_lock)

Definition at line 1105 of file GC.cpp.

References MMgc::GCHeap::Alloc(), allocsSinceCollect, collecting, collectThreshold, FinishIncrementalMark(), GCAssert, GetPerformanceCounter(), heap, IncrementalMark(), incrementalValidation, MMgc::kFreeSpaceDivisor, MMgc::kIncrementalMarkDelayTicks, MMgc::kMarkSweepBurstTicks, lastMarkTicks, lastSweepTicks, marking, MMGC_ASSERT_GC_LOCK, nogc, runtests::now, StartIncrementalMark(), and totalGCPages.

Referenced by AllocBlock().

01106     {
01107         MMGC_ASSERT_GC_LOCK(this);
01108 
01109         if(!collecting || incrementalValidation) {
01110             uint64 now = GetPerformanceCounter();
01111             if (marking) {      
01112                 if(now - lastMarkTicks > kIncrementalMarkDelayTicks) {
01113                     IncrementalMark();
01114                 }
01115             } else if (incrementalValidation ||
01116                 (totalGCPages > collectThreshold &&
01117                 allocsSinceCollect * kFreeSpaceDivisor >= totalGCPages &&
01118                 // burst detection
01119                 (now - lastSweepTicks > kMarkSweepBurstTicks))) {
01120                     StartIncrementalMark();
01121             }
01122         }
01123 
01124         void *item = heap->Alloc(size, false, zero);
01125         if(!item && !collecting) {
01126             if(marking) {
01127                 GCAssert(!nogc);
01128                 FinishIncrementalMark();
01129                 item = heap->Alloc(size, false, zero);
01130             }
01131         }
01132         return item;
01133     }

void * MMgc::GC::AllocBlockNonIncremental int  size,
bool  zero = true
[private]
 

Requires(m_lock)

Definition at line 1135 of file GC.cpp.

References MMgc::GCHeap::Alloc(), allocsSinceCollect, collectThreshold, CollectWithBookkeeping(), MMgc::GCHeap::GetTotalHeapSize(), heap, MMgc::kFreeSpaceDivisor, MMGC_ASSERT_GC_LOCK, and totalGCPages.

Referenced by AllocBlock().

01136     {
01137         MMGC_ASSERT_GC_LOCK(this);
01138 
01139         void *item = heap->Alloc(size, false, zero);
01140         if (!item) {
01141             if (heap->GetTotalHeapSize() >= collectThreshold &&
01142                 allocsSinceCollect >= totalGCPages / kFreeSpaceDivisor) 
01143             {
01144                 CollectWithBookkeeping(true, true);
01145                 item = heap->Alloc(size, false, zero);
01146             }
01147         }
01148         return item;
01149     }

void * MMgc::GC::Calloc size_t  num,
size_t  elsize,
int  flags = 0
 

overflow checking way to call Alloc for a # of n size'd items, all instance of Alloc(num*sizeof(thing)) should be replaced with: Calloc(num, sizeof(thing))

Do not call this from a finalizer.

Requires(request)

Definition at line 789 of file GC.cpp.

References Alloc(), GCAssertMsg, and NULL.

Referenced by avmplus::AtomArray::AtomArray(), avmplus::AtomArray::checkCapacity(), avmplus::SortedIntMap< FrameState * >::ensureCapacity(), avmplus::MultinameHashtable::grow(), avmplus::Hashtable::grow(), avmplus::AbstractFunction::initDefaultValues(), avmplus::Traits::initMetadataTable(), avmplus::AbstractFunction::initParamTypes(), avmplus::AbcParser::parseMetadataInfos(), and avmshell::ShellToplevel::ShellToplevel().

00790     {
00791         uint64 size = (uint64)num * (uint64)elsize;
00792         if(size > 0xfffffff0) 
00793         {
00794             GCAssertMsg(false, "Attempted allocation overflows size_t\n");
00795             return NULL;
00796         }
00797         return Alloc(num * elsize, flags);
00798     }

void MMgc::GC::CheckThread  )  [private]
 

Definition at line 1424 of file GC.cpp.

References disableThreadCheck, and GCAssertMsg.

Referenced by Alloc(), CollectWithBookkeeping(), and Free().

01425     {
01426 #ifdef _DEBUG
01427 #ifdef WIN32
01428         GCAssertMsg(disableThreadCheck || m_gcThread == GetCurrentThreadId(), "Unsafe access to GC from wrong thread!");
01429 #endif
01430 #endif
01431     }

void MMgc::GC::CleanStack bool  force = false  ) 
 

Definition at line 1279 of file GC.cpp.

References rememberedStackBottom, rememberedStackTop, and stackCleaned.

01280     {
01281 #if defined(_MSC_VER) && (defined(_DEBUG) || defined(_ARM_))
01282         // debug builds poison the stack already
01283         (void)force;
01284         return;
01285 #else
01286         if(!force && (stackCleaned || rememberedStackTop == 0))
01287             return;
01288 
01289         stackCleaned = true;
01290         
01291         register void *stackP;
01292 
01293 #if defined MMGC_IA32
01294         #ifdef WIN32
01295         __asm {
01296             mov stackP,esp
01297         }
01298         #elif defined SOLARIS
01299         stackP = (void *) _getsp();
01300         #else
01301         asm("movl %%esp,%0" : "=r" (stackP));
01302         #endif
01303 #endif
01304 
01305 #if defined MMGC_AMD64
01306     #ifdef WIN32
01307         int foo;
01308         stackP = &foo;
01309     #else
01310         asm("mov %%rsp,%0" : "=r" (stackP));
01311     #endif
01312 #endif
01313 
01314 #if defined MMGC_SPARC
01315         stackP = (void *) _getsp();
01316 #endif
01317 
01318 #if defined MMGC_PPC
01319         // save off sp
01320     #ifdef _MAC
01321             asm("mr %0,r1" : "=r" (stackP));
01322     #else // _MAC
01323             asm("mr %0,%%r1" : "=r" (stackP));
01324     #endif // _MAC
01325 #endif // MMGC_PPC
01326 
01327         if( ((char*) stackP > (char*)rememberedStackTop) && ((char *)rememberedStackBottom > (char*)stackP)) {
01328             size_t amount = (char*) stackP - (char*)rememberedStackTop;
01329             void *stack = alloca(amount);
01330             if(stack) {
01331                 memset(stack, 0, amount);
01332             }
01333         }
01334 #endif // __MSC_VER && _DEBUG
01335     }

static void MMgc::GC::ClearFinalized const void *  item  )  [inline, static]
 

Definition at line 776 of file GC.h.

References MMgc::GCAlloc::ClearFinalized(), MMgc::GCLargeAlloc::ClearFinalized(), GCAssert, GetRealPointer, MMgc::GCLargeAlloc::IsLargeBlock(), and IsPointerToGCPage().

Referenced by Free().

00777         {
00778 #ifdef MEMORY_INFO
00779             GC *gc = GetGC(item);   
00780             item = GetRealPointer(item);
00781             GCAssert(gc->IsPointerToGCPage(item));
00782 #endif          
00783             if (GCLargeAlloc::IsLargeBlock(item)) {
00784                 GCLargeAlloc::ClearFinalized(item);
00785             } else {
00786                 GCAlloc::ClearFinalized(item);
00787             }
00788         }

void MMgc::GC::ClearMarks  )  [private]
 

Requires(exclusiveGC)

Definition at line 875 of file GC.cpp.

References MMgc::GCAlloc::ClearMarks(), containsPointersAllocs, util::threadpool::i, kNumSizeClasses, MMGC_ASSERT_EXCLUSIVE_GC, MMGC_DRC, and noPointersAllocs.

Referenced by ~GC().

00876     {
00877         MMGC_ASSERT_EXCLUSIVE_GC(this);
00878 
00879         for (int i=0; i < kNumSizeClasses; i++) {
00880 #ifdef MMGC_DRC
00881             containsPointersRCAllocs[i]->ClearMarks();
00882 #endif
00883             containsPointersAllocs[i]->ClearMarks();
00884             noPointersAllocs[i]->ClearMarks();
00885         }
00886         largeAlloc->ClearMarks();
00887     }

void MMgc::GC::ClearPageMapValue uintptr  addr  )  [private]
 

Zero out the pageMap bits for the given address.

Requires(pageMapLock)

Definition at line 1197 of file GC.cpp.

References GCAssert, MMgc::GCHeap::kBlockSize, memStart, and pageMap.

Referenced by UnmarkGCPages().

01198     {
01199         uintptr index = (addr-memStart) >> 12;
01200 #ifdef MMGC_AMD64
01201         GCAssert((index >> 2) < uintptr(64*65536) * uintptr(GCHeap::kBlockSize));
01202 #else
01203         GCAssert((index >> 2) < 64 * GCHeap::kBlockSize);
01204 #endif
01205         pageMap[index >> 2] &= ~(3<<((index&0x3)*2));
01206     }   

void MMgc::GC::ClearWeakRef const void *  obj  ) 
 

Requires((request && m_lock) || exclusiveGC)

Definition at line 3204 of file GC.cpp.

References GCAssert, MMgc::GCWeakRef::get(), MMgc::GCHashtable::get(), GetRealPointer, MMgc::GCLargeAlloc::IsLargeBlock(), MMgc::GCWeakRef::m_obj, NULL, MMgc::GCHashtable::remove(), MMgc::GCAlloc::SetHasWeakRef(), MMgc::GCLargeAlloc::SetHasWeakRef(), and weakRefs.

Referenced by MMgc::GCLargeAlloc::Finalize(), MMgc::GCLargeAlloc::Free(), MMgc::GCAlloc::Free(), Free(), and MMgc::GCWeakRef::~GCWeakRef().

03205     {
03206         GCWeakRef *ref = (GCWeakRef*) weakRefs.remove(item);
03207         GCAssert(weakRefs.get(item) == NULL);
03208         GCAssert(ref != NULL);
03209         GCAssert(ref->get() == item || ref->get() == NULL);
03210         if(ref) {
03211             ref->m_obj = NULL;
03212             item = GetRealPointer(item);
03213             if (GCLargeAlloc::IsLargeBlock(item)) {
03214                 GCLargeAlloc::SetHasWeakRef(item, false);
03215             } else {
03216                 GCAlloc::SetHasWeakRef(item, false);
03217             }
03218         }
03219     }

void MMgc::GC::Collect  ) 
 

Causes an immediate garbage collection.

In an MMGC_THREADSAFE build, the caller must not be inside a request. If the caller is inside a request, call CollectFromRequest() instead.

Requires(!m_lock && !request)

Definition at line 439 of file GC.cpp.

References CollectWithBookkeeping().

00440     {
00441         CollectWithBookkeeping(false, false);
00442     }

void MMgc::GC::CollectImpl  )  [private]
 

Just collect.

Requires(exclusiveGC)

Definition at line 594 of file GC.cpp.

References FinishIncrementalMark(), marking, and StartIncrementalMark().

Referenced by CollectWithBookkeeping().

00595     {
00596 #ifndef MMGC_THREADSAFE
00597         ReapZCT();
00598 #endif
00599 
00600         if(!marking)
00601             StartIncrementalMark();
00602         if(marking)
00603             FinishIncrementalMark();
00604 
00605 #ifdef _DEBUG
00606         // Dumping the stack trace at GC time can be very helpful with stack walk bugs
00607         // where something was created, stored away in untraced, unmanaged memory and not 
00608         // reachable by the conservative stack walk
00609         //DumpStackTrace();
00610         FindUnmarkedPointers();
00611 #endif
00612     }

bool MMgc::GC::Collecting  )  const [inline]
 

True during Sweep phase. Application code can use this to determine if it's being called (directly or indirectly) from a finalizer.

See also:
IsGCRunning() Requires(request || exclusiveGC)

Definition at line 1002 of file GC.h.

01003         {
01004             return collecting;
01005         }

void MMgc::GC::CollectWithBookkeeping bool  callerHoldsLock,
bool  callerHasActiveRequest
[protected]
 

Collect in a thread-safe, recursion-preventing way, with callbacks.

Both parameters are ignored in non-MMGC_THREADSAFE builds. In an MMGC_THREADSAFE build, callerHoldsLock must be true iff the calling thread already holds m_lock, and callerHasActiveRequest must be true iff the calling thread is already in an active request.

Definition at line 444 of file GC.cpp.

References CheckThread(), CollectImpl(), collecting, GCAssert, GCRoot, m_callbacks, MMgc::GCCallback::nextCB, nogc, NULL, and USING_CALLBACK_LIST.

Referenced by AllocAlreadyLocked(), AllocBlock(), AllocBlockNonIncremental(), Collect(), and MaybeGC().

00446     {
00447 #ifdef MMGC_THREADSAFE
00448         GCAssert(callerHoldsLock == m_lock.IsHeld());
00449 #ifdef _DEBUG
00450         GCAssert(callerHasActiveRequest == GCThread::GetCurrentThread()->IsInActiveRequest());
00451 #endif
00452 #else
00453         (void) callerHoldsLock;
00454         (void) callerHasActiveRequest;
00455         CheckThread();
00456 #endif
00457 
00458 #ifdef MMGC_THREADSAFE
00459         if (!callerHoldsLock)
00460             m_lock.Acquire();
00461 
00462         if (nogc || m_gcRunning || zct.reaping) {
00463             if (!callerHoldsLock)
00464                 m_lock.Release();
00465             return;
00466         }
00467 #else
00468         if (nogc || collecting || zct.reaping) {
00469             return;
00470         }
00471 #endif
00472 
00473 #ifdef MMGC_THREADSAFE
00474         GCThread *thisThread = GCThread::GetCurrentThread();
00475         if (m_exclusiveGCThread != NULL) {
00476             // Someone is already collecting or waiting to collect.
00477             //
00478             // If it's the current thread, then we're being called
00479             // recursively.  This maybe shouldn't happen, but Collect can be
00480             // called indirectly from a finalizer.  Don't recurse, just ignore
00481             // it.
00482             //
00483             // If it's some other thread, wait for that thread to finish.
00484             //
00485             if (m_exclusiveGCThread != thisThread) {
00486                 GCRoot *stackRoot;
00487                 void *stack;
00488                 size_t stackSize;
00489 
00490                 // Call this macro here, not under "if
00491                 // (callerHasActiveRequest)", because it introduces local
00492                 // variables that must survive for the whole lifetime of
00493                 // stackRoot.
00494                 MMGC_GET_STACK_EXTENTS(this, stack, stackSize);
00495 
00496                 // Before waiting, this thread must suspend any active
00497                 // requests.  This avoids a deadlock where m_exclusiveGCThread
00498                 // is waiting for m_requestCount to go to zero while we're
00499                 // waiting for m_exclusiveGCThread to be done.
00500                 //
00501                 // When we do this, we root the calling thread's stack; this
00502                 // way each collection scans the stack of every thread that is
00503                 // in a suspended request.
00504                 //
00505                 if (callerHasActiveRequest) {
00506                     stackRoot = new GCRoot(this, stack, stackSize);
00507 
00508                     OnLeaveRequestAlreadyLocked();
00509                 }
00510 
00511                 while (m_exclusiveGCThread != NULL)
00512                     m_condDone.Wait();
00513 
00514                 if (callerHasActiveRequest) {
00515                     // Resume previously suspended request.
00516                     delete stackRoot;
00517                     OnEnterRequestAlreadyLocked();
00518                 }
00519             }
00520 
00521             if (!callerHoldsLock)
00522                 m_lock.Release();
00523             return;
00524         }
00525 
00526         // If we get here, this thread will collect.
00527         m_exclusiveGCThread = thisThread;
00528         if (callerHasActiveRequest) {
00529             // We must suspend any active requests on this thread.
00530             OnLeaveRequestAlreadyLocked();
00531         }
00532         // Wait for other threads to suspend or end their active requests,
00533         // if any.
00534         while (m_requestCount > 0)
00535             m_condNoRequests.Wait();
00536 
00537         // These should not have changed while we were waiting, even though we
00538         // released the lock.
00539         GCAssert(m_requestCount == 0);
00540         GCAssert(m_exclusiveGCThread == thisThread);
00541 
00542         // This thread has acquired exclusiveGC.
00543         m_gcRunning = true;
00544 #endif
00545 
00546         {
00547             USING_CALLBACK_LIST(this);
00548             for (GCCallback *cb = m_callbacks; cb; cb = cb->nextCB)
00549                 cb->enterExclusiveGC();
00550         }
00551 
00552 #ifdef MMGC_THREADSAFE
00553         m_lock.Release();
00554 #endif
00555 
00556         {
00557             USING_CALLBACK_LIST(this);
00558             for (GCCallback *cb = m_callbacks; cb; cb = cb->nextCB)
00559                 cb->enterExclusiveGCNoLock();
00560         }
00561 
00562         CollectImpl();
00563 
00564 #ifdef MMGC_THREADSAFE
00565         m_lock.Acquire();
00566 
00567         // These should not have changed during collection,
00568         // even though we released the lock.
00569         GCAssert(m_requestCount == 0);
00570         GCAssert(m_exclusiveGCThread == thisThread);
00571 #endif
00572 
00573         {
00574             USING_CALLBACK_LIST(this);
00575             for (GCCallback *cb = m_callbacks; cb; cb = cb->nextCB)
00576                 cb->leaveExclusiveGC();
00577         }
00578 
00579 #ifdef MMGC_THREADSAFE
00580         // This thread is relinquishing exclusiveGC.
00581         m_gcRunning = false;
00582 
00583         m_exclusiveGCThread = NULL;
00584         if (callerHasActiveRequest)
00585             OnEnterRequestAlreadyLocked();
00586 
00587         m_condDone.NotifyAll();
00588 
00589         if (!callerHoldsLock)
00590             m_lock.Release();
00591 #endif
00592     }

void MMgc::GC::ConservativeMarkRegion const void *  base,
size_t  bytes
[private]
 

Mark a region of memory, this will search all memory pointed to recursively and mark any GC Objects it finds

void MMgc::GC::ConservativeWriteBarrierNoSubstitute const void *  address,
const void *  value
[inline]
 

Definition at line 939 of file GC.h.

00940         {
00941             if(IsPointerToGCPage(address))
00942                 WriteBarrierNoSubstitute(FindBeginning(address), value);
00943         }

bool MMgc::GC::ContainsPointers const void *  item  ) 
 

Requires(request || exclusiveGC)

Definition at line 3051 of file GC.cpp.

References MMgc::GCAlloc::ContainsPointers(), MMgc::GCLargeAlloc::ContainsPointers(), GetRealPointer, and MMgc::GCLargeAlloc::IsLargeBlock().

Referenced by TrapWrite().

03052     {
03053         item = GetRealPointer(item);
03054         if (GCLargeAlloc::IsLargeBlock(item)) {
03055             return GCLargeAlloc::ContainsPointers(item);
03056         } else {
03057             return GCAlloc::ContainsPointers(item);
03058         }
03059     }

avmplus::AvmCore* MMgc::GC::core  )  const [inline]
 

Definition at line 568 of file GC.h.

Referenced by AllocAlreadyLocked(), IncrementalMark(), and Sweep().

bool MMgc::GC::Destroying  )  [inline]
 

Definition at line 1120 of file GC.h.

01120 { return destroying; }

void MMgc::GC::DisableThreadCheck  )  [inline]
 

Definition at line 1022 of file GC.h.

01022 { disableThreadCheck = true; }

static double MMgc::GC::duration uint64  start  )  [inline, static]
 

Definition at line 1016 of file GC.h.

References GetPerformanceCounter(), and GetPerformanceFrequency().

Referenced by Sweep().

01017         {
01018             return (double(GC::GetPerformanceCounter() - start) * 1000) / GC::GetPerformanceFrequency();
01019         }

void MMgc::GC::Finalize  )  [private]
 

Requires(exclusiveGC)

Definition at line 889 of file GC.cpp.

References containsPointersAllocs, MMgc::GCAlloc::Finalize(), util::threadpool::i, kNumSizeClasses, MMGC_ASSERT_EXCLUSIVE_GC, MMGC_DRC, and noPointersAllocs.

Referenced by Sweep().

00890     {
00891         MMGC_ASSERT_EXCLUSIVE_GC(this);
00892 
00893         for(int i=0; i < kNumSizeClasses; i++) {
00894 #ifdef MMGC_DRC
00895             containsPointersRCAllocs[i]->Finalize();
00896 #endif
00897             containsPointersAllocs[i]->Finalize();
00898             noPointersAllocs[i]->Finalize();
00899         }
00900         largeAlloc->Finalize();
00901         finalizedValue = !finalizedValue;
00902 
00903         
00904         for(int i=0; i < kNumSizeClasses; i++) {
00905 #ifdef MMGC_DRC
00906             containsPointersRCAllocs[i]->m_finalized = false;
00907 #endif
00908             containsPointersAllocs[i]->m_finalized = false;
00909             noPointersAllocs[i]->m_finalized = false;
00910         }
00911     }

void* MMgc::GC::FindBeginning const void *  gcItem  )  [inline]
 

Requires(request)

Definition at line 955 of file GC.h.

References MMgc::GCLargeAlloc::FindBeginning(), MMgc::GCAlloc::FindBeginning(), GCAssert, GetUserPointer, MMgc::GCHeap::kBlockSize, and NULL.

Referenced by avmplus::SortedIntMap< FrameState * >::ensureCapacity(), MMgc::WriteBarrierRC< T >::set(), avmplus::Hashtable::setAtoms(), avmplus::AtomArray::setAtoms(), WriteBarrier(), WriteBarrierNoSub(), and WriteBarrierWriteRC().

00956         {
00957             GCAssert(gcItem != NULL);
00958             GCAssert(GetPageMapValue((uintptr)gcItem) != 0);
00959             void *realItem = NULL;
00960             if((uintptr)gcItem < memStart || (uintptr)gcItem >= memEnd)
00961                 return NULL;
00962             int bits = GetPageMapValue((uintptr)gcItem);
00963             switch(bits)
00964             {
00965             case kGCAllocPage:
00966                 realItem = GCAlloc::FindBeginning(gcItem);
00967                 break;
00968             case kGCLargeAllocPageFirst:
00969                 realItem = GCLargeAlloc::FindBeginning(gcItem);
00970                 break;
00971             case kGCLargeAllocPageRest:
00972                 while(bits == kGCLargeAllocPageRest)
00973                 {
00974                     gcItem = (void*) ((uintptr)gcItem - GCHeap::kBlockSize);
00975                     bits = GetPageMapValue((uintptr)gcItem);
00976                 }
00977                 realItem = GCLargeAlloc::FindBeginning(gcItem);
00978                 break;
00979             default:
00980                 return NULL;
00981             }       
00982 #ifdef MEMORY_INFO
00983             realItem = GetUserPointer(realItem);
00984 #endif
00985             return realItem;
00986         }

void MMgc::GC::FinishIncrementalMark  )  [private]
 

Definition at line 2895 of file GC.cpp.

References collecting, MMgc::GCStack< T, defSize >::Count(), GCAssert, GetPerformanceCounter(), MMgc::GCRoot::GetWorkItem(), hitZeroObjects, m_incrementalWork, m_roots, marking, MarkItem(), MarkQueueAndStack(), MMGC_ASSERT_EXCLUSIVE_GC, MMgc::GCRoot::next, MMgc::GCWorkItem::ptr, Sweep(), and sweepStart.

Referenced by AllocBlockIncremental(), CollectImpl(), and IncrementalMark().

02896     {
02897         MMGC_ASSERT_EXCLUSIVE_GC(this);
02898 
02899         // Don't finish an incremental mark (i.e., sweep) if we
02900         // are in the midst of a ZCT reap.
02901         if (zct.reaping)
02902         {
02903             return;
02904         }
02905         
02906         hitZeroObjects = false;
02907 
02908         // finished in Sweep
02909         sweepStart = GetPerformanceCounter();
02910         
02911         // mark roots again, could have changed (alternative is to put WB's on the roots
02912         // which we may need to do if we find FinishIncrementalMark taking too long)
02913         
02914         {
02915 #ifdef GCHEAP_LOCK
02916             GCAcquireSpinlock lock(m_rootListLock);
02917 #endif
02918             GCRoot *r = m_roots;
02919             while(r) {                  
02920                 GCWorkItem item = r->GetWorkItem();
02921                 // need to do this while holding the root lock so we don't end 
02922                 // up trying to scan a deleted item later, another reason to keep
02923                 // the root set small
02924                 if(item.ptr) {
02925                     MarkItem(item, m_incrementalWork);
02926                 }
02927                 r = r->next;
02928             }
02929         }
02930         MarkQueueAndStack(m_incrementalWork);
02931 
02932 #ifdef _DEBUG
02933         // need to traverse all marked objects and make sure they don't contain
02934         // pointers to unmarked objects
02935         FindMissingWriteBarriers();
02936 #endif
02937 
02938         GCAssert(!collecting);
02939         collecting = true;
02940         GCAssert(m_incrementalWork.Count() == 0);
02941         Sweep();
02942         GCAssert(m_incrementalWork.Count() == 0);
02943         collecting = false;
02944         marking = false;
02945     }

void MMgc::GC::ForceSweep  )  [inline, private]
 

Requires(exclusiveGC)

Definition at line 1353 of file GC.h.

Referenced by ~GC().

01353 { Sweep(true); }

void MMgc::GC::Free const void *  ptr  ) 
 

One can free a GC allocated pointer, this will throw an assertion if called during the Sweep phase (ie via a finalizer) it can only be used outside the scope of a collection

Requires(request)

Definition at line 800 of file GC.cpp.

References CheckThread(), ClearFinalized(), ClearWeakRef(), collecting, MMgc::GCAlloc::Free(), MMgc::GCLargeAlloc::Free(), GCAssert, GetRealPointer, HasWeakRef(), IsFinalized(), MMgc::GCLargeAlloc::IsLargeBlock(), IsQueued(), MMgc::GCAlloc::IsRCObject(), MMgc::GCLargeAlloc::IsRCObject(), largeAlloc, marking, NULL, SAMPLE_DEALLOC, and Size().

Referenced by avmplus::AtomArray::checkCapacity(), avmplus::AtomArray::clear(), avmplus::Hashtable::destroy(), avmplus::SortedIntMap< FrameState * >::ensureCapacity(), avmplus::MultinameHashtable::grow(), avmplus::BitSet::grow(), avmplus::Hashtable::grow(), MMgc::GCObject::operator delete(), MMgc::GCFinalizedObjectOptIn::operator delete(), MMgc::GCFinalizedObject::operator delete(), avmplus::StringOutputStream::write(), avmplus::AbcParser::~AbcParser(), avmplus::ArraySort::~ArraySort(), avmplus::BitSet::~BitSet(), avmplus::MultinameHashtable::~MultinameHashtable(), avmplus::ObjectVectorObject::~ObjectVectorObject(), avmplus::SortedIntMap< FrameState * >::~SortedIntMap(), avmplus::StringNullTerminatedUTF8::~StringNullTerminatedUTF8(), avmplus::StringOutputStream::~StringOutputStream(), avmplus::UsesUTF8String::~UsesUTF8String(), and avmplus::Verifier::~Verifier().

00801     {
00802 #ifdef MMGC_THREADSAFE
00803         GCAutoLock _lock(m_lock);
00804         GCAssert(!m_gcRunning);
00805 #else
00806         CheckThread();
00807 #endif
00808 
00809         if(item == NULL) {
00810             return;
00811         }
00812 
00813         bool isLarge;
00814 
00815         SAMPLE_DEALLOC(GetRealPointer(item), GC::Size(item));
00816 
00817         // we can't allow free'ing something during Sweeping, otherwise alloc counters
00818         // get decremented twice and destructors will be called twice.
00819         if(collecting) {
00820             goto bail;
00821         }
00822 
00823         isLarge = GCLargeAlloc::IsLargeBlock(GetRealPointer(item));
00824 
00825         if (marking) {
00826             // if its on the work queue don't delete it, if this item is
00827             // really garbage we're just leaving it for the next sweep
00828             if(IsQueued(item)) 
00829                 goto bail;
00830         }
00831 
00832 #ifdef _DEBUG
00833 #ifdef MMGC_DRC
00834         // RCObject have constract that they must clean themselves, since they 
00835         // have to scan themselves to decrement other RCObjects they might as well
00836         // clean themselves too, better than suffering a memset later
00837         if(isLarge ? GCLargeAlloc::IsRCObject(item) : GCAlloc::IsRCObject(item))
00838         {
00839              RCObjectZeroCheck((RCObject*)item);
00840         }
00841 #endif // MMGC_DRC
00842 #endif
00843 
00844 #ifdef MEMORY_INFO
00845         DebugFree(item, 0xca, 4);
00846 #endif
00847     
00848         if (isLarge) {
00849             largeAlloc->Free(GetRealPointer(item));
00850         } else {
00851             GCAlloc::Free(GetRealPointer(item));
00852         }
00853         return;
00854 
00855 bail:
00856 
00857         // this presumes we got here via delete, maybe we should have
00858         // delete call something other than the public Free to distinguish
00859         if(IsFinalized(item))
00860             ClearFinalized(item);
00861         if(HasWeakRef(item))
00862             ClearWeakRef(item);
00863     }

void MMgc::GC::FreeBits uint32 bits,
int  sizeClass
[inline, private]
 

Requires((request && m_lock) || exclusiveGC)

Definition at line 1150 of file GC.h.

References GCAssert, and util::threadpool::i.

Referenced by MMgc::GCAlloc::FreeChunk(), and GetBits().

01151         {
01152 #ifdef _DEBUG
01153             for(int i=0, n=noPointersAllocs[sizeClass]->m_numBitmapBytes; i<n;i++) GCAssert(((uint8*)bits)[i] == 0);
01154 #endif
01155             *(uint32**)bits = m_bitsFreelists[sizeClass];
01156             m_bitsFreelists[sizeClass] = bits;
01157         }

void MMgc::GC::FreeBlock void *  ptr,
uint32  size
 

Requires((request && m_lock) || exclusiveGC)

Definition at line 1151 of file GC.cpp.

References allocsSinceCollect, collecting, destroying, MMgc::GCHeap::Free(), GCAssert, heap, totalGCPages, and UnmarkGCPages().

Referenced by MMgc::GCLargeAlloc::Free(), MMgc::GCAlloc::FreeChunk(), and Sweep().

01152     {
01153 #ifdef MMGC_THREADSAFE
01154         GCAssert(m_lock.IsHeld() || destroying
01155                  || (m_gcRunning
01156                      && m_exclusiveGCThread == GCThread::GetCurrentThread()));
01157 #endif
01158 #ifdef DEBUGGER
01159         AllocActivity(- (int)size);
01160 #endif
01161         if(!collecting) {
01162             allocsSinceCollect -= size;
01163         }
01164         totalGCPages -= size;
01165         heap->Free(ptr);
01166         UnmarkGCPages(ptr, size);
01167     }

void MMgc::GC::gclog const char *  format,
  ...
[private]
 

Referenced by log_mem(), Sweep(), and updateGrossMemoryStats().

uint32 * MMgc::GC::GetBits int  numBytes,
int  sizeClass
[private]
 

Requires(request && m_lock)

Definition at line 3072 of file GC.cpp.

References MMgc::GCHeap::Alloc(), FreeBits(), GCAssert, heap, MMgc::GCHeap::kBlockSize, m_bitsFreelists, m_bitsNext, MMGC_ASSERT_GC_LOCK, and noPointersAllocs.

Referenced by MMgc::GCAlloc::CreateChunk().

03073     {
03074         uint32 *bits;
03075 
03076         MMGC_ASSERT_GC_LOCK(this);
03077         GCAssert(numBytes % 4 == 0);
03078 
03079         #ifdef MMGC_64BIT // we use first 8-byte slot for the free list
03080         if (numBytes == 4)
03081             numBytes = 8;
03082         #endif
03083 
03084         // hit freelists first
03085         if(m_bitsFreelists[sizeClass]) {
03086             bits = m_bitsFreelists[sizeClass];
03087             m_bitsFreelists[sizeClass] = *(uint32**)bits;
03088             memset(bits, 0, sizeof(uint32*));
03089             return bits;
03090         }
03091 
03092         if(!m_bitsNext)
03093             m_bitsNext = (uint32*)heap->Alloc(1);
03094 
03095         int leftOver = GCHeap::kBlockSize - ((uintptr)m_bitsNext & 0xfff);
03096         if(leftOver >= numBytes) {
03097             bits = m_bitsNext;
03098             if(leftOver == numBytes) 
03099                 m_bitsNext = 0;
03100             else 
03101                 m_bitsNext += numBytes/sizeof(uint32);
03102         } else {
03103             if(leftOver>=int(sizeof(void*))) {
03104                 // put waste in freelist
03105                 for(int i=0, n=kNumSizeClasses; i<n; i++) {
03106                     GCAlloc *a = noPointersAllocs[i];
03107                     if(!a->m_bitsInPage && a->m_numBitmapBytes <= leftOver) {
03108                         FreeBits(m_bitsNext, a->m_sizeClassIndex);
03109                         break;
03110                     }
03111                 }
03112             }
03113             m_bitsNext = 0;
03114             // recurse rather than duplicating code
03115             return GetBits(numBytes, sizeClass);
03116         }
03117         return bits;
03118     }

size_t MMgc::GC::GetBytesInUse  ) 
 

Definition at line 3388 of file GC.cpp.

References containsPointersAllocs, MMgc::GCAlloc::GetBytesInUse(), MMGC_DRC, and noPointersAllocs.

Referenced by updateGrossMemoryStats().

03389     {
03390         size_t bytes=0;
03391         for(int i=0; i < kNumSizeClasses; i++) {
03392 #ifdef MMGC_DRC
03393             bytes += containsPointersRCAllocs[i]->GetBytesInUse();
03394 #endif
03395             bytes += containsPointersAllocs[i]->GetBytesInUse();
03396             bytes += noPointersAllocs[i]->GetBytesInUse();
03397         }
03398         bytes += largeAlloc->GetBytesInUse();
03399         return bytes;
03400     }

static GC* MMgc::GC::GetGC const void *  item  )  [inline, static]
 

Utility function: Returns the GC object associated with an allocated object

Definition at line 836 of file GC.h.

Referenced by avmplus::ObjectVectorObject::_setUintProperty(), avmplus::String::allocBuf(), avmplus::AtomArray::AtomArray(), avmplus::String::charAt(), avmplus::AtomArray::checkCapacity(), avmplus::AtomArray::clear(), avmplus::Hashtable::destroy(), avmplus::HeapMultiname::gc(), avmplus::E4XNode::gc(), avmplus::AvmCore::gcObjectToAtom(), MMgc::GCWorkItem::GCWorkItem(), avmplus::WeakValueHashtable::getValue(), GetWeakRef(), avmplus::ObjectVectorObject::grow(), avmplus::MultinameHashtable::grow(), avmplus::Hashtable::grow(), avmplus::MultinameHashtable::Init(), avmplus::String::localeCompare(), MMgc::GCObject::operator delete(), MMgc::GCFinalizedObjectOptIn::operator delete(), MMgc::GCFinalizedObject::operator delete(), avmplus::MultinameHashtable::put(), avmplus::Hashtable::put(), avmplus::Hashtable::reset(), MMgc::WriteBarrierRC< T >::set(), avmplus::AtomArray::setAtInternal(), avmplus::Hashtable::setAtoms(), avmplus::String::setBuf(), avmplus::ScriptObject::setDelegate(), avmplus::XMLObject::setNode(), avmplus::E4XNode::setParent(), avmplus::Namespace::setPrefix(), avmplus::String::setPrefixOrOffsetOrNumber(), avmplus::ScopeChain::setScope(), avmplus::XMLListObject::setTargetObject(), avmplus::Namespace::setUri(), avmplus::String::slice(), avmplus::String::sliceDouble(), avmplus::String::String(), avmplus::String::substr(), avmplus::String::substrDouble(), avmplus::String::substring(), avmplus::String::substringDouble(), avmplus::String::toLowerCase(), avmplus::String::toUpperCase(), avmplus::String::toUTF8String(), avmplus::XMLObject::toXMLString(), avmplus::StringOutputStream::write(), WriteBarrier(), WriteBarrierNoSub(), avmplus::BitSet::~BitSet(), MMgc::GCWeakRef::~GCWeakRef(), avmplus::MultinameHashtable::~MultinameHashtable(), avmplus::Namespace::~Namespace(), avmplus::ObjectVectorObject::~ObjectVectorObject(), avmplus::StringOutputStream::~StringOutputStream(), and avmplus::UsesUTF8String::~UsesUTF8String().

00837         {
00838             GC **gc = (GC**) ((uintptr)item&~0xfff);
00839             return *gc;
00840         }

void* MMgc::GC::GetGCContextVariable int  var  )  const [inline]
 

Definition at line 565 of file GC.h.

Referenced by AllocAlreadyLocked(), avmplus::String::charAt(), and avmplus::String::localeCompare().

00565 { return m_contextVars[var]; }

GCHeap* MMgc::GC::GetGCHeap  )  const [inline]
 

Definition at line 852 of file GC.h.

Referenced by avmshell::SystemClass::getFreeMemory(), avmshell::SystemClass::getTotalMemory(), avmplus::PoolObject::PoolObject(), and MMgc::GCAlloc::~GCAlloc().

00852 { return heap; }

int MMgc::GC::GetMark const void *  item  )  [static]
 

Tracers should employ GetMark and SetMark to set the mark bits during the mark pass.

Requires(request || exclusiveGC)

Definition at line 865 of file GC.cpp.

References MMgc::GCAlloc::GetMark(), MMgc::GCLargeAlloc::GetMark(), GetRealPointer, and MMgc::GCLargeAlloc::IsLargeBlock().

Referenced by IsQueued(), and TrapWrite().

00866     {
00867         item = GetRealPointer(item);
00868         if (GCLargeAlloc::IsLargeBlock(item)) {
00869             return GCLargeAlloc::GetMark(item);
00870         } else {
00871             return GCAlloc::GetMark(item);
00872         }
00873     }

int MMgc::GC::GetPageMapValue uintptr  addr  )  const [inline, private]
 

This spinlock covers memStart, memEnd, and the contents of pageMap.

Definition at line 1260 of file GC.h.

Referenced by IsGCMemory(), and IsWhite().

01261         {
01262 #ifdef MMGC_THREADSAFE
01263             GCAcquireSpinlock lock(pageMapLock);
01264 #endif
01265             return GetPageMapValueAlreadyLocked(addr);
01266         }

int MMgc::GC::GetPageMapValueAlreadyLocked uintptr  addr  )  const [private]
 

Requires(pageMapLock)

Definition at line 1169 of file GC.cpp.

References GCAssert, MMgc::GCHeap::kBlockSize, memStart, and pageMap.

Referenced by IsPointerToGCPage().

01170     {
01171         uintptr index = (addr-memStart) >> 12;
01172 
01173 #ifdef MMGC_AMD64
01174         GCAssert((index >> 2) < uintptr(64*65536) * uintptr(GCHeap::kBlockSize));
01175 #else
01176         GCAssert(index >> 2 < 64 * GCHeap::kBlockSize);
01177 #endif
01178         // shift amount to determine position in the byte (times 2 b/c 2 bits per page)
01179         uint32 shiftAmount = (index&0x3) * 2;
01180         // 3 ... is mask for 2 bits, shifted to the left by shiftAmount
01181         // finally shift back by shift amount to get the value 0, 1 or 3
01182         //return (pageMap[addr >> 2] & (3<<shiftAmount)) >> shiftAmount;
01183         return (pageMap[index >> 2] >> shiftAmount) & 3;
01184     }

uint64 MMgc::GC::GetPerformanceCounter  )  [static]
 

Definition at line 2782 of file GC.cpp.

References MMGC_PortAPI_Time, and NULL.

Referenced by AllocBlock(), AllocBlockIncremental(), MMgc::GCHeap::Decommit(), duration(), FinishIncrementalMark(), MaybeGC(), StartIncrementalMark(), and Sweep().

02783     {
02784     #if defined(MMGC_PORTING_API)
02785         return MMGC_PortAPI_Time();
02786     #else
02787         #ifdef WIN32
02788         LARGE_INTEGER value;
02789         QueryPerformanceCounter(&value);
02790         return value.QuadPart;
02791         #elif defined SOLARIS
02792         uint64 retval = gethrtime();
02793         return retval;
02794         #elif defined(_MAC)
02795         return mach_absolute_time();
02796         #elif defined(AVMPLUS_UNIX)
02797         struct timeval tv;
02798         ::gettimeofday(&tv, NULL);
02799 
02800         uint64 seconds = (uint64)(tv.tv_sec * 1000000);
02801         uint64 microseconds = (uint64)tv.tv_usec;
02802         uint64 result = seconds + microseconds;
02803         
02804         return result;
02805         #else
02806         #error "Need high res timer"
02807         #endif
02808     #endif // MMMGC_PORTING_API
02809     }

uint64 MMgc::GC::GetPerformanceFrequency  )  [static]
 

Definition at line 2811 of file GC.cpp.

References MMGC_PortAPI_Frequency.

Referenced by duration().

02812     {
02813     #if defined(MMGC_PORTING_API)
02814         return MMGC_PortAPI_Frequency();
02815     #else
02816         #ifdef WIN32
02817         static uint64 gPerformanceFrequency = 0;        
02818         if (gPerformanceFrequency == 0) {
02819             QueryPerformanceFrequency((LARGE_INTEGER*)&gPerformanceFrequency);
02820         }
02821         return gPerformanceFrequency;
02822         #elif defined(_MAC)
02823         static mach_timebase_info_data_t info;
02824         static uint64 frequency = 0;
02825         if ( frequency == 0 ) {
02826             (void) mach_timebase_info(&info);
02827             frequency = (uint64) ( 1.0 / ( 1e-9 * (double) info.numer / (double) info.denom ) );
02828         }
02829         return frequency;
02830         #elif defined(AVMPLUS_UNIX)
02831         return 1000000;
02832         #else
02833         #error "need high res time impl"
02834         #endif
02835     #endif // MMGC_PORTING_API
02836     }

uintptr MMgc::GC::GetStackTop  )  const
 

GCWeakRef * MMgc::GC::GetWeakRef const void *  obj  )  [static]
 

Requires(request)

Definition at line 3181 of file GC.cpp.

References GCAssert, MMgc::GCWeakRef::get(), MMgc::GCHashtable::get(), GetGC(), GetRealPointer, MMgc::GCLargeAlloc::IsLargeBlock(), NULL, MMgc::GCHashtable::put(), MMgc::GCAlloc::SetHasWeakRef(), MMgc::GCLargeAlloc::SetHasWeakRef(), and weakRefs.

Referenced by MMgc::GCFinalizedObject::GetWeakRef(), and MMgc::GCObject::GetWeakRef().

03182     {
03183         GC *gc = GetGC(item);
03184 #ifdef MMGC_THREADSAFE
03185         GCAutoLock _lock(gc->m_lock);
03186 #endif
03187         GCWeakRef *ref = (GCWeakRef*) gc->weakRefs.get(item);
03188 
03189         if(ref == NULL) {
03190             ref = new (gc) GCWeakRef(item);
03191             gc->weakRefs.put(item, ref);
03192             item = GetRealPointer(item);
03193             if (GCLargeAlloc::IsLargeBlock(item)) {
03194                 GCLargeAlloc::SetHasWeakRef(item, true);
03195             } else {
03196                 GCAlloc::SetHasWeakRef(item, true);
03197             }
03198         } else {
03199             GCAssert(ref->get() == item);
03200         }
03201         return ref;
03202     }

static int MMgc::GC::HasWeakRef const void *  item  )  [inline, static]
 

Definition at line 818 of file GC.h.

References GCAssert, GetRealPointer, MMgc::GCAlloc::HasWeakRef(), MMgc::GCLargeAlloc::HasWeakRef(), MMgc::GCLargeAlloc::IsLargeBlock(), and IsPointerToGCPage().

Referenced by Free().

00819         {
00820 #ifdef MEMORY_INFO
00821             GC *gc = GetGC(item);   
00822             item = GetRealPointer(item);
00823             GCAssert(gc->IsPointerToGCPage(item));
00824 #endif          
00825             if (GCLargeAlloc::IsLargeBlock(item)) {
00826                 return GCLargeAlloc::HasWeakRef(item);
00827             } else {
00828                 return GCAlloc::HasWeakRef(item);
00829             }
00830         }

void * MMgc::GC::heapAlloc size_t  size,
bool  expand = true,
bool  zero = true
[private]
 

Definition at line 3362 of file GC.cpp.

References MMgc::GCHeap::Alloc(), heap, and totalGCPages.

03363     {
03364         void *ptr = heap->Alloc((int)siz, expand, zero);
03365         if(ptr)
03366             totalGCPages += siz;
03367         return ptr;
03368     }

void MMgc::GC::heapFree void *  ptr,
size_t  siz = 0
[private]
 

Definition at line 3370 of file GC.cpp.

References MMgc::GCHeap::Free(), heap, MMgc::GCHeap::Size(), and totalGCPages.

03371     {
03372         if(!siz)
03373             siz = heap->Size(ptr);
03374         totalGCPages -= siz;
03375         heap->Free(ptr);
03376     }   

void MMgc::GC::IncrementalMark  ) 
 

Do as much marking as possible in time milliseconds

Definition at line 2838 of file GC.cpp.

References core(), MMgc::GCStack< T, defSize >::Count(), FinishIncrementalMark(), hitZeroObjects, incrementalValidation, m_incrementalWork, MMGC_ASSERT_EXCLUSIVE_GC, and SAMPLE_FRAME.

Referenced by AllocBlockIncremental(), and MaybeGC().

02839     {
02840         MMGC_ASSERT_EXCLUSIVE_GC(this);
02841         uint32 time = incrementalValidation ? 1 : 5;
02842 #ifdef _DEBUG
02843         time = 1;
02844 #endif
02845 
02846         SAMPLE_FRAME("[mark]", core());
02847         if(m_incrementalWork.Count() == 0 || hitZeroObjects) {
02848             FinishIncrementalMark();
02849             return;
02850         } 
02851 
02852 #ifdef DEBUGGER
02853         StartGCActivity();
02854 #endif
02855         
02856         markIncrements++;
02857         // FIXME: tune this so that getPerformanceCounter() overhead is noise
02858         static unsigned int checkTimeIncrements = 100;
02859         uint64 start = GetPerformanceCounter();
02860 
02861 #ifdef DEBUGGER
02862         numObjects=0;
02863         objSize=0;
02864 #endif
02865 
02866         uint64 ticks = start + time * GetPerformanceFrequency() / 1000;
02867         do {
02868             unsigned int count = m_incrementalWork.Count();
02869             if (count == 0) {
02870                 hitZeroObjects = true;
02871                 break;
02872             }
02873             if (count > checkTimeIncrements) {
02874                 count = checkTimeIncrements;
02875             }
02876             for(unsigned int i=0; i<count; i++) 
02877             {
02878                 MarkItem(m_incrementalWork);
02879             }
02880             SAMPLE_CHECK();
02881         } while(GetPerformanceCounter() < ticks);
02882 
02883         lastMarkTicks = GetPerformanceCounter();
02884         markTicks += lastMarkTicks - start;
02885 
02886         if(gcstats) {
02887             double millis = duration(start);
02888             uint32 kb = objSize>>10;
02889             gclog("[mem] mark(%d) %d objects (%d kb %d mb/s) in %.2f millis (%.4f s)\n", 
02890                 markIncrements-lastStartMarkIncrementCount, numObjects, kb, 
02891                 uint32(double(kb)/millis), millis, duration(t0)/1000);
02892         }
02893     }

bool MMgc::GC::IncrementalMarking  )  [inline]
 

Are we currently marking

Definition at line 875 of file GC.h.

00875 { return marking; }

static int MMgc::GC::IsFinalized const void *  item  )  [inline, static]
 

Definition at line 804 of file GC.h.

References GCAssert, GetRealPointer, MMgc::GCAlloc::IsFinalized(), MMgc::GCLargeAlloc::IsFinalized(), MMgc::GCLargeAlloc::IsLargeBlock(), and IsPointerToGCPage().

Referenced by Free().

00805         {
00806 #ifdef MEMORY_INFO
00807             GC *gc = GetGC(item);   
00808             item = GetRealPointer(item);
00809             GCAssert(gc->IsPointerToGCPage(item));
00810 #endif          
00811             if (GCLargeAlloc::IsLargeBlock(item)) {
00812                 return GCLargeAlloc::IsFinalized(item);
00813             } else {
00814                 return GCAlloc::IsFinalized(item);
00815             }
00816         }

bool MMgc::GC::IsGCMemory const void *   ) 
 

Requires(request || exclusiveGC)

Definition at line 3061 of file GC.cpp.

References GetPageMapValue().

03062     {
03063         int bits = GetPageMapValue((uintptr)item);
03064         return (bits != 0);
03065     }

bool MMgc::GC::IsPointerToGCPage const void *  item  ) 
 

debugging tool

Definition at line 1434 of file GC.cpp.

References GetPageMapValueAlreadyLocked(), memEnd, memStart, and USING_PAGE_MAP.

Referenced by ClearFinalized(), avmplus::BitSet::grow(), HasWeakRef(), IsFinalized(), IsWhite(), SetFinalize(), SetMark(), avmplus::StringOutputStream::StringOutputStream(), and writeBarrierRC().

01435     {
01436         USING_PAGE_MAP();
01437         if((uintptr)item >= memStart && (uintptr)item < memEnd)
01438             return GetPageMapValueAlreadyLocked((uintptr) item) != 0;
01439         return false;
01440     }

bool MMgc::GC::IsQueued const void *  item  ) 
 

Requires(request || exclusiveGC)

Definition at line 3067 of file GC.cpp.

References GetMark(), and IsWhite().

Referenced by Free().

03068     {
03069         return !GetMark(item) && !IsWhite(item);
03070     }

bool MMgc::GC::IsRCObject const void *   )  [inline]
 

Definition at line 991 of file GC.h.

Referenced by avmplus::AvmCore::gcObjectToAtom(), WriteBarrierWrite(), and WriteBarrierWriteRC().

00991 { return false; }

int MMgc::GC::IsWhite const void *  item  )  [private]
 

Requires(request || exclusiveGC)

Definition at line 2947 of file GC.cpp.

References GetPageMapValue(), GetRealPointer, IsPointerToGCPage(), MMgc::GCLargeAlloc::IsWhite(), and MMgc::GCAlloc::IsWhite().

Referenced by IsQueued(), and TrapWrite().

02948     {
02949         // back up to real beginning
02950         item = GetRealPointer((const void*) item);
02951 
02952         // normalize and divide by 4K to get index
02953         if(!IsPointerToGCPage(item))
02954             return false;
02955         int bits = GetPageMapValue((uintptr)item);  
02956         switch(bits) {
02957         case 1:
02958             return GCAlloc::IsWhite(item);
02959         case 3:
02960             // FIXME: we only want pointers to the first page for large items, fix
02961             // this by marking the first page and subsequent pages of large items differently
02962             // in the page map (ie use 2).
02963             return GCLargeAlloc::IsWhite(item);
02964         }
02965         return false;
02966     }

void MMgc::GC::log_mem const char *  name,
size_t  s,
size_t  comp
[private]
 

Definition at line 3378 of file GC.cpp.

References gclog(), and MMgc::GCHeap::kBlockSize.

Referenced by updateGrossMemoryStats().

03379     {
03380         bytes_compare = size_t((bytes*100.0)/bytes_compare);
03381         if(bytes > 1<<20) {
03382             gclog("%s %d (%.1fM) %d%%\n", name, bytes / GCHeap::kBlockSize, bytes * 1.0 / (1024*1024), bytes_compare);
03383         } else {
03384             gclog("%s %d (%dK) %d%%\n", name, bytes / GCHeap::kBlockSize, bytes / 1024, bytes_compare);
03385         }
03386     }

void MMgc::GC::Mark GCStack< GCWorkItem > &  work  )  [private]
 

Requires(exclusiveGC)

Definition at line 1208 of file GC.cpp.

References MMgc::GCStack< T, defSize >::Count(), MarkItem(), and MMGC_ASSERT_EXCLUSIVE_GC.

Referenced by MarkQueueAndStack(), and Sweep().

01209     {
01210         MMGC_ASSERT_EXCLUSIVE_GC(this);
01211         while(work.Count()) {
01212             MarkItem(work);
01213         }
01214     }

void MMgc::GC::MarkGCPages void *  item,
uint32  numpages,
int  val
[private]
 

Definition at line 1216 of file GC.cpp.

References MMgc::GCHeap::Alloc(), heap, MMgc::GCHeap::kBlockSize, MMgc::MAX_UINTPTR, memEnd, memStart, pageMap, MMgc::GCHeap::Size(), and USING_PAGE_MAP.

Referenced by AllocBlock().

01217     {
01218         USING_PAGE_MAP();
01219         uintptr addr = (uintptr)item;
01220         size_t shiftAmount=0;
01221         unsigned char *dst = pageMap;
01222 
01223         // save the current live range in case we need to move/copy
01224         size_t numBytesToCopy = (memEnd-memStart)>>14;
01225 
01226         if(addr < memStart) {
01227             // round down to nearest 16k boundary, makes shift logic work cause it works
01228             // in bytes, ie 16k chunks
01229             addr &= ~0x3fff;
01230             // marking earlier pages
01231             if(memStart != MAX_UINTPTR) {
01232                 shiftAmount = (memStart - addr) >> 14;
01233             }
01234             memStart = addr;
01235         } 
01236         
01237         if(addr + (numPages+1)*GCHeap::kBlockSize > memEnd) {
01238             // marking later pages
01239             memEnd = addr + (numPages+1)*GCHeap::kBlockSize;
01240             // round up to 16k 
01241             memEnd = (memEnd+0x3fff)&~0x3fff;
01242         }
01243 
01244         uint32 numPagesNeeded = (uint32)(((memEnd-memStart)>>14)/GCHeap::kBlockSize + 1);
01245         if(numPagesNeeded > heap->Size(pageMap)) {
01246             dst = (unsigned char*)heap->Alloc(numPagesNeeded);
01247         }
01248 
01249         if(shiftAmount || dst != pageMap) {
01250             memmove(dst + shiftAmount, pageMap, numBytesToCopy);
01251             memset(dst, 0, shiftAmount);
01252             if(dst != pageMap) {
01253                 heap->Free(pageMap);
01254                 pageMap = dst;
01255             }
01256         }
01257 
01258         addr = (uintptr)item;
01259         while(numPages--)
01260         {
01261             GCAssert(GetPageMapValueAlreadyLocked(addr) == 0);
01262             SetPageMapValue(addr, to);
01263             addr += GCHeap::kBlockSize;
01264         }
01265     }

void MMgc::GC::MarkItem GCWorkItem workitem,
GCStack< GCWorkItem > &  work
[private]
 

Requires(exclusiveGC)

Definition at line 2562 of file GC.cpp.

References bytesMarked, GCAssert, MMgc::GCWorkItem::GetSize(), marks, MMgc::GCWorkItem::ptr, SetMark(), and validateDefRef.

02563     {
02564         size_t size = wi.GetSize();
02565         uintptr *p = (uintptr*) wi.ptr;
02566 
02567 #ifdef WERNER_MODE
02568         MarkList me(wi);
02569         
02570         if(p == shouldGo) {
02571             MarkList *wl = MarkList::current;
02572             while(wl) {
02573                 const char *name = "";
02574 // To enable RTTI, you must change all your projects to use RTTI first.  
02575 #if 0
02576                 static bool tryit = true;
02577                 if (tryit)
02578                 {
02579                     try {
02580                         const std::type_info *ti = &typeid(*(MMgc::GCFinalizedObject*)wl->wi.ptr);
02581                         if (ti->name() && (int(ti->name()) > 0x10000))
02582                             name = ti->name();
02583                     } catch(...) {
02584                         name = "unknown";
02585                     }
02586                 }
02587 #endif
02588 
02589                 if(wl->prev)
02590                     sprintf(statusBuffer, "0x%x+%d -> 0x%x size=%d (%s)\n",  (unsigned int)wl->prev->wi.ptr, wl->off, (unsigned int)wl->wi.ptr, wl->wi.GetSize(), name);
02591                 else
02592                     sprintf(statusBuffer, "0x%x : %d (%s)\n", (unsigned int)wl->wi.ptr, wl->wi.GetSize(), name);
02593                 wl = wl->prev;
02594                 OutputDebugString(statusBuffer);
02595             }
02596             sprintf(statusBuffer, "\n");
02597             OutputDebugString(statusBuffer);
02598             //shouldGo = NULL;
02599         }
02600 #endif
02601         bytesMarked += size;
02602         marks++;
02603 
02604         uintptr *end = p + (size / sizeof(void*));
02605         uintptr thisPage = (uintptr)p & ~0xfff;
02606 
02607         // set the mark bits on this guy
02608         if(wi.IsGCItem())
02609         {
02610             int b = SetMark(wi.ptr);
02611             (void)b;
02612 #ifdef _DEBUG
02613             // def ref validation does a Trace which can 
02614             // cause things on the work queue to be already marked
02615             // in incremental GC
02616             if(!validateDefRef) {
02617                 GCAssert(!b);
02618             }
02619 #endif          
02620         }
02621         else
02622         {
02623             GCAssert(!IsPointerToGCPage(wi.ptr));
02624         }
02625 
02626         uintptr _memStart = memStart;
02627         uintptr _memEnd = memEnd;
02628         
02629 #ifdef DEBUGGER
02630         numObjects++;
02631         objSize+=(uint32)size;
02632 #endif
02633 
02634         while(p < end) 
02635         {
02636 #ifdef WERNER_MODE
02637             MarkList::offset = (int)p - (int)wi.ptr;
02638 #endif
02639 
02640             uintptr val = *p++;  
02641 
02642             if(val < _memStart || val >= _memEnd)
02643                 continue;
02644 
02645             // normalize and divide by 4K to get index
02646             int bits = GetPageMapValue(val); 
02647             
02648             if (bits == kGCAllocPage)
02649             {
02650                 const void *item;
02651                 GCAlloc::GCBlock *block = (GCAlloc::GCBlock*) (val & ~0xFFF);
02652 
02653 #ifdef MMGC_INTERIOR_PTRS
02654                 item = (void*) val;
02655 #else
02656                 // back up to real beginning
02657                 item = GetRealPointer((const void*) (val & ~7));
02658 #endif
02659 
02660                 // guard against bogus pointers to the block header
02661                 if(item < block->items)
02662                     continue;
02663 
02664                 int itemNum = GCAlloc::GetIndex(block, item);
02665 #ifdef MMGC_INTERIOR_PTRS
02666                 // adjust |item| to the beginning of the allocation
02667                 item = block->items + itemNum * block->size;
02668 #else
02669                 // if |item| doesn't point to the beginning of an allocation,
02670                 // it's not considered a pointer.
02671                 if (block->items + itemNum * block->size != item)
02672                 {
02673 #ifdef MMGC_64BIT
02674 // Doubly-inherited classes have two vtables so are offset 8 more bytes than normal. 
02675 // Handle that here (shows up with PlayerScriptBufferImpl object in the Flash player)
02676                     if ((block->items + itemNum * block->size + sizeof(void *)) == item)
02677                         item = block->items + itemNum * block->size;
02678                     else
02679 #endif // MMGC_64BIT
02680                         continue;
02681                 }
02682 #endif
02683 
02684                 // inline IsWhite/SetBit
02685                 // FIXME: see if using 32 bit values is faster
02686                 uint32 *pbits = &block->GetBits()[itemNum>>3];
02687                 int shift = (itemNum&0x7)<<2;
02688                 int bits2 = *pbits;
02689                 //if(GCAlloc::IsWhite(block, itemNum)) 
02690                 if((bits2 & ((GCAlloc::kMark|GCAlloc::kQueued)<<shift)) == 0)
02691                 {
02692                     if(block->alloc->ContainsPointers())
02693                     {
02694                         const void *realItem = item;
02695                         uint32 itemSize = block->size;
02696                         #ifdef MEMORY_INFO
02697                         realItem = GetUserPointer(realItem);
02698                         itemSize -= (uint32)DebugSize();
02699                         #endif
02700                         if(((uintptr)realItem & ~0xfff) != thisPage)
02701                         {                           
02702                             *pbits = bits2 | (GCAlloc::kQueued << shift);
02703                             block->gc->PushWorkItem(work, GCWorkItem(realItem, itemSize, true));
02704                         }
02705                         else
02706                         {
02707                             // clear queued bit
02708                             *pbits = bits2 & ~(GCAlloc::kQueued << shift);
02709                             // skip stack for same page items, this recursion is naturally limited by
02710                             // how many item can appear on a page, worst case is 8 byte linked list or
02711                             // 512
02712                             GCWorkItem newItem(realItem, itemSize, true);
02713                             MarkItem(newItem, work);
02714                         }
02715                     }
02716                     else
02717                     {
02718                         //GCAlloc::SetBit(block, itemNum, GCAlloc::kMark);
02719                         *pbits = bits2 | (GCAlloc::kMark << shift);
02720                     }
02721                     #if defined(MEMORY_INFO)
02722                     GC::WriteBackPointer(item, (end==(void*)0x130000) ? p-1 : wi.ptr, block->size);
02723                     #endif
02724                 }
02725             }
02726             else if (IsLargeAllocPage(bits))
02727             {
02728                 //largeAlloc->ConservativeMark(work, (void*) (val&~7), workitem.ptr);
02729                 const void* item;
02730 
02731 #ifdef MMGC_INTERIOR_PTRS
02732                 if (bits == kGCLargeAllocPageFirst)
02733                 {
02734                     // guard against bogus pointers to the block header
02735                     if ((val & 0xffff) < sizeof(GCLargeAlloc::LargeBlock))
02736                         continue;
02737 
02738                     item = (void *) ((val & ~0xfff) |
02739                                      sizeof(GCLargeAlloc::LargeBlock));
02740                 }
02741                 else
02742                 {
02743                     item = GetRealPointer(FindBeginning((void *) val));
02744                 }
02745 #else
02746                 // back up to real beginning
02747                 item = GetRealPointer((const void*) (val & ~7));
02748 
02749                 // If |item| doesn't point to the start of the page, it's not
02750                 // really a pointer.
02751                 if(((uintptr) item & 0xfff) != sizeof(GCLargeAlloc::LargeBlock))
02752                     continue;
02753 #endif
02754 
02755                 GCLargeAlloc::LargeBlock *b = GCLargeAlloc::GetBlockHeader(item);
02756                 if((b->flags & (GCLargeAlloc::kQueuedFlag|GCLargeAlloc::kMarkFlag)) == 0) 
02757                 {
02758                     uint32 usize = b->usableSize;
02759                     if((b->flags & GCLargeAlloc::kContainsPointers) != 0) 
02760                     {
02761                         b->flags |= GCLargeAlloc::kQueuedFlag;
02762                         const void *realItem = item;
02763                         #ifdef MEMORY_INFO
02764                         realItem = GetUserPointer(item);
02765                         usize -= (uint32)DebugSize();
02766                         #endif
02767                         b->gc->PushWorkItem(work, GCWorkItem(realItem, usize, true));
02768                     } 
02769                     else
02770                     {
02771                         // doesn't need marking go right to black
02772                         b->flags |= GCLargeAlloc::kMarkFlag;
02773                     }
02774                     #if defined(MEMORY_INFO)
02775                     GC::WriteBackPointer(item, end==(void*)0x130000 ? p-1 : wi.ptr, usize);
02776                     #endif
02777                 }
02778             }
02779         }
02780     }

void MMgc::GC::MarkItem GCStack< GCWorkItem > &  work  )  [inline, private]
 

Requires(exclusiveGC)

Definition at line 1359 of file GC.h.

References MMgc::GCStack< T, defSize >::Pop().

Referenced by FinishIncrementalMark(), Mark(), and PushWorkItem().

01360         {
01361             GCWorkItem workitem = work.Pop();
01362             MarkItem(workitem, work);
01363         }

void MMgc::GC::MarkQueueAndStack GCStack< GCWorkItem > &  work  )  [private]
 

Requires(exclusiveGC)

Definition at line 1340 of file GC.cpp.

References MMgc::GCWorkItem::_size, Mark(), MMgc::GCWorkItem::ptr, PushWorkItem(), and rememberedStackTop.

Referenced by FinishIncrementalMark().

01341     {
01342         GCWorkItem item;
01343 
01344         MMGC_GET_STACK_EXTENTS(this, item.ptr, item._size);
01345 
01346         // this is where we will clear to when CleanStack is called
01347         if(rememberedStackTop == 0 || rememberedStackTop > item.ptr) {
01348             rememberedStackTop = item.ptr;
01349         }
01350 
01351         PushWorkItem(work, item);
01352         Mark(work);
01353     }

void MMgc::GC::MaybeGC bool  callerHasActiveRequest = false  ) 
 

Perform some GC-related work if needed. Call this during application down time.

In incremental mode, this may result in a call to StartIncrementalMark() or IncrementalMark(), which may in turn push the current GC cycle to completion. In non-incremental mode, this heuristically decides whether to do a full Collect().

Parameters:
callerHasActiveRequest Must be true iff the calling thread is already in a request.

Definition at line 753 of file GC.cpp.

References allocsSinceCollect, collectThreshold, CollectWithBookkeeping(), MMgc::GCHeap::GetFreeHeapSize(), GetPerformanceCounter(), MMgc::GCHeap::GetTotalHeapSize(), greedy, heap, heapSizeAtLastAlloc, incremental, IncrementalMark(), MMgc::kFreeSpaceDivisor, MMgc::kMarkSweepBurstTicks, lastSweepTicks, marking, runtests::now, StartIncrementalMark(), and totalGCPages.

00754     {
00755         if (greedy) {
00756             CollectWithBookkeeping(false, callerHasActiveRequest);
00757         } else if (marking) {
00758             IncrementalMark();
00759         } else {
00760 #ifdef MMGC_THREADSAFE
00761             GCAutoLock _lock(m_lock);
00762 #endif
00763 
00764             // Burst logic to prevent collections from happening back to back.
00765             uint64 now = GetPerformanceCounter();
00766             if (now - lastSweepTicks <= kMarkSweepBurstTicks)
00767                 return;
00768 
00769             // Definitely start GC if the heap expanded due to FixedMalloc
00770             // allocations.  The same heuristic applies to incremental and
00771             // non-incremental.
00772             bool force = (heapSizeAtLastAlloc > collectThreshold &&
00773                           heapSizeAtLastAlloc < heap->GetTotalHeapSize());
00774 
00775             if (incremental) {
00776                 if (force || (totalGCPages > collectThreshold &&
00777                               allocsSinceCollect * kFreeSpaceDivisor >= totalGCPages)) {
00778                     StartIncrementalMark();
00779                 }
00780             } else {
00781                 // Collect only if the heap is completely full (a conservative
00782                 // heuristic).
00783                 if (force || heap->GetFreeHeapSize() == 0)
00784                     CollectWithBookkeeping(true, callerHasActiveRequest);
00785             }
00786         }
00787     }

static const void* MMgc::GC::Pointer const void *  p  )  [inline, static, private]
 

Definition at line 1457 of file GC.h.

Referenced by WriteBarrier(), and WriteBarrierWriteRC().

01457 { return (const void*)(((uintptr)p)&~7); }

void MMgc::GC::PushWorkItem GCStack< GCWorkItem > &  stack,
GCWorkItem  item
[private]
 

Definition at line 3170 of file GC.cpp.

References MarkItem(), MMgc::GCWorkItem::ptr, and MMgc::GCStack< T, defSize >::Push().

03171     {
03172 #ifdef RECURSIVE_MARK
03173         MarkItem(item, stack);
03174 #else
03175         if(item.ptr) {
03176             stack.Push(item);
03177         }
03178 #endif
03179     }

void MMgc::GC::PushWorkItem GCWorkItem item  )  [inline]
 

Definition at line 1131 of file GC.h.

Referenced by MarkQueueAndStack(), and TrapWrite().

01131 { PushWorkItem(m_incrementalWork, item); }

void MMgc::GC::RemoveCallback GCCallback cb  )  [private]
 

Definition at line 3157 of file GC.cpp.

References m_callbacks, MMgc::GCCallback::nextCB, MMgc::GCCallback::prevCB, and USING_CALLBACK_LIST.

Referenced by MMgc::GCCallback::Destroy(), and MMgc::GCCallback::~GCCallback().

03158     {
03159         USING_CALLBACK_LIST(this);
03160 
03161         if( m_callbacks == cb )
03162             m_callbacks = cb->nextCB;
03163         else
03164             cb->prevCB->nextCB = cb->nextCB;
03165 
03166         if(cb->nextCB)
03167             cb->nextCB->prevCB = cb->prevCB;
03168     }

void MMgc::GC::RemoveRoot GCRoot root  )  [private]
 

Definition at line 3132 of file GC.cpp.

References m_roots, MMgc::GCRoot::next, and MMgc::GCRoot::prev.

Referenced by MMgc::GCRoot::Destroy(), and MMgc::GCRoot::~GCRoot().

03133     {       
03134 #ifdef GCHEAP_LOCK
03135         GCAcquireSpinlock lock(m_rootListLock);
03136 #endif
03137         if( m_roots == root )
03138             m_roots = root->next;
03139         else
03140             root->prev->next = root->next;
03141 
03142         if(root->next)
03143             root->next->prev = root->prev;
03144     }

static void MMgc::GC::SetFinalize const void *  item  )  [inline, static]
 

Definition at line 790 of file GC.h.

References GCAssert, GetRealPointer, MMgc::GCLargeAlloc::IsLargeBlock(), IsPointerToGCPage(), MMgc::GCAlloc::SetFinalize(), and MMgc::GCLargeAlloc::SetFinalize().

Referenced by avmplus::RegExpObject::RegExpObject().

00791         {
00792 #ifdef MEMORY_INFO
00793             GC *gc = GetGC(item);   
00794             item = GetRealPointer(item);
00795             GCAssert(gc->IsPointerToGCPage(item));
00796 #endif          
00797             if (GCLargeAlloc::IsLargeBlock(item)) {
00798                 GCLargeAlloc::SetFinalize(item);
00799             } else {
00800                 GCAlloc::SetFinalize(item);
00801             }
00802         }

void MMgc::GC::SetGCContextVariable int  var,
void *  val
[inline]
 

Definition at line 566 of file GC.h.

Referenced by avmplus::AvmCore::~AvmCore().

00566 { m_contextVars[var] = val; }

static int MMgc::GC::SetMark const void *  item  )  [inline, static]
 

Definition at line 748 of file GC.h.

References GCAssert, GetRealPointer, MMgc::GCLargeAlloc::IsLargeBlock(), IsPointerToGCPage(), NULL, MMgc::GCAlloc::SetMark(), and MMgc::GCLargeAlloc::SetMark().

Referenced by MarkItem(), and TrapWrite().

00749         {
00750             GCAssert(item != NULL);
00751 #ifdef MEMORY_INFO
00752             GC *gc = GetGC(item);   
00753             item = GetRealPointer(item);
00754             GCAssert(gc->IsPointerToGCPage(item));
00755 #endif          
00756             if (GCLargeAlloc::IsLargeBlock(item)) {
00757                 return GCLargeAlloc::SetMark(item);
00758             } else {
00759                 return GCAlloc::SetMark(item);
00760             }
00761         }

void MMgc::GC::SetPageMapValue uintptr  addr,
int  val
[private]
 

Set the pageMap bits for the given address. Those bits must be zero beforehand.

Requires(pageMapLock)

Definition at line 1186 of file GC.cpp.

References GCAssert, MMgc::GCHeap::kBlockSize, memStart, and pageMap.

01187     {
01188         uintptr index = (addr-memStart) >> 12;
01189 #ifdef MMGC_AMD64
01190         GCAssert((index >> 2) < uintptr(64*65536) * uintptr(GCHeap::kBlockSize));
01191 #else
01192         GCAssert(index >> 2 < 64 * GCHeap::kBlockSize);
01193 #endif
01194         pageMap[index >> 2] |= (val<<((index&0x3)*2));
01195     }   

void MMgc::GC::SetQueued const void *  item  )  [inline]
 

Definition at line 763 of file GC.h.

References GCAssert, GetRealPointer, MMgc::GCLargeAlloc::IsLargeBlock(), MMgc::GCAlloc::SetQueued(), and MMgc::GCLargeAlloc::SetQueued().

Referenced by TrapWrite().

00764         {
00765 #ifdef MEMORY_INFO
00766             item = GetRealPointer(item);
00767             GCAssert(IsPointerToGCPage(item));
00768 #endif          
00769             if (GCLargeAlloc::IsLargeBlock(item)) {
00770                 GCLargeAlloc::SetQueued(item);
00771             } else {
00772                 GCAlloc::SetQueued(item);
00773             }
00774         }

static size_t MMgc::GC::Size const void *  ptr  )  [inline, static]
 

return the size of a piece of memory, may be bigger than what was asked for

Requires(request || exclusiveGC)

Definition at line 731 of file GC.h.

References DebugSize, GCAssert, and MMgc::GCLargeAlloc::GetBlockHeader().

Referenced by AllocAlreadyLocked(), avmplus::AtomArray::capacity(), MMgc::GCLargeAlloc::Finalize(), Free(), avmplus::DictionaryObject::getKeyFromObject(), avmplus::ScriptObject::ScriptObject(), TrapWrite(), avmplus::StringOutputStream::write(), writeBarrierRC(), and avmplus::ArraySort::~ArraySort().

00732         {
00733             GCAssert(GetGC(ptr)->IsGCMemory(ptr));          
00734             size_t size = GCLargeAlloc::GetBlockHeader(ptr)->usableSize;
00735             size -= DebugSize();
00736             return size;
00737 
00738         }

void MMgc::GC::StartIncrementalMark  )  [private]
 

Definition at line 2374 of file GC.cpp.

References collecting, containsPointersAllocs, MMgc::GCStack< T, defSize >::Count(), GCAssert, GetPerformanceCounter(), kNumSizeClasses, lastStartMarkIncrementCount, m_incrementalWork, markIncrements, marking, MMGC_DRC, noPointersAllocs, stackCleaned, and MMgc::GCAlloc::SweepNeedsSweeping().

Referenced by AllocAlreadyLocked(), AllocBlock(), AllocBlockIncremental(), CollectImpl(), and MaybeGC().

02375     {
02376         GCAssert(!marking);
02377         GCAssert(!collecting);
02378 
02379         lastStartMarkIncrementCount = markIncrements;
02380 
02381         // set the stack cleaning trigger
02382         stackCleaned = false;
02383 
02384         marking = true;
02385 
02386         GCAssert(m_incrementalWork.Count() == 0);
02387     
02388         uint64 start = GetPerformanceCounter();
02389 
02390         // clean up any pages that need sweeping
02391         for(int i=0; i < kNumSizeClasses; i++) {
02392 #ifdef MMGC_DRC
02393             containsPointersRCAllocs[i]->SweepNeedsSweeping();
02394 #endif
02395             containsPointersAllocs[i]->SweepNeedsSweeping();
02396             noPointersAllocs[i]->SweepNeedsSweeping();
02397         }
02398 
02399         // at this point every object should have no marks or be marked kFreelist
02400 #ifdef _DEBUG       
02401         for(int i=0; i < kNumSizeClasses; i++) {
02402 #ifdef MMGC_DRC
02403             containsPointersRCAllocs[i]->CheckMarks();
02404 #endif
02405             containsPointersAllocs[i]->CheckMarks();
02406             noPointersAllocs[i]->CheckMarks();
02407         }
02408 #endif
02409     
02410         {
02411 #ifdef GCHEAP_LOCK
02412             GCAcquireSpinlock lock(m_rootListLock);
02413 #endif
02414             GCRoot *r = m_roots;
02415             while(r) {
02416                 GCWorkItem item = r->GetWorkItem();
02417                 if(item.ptr)
02418                     MarkItem(item, m_incrementalWork);
02419                 r = r->next;
02420             }
02421         }
02422         markTicks += GetPerformanceCounter() - start;
02423         IncrementalMark();
02424     }

void MMgc::GC::Sweep bool  force = false  )  [private]
 

Requires(exclusiveGC)

Definition at line 913 of file GC.cpp.

References MMgc::GCAlloc::GCBlock::alloc, allocsSinceCollect, collecting, core(), duration(), Finalize(), FreeBlock(), MMgc::GCAlloc::FreeChunk(), MMgc::GCDebugMsg(), gclog(), gcstats, MMgc::GCLargeAlloc::LargeBlock::GetNumBlocks(), GetPerformanceCounter(), MMgc::GCHeap::GetUsedHeapSize(), heap, MMgc::GCHeap::kBlockSize, largeEmptyPageList, lastSweepTicks, m_callbacks, m_incrementalWork, Mark(), marking, MMGC_ASSERT_EXCLUSIVE_GC, MMgc::GCLargeAlloc::LargeBlock::next, MMgc::GCAlloc::GCBlock::next, next, MMgc::GCCallback::nextCB, NULL, MMgc::GCCallback::postsweep(), MMgc::GCCallback::presweep(), SAMPLE_CHECK, SAMPLE_FRAME, smallEmptyPageList, MMgc::GCAlloc::SweepGuts(), sweeps, sweepStart, t0, and USING_CALLBACK_LIST.

Referenced by FinishIncrementalMark().

00914     {   
00915         MMGC_ASSERT_EXCLUSIVE_GC(this);
00916 
00917         // collecting must be true because it indicates allocations should
00918         // start out marked, we can't rely on write barriers below since 
00919         // presweep could write a new GC object to a root
00920         collecting = true;
00921 
00922         SAMPLE_FRAME("[sweep]", core());
00923         sweeps++;
00924 
00925         size_t heapSize = heap->GetUsedHeapSize();
00926 
00927 #ifdef MEMORY_INFO
00928         if(heap->enableMemoryProfiling) {
00929             GCDebugMsg(false, "Pre sweep memory info:\n");
00930             DumpMemoryInfo();
00931         }
00932 #endif
00933         
00934 
00935         // invoke presweep on all callbacks
00936         {
00937             USING_CALLBACK_LIST(this);
00938             GCCallback *cb = m_callbacks;
00939             while(cb) {
00940                 cb->presweep();
00941                 cb = cb->nextCB;
00942             }
00943         }
00944 
00945         SAMPLE_CHECK();
00946 
00947         // if force is true we're being called from ~GC and this isn't necessary
00948         if(!force) {
00949             // we just executed mutator code which could have fired some WB's
00950             Mark(m_incrementalWork);
00951         }
00952 
00953         Finalize();
00954 
00955         // if force is true we're being called from ~GC and this isn't necessary
00956         if(!force) {
00957             // we just executed mutator code which could have fired some WB's
00958             Mark(m_incrementalWork);
00959         }
00960     
00961         SAMPLE_CHECK();
00962         // ISSUE: this could be done lazily at the expense other GC's potentially expanding
00963         // unnecessarily, not sure its worth it as this should be pretty fast
00964         GCAlloc::GCBlock *b = smallEmptyPageList;
00965         while(b) {
00966             GCAlloc::GCBlock *next = b->next;
00967 #ifdef _DEBUG
00968             b->alloc->SweepGuts(b);
00969 #endif
00970             b->alloc->FreeChunk(b);
00971             b = next;
00972         }
00973         smallEmptyPageList = NULL;
00974 
00975         SAMPLE_CHECK();
00976 
00977         GCLargeAlloc::LargeBlock *lb = largeEmptyPageList;      
00978         while(lb) {
00979             GCLargeAlloc::LargeBlock *next = lb->next;
00980 #ifdef MEMORY_INFO
00981             DebugFreeReverse(lb+1, 0xba, 3);
00982 #endif
00983             // FIXME: this makes for some chatty locking, maybe not a problem?
00984             FreeBlock(lb, lb->GetNumBlocks());
00985             lb = next;
00986         }
00987         largeEmptyPageList = NULL;
00988 
00989         SAMPLE_CHECK();
00990 
00991 #ifdef MEMORY_INFO
00992         if(heap->enableMemoryProfiling) {           
00993             GCDebugMsg(false, "Post sweep memory info:\n");
00994             DumpMemoryInfo();
00995         }
00996 #endif
00997 
00998         // don't want postsweep to fire WB's
00999         marking = false;
01000         collecting = false;
01001 
01002         // invoke postsweep callback
01003         {
01004             USING_CALLBACK_LIST(this);
01005             GCCallback *cb = m_callbacks;
01006             while(cb) {
01007                 cb->postsweep();
01008                 cb = cb->nextCB;
01009             }
01010         }
01011 
01012         SAMPLE_CHECK();
01013 
01014         allocsSinceCollect = 0;
01015         lastSweepTicks = GetPerformanceCounter();
01016 
01017         if(GC::gcstats) {
01018             int sweepResults = 0;
01019             GCAlloc::GCBlock *bb = smallEmptyPageList;
01020             while(bb) {
01021                 sweepResults++;
01022                 bb = bb->next;
01023             }
01024             
01025             GCLargeAlloc::LargeBlock *lbb = largeEmptyPageList;
01026             while(lbb) {
01027                 sweepResults += lbb->GetNumBlocks();
01028                 lbb = lbb->next;
01029             }
01030             // include large pages given back
01031             sweepResults += int(heapSize - heap->GetUsedHeapSize());
01032             double millis = duration(sweepStart);
01033             gclog("[mem] sweep(%d) reclaimed %d whole pages (%d kb) in %.2f millis (%.4f s)\n", 
01034                 sweeps, sweepResults, sweepResults*GCHeap::kBlockSize>>10, millis,
01035                 duration(t0)/1000);
01036         }
01037 #ifdef DEBUGGER
01038         StopGCActivity();
01039 #endif
01040 
01041 #ifdef MEMORY_INFO
01042         m_gcLastStackTrace = GetStackTraceIndex(5);
01043 #endif
01044     }

static uint64 MMgc::GC::ticksToMicros uint64  ticks  )  [inline, static]
 

Definition at line 1029 of file GC.h.

01030         { 
01031 #ifdef WIN32
01032             return (ticks*1000000)/GetPerformanceFrequency();
01033 #else
01034             return ticks;
01035 #endif
01036         }

static uint64 MMgc::GC::ticksToMillis uint64  ticks  )  [inline, static]
 

Definition at line 1039 of file GC.h.

01040         { 
01041 #ifdef WIN32
01042             return (ticks*1000)/GetPerformanceFrequency();
01043 #else
01044             return ticks/1000;
01045 #endif
01046         }

void MMgc::GC::TrapWrite const void *  black,
const void *  white
[private]
 

Write barrier slow path. Queues the white object.

Requires(request)

Definition at line 3029 of file GC.cpp.

References ContainsPointers(), GCAssert, GetMark(), IsWhite(), m_incrementalWork, marking, PushWorkItem(), SetMark(), SetQueued(), and Size().

03030     {
03031         // assert fast path preconditions
03032         (void)black;
03033         GCAssert(marking);
03034         GCAssert(GetMark(black));
03035         GCAssert(IsWhite(white));
03036         // currently using the simplest finest grained implementation,
03037         // which could result in huge work queues.  should try the
03038         // more granular approach of moving the black object to grey
03039         // (smaller work queue, less frequent wb slow path) but if the
03040         // black object is big we end up doing useless redundant
03041         // marking.  optimal approach from lit is card marking (mark a
03042         // region of the black object as needing to be re-marked)
03043         if(ContainsPointers(white)) {
03044             SetQueued(white);
03045             PushWorkItem(m_incrementalWork, GCWorkItem(white, (uint32)Size(white), true));
03046         } else {
03047             SetMark(white);
03048         }
03049     }

void MMgc::GC::UnmarkGCPages void *  item,
uint32  numpages
[private]
 

Definition at line 1267 of file GC.cpp.

References ClearPageMapValue(), MMgc::GCHeap::kBlockSize, and USING_PAGE_MAP.

Referenced by FreeBlock().

01268     {
01269         uintptr addr = (uintptr) item;
01270 
01271         USING_PAGE_MAP();
01272         while(numpages--)
01273         {
01274             ClearPageMapValue(addr);
01275             addr += GCHeap::kBlockSize;
01276         }
01277     }

void MMgc::GC::updateGrossMemoryStats  )  [private]
 

Definition at line 3402 of file GC.cpp.

References gclog(), MMgc::GCHashtable::get(), MMgc::FixedMalloc::GetBytesInUse(), GetBytesInUse(), MMgc::GCHeap::GetFreeHeapSize(), MMgc::FixedMalloc::GetInstance(), MMgc::GCHeap::GetPrivateBytes(), MMgc::GCHeap::GetTotalHeapSize(), MMgc::FixedMalloc::GetTotalSize(), heap, MMgc::GCHeap::kBlockSize, log_mem(), stats, and totalGCPages.

03403     {
03404         size_t priv = GCHeap::GetPrivateBytes() * GCHeap::kBlockSize;
03405         size_t mmgc = heap->GetTotalHeapSize() * GCHeap::kBlockSize;
03406         size_t unmanaged = FixedMalloc::GetInstance()->GetTotalSize() * GCHeap::kBlockSize;
03407         size_t jit = (size_t)stats.get("jit") * GCHeap::kBlockSize;
03408         size_t gc_alloced = GetBytesInUse();
03409         size_t fixed_alloced = FixedMalloc::GetInstance()->GetBytesInUse();
03410         size_t gc = totalGCPages * GCHeap::kBlockSize;
03411         gclog("[mem] ------- gross stats -----\n");
03412         log_mem("[mem] private", priv, priv);
03413         log_mem("[mem]\t mmgc", mmgc, priv);
03414         log_mem("[mem]\t\t unmanaged", unmanaged, priv);
03415         log_mem("[mem]\t\t managed", gc, priv);
03416         log_mem("[mem]\t\t free",  (size_t)heap->GetFreeHeapSize() * GCHeap::kBlockSize, priv);
03417         log_mem("[mem]\t jit", jit, priv);
03418         log_mem("[mem]\t other",  priv - jit - mmgc, priv);
03419         log_mem("[mem] bytes (interal fragmentation)", fixed_alloced + gc_alloced, gc + unmanaged);
03420         log_mem("[mem] \tmanaged bytes ", gc_alloced, gc);
03421         log_mem("[mem] \tunmanaged bytes ", fixed_alloced, unmanaged);
03422         gclog("[mem] -------- gross stats end -----\n");
03423     }

void MMgc::GC::UpdateStat const char *  key,
int  delta
[inline]
 

Definition at line 1545 of file GC.h.

01546         {
01547             stats.put(key, (const void*)((size_t)stats.get(key) + delta));
01548         }

void MMgc::GC::writeBarrier const void *  container,
const void *  address,
const void *  value
[inline]
 

Requires(request)

Definition at line 890 of file GC.h.

References GCAssert.

Referenced by avmplus::Hashtable::setAtoms().

00891         {
00892             GCAssert(!container || IsPointerToGCPage(container));
00893             GCAssert(((uintptr)address & 3) == 0);
00894 
00895             if (container) {
00896                 GCAssert(address >= container);
00897                 GCAssert(address < (char*)container + Size(container));
00898                 WriteBarrierNoSubstitute(container, value);
00899             }
00900             WriteBarrierWrite(address, value);
00901         }

void MMgc::GC::WriteBarrier const void *  address,
const void *  value
[static]
 

A magical write barrier that finds the container's address and the GC, just make sure address is a pointer to a GC page. Only used by WB smart pointers.

Requires(request)

Definition at line 3010 of file GC.cpp.

References FindBeginning(), GetGC(), marking, NULL, Pointer(), WriteBarrierNoSubstitute(), and WriteBarrierWrite().

Referenced by MMgc::WriteBarrier< T >::set().

03011     {
03012         GC* gc = GC::GetGC(address);
03013         if(Pointer(value) != NULL && gc->marking) {
03014             void *container = gc->FindBeginning(address);
03015             gc->WriteBarrierNoSubstitute(container, value);
03016         }
03017         gc->WriteBarrierWrite(address, value);
03018     }

void MMgc::GC::WriteBarrierNoSub const void *  address,
const void *  value
[static]
 

Requires(request)

Definition at line 3020 of file GC.cpp.

References FindBeginning(), GetGC(), marking, NULL, and WriteBarrierNoSubstitute().

03021     {
03022         GC *gc = NULL;
03023         if(value != NULL && (gc = GC::GetGC(address))->marking) {
03024             void *container = gc->FindBeginning(address);
03025             gc->WriteBarrierNoSubstitute(container, value);     
03026         }
03027     }

__forceinline void MMgc::GC::WriteBarrierNoSubstitute const void *  container,
const void *  value
[inline]
 

Write barrier when the value could be a pointer with anything in the lower 3 bits FIXME: maybe assert that the lower 3 bits are either zero or a pointer type signature, this would require the application to tell us what bit patterns are pointers.

Requires(request)

Definition at line 917 of file GC.h.

Referenced by avmplus::AvmCore::atomWriteBarrier(), avmplus::String::setPrefixOrOffsetOrNumber(), WriteBarrier(), WriteBarrierNoSub(), and writeBarrierRC().

00918         {
00919             WriteBarrierTrap(container, (const void*)((uintptr)value&~7));
00920         }

void MMgc::GC::writeBarrierRC const void *  container,
const void *  address,
const void *  value
 

optimized version with no RC checks or pointer masking

Requires(request)

Definition at line 2976 of file GC.cpp.

References GCAssert, IsPointerToGCPage(), Size(), WriteBarrierNoSubstitute(), and WriteBarrierWriteRC().

Referenced by MMgc::WriteBarrierRC< T >::set().

02977     {
02978         GCAssert(IsPointerToGCPage(container));
02979         GCAssert(((uintptr)container & 3) == 0);
02980         GCAssert(((uintptr)address & 2) == 0);
02981         GCAssert(address >= container);
02982         GCAssert(address < (char*)container + Size(container));
02983 
02984         WriteBarrierNoSubstitute(container, value);
02985         WriteBarrierWriteRC(address, value);
02986     }

__forceinline void MMgc::GC::WriteBarrierTrap const void *  container,
const void *  valuePtr
[inline]
 

AVM+ write barrier, valuePtr is known to be pointer and the caller does the write.

Requires(request)

Definition at line 928 of file GC.h.

References GCAssert.

00929         {
00930             GCAssert(IsPointerToGCPage(container));
00931             GCAssert(((uintptr)valuePtr&7) == 0);
00932             GCAssert(IsPointerToGCPage(container));
00933             if(marking && valuePtr && GetMark(container) && IsWhite(valuePtr))
00934             {
00935                 TrapWrite(container, valuePtr);
00936             }
00937         }

void MMgc::GC::WriteBarrierWrite const void *  address,
const void *  value
[private]
 

Definition at line 2969 of file GC.cpp.

References GCAssert, and IsRCObject().

Referenced by WriteBarrier().

02970     {
02971         GCAssert(!IsRCObject(value));
02972         *(uintptr*)address = (uintptr) value;
02973     }

void MMgc::GC::WriteBarrierWriteRC const void *  address,
const void *  value
[private]
 

Definition at line 2989 of file GC.cpp.

References FindBeginning(), GCAssert, IsRCObject(), NULL, and Pointer().

Referenced by writeBarrierRC().

02990     {
02991         #ifdef MMGC_DRC
02992             RCObject *rc = (RCObject*)Pointer(*(RCObject**)address);
02993             if(rc != NULL) {
02994                 GCAssert(rc == FindBeginning(rc));
02995                 GCAssert(IsRCObject(rc));
02996                 rc->DecrementRef();
02997             }
02998         #endif
02999         *(uintptr*)address = (uintptr) value;
03000         #ifdef MMGC_DRC     
03001             rc = (RCObject*)Pointer(value);
03002             if(rc != NULL) {
03003                 GCAssert(IsRCObject(rc));
03004                 GCAssert(rc == FindBeginning(value));
03005                 rc->IncrementRef();
03006             }
03007         #endif
03008     }


Friends And Related Function Documentation

friend class GCAlloc [friend]
 

Definition at line 549 of file GC.h.

Referenced by GC().

friend class GCCallback [friend]
 

Definition at line 548 of file GC.h.

friend class GCInterval [friend]
 

Definition at line 552 of file GC.h.

friend class GCLargeAlloc [friend]
 

Definition at line 550 of file GC.h.

friend class GCRoot [friend]
 

Definition at line 547 of file GC.h.

Referenced by CollectWithBookkeeping().

friend class RCObject [friend]
 

Definition at line 551 of file GC.h.

friend class ZCT [friend]
 

Definition at line 553 of file GC.h.


Member Data Documentation

unsigned int MMgc::GC::allocsSinceCollect [private]
 

Number of pages allocated from the GCHeap since the start of the current GC cycle.

Requires((request && m_lock) || exclusiveGC)

Definition at line 1380 of file GC.h.

Referenced by AllocBlock(), AllocBlockIncremental(), AllocBlockNonIncremental(), FreeBlock(), MaybeGC(), and Sweep().

uint64 MMgc::GC::bytesMarked
 

Total number of bytes of pointer-containing memory scanned by this GC. Used to measure marking rate, which is bytesMarked/ticksToMillis(markTicks).

ReadWrite(request, exclusiveGC)

Definition at line 1055 of file GC.h.

Referenced by MarkItem().

bool MMgc::GC::collecting [private]
 

True during the sweep phase of collection. Several things have to behave a little differently during this phase. For example, GC::Free() does nothing during sweep phase; otherwise finalizers could be called twice.

Also, Collect() uses this to protect itself from recursive calls (from badly behaved finalizers).

ReadWrite(request, exclusiveGC)

Definition at line 1393 of file GC.h.

Referenced by MMgc::GCLargeAlloc::Alloc(), MMgc::GCAlloc::Alloc(), AllocBlock(), AllocBlockIncremental(), CollectWithBookkeeping(), MMgc::GCAlloc::CreateChunk(), FinishIncrementalMark(), Free(), FreeBlock(), StartIncrementalMark(), and Sweep().

size_t MMgc::GC::collectThreshold
 

Expand, don't collect, until we reach this threshold. Units are pages, not KB, just like GCHeap::GetTotalHeapSize().

In an MMGC_THREADSAFE build, the GC reads this configuration value only when holding the GC lock. Set it during initialization, before the GC is visible to multiple threads.

Requires(m_lock)

Definition at line 613 of file GC.h.

Referenced by AllocBlock(), AllocBlockIncremental(), AllocBlockNonIncremental(), and MaybeGC().

GCAlloc* MMgc::GC::containsPointersAllocs[kNumSizeClasses] [private]
 

Definition at line 1295 of file GC.h.

Referenced by AllocAlreadyLocked(), ClearMarks(), Finalize(), GC(), GetBytesInUse(), and StartIncrementalMark().

bool MMgc::GC::destroying [private]
 

Definition at line 1167 of file GC.h.

Referenced by FreeBlock(), and ~GC().

bool MMgc::GC::disableThreadCheck [private]
 

Definition at line 1191 of file GC.h.

Referenced by CheckThread().

bool MMgc::GC::dontAddToZCTDuringCollection
 

Definition at line 627 of file GC.h.

bool MMgc::GC::finalizedValue [private]
 

Requires((request && m_lock) || exclusiveGC)

Definition at line 1396 of file GC.h.

Referenced by MMgc::GCAlloc::CreateChunk().

bool MMgc::GC::findUnmarkedPointers
 

findUnmarkedPointers is a debugging flag, only

Definition at line 594 of file GC.h.

bool MMgc::GC::gcstats
 

If true, log some statistics during each collection. The output goes to gclog().

In an MMGC_THREADSAFE build, the GC reads this flag only during stop-the-world collection. Set it during initialization, before the GC is visible to multiple threads.

Requires(exclusiveGC)

Definition at line 625 of file GC.h.

Referenced by Sweep().

bool MMgc::GC::greedy
 

greedy is a debugging flag. When set, every allocation will cause a garbage collection. This makes code run abysmally slow, but can be useful for detecting mark bugs.

The GC reads this flag only when holding the GC lock. It is best to set it as soon as the GC is created.

Requires(m_lock)

Definition at line 581 of file GC.h.

Referenced by AllocAlreadyLocked(), and MaybeGC().

GCHeap* MMgc::GC::heap [private]
 

Definition at line 1301 of file GC.h.

Referenced by AllocBlock(), AllocBlockIncremental(), AllocBlockNonIncremental(), FreeBlock(), GetBits(), heapAlloc(), heapFree(), MarkGCPages(), MaybeGC(), Sweep(), and updateGrossMemoryStats().

size_t MMgc::GC::heapSizeAtLastAlloc [private]
 

We track the heap size so if it expands due to fixed memory allocations we can trigger a mark/sweep. Otherwise we can have lots of small GC objects allocating tons of fixed memory, which results in huge heaps and possible out of memory situations.

Requires(m_lock)

Definition at line 1177 of file GC.h.

Referenced by AllocBlock(), and MaybeGC().

bool MMgc::GC::hitZeroObjects
 

True if we emptied the work queue during the most recent incremental mark. This means the next mark will force the GC cycle through to completion.

ReadWrite(request, exclusiveGC)

Definition at line 1111 of file GC.h.

Referenced by FinishIncrementalMark(), and IncrementalMark().

bool MMgc::GC::incremental
 

Configuration flag enabling incremental collection.

In an MMGC_THREADSAFE build, the GC reads this flag only when holding the GC lock. Set it during initialization.

Requires(m_lock)

Definition at line 642 of file GC.h.

Referenced by AllocBlock(), and MaybeGC().

bool MMgc::GC::incrementalValidation
 

Definition at line 628 of file GC.h.

Referenced by AllocBlockIncremental(), and IncrementalMark().

bool MMgc::GC::keepDRCHistory
 

Definition at line 601 of file GC.h.

const int MMgc::GC::kNumSizeClasses = 40 [static, private]
 

Definition at line 1141 of file GC.h.

Referenced by ClearMarks(), Finalize(), GC(), StartIncrementalMark(), and ~GC().

const int MMgc::GC::kPageUsableSpace = 3936 [static, private]
 

Definition at line 1144 of file GC.h.

const int16 MMgc::GC::kSizeClasses [static, private]
 

Initial value:

 {
        8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 
        88, 96, 104, 112, 120, 128, 144, 160, 168, 176,  
        184, 192, 200, 216, 224, 240, 256, 280, 296, 328, 
        352, 392, 432, 488, 560, 656, 784, 984, 1312, 1968 
    }

Definition at line 1216 of file GC.h.

Referenced by GC().

const uint8 MMgc::GC::kSizeClassIndex [static, private]
 

Initial value:

 {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
        10, 11, 12, 13, 14, 15, 16, 16, 17, 17,
        18, 19, 20, 21, 22, 23, 23, 24, 25, 25,
        26, 26, 27, 27, 27, 28, 28, 29, 29, 29,
        29, 30, 30, 30, 31, 31, 31, 31, 31, 32,
        32, 32, 32, 32, 33, 33, 33, 33, 33, 33,
        33, 34, 34, 34, 34, 34, 34, 34, 34, 34,
        35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
        35, 35, 36, 36, 36, 36, 36, 36, 36, 36,
        36, 36, 36, 36, 36, 36, 36, 36, 37, 37,
        37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
        37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
        37, 37, 37, 38, 38, 38, 38, 38, 38, 38,
        38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
        38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
        38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
        38, 38, 38, 38, 39, 39, 39, 39, 39, 39,
        39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
        39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
        39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
        39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
        39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
        39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
        39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
        39, 39, 39, 39, 39, 39  
    }

Definition at line 1217 of file GC.h.

Referenced by AllocAlreadyLocked().

GCLargeAlloc* MMgc::GC::largeAlloc [private]
 

Definition at line 1300 of file GC.h.

Referenced by AllocAlreadyLocked(), and Free().

GCLargeAlloc::LargeBlock* MMgc::GC::largeEmptyPageList [private]
 

List of pages to be swept, built up in Finalize. Requires(exclusiveGC)

Definition at line 1422 of file GC.h.

Referenced by Sweep().

uint64 MMgc::GC::lastMarkTicks [private]
 

ReadWrite(request, exclusiveGC)

Definition at line 1212 of file GC.h.

Referenced by AllocBlockIncremental().

uint32 MMgc::GC::lastStartMarkIncrementCount
 

Definition at line 1066 of file GC.h.

Referenced by StartIncrementalMark().

uint64 MMgc::GC::lastSweepTicks [private]
 

ReadWrite(request, exclusiveGC)

Definition at line 1214 of file GC.h.

Referenced by AllocBlock(), AllocBlockIncremental(), MaybeGC(), and Sweep().

uint32* MMgc::GC::m_bitsFreelists[kNumSizeClasses] [private]
 

Requires((request && m_lock) || exclusiveGC)

Definition at line 1160 of file GC.h.

Referenced by GetBits(), and ~GC().

uint32* MMgc::GC::m_bitsNext [private]
 

Requires((request && m_lock) || exclusiveGC)

Definition at line 1162 of file GC.h.

Referenced by GetBits().

GCCallback* MMgc::GC::m_callbacks [private]
 

Points to the head of a linked list of callback objects.

Requires(m_callbackListLock)

Definition at line 1442 of file GC.h.

Referenced by AddCallback(), CollectWithBookkeeping(), RemoveCallback(), and Sweep().

void* MMgc::GC::m_contextVars[GCV_COUNT] [private]
 

Definition at line 1219 of file GC.h.

GCStack<GCWorkItem> MMgc::GC::m_incrementalWork [private]
 

Definition at line 1204 of file GC.h.

Referenced by FinishIncrementalMark(), IncrementalMark(), StartIncrementalMark(), Sweep(), and TrapWrite().

GCRoot* MMgc::GC::m_roots [private]
 

Requires(m_rootListLock)

Definition at line 1429 of file GC.h.

Referenced by AddRoot(), FinishIncrementalMark(), and RemoveRoot().

uint32 MMgc::GC::markIncrements
 

Definition at line 1067 of file GC.h.

Referenced by StartIncrementalMark().

bool MMgc::GC::marking [private]
 

True if incremental marking is on and some objects have been marked. This means write barriers are enabled.

ReadWrite(request, exclusiveGC)

The GC thread may read and write this flag. Application threads in requests have read-only access.

Definition at line 1203 of file GC.h.

Referenced by AllocAlreadyLocked(), AllocBlock(), AllocBlockIncremental(), CollectImpl(), FinishIncrementalMark(), Free(), MaybeGC(), StartIncrementalMark(), Sweep(), TrapWrite(), WriteBarrier(), and WriteBarrierNoSub().

uint32 MMgc::GC::marks
 

Number of calls to MarkItem(). ReadWrite(request, exclusiveGC)

Definition at line 1073 of file GC.h.

Referenced by MarkItem().

uint64 MMgc::GC::markTicks
 

Total time spent doing incremental marking, in ticks. See bytesMarked.

ReadWrite(request, exclusiveGC)

Definition at line 1063 of file GC.h.

uintptr MMgc::GC::memEnd [private]
 

Requires(pageMapLock)

Definition at line 1229 of file GC.h.

Referenced by IsPointerToGCPage(), and MarkGCPages().

uintptr MMgc::GC::memStart [private]
 

Requires(pageMapLock)

Definition at line 1227 of file GC.h.

Referenced by ClearPageMapValue(), GetPageMapValueAlreadyLocked(), IsPointerToGCPage(), MarkGCPages(), and SetPageMapValue().

bool MMgc::GC::nogc
 

nogc is a debugging flag. When set, garbage collection never happens.

Requires(m_lock)

Definition at line 589 of file GC.h.

Referenced by AllocBlock(), AllocBlockIncremental(), and CollectWithBookkeeping().

GCAlloc* MMgc::GC::noPointersAllocs[kNumSizeClasses] [private]
 

Definition at line 1299 of file GC.h.

Referenced by AllocAlreadyLocked(), ClearMarks(), Finalize(), GC(), GetBits(), GetBytesInUse(), and StartIncrementalMark().

uint32 MMgc::GC::numObjects
 

Number of calls to MarkItem() during the current (or most recent) IncrementalMark().

ReadWrite(request, exclusiveGC)

Definition at line 1087 of file GC.h.

uint32 MMgc::GC::objSize
 

Number of bytes scanned in MarkItem() during the current (or most recent) IncrementalMark().

ReadWrite(request, exclusiveGC)

Definition at line 1095 of file GC.h.

unsigned char* MMgc::GC::pageMap [private]
 

The bitmap for what pages are in use. Any access to either the pageMap pointer or the bitmap requires pageMapLock.

(Note: A better synchronization scheme might be to use atomic operations to read and write the pageMap pointer, writing it only from within m_lock; and then using atomic read and write operations--on Intel x86, these are just ordinary reads and writes--to access the bitmap, with writes again only from within m_lock. This would require reallocating the pageMap more often, but at least write barriers wouldn't have to acquire the spinlock.)

Requires(pageMapLock)

Definition at line 1251 of file GC.h.

Referenced by ClearPageMapValue(), GetPageMapValueAlreadyLocked(), MarkGCPages(), and SetPageMapValue().

const void* MMgc::GC::rememberedStackBottom [private]
 

Definition at line 1187 of file GC.h.

Referenced by CleanStack(), and GC().

const void* MMgc::GC::rememberedStackTop [private]
 

Definition at line 1186 of file GC.h.

Referenced by CleanStack(), and MarkQueueAndStack().

GCAlloc::GCBlock* MMgc::GC::smallEmptyPageList [private]
 

List of pages to be swept, built up in Finalize. Requires(exclusiveGC)

Definition at line 1409 of file GC.h.

Referenced by Sweep().

bool MMgc::GC::stackCleaned [private]
 

Definition at line 1185 of file GC.h.

Referenced by CleanStack(), and StartIncrementalMark().

GCHashtable MMgc::GC::stats [private]
 

Definition at line 1234 of file GC.h.

Referenced by updateGrossMemoryStats().

uint32 MMgc::GC::sweeps
 

Number of calls to Sweep(). ReadWrite(request, exclusiveGC)

Definition at line 1079 of file GC.h.

Referenced by Sweep().

uint64 MMgc::GC::sweepStart
 

Time of the latest FinishIncrementalMark() call, in ticks.

ReadWrite(request, exclusiveGC)

Definition at line 1102 of file GC.h.

Referenced by FinishIncrementalMark(), and Sweep().

const uint64 MMgc::GC::t0
 

GC initialization time, in ticks. Used for logging.

Definition at line 1026 of file GC.h.

Referenced by Sweep().

size_t MMgc::GC::totalGCPages [private]
 

Requires(m_lock)

Definition at line 1232 of file GC.h.

Referenced by AllocBlock(), AllocBlockIncremental(), AllocBlockNonIncremental(), FreeBlock(), heapAlloc(), heapFree(), MaybeGC(), and updateGrossMemoryStats().

bool MMgc::GC::validateDefRef
 

turns on code that does a trace before reaping zero count object and asserting on any objects that get marked, debug builds only

Definition at line 600 of file GC.h.

Referenced by MarkItem().

GCHashtable MMgc::GC::weakRefs [private]
 

Requires((request && m_lock) || exclusiveGC)

Definition at line 1165 of file GC.h.

Referenced by ClearWeakRef(), and GetWeakRef().


The documentation for this class was generated from the following files:
Generated on Sun Oct 12 18:51:37 2008 for Tamarin by  doxygen 1.4.6