@@ -14,12 +14,22 @@ extern "C" {
14
14
15
15
size_t const HYPERBLOCK_SIZE = (size_t )BLOCK_SIZE * 1024 * 1024 ;
16
16
17
+ // After a garbage collect we change the tripwire to the amount of non-garbage times
18
+ // this factor, so we do a decent amount of allocations between collections even
19
+ // when there is very little garbage
20
+ size_t const EXPAND_FACTOR = 2 ;
21
+
22
+ // We don't consider collecting garbage until at least this amount of space has
23
+ // been allocated, to avoid collections near startup when there is little garbage.
24
+ size_t const MIN_SPACE = 1024 * 1024 ;
25
+
17
26
// An arena can be used to allocate objects that can then be deallocated all at
18
27
// once.
19
28
class arena {
20
29
public:
21
- arena (char id)
22
- : allocation_semispace_id(id) { }
30
+ arena (char id, bool trigger_collection)
31
+ : allocation_semispace_id(id)
32
+ , trigger_collection(trigger_collection) { }
23
33
24
34
~arena () {
25
35
if (current_addr_ptr)
@@ -36,17 +46,17 @@ class arena {
36
46
37
47
// Returns the address of the first byte that belongs in the given arena.
38
48
// Returns nullptr if nothing has been allocated ever in that arena.
39
- char *arena_start_ptr () const { return current_addr_ptr; }
49
+ char *start_ptr () const { return current_addr_ptr; }
40
50
41
51
// Returns a pointer to a location holding the address of last allocated
42
52
// byte in the given arena plus 1.
43
53
// This address is nullptr if nothing has been allocated ever in that arena.
44
- char *arena_end_ptr () { return allocation_ptr; }
54
+ char *end_ptr () { return allocation_ptr; }
45
55
46
56
// Clears the current allocation space by setting its start back to its first
47
57
// block. It is used during garbage collection to effectively collect all of the
48
- // arena. Resets the tripwire.
49
- void arena_clear ();
58
+ // arena.
59
+ void arena_clear () { allocation_ptr = current_addr_ptr; }
50
60
51
61
// Resizes the last allocation.
52
62
// Returns the address of the byte following the last newly allocated byte.
@@ -67,6 +77,14 @@ class arena {
67
77
// It is used before garbage collection.
68
78
void arena_swap_and_clear ();
69
79
80
+ // Decide how much space to use in arena before setting the flag for a collection.
81
+ // If an arena is going to request collections, updating this at the end of a
82
+ // collection is mandatory.
83
+ void update_tripwire () {
84
+ size_t space = EXPAND_FACTOR * (allocation_ptr - current_addr_ptr);
85
+ tripwire = current_addr_ptr + ((space < MIN_SPACE) ? MIN_SPACE : space);
86
+ }
87
+
70
88
// Given two pointers to objects allocated in the same arena, return the number
71
89
// of bytes they are apart. Undefined behavior will result if the pointers
72
90
// don't belong to the same arena
@@ -92,20 +110,6 @@ class arena {
92
110
static char get_arena_semispace_id_of_object (void *ptr);
93
111
94
112
private:
95
- //
96
- // We update the number of 1MB blocks actually written to, only when we need this value,
97
- // or before a garbage collection rather than trying to determine when we write to a fresh block.
98
- //
99
- void update_num_blocks () const {
100
- //
101
- // Calculate how many 1M blocks of the current arena we used.
102
- //
103
- size_t num_used_blocks
104
- = (allocation_ptr - current_addr_ptr - 1 ) / BLOCK_SIZE + 1 ;
105
- if (num_used_blocks > num_blocks)
106
- num_blocks = num_used_blocks;
107
- }
108
-
109
113
void initialize_semispace ();
110
114
//
111
115
// Current semispace where allocations are being made.
@@ -114,16 +118,13 @@ class arena {
114
118
char *allocation_ptr
115
119
= nullptr ; // next available location in current semispace
116
120
char *tripwire = nullptr ; // allocating past this triggers slow allocation
117
- mutable size_t num_blocks
118
- = 0 ; // notional number of BLOCK_SIZE blocks in current semispace
119
121
char allocation_semispace_id; // id of current semispace
122
+ bool const trigger_collection; // request collections?
120
123
//
121
124
// Semispace where allocations will be made during and after garbage collect.
122
125
//
123
126
char *collection_addr_ptr
124
127
= nullptr ; // pointer to start of collection address space
125
- size_t num_collection_blocks
126
- = 0 ; // notional number of BLOCK_SIZE blocks in collection semispace
127
128
};
128
129
129
130
inline char arena::get_arena_semispace_id_of_object (void *ptr) {
@@ -139,10 +140,6 @@ inline char arena::get_arena_semispace_id_of_object(void *ptr) {
139
140
return *reinterpret_cast <char *>(end_address);
140
141
}
141
142
142
- // Macro to define a new arena with the given ID. Supports IDs ranging from 0 to
143
- // 127.
144
- #define REGISTER_ARENA (name, id ) thread_local arena name (id)
145
-
146
143
#ifdef __MACH__
147
144
//
148
145
// thread_local disabled for Apple
@@ -183,32 +180,12 @@ inline void *arena::kore_arena_alloc(size_t requested) {
183
180
return result;
184
181
}
185
182
186
- inline void arena::arena_clear () {
187
- //
188
- // We set the allocation pointer to the first available address.
189
- //
190
- allocation_ptr = arena_start_ptr ();
191
- //
192
- // If the number of blocks we've touched is >= threshold, we want to trigger
193
- // a garbage collection if we get within 1 block of the end of this area.
194
- // Otherwise we only want to generate a garbage collect if we allocate off the
195
- // end of this area.
196
- //
197
- tripwire = current_addr_ptr
198
- + (num_blocks - (num_blocks >= get_gc_threshold ())) * BLOCK_SIZE;
199
- }
200
-
201
183
inline void arena::arena_swap_and_clear () {
202
- update_num_blocks (); // so we save the correct number of touched blocks
203
184
std::swap (current_addr_ptr, collection_addr_ptr);
204
- std::swap (num_blocks, num_collection_blocks);
205
185
allocation_semispace_id = ~allocation_semispace_id;
206
- if (current_addr_ptr == nullptr ) {
207
- //
208
- // The other semispace hasn't be initialized yet.
209
- //
210
- initialize_semispace ();
211
- } else
186
+ if (current_addr_ptr == nullptr )
187
+ initialize_semispace (); // not yet initialized
188
+ else
212
189
arena_clear ();
213
190
}
214
191
}
0 commit comments