Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7dcd28e

Browse files
GH-98831: Implement super-instruction generation (#99084)
Co-authored-by: C.A.M. Gerlach <CAM.Gerlach@Gerlach.CAM>
1 parentede6cb2 commit7dcd28e

File tree

5 files changed

+163
-138
lines changed

5 files changed

+163
-138
lines changed
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff 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.

‎Python/bytecodes.c‎

Lines changed: 6 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ do { \
6969
#defineDISPATCH() ((void)0)
7070

7171
#defineinst(name) case name:
72+
#definesuper(name) static int SUPER_##name
7273
#definefamily(name) static int family_##name
7374

7475
#defineNAME_ERROR_MSG \
@@ -158,67 +159,11 @@ dummy_func(
158159
SETLOCAL(oparg,value);
159160
}
160161

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;
222167

223168
// stack effect: (__0 -- )
224169
inst(POP_TOP) {

‎Python/generated_cases.c.h‎

Lines changed: 82 additions & 62 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎Tools/cases_generator/generate_cases.py‎

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
importsys
1212

1313
importparser
14-
fromparserimportInstDef
14+
fromparserimportInstDef# TODO: Use parser.InstDef
1515

1616
arg_parser=argparse.ArgumentParser()
1717
arg_parser.add_argument("-i","--input",type=str,default="Python/bytecodes.c")
@@ -29,19 +29,24 @@ def eopen(filename: str, mode: str = "r"):
2929
returnopen(filename,mode)
3030

3131

32-
defparse_cases(src:str,filename:str|None=None)->tuple[list[InstDef],list[parser.Family]]:
32+
defparse_cases(
33+
src:str,filename:str|None=None
34+
)->tuple[list[InstDef],list[parser.Super],list[parser.Family]]:
3335
psr=parser.Parser(src,filename=filename)
3436
instrs:list[InstDef]= []
37+
supers:list[parser.Super]= []
3538
families:list[parser.Family]= []
3639
whilenotpsr.eof():
3740
ifinst:=psr.inst_def():
3841
assertinst.block
39-
instrs.append(InstDef(inst.name,inst.inputs,inst.outputs,inst.block))
42+
instrs.append(inst)
43+
elifsup:=psr.super_def():
44+
supers.append(sup)
4045
eliffam:=psr.family_def():
4146
families.append(fam)
4247
else:
4348
raisepsr.make_syntax_error(f"Unexpected token")
44-
returninstrs,families
49+
returninstrs,supers,families
4550

4651

4752
defalways_exits(block:parser.Block)->bool:
@@ -62,16 +67,18 @@ def always_exits(block: parser.Block) -> bool:
6267
returnline.startswith(("goto ","return ","DISPATCH","GO_TO_","Py_UNREACHABLE()"))
6368

6469

65-
defwrite_cases(f:io.TextIOBase,instrs:list[InstDef]):
70+
defwrite_cases(f:io.TextIOBase,instrs:list[InstDef],supers:list[parser.Super]):
6671
predictions=set()
6772
forinstininstrs:
6873
fortargetinre.findall(r"(?:PREDICT|GO_TO_INSTRUCTION)\((\w+)\)",inst.block.text):
6974
predictions.add(target)
7075
indent=" "
7176
f.write(f"// This file is generated by{os.path.relpath(__file__)}\n")
7277
f.write("// Do not edit!\n")
78+
instr_index:dict[str,InstDef]= {}
7379
forinstrininstrs:
7480
assertisinstance(instr,InstDef)
81+
instr_index[instr.name]=instr
7582
f.write(f"\n{indent}TARGET({instr.name}) {{\n")
7683
ifinstr.nameinpredictions:
7784
f.write(f"{indent} PREDICTED({instr.name});\n")
@@ -102,6 +109,22 @@ def write_cases(f: io.TextIOBase, instrs: list[InstDef]):
102109
# Write trailing '}'
103110
f.write(f"{indent}}}\n")
104111

112+
forsupinsupers:
113+
assertisinstance(sup,parser.Super)
114+
components= [instr_index[name]fornameinsup.ops]
115+
f.write(f"\n{indent}TARGET({sup.name}) {{\n")
116+
fori,instrinenumerate(components):
117+
ifi>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= [lineforlineintextlinesifnotline.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+
105128

106129
defmain():
107130
args=arg_parser.parse_args()
@@ -110,21 +133,22 @@ def main():
110133
begin=srclines.index("// BEGIN BYTECODES //")
111134
end=srclines.index("// END BYTECODES //")
112135
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
115138
ifnotargs.quiet:
116139
ninstrs=len(instrs)
140+
nsupers=len(supers)
117141
nfamilies=len(families)
118142
print(
119-
f"Read{ninstrs} instructions "
143+
f"Read{ninstrs} instructions,{nsupers} supers, "
120144
f"and{nfamilies} families from{args.input}",
121145
file=sys.stderr,
122146
)
123147
witheopen(args.output,"w")asf:
124-
write_cases(f,instrs)
148+
write_cases(f,instrs,supers)
125149
ifnotargs.quiet:
126150
print(
127-
f"Wrote{ninstrs} instructions to{args.output}",
151+
f"Wrote{ninstrs+nsupers} instructions to{args.output}",
128152
file=sys.stderr,
129153
)
130154

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp