From b9d93e5a2054b77651272d9b9e7813131c0856ff Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Fri, 6 Mar 2026 21:45:28 +0000 Subject: [PATCH 1/4] [std] Restore carray_get/length for 1.13 compat --- src/std/array.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/std/array.c b/src/std/array.c index 317480e51..4e447e0ae 100644 --- a/src/std/array.c +++ b/src/std/array.c @@ -54,6 +54,11 @@ DEFINE_PRIM(_VOID,array_blit,_ARR _I32 _ARR _I32 _I32); DEFINE_PRIM(_TYPE,array_type,_ARR); DEFINE_PRIM(_BYTES,array_bytes,_ARR); +typedef struct { + size_t size; + hl_type* type; +} hl_carray_header; + HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) { if( at->kind != HOBJ && at->kind != HSTRUCT ) hl_error("Invalid array type"); @@ -62,7 +67,10 @@ HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) { hl_runtime_obj *rt = at->obj->rt; if( rt == NULL || rt->methods == NULL ) rt = hl_get_obj_proto(at); - char *arr = hl_gc_alloc_gen(at, size * rt->size, (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); + void *ptr = hl_gc_alloc_gen(at, sizeof(hl_carray_header) + size * rt->size, (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); + ((hl_carray_header*)ptr)->size = size; + ((hl_carray_header*)ptr)->type = at; + char *arr = (char*)ptr + sizeof(hl_carray_header); if( at->kind == HOBJ || rt->nbindings ) { int i,k; for(k=0;ksize; +} + +HL_PRIM vdynamic *hl_carray_get( void *arr, int pos ) { + if (!hl_is_gc_ptr((char*)arr - sizeof(hl_carray_header))) { + hl_error("Cannot call hl_carray_get with external carray"); + } + hl_carray_header* header = (hl_carray_header*)((char*)arr - sizeof(hl_carray_header)); + if (pos < 0 || pos >= header->size) return NULL; + hl_type* type = header->type; + void* element = (void*)((char*)arr + pos * type->obj->rt->size); + if (type->kind == HSTRUCT) { + vdynamic* dyn = hl_alloc_dynamic(type); + dyn->v.ptr = element; + return dyn; + } + return (vdynamic*)element; +} + +DEFINE_PRIM(_DYN,carray_get,_CARRAY _I32); +DEFINE_PRIM(_I32,carray_length,_CARRAY); From ffafdab80fb62ae6e37a292ebbd115bbd50b81ae Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Tue, 10 Mar 2026 12:38:34 +0000 Subject: [PATCH 2/4] Add HL_DISABLE_COMPAT to remove compat primitives --- src/std/array.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/std/array.c b/src/std/array.c index 4e447e0ae..e3fb9f29f 100644 --- a/src/std/array.c +++ b/src/std/array.c @@ -54,10 +54,12 @@ DEFINE_PRIM(_VOID,array_blit,_ARR _I32 _ARR _I32 _I32); DEFINE_PRIM(_TYPE,array_type,_ARR); DEFINE_PRIM(_BYTES,array_bytes,_ARR); +#ifndef HL_DISABLE_COMPAT typedef struct { size_t size; hl_type* type; } hl_carray_header; +#endif HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) { if( at->kind != HOBJ && at->kind != HSTRUCT ) @@ -67,10 +69,14 @@ HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) { hl_runtime_obj *rt = at->obj->rt; if( rt == NULL || rt->methods == NULL ) rt = hl_get_obj_proto(at); +#ifdef HL_DISABLE_COMPAT + char *arr = hl_gc_alloc_gen(at, size * rt->size, (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); +#else void *ptr = hl_gc_alloc_gen(at, sizeof(hl_carray_header) + size * rt->size, (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); ((hl_carray_header*)ptr)->size = size; ((hl_carray_header*)ptr)->type = at; char *arr = (char*)ptr + sizeof(hl_carray_header); +#endif if( at->kind == HOBJ || rt->nbindings ) { int i,k; for(k=0;k Date: Sat, 14 Mar 2026 22:32:32 +0000 Subject: [PATCH 3/4] [std] Move carray compat metadata to footer This way, the carray pointer is still the start of the allocated memory block. This avoids GC issues due to interior pointers. --- src/std/array.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/std/array.c b/src/std/array.c index e3fb9f29f..5e2670ccb 100644 --- a/src/std/array.c +++ b/src/std/array.c @@ -58,7 +58,7 @@ DEFINE_PRIM(_BYTES,array_bytes,_ARR); typedef struct { size_t size; hl_type* type; -} hl_carray_header; +} hl_carray_footer; #endif HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) { @@ -72,10 +72,10 @@ HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) { #ifdef HL_DISABLE_COMPAT char *arr = hl_gc_alloc_gen(at, size * rt->size, (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); #else - void *ptr = hl_gc_alloc_gen(at, sizeof(hl_carray_header) + size * rt->size, (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); - ((hl_carray_header*)ptr)->size = size; - ((hl_carray_header*)ptr)->type = at; - char *arr = (char*)ptr + sizeof(hl_carray_header); + char *arr = hl_gc_alloc_gen(at, size * rt->size + sizeof(hl_carray_footer), (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); + hl_carray_footer *footer = (hl_carray_footer*)(arr + size * rt->size); + footer->size = size; + footer->type = at; #endif if( at->kind == HOBJ || rt->nbindings ) { int i,k; @@ -109,22 +109,23 @@ DEFINE_PRIM(_VOID,carray_blit,_CARRAY _TYPE _I32 _CARRAY _I32 _I32); #ifndef HL_DISABLE_COMPAT // For backwards compatibility with HL 1.13 +#define HL_CARRAY_GET_FOOTER(arr) ((hl_carray_footer*)((char*)(arr) + hl_gc_get_memsize((arr)) - sizeof(hl_carray_footer))) HL_PRIM int hl_carray_length( void *arr ) { - if (!hl_is_gc_ptr((char*)arr - sizeof(hl_carray_header))) { + if (!hl_is_gc_ptr(arr)) { hl_error("Cannot call hl_carray_length with external carray"); } - hl_carray_header* header = (hl_carray_header*)((char*)arr - sizeof(hl_carray_header)); - return header->size; + return HL_CARRAY_GET_FOOTER(arr)->size; } HL_PRIM vdynamic *hl_carray_get( void *arr, int pos ) { - if (!hl_is_gc_ptr((char*)arr - sizeof(hl_carray_header))) { + if (!hl_is_gc_ptr(arr)) { hl_error("Cannot call hl_carray_get with external carray"); } - hl_carray_header* header = (hl_carray_header*)((char*)arr - sizeof(hl_carray_header)); - if (pos < 0 || pos >= header->size) return NULL; - hl_type* type = header->type; + + hl_carray_footer* footer = HL_CARRAY_GET_FOOTER(arr); + if (pos < 0 || pos >= footer->size) return NULL; + hl_type* type = footer->type; void* element = (void*)((char*)arr + pos * type->obj->rt->size); if (type->kind == HSTRUCT) { vdynamic* dyn = hl_alloc_dynamic(type); From ca608d8a9c78687c0c07d8e8cb6dc6f1580861e9 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Sat, 14 Mar 2026 22:39:56 +0000 Subject: [PATCH 4/4] [std] Use HL_CARRAY_GET_FOOTER consistently In case hl_gc_get_memsize is not exactly equal to the requested size --- src/std/array.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/std/array.c b/src/std/array.c index 5e2670ccb..b20b221dd 100644 --- a/src/std/array.c +++ b/src/std/array.c @@ -60,6 +60,7 @@ typedef struct { hl_type* type; } hl_carray_footer; #endif +#define HL_CARRAY_GET_FOOTER(arr) ((hl_carray_footer*)((char*)(arr) + hl_gc_get_memsize((arr)) - sizeof(hl_carray_footer))) HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) { if( at->kind != HOBJ && at->kind != HSTRUCT ) @@ -73,7 +74,7 @@ HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) { char *arr = hl_gc_alloc_gen(at, size * rt->size, (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); #else char *arr = hl_gc_alloc_gen(at, size * rt->size + sizeof(hl_carray_footer), (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO); - hl_carray_footer *footer = (hl_carray_footer*)(arr + size * rt->size); + hl_carray_footer *footer = HL_CARRAY_GET_FOOTER(arr); footer->size = size; footer->type = at; #endif @@ -109,7 +110,6 @@ DEFINE_PRIM(_VOID,carray_blit,_CARRAY _TYPE _I32 _CARRAY _I32 _I32); #ifndef HL_DISABLE_COMPAT // For backwards compatibility with HL 1.13 -#define HL_CARRAY_GET_FOOTER(arr) ((hl_carray_footer*)((char*)(arr) + hl_gc_get_memsize((arr)) - sizeof(hl_carray_footer))) HL_PRIM int hl_carray_length( void *arr ) { if (!hl_is_gc_ptr(arr)) {