Skip to content

Commit f89e102

Browse files
author
rocky
committed
Bang on 3.14 stack effects...
Reinstate stackeffect check partially for 3.14 Note we support 3.14 in pyproject.toml Mark VARYING_INT parameters
1 parent e203d6b commit f89e102

File tree

11 files changed

+47
-38
lines changed

11 files changed

+47
-38
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ classifiers = [
4242
"Programming Language :: Python :: 3.11",
4343
"Programming Language :: Python :: 3.12",
4444
"Programming Language :: Python :: 3.13",
45+
"Programming Language :: Python :: 3.14",
4546
]
4647
dynamic = ["version"]
4748

pytest/test_stack_effect.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,13 @@ def test_stack_effect_fixed() -> None:
9090
xdis.PYTHON_VERSION_TRIPLE < (3, 4) or xdis.IS_PYPY or xdis.IS_GRAAL,
9191
reason="Python version is before 3.4. Can't test",
9292
)
93-
@pytest.mark.skipif(
94-
xdis.PYTHON_VERSION_TRIPLE >= (3, 14),
95-
reason="Python >= 3.14 is not complete.",
96-
)
9793
def test_stack_effect_vs_dis() -> None:
9894
import dis
9995

10096
def test_one(xdis_args, dis_args, has_arg: bool) -> None:
97+
98+
if opname.startswith("INSTRUMENTED"):
99+
return
101100
effect = xstack_effect(*xdis_args)
102101
try:
103102
check_effect = dis.stack_effect(*dis_args[:2])
@@ -148,6 +147,8 @@ def test_one(xdis_args, dis_args, has_arg: bool) -> None:
148147
and opcode in opc.CONDITION_OPS
149148
and opname
150149
not in (
150+
"INSTRUMENTED_POP_JUMP_IF_FALSE",
151+
"INSTRUMENTED_POP_JUMP_IF_TRUE",
151152
"JUMP_IF_FALSE_OR_POP",
152153
"JUMP_IF_TRUE_OR_POP",
153154
"POP_JUMP_IF_FALSE",

xdis/cross_dis.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -468,16 +468,20 @@ def xstack_effect(opcode, opc, oparg: int = 0, jump=None):
468468
version_tuple = opc.version_tuple
469469
pop, push = opc.oppop[opcode], opc.oppush[opcode]
470470
opname = opc.opname[opcode]
471-
if opname in "BUILD_CONST_KEY_MAP" and version_tuple >= (3, 12):
472-
return -oparg
473-
if opname == "BUILD_MAP" and version_tuple >= (3, 5):
474-
return 1 - (2 * oparg)
475-
elif opname in ("UNPACK_SEQUENCE", "UNPACK_EX") and version_tuple >= (3, 0):
476-
return (oparg & 0xFF) + (oparg >> 8)
477-
elif opname == "BUILD_INTERPOLATION":
478-
# 3.14+ only
479-
return -2 if oparg & 1 else -1
480-
elif opname in (
471+
if version_tuple >= (3, 0):
472+
if opname in "BUILD_CONST_KEY_MAP" and version_tuple >= (3, 12):
473+
return -oparg
474+
if opname == "BUILD_MAP" and version_tuple >= (3, 5):
475+
return 1 - (2 * oparg)
476+
if opname in ("UNPACK_SEQUENCE",):
477+
return oparg - 1
478+
elif opname in ("UNPACK_EX"):
479+
return (oparg & 0xFF) + (oparg >> 8)
480+
elif opname == "BUILD_INTERPOLATION":
481+
# 3.14+ only
482+
return -2 if oparg & 1 else -1
483+
484+
if opname in (
481485
"BUILD_LIST",
482486
"BUILD_SET",
483487
"BUILD_STRING",
@@ -501,9 +505,9 @@ def xstack_effect(opcode, opc, oparg: int = 0, jump=None):
501505
return None
502506
else:
503507
return None
504-
elif opname == "CALL" and version_tuple >= (3, 12):
508+
elif opname in ("CALL", "INSTRUMENTED_CALL") and version_tuple >= (3, 12):
505509
return -oparg - 1
506-
elif opname == "CALL_KW":
510+
elif opname in ("CALL_KW", "INSTRUMENTED_CALL_KW"):
507511
return -2 - oparg
508512
elif opname == "CALL_FUNCTION_EX":
509513
if version_tuple >= (3, 14):
@@ -518,6 +522,8 @@ def xstack_effect(opcode, opc, oparg: int = 0, jump=None):
518522
"INSTRUMENTED_LOAD_SUPER_ATTR",
519523
"LOAD_SUPER_ATTR",
520524
) and version_tuple >= (3, 12):
525+
if opname == "INSTRUMENTED_LOAD_SUPER_ATTR" and version_tuple >= (3, 14):
526+
return -2
521527
return -1 if oparg & 1 else -2
522528
elif opname == "LOAD_GLOBAL" and version_tuple >= (3, 11):
523529
return 2 if oparg & 1 else 1

xdis/opcodes/opcode_2x.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# (C) Copyright 2018, 2020-2024 by Rocky Bernstein
1+
# (C) Copyright 2018, 2020-2025 by Rocky Bernstein
22
#
33
# This program is free software; you can redistribute it and/or
44
# modify it under the terms of the GNU General Public License
@@ -25,6 +25,7 @@
2525
from typing import Optional, Tuple
2626

2727
from xdis.opcodes.base import (
28+
VARYING_STACK_INT,
2829
binary_op,
2930
call_op,
3031
compare_op,
@@ -152,7 +153,7 @@
152153
store_op(loc, "STORE_NAME", 90, 1, 0, is_type="name")
153154
# Operand is in name list
154155
name_op(loc, "DELETE_NAME", 91, 0, 0) # ""
155-
varargs_op(loc, "UNPACK_SEQUENCE", 92, -1, 1) # TOS is number of tuple items
156+
varargs_op(loc, "UNPACK_SEQUENCE", 92, 1, VARYING_STACK_INT) # TOS is number of tuple items
156157
jrel_op(loc, "FOR_ITER", 93, 0, 1) # TOS is read
157158

158159
store_op(loc, "STORE_ATTR", 95, 2, 0, is_type="name")

xdis/opcodes/opcode_310graal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@
461461
# Pushed: unpacked items, the count is determined by the immediate operand
462462
#
463463
def_op_graal(
464-
loc, "UNPACK_SEQUENCE", 0x47, 1, 1, 1
464+
loc, "UNPACK_SEQUENCE", 0x47, 1, 1, VARYING_STACK_INT
465465
) # , (oparg, followingArgs, withJump) -> oparg)
466466

467467
# Unpacks an iterable into multiple stack items with a star item that gets the rest. The first

xdis/opcodes/opcode_311graal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@
479479
# Pushed: unpacked items, the count is determined by the immediate operand
480480
#
481481
def_op_graal(
482-
loc, "UNPACK_SEQUENCE", 0x47, 1, 1, 1
482+
loc, "UNPACK_SEQUENCE", 0x47, 1, VARYING_STACK_INT, 1
483483
) # , (oparg, followingArgs, withJump) -> oparg)
484484

485485
# Unpacks an iterable into multiple stack items with a star item that gets the rest. The first
@@ -492,7 +492,7 @@
492492
# operand)
493493
#
494494
def_op_graal(
495-
loc, "UNPACK_EX", 0x48, 2, VARYING_STACK_INT, VARYING_STACK_INT
495+
loc, "UNPACK_EX", 0x48, VARYING_STACK_INT, VARYING_STACK_INT, 2
496496
) # (oparg, followingArgs, withJump) -> oparg + 1 + Byte.toUnsignedInt(followingArgs[0]))
497497

498498
# jumps

xdis/opcodes/opcode_312graal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@
472472
# Pushed: unpacked items, the count is determined by the immediate operand
473473
#
474474
def_op_graal(
475-
loc, "UNPACK_SEQUENCE", 0x49, 1, 1, 1
475+
loc, "UNPACK_SEQUENCE", 0x49, 1, VARYING_STACK_INT, 1
476476
) # , (oparg, followingArgs, withJump) -> oparg)
477477

478478
# Unpacks an iterable into multiple stack items with a star item that gets the rest. The first
@@ -485,7 +485,7 @@
485485
# operand)
486486
#
487487
def_op_graal(
488-
loc, "UNPACK_EX", 0x4a, 2, VARYING_STACK_INT, VARYING_STACK_INT
488+
loc, "UNPACK_EX", 0x4a, VARYING_STACK_INT, VARYING_STACK_INT, 1
489489
) # (oparg, followingArgs, withJump) -> oparg + 1 + Byte.toUnsignedInt(followingArgs[0]))
490490

491491
# jumps

xdis/opcodes/opcode_312rust.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77

88
from typing import Dict, List, Optional, Tuple
99

10-
from opcodes.base import VARYING_STACK_INT
11-
12-
import xdis.opcodes.opcode_313 as opcode_313
1310
from xdis.opcodes.base import (
11+
VARYING_STACK_INT,
1412
binary_op,
1513
compare_op,
1614
const_op,
@@ -25,6 +23,7 @@
2523
store_op,
2624
unary_op,
2725
update_pj3,
26+
varargs_op,
2827
)
2928
from xdis.opcodes.format.extended import extended_format_binary_op
3029
from xdis.opcodes.opcode_312 import opcode_arg_fmt312, opcode_extended_fmt312
@@ -174,7 +173,7 @@ def pseudo_op(name: str, op: int, real_ops: list):
174173

175174
name_op(loc, "STORE_NAME", 90) # Index in name list
176175
name_op(loc, "DELETE_NAME", 91) # ""
177-
def_op(loc, "UNPACK_SEQUENCE", 92) # Number of tuple items
176+
varargs_op(loc, "UNPACK_SEQUENCE", 92, 1, VARYING_STACK_INT) # Number of tuple items
178177
jrel_op(loc, "FOR_ITER", 93)
179178
def_op(loc, "UNPACK_EX", 94, VARYING_STACK_INT, VARYING_STACK_INT)
180179
name_op(loc, "STORE_ATTR", 95) # Index in name list

xdis/opcodes/opcode_314.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
varargs_op(loc, "BUILD_SLICE", 49, -1, 1) # TOS is slice
8989
varargs_op(loc, "BUILD_STRING", 50, -1, 1) # TOS is concatenated strings
9090
varargs_op(loc, "BUILD_TUPLE", 51, -1, 1) # TOS is count of tuple items
91-
call_op(loc, "CALL", 52, -2, 1) # pops 2 + oparg; TOS is return value
91+
call_op(loc, "CALL", 52, VARYING_STACK_INT, 2) # pops 2 + oparg; TOS is return value
9292
def_op(loc, "CALL_INTRINSIC_1", 53, 1, 1)
9393
def_op(loc, "CALL_INTRINSIC_2", 54, 2, 1)
9494
call_op(loc, "CALL_KW", 55, -3, 1) # pops 3 + oparg; TOS is return value
@@ -155,7 +155,7 @@
155155
store_op(loc, "STORE_NAME", 116, 1, 0, is_type="name")
156156
def_op(loc, "SWAP", 117, 0, 0)
157157
varargs_op(loc, "UNPACK_EX", 118, VARYING_STACK_INT, VARYING_STACK_INT) # pushes 1 + (oparg & 0xFF) + (oparg >> 8)
158-
varargs_op(loc, "UNPACK_SEQUENCE", 119, VARYING_STACK_INT, VARYING_STACK_INT) # unpacks TOS, arg is the count
158+
varargs_op(loc, "UNPACK_SEQUENCE", 119, 1, VARYING_STACK_INT) # unpacks TOS, arg is the count
159159
def_op(loc, "YIELD_VALUE", 120, 1, 1)
160160
def_op(loc, "RESUME", 128, 0, 0)
161161

@@ -242,21 +242,21 @@
242242
varargs_op(loc, "UNPACK_SEQUENCE_TUPLE", 208, 1, -1)
243243
def_op(loc, "UNPACK_SEQUENCE_TWO_TUPLE", 209, 1, 2)
244244
def_op(loc, "INSTRUMENTED_END_FOR", 233, 3, 2)
245-
def_op(loc, "INSTRUMENTED_POP_ITER", 234, 2, 0)
245+
def_op(loc, "INSTRUMENTED_POP_ITER", 234, 1, 0)
246246
def_op(loc, "INSTRUMENTED_END_SEND", 235, 2, 1)
247-
jrel_op(loc, "INSTRUMENTED_FOR_ITER", 236, 2, 3, conditional=True)
248-
def_op(loc, "INSTRUMENTED_INSTRUCTION", 237, 0, 0)
247+
jrel_op(loc, "INSTRUMENTED_FOR_ITER", 236, 2, 1, conditional=True)
248+
def_op(loc, "INSTRUMENTED_INSTRUCTION", 237, 0, 1)
249249
jrel_op(loc, "INSTRUMENTED_JUMP_FORWARD", 238, 0, 0, conditional=False)
250250
def_op(loc, "INSTRUMENTED_NOT_TAKEN", 239, 0, 0)
251-
jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_TRUE", 240, 1, 0, conditional=True)
251+
jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_TRUE", 240, 0, 0, conditional=True) # dunno why it's not 1, 0.
252252
jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_FALSE", 241, 1, 0, conditional=True)
253253
jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_NONE", 242, 1, 0, conditional=True)
254254
jrel_op(loc, "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", 243, 1, 0, conditional=True)
255-
def_op(loc, "INSTRUMENTED_RESUME", 244, 0, 0)
255+
def_op(loc, "INSTRUMENTED_RESUME", 244, 1, 0) # dunno why it's not 0, 0.
256256
def_op(loc, "INSTRUMENTED_RETURN_VALUE", 245, 1, 1)
257257
def_op(loc, "INSTRUMENTED_YIELD_VALUE", 246, 1, 1)
258-
jrel_op(loc, "INSTRUMENTED_END_ASYNC_FOR", 247, 2, 0, conditional=True)
259-
name_op(loc, "INSTRUMENTED_LOAD_SUPER_ATTR", 248, 3, 1) # pushes 1 + (oparg & 1)
258+
jrel_op(loc, "INSTRUMENTED_END_ASYNC_FOR", 247, 0, 0, conditional=True) # dunnow why it's not 2, 0
259+
name_op(loc, "INSTRUMENTED_LOAD_SUPER_ATTR", 248, VARYING_STACK_INT, 1) # pushes 1 + (oparg & 1)
260260
call_op(loc, "INSTRUMENTED_CALL", 249, -2, 1)
261261
call_op(loc, "INSTRUMENTED_CALL_KW", 250, -3, 1)
262262
def_op(loc, "INSTRUMENTED_CALL_FUNCTION_EX", 251, 4, 1)

xdis/opcodes/opcode_38graal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@
422422
# Pushed: unpacked items, the count is determined by the immediate operand
423423
#
424424
def_op_graal(
425-
loc, "UNPACK_SEQUENCE", 0x3C, 1, 1, 1
425+
loc, "UNPACK_SEQUENCE", 0x3C, 1, 1, VARYING_STACK_INT
426426
) # , (oparg, followingArgs, withJump) -> oparg)
427427

428428
# Unpacks an iterable into multiple stack items with a star item that gets the rest. The first

0 commit comments

Comments
 (0)