Skip to content

Commit 8d32ca0

Browse files
committed
mro_core.c mro.xs actually use static global field struct mro_alg->hash_U32
Perl_mro_register(aTHX_ &dfs_alg); will remember and store ptr &dfs_alg forever in a SVUV. So do not keep struct mro_alg'es in const RO memory, and fill in the U32 hash at perl proc start or shared lib attach time. Other parts of the interp will deref and pass struct member "struct mro_alg->hash" to hv_common(). PERL_HASH(hash, "c3", (sizeof("c3")-1)); was specially written instead of PERL_HASH(hash, c3_alg.name, c3_alg.length); because PERL_HASH() is inlineable, and I've seen MSVC 2022 -O1 do heavy inlining and heavy const folding of sbox32_hash_with_state(), if it knows the constant chars in a string, and the constant length of the string, ahead of time during CC .c->.obj phase. The machine code of a very heavy const fold of sbox32_hash_with_state(), superficially looks more like an inlined fixed length memcpy() or a struct to struct = assignment, than some kind of fancy "hash" or "cryptographic" or jpg/mpeg algorithm. I will assume "U32 hash = c3_alg.hash; if (hash == 0) {" and "c3_alg.hash = hash;" are atomic/multi-core safe. Aligned R/Ws to types U8/U16/U32 on all CPUs, and U64 on 64b, are supposed to be atomic safe on all CPUs. Aligned U32 R/Ws in C are never emulated with 4 separate U8 or 8 U4 R/W ops on any commercial CPU.
1 parent b0e6192 commit 8d32ca0

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

ext/mro/mro.xs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
static AV*
88
S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level);
99

10-
static const struct mro_alg c3_alg =
10+
static struct mro_alg c3_alg =
1111
{S_mro_get_linear_isa_c3, "c3", 2, 0, 0};
1212

1313
/*
@@ -665,4 +665,14 @@ mro__nextcan(...)
665665
XSRETURN_EMPTY;
666666

667667
BOOT:
668+
{
669+
U32 hash = c3_alg.hash;
670+
if (hash == 0) {
671+
assert(c3_alg.name == "c3" && c3_alg.length == (sizeof("c3")-1));
672+
/* Using "c3" will aggressively SBOX32 CC const fold.
673+
But RW const char * c3_alg.name can not. */
674+
PERL_HASH(hash, "c3", (sizeof("c3")-1));
675+
c3_alg.hash = hash;
676+
}
677+
}
668678
Perl_mro_register(aTHX_ &c3_alg);

mro_core.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Also see L<perlmroapi>.
3131
#define PERL_IN_MRO_CORE_C
3232
#include "perl.h"
3333

34-
static const struct mro_alg dfs_alg =
34+
static struct mro_alg dfs_alg =
3535
{S_mro_get_linear_isa_dfs, "dfs", 3, 0, 0};
3636

3737
SV *
@@ -1429,6 +1429,16 @@ Perl_boot_core_mro(pTHX)
14291429
{
14301430
static const char file[] = __FILE__;
14311431

1432+
{
1433+
U32 hash = dfs_alg.hash;
1434+
if (hash == 0) {
1435+
assert(dfs_alg.name == "dfs" && dfs_alg.length == STRLENs("dfs"));
1436+
/* Using "dfs" will aggressively SBOX32 CC const fold.
1437+
But RW const char * dfs_alg.name can not. */
1438+
PERL_HASH(hash, "dfs", STRLENs("dfs"));
1439+
dfs_alg.hash = hash;
1440+
}
1441+
}
14321442
Perl_mro_register(aTHX_ &dfs_alg);
14331443

14341444
newXSproto("mro::method_changed_in", XS_mro_method_changed_in, file, "$");

0 commit comments

Comments
 (0)