@@ -164,6 +164,11 @@ npy_string_arena_malloc(npy_string_arena *arena, npy_string_realloc_func r,
164164int
165165npy_string_arena_free (npy_string_arena * arena , _npy_static_string_u * str )
166166{
167+ if (arena -> size == 0 && arena -> cursor == 0 && arena -> buffer == NULL ) {
168+ // empty arena, nothing to do
169+ return 0 ;
170+ }
171+
167172 char * ptr = vstring_buffer (arena , str );
168173 if (ptr == NULL ) {
169174 return -1 ;
@@ -195,7 +200,7 @@ npy_string_new_allocator(npy_string_malloc_func m, npy_string_free_func f,
195200 allocator -> malloc = m ;
196201 allocator -> free = f ;
197202 allocator -> realloc = r ;
198- // arenas don't get created until the dtype is used for array creation
203+ // arena buffer gets allocated in npy_string_arena_malloc
199204 allocator -> arena = NEW_ARENA ;
200205 return allocator ;
201206}
@@ -295,17 +300,24 @@ heap_or_arena_allocate(npy_string_allocator *allocator,
295300 _npy_static_string_u * to_init_u , size_t size ,
296301 int * on_heap )
297302{
298- // check if it's a previously heap-allocated string or a short string
299- // that has no heap allocation
300303 unsigned char * flags = & to_init_u -> direct_buffer .flags_and_size ;
304+ if (* flags & NPY_STRING_SHORT ) {
305+ // Have to heap allocate since there isn't a preexisting
306+ // allocation. This leaves the NPY_STRING_SHORT flag set to indicate
307+ // that there is no room in the arena buffer for strings in this
308+ // entry
309+ * flags |= NPY_STRING_ON_HEAP ;
310+ * on_heap = 1 ;
311+ return allocator -> malloc (sizeof (char ) * size );
312+ }
313+ npy_string_arena * arena = & allocator -> arena ;
314+ if (arena == NULL ) {
315+ return NULL ;
316+ }
301317 if (* flags & NPY_STRING_ARENA_FREED ) {
302318 // Check if there's room for the new string in the existing
303319 // allocation. The size is stored one size_t "behind" the beginning of
304320 // the allocation.
305- npy_string_arena * arena = & allocator -> arena ;
306- if (arena == NULL ) {
307- return NULL ;
308- }
309321 char * buf = vstring_buffer (arena , to_init_u );
310322 if (buf == NULL ) {
311323 return NULL ;
@@ -326,29 +338,13 @@ heap_or_arena_allocate(npy_string_allocator *allocator,
326338 return buf ;
327339 }
328340 else {
329- // No room, resort to a heap allocation. This leaves the
330- // NPY_STRING_ARENA_FREED flag set to possibly re-use the arena
331- // allocation in the future if there is room for it
332- * flags |= NPY_STRING_ON_HEAP ;
341+ // No room, resort to a heap allocation.
342+ * flags = NPY_STRING_ON_HEAP ;
333343 * on_heap = 1 ;
334344 return allocator -> malloc (sizeof (char ) * size );
335345 }
336346 }
337- else if (* flags & NPY_STRING_SHORT ) {
338- // Have to heap allocate since there isn't a preexisting
339- // allocation. This leaves the NPY_STRING_SHORT flag set to indicate
340- // that there is no room in the arena buffer for strings in this
341- // entry, avoiding possible reallocation of the entire arena buffer
342- // when writing to a single string
343- * flags |= NPY_STRING_ON_HEAP ;
344- * on_heap = 1 ;
345- return allocator -> malloc (sizeof (char ) * size );
346- }
347347 // string isn't previously allocated, so add to existing arena allocation
348- npy_string_arena * arena = & allocator -> arena ;
349- if (arena == NULL ) {
350- return NULL ;
351- }
352348 char * ret = npy_string_arena_malloc (arena , allocator -> realloc ,
353349 sizeof (char ) * size );
354350 if (size < NPY_MEDIUM_STRING_MAX_SIZE ) {
@@ -382,7 +378,9 @@ heap_or_arena_deallocate(npy_string_allocator *allocator,
382378 if (npy_string_arena_free (arena , str_u ) < 0 ) {
383379 return -1 ;
384380 }
385- str_u -> direct_buffer .flags_and_size |= NPY_STRING_ARENA_FREED ;
381+ if (arena -> buffer != NULL ) {
382+ str_u -> direct_buffer .flags_and_size |= NPY_STRING_ARENA_FREED ;
383+ }
386384 }
387385 return 0 ;
388386}
0 commit comments