28#define POLAR_SIZE_RUNTIME_MEMORY_POOL_PAGE ( OBJC_SIZEOF_POINTER << 12 )
29#define POLAR_COUNT_RUNTIME_MEMORY_TUNE_MISSES_START 1
30#define POLAR_COUNT_BUCKETS_TABLE_STRINGS_INTERNED 4
38 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
39 assert( idx_idle_list > 0 );
40 assert( idx_idle_list <= POLAR_LENGTH_ARRAY_MEMBLOCK_IDLE );
42 result = self->array_idle_blocks[idx_idle_list].block_last;
45 self->array_idle_blocks[idx_idle_list].block_last = *( (
void **)result );
46 *( (
void **)result ) = NULL;
48 #ifdef POLAR_DEBUG_RUNTIME_MEMORY
49 self->array_idle_blocks[idx_idle_list].count_blocks_idle--;
61 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
62 assert( idx_idle_list > 0 );
63 assert( idx_idle_list <= POLAR_LENGTH_ARRAY_MEMBLOCK_IDLE );
64 assert( block_new != NULL );
65 assert( *((
void **)block_new) == NULL );
67 *( (
void **)block_new ) = self->array_idle_blocks[idx_idle_list].block_last;
68 self->array_idle_blocks[idx_idle_list].block_last = block_new;
70#ifdef POLAR_DEBUG_RUNTIME_MEMORY
71 self->array_idle_blocks[idx_idle_list].count_blocks_idle++;
76POLAR_FUNCTION_INTERNAL uintptr_t
81 void *block_current, *block_next;
83 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
84 assert( idx_idle_list > 0 );
85 assert( idx_idle_list <= POLAR_LENGTH_ARRAY_MEMBLOCK_IDLE );
86 assert( block_first != NULL );
91 block_next = block_first;
95 block_current = block_next;
98 block_next = *( (
void **)block_current );
99 }
while( block_next != NULL );
102 *( (
void **)block_current ) = self->array_idle_blocks[idx_idle_list].block_last;
103 self->array_idle_blocks[idx_idle_list].block_last = block_first;
105#ifdef POLAR_DEBUG_RUNTIME_MEMORY
106 self->array_idle_blocks[idx_idle_list].count_blocks_idle += result;
113POLAR_FUNCTION_INTERNAL
void
117 uintptr_t count_blocks_returned;
119 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
120 assert( array_idle_blocks != NULL );
122 for( i = 1; i <= POLAR_LENGTH_ARRAY_MEMBLOCK_IDLE; i++ )
124 if( array_idle_blocks[i] != NULL )
127 count_blocks_returned = polar_runtime_memory_pool_block_idle_push_list( self, i, array_idle_blocks[i] );
130 objc_atomic_subtract_uintptr( &self->array_idle_blocks[i].count_misses, count_blocks_returned );
137POLAR_FUNCTION_INTERNAL
void
142 uintptr_t count_misses_max, count_misses_current;
143 size_t size_block, size_chain;
144 char *block_first, *block_last, *block_current;
146 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
148 superclass = POLAR_MEMORY_POOL_CLASS(superclass_polar_runtime_memory_pool);
149 count_misses_max = POLAR_COUNT_RUNTIME_MEMORY_TUNE_MISSES_START;
155 for( i = POLAR_LENGTH_ARRAY_MEMBLOCK_IDLE; i > 0; i-- )
157 count_misses_current = objc_atomic_exchange_uintptr( &self->array_idle_blocks[i].count_misses, 0 );
159 if( count_misses_current >= count_misses_max )
162 count_misses_current = MAX(count_misses_current >> 1, 1);
164 if( count_misses_current > 1 )
170 size_block = ( i << X2_SIZE_SHIFT_POINTER );
171 size_chain = ( size_block * count_misses_current );
174 block_first = (
char *)
175 superclass->allocate_elements( (
polar_memory_pool *)self, (i << 1) * count_misses_current );
178 block_last = ( (block_first + size_chain) - size_block );
179 block_current = block_first;
181 while( block_current != block_last )
184 *( (
void **)block_current ) = ( block_current + size_block );
185 block_current += size_block;
190 *( (
void **)block_last ) = self->array_idle_blocks[i].block_last;
191 self->array_idle_blocks[i].block_last = block_first;
193 #ifdef POLAR_DEBUG_RUNTIME_MEMORY
194 self->array_idle_blocks[i].count_blocks_idle += count_misses_current;
195 self->array_idle_blocks[i].count_blocks_allocated += count_misses_current;
204 block_current = (
char *)superclass->allocate_elements( (
polar_memory_pool *)self, i << 1 );
205 polar_runtime_memory_pool_block_idle_push(self, i, block_current);
215 if( (i & (i - 1)) == 0 )
216 count_misses_max <<= 1;
225 size_t size_array_idle_blocks;
229 POLAR_RUNTIME_OBJECT_CLASS(superclass_polar_runtime_memory_pool)->init( (
polar_runtime_object *)self );
242 self->data_inherited.size_pool_elements = OBJC_SIZEOF_POINTER;
253 self->array_idle_blocks = &self->array_idle_blocks[-1];
262 if( self->array_idle_blocks != NULL )
265 objc_memzero( &self->pool_lock,
sizeof(self->pool_lock) );
267 self->array_idle_blocks = NULL;
271 return POLAR_RUNTIME_OBJECT_CLASS(superclass_polar_runtime_memory_pool)->finalize( (
polar_runtime_object *)self );
274POLAR_FUNCTION_INTERNAL OBJC_FUNCTION_HOTSPOT
void *
279 intptr_t idx_idle_list, i;
280 char *block_remainder;
282 assert( count_elements > 0 );
284 superclass = POLAR_MEMORY_POOL_CLASS(superclass_polar_runtime_memory_pool);
286 if( count_elements <= POLAR_LENGTH_RUNTIME_STRUCT_MAX )
292 result = superclass->allocate_elements( (
polar_memory_pool *)self, count_elements );
299 idx_idle_list = ( count_elements >> 1 );
303 result = polar_runtime_memory_pool_block_idle_pop(self, idx_idle_list);
313 self->array_idle_blocks[idx_idle_list].count_misses++;
316 if( idx_idle_list < POLAR_LENGTH_ARRAY_MEMBLOCK_IDLE )
318 for( i = idx_idle_list + 1; i <= POLAR_LENGTH_ARRAY_MEMBLOCK_IDLE; i++ )
320 result = polar_runtime_memory_pool_block_idle_pop(self, i);
325 block_remainder = ( (
char *)result + (count_elements << OBJC_SIZE_SHIFT_POINTER) );
326 polar_runtime_memory_pool_block_idle_push(self, i - idx_idle_list, block_remainder);
337 result = superclass->allocate_elements( (
polar_memory_pool *)self, count_elements );
339#ifdef POLAR_DEBUG_RUNTIME_MEMORY
340 self->array_blocks_idle[idx_idle_list].count_blocks_allocated++;
356POLAR_FUNCTION_INTERNAL
void
358 size_t count_bytes_remaining )
360 size_t size_block_current;
361 intptr_t idx_idle_list;
363 while( count_bytes_remaining >= X2_SIZEOF_POINTER )
365 size_block_current = MIN(count_bytes_remaining, POLAR_SIZE_RUNTIME_STRUCT_MAX);
367 idx_idle_list = ( size_block_current >> X2_SIZE_SHIFT_POINTER );
368 size_block_current = ( idx_idle_list << X2_SIZE_SHIFT_POINTER );
370 polar_runtime_memory_pool_block_idle_push(self, idx_idle_list, byte_next);
371 byte_next += size_block_current;
372 count_bytes_remaining -= size_block_current;
374 #ifdef POLAR_DEBUG_RUNTIME_MEMORY
375 self->count_bytes_salvage += size_block_current;
380POLAR_FUNCTION_INTERNAL
void
384 superclass_polar_runtime_memory_pool = POLAR_RUNTIME_OBJECT_CLASS(self)->class_superclass;
390 (polar_func_runtime_object_lifecycle)_polar_runtime_memory_pool_finalize;
398 .name_type =
"polar_runtime_memory_pool",
401 .type_class_init = (polar_func_runtime_object_class_lifecycle)_polar_runtime_memory_pool_class_init
406POLAR_FUNCTION_INTERNAL OBJC_FUNCTION_CONSTANT polar_internal_type
407polar_runtime_memory_pool_get_type(
void )
409 static polar_internal_type pt_polar_runtime_memory_pool = POLAR_INTERNAL_TYPE_INVALID;
411 if( pt_polar_runtime_memory_pool != POLAR_INTERNAL_TYPE_INVALID )
412 return pt_polar_runtime_memory_pool;
414 pt_polar_runtime_memory_pool = polar_internal_type_init( POLAR_TYPE_MEMORY_POOL, &class_polar_runtime_memory_pool,
415 &pti_polar_runtime_memory_pool );
417 return pt_polar_runtime_memory_pool;
420POLAR_FUNCTION_INTERNAL
void
422 void *array_elements )
424 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
425 assert( count_elements <= POLAR_LENGTH_RUNTIME_STRUCT_MAX );
426 assert( count_elements & 1 == 0 );
428 if( (count_elements > 0) && (array_elements != NULL) )
431 objc_memzero(array_elements, count_elements << OBJC_SIZE_SHIFT_POINTER);
434 polar_runtime_memory_pool_block_idle_push(self, (count_elements >> 1), array_elements);
439POLAR_FUNCTION_INTERNAL
void *
441 size_t size_struct_source )
444 size_t length_struct_source;
446 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
447 assert( size_struct_source > 0 );
449 length_struct_source = POLAR_LENGTH_STRUCT_IN_POINTERS(size_struct_source);
450 result = polar_memory_pool_allocate_elements( (
polar_memory_pool *)self, length_struct_source );
452 if( p_struct_source != NULL )
453 return objc_memcpy(result, p_struct_source, size_struct_source);
458POLAR_FUNCTION_INTERNAL
const char *
460 intptr_t len_string_source )
464 size_t len_string, len_string_in_pointers;
466 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
468 if( (p_string_source != NULL) && (*p_string_source != 0) && (len_string_source != 0) )
474 if( len_string_source > 0 )
475 len_string = objc_strnlen(p_string_source, (
size_t)len_string_source);
478 len_string = objc_strlen(p_string_source);
482 if( self->table_strings_interned != NULL )
485 polar_hash_table_get_node(self->table_strings_interned, (
void *)p_string_source);
487 if( node_string_interned != NULL )
489 result = (
char *)polar_hash_table_node_string_key_get_key(node_string_interned);
492 return (
const char *)result;
498 self->table_strings_interned = polar_hash_table_new( POLAR_COUNT_BUCKETS_TABLE_STRINGS_INTERNED,
499 POLAR_TYPE_HASH_TABLE_NODE_STRING_KEY );
502 len_string_in_pointers = POLAR_LENGTH_STRUCT_IN_POINTERS(len_string + 1);
507 result = (
char *)polar_memory_pool_allocate_elements( (
polar_memory_pool *)self, len_string_in_pointers );
509 objc_memcpy(result, (
void *)p_string_source, len_string);
510 polar_hash_table_add_node(self->table_strings_interned, result);
513 return (
const char *)result;
516POLAR_FUNCTION_INTERNAL
void
518 size_t size_struct_source )
520 assert( POLAR_IS_RUNTIME_MEMORY_POOL(self) );
522 if( (size_struct_source >= X2_SIZEOF_POINTER) && (p_struct_source != NULL) )
525 objc_memzero(p_struct_source, size_struct_source);
528 polar_memory_pool_memory_salvage( (
polar_memory_pool *)self, (
char *)p_struct_source, size_struct_source );
Definition polar-hash-table-node-string-key.h:25
Definition polar-internal-type.h:34
Definition polar-runtime-memory-pool.h:35
Definition polar-memory-pool.h:31
Definition polar-memory-pool-page.h:24
Definition polar-memory-pool.h:24
Definition polar-runtime-memory-pool.h:58
Definition polar-runtime-memory-pool.h:46
Definition polar-runtime-object.h:36
Definition polar-runtime-object.h:31