jitcraft/Heap.h
author David Anderson <dvander@alliedmods.net>
Sat Jul 07 21:30:23 2012 -0700 (2012-07-07)
changeset 59 b7d61ddb3c8d
parent 53 13bd3a8df334
child 69 dfce0539a77d
permissions -rw-r--r--
Rename jc:: to ke::
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@28
     5
 * This file is part of JITCraft.
dvander@28
     6
 *
dvander@28
     7
 * JITCraft 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@28
    12
 * Foobar 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@28
    17
 * JITCraft. 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@28
   117
  public:
dvander@28
   118
    Heap(Zone *zone);
dvander@52
   119
    ~Heap();
dvander@28
   120
    bool initialize();
dvander@28
   121
dvander@28
   122
    inline Object *allocate(Handle<Map> map, size_t byes, Tenure pretenure);
dvander@28
   123
    Map *allocateMap(MapKind kind, size_t bytes);
dvander@28
   124
dvander@28
   125
    Map *metaMap() {
dvander@28
   126
        return metaMap_;
dvander@28
   127
    }
dvander@28
   128
    inline Address lifoPosition() const {
dvander@28
   129
        return lifoSpace_.position();
dvander@28
   130
    }
dvander@28
   131
    inline void unwindLifo(Address to) {
dvander@28
   132
        lifoSpace_.unwind(to);
dvander@28
   133
    }
dvander@49
   134
dvander@49
   135
    // Perform a full garbage collection.
dvander@49
   136
    void reclaim();
dvander@28
   137
};
dvander@28
   138
dvander@28
   139
}
dvander@28
   140
dvander@28
   141
#endif //_include_jitcraft_heap_h_