Skip to content

Commit a6105e6

Browse files
Hosted stencil changes
1 parent b70a567 commit a6105e6

File tree

7 files changed

+83
-38
lines changed

7 files changed

+83
-38
lines changed

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
# Specific binary files
2121
PC/classicAppCompat.* binary
2222

23+
# JIT stencils are generated by the build and should not be modified
24+
Tools/jit/stencils/* text eol=lf
25+
2326
# Text files that should not be subject to eol conversion
2427
[attr]noeol -text
2528

.github/workflows/jit.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,71 @@ jobs:
132132
make all --jobs 4
133133
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
134134
135+
- name: Check if stencils need regeneration
136+
id: check-stencils
137+
if: ${{!matrix.debug }}
138+
shell: bash
139+
run: |
140+
git add Tools/jit/stencils
141+
142+
if ! git diff --staged --exit-code --quiet; then
143+
git diff --staged > jit_stencils.patch
144+
exit 1
145+
fi
146+
147+
- name: Format target name
148+
if: ${{ failure() && steps.check-stencils.conclusion == 'failure' && !matrix.debug }}
149+
id: strip-target
150+
shell: bash
151+
run: |
152+
target=${{ matrix.target }}
153+
target="${target%%/*}"
154+
echo "target=$target" >> $GITHUB_OUTPUT
155+
156+
- name: Upload stencil patch
157+
if: ${{ failure() && steps.check-stencils.conclusion == 'failure' && !matrix.debug }}
158+
uses: actions/upload-artifact@v4
159+
with:
160+
name: ${{ steps.strip-target.outputs.target }}-jit-stencils
161+
path: jit_stencils.patch
162+
163+
aggregate-stencil-patches:
164+
name: Aggregate stencil patches
165+
needs: jit
166+
runs-on: ubuntu-24.04
167+
if: ${{ failure() }}
168+
steps:
169+
- name: Download stencil artifacts
170+
run: |
171+
mkdir -p artifacts
172+
gh run download ${{ github.run_id }} --pattern '*jit-stencils*' --dir artifacts --repo ${{ github.repository }}
173+
env:
174+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
175+
176+
- name: Aggregate stencil patches
177+
run: |
178+
temp_file="$(mktemp)"
179+
: > "$temp_file"
180+
181+
find artifacts -mindepth 1 -maxdepth 1 -type d | while read -r dir; do
182+
find "$dir" -type f -name "*.patch" -exec cat {} + >> "$temp_file"
183+
done
184+
185+
sed_command="s/[[:space:]]*$//"
186+
if [[ "$(uname)" == "Darwin" ]]; then
187+
sed -i '' "$sed_command" "$temp_file"
188+
else
189+
sed -i "$sed_command" "$temp_file"
190+
fi
191+
192+
mv "$temp_file" aggregated_jit_stencils.patch
193+
194+
- name: Upload aggregated stencil patch
195+
uses: actions/upload-artifact@v4
196+
with:
197+
name: aggregated-jit-stencils
198+
path: aggregated_jit_stencils.patch
199+
135200
jit-with-disabled-gil:
136201
name: Free-Threaded (Debug)
137202
needs: interpreter

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ repos:
3333
args: [--line-length=79]
3434
- id: black
3535
name: Run Black on Tools/jit/
36-
files: ^Tools/jit/
36+
files: ^Tools/jit/(?!stencils/).*
3737
language_version: python3.12
3838

3939
- repo: https://github.com/pre-commit/pre-commit-hooks

PCbuild/regen.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<_KeywordOutputs Include="$(PySourcePath)Lib\keyword.py" />
3131
<!-- Taken from _Target._compute_digest in Tools\jit\_targets.py: -->
3232
<_JITSources Include="$(PySourcePath)Python\executor_cases.c.h;$(GeneratedPyConfigDir)pyconfig.h;$(PySourcePath)Tools\jit\**"/>
33-
<_JITOutputs Include="$(GeneratedPyConfigDir)jit_stencils.h"/>
33+
<_JITOutputs Include="$(GeneratedPyConfigDir)jit_stencils.h;$(PySourcePath)Tools\jit\stencils\**"/>
3434
<_CasesSources Include="$(PySourcePath)Python\bytecodes.c;$(PySourcePath)Python\optimizer_bytecodes.c;"/>
3535
<_CasesOutputs Include="$(PySourcePath)Python\generated_cases.c.h;$(PySourcePath)Include\opcode_ids.h;$(PySourcePath)Include\internal\pycore_uop_ids.h;$(PySourcePath)Python\opcode_targets.h;$(PySourcePath)Include\internal\pycore_opcode_metadata.h;$(PySourcePath)Include\internal\pycore_uop_metadata.h;$(PySourcePath)Python\optimizer_cases.c.h;$(PySourcePath)Lib\_opcode_metadata.py"/>
3636
<_SbomSources Include="$(PySourcePath)PCbuild\get_externals.bat" />

Tools/jit/_targets.py

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
import asyncio
44
import dataclasses
5-
import hashlib
65
import json
7-
import os
86
import pathlib
97
import re
8+
import shutil
109
import sys
1110
import tempfile
1211
import typing
@@ -44,18 +43,6 @@ class _Target(typing.Generic[_S, _R]):
4443
verbose: bool = False
4544
known_symbols: dict[str, int] = dataclasses.field(default_factory=dict)
4645

47-
def _compute_digest(self, out: pathlib.Path) -> str:
48-
hasher = hashlib.sha256()
49-
hasher.update(self.triple.encode())
50-
hasher.update(self.debug.to_bytes())
51-
# These dependencies are also reflected in _JITSources in regen.targets:
52-
hasher.update(PYTHON_EXECUTOR_CASES_C_H.read_bytes())
53-
hasher.update((out / "pyconfig.h").read_bytes())
54-
for dirpath, _, filenames in sorted(os.walk(TOOLS_JIT)):
55-
for filename in filenames:
56-
hasher.update(pathlib.Path(dirpath, filename).read_bytes())
57-
return hasher.hexdigest()
58-
5946
async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup:
6047
group = _stencils.StencilGroup()
6148
args = ["--disassemble", "--reloc", f"{path}"]
@@ -176,35 +163,28 @@ async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]:
176163
)
177164
return stencil_groups
178165

179-
def build(
180-
self, out: pathlib.Path, *, comment: str = "", force: bool = False
181-
) -> None:
166+
def build(self, out: pathlib.Path, *, force: bool = False) -> None:
182167
"""Build jit_stencils.h in the given directory."""
183168
if not self.stable:
184169
warning = f"JIT support for {self.triple} is still experimental!"
185170
request = "Please report any issues you encounter.".center(len(warning))
186171
outline = "=" * len(warning)
187172
print("\n".join(["", outline, warning, request, outline, ""]))
188-
digest = f"// {self._compute_digest(out)}\n"
189-
jit_stencils = out / "jit_stencils.h"
190-
if (
191-
not force
192-
and jit_stencils.exists()
193-
and jit_stencils.read_text().startswith(digest)
194-
):
195-
return
173+
target = self.triple
174+
darwin_index = target.find("-darwin")
175+
if darwin_index != -1:
176+
target = self.triple[: darwin_index + len("-darwin")]
177+
178+
jit_stencils = CPYTHON / "Tools" / "jit" / "stencils" / f"{target}.h"
196179
stencil_groups = asyncio.run(self._build_stencils())
197-
jit_stencils_new = out / "jit_stencils.h.new"
180+
jit_stencils_new = CPYTHON / "Tools" / "jit" / "stencils" / f"{target}.h.new"
198181
try:
199-
with jit_stencils_new.open("w") as file:
200-
file.write(digest)
201-
if comment:
202-
file.write(f"// {comment}\n")
203-
file.write("\n")
182+
with jit_stencils_new.open("w", newline="\n") as file:
204183
for line in _writer.dump(stencil_groups, self.known_symbols):
205184
file.write(f"{line}\n")
206185
try:
207186
jit_stencils_new.replace(jit_stencils)
187+
shutil.copy(jit_stencils, out / "jit_stencils.h")
208188
except FileNotFoundError:
209189
# another process probably already moved the file
210190
if not jit_stencils.is_file():

Tools/jit/_writer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def _dump_stencil(opname: str, group: _stencils.StencilGroup) -> typing.Iterator
4848
yield "{"
4949
for part, stencil in [("code", group.code), ("data", group.data)]:
5050
for line in stencil.disassembly:
51-
yield f" // {line}"
51+
yield f" // {line}".rstrip()
5252
if stencil.body:
5353
yield f" const unsigned char {part}_body[{len(stencil.body)}] = {{"
5454
for i in range(0, len(stencil.body), 8):

Tools/jit/build.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22

33
import argparse
44
import pathlib
5-
import shlex
6-
import sys
75

86
import _targets
97

108
if __name__ == "__main__":
11-
comment = f"$ {shlex.join([pathlib.Path(sys.executable).name] + sys.argv)}"
129
parser = argparse.ArgumentParser(description=__doc__)
1310
parser.add_argument(
1411
"target", type=_targets.get_target, help="a PEP 11 target triple to compile for"
@@ -25,4 +22,4 @@
2522
args = parser.parse_args()
2623
args.target.debug = args.debug
2724
args.target.verbose = args.verbose
28-
args.target.build(pathlib.Path.cwd(), comment=comment, force=args.force)
25+
args.target.build(pathlib.Path.cwd(), force=args.force)

0 commit comments

Comments
 (0)