jitcraft/Heap.h
author David Anderson <dvander@alliedmods.net>
Fri Jul 06 19:24:22 2012 -0400 (2012-07-06)
changeset 51 fb324242a675
parent 49 a92afa7484fd
child 52 22b67b4cf067
permissions -rw-r--r--
Removed HeapChunk::cursor_, converted LifoSpace to HeapChunk.
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@28
    28
namespace jc {
dvander@28
    29
dvander@28
    30
class Zone;
dvander@28
    31
dvander@49
    32
// Heap-allocated objects go here. Heaps are thread-local. The heap contains
dvander@49
    33
// four spaces:
dvander@49
    34
//
dvander@49
    35
//    LIFO Space:  Used for objects that may be stack-allocated.
dvander@49
    36
//    New Space:   Used for objects that are expected to be short-lived.
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@49
    42
// The garbage collector is both incremental and generational. Marking is
dvander@49
    43
// performed incrementally, interleaved with program execution. Minor
dvander@49
    44
// collections are also performed to mitigate the potential necessity of
dvander@49
    45
// major collections.
dvander@49
    46
//
dvander@49
    47
// MINOR COLLECTIONS (also called "scavenges") are usually performed when the
dvander@49
    48
//   new space reaches maximum capacity. During a minor collection, all live
dvander@49
    49
//   objects in the new space are moved into the old space. Then, the new space
dvander@49
    50
//   is reset such that it is empty.
dvander@49
    51
//
dvander@49
    52
//   The new is split into contiguous halves. When both halves reach maximum
dvander@49
    53
//   capacity, a scavenge is performed on the older half. Thus, allocation is
dvander@49
    54
//   only ever performed in one half at a time, to give newer objects a chance
dvander@49
    55
//   to die.
dvander@49
    56
//
dvander@49
    57
//   Scavenges are beneficial for two major reasons:
dvander@49
    58
//    (1) Allocation from the new space is just a pointer bump.
dvander@49
    59
//    (2) Only the root set and remembered sets need to visited.
dvander@49
    60
//
dvander@49
    61
//   The "remembered set" is a list of all pointers that reach into the new
dvander@49
    62
//   space, but come from the Old or Large spaces. The remembered set is
dvander@49
    63
//   maintained via write barriers, and if it becomes full, entire chunks
dvander@49
    64
//   are marked as requiring traversal.
dvander@49
    65
//
dvander@49
    66
//   The root and remembered sets must be visited twice: once to determine
dvander@49
    67
//   which objects in the new space are live, and again to update any
dvander@49
    68
//   references after the new space has been reclaimed.
dvander@49
    69
//
dvander@49
    70
//   Live objects in the LIFO space are always deeply traversed for pointers
dvander@49
    71
//   into the new space, since it would be too difficult to maintain a working
dvander@49
    72
//   remembered set.
dvander@49
    73
//
dvander@49
    74
// MAJOR COLLECTIONS are performed periodically, when either a given memory
dvander@49
    75
//   threshold has been reached, or when requested by the host application.
dvander@49
    76
//   They are also performed if no memory can be allocated.
dvander@49
    77
//
dvander@49
    78
//   Major collections are extremely slow; they require full heap traversal,
dvander@49
    79
//   which can take more than a second on very large heaps. However, they
dvander@49
    80
//   have the greatest chance at reclaiming all syntactically dead objects.
dvander@49
    81
//
dvander@49
    82
// SWEEPING is performed after major collections. The free space in between
dvander@49
    83
//   live objects is added to a free list. Tenured allocations are then
dvander@49
    84
//   performed in the free space, if possible.
dvander@49
    85
//
dvander@28
    86
class Heap
dvander@28
    87
{
dvander@28
    88
    Zone *zone_;
dvander@28
    89
    HeapStack lifoSpace_;
dvander@28
    90
    OldSpace mapSpace_;
dvander@28
    91
    OldSpace oldSpace_;
dvander@49
    92
    LargeObjectSpace largeSpace_;
dvander@28
    93
dvander@28
    94
    Map *metaMap_;
dvander@28
    95
dvander@11
    96
  public:
dvander@28
    97
    enum Tenure {
dvander@28
    98
        // Default, objects go into the nursery.
dvander@28
    99
        Tenure_Default,
dvander@28
   100
        
dvander@28
   101
        // If objects are proven to not escape the stack, they can go into
dvander@28
   102
        // a LIFO arena. Allocation on the LIFO arena is not guaranteed to
dvander@28
   103
        // succeed; thus, objects may still be allocated in other arenas.
dvander@28
   104
        Tenure_Stack,
dvander@28
   105
dvander@28
   106
        // Objects that should not go into the nursery (i.e. are expected
dvander@28
   107
        // to be long-living) go here.
dvander@28
   108
        Tenure_Old
dvander@28
   109
    };
dvander@28
   110
dvander@28
   111
  private:
dvander@49
   112
    inline Address newLargeObject(size_t bytes);
dvander@49
   113
    inline Address newOldObject(size_t bytes);
dvander@28
   114
    inline Address newStackObject(size_t bytes);
dvander@28
   115
    inline Address newObject(size_t bytes, Tenure pretenure);
dvander@11
   116
dvander@51
   117
    void mark();
dvander@51
   118
dvander@28
   119
  public:
dvander@28
   120
    Heap(Zone *zone);
dvander@28
   121
    bool initialize();
dvander@28
   122
dvander@28
   123
    inline Object *allocate(Handle<Map> map, size_t byes, Tenure pretenure);
dvander@28
   124
    Map *allocateMap(MapKind kind, size_t bytes);
dvander@28
   125
dvander@28
   126
    Map *metaMap() {
dvander@28
   127
        return metaMap_;
dvander@28
   128
    }
dvander@28
   129
    inline Address lifoPosition() const {
dvander@28
   130
        return lifoSpace_.position();
dvander@28
   131
    }
dvander@28
   132
    inline void unwindLifo(Address to) {
dvander@28
   133
        lifoSpace_.unwind(to);
dvander@28
   134
    }
dvander@49
   135
dvander@49
   136
    // Perform a full garbage collection.
dvander@49
   137
    void reclaim();
dvander@28
   138
};
dvander@28
   139
dvander@28
   140
}
dvander@28
   141
dvander@28
   142
#endif //_include_jitcraft_heap_h_