Perl_more_bodies - figure out sizing from sv_type

`Perl_more_bodies` allocates and sets up a new arena for the likes of
SV body, HE, and HVAUX structs. It has traditionally been called with
three arguments:
  * the `svtype`
  * the size of the structs that the arena will contain
  * the size of the arena to allocate

This commit changes the function definition such that it only takes
a single argument: the `svtype`. From that, and with a bit of
additional logic to account of HE and HVAUX using the indexes
notionally for SVt_NULL and SVt_IV, `Perl_more_bodies` can figure
out the sizing for itself.

The rationale for this is that:
  * When an application is starting up, the need to call `Perl_more_bodies`
    is the unlikely case in each new SV allocation or upgrade.
  * When the application has reached a steady state, the function
    may not be called regardless of how many SVs are created or upgraded.

With `Perl_newSV_type` being an inline function, there are a lot of
potential callers to this function though, each of which will have
two `mov` instructions for pushing the two size parameters onto the
stack should the need to call `Perl_more_bodies` arise. Removing two
instructions from each potential call site should help reduce binary
size a little and avoid taking up unnecessary space in the CPU's
instruction buffer.
This commit is contained in:
Richard Leach 2025-04-10 22:28:41 +00:00
parent 9c39a33a0e
commit b40ae72cfc
5 changed files with 30 additions and 22 deletions

View File

@ -2024,9 +2024,7 @@ p |int |mode_from_discipline \
|STRLEN len
: Used in sv.c and hv.c
Cop |void * |more_bodies |const svtype sv_type \
|const size_t body_size \
|const size_t arena_size
Cop |void * |more_bodies |const svtype sv_type
Cp |const char *|moreswitches \
|NN const char *s
Adp |void |mortal_destructor_sv \

2
hv.c
View File

@ -159,7 +159,7 @@ S_new_he(pTHX)
void ** const root = &PL_body_roots[HE_ARENA_ROOT_IX];
if (!*root)
Perl_more_bodies(aTHX_ HE_ARENA_ROOT_IX, sizeof(HE), PERL_ARENA_SIZE);
Perl_more_bodies(aTHX_ HE_ARENA_ROOT_IX);
he = (HE*) *root;
assert(he);
*root = HeNEXT(he);

2
proto.h generated
View File

@ -2493,7 +2493,7 @@ Perl_mode_from_discipline(pTHX_ const char *s, STRLEN len)
#define PERL_ARGS_ASSERT_MODE_FROM_DISCIPLINE
PERL_CALLCONV void *
Perl_more_bodies(pTHX_ const svtype sv_type, const size_t body_size, const size_t arena_size);
Perl_more_bodies(pTHX_ const svtype sv_type);
#define PERL_ARGS_ASSERT_MORE_BODIES
PERL_CALLCONV const char *

20
sv.c
View File

@ -856,10 +856,22 @@ available in hv.c. Similarly SVt_IV is re-used for HVAUX_ARENA_ROOT_IX.
void *
Perl_more_bodies (pTHX_ const svtype sv_type, const size_t body_size,
const size_t arena_size)
Perl_more_bodies (pTHX_ const svtype sv_type)
{
void ** const root = &PL_body_roots[sv_type];
const struct body_details *type_details =
(sv_type > SVt_IV)
? bodies_by_type + sv_type
: (sv_type == SVt_NULL)
? NULL
: &fake_hv_with_aux
;
const size_t body_size = (type_details) ? type_details->body_size
: sizeof(HE);
const size_t arena_size = (type_details) ? type_details->arena_size
: PERL_ARENA_SIZE;
struct arena_desc *adesc;
struct arena_set *aroot = (struct arena_set *) PL_body_arenas;
unsigned int curr;
@ -1291,7 +1303,7 @@ Perl_hv_auxalloc(pTHX_ HV *hv) {
#ifdef PURIFY
new_body = new_NOARENAZ(&fake_hv_with_aux);
#else
new_body_from_arena(new_body, HVAUX_ARENA_ROOT_IX, fake_hv_with_aux);
new_body_from_arena(new_body, HVAUX_ARENA_ROOT_IX);
#endif
old_body = SvANY(hv);
@ -14713,7 +14725,7 @@ S_sv_dup_common(pTHX_ const SV *const ssv, CLONE_PARAMS *const param)
#ifdef PURIFY
new_body = new_NOARENA(sv_type_details);
#else
new_body_from_arena(new_body, HVAUX_ARENA_ROOT_IX, fake_hv_with_aux);
new_body_from_arena(new_body, HVAUX_ARENA_ROOT_IX);
#endif
goto have_body;
}

View File

@ -180,6 +180,14 @@ ALIGNED_TYPE(XPVOBJ);
STRUCT_OFFSET(type, last_member) \
+ sizeof (((type*)SvANY((const SV *)0))->last_member)
static const struct body_details fake_hv_with_aux =
/* The SVt_IV arena is used for (larger) PVHV bodies. */
{ sizeof(ALIGNED_TYPE_NAME(XPVHV_WITH_AUX)),
copy_length(XPVHV, xhv_max),
0,
SVt_PVHV, TRUE, NONV, HASARENA,
FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVHV_WITH_AUX))) };
static const struct body_details bodies_by_type[] = {
/* HEs use this offset for their arena. */
{ 0, 0, 0, SVt_NULL, FALSE, NONV, NOARENA, 0 },
@ -328,13 +336,11 @@ static const struct body_details bodies_by_type[] = {
#ifndef PURIFY
/* grab a new thing from the arena's free list, allocating more if necessary. */
#define new_body_from_arena(xpv, root_index, type_meta) \
#define new_body_from_arena(xpv, root_index) \
STMT_START { \
void ** const r3wt = &PL_body_roots[root_index]; \
xpv = (PTR_TBL_ENT_t*) (*((void **)(r3wt)) \
? *((void **)(r3wt)) : Perl_more_bodies(aTHX_ root_index, \
type_meta.body_size,\
type_meta.arena_size)); \
? *((void **)(r3wt)) : Perl_more_bodies(aTHX_ root_index)); \
*(r3wt) = *(void**)(xpv); \
} STMT_END
@ -342,7 +348,7 @@ PERL_STATIC_INLINE void *
S_new_body(pTHX_ const svtype sv_type)
{
void *xpv;
new_body_from_arena(xpv, sv_type, bodies_by_type[sv_type]);
new_body_from_arena(xpv, sv_type);
return xpv;
}
@ -351,14 +357,6 @@ S_new_body(pTHX_ const svtype sv_type)
static const struct body_details fake_rv =
{ 0, 0, 0, SVt_IV, FALSE, NONV, NOARENA, 0 };
static const struct body_details fake_hv_with_aux =
/* The SVt_IV arena is used for (larger) PVHV bodies. */
{ sizeof(ALIGNED_TYPE_NAME(XPVHV_WITH_AUX)),
copy_length(XPVHV, xhv_max),
0,
SVt_PVHV, TRUE, NONV, HASARENA,
FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVHV_WITH_AUX))) };
/*
=for apidoc newSV_type