#include <GC.h>
Inheritance diagram for MMgc::GC:

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::AvmCore * | core () 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) |
| GCHeap * | GetGCHeap () 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 GC * | GetGC (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 GCWeakRef * | GetWeakRef (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) |
| uint32 * | GetBits (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 | |
| uint32 * | m_bitsFreelists [kNumSizeClasses] |
| uint32 * | m_bitsNext |
| GCHashtable | weakRefs |
| bool | destroying |
| size_t | heapSizeAtLastAlloc |
| bool | stackCleaned |
| const void * | rememberedStackTop |
| const void * | rememberedStackBottom |
| bool | disableThreadCheck |
| bool | marking |
| GCStack< GCWorkItem > | m_incrementalWork |
| uint64 | lastMarkTicks |
| uint64 | lastSweepTicks |
| void * | m_contextVars [GCV_COUNT] |
| uintptr | memStart |
| uintptr | memEnd |
| size_t | totalGCPages |
| GCHashtable | stats |
| unsigned char * | pageMap |
| GCAlloc * | containsPointersAllocs [kNumSizeClasses] |
| GCAlloc * | noPointersAllocs [kNumSizeClasses] |
| GCLargeAlloc * | largeAlloc |
| GCHeap * | heap |
| unsigned int | allocsSinceCollect |
| bool | collecting |
| bool | finalizedValue |
| GCAlloc::GCBlock * | smallEmptyPageList |
| GCLargeAlloc::LargeBlock * | largeEmptyPageList |
| GCRoot * | m_roots |
| GCCallback * | m_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 |
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.
|
|
If you need context vars use this! Definition at line 559 of file GC.h. 00560 { 00561 GCV_COREPLAYER, 00562 GCV_AVMCORE, 00563 GCV_COUNT 00564 };
|
|
|
flags to be passed as second argument to alloc Definition at line 676 of file GC.h. 00677 { 00678 kZero=1, 00679 kContainsPointers=2, 00680 kFinalize=4, 00681 kRCObject=8 00682 };
|
|
|
Definition at line 684 of file GC.h. 00685 { 00686 kNonGC = 0, 00687 kGCAllocPage = 1, 00688 kGCLargeAllocPageRest = 2, 00689 kGCLargeAllocPageFirst = 3 00690 };
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
Requires(exclusiveGC) Definition at line 1399 of file GC.h. References MMgc::GCAlloc::GCBlock::next. 01400 { 01401 b->next = smallEmptyPageList; 01402 smallEmptyPageList = b; 01403 }
|
|
||||||||||||
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
True during Sweep phase. Application code can use this to determine if it's being called (directly or indirectly) from a finalizer.
Definition at line 1002 of file GC.h. 01003 { 01004 return collecting; 01005 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
Mark a region of memory, this will search all memory pointed to recursively and mark any GC Objects it finds |
|
||||||||||||
|
Definition at line 939 of file GC.h. 00940 { 00941 if(IsPointerToGCPage(address)) 00942 WriteBarrierNoSubstitute(FindBeginning(address), value); 00943 }
|
|
|
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 }
|
|
|
Definition at line 568 of file GC.h. Referenced by AllocAlreadyLocked(), IncrementalMark(), and Sweep(). 00568 { return (avmplus::AvmCore*)GetGCContextVariable(GCV_AVMCORE); }
|
|
|
Definition at line 1120 of file GC.h. 01120 { return destroying; }
|
|
|
Definition at line 1022 of file GC.h. 01022 { disableThreadCheck = true; }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
Requires(exclusiveGC) Definition at line 1353 of file GC.h. Referenced by ~GC(). 01353 { Sweep(true); }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
Referenced by log_mem(), Sweep(), and updateGrossMemoryStats(). |
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
|
Definition at line 565 of file GC.h. Referenced by AllocAlreadyLocked(), avmplus::String::charAt(), and avmplus::String::localeCompare(). 00565 { return m_contextVars[var]; }
|
|
|
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; }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
Are we currently marking Definition at line 875 of file GC.h. 00875 { return marking; }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
Requires(request || exclusiveGC) Definition at line 3067 of file GC.cpp. References GetMark(), and IsWhite(). Referenced by Free().
|
|
|
Definition at line 991 of file GC.h. Referenced by avmplus::AvmCore::gcObjectToAtom(), WriteBarrierWrite(), and WriteBarrierWriteRC().
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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().
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 }
|
|
|
Definition at line 1457 of file GC.h. Referenced by WriteBarrier(), and WriteBarrierWriteRC(). 01457 { return (const void*)(((uintptr)p)&~7); }
|
|
||||||||||||
|
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 }
|
|
|
Definition at line 1131 of file GC.h. Referenced by MarkQueueAndStack(), and TrapWrite(). 01131 { PushWorkItem(m_incrementalWork, item); }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
Definition at line 566 of file GC.h. Referenced by avmplus::AvmCore::~AvmCore(). 00566 { m_contextVars[var] = val; }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
Definition at line 1545 of file GC.h.
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
Definition at line 549 of file GC.h. Referenced by GC(). |
|
|
|
|
|
|
|
|
|
|
|
Definition at line 547 of file GC.h. Referenced by CollectWithBookkeeping(). |
|
|
|
|
|
|
|
|
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(). |
|
|
Total number of bytes of pointer-containing memory scanned by this GC. Used to measure marking rate, which is ReadWrite(request, exclusiveGC) Definition at line 1055 of file GC.h. Referenced by MarkItem(). |
|
|
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(). |
|
|
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(). |
|
|
Definition at line 1295 of file GC.h. Referenced by AllocAlreadyLocked(), ClearMarks(), Finalize(), GC(), GetBytesInUse(), and StartIncrementalMark(). |
|
|
Definition at line 1167 of file GC.h. Referenced by FreeBlock(), and ~GC(). |
|
|
Definition at line 1191 of file GC.h. Referenced by CheckThread(). |
|
|
|
|
|
Requires((request && m_lock) || exclusiveGC) Definition at line 1396 of file GC.h. Referenced by MMgc::GCAlloc::CreateChunk(). |
|
|
findUnmarkedPointers is a debugging flag, only |
|
|
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(). |
|
|
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(). |
|
|
Definition at line 1301 of file GC.h. Referenced by AllocBlock(), AllocBlockIncremental(), AllocBlockNonIncremental(), FreeBlock(), GetBits(), heapAlloc(), heapFree(), MarkGCPages(), MaybeGC(), Sweep(), and updateGrossMemoryStats(). |
|
|
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(). |
|
|
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(). |
|
|
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(). |
|
|
Definition at line 628 of file GC.h. Referenced by AllocBlockIncremental(), and IncrementalMark(). |
|
|
|
|
|
Definition at line 1141 of file GC.h. Referenced by ClearMarks(), Finalize(), GC(), StartIncrementalMark(), and ~GC(). |
|
|
|
|
|
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(). |
|
|
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(). |
|
|
Definition at line 1300 of file GC.h. Referenced by AllocAlreadyLocked(), and Free(). |
|
|
List of pages to be swept, built up in Finalize. Requires(exclusiveGC) Definition at line 1422 of file GC.h. Referenced by Sweep(). |
|
|
ReadWrite(request, exclusiveGC) Definition at line 1212 of file GC.h. Referenced by AllocBlockIncremental(). |
|
|
Definition at line 1066 of file GC.h. Referenced by StartIncrementalMark(). |
|
|
ReadWrite(request, exclusiveGC) Definition at line 1214 of file GC.h. Referenced by AllocBlock(), AllocBlockIncremental(), MaybeGC(), and Sweep(). |
|
|
Requires((request && m_lock) || exclusiveGC) |
|
|
Requires((request && m_lock) || exclusiveGC) Definition at line 1162 of file GC.h. Referenced by GetBits(). |
|
|
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(). |
|
|
|
|
|
Definition at line 1204 of file GC.h. Referenced by FinishIncrementalMark(), IncrementalMark(), StartIncrementalMark(), Sweep(), and TrapWrite(). |
|
|
Requires(m_rootListLock) Definition at line 1429 of file GC.h. Referenced by AddRoot(), FinishIncrementalMark(), and RemoveRoot(). |
|
|
Definition at line 1067 of file GC.h. Referenced by StartIncrementalMark(). |
|
|
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(). |
|
|
Number of calls to MarkItem(). ReadWrite(request, exclusiveGC) Definition at line 1073 of file GC.h. Referenced by MarkItem(). |
|
|
Total time spent doing incremental marking, in ticks. See bytesMarked. ReadWrite(request, exclusiveGC) |
|
|
Requires(pageMapLock) Definition at line 1229 of file GC.h. Referenced by IsPointerToGCPage(), and MarkGCPages(). |
|
|
Requires(pageMapLock) Definition at line 1227 of file GC.h. Referenced by ClearPageMapValue(), GetPageMapValueAlreadyLocked(), IsPointerToGCPage(), MarkGCPages(), and SetPageMapValue(). |
|
|
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(). |
|
|
Definition at line 1299 of file GC.h. Referenced by AllocAlreadyLocked(), ClearMarks(), Finalize(), GC(), GetBits(), GetBytesInUse(), and StartIncrementalMark(). |
|
|
Number of calls to MarkItem() during the current (or most recent) IncrementalMark(). ReadWrite(request, exclusiveGC) |
|
|
Number of bytes scanned in MarkItem() during the current (or most recent) IncrementalMark(). ReadWrite(request, exclusiveGC) |
|
|
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(). |
|
|
Definition at line 1187 of file GC.h. Referenced by CleanStack(), and GC(). |
|
|
Definition at line 1186 of file GC.h. Referenced by CleanStack(), and MarkQueueAndStack(). |
|
|
List of pages to be swept, built up in Finalize. Requires(exclusiveGC) Definition at line 1409 of file GC.h. Referenced by Sweep(). |
|
|
Definition at line 1185 of file GC.h. Referenced by CleanStack(), and StartIncrementalMark(). |
|
|
Definition at line 1234 of file GC.h. Referenced by updateGrossMemoryStats(). |
|
|
Number of calls to Sweep(). ReadWrite(request, exclusiveGC) Definition at line 1079 of file GC.h. Referenced by Sweep(). |
|
|
Time of the latest FinishIncrementalMark() call, in ticks. ReadWrite(request, exclusiveGC) Definition at line 1102 of file GC.h. Referenced by FinishIncrementalMark(), and Sweep(). |
|
|
GC initialization time, in ticks. Used for logging. Definition at line 1026 of file GC.h. Referenced by Sweep(). |
|
|
Requires(m_lock) Definition at line 1232 of file GC.h. Referenced by AllocBlock(), AllocBlockIncremental(), AllocBlockNonIncremental(), FreeBlock(), heapAlloc(), heapFree(), MaybeGC(), and updateGrossMemoryStats(). |
|
|
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(). |
|
|
Requires((request && m_lock) || exclusiveGC) Definition at line 1165 of file GC.h. Referenced by ClearWeakRef(), and GetWeakRef(). |
1.4.6