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