Skip to content

Commit 93fbcb7

Browse files
committed
Make local constant arrays static
Local, non-static constant arrays may get re-initialised at runtime (by pushing their contents on the stack) every time they are reached. This somewhat surprising behaviour is caused by the fact that the C standard requires (almost) every object to have a unique address. In theory, a compiler may eliminate the re-initialisation, if it can prove that the address of an array is never examined. However: 1. This often isn't possible to prove. The compiler has no way to know what will happen to an array pointer once it leaves the compilation unit. 2. Unlike Clang, GCC and Visual C++ don't even attempt this optimisation at all. GCC has an open ticket for this: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59863 Making those arrays static avoids the problem, because static arrays are guaranteed to be initialised only once, prior the to the program startup.
1 parent 6eee01a commit 93fbcb7

File tree

6 files changed

+39
-40
lines changed

6 files changed

+39
-40
lines changed

locale.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ S_parse_LC_ALL_string(pTHX_ const char * string,
12351235

12361236
# ifdef PERL_LC_ALL_USES_NAME_VALUE_PAIRS
12371237

1238-
const char separator[] = ";";
1238+
const char * const separator = ";";
12391239
const Size_t separator_len = 1;
12401240
const bool single_component = (strchr(string, ';') == NULL);
12411241

@@ -5277,7 +5277,7 @@ S_my_localeconv(pTHX_ const int item)
52775277
#define LCONV_MONETARY_ENTRY(name) LCONV_ENTRY(name)
52785278

52795279
/* There are just a few fields for NUMERIC strings */
5280-
const lconv_offset_t lconv_numeric_strings[] = {
5280+
static const lconv_offset_t lconv_numeric_strings[] = {
52815281
#ifndef NO_LOCALECONV_GROUPING
52825282
LCONV_NUMERIC_ENTRY(grouping),
52835283
# endif
@@ -5301,7 +5301,7 @@ S_my_localeconv(pTHX_ const int item)
53015301
&lconv_numeric_strings[(C_ARRAY_LENGTH(lconv_numeric_strings) - 2)]
53025302

53035303
/* And the MONETARY string fields */
5304-
const lconv_offset_t lconv_monetary_strings[] = {
5304+
static const lconv_offset_t lconv_monetary_strings[] = {
53055305
LCONV_MONETARY_ENTRY(int_curr_symbol),
53065306
LCONV_MONETARY_ENTRY(mon_decimal_point),
53075307
#ifndef NO_LOCALECONV_MON_THOUSANDS_SEP
@@ -5322,7 +5322,7 @@ S_my_localeconv(pTHX_ const int item)
53225322
&lconv_monetary_strings[(C_ARRAY_LENGTH(lconv_monetary_strings) - 2)]
53235323

53245324
/* Finally there are integer fields, all are for monetary purposes */
5325-
const lconv_offset_t lconv_integers[] = {
5325+
static const lconv_offset_t lconv_integers[] = {
53265326
LCONV_ENTRY(int_frac_digits),
53275327
LCONV_ENTRY(frac_digits),
53285328
LCONV_ENTRY(p_sep_by_space),
@@ -5432,7 +5432,7 @@ S_my_localeconv(pTHX_ const int item)
54325432
* the data structure could do double duty. However, both this and
54335433
* RADIXCHAR would need to be in the final position of the same full
54345434
* structure; an impossibility. So make this into a separate structure */
5435-
const lconv_offset_t thousands_sep_string[] = {
5435+
static const lconv_offset_t thousands_sep_string[] = {
54365436
LCONV_NUMERIC_ENTRY(thousands_sep),
54375437
{NULL, 0}
54385438
};
@@ -7684,10 +7684,10 @@ S_emulate_langinfo(pTHX_ const PERL_INTMAX_T item,
76847684
* holds what field in the 'struct tm' to applies to the corresponding
76857685
* format */
76867686
int year, min, sec;
7687-
const char * fmts[] = {"%Oy", "%OM", "%OS", "%Od", "%OH", "%Om", "%Ow" };
7688-
const Size_t maxes[] = { 99, 59, 59, 31, 23, 11, 6 };
7689-
const int offsets[] = { 0, 0, 0, 1, 0, 1, 0 };
7690-
int * vars[] = {&year, &min, &sec, &mday, &hour, &mon, &mday };
7687+
static const char * const fmts[] = {"%Oy", "%OM", "%OS", "%Od", "%OH", "%Om", "%Ow" };
7688+
static const Size_t const maxes[] = { 99, 59, 59, 31, 23, 11, 6 };
7689+
static const int const offsets[] = { 0, 0, 0, 1, 0, 1, 0 };
7690+
int * vars[] = {&year, &min, &sec, &mday, &hour, &mon, &mday };
76917691
Size_t j = 0; /* Current index into the above tables */
76927692

76937693
orig_TIME_locale = toggle_locale_c_unless_locking(LC_TIME, locale);
@@ -7965,7 +7965,7 @@ S_maybe_override_codeset(pTHX_ const char * codeset,
79657965
utf8ness_t strings_utf8ness = UTF8NESS_UNKNOWN;
79667966

79677967
/* List of strings to look at */
7968-
const int trials[] = {
7968+
static const int trials[] = {
79697969

79707970
# if defined(USE_LOCALE_MONETARY) && defined(HAS_LOCALECONV)
79717971

@@ -9530,7 +9530,7 @@ S_compute_collxfrm_coefficients(pTHX)
95309530
* digits tend to have fewer levels, and some punctuation has more, but
95319531
* those are relatively sparse in text, and khw believes this gives a
95329532
* reasonable result, but it could be changed if experience so dictates. */
9533-
const char longer[] = "ABCDEFGHIJKLMnopqrstuvwxyz";
9533+
const char * const longer = "ABCDEFGHIJKLMnopqrstuvwxyz";
95349534
char * x_longer; /* Transformed 'longer' */
95359535
Size_t x_len_longer; /* Length of 'x_longer' */
95369536

@@ -9555,7 +9555,7 @@ S_compute_collxfrm_coefficients(pTHX)
95559555

95569556
/* Find out how long the transformation really is */
95579557
x_longer = mem_collxfrm_(longer,
9558-
sizeof(longer) - 1,
9558+
strlen(longer),
95599559
&x_len_longer,
95609560

95619561
/* We avoid converting to UTF-8 in the called
@@ -9572,7 +9572,7 @@ S_compute_collxfrm_coefficients(pTHX)
95729572
* first character. This minimizes the chances of being swayed by outliers
95739573
* */
95749574
x_shorter = mem_collxfrm_(longer + 1,
9575-
sizeof(longer) - 2,
9575+
strlen(longer) - 1,
95769576
&x_len_shorter,
95779577
PL_in_utf8_COLLATE_locale);
95789578
Safefree(x_shorter);
@@ -9616,7 +9616,7 @@ S_compute_collxfrm_coefficients(pTHX)
96169616
/* mx + b = len
96179617
* so: b = len - mx
96189618
* but in case something has gone wrong, make sure it is non-negative */
9619-
base = x_len_longer - PL_collxfrm_mult * (sizeof(longer) - 1);
9619+
base = x_len_longer - PL_collxfrm_mult * strlen(longer);
96209620
if (base < 0) {
96219621
base = 0;
96229622
}

perl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5172,7 +5172,7 @@ S_incpush(pTHX_ const char *const dir, STRLEN len, U32 flags)
51725172
SV *subdir = newSVsv(libdir);
51735173
#ifdef PERL_INC_VERSION_LIST
51745174
/* Configure terminates PERL_INC_VERSION_LIST with a NULL */
5175-
const char * const incverlist[] = { PERL_INC_VERSION_LIST };
5175+
static const char * const incverlist[] = { PERL_INC_VERSION_LIST };
51765176
const char * const *incver;
51775177
#endif
51785178

pp_ctl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4699,9 +4699,9 @@ S_require_file(pTHX_ SV *sv)
46994699
* of checks here at runtime.
47004700
*/
47014701
const STRLEN package_len = len - 3;
4702-
const char slashdot[2] = {'/', '.'};
4702+
static const char slashdot[2] = {'/', '.'};
47034703
#ifdef DOSISH
4704-
const char backslashdot[2] = {'\\', '.'};
4704+
static const char backslashdot[2] = {'\\', '.'};
47054705
#endif
47064706

47074707
/* Disallow *purported* barewords that map to absolute

regcomp.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3484,9 +3484,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
34843484
bool is_logical = 0, is_optimistic = 0;
34853485
const char * const seqstart = RExC_parse;
34863486
const char * endptr;
3487-
const char non_existent_group_msg[]
3487+
const char * const non_existent_group_msg
34883488
= "Reference to nonexistent group";
3489-
const char impossible_group[] = "Invalid reference to group";
3489+
const char * const impossible_group = "Invalid reference to group";
34903490

34913491
if (has_intervening_patws) {
34923492
RExC_parse_inc_by(1);
@@ -4476,7 +4476,7 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
44764476
{
44774477
const char *p;
44784478
/* Even/odd or x = don't care: 010101x10x */
4479-
static const char parens[] = "=!aA<,>Bbt";
4479+
const char * const parens = "=!aA<,>Bbt";
44804480
/* flag below is set to 0 up through 'A'; 1 for larger */
44814481

44824482
if (paren && (p = strchr(parens, paren))) {
@@ -8350,7 +8350,7 @@ S_handle_possible_posix(pTHX_ RExC_state_t *pRExC_state,
83508350
* was, but there was a typo. We tease these apart by doing fuzzy
83518351
* matching on the name */
83528352
if (class_number == OOB_NAMEDCLASS && found_problem) {
8353-
const UV posix_names[][6] = {
8353+
static const UV posix_names[][6] = {
83548354
{ 'a', 'l', 'n', 'u', 'm' },
83558355
{ 'a', 'l', 'p', 'h', 'a' },
83568356
{ 'a', 's', 'c', 'i', 'i' },
@@ -8368,7 +8368,7 @@ S_handle_possible_posix(pTHX_ RExC_state_t *pRExC_state,
83688368
};
83698369
/* The names of the above all have added NULs to make them the same
83708370
* size, so we need to also have the real lengths */
8371-
const UV posix_name_lengths[] = {
8371+
static const UV posix_name_lengths[] = {
83728372
sizeof("alnum") - 1,
83738373
sizeof("alpha") - 1,
83748374
sizeof("ascii") - 1,
@@ -14247,7 +14247,7 @@ S_handle_user_defined_property(pTHX_
1424714247

1424814248
const char * s0 = string; /* Points to first byte in the current line
1424914249
being parsed in 'string' */
14250-
const char overflow_msg[] = "Code point too large in \"";
14250+
const char * const overflow_msg = "Code point too large in \"";
1425114251
SV* running_definition = NULL;
1425214252

1425314253
PERL_ARGS_ASSERT_HANDLE_USER_DEFINED_PROPERTY;
@@ -15332,7 +15332,7 @@ S_parse_uniprop_string(pTHX_
1533215332
/* Drop down to look up in the official properties */
1533315333
}
1533415334
else {
15335-
const char insecure[] = "Insecure user-defined property";
15335+
const char * const insecure = "Insecure user-defined property";
1533615336

1533715337
/* Here, there is a sub by the correct name. Normally we call it
1533815338
* to get the property definition */
@@ -15357,7 +15357,7 @@ S_parse_uniprop_string(pTHX_
1535715357
* error instead */
1535815358
if (TAINT_get) {
1535915359
if (SvCUR(msg) > 0) sv_catpvs(msg, "; ");
15360-
sv_catpvn(msg, insecure, sizeof(insecure) - 1);
15360+
sv_catpvn(msg, insecure, strlen(insecure));
1536115361
goto append_name_to_msg;
1536215362
}
1536315363

@@ -15545,7 +15545,7 @@ S_parse_uniprop_string(pTHX_
1554515545
}
1554615546
if (TAINT_get) {
1554715547
if (SvTRUE(error)) sv_catpvs(msg, "; ");
15548-
sv_catpvn(msg, insecure, sizeof(insecure) - 1);
15548+
sv_catpvn(msg, insecure, strlen(insecure));
1554915549
}
1555015550

1555115551
if (name_len > 0) {
@@ -16033,8 +16033,8 @@ S_handle_names_wildcard(pTHX_ const char * wname, /* wildcard name to match */
1603316033
const char * must; /* The PV of 'must' */
1603416034
STRLEN must_len; /* And its length */
1603516035
SV * syllable_name = NULL; /* For Hangul syllables */
16036-
const char hangul_prefix[] = "HANGUL SYLLABLE ";
16037-
const STRLEN hangul_prefix_len = sizeof(hangul_prefix) - 1;
16036+
const char * const hangul_prefix = "HANGUL SYLLABLE ";
16037+
const STRLEN hangul_prefix_len = strlen(hangul_prefix);
1603816038

1603916039
/* By inspection, there are a maximum of 7 bytes in the suffix of a hangul
1604016040
* syllable name, and these are immutable and guaranteed by the Unicode
@@ -16267,20 +16267,20 @@ S_handle_names_wildcard(pTHX_ const char * wname, /* wildcard name to match */
1626716267
/* These constants, names, values, and algorithm are adapted from the
1626816268
* Unicode standard, version 5.1, section 3.12, and should never
1626916269
* change. */
16270-
const char * JamoL[] = {
16270+
static const char * const JamoL[] = {
1627116271
"G", "GG", "N", "D", "DD", "R", "M", "B", "BB",
1627216272
"S", "SS", "", "J", "JJ", "C", "K", "T", "P", "H"
1627316273
};
1627416274
const int LCount = C_ARRAY_LENGTH(JamoL);
1627516275

16276-
const char * JamoV[] = {
16276+
static const char * const JamoV[] = {
1627716277
"A", "AE", "YA", "YAE", "EO", "E", "YEO", "YE", "O", "WA",
1627816278
"WAE", "OE", "YO", "U", "WEO", "WE", "WI", "YU", "EU", "YI",
1627916279
"I"
1628016280
};
1628116281
const int VCount = C_ARRAY_LENGTH(JamoV);
1628216282

16283-
const char * JamoT[] = {
16283+
static const char * const JamoT[] = {
1628416284
"", "G", "GG", "GS", "N", "NJ", "NH", "D", "L",
1628516285
"LG", "LM", "LB", "LS", "LT", "LP", "LH", "M", "B",
1628616286
"BS", "S", "SS", "NG", "J", "C", "K", "T", "P", "H"
@@ -16415,7 +16415,7 @@ S_handle_names_wildcard(pTHX_ const char * wname, /* wildcard name to match */
1641516415
/* If we ever were to accept aliases for, say private use names, we would
1641616416
* need to do something fancier to find empty names. The code below works
1641716417
* (at the time it was written), and is slower than the above */
16418-
const char empties_pat[] = "^.";
16418+
const char * const empties_pat = "^.";
1641916419
if (strNE(name, empties_pat)) {
1642016420
SV * empty = newSVpvs("");
1642116421
if (execute_wildcard(subpattern_re,

toke.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4093,9 +4093,9 @@ S_scan_const(pTHX_ char *start)
40934093
if (PL_lex_inpat) {
40944094

40954095
if (! len) { /* The name resolved to an empty string */
4096-
const char empty_N[] = "\\N{_}";
4097-
Copy(empty_N, d, sizeof(empty_N) - 1, char);
4098-
d += sizeof(empty_N) - 1;
4096+
const char * const empty_N = "\\N{_}";
4097+
Copy(empty_N, d, strlen(empty_N), char);
4098+
d += strlen(empty_N);
40994099
}
41004100
else {
41014101
/* In order to not lose information for the regex
@@ -4113,9 +4113,8 @@ S_scan_const(pTHX_ char *start)
41134113
* through the string. Each character takes up
41144114
* 2 hex digits plus either a trailing dot or
41154115
* the "}" */
4116-
const char initial_text[] = "\\N{U+";
4117-
const STRLEN initial_len = sizeof(initial_text)
4118-
- 1;
4116+
const char * const initial_text = "\\N{U+";
4117+
const STRLEN initial_len = strlen(initial_text);
41194118
d = off + SvGROW(sv, off
41204119
+ 3 * len
41214120

util.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6195,11 +6195,11 @@ static void atos_update(atos_context* ctx,
61956195
if (ctx->unavail)
61966196
return;
61976197
if (ctx->tool == NULL) {
6198-
const char* tools[] = {
6198+
static const char* const tools[] = {
61996199
"/usr/bin/xcrun",
62006200
"/usr/bin/atos"
62016201
};
6202-
const char* formats[] = {
6202+
static const char* const formats[] = {
62036203
"/usr/bin/xcrun atos -o '%s' -l %08x %08x 2>&1",
62046204
"/usr/bin/atos -d -o '%s' -l %08x %08x 2>&1"
62056205
};

0 commit comments

Comments
 (0)