-
Notifications
You must be signed in to change notification settings - Fork 19
jit: heal nested for-range degenerate loop; virtualize range GET_ITER/FOR_ITER #683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -631,6 +631,10 @@ pub enum PyreHelperKind { | |
| /// the in-flight iteration to the live frame instead of dropping it (the | ||
| /// iterator advance is an irreversible side effect with no journal undo). | ||
| ForIterNext, | ||
| /// `get_iter(obj)` — the GET_ITER residual (`iter(obj)`). The full-body | ||
| /// walker recognises exact machine-word `range` objects and emits the | ||
| /// virtual `W_IntRangeIterator` allocation shape directly. | ||
| GetIter, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Useful? React with 👍 / 👎.
coderabbitai[bot] marked this conversation as resolved.
|
||
| /// `store_deref_value(cell, value)` — the STORE_DEREF residual | ||
| /// (`bh_store_deref_value_fn` via `cpu.store_deref_value_fn`). It mutates | ||
| /// the cell's contents in place and RETURNS the slot value (`Ref`), so it | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -902,6 +902,45 @@ static RANGE_ITER_DESCR_GROUP: LazyLock<PyreObjectDescrGroup> = LazyLock::new(|| | |
| ) | ||
| }); | ||
|
|
||
| static RANGE_DESCR_GROUP: LazyLock<PyreObjectDescrGroup> = LazyLock::new(|| { | ||
| build_object_descr_group_with_def_path( | ||
| std::mem::size_of::<W_Range>(), | ||
| pyre_object::functional::W_RANGE_GC_TYPE_ID, | ||
| &pyre_object::functional::RANGE_TYPE as *const _ as usize, | ||
| &[ | ||
| ( | ||
| "W_Range.start", | ||
| RANGE_START_OFFSET, | ||
| 8, | ||
| Type::Ref, | ||
| false, | ||
| true, | ||
| false, | ||
| ), | ||
| ( | ||
| "W_Range.step", | ||
| RANGE_STEP_OFFSET, | ||
|
Comment on lines
+920
to
+922
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When this new Useful? React with 👍 / 👎. |
||
| 8, | ||
| Type::Ref, | ||
| false, | ||
| true, | ||
| false, | ||
| ), | ||
| ( | ||
| "W_Range.length", | ||
| RANGE_LENGTH_OFFSET, | ||
| 8, | ||
| Type::Ref, | ||
| false, | ||
| true, | ||
| false, | ||
| ), | ||
| ], | ||
| "W_Range", | ||
| "functional::W_Range", | ||
| ) | ||
| }); | ||
|
|
||
|
Comment on lines
+905
to
+943
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
rg -n 'field_size|PyreFieldDescr|wasm32|wasm' pyre majitRepository: youknowone/pyre Length of output: 50372 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect the W_Range descriptor and nearby type definitions.
sed -n '850,980p' pyre/pyre-jit-trace/src/descr.rs
printf '\n---\n'
# Find the W_Range struct definition and PyObjectRef alias.
rg -n 'struct W_Range|type PyObjectRef|pub struct PyObjectRef|enum PyObjectRef' pyre/pyre-interpreter/src pyre/pyre-jit-trace/src
printf '\n---\n'
# Inspect how field_size is interpreted in the JIT/runtime.
sed -n '9738,9845p' pyre/pyre-jit-trace/src/state.rs
printf '\n---\n'
# Inspect any explicit pointer-size handling around descriptor field sizes.
rg -n 'size_of::<PyObjectRef>|pointer_size|field_size: std::mem::size_of::<usize>|field_size: 8' pyre/pyre-jit-trace/src pyre/pyre-interpreter/srcRepository: youknowone/pyre Length of output: 10762 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Narrower probe: look for W_Range fields and any target-layout annotations.
ast-grep outline pyre/pyre-interpreter/src pyre/pyre-jit-trace/src --match W_RangeRepository: youknowone/pyre Length of output: 167 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Focused search for the exact descriptor group and related comments.
rg -n -A6 -B6 'RANGE_DESCR_GROUP|W_Range\.start|W_Range\.step|W_Range\.length' pyre/pyre-jit-trace/src/descr.rsRepository: youknowone/pyre Length of output: 2360 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Locate the PyObjectRef definition and any target-width assumptions.
rg -n -A4 -B4 'pub type PyObjectRef|struct PyObjectRef|enum PyObjectRef|type PyObjectRef' pyre
printf '\n---\n'
# Inspect the interpreter-side type alias/definition if found.
for f in $(rg -l 'pub type PyObjectRef|struct PyObjectRef|enum PyObjectRef|type PyObjectRef' pyre); do
echo "FILE: $f"
sed -n '1,120p' "$f" | rg -n 'PyObjectRef|PyObject|usize|u64|u32|NonZero|Tagged'
echo
done
printf '\n---\n'
# Check the descriptor API for any notes on Ref field sizing.
sed -n '1,140p' pyre/pyre-jit-trace/src/descr.rsRepository: youknowone/pyre Length of output: 9102 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect references to the exact field-size convention for Ref fields.
rg -n -A3 -B3 'Type::Ref|field_size.*Ref|wrapped PyObjectRef|pointer_size\(\)|size_of::<PyObjectRef>' pyre/pyre-jit-trace/src pyre/pyre-interpreter/src pyre/pyre-object/srcRepository: youknowone/pyre Length of output: 50372 Use pointer width for 🤖 Prompt for AI Agents |
||
| /// `Method` field layout — `w_function`, `w_self`, `w_class` per | ||
| /// `function.rs:9-15`. All three are Ref slots; the JIT only consumes | ||
| /// `w_function` (for guarding which method) and `w_self` (for recovering | ||
|
|
@@ -1689,6 +1728,7 @@ pub fn make_array_descr_with_full_id( | |
| use pyre_object::floatobject::{FLOAT_FLOATVAL_OFFSET, W_FloatObject}; | ||
| use pyre_object::functional::{ | ||
| RANGE_ITER_CURRENT_OFFSET, RANGE_ITER_REMAINING_OFFSET, RANGE_ITER_STEP_OFFSET, | ||
| RANGE_LENGTH_OFFSET, RANGE_START_OFFSET, RANGE_STEP_OFFSET, W_Range, | ||
| }; | ||
| use pyre_object::interp_exceptions::{ | ||
| EXC_ARGS_W_OFFSET, EXC_KIND_COUNT, EXC_KIND_OFFSET, EXC_W_ATTR_OBJ_OFFSET, EXC_W_CAUSE_OFFSET, | ||
|
|
@@ -1763,6 +1803,21 @@ pub fn range_iter_step_descr() -> DescrRef { | |
| field_descr_from_group(&RANGE_ITER_DESCR_GROUP, 2) | ||
| } | ||
|
|
||
| /// Field descriptor for `W_Range.start` (wrapped PyObjectRef). | ||
| pub fn range_start_descr() -> DescrRef { | ||
| field_descr_from_group(&RANGE_DESCR_GROUP, 0) | ||
| } | ||
|
|
||
| /// Field descriptor for `W_Range.step` (wrapped PyObjectRef). | ||
| pub fn range_step_descr() -> DescrRef { | ||
| field_descr_from_group(&RANGE_DESCR_GROUP, 1) | ||
| } | ||
|
|
||
| /// Field descriptor for `W_Range.length` (wrapped PyObjectRef). | ||
| pub fn range_length_descr() -> DescrRef { | ||
| field_descr_from_group(&RANGE_DESCR_GROUP, 2) | ||
| } | ||
|
|
||
| /// `Method.w_function` — the underlying function (`Function` or | ||
| /// `BuiltinFunction`) bound by `getattr(obj, name)`. Marked immutable | ||
| /// per `pypy/interpreter/function.py:567` `_Method._immutable_fields_`, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the only FINISH on a compiled CALL_ASSEMBLER target is
ExitFrameWithException(or there is noDoneWithThisFrame), this new filter leaves no clean match but the following.unwrap_or(0)still publishes fail index 0 as the clean finish. The wasm CA arm treatsfi == loop_finish_fias a direct return from F'[1], so an exception finish or guard assigned fail_index 0 bypasseswasm_ca_resume_deoptand is still misrouted; use the existingWASM_CA_FINISH_FI_UNKNOWNsentinel here, and similarly for the bridge finish selector, when no clean finish exists.Useful? React with 👍 / 👎.