From f0e570c0c89bdd1a1a61810b0c3b668e2e70ee3f Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Thu, 10 Apr 2025 22:28:41 +0000 Subject: [PATCH] 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. --- embed.fnc | 4 +--- hv.c | 2 +- proto.h | 2 +- sv.c | 20 ++++++++++++++++---- sv_inline.h | 24 +++++++++++------------- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/embed.fnc b/embed.fnc index 0332f63875ec..b0510db2d229 100644 --- a/embed.fnc +++ b/embed.fnc @@ -2043,9 +2043,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 \ diff --git a/hv.c b/hv.c index 8c65091fd2ca..a62350ff4e94 100644 --- a/hv.c +++ b/hv.c @@ -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); diff --git a/proto.h b/proto.h index e132956f8ac8..f11476f1163c 100644 --- a/proto.h +++ b/proto.h @@ -2555,7 +2555,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 * diff --git a/sv.c b/sv.c index e8c6e65a2717..1ce51330cc02 100644 --- a/sv.c +++ b/sv.c @@ -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); @@ -14799,7 +14811,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; } diff --git a/sv_inline.h b/sv_inline.h index 57a68796cb02..6989be367081 100644 --- a/sv_inline.h +++ b/sv_inline.h @@ -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