Skip to content

Commit badcae7

Browse files
committed
gh-129724: Intern string constants in the compiler, not per code object
The compiler merges equal constants of a module through its constant cache. intern_constants() then ran on each code object and rebuilt a frozenset (or, in the free-threaded build, a slice) when one of its strings was replaced by an already interned one, so a constant shared by several functions was copied for some of them depending on which strings happened to be interned in the process. The class body's __qualname__ constant and co_qualname had the same problem. marshal then wrote different bytes for the same source. Intern the eligible strings of the final constants of each code unit after optimization and before the code object is created. Tuples are updated in place; a frozenset or slice is rebuilt once and stored in the constant cache so that later units get the same object. The same code is used in both builds. Which strings are interned does not change, except that identifier-like strings in slice constants are now interned in the default build too. TestConstantsIdentity compares the identity graph and the marshal output of code compiled in differently prepared processes, including names tuples shared with constants.
1 parent c6c0608 commit badcae7

5 files changed

Lines changed: 698 additions & 3 deletions

File tree

‎Include/internal/pycore_code.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,10 @@ PyAPI_FUNC(int) _PyCode_ReturnsOnlyNone(PyCodeObject *);
699699
* compare bytes and str which can raise a BytesWarning exception. */
700700
extern PyObject* _PyCode_ConstantKey(PyObject *obj);
701701

702+
// Return true if the string constant *o* gets interned when it is stored in
703+
// the co_consts of a code object. *o* must be an exact str.
704+
extern int _PyCode_ShouldInternString(PyObject *o);
705+
702706

703707
#ifdef __cplusplus
704708
}

0 commit comments

Comments
 (0)