1 | /* Shared pool of memory blocks for pool allocators. |
2 | Copyright (C) 2015-2023 Free Software Foundation, Inc. |
3 | |
4 | This file is part of GCC. |
5 | |
6 | GCC is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 3, or (at your option) |
9 | any later version. |
10 | |
11 | GCC is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ |
19 | |
20 | |
21 | #ifndef MEMORY_BLOCK_H |
22 | #define MEMORY_BLOCK_H |
23 | |
24 | /* Shared pool which allows other memory pools to reuse each others' allocated |
25 | memory blocks instead of calling free/malloc again. */ |
26 | class memory_block_pool |
27 | { |
28 | public: |
29 | /* Blocks have fixed size. This is necessary for sharing. */ |
30 | static const size_t block_size = 64 * 1024; |
31 | /* Number of blocks we keep in the freelists. */ |
32 | static const size_t freelist_size = 1024 * 1024 / block_size; |
33 | |
34 | memory_block_pool (); |
35 | |
36 | static inline void *allocate () ATTRIBUTE_MALLOC; |
37 | static inline void release (void *); |
38 | static void trim (int nblocks = freelist_size); |
39 | void reduce_free_list (int); |
40 | |
41 | private: |
42 | /* memory_block_pool singleton instance, defined in memory-block.cc. */ |
43 | static memory_block_pool instance; |
44 | |
45 | struct block_list |
46 | { |
47 | block_list *m_next; |
48 | }; |
49 | |
50 | /* Free list. */ |
51 | block_list *m_blocks; |
52 | }; |
53 | |
54 | /* Allocate a single block. Reuse a previously returned block, if possible. */ |
55 | inline void * |
56 | memory_block_pool::allocate () |
57 | { |
58 | if (instance.m_blocks == NULL) |
59 | return XNEWVEC (char, block_size); |
60 | |
61 | void *result = instance.m_blocks; |
62 | instance.m_blocks = instance.m_blocks->m_next; |
63 | VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (result, block_size)); |
64 | return result; |
65 | } |
66 | |
67 | /* Return UNCAST_BLOCK to the pool. */ |
68 | inline void |
69 | memory_block_pool::release (void *uncast_block) |
70 | { |
71 | block_list *block = new (uncast_block) block_list; |
72 | block->m_next = instance.m_blocks; |
73 | instance.m_blocks = block; |
74 | |
75 | VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *)uncast_block |
76 | + sizeof (block_list), |
77 | block_size |
78 | - sizeof (block_list))); |
79 | } |
80 | |
81 | extern void *mempool_obstack_chunk_alloc (size_t) ATTRIBUTE_MALLOC; |
82 | extern void mempool_obstack_chunk_free (void *); |
83 | |
84 | #endif /* MEMORY_BLOCK_H */ |
85 | |