Skip to content

Commit 5a48ab0

Browse files
authored
[3.11] GH-95113: Don't use EXTENDED_ARG_QUICK in unquickened code (GH-95121) (GH-95143)
(cherry picked from commit e402b26)
1 parent e99496e commit 5a48ab0

File tree

8 files changed

+20
-198
lines changed

8 files changed

+20
-198
lines changed

Include/internal/pycore_opcode.h

-186
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_dis.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ def extended_arg_quick():
638638
%3d 0 RESUME 0
639639
640640
%3d 2 LOAD_CONST 1 (Ellipsis)
641-
4 EXTENDED_ARG_QUICK 1
641+
4 EXTENDED_ARG 1
642642
6 UNPACK_EX 256
643643
8 STORE_FAST 0 (_)
644644
10 STORE_FAST 0 (_)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Replace all ``EXTENDED_ARG_QUICK`` instructions with basic
2+
:opcode:`EXTENDED_ARG` instructions in unquickened code. Consumers of
3+
non-adaptive bytecode should be able to handle extended arguments the same
4+
way they were handled in CPython 3.10 and older.

Objects/codeobject.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1416,7 +1416,7 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
14161416
{
14171417
for (int i = 0; i < len; i++) {
14181418
_Py_CODEUNIT instruction = instructions[i];
1419-
int opcode = _PyOpcode_Original[_Py_OPCODE(instruction)];
1419+
int opcode = _PyOpcode_Deopt[_Py_OPCODE(instruction)];
14201420
int caches = _PyOpcode_Caches[opcode];
14211421
instructions[i] = _Py_MAKECODEUNIT(opcode, _Py_OPARG(instruction));
14221422
while (caches--) {

Python/ceval.c

+8
Original file line numberDiff line numberDiff line change
@@ -5590,8 +5590,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
55905590
assert(oparg);
55915591
oparg <<= 8;
55925592
oparg |= _Py_OPARG(*next_instr);
5593+
// We might be tracing. To avoid breaking tracing guarantees in
5594+
// quickened instructions, always deoptimize the next opcode:
55935595
opcode = _PyOpcode_Deopt[_Py_OPCODE(*next_instr)];
55945596
PRE_DISPATCH_GOTO();
5597+
// CPython hasn't traced the following instruction historically
5598+
// (DO_TRACING would clobber our extended oparg anyways), so just
5599+
// skip our usual cframe.use_tracing check before dispatch. Also,
5600+
// make sure the next instruction isn't a RESUME, since that needs
5601+
// to trace properly (and shouldn't have an extended arg anyways):
5602+
assert(opcode != RESUME);
55955603
DISPATCH_GOTO();
55965604
}
55975605

Python/compile.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -211,13 +211,13 @@ write_instr(_Py_CODEUNIT *codestr, struct instr *instruction, int ilen)
211211
int caches = _PyOpcode_Caches[opcode];
212212
switch (ilen - caches) {
213213
case 4:
214-
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG_QUICK, (oparg >> 24) & 0xFF);
214+
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 24) & 0xFF);
215215
/* fall through */
216216
case 3:
217-
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG_QUICK, (oparg >> 16) & 0xFF);
217+
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 16) & 0xFF);
218218
/* fall through */
219219
case 2:
220-
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG_QUICK, (oparg >> 8) & 0xFF);
220+
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 8) & 0xFF);
221221
/* fall through */
222222
case 1:
223223
*codestr++ = _Py_MAKECODEUNIT(opcode, oparg & 0xFF);

Python/specialize.c

+3
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ _PyCode_Quicken(PyCodeObject *code)
275275
else {
276276
assert(!_PyOpcode_Caches[opcode]);
277277
switch (opcode) {
278+
case EXTENDED_ARG:
279+
_Py_SET_OPCODE(instructions[i], EXTENDED_ARG_QUICK);
280+
break;
278281
case JUMP_BACKWARD:
279282
_Py_SET_OPCODE(instructions[i], JUMP_BACKWARD_QUICK);
280283
break;

Tools/scripts/generate_opcode_h.py

-7
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
117117

118118
iobj.write("\nextern const uint8_t _PyOpcode_Caches[256];\n")
119119
iobj.write("\nextern const uint8_t _PyOpcode_Deopt[256];\n")
120-
iobj.write("\nextern const uint8_t _PyOpcode_Original[256];\n")
121120
iobj.write("\n#ifdef NEED_OPCODE_TABLES\n")
122121
write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], iobj)
123122
write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], iobj)
@@ -138,12 +137,6 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
138137
for opt, deopt in sorted(deoptcodes.items()):
139138
iobj.write(f" [{opt}] = {deopt},\n")
140139
iobj.write("};\n")
141-
iobj.write("\nconst uint8_t _PyOpcode_Original[256] = {\n")
142-
for opt, deopt in sorted(deoptcodes.items()):
143-
if opt.startswith("EXTENDED_ARG"):
144-
deopt = "EXTENDED_ARG_QUICK"
145-
iobj.write(f" [{opt}] = {deopt},\n")
146-
iobj.write("};\n")
147140
iobj.write("#endif // NEED_OPCODE_TABLES\n")
148141

149142
fobj.write("\n")

0 commit comments

Comments
 (0)