Skip to content

Commit ec50298

Browse files
committed
Merge branch 'main' into quickening-infrastructure
2 parents ecfa62b + 0d12f24 commit ec50298

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+5807
-6098
lines changed

Doc/library/contextlib.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ Functions and classes provided:
267267
.. function:: suppress(*exceptions)
268268

269269
Return a context manager that suppresses any of the specified exceptions
270-
if they are raised in the body of a :keyword:`!with` statement and then
270+
if they occur in the body of a :keyword:`!with` statement and then
271271
resumes execution with the first statement following the end of the
272272
:keyword:`!with` statement.
273273

Doc/library/dis.rst

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,24 +1058,17 @@ All of the following opcodes use their arguments.
10581058

10591059
.. opcode:: LOAD_CLOSURE (i)
10601060

1061-
Pushes a reference to the cell contained in slot ``i`` of the "fast locals"
1062-
storage. The name of the variable is ``co_fastlocalnames[i]``.
1063-
1064-
Note that ``LOAD_CLOSURE`` is effectively an alias for ``LOAD_FAST``.
1065-
It exists to keep bytecode a little more readable.
1066-
1067-
.. versionchanged:: 3.11
1068-
``i`` is no longer offset by the length of ``co_varnames``.
1061+
Pushes a reference to the cell contained in slot *i* of the cell and free
1062+
variable storage. The name of the variable is ``co_cellvars[i]`` if *i* is
1063+
less than the length of *co_cellvars*. Otherwise it is ``co_freevars[i -
1064+
len(co_cellvars)]``.
10691065

10701066

10711067
.. opcode:: LOAD_DEREF (i)
10721068

1073-
Loads the cell contained in slot ``i`` of the "fast locals" storage.
1069+
Loads the cell contained in slot *i* of the cell and free variable storage.
10741070
Pushes a reference to the object the cell contains on the stack.
10751071

1076-
.. versionchanged:: 3.11
1077-
``i`` is no longer offset by the length of ``co_varnames``.
1078-
10791072

10801073
.. opcode:: LOAD_CLASSDEREF (i)
10811074

@@ -1085,29 +1078,20 @@ All of the following opcodes use their arguments.
10851078

10861079
.. versionadded:: 3.4
10871080

1088-
.. versionchanged:: 3.11
1089-
``i`` is no longer offset by the length of ``co_varnames``.
1090-
10911081

10921082
.. opcode:: STORE_DEREF (i)
10931083

1094-
Stores TOS into the cell contained in slot ``i`` of the "fast locals"
1084+
Stores TOS into the cell contained in slot *i* of the cell and free variable
10951085
storage.
10961086

1097-
.. versionchanged:: 3.11
1098-
``i`` is no longer offset by the length of ``co_varnames``.
1099-
11001087

11011088
.. opcode:: DELETE_DEREF (i)
11021089

1103-
Empties the cell contained in slot ``i`` of the "fast locals" storage.
1090+
Empties the cell contained in slot *i* of the cell and free variable storage.
11041091
Used by the :keyword:`del` statement.
11051092

11061093
.. versionadded:: 3.2
11071094

1108-
.. versionchanged:: 3.11
1109-
``i`` is no longer offset by the length of ``co_varnames``.
1110-
11111095

11121096
.. opcode:: RAISE_VARARGS (argc)
11131097

Doc/license.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ W3C C14N test suite
955955
The C14N 2.0 test suite in the :mod:`test` package
956956
(``Lib/test/xmltestdata/c14n-20/``) was retrieved from the W3C website at
957957
https://www.w3.org/TR/xml-c14n2-testcases/ and is distributed under the
958-
3-clause BSD license:
958+
3-clause BSD license::
959959

960960
Copyright (c) 2013 W3C(R) (MIT, ERCIM, Keio, Beihang),
961961
All Rights Reserved.

Include/cpython/code.h

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
#endif
44

55
typedef uint16_t _Py_CODEUNIT;
6-
// Each oparg must fit in the second half of _Py_CODEUNIT, hence 8 bits.
7-
#define _Py_MAX_OPARG 255
86

97
#ifdef WORDS_BIGENDIAN
108
# define _Py_OPCODE(word) ((word) >> 8)
@@ -18,11 +16,6 @@ typedef uint16_t _Py_CODEUNIT;
1816

1917
typedef struct _PyOpcache _PyOpcache;
2018

21-
22-
// These are duplicated from pycore_code.h.
23-
typedef unsigned char _PyLocalsPlusKind;
24-
typedef _PyLocalsPlusKind *_PyLocalsPlusKinds;
25-
2619
/* Bytecode object */
2720
struct PyCodeObject {
2821
PyObject_HEAD
@@ -66,8 +59,9 @@ struct PyCodeObject {
6659
int co_stacksize; /* #entries needed for evaluation stack */
6760
int co_firstlineno; /* first source line number */
6861
PyObject *co_code; /* instruction opcodes */
69-
PyObject *co_localsplusnames; /* tuple mapping offsets to names */
70-
_PyLocalsPlusKinds co_localspluskinds; /* array mapping to local kinds */
62+
PyObject *co_varnames; /* tuple of strings (local variable names) */
63+
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
64+
PyObject *co_freevars; /* tuple of strings (free variable names) */
7165
PyObject *co_filename; /* unicode (where it was loaded from) */
7266
PyObject *co_name; /* unicode (name, for reference) */
7367
PyObject *co_linetable; /* string (encoding addr<->lineno mapping) See
@@ -76,15 +70,11 @@ struct PyCodeObject {
7670
/* These fields are set with computed values on new code objects. */
7771

7872
int *co_cell2arg; /* Maps cell vars which are arguments. */
79-
// redundant values (derived from co_localsplusnames and co_localspluskinds)
73+
// These are redundant but offer some performance benefit.
8074
int co_nlocalsplus; /* number of local + cell + free variables */
8175
int co_nlocals; /* number of local variables */
8276
int co_ncellvars; /* number of cell variables */
8377
int co_nfreevars; /* number of free variables */
84-
// lazily-computed values
85-
PyObject *co_varnames; /* tuple of strings (local variable names) */
86-
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
87-
PyObject *co_freevars; /* tuple of strings (free variable names) */
8878

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

@@ -162,7 +152,7 @@ struct PyCodeObject {
162152
PyAPI_DATA(PyTypeObject) PyCode_Type;
163153

164154
#define PyCode_Check(op) Py_IS_TYPE(op, &PyCode_Type)
165-
#define PyCode_GetNumFree(op) ((op)->co_nfreevars)
155+
#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars))
166156

167157
/* Public interface */
168158
PyAPI_FUNC(PyCodeObject *) PyCode_New(

Include/internal/pycore_code.h

Lines changed: 3 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -149,57 +149,6 @@ PyCodeObject_IsWarmedUp(PyCodeObject * co)
149149
int _Py_Quicken(PyCodeObject *code);
150150

151151

152-
/* "Locals plus" for a code object is the set of locals + cell vars +
153-
* free vars. This relates to variable names as well as offsets into
154-
* the "fast locals" storage array of execution frames. The compiler
155-
* builds the list of names, their offsets, and the corresponding
156-
* kind of local.
157-
*
158-
* Those kinds represent the source of the initial value and the
159-
* variable's scope (as related to closures). A "local" is an
160-
* argument or other variable defined in the current scope. A "free"
161-
* variable is one that is defined in an outer scope and comes from
162-
* the function's closure. A "cell" variable is a local that escapes
163-
* into an inner function as part of a closure, and thus must be
164-
* wrapped in a cell. Any "local" can also be a "cell", but the
165-
* "free" kind is mutually exclusive with both.
166-
*/
167-
168-
// We would use an enum if C let us specify the storage type.
169-
typedef unsigned char _PyLocalsPlusKind;
170-
/* Note that these all fit within _PyLocalsPlusKind, as do combinations. */
171-
// Later, we will use the smaller numbers to differentiate the different
172-
// kinds of locals (e.g. pos-only arg, varkwargs, local-only).
173-
#define CO_FAST_LOCAL 0x20
174-
#define CO_FAST_CELL 0x40
175-
#define CO_FAST_FREE 0x80
176-
177-
typedef _PyLocalsPlusKind *_PyLocalsPlusKinds;
178-
179-
static inline int
180-
_PyCode_InitLocalsPlusKinds(int num, _PyLocalsPlusKinds *pkinds)
181-
{
182-
if (num == 0) {
183-
*pkinds = NULL;
184-
return 0;
185-
}
186-
_PyLocalsPlusKinds kinds = PyMem_NEW(_PyLocalsPlusKind, num);
187-
if (kinds == NULL) {
188-
PyErr_NoMemory();
189-
return -1;
190-
}
191-
*pkinds = kinds;
192-
return 0;
193-
}
194-
195-
static inline void
196-
_PyCode_ClearLocalsPlusKinds(_PyLocalsPlusKinds kinds)
197-
{
198-
if (kinds != NULL) {
199-
PyMem_Free(kinds);
200-
}
201-
}
202-
203152
struct _PyCodeConstructor {
204153
/* metadata */
205154
PyObject *filename;
@@ -216,13 +165,13 @@ struct _PyCodeConstructor {
216165
PyObject *names;
217166

218167
/* mapping frame offsets to information */
219-
PyObject *localsplusnames;
220-
_PyLocalsPlusKinds localspluskinds;
168+
PyObject *varnames;
169+
PyObject *cellvars;
170+
PyObject *freevars;
221171

222172
/* args (within varnames) */
223173
int argcount;
224174
int posonlyargcount;
225-
// XXX Replace argcount with posorkwargcount (argcount - posonlyargcount).
226175
int kwonlyargcount;
227176

228177
/* needed to create the frame */
@@ -249,11 +198,6 @@ PyAPI_FUNC(PyCodeObject *) _PyCode_New(struct _PyCodeConstructor *);
249198

250199
int _PyCode_InitOpcache(PyCodeObject *co);
251200

252-
/* Getters for internal PyCodeObject data. */
253-
PyAPI_FUNC(PyObject *) _PyCode_GetVarnames(PyCodeObject *);
254-
PyAPI_FUNC(PyObject *) _PyCode_GetCellvars(PyCodeObject *);
255-
PyAPI_FUNC(PyObject *) _PyCode_GetFreevars(PyCodeObject *);
256-
257201

258202
#ifdef __cplusplus
259203
}

Lib/ctypes/test/test_values.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ class struct_frozen(Structure):
8080
continue
8181
items.append((entry.name.decode("ascii"), entry.size))
8282

83-
expected = [("__hello__", 128),
84-
("__phello__", -128),
85-
("__phello__.spam", 128),
83+
expected = [("__hello__", 138),
84+
("__phello__", -138),
85+
("__phello__.spam", 138),
8686
]
8787
self.assertEqual(items, expected, "PyImport_FrozenModules example "
8888
"in Doc/library/ctypes.rst may be out of date")

Lib/dis.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -273,15 +273,15 @@ def get_instructions(x, *, first_line=None):
273273
the disassembled code object.
274274
"""
275275
co = _get_code_object(x)
276+
cell_names = co.co_cellvars + co.co_freevars
276277
linestarts = dict(findlinestarts(co))
277278
if first_line is not None:
278279
line_offset = first_line - co.co_firstlineno
279280
else:
280281
line_offset = 0
281-
return _get_instructions_bytes(co.co_code,
282-
co._varname_from_oparg,
283-
co.co_names, co.co_consts,
284-
linestarts, line_offset)
282+
return _get_instructions_bytes(co.co_code, co.co_varnames, co.co_names,
283+
co.co_consts, cell_names, linestarts,
284+
line_offset)
285285

286286
def _get_const_info(const_index, const_list):
287287
"""Helper to get optional details about const references
@@ -295,16 +295,16 @@ def _get_const_info(const_index, const_list):
295295
argval = const_list[const_index]
296296
return argval, repr(argval)
297297

298-
def _get_name_info(name_index, get_name, **extrainfo):
298+
def _get_name_info(name_index, name_list):
299299
"""Helper to get optional details about named references
300300
301301
Returns the dereferenced name as both value and repr if the name
302302
list is defined.
303303
Otherwise returns the name index and its repr().
304304
"""
305305
argval = name_index
306-
if get_name is not None:
307-
argval = get_name(name_index, **extrainfo)
306+
if name_list is not None:
307+
argval = name_list[name_index]
308308
argrepr = argval
309309
else:
310310
argrepr = repr(argval)
@@ -336,10 +336,8 @@ def parse_exception_table(code):
336336
except StopIteration:
337337
return entries
338338

339-
def _get_instructions_bytes(code, varname_from_oparg=None,
340-
names=None, constants=None,
341-
linestarts=None, line_offset=0,
342-
exception_entries=()):
339+
def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
340+
cells=None, linestarts=None, line_offset=0, exception_entries=()):
343341
"""Iterate over the instructions in a bytecode string.
344342
345343
Generates a sequence of Instruction namedtuples giving the details of each
@@ -348,7 +346,6 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
348346
arguments.
349347
350348
"""
351-
get_name = None if names is None else names.__getitem__
352349
labels = set(findlabels(code))
353350
for start, end, target, _, _ in exception_entries:
354351
for i in range(start, end):
@@ -371,18 +368,20 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
371368
if op in hasconst:
372369
argval, argrepr = _get_const_info(arg, constants)
373370
elif op in hasname:
374-
argval, argrepr = _get_name_info(arg, get_name)
371+
argval, argrepr = _get_name_info(arg, names)
375372
elif op in hasjabs:
376373
argval = arg*2
377374
argrepr = "to " + repr(argval)
378375
elif op in hasjrel:
379376
argval = offset + 2 + arg*2
380377
argrepr = "to " + repr(argval)
381-
elif op in haslocal or op in hasfree:
382-
argval, argrepr = _get_name_info(arg, varname_from_oparg)
378+
elif op in haslocal:
379+
argval, argrepr = _get_name_info(arg, varnames)
383380
elif op in hascompare:
384381
argval = cmp_op[arg]
385382
argrepr = argval
383+
elif op in hasfree:
384+
argval, argrepr = _get_name_info(arg, cells)
386385
elif op == FORMAT_VALUE:
387386
argval, argrepr = FORMAT_VALUE_CONVERTERS[arg & 0x3]
388387
argval = (argval, bool(arg & 0x4))
@@ -399,11 +398,11 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
399398

400399
def disassemble(co, lasti=-1, *, file=None):
401400
"""Disassemble a code object."""
401+
cell_names = co.co_cellvars + co.co_freevars
402402
linestarts = dict(findlinestarts(co))
403403
exception_entries = parse_exception_table(co)
404-
_disassemble_bytes(co.co_code, lasti,
405-
co._varname_from_oparg,
406-
co.co_names, co.co_consts, linestarts, file=file,
404+
_disassemble_bytes(co.co_code, lasti, co.co_varnames, co.co_names,
405+
co.co_consts, cell_names, linestarts, file=file,
407406
exception_entries=exception_entries)
408407

409408
def _disassemble_recursive(co, *, file=None, depth=None):
@@ -417,8 +416,8 @@ def _disassemble_recursive(co, *, file=None, depth=None):
417416
print("Disassembly of %r:" % (x,), file=file)
418417
_disassemble_recursive(x, file=file, depth=depth)
419418

420-
def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
421-
names=None, constants=None, linestarts=None,
419+
def _disassemble_bytes(code, lasti=-1, varnames=None, names=None,
420+
constants=None, cells=None, linestarts=None,
422421
*, file=None, line_offset=0, exception_entries=()):
423422
# Omit the line number column entirely if we have no line number info
424423
show_lineno = bool(linestarts)
@@ -435,8 +434,8 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
435434
offset_width = len(str(maxoffset))
436435
else:
437436
offset_width = 4
438-
for instr in _get_instructions_bytes(code, varname_from_oparg, names,
439-
constants, linestarts,
437+
for instr in _get_instructions_bytes(code, varnames, names,
438+
constants, cells, linestarts,
440439
line_offset=line_offset, exception_entries=exception_entries):
441440
new_source_line = (show_lineno and
442441
instr.starts_line is not None and
@@ -518,16 +517,16 @@ def __init__(self, x, *, first_line=None, current_offset=None):
518517
else:
519518
self.first_line = first_line
520519
self._line_offset = first_line - co.co_firstlineno
520+
self._cell_names = co.co_cellvars + co.co_freevars
521521
self._linestarts = dict(findlinestarts(co))
522522
self._original_object = x
523523
self.current_offset = current_offset
524524
self.exception_entries = parse_exception_table(co)
525525

526526
def __iter__(self):
527527
co = self.codeobj
528-
return _get_instructions_bytes(co.co_code,
529-
co._varname_from_oparg,
530-
co.co_names, co.co_consts,
528+
return _get_instructions_bytes(co.co_code, co.co_varnames, co.co_names,
529+
co.co_consts, self._cell_names,
531530
self._linestarts,
532531
line_offset=self._line_offset,
533532
exception_entries=self.exception_entries)
@@ -555,9 +554,9 @@ def dis(self):
555554
else:
556555
offset = -1
557556
with io.StringIO() as output:
558-
_disassemble_bytes(co.co_code,
559-
varname_from_oparg=co._varname_from_oparg,
557+
_disassemble_bytes(co.co_code, varnames=co.co_varnames,
560558
names=co.co_names, constants=co.co_consts,
559+
cells=self._cell_names,
561560
linestarts=self._linestarts,
562561
line_offset=self._line_offset,
563562
file=output,

0 commit comments

Comments
 (0)