diff --git a/.agents/skills/rota-bench-regression-analysis/SKILL.md b/.agents/skills/rota-bench-regression-analysis/SKILL.md index ee5449ace3..5779ea32dc 100644 --- a/.agents/skills/rota-bench-regression-analysis/SKILL.md +++ b/.agents/skills/rota-bench-regression-analysis/SKILL.md @@ -78,6 +78,7 @@ git diff --stat GOOD..BAD - In the attributed section, use this header format: `abcd1234efgh | author@oracle.com | Full subject` - Unattributed changes that look plausible go to "to bisect", flaky ones go to "to watch" - In the "to bisect" section, add an invocation (don't execute yet) of `scripts/bisect_benchmark_regression.py` that can bisect it (use unabbreviated commits in this case) +- The positional benchmark name identifies the result to compare. If the harness runs that result through a differently named parent or group, pass the runnable name with `--benchmark-selector`. For example, use result `pyperformance-suite.scimark_fft` with `--benchmark-selector scimark`, because pyperformance runs the `scimark` group and reports `scimark_fft` separately. - In the "to watch" section, say whether the item looks flaky, or likely the same cause as another attributed item. - Do not abbreviate commit subjects. - Keep author emails. diff --git a/abi/abi-graalpy253.xml b/abi/abi-graalpy253.xml new file mode 100644 index 0000000000..bd238a0633 --- /dev/null +++ b/abi/abi-graalpy253.xml @@ -0,0 +1,14963 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ci/python-gate.libsonnet b/ci/python-gate.libsonnet index f7ab83145c..14e8870953 100644 --- a/ci/python-gate.libsonnet +++ b/ci/python-gate.libsonnet @@ -517,6 +517,8 @@ $.overlay_imports.BUILDBOT_COMMIT_SERVICE + '?repoName=graal&target=weekly&before-ts=${MAIN_COMMIT_TS}']], ["git", "clone", $.overlay_imports.GRAAL_ENTERPRISE_GIT, "../graal-enterprise"], ['git', '-C', '../graal', 'checkout', '${GRAAL_COMMIT}'], + ['mx', '-p', '../graal', 'fetch-jdk', '-A', 'labsjdk-ce-latest'], + ['set-export', 'JAVA_HOME', ['mx', '-p', '../graal', 'get-jdk-path', 'labsjdk-ce-latest']], // NOTE: this will checkout older graalpy. We need to live with that to ensure consistency with graal ['mx', '-p', '../graal/vm', '--dynamicimports', 'graalpython', 'sforceimports'], // NOTE: jvm-only, so not need to handle substratevm-enterprise-gcs diff --git a/graalpython/com.oracle.graal.python.cext/CMakeLists.txt b/graalpython/com.oracle.graal.python.cext/CMakeLists.txt index 8fe18afaca..04196a6e16 100644 --- a/graalpython/com.oracle.graal.python.cext/CMakeLists.txt +++ b/graalpython/com.oracle.graal.python.cext/CMakeLists.txt @@ -165,6 +165,7 @@ set(SRC_FILES ${CAPI_SRC}/codecs.c ${CAPI_SRC}/compile.c ${CAPI_SRC}/thread.c ${CAPI_SRC}/genobject.c ${CAPI_SRC}/methodobject.c ${CAPI_SRC}/boolobject.c ${CAPI_SRC}/pylifecycle.c ${CAPI_SRC}/errors.c ${CAPI_SRC}/signals.c ${CAPI_SRC}/datetime.c ${CAPI_SRC}/call.c ${CAPI_SRC}/getargs.c ${CAPI_SRC}/tracemalloc.c ${CAPI_SRC}/initconfig.c ${CAPI_SRC}/graalpy_stacktrace.c + ${CAPI_SRC}/graalpyarray.c ${CAPI_SRC}/lock.c ${CAPI_SRC}/parking_lot.c ) diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/cellobject.h b/graalpython/com.oracle.graal.python.cext/include/cpython/cellobject.h index 68f012f62b..d49313186b 100644 --- a/graalpython/com.oracle.graal.python.cext/include/cpython/cellobject.h +++ b/graalpython/com.oracle.graal.python.cext/include/cpython/cellobject.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, 2024, Oracle and/or its affiliates. +/* Copyright (c) 2018, 2026, Oracle and/or its affiliates. * Copyright (C) 1996-2020 Python Software Foundation * * Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 @@ -26,19 +26,19 @@ PyAPI_FUNC(PyObject *) PyCell_New(PyObject *); PyAPI_FUNC(PyObject *) PyCell_Get(PyObject *); PyAPI_FUNC(int) PyCell_Set(PyObject *, PyObject *); +/* GraalPy public API functions replacing direct PyCellObject field access. */ +PyAPI_FUNC(PyObject *) GraalPyCell_GET(PyObject *op); +PyAPI_FUNC(void) GraalPyCell_SET(PyObject *op, PyObject *value); + static inline PyObject* PyCell_GET(PyObject *op) { - PyCellObject *cell; assert(PyCell_Check(op)); - cell = _Py_CAST(PyCellObject*, op); - return cell->ob_ref; + return GraalPyCell_GET(op); } #define PyCell_GET(op) PyCell_GET(_PyObject_CAST(op)) static inline void PyCell_SET(PyObject *op, PyObject *value) { - PyCellObject *cell; assert(PyCell_Check(op)); - cell = _Py_CAST(PyCellObject*, op); - cell->ob_ref = value; + GraalPyCell_SET(op, value); } #define PyCell_SET(op, value) PyCell_SET(_PyObject_CAST(op), (value)) diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/code.h b/graalpython/com.oracle.graal.python.cext/include/cpython/code.h index f529fad331..4a57e7774d 100644 --- a/graalpython/com.oracle.graal.python.cext/include/cpython/code.h +++ b/graalpython/com.oracle.graal.python.cext/include/cpython/code.h @@ -186,14 +186,18 @@ PyAPI_DATA(PyTypeObject) PyCode_Type; #define PyCode_Check(op) Py_IS_TYPE((op), &PyCode_Type) +/* GraalPy public API functions replacing direct PyCodeObject field access. */ +PyAPI_FUNC(Py_ssize_t) GraalPyCode_GetNumFree(PyCodeObject *op); +PyAPI_FUNC(int) GraalPyCode_GetFirstFree(PyCodeObject *op); + static inline Py_ssize_t PyCode_GetNumFree(PyCodeObject *op) { assert(PyCode_Check(op)); - return op->co_nfreevars; + return GraalPyCode_GetNumFree(op); } static inline int PyUnstable_Code_GetFirstFree(PyCodeObject *op) { assert(PyCode_Check(op)); - return op->co_nlocalsplus - op->co_nfreevars; + return GraalPyCode_GetFirstFree(op); } Py_DEPRECATED(3.13) static inline int PyCode_GetFirstFree(PyCodeObject *op) { diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/dictobject.h b/graalpython/com.oracle.graal.python.cext/include/cpython/dictobject.h index 331fab9bd3..1aac6e296e 100644 --- a/graalpython/com.oracle.graal.python.cext/include/cpython/dictobject.h +++ b/graalpython/com.oracle.graal.python.cext/include/cpython/dictobject.h @@ -56,18 +56,15 @@ PyAPI_FUNC(PyObject *) PyDict_SetDefault( // 1 if `key` was present and `default_value` was not inserted PyAPI_FUNC(int) PyDict_SetDefaultRef(PyObject *mp, PyObject *key, PyObject *default_value, PyObject **result); +/* GraalPy public API function replacing direct PyDictObject field access. */ +PyAPI_FUNC(Py_ssize_t) GraalPyDict_GET_SIZE(PyObject *op); + /* Get the number of items of a dictionary. */ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) { - PyDictObject *mp; assert(PyDict_Check(op)); - mp = _Py_CAST(PyDictObject*, op); -#ifdef Py_GIL_DISABLED - return _Py_atomic_load_ssize_relaxed(&mp->ma_used); -#else - return mp->ma_used; -#endif + return GraalPyDict_GET_SIZE(op); } -#define PyDict_GET_SIZE(mp) (assert(PyDict_Check(mp)),PyObject_Size((PyObject*) mp)) +#define PyDict_GET_SIZE(op) PyDict_GET_SIZE(_PyObject_CAST(op)) PyAPI_FUNC(int) PyDict_ContainsString(PyObject *mp, const char *key); diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/funcobject.h b/graalpython/com.oracle.graal.python.cext/include/cpython/funcobject.h index 50f863a887..9f235c6cf7 100644 --- a/graalpython/com.oracle.graal.python.cext/include/cpython/funcobject.h +++ b/graalpython/com.oracle.graal.python.cext/include/cpython/funcobject.h @@ -89,40 +89,50 @@ PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *); #define _PyFunction_CAST(func) \ (assert(PyFunction_Check(func)), _Py_CAST(PyFunctionObject*, func)) +/* GraalPy public API functions replacing direct PyFunctionObject field access. + Return borrowed references. */ +PyAPI_FUNC(PyObject *) GraalPyFunction_GET_CODE(PyObject *func); +PyAPI_FUNC(PyObject *) GraalPyFunction_GET_GLOBALS(PyObject *func); +PyAPI_FUNC(PyObject *) GraalPyFunction_GET_MODULE(PyObject *func); +PyAPI_FUNC(PyObject *) GraalPyFunction_GET_DEFAULTS(PyObject *func); +PyAPI_FUNC(PyObject *) GraalPyFunction_GET_KW_DEFAULTS(PyObject *func); +PyAPI_FUNC(PyObject *) GraalPyFunction_GET_CLOSURE(PyObject *func); +PyAPI_FUNC(PyObject *) GraalPyFunction_GET_ANNOTATIONS(PyObject *func); + /* Static inline functions for direct access to these values. Type checks are *not* done, so use with care. */ static inline PyObject* PyFunction_GET_CODE(PyObject *func) { - return _PyFunction_CAST(func)->func_code; + return GraalPyFunction_GET_CODE(func); } #define PyFunction_GET_CODE(func) PyFunction_GET_CODE(_PyObject_CAST(func)) static inline PyObject* PyFunction_GET_GLOBALS(PyObject *func) { - return _PyFunction_CAST(func)->func_globals; + return GraalPyFunction_GET_GLOBALS(func); } #define PyFunction_GET_GLOBALS(func) PyFunction_GET_GLOBALS(_PyObject_CAST(func)) static inline PyObject* PyFunction_GET_MODULE(PyObject *func) { - return _PyFunction_CAST(func)->func_module; + return GraalPyFunction_GET_MODULE(func); } #define PyFunction_GET_MODULE(func) PyFunction_GET_MODULE(_PyObject_CAST(func)) static inline PyObject* PyFunction_GET_DEFAULTS(PyObject *func) { - return _PyFunction_CAST(func)->func_defaults; + return GraalPyFunction_GET_DEFAULTS(func); } #define PyFunction_GET_DEFAULTS(func) PyFunction_GET_DEFAULTS(_PyObject_CAST(func)) static inline PyObject* PyFunction_GET_KW_DEFAULTS(PyObject *func) { - return _PyFunction_CAST(func)->func_kwdefaults; + return GraalPyFunction_GET_KW_DEFAULTS(func); } #define PyFunction_GET_KW_DEFAULTS(func) PyFunction_GET_KW_DEFAULTS(_PyObject_CAST(func)) static inline PyObject* PyFunction_GET_CLOSURE(PyObject *func) { - return _PyFunction_CAST(func)->func_closure; + return GraalPyFunction_GET_CLOSURE(func); } #define PyFunction_GET_CLOSURE(func) PyFunction_GET_CLOSURE(_PyObject_CAST(func)) static inline PyObject* PyFunction_GET_ANNOTATIONS(PyObject *func) { - return _PyFunction_CAST(func)->func_annotations; + return GraalPyFunction_GET_ANNOTATIONS(func); } #define PyFunction_GET_ANNOTATIONS(func) PyFunction_GET_ANNOTATIONS(_PyObject_CAST(func)) diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/memoryobject.h b/graalpython/com.oracle.graal.python.cext/include/cpython/memoryobject.h index 8ea700350d..3ef6ad88d3 100644 --- a/graalpython/com.oracle.graal.python.cext/include/cpython/memoryobject.h +++ b/graalpython/com.oracle.graal.python.cext/include/cpython/memoryobject.h @@ -42,14 +42,18 @@ typedef struct { #define _PyMemoryView_CAST(op) _Py_CAST(PyMemoryViewObject*, op) +/* GraalPy public API functions replacing direct PyMemoryViewObject field access. */ +PyAPI_FUNC(Py_buffer *) GraalPyMemoryView_GET_BUFFER(PyObject *op); +PyAPI_FUNC(PyObject *) GraalPyMemoryView_GET_BASE(PyObject *op); + /* Get a pointer to the memoryview's private copy of the exporter's buffer. */ static inline Py_buffer* PyMemoryView_GET_BUFFER(PyObject *op) { - return (&_PyMemoryView_CAST(op)->view); + return GraalPyMemoryView_GET_BUFFER(op); } #define PyMemoryView_GET_BUFFER(op) PyMemoryView_GET_BUFFER(_PyObject_CAST(op)) /* Get a pointer to the exporting object (this may be NULL!). */ static inline PyObject* PyMemoryView_GET_BASE(PyObject *op) { - return _PyMemoryView_CAST(op)->view.obj; + return GraalPyMemoryView_GET_BASE(op); } #define PyMemoryView_GET_BASE(op) PyMemoryView_GET_BASE(_PyObject_CAST(op)) diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h b/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h index 62ab105485..85f89e8a92 100644 --- a/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h +++ b/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h @@ -39,9 +39,8 @@ PyAPI_FUNC(void) GraalPyTuple_SET_ITEM(PyObject*, Py_ssize_t, PyObject*); /* Function *only* to be used to fill in brand new tuples */ static inline void PyTuple_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) { - PyTupleObject *tuple = _PyTuple_CAST(op); assert(0 <= index); - assert(index < Py_SIZE(tuple)); + assert(index < Py_SIZE(_PyTuple_CAST(op))); GraalPyTuple_SET_ITEM(op, index, value); } #define PyTuple_SET_ITEM(op, index, value) \ diff --git a/graalpython/com.oracle.graal.python.cext/include/listobject.h b/graalpython/com.oracle.graal.python.cext/include/listobject.h index 5d8510bc0c..8a0280eb21 100644 --- a/graalpython/com.oracle.graal.python.cext/include/listobject.h +++ b/graalpython/com.oracle.graal.python.cext/include/listobject.h @@ -57,6 +57,17 @@ PyAPI_FUNC(int) GraalPyArray_Resize(PyObject* array, Py_ssize_t new_size); */ PyAPI_FUNC(char*) GraalPyArray_Data(PyObject* array); +typedef struct GraalPyArray_Descriptor { + char typecode; + int itemsize; +} GraalPyArray_Descriptor; + +/* + * GraalPy public API used by Cython's array module. Available since GraalPy 25.3.4. + */ +PyAPI_FUNC(GraalPyArray_Descriptor*) GraalPyArray_GetDescriptor(PyObject* array); +PyAPI_FUNC(PyObject*) GraalPyArray_New(PyObject* type, Py_ssize_t size, GraalPyArray_Descriptor* descriptor); + #ifndef Py_LIMITED_API # define Py_CPYTHON_LISTOBJECT_H # include "cpython/listobject.h" diff --git a/graalpython/com.oracle.graal.python.cext/include/pylifecycle.h b/graalpython/com.oracle.graal.python.cext/include/pylifecycle.h index 5e4f47a1a5..75428e64c7 100644 --- a/graalpython/com.oracle.graal.python.cext/include/pylifecycle.h +++ b/graalpython/com.oracle.graal.python.cext/include/pylifecycle.h @@ -73,6 +73,9 @@ PyAPI_DATA(const unsigned long) Py_Version; PyAPI_FUNC(int) Py_IsFinalizing(void); #endif +// GraalPy change: compatibility alias for pybind11 +PyAPI_FUNC(int) _Py_IsFinalizing(void); + #ifndef Py_LIMITED_API # define Py_CPYTHON_PYLIFECYCLE_H # include "cpython/pylifecycle.h" diff --git a/graalpython/com.oracle.graal.python.cext/src/capi.h b/graalpython/com.oracle.graal.python.cext/src/capi.h index bada348ba4..3fcfa909e6 100644 --- a/graalpython/com.oracle.graal.python.cext/src/capi.h +++ b/graalpython/com.oracle.graal.python.cext/src/capi.h @@ -323,18 +323,36 @@ PY_TRUFFLE_TYPE_LOCAL(Arraytype, "array", & PY_TRUFFLE_TYPE_LOCAL(mmap_object_type, "mmap.mmap", &PyType_Type, 0) \ PY_TRUFFLE_TYPE(PyArrayIter_Type, "arrayiterator", &PyType_Type, sizeof(arrayiterobject)) \ PY_TRUFFLE_TYPE(PyAsyncGen_Type, "async_generator", &PyType_Type, sizeof(PyAsyncGenObject)) \ +PY_TRUFFLE_TYPE(_PyAsyncGenASend_Type, "async_generator_asend", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(_PyAsyncGenAThrow_Type, "async_generator_athrow", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(_PyAsyncGenWrappedValue_Type, "async_generator_wrapped_value", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE_WITH_ITEMSIZE(PyLong_Type, "int", &PyType_Type, offsetof(PyLongObject, long_value.ob_digit), sizeof(PyObject *)) \ PY_TRUFFLE_TYPE(PyBool_Type, "bool", &PyType_Type, sizeof(struct _longobject)) \ PY_TRUFFLE_TYPE(PyByteArray_Type, "bytearray", &PyType_Type, sizeof(PyByteArrayObject)) \ PY_TRUFFLE_TYPE_WITH_ITEMSIZE(PyBytes_Type, "bytes", &PyType_Type, PyBytesObject_SIZE, sizeof(char)) \ PY_TRUFFLE_TYPE_WITH_ALLOC(PyCapsule_Type, "PyCapsule", &PyType_Type, sizeof(PyCapsule), PyType_GenericAlloc, capsule_dealloc, PyObject_Del) \ +PY_TRUFFLE_TYPE(PyCallIter_Type, "callable_iterator", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE(PyCell_Type, "cell", &PyType_Type, sizeof(PyCellObject)) \ PY_TRUFFLE_TYPE(PyCMethod_Type, "builtin_method", &PyCFunction_Type, sizeof(PyCFunctionObject)) \ +PY_TRUFFLE_TYPE(PyClassMethod_Type, "classmethod", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyClassMethodDescr_Type, "classmethod_descriptor", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE(PyCode_Type, "code", &PyType_Type, sizeof(PyTypeObject)) \ +PY_TRUFFLE_TYPE(PyCmpWrapper_Type, "KeyWrapper", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE(PyComplex_Type, "complex", &PyType_Type, sizeof(PyComplexObject)) \ +PY_TRUFFLE_TYPE(PyContext_Type, "Context", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyContextToken_Type, "Token", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyContextVar_Type, "ContextVar", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(_PyCoroWrapper_Type, "coroutine_wrapper", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE_EXTERN(PyDict_Type, "dict" ) \ +PY_TRUFFLE_TYPE(PyDictIterItem_Type, "dict_itemiterator", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyDictIterKey_Type, "dict_keyiterator", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyDictIterValue_Type, "dict_valueiterator", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyDictItems_Type, "dict_items", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyDictKeys_Type, "dict_keys", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE(PyDictProxy_Type, "mappingproxy", &PyType_Type, sizeof(mappingproxyobject)) \ +PY_TRUFFLE_TYPE(PyDictValues_Type, "dict_values", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE(PyEllipsis_Type, "ellipsis", &PyType_Type, 0) \ +PY_TRUFFLE_TYPE(PyFilter_Type, "filter", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE(PyFloat_Type, "float", &PyType_Type, sizeof(PyFloatObject)) \ PY_TRUFFLE_TYPE_WITH_ITEMSIZE(PyFrame_Type, "frame", &PyType_Type, sizeof(PyTypeObject), sizeof(PyObject *)) \ PY_TRUFFLE_TYPE(PyFrozenSet_Type, "frozenset", &PyType_Type, sizeof(PySetObject)) \ @@ -347,9 +365,15 @@ PY_TRUFFLE_TYPE(PyMap_Type, "map", & PY_TRUFFLE_TYPE(PyMemberDescr_Type, "member_descriptor", &PyType_Type, sizeof(PyMemberDescrObject)) \ PY_TRUFFLE_TYPE_WITH_ITEMSIZE(PyMemoryView_Type, "memoryview", &PyType_Type, offsetof(PyMemoryViewObject, ob_array), sizeof(Py_ssize_t)) \ PY_TRUFFLE_TYPE(PyMethod_Type, "method", &PyType_Type, sizeof(PyMethodObject)) \ +PY_TRUFFLE_TYPE(_PyMethodWrapper_Type, "method-wrapper", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE(PyMethodDescr_Type, "method_descriptor", &PyType_Type, sizeof(PyMethodDescrObject)) \ PY_TRUFFLE_TYPE_EXTERN(PyModule_Type, "module" ) \ PY_TRUFFLE_TYPE(PyModuleDef_Type, "moduledef", &PyType_Type, sizeof(struct PyModuleDef)) \ +PY_TRUFFLE_TYPE(PyODict_Type, "OrderedDict", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyODictItems_Type, "odict_items", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyODictIter_Type, "odict_iterator", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyODictKeys_Type, "odict_keys", &PyType_Type, sizeof(PyObject)) \ +PY_TRUFFLE_TYPE(PyODictValues_Type, "odict_values", &PyType_Type, sizeof(PyObject)) \ PY_TRUFFLE_TYPE(PyProperty_Type, "property", &PyType_Type, sizeof(propertyobject)) \ PY_TRUFFLE_TYPE(PyRange_Type, "range", &PyType_Type, sizeof(rangeobject)) \ PY_TRUFFLE_TYPE(PySet_Type, "set", &PyType_Type, sizeof(PySetObject)) \ @@ -370,11 +394,8 @@ PY_TRUFFLE_TYPE(PyCoro_Type, "coroutine", & PY_TRUFFLE_TYPE(Py_GenericAliasType, "types.GenericAlias", &PyType_Type, sizeof(PyObject)) \ /* PyPickleBufferObject (PyObject_HEAD + Py_buffer + PyObject*) is defined within Objects/picklebufobject.c, so its not exposed. */ \ PY_TRUFFLE_TYPE(PyPickleBuffer_Type, "_pickle.PickleBuffer", &PyType_Type, sizeof(PyPickleBufferObject)) \ +/* GraalPy has no corresponding Python object types for these CPython implementation details. */ \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyAIterWrapper_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyAsyncGenASend_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyAsyncGenAThrow_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyAsyncGenWrappedValue_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyCoroWrapper_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyHamt_ArrayNode_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyHamt_BitmapNode_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyHamt_CollisionNode_Type) \ @@ -384,41 +405,21 @@ PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyHamtKeys_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyHamtValues_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyInterpreterID_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyManagedBuffer_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(_PyMethodWrapper_Type) \ +PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyNullImporter_Type) \ +PY_TRUFFLE_TYPE_UNIMPLEMENTED(PySortWrapper_Type) \ +PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyStdPrinter_Type) \ +PY_TRUFFLE_TYPE_UNIMPLEMENTED(PySTEntry_Type) \ +/* GraalPy represents these using shared iterator types rather than distinct Python types. */ \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyByteArrayIter_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyBytesIter_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyCallIter_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyClassMethod_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyClassMethodDescr_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyCmpWrapper_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyContext_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyContextToken_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyContextVar_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictItems_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictIterItem_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictIterKey_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictIterValue_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictKeys_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictRevIterItem_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictRevIterKey_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictRevIterValue_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyDictValues_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyFilter_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyListIter_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyListRevIter_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyLongRangeIter_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyNullImporter_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyODict_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyODictItems_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyODictIter_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyODictKeys_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyODictValues_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyRangeIter_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PySetIter_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PySortWrapper_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyStaticMethod_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyStdPrinter_Type) \ -PY_TRUFFLE_TYPE_UNIMPLEMENTED(PySTEntry_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyTupleIter_Type) \ PY_TRUFFLE_TYPE_UNIMPLEMENTED(PyUnicodeIter_Type) \ diff --git a/graalpython/com.oracle.graal.python.cext/src/graalpyarray.c b/graalpython/com.oracle.graal.python.cext/src/graalpyarray.c new file mode 100644 index 0000000000..15b11555fb --- /dev/null +++ b/graalpython/com.oracle.graal.python.cext/src/graalpyarray.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "capi.h" + +#if PY_VERSION_HEX >= 0x030F0000 +_Static_assert(sizeof(((GraalPyArray_Descriptor *)0)->typecode) == 3, + "GraalPyArray_Descriptor.typecode must support multi-character Python 3.15 array typecodes"); +#endif + +#define GRAALPY_ARRAY_DESCRIPTOR(TYPECODE, TYPE) \ + {TYPECODE, sizeof(TYPE)} + +static GraalPyArray_Descriptor array_descriptor_b = GRAALPY_ARRAY_DESCRIPTOR('b', signed char); +static GraalPyArray_Descriptor array_descriptor_B = GRAALPY_ARRAY_DESCRIPTOR('B', unsigned char); +static GraalPyArray_Descriptor array_descriptor_u = GRAALPY_ARRAY_DESCRIPTOR('u', Py_UCS4); +static GraalPyArray_Descriptor array_descriptor_w = GRAALPY_ARRAY_DESCRIPTOR('w', Py_UCS4); +static GraalPyArray_Descriptor array_descriptor_h = GRAALPY_ARRAY_DESCRIPTOR('h', short); +static GraalPyArray_Descriptor array_descriptor_H = GRAALPY_ARRAY_DESCRIPTOR('H', unsigned short); +static GraalPyArray_Descriptor array_descriptor_i = GRAALPY_ARRAY_DESCRIPTOR('i', int); +static GraalPyArray_Descriptor array_descriptor_I = GRAALPY_ARRAY_DESCRIPTOR('I', unsigned int); +static GraalPyArray_Descriptor array_descriptor_l = GRAALPY_ARRAY_DESCRIPTOR('l', long); +static GraalPyArray_Descriptor array_descriptor_L = GRAALPY_ARRAY_DESCRIPTOR('L', unsigned long); +static GraalPyArray_Descriptor array_descriptor_q = GRAALPY_ARRAY_DESCRIPTOR('q', long long); +static GraalPyArray_Descriptor array_descriptor_Q = GRAALPY_ARRAY_DESCRIPTOR('Q', unsigned long long); +static GraalPyArray_Descriptor array_descriptor_f = GRAALPY_ARRAY_DESCRIPTOR('f', float); +static GraalPyArray_Descriptor array_descriptor_d = GRAALPY_ARRAY_DESCRIPTOR('d', double); + +#undef GRAALPY_ARRAY_DESCRIPTOR + +GraalPyArray_Descriptor * +GraalPyArray_GetDescriptor(PyObject *array) +{ + switch (GraalPyPrivate_Array_TypeCode(array)) { + case 'b': return &array_descriptor_b; + case 'B': return &array_descriptor_B; + case 'u': return &array_descriptor_u; + case 'w': return &array_descriptor_w; + case 'h': return &array_descriptor_h; + case 'H': return &array_descriptor_H; + case 'i': return &array_descriptor_i; + case 'I': return &array_descriptor_I; + case 'l': return &array_descriptor_l; + case 'L': return &array_descriptor_L; + case 'q': return &array_descriptor_q; + case 'Q': return &array_descriptor_Q; + case 'f': return &array_descriptor_f; + case 'd': return &array_descriptor_d; + default: + PyErr_BadInternalCall(); + return NULL; + } +} + +PyObject * +GraalPyArray_New(PyObject *type, Py_ssize_t size, GraalPyArray_Descriptor *descriptor) +{ + if (type == NULL || descriptor == NULL || size < 0) { + PyErr_BadInternalCall(); + return NULL; + } + return GraalPyPrivate_Array_New(type, size, (unsigned char)descriptor->typecode); +} diff --git a/graalpython/com.oracle.graal.python.cext/src/memoryobject.c b/graalpython/com.oracle.graal.python.cext/src/memoryobject.c index c3b34413b9..a51e7346b7 100644 --- a/graalpython/com.oracle.graal.python.cext/src/memoryobject.c +++ b/graalpython/com.oracle.graal.python.cext/src/memoryobject.c @@ -3520,3 +3520,16 @@ GraalPyPrivate_ReleaseBuffer(Py_buffer* buffer) } free(buffer); } + +// GraalPy additions +Py_buffer * +GraalPyMemoryView_GET_BUFFER(PyObject *op) +{ + return &_PyMemoryView_CAST(op)->view; +} + +PyObject * +GraalPyMemoryView_GET_BASE(PyObject *op) +{ + return _PyMemoryView_CAST(op)->view.obj; +} diff --git a/graalpython/com.oracle.graal.python.cext/src/pylifecycle.c b/graalpython/com.oracle.graal.python.cext/src/pylifecycle.c index 0d6e6a774a..8375849147 100644 --- a/graalpython/com.oracle.graal.python.cext/src/pylifecycle.c +++ b/graalpython/com.oracle.graal.python.cext/src/pylifecycle.c @@ -74,6 +74,13 @@ Py_IsFinalizing(void) return graalpy_finalizing; } +// GraalPy change: compatibility alias for pybind11 +int +_Py_IsFinalizing(void) +{ + return Py_IsFinalizing(); +} + static void graalpy_fork_not_supported(void) { diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_array.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_array.py index 4d10e16cdc..68af1a88d4 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_array.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_array.py @@ -1,4 +1,4 @@ -# Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -56,9 +56,24 @@ def reference_getbuffer(args): return a, bytes(a), len(a) * a.itemsize, a.itemsize, 0, 1, a.typecode, len(a), a.itemsize +def reference_array_new(args): + array_type, size, template = args + result = array_type(template.typecode, [0] * size) + return type(result) is array_type, result + + +def reference_array_descriptor(args): + array_obj, other = args + return array_obj.typecode, True, array_obj.typecode == other.typecode + + TEST_ARRAY = array('i', [1, 2, 3]) +class ArraySubclass(array): + pass + + class TestPyArray(CPyExtTestCase): if sys.implementation.name == 'graalpy': @@ -103,6 +118,106 @@ class TestPyArray(CPyExtTestCase): cmpfunc=unhandled_error_compare, ) + test_GraalPyArray_New = CPyExtFunction( + reference_array_new, + lambda: ( + (array, 0, array('b')), + (array, 3, array('i')), + (ArraySubclass, 2, array('d')), + ), + code=""" + PyObject* wrap_GraalPyArray_New(PyObject* type, Py_ssize_t size, PyObject* template) { + GraalPyArray_Descriptor* descriptor = GraalPyArray_GetDescriptor(template); + if (descriptor == NULL) + return NULL; + PyObject* result = GraalPyArray_New(type, size, descriptor); + if (result == NULL) + return NULL; + PyObject* is_requested_type = PyBool_FromLong(Py_TYPE(result) == (PyTypeObject*)type); + if (is_requested_type == NULL) { + Py_DECREF(result); + return NULL; + } + return Py_BuildValue("NN", is_requested_type, result); + } + """, + callfunction="wrap_GraalPyArray_New", + resultspec="O", + argspec="OnO", + arguments=["PyObject* type", "Py_ssize_t size", "PyObject* template"], + cmpfunc=unhandled_error_compare, + ) + + test_GraalPyArray_Descriptor = CPyExtFunction( + reference_array_descriptor, + lambda: ( + (array('b'), array('b')), + (array('B'), array('B')), + (array('u'), array('u')), + (array('w'), array('w')), + (array('h'), array('h')), + (array('H'), array('H')), + (array('i'), array('I')), + (array('I'), array('I')), + (array('l'), array('l')), + (array('L'), array('L')), + (array('q'), array('q')), + (array('Q'), array('Q')), + (array('f'), array('f')), + (array('d'), array('d')), + ), + code=""" + PyObject* wrap_GraalPyArray_Descriptor(PyObject* array, PyObject* other) { + GraalPyArray_Descriptor* descriptor = GraalPyArray_GetDescriptor(array); + GraalPyArray_Descriptor* other_descriptor = GraalPyArray_GetDescriptor(other); + PyObject* typecode; + PyObject* itemsize; + long itemsize_value; + if (descriptor == NULL || other_descriptor == NULL) + return NULL; + typecode = PyUnicode_FromOrdinal((unsigned char)descriptor->typecode); + if (typecode == NULL) + return NULL; + itemsize = PyObject_GetAttrString(array, "itemsize"); + if (itemsize == NULL) { + Py_DECREF(typecode); + return NULL; + } + itemsize_value = PyLong_AsLong(itemsize); + Py_DECREF(itemsize); + if (itemsize_value == -1 && PyErr_Occurred()) { + Py_DECREF(typecode); + return NULL; + } + return Py_BuildValue("Nii", typecode, descriptor->itemsize == itemsize_value, + descriptor == other_descriptor); + } + """, + callfunction="wrap_GraalPyArray_Descriptor", + resultspec="O", + argspec="OO", + arguments=["PyObject* array", "PyObject* other"], + cmpfunc=unhandled_error_compare, + ) + + test_array_Py_SIZE = CPyExtFunction( + lambda args: len(args[0]), + lambda: ( + (array('b'),), + (array('i', [1, 2, 3]),), + (ArraySubclass('d', [1, 2]),), + ), + code=""" + Py_ssize_t wrap_array_Py_SIZE(PyObject* array) { + return Py_SIZE(array); + } + """, + callfunction="wrap_array_Py_SIZE", + resultspec="n", + argspec="O", + arguments=["PyObject* array"], + ) + test_array_getbuffer = CPyExtFunction( reference_getbuffer, lambda: ( diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_codeobject.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_codeobject.py index 33ca0cf196..46876e6ff3 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_codeobject.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_codeobject.py @@ -60,6 +60,19 @@ def example_function(): return 1 +def make_closure_function(): + first = 1 + second = 2 + + def closure_function(): + return first + second + + return closure_function + + +closure_function = make_closure_function() + + def reference_PyCode_Addr2Line(args): code, lasti = args if lasti >= 0: @@ -80,6 +93,23 @@ class TestCodeobject(CPyExtTestCase): testmod = type(sys)("foo") + test_PyCode_GetNumFree = CPyExtFunction( + lambda args: len(args[0].co_freevars), + lambda: ( + (example_function.__code__,), + (closure_function.__code__,), + ), + code=""" + static Py_ssize_t wrap_PyCode_GetNumFree(PyObject *code) { + return PyCode_GetNumFree((PyCodeObject *)code); + } + """, + resultspec="n", + argspec="O", + arguments=["PyObject* code"], + callfunction="wrap_PyCode_GetNumFree", + ) + test_PyCode_NewEmpty = CPyExtFunction( lambda args: args, lambda: ( diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_context.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_context.py index 4dc0896d45..c60c396b1f 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_context.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_context.py @@ -1,4 +1,4 @@ -# Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -71,13 +71,26 @@ static PyObject* context_copy_current(PyObject* unused, PyObject* args) { return PyContext_CopyCurrent(); } + static PyObject* context_is_exact_type(PyObject* unused, PyObject* args) { + PyObject *obj; + int kind; + if (!PyArg_ParseTuple(args, "Oi", &obj, &kind)) + return NULL; + PyTypeObject *expected_types[] = { + &PyContext_Type, + &PyContextVar_Type, + &PyContextToken_Type, + }; + return PyBool_FromLong(Py_IS_TYPE(obj, expected_types[kind])); + } ''', tp_methods=''' {"enter", (PyCFunction)context_enter, METH_VARARGS | METH_STATIC, ""}, {"exit", (PyCFunction)context_exit, METH_VARARGS | METH_STATIC, ""}, {"copy", (PyCFunction)context_copy, METH_VARARGS | METH_STATIC, ""}, {"new", (PyCFunction)context_new, METH_VARARGS | METH_STATIC, ""}, - {"copy_current", (PyCFunction)context_copy_current, METH_VARARGS | METH_STATIC, ""} + {"copy_current", (PyCFunction)context_copy_current, METH_VARARGS | METH_STATIC, ""}, + {"is_exact_type", (PyCFunction)context_is_exact_type, METH_VARARGS | METH_STATIC, ""} ''' ) @@ -91,6 +104,10 @@ def test_cext_context_management(): assert v.get() == 'new value' current_copy = ContextHelper.copy_current() + assert ContextHelper.is_exact_type(current_copy, 0) + assert ContextHelper.is_exact_type(v, 1) + assert ContextHelper.is_exact_type(token, 2) + assert v.get() == 'new value' assert current_copy.run(v.get) == 'new value' @@ -120,4 +137,4 @@ def test_cext_context_management(): assert copy_of_copy.run(v.get) == 'newer value 2' new_ctx = ContextHelper.new() - assert new_ctx.run(v.get) == 'default value' \ No newline at end of file + assert new_ctx.run(v.get) == 'default value' diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_dict.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_dict.py index 34b59cca6e..38228de256 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_dict.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_dict.py @@ -176,6 +176,11 @@ class SubDict(dict): pass +class DictWithOverriddenLen(dict): + def __len__(self): + return 42 + + ExampleDict = {} @@ -593,6 +598,20 @@ class TestPyDict(CPyExtTestCase): arguments=["PyObject* dict"], ) + test_PyDict_GET_SIZE = CPyExtFunction( + lambda args: dict.__len__(args[0]), + lambda: ( + ({},), + ({'a': "hello"},), + ({'a': "hello", 'b': "world"},), + (SubDict({'a': "hello"}),), + (DictWithOverriddenLen({'a': "hello", 'b': "world"}),), + ), + resultspec="n", + argspec='O', + arguments=["PyObject* dict"], + ) + # PyDict_Copy test_PyDict_Copy = CPyExtFunction( _reference_copy, @@ -659,6 +678,48 @@ class TestPyDict(CPyExtTestCase): arguments=["PyObject* o"], ) + test_PyDictView_Type = CPyExtFunction( + lambda args: True, + lambda: ( + ({}.keys(), 0), + ({}.items(), 1), + ({}.values(), 2), + ), + code='''int wrap_PyDictView_Type(PyObject* view, int kind) { + PyTypeObject* expected_types[] = { + &PyDictKeys_Type, + &PyDictItems_Type, + &PyDictValues_Type, + }; + return Py_IS_TYPE(view, expected_types[kind]); + }''', + resultspec="i", + argspec="Oi", + arguments=["PyObject* view", "int kind"], + callfunction="wrap_PyDictView_Type", + ) + + test_PyDictIter_Type = CPyExtFunction( + lambda args: True, + lambda: ( + (iter({}), 0), + (iter({}.values()), 1), + (iter({}.items()), 2), + ), + code='''int wrap_PyDictIter_Type(PyObject* iterator, int kind) { + PyTypeObject* expected_types[] = { + &PyDictIterKey_Type, + &PyDictIterValue_Type, + &PyDictIterItem_Type, + }; + return Py_IS_TYPE(iterator, expected_types[kind]); + }''', + resultspec="i", + argspec="Oi", + arguments=["PyObject* iterator", "int kind"], + callfunction="wrap_PyDictIter_Type", + ) + test_PyDict_Update = CPyExtFunction( lambda args: 1 if args[0].update(args[1]) else 0, lambda: ( diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_functions.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_functions.py index ba63aa5295..8a7f4a7071 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_functions.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_functions.py @@ -39,6 +39,7 @@ import os import sys +import types import unittest from . import ( @@ -82,6 +83,43 @@ def identCallResult(arg): return ident(arg) +def _make_function_with_fields(): + closed_over = 42 + + def function(positional="default", *, keyword="kwdefault") -> int: + return closed_over + + return function + + +function_with_fields = _make_function_with_fields() + + +def function_without_optional_fields(): + pass + + +def _reference_cell_get(args): + cell = args[0] + if not isinstance(cell, types.CellType): + raise SystemError + return cell.cell_contents + + +def _reference_cell_set(args): + cell, value, clear = args + if not isinstance(cell, types.CellType): + raise SystemError + if clear: + del cell.cell_contents + else: + cell.cell_contents = value + try: + return False, cell.cell_contents + except ValueError: + return True, None + + class TypeWithAttr: attr = "str" @@ -122,6 +160,97 @@ def __delitem__(self, key): class TestPyObject(CPyExtTestCase): + test_PyCell_Get = CPyExtFunction( + _reference_cell_get, + lambda: ( + (types.CellType(42),), + (types.CellType(["value"]),), + (42,), + ), + code=""" + static PyObject* wrap_PyCell_Get(PyObject* cell) { + return PyCell_Get(cell); + } + """, + argspec="O", + arguments=["PyObject* cell"], + resultspec="N", + callfunction="wrap_PyCell_Get", + cmpfunc=unhandled_error_compare, + ) + + test_PyCell_GET_macro = CPyExtFunction( + lambda args: (args[0].cell_contents, True), + lambda: ( + (types.CellType(42),), + (types.CellType(["value"]),), + ), + code=""" + static PyObject* wrap_PyCell_GET(PyObject* cell) { + PyObject *contents = PyCell_GET(cell); + PyObject *contents_attr = PyObject_GetAttrString(cell, "cell_contents"); + PyObject *result; + + if (contents_attr == NULL) { + return NULL; + } + result = PyTuple_Pack(2, contents, contents == contents_attr ? Py_True : Py_False); + Py_DECREF(contents_attr); + return result; + } + """, + argspec="O", + arguments=["PyObject* cell"], + callfunction="wrap_PyCell_GET", + ) + + test_PyCell_Set = CPyExtFunction( + _reference_cell_set, + lambda: ( + (types.CellType(), 42, False), + (types.CellType("old"), ["new"], False), + (types.CellType("old"), None, True), + (42, "new", False), + ), + code=""" + static PyObject* wrap_PyCell_Set(PyObject* cell, PyObject* value, int clear) { + PyObject *contents; + if (PyCell_Set(cell, clear ? NULL : value) < 0) { + return NULL; + } + contents = PyCell_GET(cell); + return Py_BuildValue("(iO)", contents == NULL, contents == NULL ? Py_None : contents); + } + """, + argspec="OOp", + arguments=["PyObject* cell", "PyObject* value", "int clear"], + callfunction="wrap_PyCell_Set", + cmpfunc=unhandled_error_compare, + ) + + test_PyCell_SET_macro = CPyExtFunction( + _reference_cell_set, + lambda: ( + (types.CellType(), 42, False), + (types.CellType("old"), ["new"], False), + (types.CellType("old"), None, True), + ), + code=""" + static PyObject* wrap_PyCell_SET(PyObject* cell, PyObject* value, int clear) { + PyObject *contents; + if (!clear) { + Py_INCREF(value); + } + PyCell_SET(cell, clear ? NULL : value); + contents = PyCell_GET(cell); + return Py_BuildValue("(iO)", contents == NULL, contents == NULL ? Py_None : contents); + } + """, + argspec="OOp", + arguments=["PyObject* cell", "PyObject* value", "int clear"], + callfunction="wrap_PyCell_SET", + ) + test_Py_TYPE = CPyExtFunction( type, @@ -652,6 +781,57 @@ def _ref_hash_not_implemented(args): callfunction="wrapGraalPyCFunction_GetMethodDef", cmpfunc=unhandled_error_compare ) + + test_PyFunction_GET_FIELDS = CPyExtFunction( + lambda args: ( + args[0].__code__, + args[0].__globals__, + args[0].__module__, + args[0].__defaults__, + args[0].__kwdefaults__, + args[0].__closure__, + args[0].__annotations__ or None, + True, + ), + lambda: ( + (function_with_fields,), + (function_without_optional_fields,), + ), + code=""" + static PyObject* wrap_PyFunction_GET_FIELDS(PyObject* function) { + PyObject *module = PyFunction_GET_MODULE(function); + PyObject *defaults = PyFunction_GET_DEFAULTS(function); + PyObject *kwdefaults = PyFunction_GET_KW_DEFAULTS(function); + PyObject *closure = PyFunction_GET_CLOSURE(function); + PyObject *annotations = PyFunction_GET_ANNOTATIONS(function); + PyObject *module_attr = PyObject_GetAttrString(function, "__module__"); + PyObject *result; + int stable_module; + + if (module_attr == NULL) { + return NULL; + } + stable_module = module == module_attr; + Py_DECREF(module_attr); + + result = PyTuple_Pack( + 8, + PyFunction_GET_CODE(function), + PyFunction_GET_GLOBALS(function), + module, + defaults != NULL ? defaults : Py_None, + kwdefaults != NULL ? kwdefaults : Py_None, + closure != NULL ? closure : Py_None, + annotations != NULL ? annotations : Py_None, + stable_module ? Py_True : Py_False + ); + return result; + } + """, + argspec="O", + arguments=["PyObject* function"], + callfunction="wrap_PyFunction_GET_FIELDS", + ) # create function from PyMethodDef # test PyMethodDef is same # test calling m_meth diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_memoryview.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_memoryview.py index c4d3ac3e99..200a1b92ee 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_memoryview.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_memoryview.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -320,6 +320,29 @@ class TestPyMemoryView(CPyExtTestCase): cmpfunc=unhandled_error_compare_with_message, ) + test_memoryview_accessors = CPyExtFunction( + lambda args: (True, bytes(args[0])), + lambda: ((bytearray(b'12345678'),),), + code=''' + static PyObject* test_accessors(PyObject* obj) { + PyObject *mv = PyMemoryView_FromObject(obj); + if (!mv) + return NULL; + Py_buffer *view = PyMemoryView_GET_BUFFER(mv); + PyObject *result = Py_BuildValue( + "NN", + PyBool_FromLong(PyMemoryView_GET_BASE(mv) == obj), + PyBytes_FromStringAndSize(view->buf, view->len)); + Py_DECREF(mv); + return result; + } + ''', + resultspec='O', + argspec='O', + arguments=["PyObject* obj"], + callfunction="test_accessors", + ) + ignored_test_memoryview_slice = CPyExtFunction( lambda args: bytes((5, 6, 255, 128, 99))[args[0]][args[1]][args[2]], lambda: list(itertools.product(slices, slices, range(-2, 5))), @@ -378,7 +401,7 @@ class TestPyMemoryView(CPyExtTestCase): 0, "l", }; - + static PyObject* test_read(PyObject *key, PyObject* expected) { PyObject *mv = PyMemoryView_FromBuffer(&buffer); if (!mv) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_misc.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_misc.py index 7d0510cc3b..908e846e10 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_misc.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_misc.py @@ -91,8 +91,39 @@ def _reference_builtins(args): return type(__global_builtins_dict) +async def _async_generator(): + yield None + + class TestMisc(CPyExtTestCase): + test_builtin_type_objects = CPyExtFunction( + lambda args: True, + lambda: ( + (_async_generator().__anext__(), 0), + (iter(lambda: None, None), 1), + (classmethod(lambda: None), 2), + (dict.__dict__["fromkeys"], 3), + (staticmethod(lambda: None), 4), + ), + callfunction="check_builtin_type_object", + code=''' + static int check_builtin_type_object(PyObject* obj, int kind) { + PyTypeObject* expected_types[] = { + &_PyAsyncGenASend_Type, + &PyCallIter_Type, + &PyClassMethod_Type, + &PyClassMethodDescr_Type, + &PyStaticMethod_Type, + }; + return Py_IS_TYPE(obj, expected_types[kind]); + } + ''', + resultspec="i", + argspec="Oi", + arguments=["PyObject* obj", "int kind"], + ) + test_PyEllipsis_isSingleton = CPyExtFunction( lambda args: 1, lambda: ( diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py index bf9a6d9d65..8f05308339 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py @@ -38,6 +38,7 @@ # SOFTWARE. import sys +import typing import unittest from unittest import skipIf @@ -1596,6 +1597,21 @@ class DummyBytes(bytes): class TestObjectFunctions(CPyExtTestCase): + test_abstract_object_constants_native_roundtrip = CPyExtFunction( + lambda args: args[0], + lambda: ( + (None,), + (Ellipsis,), + (NotImplemented,), + (typing.NoDefault,), + ), + arguments=["PyObject* obj"], + resultspec="N", + argspec="O", + callfunction="Py_NewRef", + cmpfunc=lambda actual, expected: actual is expected, + ) + test_PyCallable_Check = CPyExtFunction( lambda args: callable(args[0]), lambda: ( diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_frame_tests.py b/graalpython/com.oracle.graal.python.test/src/tests/test_frame_tests.py index 812ad76bd5..fc0a893df1 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_frame_tests.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_frame_tests.py @@ -434,6 +434,20 @@ def inner(): assert update_freevar() == (2, 2) +def test_f_locals_proxy_cell_parameter_after_return(): + def get_frame(cell_parameter): + def read_cell_parameter(): + return cell_parameter + + return sys._getframe(), read_cell_parameter + + frame, read_cell_parameter = get_frame(1) + locals_proxy = frame.f_locals + assert locals_proxy['cell_parameter'] == 1 + locals_proxy['cell_parameter'] = 2 + assert read_cell_parameter() == 2 + + OTHER_RUNNING_INNER = 'running_inner' OTHER_RUNNING_OUTER = 'running_outer' OTHER_TERMINATED = 'terminated' diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_id.py b/graalpython/com.oracle.graal.python.test/src/tests/test_id.py index 210a8fe462..3d1d695ceb 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_id.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_id.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -38,6 +38,7 @@ # SOFTWARE. import sys +import typing def test_small_int_id_is_constant(): @@ -53,6 +54,13 @@ def test_object_id_is_constant(): assert id(x) == xid +def test_abstract_object_constants_have_id(): + for constant in (None, Ellipsis, NotImplemented, typing.NoDefault): + constant_id = id(constant) + assert isinstance(constant_id, int) + assert id(constant) == constant_id + + def test_double_id_is_constant(): assert id(12.2) == id(12.2) x = 128.12 @@ -95,4 +103,3 @@ def test_string_interned(): # y = x * 2 # z = x * 2 # assert id(y) != id(z) - diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_sysconfig.py b/graalpython/com.oracle.graal.python.test/src/tests/test_sysconfig.py index a3fab2f075..9a3a9ba1c7 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_sysconfig.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_sysconfig.py @@ -52,7 +52,8 @@ def test_platform_sysconfigdata(): import sysconfig mod = importlib.import_module(sysconfig._get_sysconfigdata_name()) # These flags are parsed directly from the file by maturin - for key in ("ABIFLAGS", "EXT_SUFFIX", "SOABI", "VERSION"): + for key in ("ABIFLAGS", "EXT_SUFFIX", "INSTSONAME", "SOABI", "VERSION"): assert key in mod.build_time_vars assert mod.build_time_vars["ABIFLAGS"] == sys.abiflags + assert mod.build_time_vars["INSTSONAME"] == mod.build_time_vars["LDLIBRARY"] assert sys.abiflags in sysconfig.get_config_var("INCLUDEPY") diff --git a/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_marshal.txt b/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_marshal.txt index f68eaa6e60..b1396a9f3a 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_marshal.txt +++ b/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_marshal.txt @@ -18,6 +18,7 @@ test.test_marshal.BugsTestCase.test_version_argument @ darwin-arm64,linux-aarch6 !test.test_marshal.CodeTestCase.test_code test.test_marshal.CodeTestCase.test_different_filenames @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github test.test_marshal.CodeTestCase.test_many_codeobjects @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github +test.test_marshal.CodeTestCase.test_no_allow_code @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github test.test_marshal.CompatibilityTestCase.test0To3 @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github test.test_marshal.CompatibilityTestCase.test1To3 @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github test.test_marshal.CompatibilityTestCase.test2To3 @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 8de2783999..8dd6298e85 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -77,6 +77,7 @@ import com.oracle.graal.python.builtins.objects.type.PythonManagedClass; import com.oracle.graal.python.builtins.objects.type.TpSlots; import com.oracle.graal.python.builtins.objects.type.slots.TpSlot; +import com.oracle.graal.python.builtins.objects.typing.PNoDefault; import com.oracle.graal.python.compiler.ParserCallbacksImpl; import com.oracle.graal.python.compiler.bytecode_dsl.BytecodeDSLCompiler; import com.oracle.graal.python.compiler.bytecode_dsl.BytecodeDSLCompiler.BytecodeDSLCompilerResult; @@ -365,7 +366,7 @@ public boolean isSingleContext() { @CompilationFinal(dimensions = 1) private final Shape[] builtinTypeInstanceShapes = new Shape[PythonBuiltinClassType.VALUES.length]; @CompilationFinal(dimensions = 1) public static final PythonAbstractObject[] CONTEXT_INSENSITIVE_SINGLETONS = new PythonAbstractObject[]{PNone.NONE, PEllipsis.INSTANCE, - PNotImplemented.NOT_IMPLEMENTED}; + PNotImplemented.NOT_IMPLEMENTED, PNoDefault.NO_DEFAULT}; @CompilationFinal(dimensions = 1) private volatile Object[] engineOptionsStorage; @CompilationFinal private volatile OptionValues engineOptions; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java index 5e3a8c62f3..70af888874 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java @@ -119,10 +119,9 @@ import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNodeGen; import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode; import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode; -import com.oracle.graal.python.nodes.function.PythonBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode; +import com.oracle.graal.python.nodes.function.builtins.PythonQuaternaryClinicBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.PythonTernaryClinicBuiltinNode; -import com.oracle.graal.python.nodes.function.builtins.PythonUnaryClinicBuiltinNode; import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider; import com.oracle.graal.python.runtime.ExecutionContext.BoundaryCallContext; import com.oracle.graal.python.runtime.IndirectCallData.BoundaryCallData; @@ -174,17 +173,18 @@ public void initialize(Python3Core core) { addBuiltinConstant(T_VERSION, CURRENT_VERSION); } - @Builtin(name = "dump", minNumOfPositionalArgs = 2, parameterNames = {"value", "file", "version"}) + @Builtin(name = "dump", minNumOfPositionalArgs = 2, numOfPositionalOnlyArgs = 3, parameterNames = {"value", "file", "version"}, keywordOnlyNames = "allow_code") @ArgumentClinic(name = "version", defaultValue = "CURRENT_VERSION", conversion = ClinicConversion.Int) + @ArgumentClinic(name = "allow_code", defaultValue = "true", conversion = ClinicConversion.Boolean) @GenerateNodeFactory - abstract static class DumpNode extends PythonTernaryClinicBuiltinNode { + abstract static class DumpNode extends PythonQuaternaryClinicBuiltinNode { @Override protected ArgumentClinicProvider getArgumentClinic() { return DumpNodeClinicProviderGen.INSTANCE; } @Specialization - static Object doit(VirtualFrame frame, Object value, Object file, int version, + static Object doit(VirtualFrame frame, Object value, Object file, int version, boolean allowCode, @Bind Node inliningTarget, @Bind PythonContext context, @Cached("createFor($node)") BoundaryCallData boundaryCallData, @@ -195,7 +195,7 @@ static Object doit(VirtualFrame frame, Object value, Object file, int version, Object savedState = BoundaryCallContext.enter(frame, threadState, boundaryCallData); byte[] data; try { - data = Marshal.dump(language, value, version); + data = Marshal.dump(language, value, version, allowCode); } catch (IOException e) { throw CompilerDirectives.shouldNotReachHere(e); } catch (Marshal.MarshalError me) { @@ -207,17 +207,18 @@ static Object doit(VirtualFrame frame, Object value, Object file, int version, } } - @Builtin(name = "dumps", minNumOfPositionalArgs = 1, parameterNames = {"value", "version"}) + @Builtin(name = "dumps", minNumOfPositionalArgs = 1, numOfPositionalOnlyArgs = 2, parameterNames = {"value", "version"}, keywordOnlyNames = "allow_code") @ArgumentClinic(name = "version", defaultValue = "CURRENT_VERSION", conversion = ClinicConversion.Int) + @ArgumentClinic(name = "allow_code", defaultValue = "true", conversion = ClinicConversion.Boolean) @GenerateNodeFactory - abstract static class DumpsNode extends PythonBinaryClinicBuiltinNode { + abstract static class DumpsNode extends PythonTernaryClinicBuiltinNode { @Override protected ArgumentClinicProvider getArgumentClinic() { return DumpsNodeClinicProviderGen.INSTANCE; } @Specialization - static Object doit(VirtualFrame frame, Object value, int version, + static Object doit(VirtualFrame frame, Object value, int version, boolean allowCode, @Bind Node inliningTarget, @Bind PythonContext context, @Cached("createFor($node)") BoundaryCallData boundaryCallData, @@ -226,7 +227,7 @@ static Object doit(VirtualFrame frame, Object value, int version, PythonContext.PythonThreadState threadState = context.getThreadState(language); Object savedState = BoundaryCallContext.enter(frame, threadState, boundaryCallData); try { - return PFactory.createBytes(language, Marshal.dump(language, value, version)); + return PFactory.createBytes(language, Marshal.dump(language, value, version, allowCode)); } catch (IOException e) { throw CompilerDirectives.shouldNotReachHere(e); } catch (Marshal.MarshalError me) { @@ -237,16 +238,22 @@ static Object doit(VirtualFrame frame, Object value, int version, } } - @Builtin(name = "load", minNumOfPositionalArgs = 1) + @Builtin(name = "load", minNumOfPositionalArgs = 1, numOfPositionalOnlyArgs = 1, parameterNames = "file", keywordOnlyNames = "allow_code") + @ArgumentClinic(name = "allow_code", defaultValue = "true", conversion = ClinicConversion.Boolean) @GenerateNodeFactory - abstract static class LoadNode extends PythonBuiltinNode { + abstract static class LoadNode extends PythonBinaryClinicBuiltinNode { + @Override + protected ArgumentClinicProvider getArgumentClinic() { + return MarshalModuleBuiltinsClinicProviders.LoadNodeClinicProviderGen.INSTANCE; + } + @NeverDefault protected static LookupAndCallBinaryNode createCallReadNode() { return LookupAndCallBinaryNode.create(T_READ); } @Specialization - static Object doit(VirtualFrame frame, Object file, + static Object doit(VirtualFrame frame, Object file, boolean allowCode, @Bind Node inliningTarget, @Bind PythonContext context, @Cached("createCallReadNode()") LookupAndCallBinaryNode callNode, @@ -258,7 +265,7 @@ static Object doit(VirtualFrame frame, Object file, throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.READ_RETURNED_NOT_BYTES, buffer); } try { - return Marshal.loadFile(language, file); + return Marshal.loadFile(language, file, allowCode); } catch (NumberFormatException e) { throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.BAD_MARSHAL_DATA_S, e.getMessage()); } catch (Marshal.MarshalError me) { @@ -267,13 +274,14 @@ static Object doit(VirtualFrame frame, Object file, } } - @Builtin(name = "loads", minNumOfPositionalArgs = 1, numOfPositionalOnlyArgs = 1, parameterNames = {"bytes"}) + @Builtin(name = "loads", minNumOfPositionalArgs = 1, numOfPositionalOnlyArgs = 1, parameterNames = {"bytes"}, keywordOnlyNames = "allow_code") @ArgumentClinic(name = "bytes", conversion = ClinicConversion.ReadableBuffer) + @ArgumentClinic(name = "allow_code", defaultValue = "true", conversion = ClinicConversion.Boolean) @GenerateNodeFactory - abstract static class LoadsNode extends PythonUnaryClinicBuiltinNode { + abstract static class LoadsNode extends PythonBinaryClinicBuiltinNode { @Specialization - static Object doit(VirtualFrame frame, Object buffer, + static Object doit(VirtualFrame frame, Object buffer, boolean allowCode, @Bind Node inliningTarget, @Bind PythonContext context, @Cached("createFor($node)") InteropCallData callData, @@ -287,7 +295,7 @@ static Object doit(VirtualFrame frame, Object buffer, if (!language.isSingleContext()) { cacheKey = language.cacheKeyForBytecode(bytes, length); } - return Marshal.load(language, bytes, length, cacheKey); + return Marshal.load(language, bytes, length, cacheKey, allowCode); } catch (NumberFormatException e) { throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.BAD_MARSHAL_DATA_S, e.getMessage()); } catch (Marshal.MarshalError me) { @@ -390,15 +398,20 @@ public final Throwable fillInStackTrace() { } @TruffleBoundary - static byte[] dump(PythonLanguage language, Object value, int version) throws IOException, MarshalError { - Marshal outMarshal = new Marshal(language, version); + static byte[] dump(PythonLanguage language, Object value, int version, boolean allowCode) throws IOException, MarshalError { + Marshal outMarshal = new Marshal(language, version, allowCode); outMarshal.writeObject(value); return outMarshal.outData.toByteArray(); } @TruffleBoundary static Object load(PythonLanguage language, byte[] ary, int length, long cacheKey) throws NumberFormatException, MarshalError { - Marshal inMarshal = new Marshal(language, ary, length, cacheKey); + return load(language, ary, length, cacheKey, true); + } + + @TruffleBoundary + static Object load(PythonLanguage language, byte[] ary, int length, long cacheKey, boolean allowCode) throws NumberFormatException, MarshalError { + Marshal inMarshal = new Marshal(language, ary, length, cacheKey, allowCode); Object result = inMarshal.readObject(); if (result == null) { throw new MarshalError(PythonBuiltinClassType.TypeError, ErrorMessages.BAD_MARSHAL_DATA_NULL); @@ -407,8 +420,8 @@ static Object load(PythonLanguage language, byte[] ary, int length, long cacheKe } @TruffleBoundary - static Object loadFile(PythonLanguage language, Object file) throws NumberFormatException, MarshalError { - Marshal inMarshal = new Marshal(language, file); + static Object loadFile(PythonLanguage language, Object file, boolean allowCode) throws NumberFormatException, MarshalError { + Marshal inMarshal = new Marshal(language, file, allowCode); Object result = inMarshal.readObject(); if (result == null) { throw new MarshalError(PythonBuiltinClassType.TypeError, ErrorMessages.BAD_MARSHAL_DATA_NULL); @@ -469,6 +482,7 @@ public int read(byte[] b, int off, int len) { final DataOutput out; final DataInput in; final int version; + final boolean allowCode; int depth = 0; long cacheKey; TruffleFile bytecodeFile; @@ -484,8 +498,13 @@ public int read(byte[] b, int off, int len) { Source source = null; Marshal(PythonLanguage language, int version) { + this(language, version, true); + } + + Marshal(PythonLanguage language, int version, boolean allowCode) { this.language = language; this.version = version; + this.allowCode = allowCode; this.outData = new ByteArrayOutputStream(); this.out = new DataOutputStream(outData); this.refMap = new HashMap<>(); @@ -496,6 +515,7 @@ public int read(byte[] b, int off, int len) { Marshal(PythonLanguage language, int version, DataOutput out) { this.language = language; this.version = version; + this.allowCode = true; this.outData = null; this.out = out; this.refMap = new HashMap<>(); @@ -504,24 +524,37 @@ public int read(byte[] b, int off, int len) { } Marshal(PythonLanguage language, byte[] in, int length, long cacheKey) { - this(language, SerializationUtils.createByteBufferDataInput(ByteBuffer.wrap(in, 0, length)), null, 0); + this(language, in, length, cacheKey, true); + } + + Marshal(PythonLanguage language, byte[] in, int length, long cacheKey, boolean allowCode) { + this(language, SerializationUtils.createByteBufferDataInput(ByteBuffer.wrap(in, 0, length)), null, 0, allowCode); this.cacheKey = cacheKey; } Marshal(PythonLanguage language, byte[] in, int length, long cacheKey, TruffleFile bytecodeFile, int baseOffset) { - this(language, SerializationUtils.createByteBufferDataInput(ByteBuffer.wrap(in, 0, length)), bytecodeFile, baseOffset); + this(language, SerializationUtils.createByteBufferDataInput(ByteBuffer.wrap(in, 0, length)), bytecodeFile, baseOffset, true); this.cacheKey = cacheKey; } Marshal(PythonLanguage language, Object in) { - this(language, new DataInputStream(new FileLikeInputStream(in)), null, 0); + this(language, in, true); + } + + Marshal(PythonLanguage language, Object in, boolean allowCode) { + this(language, new DataInputStream(new FileLikeInputStream(in)), null, 0, allowCode); } Marshal(PythonLanguage language, DataInput in, TruffleFile bytecodeFile, int baseOffset) { + this(language, in, bytecodeFile, baseOffset, true); + } + + Marshal(PythonLanguage language, DataInput in, TruffleFile bytecodeFile, int baseOffset, boolean allowCode) { this.language = language; this.in = in; this.refList = new ArrayList<>(); this.version = -1; + this.allowCode = allowCode; this.outData = null; this.out = null; this.refMap = null; @@ -923,6 +956,9 @@ private void writeComplexObject(Object v, int flag) { writeByte(ARRAY_TYPE_OBJECT); writeObjectArray((Object[]) v); } else if (v instanceof PCode c) { + if (!allowCode) { + throw new MarshalError(ValueError, ErrorMessages.MARSHALLING_CODE_OBJECTS_DISALLOWED); + } // we always store code objects in our format, CPython will not read our // marshalled data when that contains code objects writeByte(TYPE_GRAALPYTHON_CODE | flag); @@ -1151,10 +1187,19 @@ private Object readObject(int type, AddRefAndReturn addRef) throws NumberFormatE set.setDictStorage(setStore); return set; case TYPE_GRAALPYTHON_CODE: + if (!allowCode) { + throw new MarshalError(ValueError, ErrorMessages.UNMARSHALLING_CODE_OBJECTS_DISALLOWED); + } return addRef.run(readCode()); case TYPE_GRAALPYTHON_CODE_UNIT: + if (!allowCode) { + throw new MarshalError(ValueError, ErrorMessages.UNMARSHALLING_CODE_OBJECTS_DISALLOWED); + } return addRef.run(readRemovedCodeUnitPayload()); case TYPE_GRAALPYTHON_DSL_CODE_UNIT: + if (!allowCode) { + throw new MarshalError(ValueError, ErrorMessages.UNMARSHALLING_CODE_OBJECTS_DISALLOWED); + } return addRef.run(readBytecodeDSLCodeUnit()); case TYPE_DSL_SOURCE: return addRef.run(readSource()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextArrayBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextArrayBuiltins.java index 47fc8ebd6a..bab0a60c19 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextArrayBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextArrayBuiltins.java @@ -40,12 +40,15 @@ */ package com.oracle.graal.python.builtins.modules.cext; +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.MemoryError; import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Direct; import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Ignored; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.CHAR_PTR; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Int; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PY_BUFFER_PTR; +import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObject; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectRawPointer; +import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectTransfer; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_ssize_t; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Void; import static com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess.writeIntField; @@ -55,6 +58,7 @@ import static com.oracle.graal.python.runtime.nativeaccess.NativeMemory.calloc; import static com.oracle.graal.python.runtime.nativeaccess.NativeMemory.free; import static com.oracle.graal.python.runtime.nativeaccess.NativeMemory.malloc; +import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING; import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin; import com.oracle.graal.python.builtins.objects.array.ArrayNodes; @@ -65,12 +69,36 @@ import com.oracle.graal.python.builtins.objects.cext.structs.CFields; import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess; import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess.WriteTruffleStringNode; +import com.oracle.graal.python.builtins.objects.type.TypeNodes; +import com.oracle.graal.python.nodes.PRaiseNode; import com.oracle.graal.python.runtime.nativeaccess.NativeMemory; +import com.oracle.graal.python.runtime.object.PFactory; +import com.oracle.graal.python.util.BufferFormat; +import com.oracle.graal.python.util.OverflowException; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.strings.TruffleString; public final class PythonCextArrayBuiltins { + @CApiBuiltin(ret = PyObjectTransfer, args = {PyObject, Py_ssize_t, Int}, call = Ignored) + static long GraalPyPrivate_Array_New(long clsPtr, long size, int typeCode) { + Object cls = NativeToPythonInternalNode.executeUncached(clsPtr, false); + TruffleString typeCodeString = TruffleString.fromCodePointUncached(typeCode, TS_ENCODING); + BufferFormat format = BufferFormat.forArray(typeCodeString, TruffleString.CodePointLengthNode.getUncached(), + TruffleString.CodePointAtIndexUTF32Node.getUncached()); + try { + PArray array = PFactory.createArray(cls, TypeNodes.GetInstanceShape.executeUncached(cls), typeCodeString, format, Math.toIntExact(size)); + return PythonToNativeInternalNode.executeUncached(array, true); + } catch (ArithmeticException | OverflowException e) { + throw PRaiseNode.raiseStatic(null, MemoryError); + } + } + + @CApiBuiltin(ret = Int, args = {PyObjectRawPointer}, call = Ignored) + static int GraalPyPrivate_Array_TypeCode(long arrayPtr) { + return expectArray(arrayPtr, "GraalPyArray_GetDescriptor").getFormatString().codePointAtIndexUncached(0, TS_ENCODING); + } + /** * Graalpy-specific function implemented for Cython */ diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextCodeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextCodeBuiltins.java index 5d6391ef4e..b42bd711a7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextCodeBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextCodeBuiltins.java @@ -45,6 +45,7 @@ import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Int; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyCodeObjectRawPointer; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectRawPointer; +import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_ssize_t; import static com.oracle.graal.python.util.PythonUtils.EMPTY_BYTE_ARRAY; import static com.oracle.graal.python.util.PythonUtils.EMPTY_OBJECT_ARRAY; import static com.oracle.graal.python.util.PythonUtils.EMPTY_TRUFFLESTRING_ARRAY; @@ -61,6 +62,18 @@ public final class PythonCextCodeBuiltins { + @CApiBuiltin(ret = Py_ssize_t, args = {PyCodeObjectRawPointer}, call = Direct) + static long GraalPyCode_GetNumFree(long codePtr) { + PCode code = (PCode) NativeToPythonInternalNode.executeUncached(codePtr, false); + return code.getFreeVars().length; + } + + @CApiBuiltin(ret = Int, args = {PyCodeObjectRawPointer}, call = Direct) + static int GraalPyCode_GetFirstFree(long codePtr) { + PCode code = (PCode) NativeToPythonInternalNode.executeUncached(codePtr, false); + return code.getVarnames().length + code.getCellVars().length; + } + @CApiBuiltin(ret = PyCodeObjectRawPointer, args = {Int, Int, Int, Int, Int, Int, PyObjectRawPointer, PyObjectRawPointer, PyObjectRawPointer, PyObjectRawPointer, PyObjectRawPointer, PyObjectRawPointer, PyObjectRawPointer, PyObjectRawPointer, PyObjectRawPointer, Int, PyObjectRawPointer, PyObjectRawPointer}, call = Direct) static long PyUnstable_Code_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, long codePtr, long constsPtr, diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextDictBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextDictBuiltins.java index f2733756d9..6f73ee6303 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextDictBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextDictBuiltins.java @@ -56,6 +56,7 @@ import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectPtr; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectRawPointer; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectTransfer; +import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_ssize_t; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_hash_t; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Void; import static com.oracle.graal.python.nodes.ErrorMessages.BAD_ARG_TO_INTERNAL_FUNC; @@ -157,6 +158,12 @@ public final class PythonCextDictBuiltins { private static final CApiTiming TIMING_PYDICT_NEW = CApiTiming.create(false, "PyDict_New"); + @CApiBuiltin(ret = Py_ssize_t, args = {PyObject}, call = Direct) + static long GraalPyDict_GET_SIZE(long dictPtr) { + PDict dict = (PDict) NativeToPythonInternalNode.executeUncached(dictPtr, false); + return HashingStorageLen.executeUncached(dict.getDictStorage()); + } + @CApiBuiltin(ret = PyObjectTransfer, args = {}, call = Direct, acquireGil = false) static long PyDict_New() { CApiTiming.enter(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextFuncBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextFuncBuiltins.java index b0a0b38beb..7ffd7a0115 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextFuncBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextFuncBuiltins.java @@ -40,21 +40,43 @@ */ package com.oracle.graal.python.builtins.modules.cext; +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError; import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Direct; import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Ignored; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.ConstCharPtrAsTruffleString; +import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Int; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObject; +import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectBorrowed; import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectTransfer; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___ANNOTATIONS__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___MODULE__; +import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___NAME__; +import static com.oracle.graal.python.runtime.nativeaccess.NativeMemory.NULLPTR; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBinaryBuiltinNode; import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin; import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiUnaryBuiltinNode; import com.oracle.graal.python.builtins.objects.PNone; +import com.oracle.graal.python.builtins.objects.cell.PCell; +import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.EnsurePythonObjectNode; +import com.oracle.graal.python.builtins.objects.cext.capi.ExternalFunctionNodes.ToNativeBorrowedNode; +import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.NativeToPythonInternalNode; +import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeInternalNode; import com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor; +import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetItem; +import com.oracle.graal.python.builtins.objects.dict.PDict; import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction; +import com.oracle.graal.python.builtins.objects.function.PFunction; import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod; import com.oracle.graal.python.builtins.objects.method.PDecoratedMethod; +import com.oracle.graal.python.builtins.objects.module.PythonModule; +import com.oracle.graal.python.nodes.ErrorMessages; +import com.oracle.graal.python.nodes.PRaiseNode; +import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; +import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; +import com.oracle.graal.python.nodes.object.GetOrCreateDictNode; +import com.oracle.graal.python.runtime.PythonContext; import com.oracle.graal.python.runtime.object.PFactory; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -64,6 +86,170 @@ public final class PythonCextFuncBuiltins { + private static PCell getCell(long cellPtr) { + return (PCell) NativeToPythonInternalNode.executeUncached(cellPtr, false); + } + + private static Object getPromotedCellRef(long cellPtr) { + PCell cell = getCell(cellPtr); + Object ref = cell.getRef(); + if (ref == null) { + return null; + } + Object promotedRef = EnsurePythonObjectNode.executeUncached(PythonContext.get(null), ref, false); + if (promotedRef != ref) { + cell.setRef(promotedRef); + } + return promotedRef; + } + + private static void checkCell(long cellPtr) { + Object cell = NativeToPythonInternalNode.executeUncached(cellPtr, false); + if (!(cell instanceof PCell)) { + throw PRaiseNode.raiseStatic(null, SystemError, ErrorMessages.BAD_ARG_TO_INTERNAL_FUNC); + } + } + + @CApiBuiltin(ret = PyObjectTransfer, args = {PyObject}, call = Direct) + static long PyCell_Get(long cellPtr) { + checkCell(cellPtr); + Object ref = getPromotedCellRef(cellPtr); + return ref == null ? NULLPTR : PythonToNativeInternalNode.executeNewRefUncached(ref); + } + + @CApiBuiltin(ret = Int, args = {PyObject, PyObject}, call = Direct) + static int PyCell_Set(long cellPtr, long valuePtr) { + checkCell(cellPtr); + getCell(cellPtr).setRef(valuePtr == NULLPTR ? null : NativeToPythonInternalNode.executeUncached(valuePtr, false)); + return 0; + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long GraalPyCell_GET(long cellPtr) { + Object ref = getPromotedCellRef(cellPtr); + return ref == null ? NULLPTR : ToNativeBorrowedNode.executeUncached(ref); + } + + @CApiBuiltin(ret = ArgDescriptor.Void, args = {PyObject, PyObjectTransfer}, call = Direct) + static void GraalPyCell_SET(long cellPtr, long valuePtr) { + getCell(cellPtr).setRef(valuePtr == NULLPTR ? null : NativeToPythonInternalNode.executeUncached(valuePtr, true)); + } + + private static void checkFunction(long functionPtr) { + Object function = NativeToPythonInternalNode.executeUncached(functionPtr, false); + if (!(function instanceof PFunction)) { + throw PRaiseNode.raiseStatic(null, SystemError, ErrorMessages.BAD_ARG_TO_INTERNAL_FUNC); + } + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long PyFunction_GetCode(long functionPtr) { + checkFunction(functionPtr); + return GraalPyFunction_GET_CODE(functionPtr); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long PyFunction_GetGlobals(long functionPtr) { + checkFunction(functionPtr); + return GraalPyFunction_GET_GLOBALS(functionPtr); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long PyFunction_GetModule(long functionPtr) { + checkFunction(functionPtr); + return GraalPyFunction_GET_MODULE(functionPtr); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long PyFunction_GetDefaults(long functionPtr) { + checkFunction(functionPtr); + return GraalPyFunction_GET_DEFAULTS(functionPtr); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long PyFunction_GetKwDefaults(long functionPtr) { + checkFunction(functionPtr); + return GraalPyFunction_GET_KW_DEFAULTS(functionPtr); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long PyFunction_GetClosure(long functionPtr) { + checkFunction(functionPtr); + return GraalPyFunction_GET_CLOSURE(functionPtr); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long PyFunction_GetAnnotations(long functionPtr) { + checkFunction(functionPtr); + return GraalPyFunction_GET_ANNOTATIONS(functionPtr); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long GraalPyFunction_GET_CODE(long functionPtr) { + PFunction function = (PFunction) NativeToPythonInternalNode.executeUncached(functionPtr, false); + return ToNativeBorrowedNode.executeUncached(function.getCode()); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long GraalPyFunction_GET_GLOBALS(long functionPtr) { + PFunction function = (PFunction) NativeToPythonInternalNode.executeUncached(functionPtr, false); + Object globals = function.getGlobals(); + return ToNativeBorrowedNode.executeUncached(globals instanceof PythonModule ? GetOrCreateDictNode.executeUncached(globals) : globals); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long GraalPyFunction_GET_MODULE(long functionPtr) { + PFunction function = (PFunction) NativeToPythonInternalNode.executeUncached(functionPtr, false); + Object module = ReadAttributeFromObjectNode.getUncached().execute(function, T___MODULE__); + if (module == PNone.NO_VALUE) { + Object globals = function.getGlobals(); + if (globals instanceof PythonModule) { + module = ReadAttributeFromObjectNode.getUncached().execute(globals, T___NAME__); + if (module == PNone.NO_VALUE) { + module = PNone.NONE; + } + } else if (globals instanceof PDict dict) { + module = HashingStorageGetItem.executeUncached(dict.getDictStorage(), T___NAME__); + if (module == null) { + module = PNone.NONE; + } + } else { + module = PNone.NONE; + } + } + Object promotedModule = EnsurePythonObjectNode.executeUncached(PythonContext.get(null), module, false); + WriteAttributeToObjectNode.getUncached().execute(function, T___MODULE__, promotedModule); + return ToNativeBorrowedNode.executeUncached(promotedModule); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long GraalPyFunction_GET_DEFAULTS(long functionPtr) { + PFunction function = (PFunction) NativeToPythonInternalNode.executeUncached(functionPtr, false); + Object[] defaults = function.getDefaults(); + return defaults.length == 0 ? NULLPTR : ToNativeBorrowedNode.executeUncached(PFactory.createTuple(PythonLanguage.get(null), defaults)); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long GraalPyFunction_GET_KW_DEFAULTS(long functionPtr) { + PFunction function = (PFunction) NativeToPythonInternalNode.executeUncached(functionPtr, false); + Object defaults = function.getKwDefaultsDict(PythonLanguage.get(null)); + return defaults == PNone.NONE ? NULLPTR : ToNativeBorrowedNode.executeUncached(defaults); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long GraalPyFunction_GET_CLOSURE(long functionPtr) { + PFunction function = (PFunction) NativeToPythonInternalNode.executeUncached(functionPtr, false); + PCell[] closure = function.getClosure(); + return closure == null ? NULLPTR : ToNativeBorrowedNode.executeUncached(PFactory.createTuple(PythonLanguage.get(null), closure)); + } + + @CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct) + static long GraalPyFunction_GET_ANNOTATIONS(long functionPtr) { + PFunction function = (PFunction) NativeToPythonInternalNode.executeUncached(functionPtr, false); + Object annotations = ReadAttributeFromObjectNode.getUncached().execute(function, T___ANNOTATIONS__); + return annotations != PNone.NO_VALUE ? ToNativeBorrowedNode.executeUncached(annotations) : NULLPTR; + } + @CApiBuiltin(ret = PyObjectTransfer, args = {PyObject}, call = Direct) abstract static class PyStaticMethod_New extends CApiUnaryBuiltinNode { @Specialization diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/CellBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/CellBuiltins.java index 4661087d8f..d5bb915ae7 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/CellBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/CellBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -47,6 +47,7 @@ import java.util.List; +import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.annotations.Slot; import com.oracle.graal.python.annotations.Slot.SlotKind; import com.oracle.graal.python.annotations.Slot.SlotSignature; @@ -119,9 +120,10 @@ private Assumption getAssumption() { @Specialization Object newCell(@SuppressWarnings("unused") Object cls, Object contents, @Bind Node inliningTarget, + @Bind PythonLanguage language, @Cached InlinedConditionProfile nonEmptyProfile) { Assumption assumption = getAssumption(); - PCell cell = PFactory.createCell(assumption); + PCell cell = PFactory.createCell(language, assumption); if (nonEmptyProfile.profile(inliningTarget, !isNoValue(contents))) { cell.setRef(contents, assumption); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/PCell.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/PCell.java index ecbf632968..6e386b4542 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/PCell.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/PCell.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -40,18 +40,20 @@ */ package com.oracle.graal.python.builtins.objects.cell; -import com.oracle.graal.python.builtins.objects.PythonAbstractObject; +import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; import com.oracle.graal.python.util.PythonUtils; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.object.Shape; -public final class PCell extends PythonAbstractObject { +public final class PCell extends PythonBuiltinObject { private final Assumption effectivelyFinal; private Object ref; - public PCell(Assumption effectivelyFinalAssumption) { + public PCell(Object cls, Shape instanceShape, Assumption effectivelyFinalAssumption) { + super(cls, instanceShape); this.effectivelyFinal = effectivelyFinalAssumption; } @@ -65,10 +67,6 @@ public Object getRef() { return ref; } - public void clearRef(Assumption assumption) { - setRef(null, assumption); - } - public void clearRef() { setRef(null); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java index e9409c0443..7263c8724f 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java @@ -649,9 +649,7 @@ public final class CApiFunction { @CApiBuiltin(name = "PyBytes_DecodeEscape", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = NotImplemented) @CApiBuiltin(name = "PyBytes_Repr", ret = PyObject, args = {PyObject, Int}, call = NotImplemented) - @CApiBuiltin(name = "PyCell_Get", ret = PyObject, args = {PyObject}, call = NotImplemented) @CApiBuiltin(name = "PyCell_New", ret = PyObject, args = {PyObject}, call = NotImplemented) - @CApiBuiltin(name = "PyCell_Set", ret = Int, args = {PyObject, PyObject}, call = NotImplemented) @CApiBuiltin(name = "PyCode_Addr2Location", ret = Int, args = {PyCodeObject, Int, INT_LIST, INT_LIST, INT_LIST, INT_LIST}, call = NotImplemented) @CApiBuiltin(name = "PyCode_GetCellvars", ret = PyObject, args = {PyCodeObject}, call = NotImplemented) @CApiBuiltin(name = "PyCode_GetCode", ret = PyObject, args = {PyCodeObject}, call = NotImplemented) @@ -730,13 +728,6 @@ public final class CApiFunction { @CApiBuiltin(name = "PyFrame_FastToLocalsWithError", ret = Int, args = {PyFrameObject}, call = NotImplemented) @CApiBuiltin(name = "PyFrame_GetGenerator", ret = PyObject, args = {PyFrameObject}, call = NotImplemented) @CApiBuiltin(name = "PyFrame_LocalsToFast", ret = Void, args = {PyFrameObject, Int}, call = NotImplemented) - @CApiBuiltin(name = "PyFunction_GetAnnotations", ret = PyObject, args = {PyObject}, call = NotImplemented) - @CApiBuiltin(name = "PyFunction_GetClosure", ret = PyObject, args = {PyObject}, call = NotImplemented) - @CApiBuiltin(name = "PyFunction_GetCode", ret = PyObject, args = {PyObject}, call = NotImplemented) - @CApiBuiltin(name = "PyFunction_GetDefaults", ret = PyObject, args = {PyObject}, call = NotImplemented) - @CApiBuiltin(name = "PyFunction_GetGlobals", ret = PyObject, args = {PyObject}, call = NotImplemented) - @CApiBuiltin(name = "PyFunction_GetKwDefaults", ret = PyObject, args = {PyObject}, call = NotImplemented) - @CApiBuiltin(name = "PyFunction_GetModule", ret = PyObject, args = {PyObject}, call = NotImplemented) @CApiBuiltin(name = "PyFunction_New", ret = PyObject, args = {PyObject, PyObject}, call = NotImplemented) @CApiBuiltin(name = "PyFunction_NewWithQualName", ret = PyObject, args = {PyObject, PyObject, PyObject}, call = NotImplemented) @CApiBuiltin(name = "PyFunction_SetAnnotations", ret = Int, args = {PyObject, PyObject}, call = NotImplemented) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameLocalsProxyBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameLocalsProxyBuiltins.java index a216db85c2..0f551cc7f2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameLocalsProxyBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameLocalsProxyBuiltins.java @@ -105,7 +105,9 @@ protected List> getNodeFa private static int findSlot(VirtualFrame frame, Node inliningTarget, PFrameLocalsProxy self, Object key, PyObjectRichCompareBool equals) { BytecodeFrame bytecodeFrame = self.getBytecodeFrame(); BytecodeDSLFrameInfo info = (BytecodeDSLFrameInfo) bytecodeFrame.getFrameDescriptorInfo(); - for (int i = 0; i < info.getVariableCount(); i++) { + // Cell parameters occur in both varnames and cellvars. The function prologue moves their + // value to the cell slot and clears the regular slot, so prefer the later cell slot. + for (int i = info.getVariableCount() - 1; i >= 0; i--) { if (equals.executeEq(frame, inliningTarget, info.getVariableName(i), key)) { return i; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectNodes.java index d93152e889..fb01ce9774 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectNodes.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectNodes.java @@ -83,7 +83,6 @@ import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.PythonAbstractObject; import com.oracle.graal.python.builtins.objects.bytes.PBytes; -import com.oracle.graal.python.builtins.objects.cell.PCell; import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.capi.CApiContext; import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.EnsurePythonObjectNode; @@ -387,11 +386,6 @@ static Object id(PString self, return getObjectIdNode.execute(inliningTarget, self); } - @Specialization - Object id(PCell self) { - return PythonContext.get(this).getNextObjectId(self); - } - protected static boolean isDefaultCase(PythonObject object) { return !(object instanceof PBytes || object instanceof PFrozenSet || diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java index 1b32d143f6..fdcd80ad66 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java @@ -140,6 +140,8 @@ public abstract class ErrorMessages { public static final TruffleString BAD_MARSHAL_DATA_S = tsLiteral("bad marshal data (%s)"); public static final TruffleString BAD_MARSHAL_DATA_EOF = tsLiteral("marshal data too short"); public static final TruffleString BAD_MARSHAL_DATA_NULL = tsLiteral("bad NULL object in marshal data"); + public static final TruffleString MARSHALLING_CODE_OBJECTS_DISALLOWED = tsLiteral("marshalling code objects is disallowed"); + public static final TruffleString UNMARSHALLING_CODE_OBJECTS_DISALLOWED = tsLiteral("unmarshalling code objects is disallowed"); public static final TruffleString BAD_MEMBER_DESCR_TYPE_FOR_P = tsLiteral("bad memberdescr type for %p"); public static final TruffleString BAD_OPERAND_FOR = tsLiteral("bad operand type for %s%s: '%p'"); public static final TruffleString BAD_VALUES_IN_FDS_TO_KEEP = tsLiteral("bad value(s) in fds_to_keep"); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java index 89560c1427..faa93b972d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java @@ -3382,7 +3382,7 @@ public static final class CreateCells { public static void doCreateCells(VirtualFrame frame, LocalRangeAccessor locals, @Bind PBytecodeDSLRootNode rootNode) { for (int i = 0; i < locals.getLength(); i++) { - PCell cell = new PCell(rootNode.cellEffectivelyFinalAssumptions[i]); + PCell cell = PFactory.createCell(rootNode.getLanguage(), rootNode.cellEffectivelyFinalAssumptions[i]); locals.setObject(rootNode.getBytecodeNode(), frame, i, cell); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java index fa58519a8b..c90ac6c6d9 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetClassNode.java @@ -44,7 +44,6 @@ import com.oracle.graal.python.builtins.objects.PNone; import com.oracle.graal.python.builtins.objects.PNotImplemented; import com.oracle.graal.python.builtins.objects.PythonAbstractObject; -import com.oracle.graal.python.builtins.objects.cell.PCell; import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject; import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes; import com.oracle.graal.python.builtins.objects.ellipsis.PEllipsis; @@ -194,11 +193,6 @@ static Object getNoDefault(@SuppressWarnings("unused") PNoDefault object) { return PythonBuiltinClassType.PNoDefault; } - @Specialization - static Object getCell(@SuppressWarnings("unused") PCell object) { - return PythonBuiltinClassType.PCell; - } - @InliningCutoff @Specialization(guards = "isForeignObject(object)") static Object getForeign(Object object, diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java index 8c9de7cc84..f2ffc12f91 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PFactory.java @@ -833,8 +833,8 @@ public static PReferenceType createReferenceType(PythonLanguage language, Object return new PReferenceType(cls, shape, object, callback, queue); } - public static PCell createCell(Assumption effectivelyFinal) { - return new PCell(effectivelyFinal); + public static PCell createCell(PythonLanguage language, Assumption effectivelyFinal) { + return new PCell(PythonBuiltinClassType.PCell, PythonBuiltinClassType.PCell.getInstanceShape(language), effectivelyFinal); } /* diff --git a/graalpython/graalpy-pyconfig/CMakeLists.txt b/graalpython/graalpy-pyconfig/CMakeLists.txt index 13437d5c84..385a31faae 100644 --- a/graalpython/graalpy-pyconfig/CMakeLists.txt +++ b/graalpython/graalpy-pyconfig/CMakeLists.txt @@ -154,6 +154,7 @@ endif() graalpy_sysconfig_env_value("LDCXXSHARED") graalpy_sysconfig_env_value("LDSHARED") graalpy_sysconfig_value("LDLIBRARY" "libpython.${GRAALPY_SYSCONFIG_SOABI}${GRAALPY_SYSCONFIG_SHLIB_SUFFIX}") +graalpy_sysconfig_value("INSTSONAME" "${GRAALPY_SYSCONFIG_LDLIBRARY}") set(GRAALPY_SYSCONFIG_STRING_NAMES ABIFLAGS @@ -166,6 +167,7 @@ set(GRAALPY_SYSCONFIG_STRING_NAMES CXX EXE EXT_SUFFIX + INSTSONAME LD LDCXXSHARED LDLIBRARY diff --git a/graalpython/graalpy-pyconfig/_sysconfigdata_template.py b/graalpython/graalpy-pyconfig/_sysconfigdata_template.py index 7db9c37367..6891aa0b7e 100644 --- a/graalpython/graalpy-pyconfig/_sysconfigdata_template.py +++ b/graalpython/graalpy-pyconfig/_sysconfigdata_template.py @@ -47,6 +47,7 @@ "CFLAGS_DEFAULT": "@GRAALPY_SYSCONFIG_CFLAGS_DEFAULT_PYTHON_STRING@", "EXE": "@GRAALPY_SYSCONFIG_EXE_PYTHON_STRING@", "EXT_SUFFIX": "@GRAALPY_SYSCONFIG_EXT_SUFFIX_PYTHON_STRING@", + "INSTSONAME": "@GRAALPY_SYSCONFIG_INSTSONAME_PYTHON_STRING@", "LDLIBRARY": "@GRAALPY_SYSCONFIG_LDLIBRARY_PYTHON_STRING@", "LDFLAGS": "@GRAALPY_SYSCONFIG_LDFLAGS_PYTHON_STRING@", "LIBPYTHON": "", diff --git a/graalpython/lib-graalpython/patches/cloudpickle-2.2.1.patch b/graalpython/lib-graalpython/patches/cloudpickle-2.2.1.patch index e0c825cfef..0cf91ca051 100644 --- a/graalpython/lib-graalpython/patches/cloudpickle-2.2.1.patch +++ b/graalpython/lib-graalpython/patches/cloudpickle-2.2.1.patch @@ -2,10 +2,7 @@ diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 317be69..0c23e88 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py -@@ -512,10 +512,12 @@ def _walk_global_ops(code): - """ - Yield referenced name for all global-referencing instructions in *code*. - """ +@@ -515,4 +515,6 @@ def _walk_global_ops(code): - for instr in dis.get_instructions(code): - op = instr.opcode - if op in GLOBAL_OPS: @@ -16,6 +13,3 @@ index 317be69..0c23e88 100644 + # op = instr.opcode + # if op in GLOBAL_OPS: + # yield instr.argval - - - def _extract_class_dict(cls): diff --git a/graalpython/lib-graalpython/patches/cython-3.2.4.patch b/graalpython/lib-graalpython/patches/cython-3.2.4.patch index 648d6b5e40..2fa5ffd2a9 100644 --- a/graalpython/lib-graalpython/patches/cython-3.2.4.patch +++ b/graalpython/lib-graalpython/patches/cython-3.2.4.patch @@ -34,30 +34,60 @@ index 5ae2a4e..951aacc 100644 -watermark = str(version) +watermark = f'{version}-graalpy' diff --git a/Cython/Includes/cpython/array.pxd b/Cython/Includes/cpython/array.pxd -index 4bc0438..72c0360 100644 +index 4bc0438..67dcff9 100644 --- a/Cython/Includes/cpython/array.pxd +++ b/Cython/Includes/cpython/array.pxd -@@ -133,7 +133,7 @@ cdef extern from *: # Hard-coded utility code hack. +@@ -98,7 +98,10 @@ cdef extern from *: # Hard-coded utility code hack. + + cdef: + Py_ssize_t ob_size +- arraydescr* ob_descr # struct arraydescr *ob_descr; ++ ++ @property ++ cdef inline arraydescr* ob_descr(self) noexcept nogil: ++ return __Pyx_PyArray_Descr(self) + + @property + cdef inline __data_union data(self) noexcept nogil: +@@ -133,8 +136,8 @@ cdef extern from *: # Hard-coded utility code hack. PyObject_Free(info.shape) array newarrayobject(PyTypeObject* type, Py_ssize_t size, arraydescr *descr) - -+ array clonearray(object template_array, Py_ssize_t size) __data_union __Pyx_PyArray_Data(array self) noexcept nogil ++ arraydescr* __Pyx_PyArray_Descr(array self) noexcept nogil # fast resize/realloc # not suitable for small increments; reallocation 'to the point' -@@ -146,10 +146,7 @@ cdef inline array clone(array template, Py_ssize_t length, bint zero): + int resize(array self, Py_ssize_t n) except -1 +@@ -146,15 +149,18 @@ cdef inline array clone(array template, Py_ssize_t length, bint zero): """ fast creation of a new array, given a template array. type will be same as template. if zero is true, new array will be initialized with zeroes.""" - cdef array op = newarrayobject(Py_TYPE(template), length, template.ob_descr) -- if zero and op is not None: ++ cdef arraydescr* descr = template.ob_descr ++ cdef array op = newarrayobject(Py_TYPE(template), length, descr) + if zero and op is not None: - memset(op.data.as_chars, 0, length * op.ob_descr.itemsize) -- return op -+ return clonearray(template, length) ++ memset(op.data.as_chars, 0, length * descr.itemsize) + return op cdef inline array copy(array self): """ make a copy of an array. """ +- cdef array op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr) +- memcpy(op.data.as_chars, self.data.as_chars, Py_SIZE(op) * op.ob_descr.itemsize) ++ cdef Py_ssize_t length = Py_SIZE(self) ++ cdef arraydescr* descr = self.ob_descr ++ cdef array op = newarrayobject(Py_TYPE(self), length, descr) ++ memcpy(op.data.as_chars, self.data.as_chars, length * descr.itemsize) + return op + + cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n) except -1: +@@ -175,4 +181,4 @@ cdef inline int extend(array self, array other) except -1: + + cdef inline void zero(array self) noexcept: + """ set all elements of array to zero. """ +- memset(self.data.as_chars, 0, Py_SIZE(self) * self.ob_descr.itemsize) ++ memset(self.data.as_chars, 0, Py_SIZE(self) * self.ob_descr.itemsize) diff --git a/Cython/Utility/CythonFunction.c b/Cython/Utility/CythonFunction.c index 8131c86..aa67eda 100644 --- a/Cython/Utility/CythonFunction.c @@ -264,43 +294,51 @@ index b731f74..300758b 100644 return iterable; #endif diff --git a/Cython/Utility/arrayarray.h b/Cython/Utility/arrayarray.h -index 2f7f0a5..b131885 100644 +index 2f7f0a5..ba32c0f 100644 --- a/Cython/Utility/arrayarray.h +++ b/Cython/Utility/arrayarray.h -@@ -106,6 +106,36 @@ PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size, - struct arraydescr *descr); - #endif /* ifndef NO_NEWARRAY_INLINE */ +@@ -23,7 +23,7 @@ + // below. That's defined later because the appropriate get and set + // functions aren't visible yet. + typedef struct arraydescr { +- int typecode; ++ char typecode; + int itemsize; + PyObject * (*getitem)(struct arrayobject *, Py_ssize_t); + int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); +@@ -64,10 +64,27 @@ struct arrayobject { + int ob_exports; /* Number of exported buffers */ + }; -+static CYTHON_INLINE PyObject* clonearray(PyObject *template_array, Py_ssize_t size) { -+#if CYTHON_COMPILING_IN_GRAAL -+ PyObject* op = NULL; -+ PyObject* module = NULL; -+ PyObject* typecode = PyObject_GetAttrString(template_array, "typecode"); -+ if (typecode == NULL) { -+ goto cleanup; -+ } -+ module = PyImport_ImportModule("array"); -+ if (module == NULL) { -+ goto cleanup; -+ } -+ op = PyObject_CallMethod(module, "array", "O", typecode); -+ if (op == NULL) { -+ goto cleanup; -+ } -+ if (GraalPyArray_Resize(op, size) < 0) { -+ Py_DECREF(op); -+ op = NULL; -+ } -+cleanup: -+ Py_XDECREF(typecode); -+ Py_XDECREF(module); -+ return op; ++#if CYTHON_COMPILING_IN_GRAAL && defined(GRAALPY_VERSION_NUM) && GRAALPY_VERSION_NUM >= 0x190304a0 ++#define __PYX_USE_GRAALPY_ARRAY_API 1 +#else -+ arrayobject *array = (arrayobject *) template_array; -+ return newarrayobject(Py_TYPE(template_array), size, array->ob_descr); ++#define __PYX_USE_GRAALPY_ARRAY_API 0 ++#endif ++ ++static CYTHON_INLINE struct arraydescr *__Pyx_PyArray_Descr(arrayobject *self) { ++#if __PYX_USE_GRAALPY_ARRAY_API ++ return (struct arraydescr *)GraalPyArray_GetDescriptor((PyObject*)self); ++#else ++ return self->ob_descr; +#endif +} + - static CYTHON_INLINE __Pyx_data_union __Pyx_PyArray_Data(arrayobject *self) { - #if CYTHON_COMPILING_IN_GRAAL - __Pyx_data_union data; + #ifndef NO_NEWARRAY_INLINE + // fast creation of a new array + static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size, + struct arraydescr *descr) { ++#if __PYX_USE_GRAALPY_ARRAY_API ++ return GraalPyArray_New((PyObject*)type, size, (GraalPyArray_Descriptor*)descr); ++#else + arrayobject *op; + size_t nbytes; + +@@ -100,6 +117,7 @@ static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t si + } + } + return (PyObject *) op; ++#endif + } + #else + PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size, diff --git a/graalpython/lib-graalpython/patches/librt-0.10.0.patch b/graalpython/lib-graalpython/patches/librt-0.10.0.patch index e3e7e555ee..43478c1d7c 100644 --- a/graalpython/lib-graalpython/patches/librt-0.10.0.patch +++ b/graalpython/lib-graalpython/patches/librt-0.10.0.patch @@ -89,6 +89,39 @@ index 6309ed5..2851067 100644 } #define CPy_INCREF_NO_IMM(op) CPy_INCREF_NO_IMM((PyObject *)(op)) +diff --git a/pythoncapi_compat.h b/pythoncapi_compat.h +index 245050b..d04cb65 100644 +--- a/pythoncapi_compat.h ++++ b/pythoncapi_compat.h +@@ -1576,7 +1576,7 @@ static inline int PyLong_IsZero(PyObject *obj) + // gh-124502 added PyUnicode_Equal() to Python 3.14.0a0 + #if PY_VERSION_HEX < 0x030E00A0 + +-#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION) ++#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION) && !defined(GRAALPY_VERSION_NUM) + PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2); + #endif + +@@ -1593,7 +1593,9 @@ static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2) + return -1; + } + +-#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION) ++#if defined(GRAALPY_VERSION_NUM) ++ return PyObject_RichCompareBool(str1, str2, Py_EQ); ++#elif PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION) + return _PyUnicode_Equal(str1, str2); + #elif PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION) + return _PyUnicode_EQ(str1, str2); +@@ -2674,7 +2676,7 @@ PyUnstable_Unicode_GET_CACHED_HASH(PyObject *op) + } + #endif + +-#if 0x030D0000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030F00A7 && !defined(PYPY_VERSION) ++#if 0x030D0000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030F00A7 && !defined(PYPY_VERSION) && !defined(GRAALPY_VERSION_NUM) + // Immortal objects were implemented in Python 3.12, however there is no easy API + // to make objects immortal until 3.14 which has _Py_SetImmortal(). Since + // immortal objects are primarily needed for free-threading, this API is implemented diff --git a/pythonsupport.c b/pythonsupport.c index 0a99f0a..1a442bb 100644 --- a/pythonsupport.c @@ -142,10 +175,27 @@ index 0a99f0a..1a442bb 100644 // Slow path of CPyLong_AsSsize_tAndOverflow (non-inlined) Py_ssize_t diff --git a/pythonsupport.h b/pythonsupport.h -index 6f38a9b..0e89511 100644 +index 6f38a9b..c636aec 100644 --- a/pythonsupport.h +++ b/pythonsupport.h -@@ -40,7 +40,15 @@ int init_subclass(PyTypeObject *type, PyObject *kwds); +@@ -18,10 +18,16 @@ + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE + #endif ++#ifdef GRAALPY_VERSION_NUM ++PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); ++PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *); ++PyAPI_FUNC(PyObject *) _PyErr_FormatFromCause(PyObject *, const char *, ...); ++#else + #include "internal/pycore_genobject.h" // _PyGen_FetchStopIterationValue + #include "internal/pycore_pyerrors.h" // _PyErr_FormatFromCause, _PyErr_SetKeyError + #include "internal/pycore_setobject.h" // _PySet_Update + #endif ++#endif + + #if CPY_3_12_FEATURES + #include "internal/pycore_frame.h" +@@ -40,7 +46,15 @@ int init_subclass(PyTypeObject *type, PyObject *kwds); Py_ssize_t CPyLong_AsSsize_tAndOverflow_(PyObject *vv, int *overflow); @@ -162,7 +212,7 @@ index 6f38a9b..0e89511 100644 static inline Py_ssize_t CPyLong_AsSsize_tAndOverflow(PyObject *vv, int *overflow) -@@ -117,6 +125,7 @@ CPyLong_AsSsize_tAndOverflow(PyObject *vv, int *overflow) +@@ -117,6 +131,7 @@ CPyLong_AsSsize_tAndOverflow(PyObject *vv, int *overflow) #endif // Adapted from listobject.c in Python 3.7.0 @@ -170,7 +220,7 @@ index 6f38a9b..0e89511 100644 static int list_resize(PyListObject *self, Py_ssize_t newsize) { -@@ -162,6 +171,7 @@ list_resize(PyListObject *self, Py_ssize_t newsize) +@@ -162,6 +177,7 @@ list_resize(PyListObject *self, Py_ssize_t newsize) self->allocated = new_allocated; return 0; } @@ -178,7 +228,7 @@ index 6f38a9b..0e89511 100644 // Changed to use PyList_SetSlice instead of the internal list_ass_slice static PyObject * -@@ -182,6 +192,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index) +@@ -182,6 +198,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index) return NULL; } v = PySequence_Fast_ITEMS((PyObject*)self)[index]; @@ -186,7 +236,7 @@ index 6f38a9b..0e89511 100644 if (index == Py_SIZE(self) - 1) { status = list_resize(self, Py_SIZE(self) - 1); if (status >= 0) -@@ -189,6 +200,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index) +@@ -189,6 +206,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index) else return NULL; } diff --git a/graalpython/lib-graalpython/patches/metadata.toml b/graalpython/lib-graalpython/patches/metadata.toml index cb1a98f320..3f19294db8 100644 --- a/graalpython/lib-graalpython/patches/metadata.toml +++ b/graalpython/lib-graalpython/patches/metadata.toml @@ -24,7 +24,7 @@ patch = 'cffi-1.16.0.patch' license = 'MIT' [[cloudpickle.rules]] -version = '== 2.2.1' +version = '>= 2.2.1' patch = 'cloudpickle-2.2.1.patch' license = 'BSD-3-Clause' diff --git a/graalpython/lib-graalpython/patches/torch-2.10.0.patch b/graalpython/lib-graalpython/patches/torch-2.10.0.patch index 4d4a2fccb3..1d82930f1d 100644 --- a/graalpython/lib-graalpython/patches/torch-2.10.0.patch +++ b/graalpython/lib-graalpython/patches/torch-2.10.0.patch @@ -767,7 +767,7 @@ index 6a8bbe990..d77fde704 100644 if (!m) throw python_error(); diff --git a/torch/csrc/dynamo/cpython_defs.c b/torch/csrc/dynamo/cpython_defs.c -index e0cb3bfe2..c98d75851 100644 +index e0cb3bfe2..d837740b9 100644 --- a/torch/csrc/dynamo/cpython_defs.c +++ b/torch/csrc/dynamo/cpython_defs.c @@ -28,6 +28,7 @@ void init_THPCaches() {} @@ -787,19 +787,57 @@ index e0cb3bfe2..c98d75851 100644 // As a simple way to reduce the impact of ABI changes on the CPython side, this // check forces us to manually re-check that the function didn't change on the // next major version -@@ -349,9 +352,11 @@ void THP_PyFrame_Clear(_PyInterpreterFrame* frame) { +@@ -204,12 +207,15 @@ PyFrameObject* THP_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame* frame) { + // https://github.com/python/cpython/blob/e715da6db1d1d70cd779dc48e1ba8110c51cc1bf/Include/internal/pycore_frame.h#L163 + static inline PyFrameObject* THP_PyFrame_GetFrameObject( + _PyInterpreterFrame* frame) { ++#if 0 // GraalPy change + CHECK(!_PyFrame_IsIncomplete(frame)); + PyFrameObject* res = frame->frame_obj; + if (res != NULL) { + return res; + } + return THP_PyFrame_MakeAndSetFrameObject(frame); ++#endif // GraalPy change ++ abort(); + } + + #if IS_PYTHON_3_14_PLUS +@@ -262,6 +268,7 @@ static void THP_take_ownership(PyFrameObject* f, _PyInterpreterFrame* frame) { + // From + // https://github.com/python/cpython/blob/e715da6db1d1d70cd779dc48e1ba8110c51cc1bf/Python/frame.c#L79 + static void THP_take_ownership(PyFrameObject* f, _PyInterpreterFrame* frame) { ++#if 0 // GraalPy change + CHECK(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT); + CHECK(frame->owner != FRAME_CLEARED); + Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char*)frame; +@@ -299,6 +306,8 @@ static void THP_take_ownership(PyFrameObject* f, _PyInterpreterFrame* frame) { + if (!PyObject_GC_IsTracked((PyObject*)f)) { + PyObject_GC_Track((PyObject*)f); + } ++#endif // GraalPy change ++ abort(); + } + + #endif +@@ -347,6 +356,7 @@ void THP_PyFrame_Clear(_PyInterpreterFrame* frame) { + // From + // https://github.com/python/cpython/blob/e715da6db1d1d70cd779dc48e1ba8110c51cc1bf/Python/frame.c#L120 void THP_PyFrame_Clear(_PyInterpreterFrame* frame) { ++#if 0 // GraalPy change /* It is the responsibility of the owning generator/coroutine * to have cleared the enclosing generator, if any. */ -+#if 0 // GraalPy change CHECK( - frame->owner != FRAME_OWNED_BY_GENERATOR || - _PyFrame_GetGenerator(frame)->gi_frame_state == FRAME_CLEARED); +@@ -382,6 +392,8 @@ void THP_PyFrame_Clear(_PyInterpreterFrame* frame) { + Py_DECREF(frame->f_func); + #endif + Py_DECREF(F_CODE(frame)); +#endif // GraalPy change - // GH-99729: Clearing this frame can expose the stack (via finalizers). It's - // crucial that this frame has been unlinked, and is no longer visible: - #if IS_PYTHON_3_13_PLUS -@@ -496,7 +501,7 @@ void THP_PyThreadState_PopFrame( ++ abort(); + } + + #endif +@@ -496,7 +508,7 @@ void THP_PyThreadState_PopFrame( const uint8_t* THP_PyOpcode_Caches = NULL; int THP_PyOpcode_Caches_size = 0; void init_THPCaches() { diff --git a/graalpython/lib-python/3/dis.py b/graalpython/lib-python/3/dis.py index 4b12037c06..49bf53fa53 100644 --- a/graalpython/lib-python/3/dis.py +++ b/graalpython/lib-python/3/dis.py @@ -5,27 +5,46 @@ import collections import io -# GraalPy change: remove all the _opcode imports and dependent stuff - -# GraalPy change: add dummy opcode metadata for coverage.py -opmap = { - "EXTENDED_ARG": -1, - "JUMP_FORWARD": -1, - "RETURN_VALUE": -1, - "YIELD_VALUE": -1, - "YIELD_FROM": -1, -} -opname = [] -hasjabs = [] -hasjrel = [] +# GraalPy change: expose the stub opcode metadata without importing _opcode +from opcode import * +from opcode import __all__ as _opcodes_all __all__ = ["code_info", "dis", "disassemble", "distb", "disco", "findlinestarts", "findlabels", "show_code", - "get_instructions", "Instruction", "Bytecode"] + "get_instructions", "Instruction", "Bytecode"] + _opcodes_all +del _opcodes_all _have_code = (types.MethodType, types.FunctionType, types.CodeType, classmethod, staticmethod, type) +CONVERT_VALUE = opmap['CONVERT_VALUE'] + +SET_FUNCTION_ATTRIBUTE = opmap['SET_FUNCTION_ATTRIBUTE'] +FUNCTION_ATTR_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure') + +ENTER_EXECUTOR = opmap['ENTER_EXECUTOR'] +LOAD_CONST = opmap['LOAD_CONST'] +RETURN_CONST = opmap['RETURN_CONST'] +LOAD_GLOBAL = opmap['LOAD_GLOBAL'] +BINARY_OP = opmap['BINARY_OP'] +JUMP_BACKWARD = opmap['JUMP_BACKWARD'] +FOR_ITER = opmap['FOR_ITER'] +SEND = opmap['SEND'] +LOAD_ATTR = opmap['LOAD_ATTR'] +LOAD_SUPER_ATTR = opmap['LOAD_SUPER_ATTR'] +CALL_INTRINSIC_1 = opmap['CALL_INTRINSIC_1'] +CALL_INTRINSIC_2 = opmap['CALL_INTRINSIC_2'] +LOAD_FAST_LOAD_FAST = opmap['LOAD_FAST_LOAD_FAST'] +STORE_FAST_LOAD_FAST = opmap['STORE_FAST_LOAD_FAST'] +STORE_FAST_STORE_FAST = opmap['STORE_FAST_STORE_FAST'] + +CACHE = opmap["CACHE"] + +_all_opname = list(opname) +_all_opmap = dict(opmap) + +# GraalPy change +deoptmap = {} def _try_compile(source, name): """Attempts to compile the given source, first as an expression and diff --git a/graalpython/lib-python/3/opcode.py b/graalpython/lib-python/3/opcode.py index 5735686fa7..42d9a7532b 100644 --- a/graalpython/lib-python/3/opcode.py +++ b/graalpython/lib-python/3/opcode.py @@ -9,9 +9,7 @@ "HAVE_ARGUMENT", "EXTENDED_ARG", "hasarg", "hasconst", "hasname", "hasjump", "hasjrel", "hasjabs", "hasfree", "haslocal", "hasexc"] -import _opcode -from _opcode import stack_effect - +# GraalPy change: remove _opcode import from _opcode_metadata import (_specializations, _specialized_opmap, opmap, HAVE_ARGUMENT, MIN_INSTRUMENTED_OPCODE) EXTENDED_ARG = opmap['EXTENDED_ARG'] @@ -22,21 +20,26 @@ cmp_op = ('<', '<=', '==', '!=', '>', '>=') +# GraalPy change: empty stub +def stack_effect(opcode, oparg=None, /, *, jump=None): + raise NotImplementedError("'opcode' module is not supported on GraalPy") + + # These lists are documented as part of the dis module's API -hasarg = [op for op in opmap.values() if _opcode.has_arg(op)] -hasconst = [op for op in opmap.values() if _opcode.has_const(op)] -hasname = [op for op in opmap.values() if _opcode.has_name(op)] -hasjump = [op for op in opmap.values() if _opcode.has_jump(op)] +hasarg = [] +hasconst = [] +hasname = [] +hasjump = [] hasjrel = hasjump # for backward compatibility hasjabs = [] -hasfree = [op for op in opmap.values() if _opcode.has_free(op)] -haslocal = [op for op in opmap.values() if _opcode.has_local(op)] -hasexc = [op for op in opmap.values() if _opcode.has_exc(op)] +hasfree = [] +haslocal = [] +hasexc = [] -_intrinsic_1_descs = _opcode.get_intrinsic1_descs() -_intrinsic_2_descs = _opcode.get_intrinsic2_descs() -_nb_ops = _opcode.get_nb_ops() +_intrinsic_1_descs = [] +_intrinsic_2_descs = [] +_nb_ops = [] hascompare = [opmap["COMPARE_OP"]] diff --git a/mx.graalpython/downstream_tests.py b/mx.graalpython/downstream_tests.py index e4948235b3..fe9982c230 100644 --- a/mx.graalpython/downstream_tests.py +++ b/mx.graalpython/downstream_tests.py @@ -117,9 +117,6 @@ def downstream_test_virtualenv(graalpy, testdir): def downstream_test_pyo3(graalpy, testdir): run(['git', 'clone', 'https://github.com/PyO3/pyo3.git', '-b', 'main', '--depth', '1'], cwd=testdir) src = testdir / 'pyo3' - # The runtime test session does not run mypy. Avoid installing it because its - # librt dependency relies on CPython-internal APIs that are incompatible with GraalPy. - replace_in_file(src / 'pytests/pyproject.toml', r'^\s*"mypy[^\n]*\n', '', flags=re.MULTILINE) venv = src / 'venv' run([graalpy, '-m', 'venv', str(venv)]) run_in_venv(venv, ['python', '-m', 'pip', 'install', '--upgrade', 'pip', 'nox[uv]']) diff --git a/mx.graalpython/mx_graalpython_bisect.py b/mx.graalpython/mx_graalpython_bisect.py index c696c806cc..f42f5f8213 100644 --- a/mx.graalpython/mx_graalpython_bisect.py +++ b/mx.graalpython/mx_graalpython_bisect.py @@ -305,10 +305,15 @@ def checkout(repo_path: Path, commit): if repo_path == DIR: mx.run_mx(['sforceimports'], suite=str(DIR)) if args.enterprise: + # Keep the Graal revision selected by the current bisection point. The + # enterprise suite imports Graal, so its sforceimports would otherwise + # replace that revision with the one recorded in graal-enterprise. + graal_commit = get_commit(GRAAL_DIR) if repo_path.name != 'graal-enterprise': mx.run_mx(['--quiet', 'checkout-downstream', 'vm', 'vm-enterprise', '--no-fetch'], suite=str(VM_ENTERPRISE_DIR)) mx.run_mx(['--dy', 'substratevm-enterprise-gcs', 'sforceimports'], suite=str(VM_ENTERPRISE_DIR)) + GIT.update_to_branch(GRAAL_DIR, graal_commit) debug_str = f"debug: {SUITE.name}={get_commit(SUITE.vc_dir)} graal={get_commit(GRAAL_DIR)}" if args.enterprise: debug_str += f" graal-enterprise={get_commit(GRAAL_ENTERPRISE_DIR)}" @@ -343,7 +348,7 @@ def checkout_and_build(repo_path, commit): build_command = shlex.split(args.build_command) if not args.no_clean: try: - clean_command = build_command[:build_command.index('build')] + ['clean'] + clean_command = build_command[:build_command.index('build')] + ['clean', '--all', '--aggressive'] retcode = mx.run(clean_command, nonZeroIsFatal=False) if retcode: print("Warning: clean command failed") diff --git a/scripts/bisect_benchmark_regression.py b/scripts/bisect_benchmark_regression.py index 1207b5adbe..de28a01917 100644 --- a/scripts/bisect_benchmark_regression.py +++ b/scripts/bisect_benchmark_regression.py @@ -105,10 +105,17 @@ def parse_args() -> argparse.Namespace: description="Generate and optionally submit a bisect-benchmark CI workflow for a benchmark regression.", ) parser.add_argument("benchmark_job_name", help="Benchmark job key, for example pybench-micro-graalvm_ee_default-post_merge-linux-amd64-jdk-latest.") - parser.add_argument("benchmark_name", help="Benchmark selector to narrow the benchmark command to a single benchmark.") + parser.add_argument("benchmark_name", help="Benchmark result name to bisect.") parser.add_argument("metric", help="Benchmark metric name, or WORKS.") parser.add_argument("good_commit", help="Known good GraalPy commit or ref.") parser.add_argument("bad_commit", help="Known bad GraalPy commit or ref.") + parser.add_argument( + "--benchmark-selector", + help=( + "Benchmark selector used to narrow the benchmark command. Defaults to benchmark_name. " + "Use this when a harness selector produces several separately named results." + ), + ) parser.add_argument("--config-only", action="store_true", help="Print the generated bisect config and exit.") parser.add_argument("--force-rebuild", action="store_true", help="Submit a fresh bisect job even if one already exists.") parser.add_argument("--debug", action="store_true", help="Print progress information to stderr.") @@ -153,16 +160,19 @@ def abbreviate_commit(commit: str) -> str: return commit[:12] -def build_branch_name(job_name: str, benchmark_name: str, metric: str, good_commit: str, bad_commit: str) -> str: - slug = "_".join( - [ - job_name, - benchmark_name, - metric, - abbreviate_commit(good_commit), - abbreviate_commit(bad_commit), - ] - ) +def build_branch_name( + job_name: str, + benchmark_name: str, + metric: str, + good_commit: str, + bad_commit: str, + benchmark_selector: str | None = None, +) -> str: + parts = [job_name, benchmark_name] + if benchmark_selector: + parts.append(benchmark_selector) + parts.extend([metric, abbreviate_commit(good_commit), abbreviate_commit(bad_commit)]) + slug = "_".join(parts) return "bisect/{}".format(slug) @@ -487,7 +497,7 @@ def write_temp_branch(repo_dir: Path, branch_name: str, config_text: str) -> str run_command(["git", "add", *[str(path) for path in BRANCH_SUPPORT_FILES]], cwd=clone_dir) run_command(["git", "commit", "-m", commit_message], cwd=clone_dir) commit = resolve_commit(clone_dir, "HEAD") - run_command(["git", "push", "origin", "HEAD:refs/heads/{}".format(branch_name)], cwd=clone_dir) + run_command(["git", "push", "--force", "origin", "HEAD:refs/heads/{}".format(branch_name)], cwd=clone_dir) debug("Pushed branch {} at {}".format(branch_name, commit)) return commit @@ -509,6 +519,7 @@ def generate_config( repo_dir: Path, benchmark_job_name: str, benchmark_name: str, + benchmark_selector: str | None, metric: str, good_commit: str, bad_commit: str, @@ -516,7 +527,7 @@ def generate_config( reference_build = get_reference_build(repo_dir, benchmark_job_name, bad_commit, good_commit) debug("Using reference build {} ({})".format(reference_build.build_number, reference_build.url)) build_log = run_command(["gdev-cli", "buildbot", "get-log", str(reference_build.build_number)], cwd=repo_dir) - build_command, benchmark_command = extract_commands(build_log, benchmark_name) + build_command, benchmark_command = extract_commands(build_log, benchmark_selector or benchmark_name) results_benchmark_name = None if metric == "WORKS" else benchmark_selector_for_command(benchmark_name) enterprise = "enterprise" in build_command return build_config_text( @@ -543,6 +554,7 @@ def main() -> int: repo_dir=repo_dir, benchmark_job_name=args.benchmark_job_name, benchmark_name=args.benchmark_name, + benchmark_selector=args.benchmark_selector, metric=args.metric, good_commit=good_commit, bad_commit=bad_commit, @@ -558,11 +570,12 @@ def main() -> int: args.metric, good_commit, bad_commit, + args.benchmark_selector, ) debug("Branch name: {}".format(branch_name)) branch_head = get_remote_branch_head(repo_dir, branch_name) - if branch_head is None: + if branch_head is None or args.force_rebuild: branch_head = write_temp_branch(repo_dir, branch_name, config_text) wait_for_enumeration( repo_dir, @@ -577,7 +590,7 @@ def main() -> int: else: debug("Remote branch head: {}".format(branch_head)) existing_builds = get_matching_builds(repo_dir, branch_head, BISECT_JOB_NAME) - if existing_builds and not args.force_rebuild: + if existing_builds: build = wait_for_bisect_build(repo_dir, branch_head) else: wait_for_enumeration( diff --git a/scripts/get_pypi_source.py b/scripts/get_pypi_source.py index 06a9d07d73..50f50ff306 100755 --- a/scripts/get_pypi_source.py +++ b/scripts/get_pypi_source.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 # Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -37,8 +38,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -#!/usr/bin/python - import argparse import builtins import json