Skip to content

Commit cd8d85d

Browse files
gpsheadclaude
andcommitted
Statically alias match to prefixmatch instead of runtime memcpy
Replace the copy_prefixmatch_method_def_to_match() runtime memcpy with static struct initializers that reuse the Clinic-generated prefixmatch parser directly. This avoids duplicating argument parsing boilerplate while keeping everything initialized at compile time. Add Py_DEBUG assertions in sre_exec to verify the match and prefixmatch method table entries remain identical except for ml_name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 341972f commit cd8d85d

File tree

1 file changed

+22
-23
lines changed

1 file changed

+22
-23
lines changed

Modules/_sre/sre.c

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3172,7 +3172,11 @@ pattern_richcompare(PyObject *lefto, PyObject *righto, int op)
31723172

31733173
static PyMethodDef pattern_methods[] = {
31743174
_SRE_SRE_PATTERN_PREFIXMATCH_METHODDEF
3175-
{"match", NULL}, /* filled in by sre_exec() */
3175+
/* "match" reuses the prefixmatch Clinic-generated parser and impl
3176+
* to avoid duplicating the argument parsing boilerplate code. */
3177+
{"match", _PyCFunction_CAST(_sre_SRE_Pattern_prefixmatch),
3178+
METH_METHOD|METH_FASTCALL|METH_KEYWORDS,
3179+
_sre_SRE_Pattern_prefixmatch__doc__},
31763180
_SRE_SRE_PATTERN_FULLMATCH_METHODDEF
31773181
_SRE_SRE_PATTERN_SEARCH_METHODDEF
31783182
_SRE_SRE_PATTERN_SUB_METHODDEF
@@ -3300,7 +3304,11 @@ static PyType_Spec match_spec = {
33003304

33013305
static PyMethodDef scanner_methods[] = {
33023306
_SRE_SRE_SCANNER_PREFIXMATCH_METHODDEF
3303-
{"match", NULL}, /* filled in by sre_exec() */
3307+
/* "match" reuses the prefixmatch Clinic-generated parser and impl
3308+
* to avoid duplicating the argument parsing boilerplate code. */
3309+
{"match", _PyCFunction_CAST(_sre_SRE_Scanner_prefixmatch),
3310+
METH_METHOD|METH_FASTCALL|METH_KEYWORDS,
3311+
_sre_SRE_Scanner_prefixmatch__doc__},
33043312
_SRE_SRE_SCANNER_SEARCH_METHODDEF
33053313
{NULL, NULL}
33063314
};
@@ -3405,38 +3413,29 @@ do { \
34053413
} while (0)
34063414

34073415

3416+
#ifdef Py_DEBUG
34083417
static void
3409-
copy_prefixmatch_method_def_to_match(PyMethodDef *method_defs)
3418+
_assert_match_aliases_prefixmatch(PyMethodDef *methods)
34103419
{
3411-
/* We could implement logic to scan the null filled sentry
3412-
* terminated list for the two method names. But we're a
3413-
* bunch of static structs. We just guarantee their position
3414-
* and flag deviation from this via debug build assertions.
3415-
*/
3416-
assert(method_defs);
3417-
PyMethodDef *prefixmatch_md = &method_defs[0];
3418-
assert(prefixmatch_md->ml_name != NULL);
3420+
PyMethodDef *prefixmatch_md = &methods[0];
3421+
PyMethodDef *match_md = &methods[1];
34193422
assert(strcmp(prefixmatch_md->ml_name, "prefixmatch") == 0);
3420-
3421-
PyMethodDef *match_md = &method_defs[1];
3422-
assert(match_md->ml_name != NULL);
34233423
assert(strcmp(match_md->ml_name, "match") == 0);
3424-
/* If the public stable C API struct ever changed (!) and
3425-
* somehow wound up with unexpected layout and alignment
3426-
* constraints, fix the memcpy below. */
3427-
assert(offsetof(PyMethodDef, ml_meth) == sizeof(char *));
3428-
memcpy(&match_md->ml_meth, &prefixmatch_md->ml_meth,
3429-
sizeof(PyMethodDef) - offsetof(PyMethodDef, ml_meth));
3424+
assert(match_md->ml_meth == prefixmatch_md->ml_meth);
3425+
assert(match_md->ml_flags == prefixmatch_md->ml_flags);
3426+
assert(match_md->ml_doc == prefixmatch_md->ml_doc);
34303427
}
3431-
3428+
#endif
34323429

34333430
static int
34343431
sre_exec(PyObject *m)
34353432
{
34363433
_sremodulestate *state;
34373434

3438-
copy_prefixmatch_method_def_to_match(pattern_methods);
3439-
copy_prefixmatch_method_def_to_match(scanner_methods);
3435+
#ifdef Py_DEBUG
3436+
_assert_match_aliases_prefixmatch(pattern_methods);
3437+
_assert_match_aliases_prefixmatch(scanner_methods);
3438+
#endif
34403439

34413440
/* Create heap types */
34423441
state = get_sre_module_state(m);

0 commit comments

Comments
 (0)