@@ -164,6 +164,11 @@ npy_string_arena_malloc(npy_string_arena *arena, npy_string_realloc_func r,
164
164
int
165
165
npy_string_arena_free (npy_string_arena * arena , _npy_static_string_u * str )
166
166
{
167
+ if (arena -> size == 0 && arena -> cursor == 0 && arena -> buffer == NULL ) {
168
+ // empty arena, nothing to do
169
+ return 0 ;
170
+ }
171
+
167
172
char * ptr = vstring_buffer (arena , str );
168
173
if (ptr == NULL ) {
169
174
return -1 ;
@@ -195,7 +200,7 @@ npy_string_new_allocator(npy_string_malloc_func m, npy_string_free_func f,
195
200
allocator -> malloc = m ;
196
201
allocator -> free = f ;
197
202
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
199
204
allocator -> arena = NEW_ARENA ;
200
205
return allocator ;
201
206
}
@@ -295,17 +300,24 @@ heap_or_arena_allocate(npy_string_allocator *allocator,
295
300
_npy_static_string_u * to_init_u , size_t size ,
296
301
int * on_heap )
297
302
{
298
- // check if it's a previously heap-allocated string or a short string
299
- // that has no heap allocation
300
303
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
+ }
301
317
if (* flags & NPY_STRING_ARENA_FREED ) {
302
318
// Check if there's room for the new string in the existing
303
319
// allocation. The size is stored one size_t "behind" the beginning of
304
320
// the allocation.
305
- npy_string_arena * arena = & allocator -> arena ;
306
- if (arena == NULL ) {
307
- return NULL ;
308
- }
309
321
char * buf = vstring_buffer (arena , to_init_u );
310
322
if (buf == NULL ) {
311
323
return NULL ;
@@ -326,29 +338,13 @@ heap_or_arena_allocate(npy_string_allocator *allocator,
326
338
return buf ;
327
339
}
328
340
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 ;
333
343
* on_heap = 1 ;
334
344
return allocator -> malloc (sizeof (char ) * size );
335
345
}
336
346
}
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
- }
347
347
// 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
- }
352
348
char * ret = npy_string_arena_malloc (arena , allocator -> realloc ,
353
349
sizeof (char ) * size );
354
350
if (size < NPY_MEDIUM_STRING_MAX_SIZE ) {
@@ -382,7 +378,9 @@ heap_or_arena_deallocate(npy_string_allocator *allocator,
382
378
if (npy_string_arena_free (arena , str_u ) < 0 ) {
383
379
return -1 ;
384
380
}
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
+ }
386
384
}
387
385
return 0 ;
388
386
}
0 commit comments