-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathpz_gc_layout.h
144 lines (116 loc) · 3.21 KB
/
pz_gc_layout.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* Plasma garbage collector memory layout
* vim: ts=4 sw=4 et
*
* Copyright (C) Plasma Team
* Distributed under the terms of the MIT license, see ../LICENSE.code
*/
#ifndef PZ_GC_LAYOUT_H
#define PZ_GC_LAYOUT_H
#include "pz_gc.h"
#include "pz_gc.impl.h"
namespace pz {
constexpr uint8_t Poison_Byte = 0xF0;
/*
* These must be a power-of-two and mmap must align to them. 4K is the
* default.
*/
static const unsigned GC_Block_Log = 13;
static const size_t GC_Block_Size = 1 << (GC_Block_Log - 1);
static const size_t GC_Block_Mask = ~(GC_Block_Size - 1);
static const unsigned GC_Min_Cell_Size = 2;
static const unsigned GC_Cells_Per_Block =
GC_Block_Size / (GC_Min_Cell_Size * WORDSIZE_BYTES);
/*
* GC_Chunk_Size is also a power of two and is therefore a multiple of
* GC_Block_Size. 4MB is the default.
*/
static const unsigned GC_Chunk_Log = 23;
static const size_t GC_Chunk_Size = 1 << (GC_Chunk_Log - 1);
static const size_t GC_Block_Per_Chunk = (GC_Chunk_Size / GC_Block_Size) - 1;
#if PZ_DEV
// Set this low for testing.
static const size_t GC_Initial_Threshold = 8 * GC_Block_Size;
#else
static const size_t GC_Initial_Threshold = 64 * GC_Block_Size;
#endif
static const float GC_Threshold_Factor = 1.5f;
// The threshold for small allocations in words. Allocations of less than
// this many words are small allocations.
static const size_t GC_Small_Alloc_Threshold = 64;
static_assert(GC_Chunk_Size > GC_Block_Size,
"Chunks must be larger than blocks");
/*
* The heap is made out of blocks and chunks. A chunk contains multiple
* blocks, which each contain multiple cells.
*/
enum CellType {
// Used for Invalid cells or unallocated chunks.
CT_INVALID,
CT_BOP,
CT_FIT
};
/*
* This class should be used by-value as a reference to a cell.
*/
class CellPtr
{
protected:
void ** m_ptr;
CellType m_type;
constexpr CellPtr() : m_ptr(nullptr), m_type(CT_INVALID) {}
public:
constexpr explicit CellPtr(void * ptr, CellType type)
: m_ptr(static_cast<void **>(ptr))
, m_type(type)
{}
void ** pointer()
{
return m_ptr;
}
bool is_valid() const
{
return m_ptr != nullptr;
}
bool is_bop_cell() const
{
return m_type == CT_BOP;
}
bool is_fit_cell() const
{
return m_type == CT_FIT;
}
};
/*
* Chunks
*/
class Chunk
{
protected:
Heap * m_heap;
CellType m_type;
private:
Chunk(const Chunk &) = delete;
void operator=(const Chunk &) = delete;
Chunk(Heap * heap) : m_heap(heap), m_type(CT_INVALID) {}
protected:
Chunk(Heap * heap, CellType type) : m_heap(heap), m_type(type) {}
public:
/*
* True if this pointer lies within the allocated part of this chunk.
*/
bool contains_pointer(void * ptr) const
{
return ptr >= this &&
ptr < (reinterpret_cast<const uint8_t *>(this) + GC_Chunk_Size);
};
};
} // namespace pz
#include "pz_gc_layout_bop.h"
#include "pz_gc_layout_fit.h"
namespace pz {
static_assert(
GC_Small_Alloc_Threshold <= Block::Max_Cell_Size,
"The small alloc threshold must be less than the maximum cell size");
} // namespace pz
#endif // ! PZ_GC_LAYOUT_H