Fix: Avoid materializing large ranges in foreach loops#201
Open
Fix: Avoid materializing large ranges in foreach loops#201
Conversation
The compiler was calling getArrayOfAlias() on ranges in some code paths, which materialized the entire range (e.g., 50 million elements for 1..50_000_000). The isGlobalUnderscore path already had an INSTANCEOF PerlRange check to use .iterator() directly, but the standard path (for lexical loop variables) was missing this optimization. This fix adds the same INSTANCEOF optimization to the standard foreach path, ensuring that ranges always use lazy iteration without materializing. Benefits: - Massive memory savings for large ranges - No semantic changes - range iterators already return proper lvalues - Array aliasing still works correctly for non-range iterables The interpreter already had this optimization via the ITERATOR_CREATE opcode, so this brings the compiler to parity with the interpreter.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixed memory issue where the compiler was materializing entire ranges (e.g., 1..50_000_000) when iterating in foreach loops, causing OOM with low memory limits.
Problem
The compiler had an INSTANCEOF PerlRange optimization in the
isGlobalUnderscorepath, but the standard path for lexical loop variables was missing this check. This causedgetArrayOfAlias()to be called on ranges, materializing all elements into memory.Solution
Added the same INSTANCEOF check to the standard foreach path:
.iterator()directly (lazy, no materialization).iterator()on base type (preserves array aliasing)Testing
for my $v (1..50_000_000) { $x++ }Verification
Disassembly now shows the INSTANCEOF check:
Fixes memory usage parity between compiler and interpreter for large ranges.
🤖 Generated with Claude Code