bpo-46841: Quicken code in-place (GH-31888) · python/cpython@2bde682 (original) (raw)

`@@ -26,91 +26,80 @@ typedef uint16_t _Py_CODEUNIT;

`

26

26

`// Use "unsigned char" instead of "uint8_t" here to avoid illegal aliasing:

`

27

27

`#define _Py_SET_OPCODE(word, opcode) (((unsigned char *)&(word))[0] = (opcode))

`

28

28

``

``

29

`+

// To avoid repeating ourselves in deepfreeze.py, all PyCodeObject members are

`

``

30

`+

// defined in this macro:

`

``

31

`+

#define _PyCode_DEF(SIZE) { \

`

``

32

`+

PyObject_VAR_HEAD \

`

``

33

`+

\

`

``

34

`+

/* Note only the following fields are used in hash and/or comparisons \

`

``

35

`+

`

``

36

`+

`

``

37

`+

`

``

38

`+

`

``

39

`+

`

``

40

`+

`

``

41

`+

`

``

42

`+

`

``

43

`+

`

``

44

`+

`

``

45

`+

`

``

46

`+

`

``

47

`+

`

``

48

`+

`

``

49

`+

`

``

50

`+

*/ \

`

``

51

`+

\

`

``

52

`+

/* These fields are set with provided values on new code objects. */ \

`

``

53

`+

\

`

``

54

`+

/* The hottest fields (in the eval loop) are grouped here at the top. */ \

`

``

55

`+

PyObject co_consts; / list (constants used) */ \

`

``

56

`+

PyObject co_names; / list of strings (names used) */ \

`

``

57

`+

PyObject co_exceptiontable; / Byte string encoding exception handling \

`

``

58

`+

table */ \

`

``

59

`+

int co_flags; /* CO_..., see below */ \

`

``

60

`+

int co_warmup; /* Warmup counter for quickening */ \

`

``

61

`+

\

`

``

62

`+

/* The rest are not so impactful on performance. */ \

`

``

63

`+

int co_argcount; /* #arguments, except *args */ \

`

``

64

`+

int co_posonlyargcount; /* #positional only arguments */ \

`

``

65

`+

int co_kwonlyargcount; /* #keyword only arguments */ \

`

``

66

`+

int co_stacksize; /* #entries needed for evaluation stack */ \

`

``

67

`+

int co_firstlineno; /* first source line number */ \

`

``

68

`+

\

`

``

69

`+

/* redundant values (derived from co_localsplusnames and \

`

``

70

`+

co_localspluskinds) */ \

`

``

71

`+

int co_nlocalsplus; /* number of local + cell + free variables \

`

``

72

`+

*/ \

`

``

73

`+

int co_nlocals; /* number of local variables */ \

`

``

74

`+

int co_nplaincellvars; /* number of non-arg cell variables */ \

`

``

75

`+

int co_ncellvars; /* total number of cell variables */ \

`

``

76

`+

int co_nfreevars; /* number of free variables */ \

`

``

77

`+

\

`

``

78

`+

PyObject co_localsplusnames; / tuple mapping offsets to names */ \

`

``

79

`+

PyObject co_localspluskinds; / Bytes mapping to local kinds (one byte \

`

``

80

`+

per variable) */ \

`

``

81

`+

PyObject co_filename; / unicode (where it was loaded from) */ \

`

``

82

`+

PyObject co_name; / unicode (name, for reference) */ \

`

``

83

`+

PyObject co_qualname; / unicode (qualname, for reference) */ \

`

``

84

`+

PyObject co_linetable; / bytes (encoding addr<->lineno mapping) \

`

``

85

`+

See Objects/lnotab_notes.txt for details. \

`

``

86

`+

*/ \

`

``

87

`+

PyObject co_endlinetable; / bytes object that holds end lineno for \

`

``

88

`+

instructions separated across different \

`

``

89

`+

lines */ \

`

``

90

`+

PyObject co_columntable; / bytes object that holds start/end column \

`

``

91

`+

offset each instruction */ \

`

``

92

`+

\

`

``

93

`+

PyObject co_weakreflist; / to support weakrefs to code objects */ \

`

``

94

`+

/* Scratch space for extra data relating to the code object. \

`

``

95

`+

Type is a void* to keep the format private in codeobject.c to force \

`

``

96

`+

people to go through the proper APIs. */ \

`

``

97

`+

void *co_extra; \

`

``

98

`+

char co_code_adaptive[(SIZE)]; \

`

``

99

`+

}

`

29

100

``

30

101

`/* Bytecode object */

`

31

``

`-

struct PyCodeObject {

`

32

``

`-

PyObject_HEAD

`

33

``

-

34

``

`-

/* Note only the following fields are used in hash and/or comparisons

`

35

``

`-

`

36

``

`-

`

37

``

`-

`

38

``

`-

`

39

``

`-

`

40

``

`-

`

41

``

`-

`

42

``

`-

`

43

``

`-

`

44

``

`-

`

45

``

`-

`

46

``

`-

`

47

``

`-

`

48

``

`-

`

49

``

`-

`

50

``

`-

`

51

``

`-

`

52

``

`-

`

53

``

`-

`

54

``

`-

*/

`

55

``

-

56

``

`-

/* These fields are set with provided values on new code objects. */

`

57

``

-

58

``

`-

// The hottest fields (in the eval loop) are grouped here at the top.

`

59

``

`-

PyObject co_consts; / list (constants used) */

`

60

``

`-

PyObject co_names; / list of strings (names used) */

`

61

``

`-

_Py_CODEUNIT co_firstinstr; / Pointer to first instruction, used for quickening.

`

62

``

`-

Unlike the other "hot" fields, this one is

`

63

``

`-

actually derived from co_code. */

`

64

``

`-

PyObject co_exceptiontable; / Byte string encoding exception handling table */

`

65

``

`-

int co_flags; /* CO_..., see below */

`

66

``

`-

int co_warmup; /* Warmup counter for quickening */

`

67

``

-

68

``

`-

// The rest are not so impactful on performance.

`

69

``

`-

int co_argcount; /* #arguments, except *args */

`

70

``

`-

int co_posonlyargcount; /* #positional only arguments */

`

71

``

`-

int co_kwonlyargcount; /* #keyword only arguments */

`

72

``

`-

int co_stacksize; /* #entries needed for evaluation stack */

`

73

``

`-

int co_firstlineno; /* first source line number */

`

74

``

`-

PyObject co_code; / instruction opcodes */

`

75

``

`-

PyObject co_localsplusnames; / tuple mapping offsets to names */

`

76

``

`-

PyObject co_localspluskinds; / Bytes mapping to local kinds (one byte per variable) */

`

77

``

`-

PyObject co_filename; / unicode (where it was loaded from) */

`

78

``

`-

PyObject co_name; / unicode (name, for reference) */

`

79

``

`-

PyObject co_qualname; / unicode (qualname, for reference) */

`

80

``

`-

PyObject co_linetable; / bytes (encoding addr<->lineno mapping) See

`

81

``

`-

Objects/lnotab_notes.txt for details. */

`

82

``

`-

PyObject co_endlinetable; / bytes object that holds end lineno for

`

83

``

`-

instructions separated across different

`

84

``

`-

lines */

`

85

``

`-

PyObject co_columntable; / bytes object that holds start/end column

`

86

``

`-

offset each instruction */

`

87

``

-

88

``

`-

/* These fields are set with computed values on new code objects. */

`

89

``

-

90

``

`-

// redundant values (derived from co_localsplusnames and co_localspluskinds)

`

91

``

`-

int co_nlocalsplus; /* number of local + cell + free variables */

`

92

``

`-

int co_nlocals; /* number of local variables */

`

93

``

`-

int co_nplaincellvars; /* number of non-arg cell variables */

`

94

``

`-

int co_ncellvars; /* total number of cell variables */

`

95

``

`-

int co_nfreevars; /* number of free variables */

`

96

``

`-

// lazily-computed values

`

97

``

`-

PyObject co_varnames; / tuple of strings (local variable names) */

`

98

``

`-

PyObject co_cellvars; / tuple of strings (cell variable names) */

`

99

``

`-

PyObject co_freevars; / tuple of strings (free variable names) */

`

100

``

-

101

``

`-

/* The remaining fields are zeroed out on new code objects. */

`

102

``

-

103

``

`-

PyObject co_weakreflist; / to support weakrefs to code objects */

`

104

``

`-

/* Scratch space for extra data relating to the code object.

`

105

``

`-

Type is a void* to keep the format private in codeobject.c to force

`

106

``

`-

people to go through the proper APIs. */

`

107

``

`-

void *co_extra;

`

108

``

`-

/* Quickened instructions and cache, or NULL

`

109

``

`-

This should be treated as opaque by all code except the specializer and

`

110

``

`-

interpreter. */

`

111

``

`-

_Py_CODEUNIT *co_quickened;

`

112

``

-

113

``

`-

};

`

``

102

`+

struct PyCodeObject _PyCode_DEF(1);

`

114

103

``

115

104

`/* Masks for co_flags above */

`

116

105

`#define CO_OPTIMIZED 0x0001

`

`@@ -151,6 +140,8 @@ PyAPI_DATA(PyTypeObject) PyCode_Type;

`

151

140

``

152

141

`#define PyCode_Check(op) Py_IS_TYPE(op, &PyCode_Type)

`

153

142

`#define PyCode_GetNumFree(op) ((op)->co_nfreevars)

`

``

143

`+

#define _PyCode_CODE(CO) ((_Py_CODEUNIT *)(CO)->co_code_adaptive)

`

``

144

`+

#define _PyCode_NBYTES(CO) (Py_SIZE(CO) * (Py_ssize_t)sizeof(_Py_CODEUNIT))

`

154

145

``

155

146

`/* Public interface */

`

156

147

`PyAPI_FUNC(PyCodeObject *) PyCode_New(

`