@@ -10,27 +10,100 @@ extern "C" {
10
10
11
11
// An arena can be used to allocate objects that can then be deallocated all at
12
12
// once.
13
- struct arena {
14
- char * first_block ;
15
- char * block ;
16
- char * block_start ;
17
- char * block_end ;
18
- char * first_collection_block ;
19
- size_t num_blocks ;
20
- size_t num_collection_blocks ;
21
- char allocation_semispace_id ;
22
- };
23
-
24
- using memory_block_header = struct {
25
- char * next_block ;
26
- char * next_superblock ;
27
- char semispace ;
13
+ class arena {
14
+ public:
15
+ arena (char id)
16
+ : allocation_semispace_id(id) { }
17
+
18
+ // Allocates the requested number of bytes as a contiguous region and returns a
19
+ // pointer to the first allocated byte.
20
+ // If called with requested size greater than the maximun single allocation
21
+ // size, the space is allocated in a general (not garbage collected pool).
22
+ void *kore_arena_alloc (size_t requested);
23
+
24
+ // Returns the address of the first byte that belongs in the given arena.
25
+ // Returns 0 if nothing has been allocated ever in that arena.
26
+ char *arena_start_ptr () const ;
27
+
28
+ // Returns a pointer to a location holding the address of last allocated
29
+ // byte in the given arena plus 1.
30
+ // This address is 0 if nothing has been allocated ever in that arena.
31
+ char **arena_end_ptr ();
32
+
33
+ // return the total number of allocatable bytes currently in the arena in its
34
+ // active semispace.
35
+ size_t arena_size () const ;
36
+
37
+ // Clears the current allocation space by setting its start back to its first
38
+ // block. It is used during garbage collection to effectively collect all of the
39
+ // arena.
40
+ void arena_clear ();
41
+
42
+ // Resizes the last allocation as long as the resize does not require a new
43
+ // block allocation.
44
+ // Returns the address of the byte following the last newlly allocated byte when
45
+ // the resize succeeds, returns 0 otherwise.
46
+ void *arena_resize_last_alloc (ssize_t increase);
47
+
48
+ // Returns the given arena's current collection semispace ID.
49
+ // Each arena has 2 semispace IDs one equal to the arena ID and the other equal
50
+ // to the 1's complement of the arena ID. At any time one of these semispaces
51
+ // is used for allocation and the other is used for collection.
52
+ char get_arena_collection_semispace_id () const ;
53
+
54
+ // Exchanges the current allocation and collection semispaces and clears the new
55
+ // current allocation semispace by setting its start back to its first block.
56
+ // It is used before garbage collection.
57
+ void arena_swap_and_clear ();
58
+
59
+ // Given two pointers to objects allocated in the same arena, return the number
60
+ // of bytes they are separated by within the virtual block of memory represented
61
+ // by the blocks of that arena. This difference will include blocks containing
62
+ // sentinel bytes. Undefined behavior will result if the pointers belong to
63
+ // different arenas.
64
+ static ssize_t ptr_diff (char *ptr1, char *ptr2);
65
+
66
+ // Given a starting pointer to an address allocated in an arena and a size in
67
+ // bytes, this function returns a pointer to an address allocated in the
68
+ // same arena after size bytes from the starting pointer.
69
+ //
70
+ // 1st argument: the starting pointer
71
+ // 2nd argument: the size in bytes to add to the starting pointer
72
+ // 3rd argument: the address of last allocated byte in the arena plus 1
73
+ // Return value: the address allocated in the arena after size bytes from the
74
+ // starting pointer, or 0 if this is equal to the 3rd argument.
75
+ static char *move_ptr (char *ptr, size_t size, char const *arena_end_ptr);
76
+
77
+ // Returns the ID of the semispace where the given address was allocated.
78
+ // The behavior is undefined if called with an address that has not been
79
+ // allocated within an arena.
80
+ static char get_arena_semispace_id_of_object (void *ptr);
81
+
82
+ private:
83
+ struct memory_block_header {
84
+ char *next_block;
85
+ char semispace;
86
+ };
87
+
88
+ void fresh_block ();
89
+ static memory_block_header *mem_block_header (void *ptr);
90
+
91
+ // helper function for `kore_arena_alloc`. Do not call directly.
92
+ void *do_alloc_slow (size_t requested);
93
+
94
+ char *first_block; // beginning of first block
95
+ char *block; // where allocations are being made in current block
96
+ char *block_start; // start of current block
97
+ char *block_end; // 1 past end of current block
98
+ char *first_collection_block; // beginning of other semispace
99
+ size_t num_blocks; // number of blocks in current semispace
100
+ size_t num_collection_blocks; // number of blocks in other semispace
101
+ char allocation_semispace_id; // id of current semispace
28
102
};
29
103
30
104
// Macro to define a new arena with the given ID. Supports IDs ranging from 0 to
31
105
// 127.
32
- #define REGISTER_ARENA (name , id ) \
33
- static thread_local struct arena name = {.allocation_semispace_id = (id)}
106
+ #define REGISTER_ARENA (name, id ) static thread_local arena name (id)
34
107
35
108
#define MEM_BLOCK_START (ptr ) \
36
109
((char *)(((uintptr_t )(ptr)-1 ) & ~(BLOCK_SIZE - 1 )))
@@ -46,92 +119,17 @@ extern thread_local bool time_for_collection;
46
119
47
120
size_t get_gc_threshold ();
48
121
49
- // Resets the given arena.
50
- void arena_reset (struct arena * );
51
-
52
- // Returns the given arena's current allocation semispace ID.
53
- // Each arena has 2 semispace IDs one equal to the arena ID and the other equal
54
- // to the 1's complement of the arena ID. At any time one of these semispaces
55
- // is used for allocation and the other is used for collection.
56
- char get_arena_allocation_semispace_id (const struct arena * );
57
-
58
- // Returns the given arena's current collection semispace ID.
59
- // See above for details.
60
- char get_arena_collection_semispace_id (const struct arena * );
61
-
62
- // Returns the ID of the semispace where the given address was allocated.
63
- // The behavior is undefined if called with an address that has not been
64
- // allocated within an arena.
65
- char get_arena_semispace_id_of_object (void * );
66
-
67
- // helper function for `kore_arena_alloc`. Do not call directly.
68
- void * do_alloc_slow (size_t , struct arena * );
69
-
70
- // Allocates the requested number of bytes as a contiguous region and returns a
71
- // pointer to the first allocated byte.
72
- // If called with requested size greater than the maximun single allocation
73
- // size, the space is allocated in a general (not garbage collected pool).
74
- inline void * kore_arena_alloc (struct arena * arena , size_t requested ) {
75
- if (arena -> block + requested > arena -> block_end ) {
76
- return do_alloc_slow (requested , arena );
122
+ inline void *arena::kore_arena_alloc (size_t requested) {
123
+ if (block + requested > block_end) {
124
+ return do_alloc_slow (requested);
77
125
}
78
- void * result = arena -> block ;
79
- arena -> block += requested ;
126
+ void *result = block;
127
+ block += requested;
80
128
MEM_LOG (
81
129
" Allocation at %p (size %zd), next alloc at %p (if it fits)\n " , result,
82
- requested , arena -> block );
130
+ requested, block);
83
131
return result;
84
132
}
85
-
86
- // Resizes the last allocation as long as the resize does not require a new
87
- // block allocation.
88
- // Returns the address of the byte following the last newlly allocated byte when
89
- // the resize succeeds, returns 0 otherwise.
90
- void * arena_resize_last_alloc (struct arena * , ssize_t );
91
-
92
- // Exchanges the current allocation and collection semispaces and clears the new
93
- // current allocation semispace by setting its start back to its first block.
94
- // It is used before garbage collection.
95
- void arena_swap_and_clear (struct arena * );
96
-
97
- // Clears the current allocation space by setting its start back to its first
98
- // block. It is used during garbage collection to effectively collect all of the
99
- // arena.
100
- void arena_clear (struct arena * );
101
-
102
- // Returns the address of the first byte that belongs in the given arena.
103
- // Returns 0 if nothing has been allocated ever in that arena.
104
- char * arena_start_ptr (const struct arena * );
105
-
106
- // Returns a pointer to a location holding the address of last allocated
107
- // byte in the given arena plus 1.
108
- // This address is 0 if nothing has been allocated ever in that arena.
109
- char * * arena_end_ptr (struct arena * );
110
-
111
- // Given a starting pointer to an address allocated in an arena and a size in
112
- // bytes, this function returns a pointer to an address allocated in the
113
- // same arena after size bytes from the starting pointer.
114
- //
115
- // 1st argument: the starting pointer
116
- // 2nd argument: the size in bytes to add to the starting pointer
117
- // 3rd argument: the address of last allocated byte in the arena plus 1
118
- // Return value: the address allocated in the arena after size bytes from the
119
- // starting pointer, or 0 if this is equal to the 3rd argument.
120
- char * move_ptr (char * , size_t , char const * );
121
-
122
- // Given two pointers to objects allocated in the same arena, return the number
123
- // of bytes they are separated by within the virtual block of memory represented
124
- // by the blocks of that arena. This difference will include blocks containing
125
- // sentinel bytes. Undefined behavior will result if the pointers belong to
126
- // different arenas.
127
- ssize_t ptr_diff (char * , char * );
128
-
129
- // return the total number of allocatable bytes currently in the arena in its
130
- // active semispace.
131
- size_t arena_size (const struct arena * );
132
-
133
- // Deallocates all the memory allocated for registered arenas.
134
- void free_all_memory (void );
135
133
}
136
134
137
135
#endif // ARENA_H
0 commit comments