Skip to content

Preserve compound index targets across exception regions - #618

Merged
dadhi merged 2 commits into
dadhi:masterfrom
jogibear9988:fix/compound-index-exceptions-standalone
Nov 10, 2026
Merged

dadhi merged 2 commits into
dadhi:masterfrom
jogibear9988:fix/compound-index-exceptions-standalone

Conversation

@jogibear9988

@jogibear9988 jogibear9988 commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Compound index assignments currently reject exception-region indices. Keep the target and indices in locals until all index expressions finish, then reload them for the getter and setter. Preserve the existing direct path for indices without exception regions. Use the aggressively inlined HasComplexArguments context helper for all five complex-argument lookups and EmitLoadLocalVariableOrAddress for the three matching receiver reloads in compound assignments and method calls. These helpers reuse existing metadata and emission without adding compiler-context fields.

Two-index indexers; exception regions in either index; add assignment, pre-increment and post-decrement; getter/setter counts, mutation, side effects and exceptions. Ordinary assignment fallback remains unchanged. Additional regressions cover concrete struct parameters, returned struct values and by-reference struct parameters, with and without exception-region indices; results, mutations and cleanup order are checked against System compilation. Regressions use strict FEC compilation for both Standard and LightExpression.

Validation

Release solution build: zero warnings/errors.

Runtime TestX groups Legacy tests
.NET 10 467 passed 1,756 passed
.NET 8 467 passed 1,755 passed
.NET Framework 4.7.2 446 passed 1,639 passed

Measurements

Current master ce28e2b0 → this change, Release, Windows ARM64, .NET 8.0.28 / 10.0.9. Compilation uses prebuilt trees; runtime measures invocation through the same wrapper. Two fresh process rounds with reversed load order, seven samples per round, about 30 ms calibration, one logical CPU and tiered compilation disabled. Tables use the median of the two per-round medians.

The controls below produce correct results on master for their measured inputs. Newly supported trees have no valid before/after execution comparison because master rejects them, produces incorrect results or emits invalid IL. Timings include machine and JIT/code-placement variation; the unchanged add control helps show that variation. These observations do not prove universal performance neutrality.

net8.0 results (master → change)
API / workload Compile ns Invoke ns Compile B/op Invoke B/op
Standard / add_control 1975.1 → 2330.3 2.1 → 2.3 872.0 → 872.0 0.0 → 0.0
Standard / new_arg_try 2668.7 → 2845.5 4.4 → 5.1 1528.2 → 1528.2 24.0 → 24.0
Standard / new_arg 1751.9 → 1951.1 4.8 → 4.6 936.1 → 936.1 24.0 → 24.0
Standard / struct_method_arg_try 2201.4 → 2161.3 2.1 → 2.1 1576.0 → 1576.0 0.0 → 0.0
Standard / struct_method_parameter_arg_try 2266.8 → 1882.6 2.0 → 2.0 1552.1 → 1552.1 0.0 → 0.0
Standard / array_bounds 1825.5 → 1718.0 42.8 → 37.2 960.0 → 960.0 64.0 → 64.0
Standard / list_read 1524.2 → 1443.0 1.8 → 1.8 952.0 → 952.0 0.0 → 0.0
Standard / compound_index 1566.9 → 1732.8 2.1 → 2.0 952.1 → 952.1 0.0 → 0.0
Standard / compound_index_unrelated_try 2225.5 → 1922.6 2.0 → 2.0 1552.2 → 1552.2 0.0 → 0.0
Light / add_control 989.8 → 1138.9 1.9 → 2.0 872.0 → 872.0 0.0 → 0.0
Light / new_arg_try 1443.3 → 1294.6 3.7 → 3.9 1528.0 → 1528.0 24.0 → 24.0
Light / new_arg 1184.3 → 1202.0 4.3 → 4.2 936.0 → 936.0 24.0 → 24.0
Light / struct_method_arg_try 1608.2 → 1656.9 2.0 → 2.0 1576.0 → 1576.0 0.0 → 0.0
Light / struct_method_parameter_arg_try 1574.8 → 1795.4 2.0 → 2.0 1552.0 → 1552.0 0.0 → 0.0
Light / array_bounds 1494.7 → 1574.1 46.5 → 44.5 960.0 → 960.0 64.0 → 64.0
Light / list_read 2223.4 → 2063.3 2.8 → 2.7 952.0 → 952.0 0.0 → 0.0
Light / compound_index 4656.6 → 5147.2 2.8 → 2.7 952.0 → 952.0 0.0 → 0.0
Light / compound_index_unrelated_try 5509.5 → 3436.8 2.5 → 2.5 1552.0 → 1552.0 0.0 → 0.0
net10.0 results (master → change)
API / workload Compile ns Invoke ns Compile B/op Invoke B/op
Standard / add_control 3452.1 → 3383.0 2.0 → 2.0 872.0 → 872.0 0.0 → 0.0
Standard / new_arg_try 4131.2 → 3656.8 3.5 → 3.9 1528.2 → 1528.2 24.0 → 24.0
Standard / new_arg 3503.5 → 3405.8 3.7 → 3.7 936.1 → 936.1 24.0 → 24.0
Standard / struct_method_arg_try 4147.2 → 4172.0 1.9 → 2.0 1576.0 → 1576.0 0.0 → 0.0
Standard / struct_method_parameter_arg_try 5210.0 → 5004.4 2.0 → 2.0 1552.3 → 1552.3 0.0 → 0.0
Standard / array_bounds 5531.3 → 5800.9 29.0 → 29.8 960.0 → 960.0 64.0 → 64.0
Standard / list_read 4104.8 → 4970.1 2.0 → 2.1 952.0 → 952.0 0.0 → 0.0
Standard / compound_index 7656.8 → 6112.9 2.0 → 2.0 952.4 → 952.4 0.0 → 0.0
Standard / compound_index_unrelated_try 5352.3 → 5577.7 2.0 → 2.0 1552.3 → 1552.3 0.0 → 0.0
Light / add_control 2538.7 → 2662.0 2.0 → 2.0 872.0 → 872.0 0.0 → 0.0
Light / new_arg_try 3116.8 → 3527.4 4.0 → 3.8 1528.0 → 1528.0 24.0 → 24.0
Light / new_arg 2740.4 → 2660.5 5.1 → 4.3 936.0 → 936.0 24.0 → 24.0
Light / struct_method_arg_try 4696.1 → 4203.3 2.1 → 2.1 1576.0 → 1576.0 0.0 → 0.0
Light / struct_method_parameter_arg_try 4096.9 → 4223.9 2.0 → 2.0 1552.0 → 1552.0 0.0 → 0.0
Light / array_bounds 3396.3 → 3491.2 29.0 → 29.5 960.0 → 960.0 64.0 → 64.0
Light / list_read 3251.1 → 3181.1 2.0 → 1.9 952.0 → 952.0 0.0 → 0.0
Light / compound_index 4011.4 → 4105.2 2.1 → 2.0 952.0 → 952.0 0.0 → 0.0
Light / compound_index_unrelated_try 4184.6 → 4571.6 2.0 → 2.0 1552.0 → 1552.0 0.0 → 0.0

Emitted IL differs in these measured workloads: none.
No measured allocation increase above 0.1 B/op in these controls.

Compound index assignments currently reject exception-region indices. Keep the target and indices in locals until all index expressions finish, then reload them for the getter and setter. Preserve the existing direct path for indices without exception regions.
Wrap complex-argument membership in an aggressively inlined CompilerContext method. Reuse an aggressively inlined value-or-address local loader in compound assignments and ordinary method calls.

Exercise concrete struct values and by-reference receivers with and without exception-region indices, checking mutation and cleanup against System compilation.
@jogibear9988
jogibear9988 force-pushed the fix/compound-index-exceptions-standalone branch from d8afaef to 929ecab Compare November 10, 2026 14:04
@dadhi
dadhi merged commit 1be1aab into dadhi:master Nov 10, 2026
4 checks passed
@jogibear9988
jogibear9988 deleted the fix/compound-index-exceptions-standalone branch November 10, 2026 22:01
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.

2 participants