Sitelet https://github.com/starkware-libs/cairo/pull/10191
Skip to content

(opt): store syntax node offsets relative to parent so get_children ignores position - #10191

Merged
eytan-starkware merged 1 commit into
mainfrom
eytan_graphite/syntax-offset-relative-to-parent
Jul 8, 2026
Merged

eytan-starkware merged 1 commit into
mainfrom
eytan_graphite/syntax-offset-relative-to-parent

Conversation

@eytan-starkware

@eytan-starkware eytan-starkware commented Jul 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Stores syntax node offsets relative to the parent (computed from the parent green alone, starting at 0) instead of as absolute file offsets. This makes get_children depend only on the green tree, so a structure-preserving edit that merely shifts a subtree no longer re-executes it. The absolute offset is recovered on demand by SyntaxNode::offset via a new absolute_offset tracked query.


Type of change

Please check one:

  • Bug fix (fixes incorrect behavior)
  • New feature
  • Performance improvement
  • Documentation change with concrete technical impact
  • Style, wording, formatting, or typo-only change

Why is this change needed?

get_children read the node's absolute offset to seed its children's offsets, so any edit that shifted a subtree (without changing its structure) invalidated get_children for the entire tail of the file — O(tail) re-execution for any insert/delete.


What was the behavior or documentation before?

Children stored absolute file offsets seeded from their parent's absolute offset. An insert/delete that shifted a subtree invalidated get_children for the whole tail of the file, even though the subtree's structure was unchanged.


What is the behavior or documentation after?

Children store offsets relative to their parent, so get_children depends only on the green tree and is position-independent. The absolute offset is recovered by SyntaxNode::offset via absolute_offset — a tracked query summing the relative offsets up the parent chain, memoized per node (O(1) amortized instead of an O(depth) walk per call; an edit recomputes only the shifted nodes actually queried).

It is a salsa query rather than a cache inside node data because get_children output is position-independent and backdatable — an absolute position cached in it would go stale — and as a query it gets revision-aware invalidation and backdating for free.

Measured on the ls_reexec structural-edit scenario (insert one const statement atop a 400-statement body): get_children re-executions drop from 1612 to 12 — identical to the end-insert control, i.e. fully position-independent. Total per-edit executions go 4139 → 2943; of the remainder, 404 are the trivial absolute_offset re-sums for the shifted statements (the control re-executes 4), and the rest is a position-correlated semantic wave (impl/trait-signature queries) plus the per-edit file_content wave shared by every scenario — both outside this fix's scope.


Related issue or discussion (if any)

Part of a stack with #10189 (regression benchmark) and #10190 (child-index-by-kind fix). Requires the stable node ids from #10190 to be effective.


Additional context

The benchmark numbers above come from the scenario added in #10189.

eytan-starkware commented Jul 6, 2026 •

Copy link
Copy Markdown
Contributor Author

@reviewable-StarkWare

Copy link
Copy Markdown

This change is Reviewable

@eytan-starkware
eytan-starkware marked this pull request as ready for review July 6, 2026 05:55
@cursor

cursor Bot commented Jul 6, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes how every syntax node’s span base is computed and memoized in salsa; wrong offsets would break lookups and IDE spans, though the public offset() contract is unchanged.

Overview
Syntax nodes now store offset_in_parent (relative to the parent, file start for roots) instead of absolute file offsets in tracked data. get_children_impl seeds child positions from TextOffset::START, so child lists depend only on the green tree and no longer re-run when an edit merely shifts a subtree.

SyntaxNode::offset still returns the absolute position, but via a new salsa absolute_offset query that walks up the parent chain with memoization (chosen over caching in node data so shifted-but-unchanged subtrees can be backdated correctly).

Reviewed by Cursor Bugbot for commit 57c5a51. Bugbot is set up for automated code reviews on this repo. Configure here.

@orizi orizi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@orizi reviewed 1 file and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on TomerStarkware).

@eytan-starkware
eytan-starkware force-pushed the eytan_graphite/syntax-child-index-kind-fix branch from 8be9353 to 711e476 Compare July 7, 2026 13:45
@eytan-starkware
eytan-starkware force-pushed the eytan_graphite/syntax-offset-relative-to-parent branch from ae4c9df to 57c5a51 Compare July 7, 2026 13:45
@eytan-starkware
eytan-starkware changed the base branch from eytan_graphite/syntax-child-index-kind-fix to main July 7, 2026 13:56

@orizi orizi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi made 1 comment.
Reviewable status: 0 of 2 files reviewed, 1 unresolved discussion (waiting on eytan-starkware and TomerStarkware).


-- commits line 3 at r2:
rebase

…gnores position

get_children read the node's absolute offset to seed its children's offsets, so any edit that shifted a subtree (without changing its structure) invalidated get_children for the entire tail of the file — O(tail) re-execution for any insert/delete. Now children store offsets RELATIVE to their parent (computed from the parent green alone, starting at 0), so get_children depends only on the green tree: a structure-preserving edit that merely shifts a subtree no longer re-executes it.

The absolute offset is recovered by SyntaxNode::offset via absolute_offset — a tracked query summing the relative offsets up the parent chain, memoized per node (O(1) amortized instead of an O(depth) walk per call; an edit recomputes only the shifted nodes actually queried). It is a salsa query rather than a cache inside node data because get_children output is position-independent and backdatable — an absolute position cached in it would go stale; the query gets revision-aware invalidation and backdating for free.

Measured on the ls_reexec structural-edit scenario (insert one const statement atop a 400-statement body): get_children re-executions drop from 1612 to 12 — identical to the end-insert control, i.e. fully position-independent. Total per-edit executions go 4139 -> 2943; of the remainder, 404 are the trivial absolute_offset re-sums for the shifted statements (the control re-executes 4), and the rest is a position-correlated semantic wave (impl/trait-signature queries) plus the per-edit file_content wave shared by every scenario — both outside this fix's scope. Requires the stable node ids from the child-index fix below it to be effective.
@eytan-starkware
eytan-starkware force-pushed the eytan_graphite/syntax-offset-relative-to-parent branch from 57c5a51 to f1247b0 Compare July 8, 2026 08:07

@orizi orizi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi reviewed 2 files and all commit messages, and resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on TomerStarkware).

@eytan-starkware
eytan-starkware added this pull request to the merge queue Jul 8, 2026
Merged via the queue into main with commit bbba07e Jul 8, 2026
55 checks passed
@eytan-starkware
eytan-starkware deleted the eytan_graphite/syntax-offset-relative-to-parent branch July 20, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants