1/* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16/**
17 * Memory pool manager implementation
18 */
19
20#include "jcontext.h"
21#include "jmem.h"
22#include "jrt-libc-includes.h"
23
24#define JMEM_ALLOCATOR_INTERNAL
25#include "jmem-allocator-internal.h"
26
27#if ENABLED (JERRY_MEM_GC_BEFORE_EACH_ALLOC)
28#include "ecma-gc.h"
29#endif /* ENABLED (JERRY_MEM_GC_BEFORE_EACH_ALLOC) */
30
31/** \addtogroup mem Memory allocation
32 * @{
33 *
34 * \addtogroup poolman Memory pool manager
35 * @{
36 */
37
38/**
39 * Finalize pool manager
40 */
41void
42jmem_pools_finalize (void)
43{
44 jmem_pools_collect_empty ();
45
46 JERRY_ASSERT (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) == NULL);
47#if ENABLED (JERRY_CPOINTER_32_BIT)
48 JERRY_ASSERT (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) == NULL);
49#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
50} /* jmem_pools_finalize */
51
52/**
53 * Allocate a chunk of specified size
54 *
55 * @return pointer to allocated chunk, if allocation was successful,
56 * or NULL - if not enough memory.
57 */
58extern inline void * JERRY_ATTR_HOT JERRY_ATTR_ALWAYS_INLINE
59jmem_pools_alloc (size_t size) /**< size of the chunk */
60{
61#if ENABLED (JERRY_MEM_GC_BEFORE_EACH_ALLOC)
62 ecma_gc_run ();
63#endif /* ENABLED (JERRY_MEM_GC_BEFORE_EACH_ALLOC) */
64
65#if ENABLED (JERRY_CPOINTER_32_BIT)
66 if (size <= 8)
67 {
68#else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
69 JERRY_ASSERT (size <= 8);
70#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
71
72 if (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) != NULL)
73 {
74 const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p);
75
76 JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
77 JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_p->next_p;
78 JMEM_VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
79
80 JMEM_HEAP_STAT_ALLOC (8);
81 return (void *) chunk_p;
82 }
83 else
84 {
85 void *chunk_p = jmem_heap_alloc_block_internal (8);
86 JMEM_HEAP_STAT_ALLOC (8);
87 return chunk_p;
88 }
89
90#if ENABLED (JERRY_CPOINTER_32_BIT)
91 }
92
93 JERRY_ASSERT (size <= 16);
94
95 if (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) != NULL)
96 {
97 const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p);
98
99 JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
100 JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_p->next_p;
101 JMEM_VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
102
103 JMEM_HEAP_STAT_ALLOC (16);
104 return (void *) chunk_p;
105 }
106 else
107 {
108 void *chunk_p = jmem_heap_alloc_block_internal (16);
109 JMEM_HEAP_STAT_ALLOC (16);
110 return chunk_p;
111 }
112#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
113} /* jmem_pools_alloc */
114
115/**
116 * Free the chunk
117 */
118extern inline void JERRY_ATTR_HOT JERRY_ATTR_ALWAYS_INLINE
119jmem_pools_free (void *chunk_p, /**< pointer to the chunk */
120 size_t size) /**< size of the chunk */
121{
122 JERRY_ASSERT (chunk_p != NULL);
123 JMEM_HEAP_STAT_FREE (size);
124
125 jmem_pools_chunk_t *const chunk_to_free_p = (jmem_pools_chunk_t *) chunk_p;
126
127 JMEM_VALGRIND_DEFINED_SPACE (chunk_to_free_p, size);
128
129#if ENABLED (JERRY_CPOINTER_32_BIT)
130 if (size <= 8)
131 {
132#else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
133 JERRY_ASSERT (size <= 8);
134#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
135
136 chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p);
137 JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_to_free_p;
138
139#if ENABLED (JERRY_CPOINTER_32_BIT)
140 }
141 else
142 {
143 JERRY_ASSERT (size <= 16);
144
145 chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p);
146 JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_to_free_p;
147 }
148#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
149
150 JMEM_VALGRIND_NOACCESS_SPACE (chunk_to_free_p, size);
151} /* jmem_pools_free */
152
153/**
154 * Collect empty pool chunks
155 */
156void
157jmem_pools_collect_empty (void)
158{
159 jmem_pools_chunk_t *chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p);
160 JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = NULL;
161
162 while (chunk_p)
163 {
164 JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
165 jmem_pools_chunk_t *const next_p = chunk_p->next_p;
166 JMEM_VALGRIND_NOACCESS_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
167
168 jmem_heap_free_block_internal (chunk_p, 8);
169 chunk_p = next_p;
170 }
171
172#if ENABLED (JERRY_CPOINTER_32_BIT)
173 chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p);
174 JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = NULL;
175
176 while (chunk_p)
177 {
178 JMEM_VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
179 jmem_pools_chunk_t *const next_p = chunk_p->next_p;
180 JMEM_VALGRIND_NOACCESS_SPACE (chunk_p, sizeof (jmem_pools_chunk_t));
181
182 jmem_heap_free_block_internal (chunk_p, 16);
183 chunk_p = next_p;
184 }
185#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
186} /* jmem_pools_collect_empty */
187
188/**
189 * @}
190 * @}
191 */
192