Skip to content

Commit a0832d5

Browse files
committed
Auto-generate cases in EXTENDED_ARG_3, and tweaks
1 parent 0dac13f commit a0832d5

File tree

4 files changed

+77
-10
lines changed

4 files changed

+77
-10
lines changed

Python/bytecodes.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3346,11 +3346,10 @@ dummy_func(
33463346
next_instr++;
33473347
// oparg2 = _Py_OPCODE(*next_instr); // Nothing uses it yet
33483348
oparg3 = oparg3 << 8 | _Py_OPARG(*next_instr);
3349-
next_instr++;
3349+
frame->prev_instr = next_instr++;
33503350
// Jump into the middle of that instruction
33513351
switch (opcode) {
3352-
case MAKE_FUNCTION_FROM_CODE:
3353-
goto into_make_function_from_code;
3352+
INSERT_EXTENDED_CASES();
33543353
default:
33553354
Py_FatalError("Unexpected opcode in EXTENDED_ARG_3");
33563355
while (1) { abort(); }

Python/generated_cases.c.h

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

Tools/cases_generator/generate_cases.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,9 @@ class Instruction:
215215
family: parser.Family | None = None
216216
predicted: bool = False
217217

218-
def __init__(self, inst: parser.InstDef):
218+
def __init__(self, inst: parser.InstDef, a: "Analyzer"):
219219
self.inst = inst
220+
self.analyzer = a
220221
self.register = inst.register
221222
self.kind = inst.kind
222223
self.name = inst.name
@@ -278,7 +279,7 @@ def write(self, out: Formatter) -> None:
278279
"""Write one instruction, sans prologue and epilogue."""
279280

280281
# Write additional instruction decoding if > 1 word
281-
if self.instr_fmt.startswith(("IBBB", "IBXB", "IBBX")):
282+
if self.instr_fmt.startswith(("IBB", "IBX")):
282283
out.emit("// Decode rest of instruction")
283284
if self.instr_fmt[2] == "B":
284285
out.emit("oparg2 = next_instr[0].opcode;")
@@ -288,7 +289,8 @@ def write(self, out: Formatter) -> None:
288289
out.emit("oparg3 = next_instr[0].oparg;")
289290
else:
290291
out.emit("// (oparg3 is unused)")
291-
out.emit("next_instr++;")
292+
# Update prev_instr, since it must equal next_instr - 1.
293+
out.emit("frame->prev_instr = next_instr++;")
292294
with out.outdent():
293295
# Need ';' because the next line may be a declaration.
294296
# Declarations are not statements, only statements can have labels.
@@ -415,6 +417,13 @@ def write_body(self, out: Formatter, dedent: int, cache_adjust: int = 0) -> None
415417
for ieff in self.input_effects:
416418
if ieff.name not in self.unmoved_names:
417419
out.write_raw(f"{extra}{space}Py_DECREF({ieff.name});\n")
420+
elif m := re.match(r"(\s*)INSERT_EXTENDED_CASES\(\);\s*$", line):
421+
assert self.name == "EXTENDED_ARG_3", self.name
422+
space = m.group(1)
423+
for instr in self.analyzer.instrs.values():
424+
if instr.instr_fmt.startswith(("IBB", "IBX")):
425+
out.write_raw(f"{extra}{space}case {instr.name}:\n")
426+
out.write_raw(f"{extra}{space} goto into_{instr.name.lower()};\n")
418427
else:
419428
out.write_raw(extra + line)
420429

@@ -540,7 +549,7 @@ def parse(self) -> None:
540549
while thing := psr.definition():
541550
match thing:
542551
case parser.InstDef(name=name):
543-
self.instrs[name] = Instruction(thing)
552+
self.instrs[name] = Instruction(thing, self)
544553
self.everything.append(thing)
545554
case parser.Super(name):
546555
self.supers[name] = thing

Tools/cases_generator/test_generator.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,69 @@ def test_long_instr():
446446
// Decode rest of instruction
447447
oparg2 = next_instr[0].opcode;
448448
oparg3 = next_instr[0].oparg;
449-
next_instr++;
449+
frame->prev_instr = next_instr++;
450450
into_op:; // For EXTENDED_ARG_3
451451
oparg, oparg2, oparg3;
452452
DISPATCH();
453453
}
454454
"""
455455
run_cases_test(input, output)
456+
457+
def test_extended_cases():
458+
input = """
459+
inst(OP, (--)) {
460+
oparg;
461+
}
462+
inst(OP1, (--)) {
463+
oparg, oparg2;
464+
}
465+
inst(OP2, (--)) {
466+
oparg, oparg3;
467+
}
468+
inst(EXTENDED_ARG_3) {
469+
switch (x) {
470+
INSERT_EXTENDED_CASES();
471+
default:
472+
abort();
473+
}
474+
}
475+
"""
476+
output = """
477+
TARGET(OP) {
478+
oparg;
479+
DISPATCH();
480+
}
481+
482+
TARGET(OP1) {
483+
// Decode rest of instruction
484+
oparg2 = next_instr[0].opcode;
485+
// (oparg3 is unused)
486+
frame->prev_instr = next_instr++;
487+
into_op1:; // For EXTENDED_ARG_3
488+
oparg, oparg2;
489+
DISPATCH();
490+
}
491+
492+
TARGET(OP2) {
493+
// Decode rest of instruction
494+
// (oparg2 is unused)
495+
oparg3 = next_instr[0].oparg;
496+
frame->prev_instr = next_instr++;
497+
into_op2:; // For EXTENDED_ARG_3
498+
oparg, oparg3;
499+
DISPATCH();
500+
}
501+
502+
TARGET(EXTENDED_ARG_3) {
503+
switch (x) {
504+
case OP1:
505+
goto into_op1;
506+
case OP2:
507+
goto into_op2;
508+
default:
509+
abort();
510+
}
511+
DISPATCH();
512+
}
513+
"""
514+
run_cases_test(input, output)

0 commit comments

Comments
 (0)