|
| 1 | +import ast |
1 | 2 | import dis |
2 | 3 | import gc |
3 | 4 | from itertools import combinations, product |
@@ -1119,6 +1120,53 @@ def trace(frame, event, arg): |
1119 | 1120 |
|
1120 | 1121 | class DirectCfgOptimizerTests(CfgOptimizationTestCase): |
1121 | 1122 |
|
| 1123 | + def test_optimize_cfg_const_index_out_of_range(self): |
| 1124 | + insts = [ |
| 1125 | + ('LOAD_CONST', 2, 0), |
| 1126 | + ('RETURN_VALUE', None, 0), |
| 1127 | + ] |
| 1128 | + seq = self.seq_from_insts(insts) |
| 1129 | + with self.assertRaisesRegex(ValueError, "out of range"): |
| 1130 | + _testinternalcapi.optimize_cfg(seq, [0, 1], 0) |
| 1131 | + |
| 1132 | + def test_optimize_cfg_consts_must_be_list(self): |
| 1133 | + insts = [ |
| 1134 | + ('LOAD_CONST', 0, 0), |
| 1135 | + ('RETURN_VALUE', None, 0), |
| 1136 | + ] |
| 1137 | + seq = self.seq_from_insts(insts) |
| 1138 | + with self.assertRaisesRegex(TypeError, "consts must be a list"): |
| 1139 | + _testinternalcapi.optimize_cfg(seq, (0,), 0) |
| 1140 | + |
| 1141 | + def test_compiler_codegen_metadata_consts_roundtrips_optimize_cfg(self): |
| 1142 | + tree = ast.parse("x = (1, 2)", mode="exec", optimize=1) |
| 1143 | + insts, meta = _testinternalcapi.compiler_codegen(tree, "<s>", 0) |
| 1144 | + consts = meta["consts"] |
| 1145 | + self.assertIsInstance(consts, list) |
| 1146 | + _testinternalcapi.optimize_cfg(insts, consts, 0) |
| 1147 | + |
| 1148 | + def test_compiler_codegen_consts_include_none_required_for_implicit_return(self): |
| 1149 | + # Module "pass" only needs the const table entry for None once |
| 1150 | + # _PyCodegen_AddReturnAtEnd runs. If metadata["consts"] were taken |
| 1151 | + # before that, the list would not match LOAD_CONST opargs (here: 0 |
| 1152 | + # for None), and optimize_cfg would read out of range. |
| 1153 | + tree = ast.parse("pass", mode="exec", optimize=1) |
| 1154 | + insts, meta = _testinternalcapi.compiler_codegen(tree, "<s>", 0) |
| 1155 | + consts = meta["consts"] |
| 1156 | + self.assertEqual(consts, [None]) |
| 1157 | + |
| 1158 | + load_const = opcode.opmap["LOAD_CONST"] |
| 1159 | + self.assertEqual( |
| 1160 | + [t[1] for t in insts.get_instructions() if t[0] == load_const], |
| 1161 | + [0], |
| 1162 | + ) |
| 1163 | + |
| 1164 | + # As if consts were snapshotted before AddReturnAtEnd: still LOAD_CONST 0, no row. |
| 1165 | + with self.assertRaisesRegex(ValueError, "out of range"): |
| 1166 | + _testinternalcapi.optimize_cfg(insts, [], 0) |
| 1167 | + |
| 1168 | + _testinternalcapi.optimize_cfg(insts, list(consts), 0) |
| 1169 | + |
1122 | 1170 | def cfg_optimization_test(self, insts, expected_insts, |
1123 | 1171 | consts=None, expected_consts=None, |
1124 | 1172 | nlocals=0): |
|
0 commit comments