Turbo Haskell  0.1
 All Classes Functions Variables Pages
gc.h
1 #ifndef INCLUDED_RTS_GC_H
2 #define INCLUDED_RTS_GC_H
3 
4 #include <cassert>
5 #include <cstdint>
6 #include <mutex>
7 #include <queue>
8 #include <unordered_set>
9 #include "rts/thread_local.h"
10 #include <boost/lockfree/queue.hpp>
11 
12 namespace rts {
13 
14 using std::uint16_t;
15 using std::uint32_t;
16 using std::uint64_t;
17 using std::uintptr_t;
18 using std::mutex;
19 using std::unordered_set;
20 using std::unique_lock;
21 
22 namespace spaces {
23  enum {
24  external = 0,
25  local_min = 1,
26  local_max = 7,
27  global_min = 8,
28  global_max = 15
29  };
30 }
31 
32 namespace triggers {
33  enum {
34  nmt = 1,
35  relocation = 2,
36  contraction = 4
37  };
38 }
39 
40 namespace types {
41  enum {
42  constructor = 0,
43  closure = 1,
44  indirection = 2,
45  blackhole = 3
46  };
47 }
48 
49 class hec;
50 
51 struct gc_ptr;
52 
53 // global garbage collector configuration
54 
55 extern mutex gc_mutex;
56 
57 // contents under the gc_mutex
58 extern uint32_t regions_begin; // lo <= x < hi
59 extern uint32_t regions_end;
60 extern uint64_t * mapped_regions; // 1 bit per region, packed
61 extern unordered_set<hec*> hecs;
62 // end contents under the gc_mutex
63 
64 extern boost::lockfree::queue<gc_ptr> global_mark_queue[8];
65 
66 static inline bool protected_region(uint32_t r) {
67  assert(regions_begin <= r && r < regions_end);
68  return mapped_regions[r>>6]&(1<<((r-regions_begin)&0x3f));
69 }
70 
71 
74 struct gc_ptr {
75  union {
76  // layout chosen so that a 0-extended 32 bit integer is a legal 'gc_ptr' as are legal native c pointers
77  // TODO: consider setting space 15 to also be a native pointer that way 0 and 1 extended pointers would
78  // be legal.
79  uint64_t unique : 1,
80  type : 2,
81  offset : 9,
82  segment : 9,
83  region : 19,
84  nmt : 1,
85  space : 4,
86  tag : 19;
87  uint64_t addr;
88  };
89 
91  static const uint64_t mask = 0x7ffffffff8;
92 
93  template <typename T> T & operator * () {
94  return *reinterpret_cast<T *>(addr&mask);
95  };
96 
97  template <typename T> T * operator -> () {
98  return reinterpret_cast<T *>(addr&mask);
99  };
100 
101  template <typename T> T & operator [] (std::ptrdiff_t i) {
102  return *reinterpret_cast<T *>((addr&mask) + (i * sizeof(T)));
103  }
104 
105  // TODO: partially template specialize these to make it so gc_ptr loads from those addresses automatically apply the
106 
108  void lvb(uint64_t * address, bool unique_context = true);
109 
110  private:
112  void lvb_slow_path(uint64_t * address, int trigger);
113 };
114 
115 inline bool operator==(const gc_ptr& lhs, const gc_ptr& rhs){ return lhs.addr == rhs.addr; }
116 inline bool operator!=(const gc_ptr& lhs, const gc_ptr& rhs){ return lhs.addr != rhs.addr; }
117 
119 class hec {
120  public:
121  static thread_local hec * current;
122  uint16_t expected_nmt;
123  std::queue<gc_ptr> local_mark_queue[8];
124 
125  private:
126  hec(hec const &);
127  hec & operator = (hec const &);
128 
129  public:
130  hec() {
131  current = this;
132  unique_lock<mutex> lock(gc_mutex);
133  hecs.insert(this);
134  }
135  ~hec() {
136  current = nullptr;
137  unique_lock<mutex> lock(gc_mutex);
138  hecs.erase(this);
139  }
140 
143  inline bool get_expected_nmt(int i) { return expected_nmt & (1 << i); }
144 };
145 
146 inline void gc_ptr::lvb(uint64_t * address, bool unique_context) {
147  if (space != 0) {
148  int trigger = 0;
149  if (nmt != hec::current->get_expected_nmt(space)) trigger |= triggers::nmt;
150  if (protected_region(region)) trigger |= triggers::relocation;
151  if (!unique_context && unique) trigger |= triggers::contraction;
152  if (trigger != 0) lvb_slow_path(address, trigger);
153  }
154 }
155 
156 } // namespace rts
157 
158 #endif
A heap pointer.
Definition: gc.h:74
uint16_t expected_nmt
16 bits, one per space
Definition: gc.h:122
uint64_t offset
offset within a 4k page
Definition: gc.h:79
uint64_t unique
does this reference locally believe it is unique?
Definition: gc.h:79
uint64_t nmt
not-marked-through toggle for LVB read-barrier
Definition: gc.h:79
static const uint64_t mask
mask for the offset, segment and region
Definition: gc.h:91
uint64_t region
which 2mb region in the system? 1tb addressable.
Definition: gc.h:79
void lvb(uint64_t *address, bool unique_context=true)
loaded-value-barrier read-barrier, modified to do contraction of "locally unique" references when the...
Definition: gc.h:146
Definition: gc.h:12
uint64_t space
which generation/space are we in?
Definition: gc.h:79
static thread_local hec * current
track the current haskell execution context in a thread_local variable.
Definition: gc.h:121
A "Haskell execution context".
Definition: gc.h:119
uint64_t type
what type of this pointer is this?
Definition: gc.h:79
bool get_expected_nmt(int i)
extract an appropriate bit from out expected_nmt mask for what the expected value of the 'not-marked-...
Definition: gc.h:143
uint64_t tag
constructor #
Definition: gc.h:79
std::queue< gc_ptr > local_mark_queue[8]
mark queues for local spaces
Definition: gc.h:123
uint64_t segment
which 4k page within a 2mb region
Definition: gc.h:79