mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Align Python 3.15 bytecode tooling (#9344)
Extract independent bytecode tooling from the Python 3.15 integration. Decode packed import-name arguments without changing older-interpreter fallback behavior, validate canonical opcode numbering, bound deoptimization families to the enum, and reuse parsed CPython analysis. Validated generators reproduce tracked metadata exactly; normal, lazy and eager import fallback matches canonical disassembly. No interpreter, generated metadata or test changes. Assisted-by: OpenAI Codex: model version unavailable
This commit is contained in:
1 parent
db4878080a
commit
65ee7bae8b
3 files changed
+27
-3
No files matched your search
+11
-1
@@ -170,12 +170,22 @@ def _resolve_arg_fallback(code, opname, arg):
|
||||
"LOAD_ATTR",
|
||||
"STORE_ATTR",
|
||||
"DELETE_ATTR",
|
||||
"IMPORT_NAME",
|
||||
"IMPORT_FROM",
|
||||
"LOAD_FROM_DICT_OR_GLOBALS",
|
||||
):
|
||||
if 0 <= arg < len(code.co_names):
|
||||
return code.co_names[arg]
|
||||
elif opname == "IMPORT_NAME":
|
||||
name_idx, policy = arg, 0
|
||||
if sys.version_info >= (3, 15):
|
||||
name_idx, policy = arg >> 2, arg & 3
|
||||
if 0 <= name_idx < len(code.co_names):
|
||||
name = code.co_names[name_idx]
|
||||
if policy & 1 and name:
|
||||
return f"{name} + lazy"
|
||||
if policy & 2 and name:
|
||||
return f"{name} + eager"
|
||||
return name
|
||||
elif opname == "LOAD_SUPER_ATTR":
|
||||
name_idx = arg >> 2
|
||||
if 0 <= name_idx < len(code.co_names):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import functools
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
@@ -18,6 +19,7 @@ from analyzer import SKIP_PROPERTIES, Analysis, Family, Properties, analyze_file
|
||||
from stack import get_stack_effect
|
||||
|
||||
|
||||
@functools.cache
|
||||
def get_analysis() -> Analysis:
|
||||
from generators_common import DEFAULT_INPUT
|
||||
|
||||
|
||||
@@ -33,10 +33,11 @@ class OpcodeInfo:
|
||||
|
||||
for member in family.members:
|
||||
member_name = to_pascal_case(member.name)
|
||||
if member.name == family_name:
|
||||
if member_name == family_name or member_name not in names:
|
||||
continue
|
||||
|
||||
res[family_name].append(member_name)
|
||||
if member_name not in res[family_name]:
|
||||
res[family_name].append(member_name)
|
||||
|
||||
return dict(res)
|
||||
|
||||
@@ -76,6 +77,17 @@ def iter_opcodes(text: str, override_confs: OverrideConfs) -> Iterable[Opcode]:
|
||||
opcode = Opcode.from_str(entry)
|
||||
|
||||
rust_name = opcode.rust_name
|
||||
# Shared opcodes use CPython's wire-format IDs; RustPython-only
|
||||
# instructions must occupy an otherwise unused slot.
|
||||
expected_id = analysis.opmap.get(opcode.cpython_name)
|
||||
if expected_id is not None and opcode.id != expected_id:
|
||||
raise ValueError(
|
||||
f"{rust_name} has opcode ID {opcode.id}; CPython requires {expected_id}"
|
||||
)
|
||||
if expected_id is None and opcode.id in analysis.opmap.values():
|
||||
raise ValueError(
|
||||
f"RustPython-only opcode {rust_name} collides with CPython ID {opcode.id}"
|
||||
)
|
||||
override = override_confs.get(rust_name, SKIP_OVERRIDE)
|
||||
|
||||
cpython_name = opcode.cpython_name
|
||||
|
||||
Reference in new issue
Block a user