src/Heap.h
author David Anderson <dvander@alliedmods.net>
Sat Jan 12 16:35:26 2013 -0800 (2013-01-12)
changeset 260 05de34f712fe
parent 122 0fc1d94166f5
permissions -rw-r--r--
Add support for mutually recursive imports.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _include_jitcraft_heap_h_
    20 #define _include_jitcraft_heap_h_
    21 
    22 #include "Utility.h"
    23 #include "Spaces.h"
    24 #include "Barriers.h"
    25 #include "Objects.h"
    26 #include "Handles.h"
    27 
    28 namespace ke {
    29 
    30 class Zone;
    31 class MarkStack;
    32 
    33 // Heap-allocated objects go here. Heaps are thread-local. The heap contains
    34 // four spaces:
    35 //
    36 //    LIFO Space:  Used for objects that may be stack-allocated.
    37 //    Old Space:   Used for objects that are expected to be long-lived, or that
    38 //                 survive one collection.
    39 //    Large Space: Used for objects that are so large they should never be
    40 //                 moved between spaces.
    41 //
    42 // ALLOCATING AN OBJECT DOES NOT ZERO ITS MEMORY.
    43 // ALLOCATING AN OBJECT DOES NOT ZERO ITS MEMORY!
    44 //
    45 // ---------------------------------------------------------------------------
    46 //
    47 // The following is a high-level overview of how garbage collection works in
    48 // Keima. Detailed notes are present in Heap.cpp.
    49 //
    50 // THE TRI-COLOR INVARIANT: Via an object's mark bits, we maintain the
    51 //   property that an object that has been fully marked may never reference a
    52 //   dead object. Objects exist in three states during collection: unmarked
    53 //   (white), scheduled for marking (grey), and fully marked (black).
    54 //
    55 //   When initiating collection, all objects are white. Objects in the root
    56 //   set are made grey. The marking process takes grey objects and marks that
    57 //   each child object is live: if the child is white, it becomes grey. Once
    58 //   all children are grey or black, the parent grey object can become black,
    59 //   as it has been fully traversed.
    60 //
    61 //   The result of this process is that when there are no more grey objects,
    62 //   then we are guaranteed that all black objects are live, and all white
    63 //   objects are dead.
    64 //
    65 // MAJOR COLLECTIONS are performed periodically, when either a given memory
    66 //   threshold has been reached, or when requested by the host application.
    67 //   They are also performed if no memory can be allocated.
    68 //
    69 //   Major collections are extremely slow; they require full heap traversal,
    70 //   which can take more than a second on very large heaps. However, they
    71 //   have the greatest chance at reclaiming all syntactically dead objects.
    72 //
    73 // SWEEPING is performed after major collections. The free space in between
    74 //   live objects is added to a free list. Tenured allocations are then
    75 //   performed in the free space, if possible.
    76 //
    77 class Heap
    78 {
    79     Zone *zone_;
    80     HeapStack lifoSpace_;
    81     OldSpace mapSpace_;
    82     OldSpace oldSpace_;
    83     LargeObjectSpace largeSpace_;
    84 
    85     Map *metaMap_;
    86 
    87     // This is a big hunk o' memory used for marking iteratively. Eventually,
    88     // this will be replaced by the inactive semispace in the nursery.
    89     void *markStack_;
    90 
    91   public:
    92     enum Tenure {
    93         // Default, objects go into the nursery.
    94         Tenure_Default,
    95         
    96         // If objects are proven to not escape the stack, they can go into
    97         // a LIFO arena. Allocation on the LIFO arena is not guaranteed to
    98         // succeed; thus, objects may still be allocated in other arenas.
    99         Tenure_Stack,
   100 
   101         // Objects that should not go into the nursery (i.e. are expected
   102         // to be long-living) go here.
   103         Tenure_Old
   104     };
   105 
   106   private:
   107     inline Address newLargeObject(size_t bytes);
   108     inline Address newOldObject(size_t bytes);
   109     inline Address newStackObject(size_t bytes);
   110     inline Address newObject(size_t bytes, Tenure pretenure);
   111 
   112   private:
   113     void findGreyObjects(MarkStack &stack);
   114     void mark();
   115     void sweep();
   116 
   117     void reportOutOfMemory();
   118 
   119   public:
   120     Heap(Zone *zone);
   121     ~Heap();
   122     bool initialize();
   123 
   124     inline Object *allocate(Handle<Map> map, size_t byes, Tenure pretenure);
   125     Map *allocateMap(MapKind kind, size_t bytes);
   126 
   127     Map *metaMap() {
   128         return metaMap_;
   129     }
   130     inline Address lifoPosition() const {
   131         return lifoSpace_.position();
   132     }
   133     inline void unwindLifo(Address to) {
   134         lifoSpace_.unwind(to);
   135     }
   136 
   137     // Perform a full garbage collection.
   138     void reclaim();
   139 };
   140 
   141 }
   142 
   143 #endif //_include_jitcraft_heap_h_