GCHeap.h

Go to the documentation of this file.
00001 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is [Open Source Virtual Machine.].
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Adobe System Incorporated.
00019  * Portions created by the Initial Developer are Copyright (C) 2004-2006
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Adobe AS3 Team
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #ifndef __GCHeap__
00040 #define __GCHeap__
00041 
00042 
00043 namespace MMgc
00044 {
00083     class MMGC_API GCHeap : public GCAllocObject
00084     {
00085     public:
00086         // -- Constants
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         // -- Implementation
00262         static GCHeap *instance;
00263         GCHeap(GCMallocFuncPtr m, GCFreeFuncPtr f, int initialSize);
00264         ~GCHeap();
00265         
00266         // Heap regions
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         // Block struct used for free lists and memory traversal
00279         class MMGC_API HeapBlock : public GCAllocObject
00280         {
00281         public:
00282             char *baseAddr;   // base address of block's memory
00283             int size;         // size of this block
00284             int sizePrevious; // size of previous block
00285             HeapBlock *prev;      // prev entry on free list
00286             HeapBlock *next;      // next entry on free list
00287             bool committed;   // is block fully committed?
00288             bool dirty;       // needs zero'ing, only valid if committed
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         // Core data structures
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         // Core methods
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         // only used on mac
00327         GCMallocFuncPtr m_malloc;
00328         GCFreeFuncPtr m_free;
00329 
00330         // debug only freelist consistency checks
00331         void CheckFreelist();
00332         bool BlocksAreContiguous(void *item1, void *item2);
00333 
00334         // Remove a block from a free list (inlined for speed)
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         // Map a number of blocks to the appropriate large block free list index
00345         // (inlined for speed)
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         // used for decommit smoothing
00358         // millis to wait before decommitting anything
00359         uint64 decommitTicks;
00360         uint64 decommitThresholdTicks;
00361 
00362 #ifdef GCHEAP_LOCK
00363         GCSpinLock m_spinlock;
00364 #endif /* GCHEAP_LOCK */
00365 
00366 #ifdef MMGC_AVMPLUS
00367         // OS abstraction to determine native page size
00368         int vmPageSize();
00369         size_t committedCodeMemory;
00370 
00371         #ifdef WIN32
00372         bool useGuardPages;
00373         #endif
00374         
00375         // mir buffer management, share a common pool across threads
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         // support for Mir buffers
00394         void* ReserveMirMemory(size_t size);        
00395         void  ReleaseMirMemory(void* addr, size_t size);
00396 
00397         // support for jit buffers
00398         void* ReserveCodeMemory(void* address, size_t size);
00399         void* CommitCodeMemory(void* address, size_t size=0);  // size=0 => 1 page
00400         void* DecommitCodeMemory(void* address, size_t size=0);  // size=0 => 1 page
00401         void ReleaseCodeMemory(void* address, size_t size);
00402         bool SetGuardPage(void *address);
00403 #ifdef AVMPLUS_JIT_READONLY
00404         // SECURITY: setting executeFlag and writeableFlag at the same time is DANGEROUS! 
00405         //           Make sure that you know what you are doing!
00406         void SetPageProtection(void *address, size_t size, bool executeFlag, bool writeableFlag);
00407 #endif /* AVMPLUS_JIT_READONLY */
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         /* m_megamap is a debugging aid for finding bugs in this
00430            memory allocator.  It tracks allocated/free pages in
00431            the crudest way possible ... a 1MB byte array with a
00432            0/1 byte for every page in the 32-bit address space. */
00433         static uint8 m_megamap[1048576];
00434 #endif
00435     };
00436 }
00437 
00438 #endif /* __GCHeap__ */

Generated on Sun Oct 12 18:50:13 2008 for Tamarin by  doxygen 1.4.6