1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-07-05 17:20:18 +02:00

Avoid untagged traced allocation in make-struct/no-tail

* libguile/struct.c (scm_struct_init_1_default):
(scm_struct_init_1): New helpers.
(scm_struct_init_array): Use new helpers.
(scm_struct_init_list): New function.
(scm_make_struct_no_tail): Use scm_struct_init_list instead of mallocing.
This commit is contained in:
Andy Wingo 2025-06-20 09:27:47 +02:00
parent 4d15cb7e6d
commit ce2f7847e8

View file

@ -255,7 +255,25 @@ scm_i_struct_inherit_vtable_magic (SCM vtable, SCM obj)
static void static void
scm_struct_init (SCM handle, SCM layout, size_t n_inits, scm_t_bits *inits) scm_struct_init_1_default (SCM handle, size_t idx)
{
SCM_STRUCT_DATA_SET (handle, idx,
SCM_STRUCT_FIELD_IS_UNBOXED (handle, idx)
? 0
: SCM_UNPACK (SCM_BOOL_F));
}
static void
scm_struct_init_1 (SCM handle, size_t idx, scm_t_bits val)
{
SCM_STRUCT_DATA_SET (handle, idx,
SCM_STRUCT_FIELD_IS_UNBOXED (handle, idx)
? scm_to_uintptr_t (SCM_PACK (val))
: val);
}
static void
scm_struct_init_array (SCM handle, SCM layout, size_t n_inits, scm_t_bits *inits)
{ {
size_t n, n_fields, inits_idx = 0; size_t n, n_fields, inits_idx = 0;
@ -264,23 +282,28 @@ scm_struct_init (SCM handle, SCM layout, size_t n_inits, scm_t_bits *inits)
for (n = 0; n < n_fields; n++) for (n = 0; n < n_fields; n++)
{ {
if (inits_idx == n_inits || scm_i_symbol_ref (layout, n*2+1) == 'h') if (inits_idx == n_inits || scm_i_symbol_ref (layout, n*2+1) == 'h')
{ scm_struct_init_1_default (handle, n);
if (SCM_STRUCT_FIELD_IS_UNBOXED (handle, n))
SCM_STRUCT_DATA_SET (handle, n, 0);
else
SCM_STRUCT_SLOT_SET (handle, n, SCM_BOOL_F);
}
else else
{ scm_struct_init_1 (handle, n, inits[inits_idx++]);
SCM_STRUCT_DATA_SET (handle, n,
SCM_STRUCT_FIELD_IS_UNBOXED (handle, n)
? scm_to_uintptr_t (SCM_PACK (inits[inits_idx]))
: inits[inits_idx]);
inits_idx++;
}
} }
} }
static void
scm_struct_init_list (SCM handle, SCM layout, SCM inits)
{
size_t n_fields = SCM_STRUCT_SIZE (handle);
for (size_t n = 0; n < n_fields; n++)
{
if (scm_is_null (inits) || scm_i_symbol_ref (layout, n*2+1) == 'h')
scm_struct_init_1_default (handle, n);
else
{
scm_struct_init_1 (handle, n, SCM_UNPACK (scm_car (inits)));
inits = scm_cdr (inits);
}
}
}
SCM_DEFINE (scm_struct_p, "struct?", 1, 0, 0, SCM_DEFINE (scm_struct_p, "struct?", 1, 0, 0,
(SCM x), (SCM x),
@ -350,7 +373,7 @@ scm_c_make_structv (SCM vtable, size_t n_tail, size_t n_init, scm_t_bits *init)
SCM_ASSERT (n_tail == 0, scm_from_size_t (n_tail), 2, FUNC_NAME); SCM_ASSERT (n_tail == 0, scm_from_size_t (n_tail), 2, FUNC_NAME);
obj = scm_i_alloc_struct (SCM_UNPACK (vtable), basic_size); obj = scm_i_alloc_struct (SCM_UNPACK (vtable), basic_size);
scm_struct_init (obj, SCM_VTABLE_LAYOUT (vtable), n_init, init); scm_struct_init_array (obj, SCM_VTABLE_LAYOUT (vtable), n_init, init);
/* If we're making a vtable, validate its layout and inherit /* If we're making a vtable, validate its layout and inherit
flags. However we allow for separation of allocation and flags. However we allow for separation of allocation and
@ -407,7 +430,7 @@ SCM_DEFINE (scm_allocate_struct, "allocate-struct", 2, 0, 0,
SCM_ASSERT (SCM_VTABLE_SIZE (vtable) == c_nfields, nfields, 2, FUNC_NAME); SCM_ASSERT (SCM_VTABLE_SIZE (vtable) == c_nfields, nfields, 2, FUNC_NAME);
ret = scm_i_alloc_struct (SCM_UNPACK (vtable), c_nfields); ret = scm_i_alloc_struct (SCM_UNPACK (vtable), c_nfields);
scm_struct_init (ret, SCM_VTABLE_LAYOUT (vtable), 0, NULL); scm_struct_init_array (ret, SCM_VTABLE_LAYOUT (vtable), 0, NULL);
return ret; return ret;
} }
@ -464,28 +487,23 @@ SCM_DEFINE (scm_make_struct_no_tail, "make-struct/no-tail", 1, 0, 1,
"initialized to 0.") "initialized to 0.")
#define FUNC_NAME s_scm_make_struct_no_tail #define FUNC_NAME s_scm_make_struct_no_tail
{ {
size_t i, n_init;
long ilen;
scm_t_bits *v;
SCM_VALIDATE_VTABLE (1, vtable); SCM_VALIDATE_VTABLE (1, vtable);
ilen = scm_ilength (init);
if (ilen < 0) if (scm_ilength (init) < 0)
SCM_MISC_ERROR ("Rest arguments do not form a proper list.", SCM_EOL); SCM_MISC_ERROR ("Rest arguments do not form a proper list.", SCM_EOL);
n_init = (size_t)ilen; SCM obj = scm_i_alloc_struct (SCM_UNPACK (vtable), SCM_VTABLE_SIZE (vtable));
scm_struct_init_list (obj, SCM_VTABLE_LAYOUT (vtable), init);
/* best to use alloca, but init could be big, so hack to avoid a possible /* If we're making a vtable, validate its layout and inherit
stack overflow */ flags. However we allow for separation of allocation and
if (n_init < 64) initialization, to humor GOOPS, so only validate if the layout was
v = alloca (n_init * sizeof(scm_t_bits)); passed as an initarg. */
else if (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_VTABLE)
v = scm_gc_malloc (n_init * sizeof(scm_t_bits), "struct"); && scm_is_true (SCM_VTABLE_LAYOUT (obj)))
scm_i_struct_inherit_vtable_magic (vtable, obj);
for (i = 0; i < n_init; i++, init = SCM_CDR (init)) return obj;
v[i] = SCM_UNPACK (SCM_CAR (init));
return scm_c_make_structv (vtable, 0, n_init, v);
} }
#undef FUNC_NAME #undef FUNC_NAME