Skip to content

Commit e402b26

Browse files
authored
GH-95113: Don't use EXTENDED_ARG_QUICK in unquickened code (GH-95121)
1 parent 79d2f54 commit e402b26

File tree

8 files changed

+20
-200
lines changed

8 files changed

+20
-200
lines changed

Include/internal/pycore_opcode.h

Lines changed: 0 additions & 188 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_dis.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ def extended_arg_quick():
744744
%3d 0 RESUME 0
745745
746746
%3d 2 LOAD_CONST 1 (Ellipsis)
747-
4 EXTENDED_ARG_QUICK 1
747+
4 EXTENDED_ARG 1
748748
6 UNPACK_EX 256
749749
8 STORE_FAST 0 (_)
750750
10 STORE_FAST 0 (_)
Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,7 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
14181418
{
14191419
for (int i = 0; i < len; i++) {
14201420
_Py_CODEUNIT instruction = instructions[i];
1421-
int opcode = _PyOpcode_Original[_Py_OPCODE(instruction)];
1421+
int opcode = _PyOpcode_Deopt[_Py_OPCODE(instruction)];
14221422
int caches = _PyOpcode_Caches[opcode];
14231423
instructions[i] = _Py_MAKECODEUNIT(opcode, _Py_OPARG(instruction));
14241424
while (caches--) {

Python/ceval.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5631,8 +5631,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
56315631
assert(oparg);
56325632
oparg <<= 8;
56335633
oparg |= _Py_OPARG(*next_instr);
5634+
// We might be tracing. To avoid breaking tracing guarantees in
5635+
// quickened instructions, always deoptimize the next opcode:
56345636
opcode = _PyOpcode_Deopt[_Py_OPCODE(*next_instr)];
56355637
PRE_DISPATCH_GOTO();
5638+
// CPython hasn't traced the following instruction historically
5639+
// (DO_TRACING would clobber our extended oparg anyways), so just
5640+
// skip our usual cframe.use_tracing check before dispatch. Also,
5641+
// make sure the next instruction isn't a RESUME, since that needs
5642+
// to trace properly (and shouldn't have an extended arg anyways):
5643+
assert(opcode != RESUME);
56365644
DISPATCH_GOTO();
56375645
}
56385646

Python/compile.c

Lines changed: 3 additions & 3 deletions
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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ _PyCode_Quicken(PyCodeObject *code)
295295
else {
296296
assert(!_PyOpcode_Caches[opcode]);
297297
switch (opcode) {
298+
case EXTENDED_ARG:
299+
_Py_SET_OPCODE(instructions[i], EXTENDED_ARG_QUICK);
300+
break;
298301
case JUMP_BACKWARD:
299302
_Py_SET_OPCODE(instructions[i], JUMP_BACKWARD_QUICK);
300303
break;

Tools/scripts/generate_opcode_h.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
131131

132132
iobj.write("\nextern const uint8_t _PyOpcode_Caches[256];\n")
133133
iobj.write("\nextern const uint8_t _PyOpcode_Deopt[256];\n")
134-
iobj.write("\nextern const uint8_t _PyOpcode_Original[256];\n")
135134
iobj.write("\n#ifdef NEED_OPCODE_TABLES\n")
136135
write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], iobj)
137136
write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], iobj)
@@ -153,12 +152,6 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
153152
for opt, deopt in sorted(deoptcodes.items()):
154153
iobj.write(f" [{opt}] = {deopt},\n")
155154
iobj.write("};\n")
156-
iobj.write("\nconst uint8_t _PyOpcode_Original[256] = {\n")
157-
for opt, deopt in sorted(deoptcodes.items()):
158-
if opt.startswith("EXTENDED_ARG"):
159-
deopt = "EXTENDED_ARG_QUICK"
160-
iobj.write(f" [{opt}] = {deopt},\n")
161-
iobj.write("};\n")
162155
iobj.write("#endif // NEED_OPCODE_TABLES\n")
163156

164157
fobj.write("\n")

0 commit comments

Comments
 (0)