00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef __GCHeap__
00040 #define __GCHeap__
00041
00042
00043 namespace MMgc
00044 {
00083 class MMGC_API GCHeap : public GCAllocObject
00084 {
00085 public:
00086
00087
00089 const static int kBlockSize = 4096;
00090
00092 #ifdef UNDER_CE
00093 const static int kDefaultReserve = 512;
00094 #else
00095 const static int kDefaultReserve = 4096;
00096 #endif
00097
00099 const static int kUniqueThreshold = 16;
00100
00105 const static int kHugeThreshold = 128;
00106
00108 const static int kFreeListCompression = 8;
00109
00111 const static int kNumFreeLists = (kHugeThreshold-kUniqueThreshold)/kFreeListCompression+kUniqueThreshold;
00112
00114 const static int kMinHeapIncrement = 32;
00115
00117 const static int kDecommitThresholdPercentage = 25;
00118
00119
00120 const static int kDecommitThresholdMillis = 1000;
00121
00123 int kNativePageSize;
00124
00125 bool heapVerbose;
00126
00127 #ifdef _DEBUG
00128
00131 bool enableMemoryProfiling;
00132 #endif
00133
00137 static void Init(GCMallocFuncPtr malloc = NULL, GCFreeFuncPtr free = NULL, int initialSize=128);
00138
00142 static void Destroy();
00143
00147 static GCHeap *GetGCHeap() { GCAssert(instance != NULL); return instance; }
00148
00155 void *Alloc(int size, bool expand=true, bool zero=true);
00156
00163 void Free(void *item);
00164
00165 size_t Size(const void *item);
00166
00223 bool ExpandHeap(int size);
00224
00225
00231 size_t GetUsedHeapSize() const { return numAlloc; }
00232
00238 size_t GetFreeHeapSize() const { return GetTotalHeapSize()-numAlloc; }
00239
00246 size_t GetTotalHeapSize() const;
00247
00252 void Decommit();
00253
00254 static size_t SizeToBlocks(size_t bytes) { return ((bytes + kBlockSize - 1) & ~(kBlockSize-1)) / kBlockSize; }
00255
00256 static size_t GetPrivateBytes();
00257
00258 void SetHeapLimit(size_t numpages) { heapLimit = numpages; }
00259 private:
00260
00261
00262 static GCHeap *instance;
00263 GCHeap(GCMallocFuncPtr m, GCFreeFuncPtr f, int initialSize);
00264 ~GCHeap();
00265
00266
00267 class Region : public GCAllocObject
00268 {
00269 public:
00270 Region *prev;
00271 char *baseAddr;
00272 char *reserveTop;
00273 char *commitTop;
00274 int blockId;
00275 };
00276 Region *lastRegion;
00277
00278
00279 class MMGC_API HeapBlock : public GCAllocObject
00280 {
00281 public:
00282 char *baseAddr;
00283 int size;
00284 int sizePrevious;
00285 HeapBlock *prev;
00286 HeapBlock *next;
00287 bool committed;
00288 bool dirty;
00289 #ifdef MEMORY_INFO
00290 int allocTrace;
00291 int freeTrace;
00292 #endif
00293 bool inUse() { return prev == NULL; }
00294 };
00295
00296 bool ExpandHeapPrivate(int size);
00297
00298
00299 HeapBlock *blocks;
00300 unsigned int blocksLen;
00301 unsigned int numDecommitted;
00302 HeapBlock freelists[kNumFreeLists];
00303 unsigned int numAlloc;
00304 size_t heapLimit;
00305
00306
00307 void AddToFreeList(HeapBlock *block);
00308 void AddToFreeList(HeapBlock *block, HeapBlock* pointToInsert);
00309 HeapBlock *AllocBlock(int size, bool& zero);
00310 void FreeBlock(HeapBlock *block);
00311 void FreeAll();
00312
00313 HeapBlock *Split(HeapBlock *block, int size);
00314
00315 #ifdef DECOMMIT_MEMORY
00316 void Commit(HeapBlock *block);
00317 #endif
00318
00319 #ifdef _DEBUG
00320 friend class GC;
00321 #endif
00322 HeapBlock *AddrToBlock(const void *item) const;
00323 Region *AddrToRegion(const void *item) const;
00324 void RemoveRegion(Region *r);
00325
00326
00327 GCMallocFuncPtr m_malloc;
00328 GCFreeFuncPtr m_free;
00329
00330
00331 void CheckFreelist();
00332 bool BlocksAreContiguous(void *item1, void *item2);
00333
00334
00335 inline void RemoveFromList(HeapBlock *block)
00336 {
00337 GCAssert(!block->inUse());
00338 block->prev->next = block->next;
00339 block->next->prev = block->prev;
00340 block->next = block->prev = 0;
00341 }
00342
00343
00344
00345
00346 inline int GetFreeListIndex(int size)
00347 {
00348 if (size <= kUniqueThreshold) {
00349 return size-1;
00350 } else if (size >= kHugeThreshold) {
00351 return kNumFreeLists-1;
00352 } else {
00353 return (size-kUniqueThreshold)/kFreeListCompression+kUniqueThreshold-1;
00354 }
00355 }
00356
00357
00358
00359 uint64 decommitTicks;
00360 uint64 decommitThresholdTicks;
00361
00362 #ifdef GCHEAP_LOCK
00363 GCSpinLock m_spinlock;
00364 #endif
00365
00366 #ifdef MMGC_AVMPLUS
00367
00368 int vmPageSize();
00369 size_t committedCodeMemory;
00370
00371 #ifdef WIN32
00372 bool useGuardPages;
00373 #endif
00374
00375
00376 GCSpinLock m_mirBufferLock;
00377 typedef struct _MirMemInfo
00378 {
00379 void* addr;
00380 size_t size;
00381 bool free;
00382 }
00383 MirMemInfo;
00384
00385 static const int MirBufferCount = 8;
00386 MirMemInfo m_mirBuffers[MirBufferCount];
00387
00388 void InitMirMemory();
00389 void FlushMirMemory();
00390
00391 public:
00392
00393
00394 void* ReserveMirMemory(size_t size);
00395 void ReleaseMirMemory(void* addr, size_t size);
00396
00397
00398 void* ReserveCodeMemory(void* address, size_t size);
00399 void* CommitCodeMemory(void* address, size_t size=0);
00400 void* DecommitCodeMemory(void* address, size_t size=0);
00401 void ReleaseCodeMemory(void* address, size_t size);
00402 bool SetGuardPage(void *address);
00403 #ifdef AVMPLUS_JIT_READONLY
00404
00405
00406 void SetPageProtection(void *address, size_t size, bool executeFlag, bool writeableFlag);
00407 #endif
00408 size_t GetCodeMemorySize() const { return committedCodeMemory; }
00409 #endif
00410
00411 #ifdef USE_MMAP
00412 public:
00413 char *ReserveMemory(char *address, size_t size);
00414 bool CommitMemory(char *address, size_t size);
00415 bool DecommitMemory(char *address, size_t size);
00416 void ReleaseMemory(char *address, size_t size);
00417
00418
00419 bool CommitMemoryThatMaySpanRegions(char *address, size_t size);
00420 bool DecommitMemoryThatMaySpanRegions(char *address, size_t size);
00421 #else
00422 char *AllocateMemory(size_t size);
00423 void ReleaseMemory(char *address);
00424 #endif
00425
00426 private:
00427
00428 #ifdef _DEBUG
00429
00430
00431
00432
00433 static uint8 m_megamap[1048576];
00434 #endif
00435 };
00436 }
00437
00438 #endif