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_free_unused_memory (JMEM_PRESSURE_LOW); 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