| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1 +1,9 @@ | |||
| 1 | - We have new tooling, in ``Tools/cases_generator``, to generate the interpreter switch from a list of opcode definitions. | ||
| 1 | + Add new tooling, in ``Tools/cases_generator``, | ||
| 2 | + to generate the interpreter switch statement from a list of opcode definitions. | ||
| 3 | + This only affects adding, modifying or removing instruction definitions. | ||
| 4 | + The instruction definitions now live in ``Python/bytecodes.c``, | ||
| 5 | + in the form of a `custom DSL (under development) | ||
| 6 | + <https://github.com/faster-cpython/ideas/blob/main/3.12/interpreter_definition.md>`__. | ||
| 7 | + The tooling reads this file and writes ``Python/generated_cases.c.h``, | ||
| 8 | + which is then included by ``Python/ceval.c`` to provide most of the cases | ||
| 9 | + of the main interpreter switch. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -69,6 +69,7 @@ do { \ | |||
| 69 | 69 | #define DISPATCH() ((void)0) | |
| 70 | 70 | ||
| 71 | 71 | #define inst(name) case name: | |
| 72 | + #define super(name) static int SUPER_##name | ||
| 72 | 73 | #define family(name) static int family_##name | |
| 73 | 74 | ||
| 74 | 75 | #define NAME_ERROR_MSG \ | |
@@ -158,67 +159,11 @@ dummy_func( | |||
| 158 | 159 | SETLOCAL(oparg, value); | |
| 159 | 160 | } | |
| 160 | 161 | ||
| 161 | - // stack effect: ( -- __0, __1) | ||
| 162 | - inst(LOAD_FAST__LOAD_FAST) { | ||
| 163 | - PyObject *value = GETLOCAL(oparg); | ||
| 164 | - assert(value != NULL); | ||
| 165 | - NEXTOPARG(); | ||
| 166 | - next_instr++; | ||
| 167 | - Py_INCREF(value); | ||
| 168 | - PUSH(value); | ||
| 169 | - value = GETLOCAL(oparg); | ||
| 170 | - assert(value != NULL); | ||
| 171 | - Py_INCREF(value); | ||
| 172 | - PUSH(value); | ||
| 173 | - } | ||
| 174 | - | ||
| 175 | - // stack effect: ( -- __0, __1) | ||
| 176 | - inst(LOAD_FAST__LOAD_CONST) { | ||
| 177 | - PyObject *value = GETLOCAL(oparg); | ||
| 178 | - assert(value != NULL); | ||
| 179 | - NEXTOPARG(); | ||
| 180 | - next_instr++; | ||
| 181 | - Py_INCREF(value); | ||
| 182 | - PUSH(value); | ||
| 183 | - value = GETITEM(consts, oparg); | ||
| 184 | - Py_INCREF(value); | ||
| 185 | - PUSH(value); | ||
| 186 | - } | ||
| 187 | - | ||
| 188 | - // stack effect: ( -- ) | ||
| 189 | - inst(STORE_FAST__LOAD_FAST) { | ||
| 190 | - PyObject *value = POP(); | ||
| 191 | - SETLOCAL(oparg, value); | ||
| 192 | - NEXTOPARG(); | ||
| 193 | - next_instr++; | ||
| 194 | - value = GETLOCAL(oparg); | ||
| 195 | - assert(value != NULL); | ||
| 196 | - Py_INCREF(value); | ||
| 197 | - PUSH(value); | ||
| 198 | - } | ||
| 199 | - | ||
| 200 | - // stack effect: (__0, __1 -- ) | ||
| 201 | - inst(STORE_FAST__STORE_FAST) { | ||
| 202 | - PyObject *value = POP(); | ||
| 203 | - SETLOCAL(oparg, value); | ||
| 204 | - NEXTOPARG(); | ||
| 205 | - next_instr++; | ||
| 206 | - value = POP(); | ||
| 207 | - SETLOCAL(oparg, value); | ||
| 208 | - } | ||
| 209 | - | ||
| 210 | - // stack effect: ( -- __0, __1) | ||
| 211 | - inst(LOAD_CONST__LOAD_FAST) { | ||
| 212 | - PyObject *value = GETITEM(consts, oparg); | ||
| 213 | - NEXTOPARG(); | ||
| 214 | - next_instr++; | ||
| 215 | - Py_INCREF(value); | ||
| 216 | - PUSH(value); | ||
| 217 | - value = GETLOCAL(oparg); | ||
| 218 | - assert(value != NULL); | ||
| 219 | - Py_INCREF(value); | ||
| 220 | - PUSH(value); | ||
| 221 | - } | ||
| 162 | + super(LOAD_FAST__LOAD_FAST) = LOAD_FAST + LOAD_FAST; | ||
| 163 | + super(LOAD_FAST__LOAD_CONST) = LOAD_FAST + LOAD_CONST; | ||
| 164 | + super(STORE_FAST__LOAD_FAST) = STORE_FAST + LOAD_FAST; | ||
| 165 | + super(STORE_FAST__STORE_FAST) = STORE_FAST + STORE_FAST; | ||
| 166 | + super (LOAD_CONST__LOAD_FAST) = LOAD_CONST + LOAD_FAST; | ||
| 222 | 167 | ||
| 223 | 168 | // stack effect: (__0 -- ) | |
| 224 | 169 | inst(POP_TOP) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,7 +11,7 @@ | |||
| 11 | 11 | import sys | |
| 12 | 12 | ||
| 13 | 13 | import parser | |
| 14 | - from parser import InstDef | ||
| 14 | + from parser import InstDef # TODO: Use parser.InstDef | ||
| 15 | 15 | ||
| 16 | 16 | arg_parser = argparse.ArgumentParser() | |
| 17 | 17 | arg_parser.add_argument("-i", "--input", type=str, default="Python/bytecodes.c") | |
@@ -29,19 +29,24 @@ def eopen(filename: str, mode: str = "r"): | |||
| 29 | 29 | return open(filename, mode) | |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | - def parse_cases(src: str, filename: str|None = None) -> tuple[list[InstDef], list[parser.Family]]: | ||
| 32 | + def parse_cases( | ||
| 33 | + src: str, filename: str|None = None | ||
| 34 | + ) -> tuple[list[InstDef], list[parser.Super], list[parser.Family]]: | ||
| 33 | 35 | psr = parser.Parser(src, filename=filename) | |
| 34 | 36 | instrs: list[InstDef] = [] | |
| 37 | + supers: list[parser.Super] = [] | ||
| 35 | 38 | families: list[parser.Family] = [] | |
| 36 | 39 | while not psr.eof(): | |
| 37 | 40 | if inst := psr.inst_def(): | |
| 38 | 41 | assert inst.block | |
| 39 | - instrs.append(InstDef(inst.name, inst.inputs, inst.outputs, inst.block)) | ||
| 42 | + instrs.append(inst) | ||
| 43 | + elif sup := psr.super_def(): | ||
| 44 | + supers.append(sup) | ||
| 40 | 45 | elif fam := psr.family_def(): | |
| 41 | 46 | families.append(fam) | |
| 42 | 47 | else: | |
| 43 | 48 | raise psr.make_syntax_error(f"Unexpected token") | |
| 44 | - return instrs, families | ||
| 49 | + return instrs, supers, families | ||
| 45 | 50 | ||
| 46 | 51 | ||
| 47 | 52 | def always_exits(block: parser.Block) -> bool: | |
@@ -62,16 +67,18 @@ def always_exits(block: parser.Block) -> bool: | |||
| 62 | 67 | return line.startswith(("goto ", "return ", "DISPATCH", "GO_TO_", "Py_UNREACHABLE()")) | |
| 63 | 68 | ||
| 64 | 69 | ||
| 65 | - def write_cases(f: io.TextIOBase, instrs: list[InstDef]): | ||
| 70 | + def write_cases(f: io.TextIOBase, instrs: list[InstDef], supers: list[parser.Super]): | ||
| 66 | 71 | predictions = set() | |
| 67 | 72 | for inst in instrs: | |
| 68 | 73 | for target in re.findall(r"(?:PREDICT|GO_TO_INSTRUCTION)\((\w+)\)", inst.block.text): | |
| 69 | 74 | predictions.add(target) | |
| 70 | 75 | indent = " " | |
| 71 | 76 | f.write(f"// This file is generated by {os.path.relpath(__file__)}\n") | |
| 72 | 77 | f.write("// Do not edit!\n") | |
| 78 | + instr_index: dict[str, InstDef] = {} | ||
| 73 | 79 | for instr in instrs: | |
| 74 | 80 | assert isinstance(instr, InstDef) | |
| 81 | + instr_index[instr.name] = instr | ||
| 75 | 82 | f.write(f"\n{indent}TARGET({instr.name}) {{\n") | |
| 76 | 83 | if instr.name in predictions: | |
| 77 | 84 | f.write(f"{indent} PREDICTED({instr.name});\n") | |
@@ -102,6 +109,22 @@ def write_cases(f: io.TextIOBase, instrs: list[InstDef]): | |||
| 102 | 109 | # Write trailing '}' | |
| 103 | 110 | f.write(f"{indent}}}\n") | |
| 104 | 111 | ||
| 112 | + for sup in supers: | ||
| 113 | + assert isinstance(sup, parser.Super) | ||
| 114 | + components = [instr_index[name] for name in sup.ops] | ||
| 115 | + f.write(f"\n{indent}TARGET({sup.name}) {{\n") | ||
| 116 | + for i, instr in enumerate(components): | ||
| 117 | + if i > 0: | ||
| 118 | + f.write(f"{indent} NEXTOPARG();\n") | ||
| 119 | + f.write(f"{indent} next_instr++;\n") | ||
| 120 | + text = instr.block.to_text(-4) | ||
| 121 | + textlines = text.splitlines(True) | ||
| 122 | + textlines = [line for line in textlines if not line.strip().startswith("PREDICTED(")] | ||
| 123 | + text = "".join(textlines) | ||
| 124 | + f.write(f"{indent} {text.strip()}\n") | ||
| 125 | + f.write(f"{indent} DISPATCH();\n") | ||
| 126 | + f.write(f"{indent}}}\n") | ||
| 127 | + | ||
| 105 | 128 | ||
| 106 | 129 | def main(): | |
| 107 | 130 | args = arg_parser.parse_args() | |
@@ -110,21 +133,22 @@ def main(): | |||
| 110 | 133 | begin = srclines.index("// BEGIN BYTECODES //") | |
| 111 | 134 | end = srclines.index("// END BYTECODES //") | |
| 112 | 135 | src = "\n".join(srclines[begin+1 : end]) | |
| 113 | - instrs, families = parse_cases(src, filename=args.input) | ||
| 114 | - ninstrs = nfamilies = 0 | ||
| 136 | + instrs, supers, families = parse_cases(src, filename=args.input) | ||
| 137 | + ninstrs = nsupers = nfamilies = 0 | ||
| 115 | 138 | if not args.quiet: | |
| 116 | 139 | ninstrs = len(instrs) | |
| 140 | + nsupers = len(supers) | ||
| 117 | 141 | nfamilies = len(families) | |
| 118 | 142 | print( | |
| 119 | - f"Read {ninstrs} instructions " | ||
| 143 | + f"Read {ninstrs} instructions, {nsupers} supers, " | ||
| 120 | 144 | f"and {nfamilies} families from {args.input}", | |
| 121 | 145 | file=sys.stderr, | |
| 122 | 146 | ) | |
| 123 | 147 | with eopen(args.output, "w") as f: | |
| 124 | - write_cases(f, instrs) | ||
| 148 | + write_cases(f, instrs, supers) | ||
| 125 | 149 | if not args.quiet: | |
| 126 | 150 | print( | |
| 127 | - f"Wrote {ninstrs} instructions to {args.output}", | ||
| 151 | + f"Wrote {ninstrs + nsupers} instructions to {args.output}", | ||
| 128 | 152 | file=sys.stderr, | |
| 129 | 153 | ) | |
| 130 | 154 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments