Repository navigation
Conversation
…strings (issue #1961) - Add `sawBeginOrSub` flag to `Lexer`: set when `BEGIN`, `sub`, `use`, or `no` appears in the token stream. - Reorder `evalStringWithInterpreter()`: tokenize first (cheap, no side effects), then run the O(visible_vars) outer-lexical alias loop only when `sawBeginOrSub` is true. Saves per-eval HashMap lookups and String allocations on the common path (simple expressions, while loops, etc.). - Fix `ScopedSymbolTable.snapShot()`: use `new BitSet()` instead of `clone()` for the three warning-flag BitSets when they are empty, matching the pattern already applied in `enterScope()`. Benchmark (dev/bench/benchmark_eval_string.pl, 3-run median): System Perl: ~326,000/s PerlOnJava: ~48,400/s (was ~44,000/s before this PR) Ratio: ~6.7x (was ~7.4x before PR #1940; ~12x before #1911 work) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
Follow-up to PR #1940 (issue #1911), targeting the remaining
eval STRINGoverhead from issue #1961.Changes
1. Skip outer-lexical alias loop when not needed (
sawBeginOrSubflag)evalStringWithInterpreter()previously ran an O(visible_vars) loop on every eval to install package-global aliases for outermyvariables — required only forBEGINblocks and namedsubdeclarations (which outlive the eval frame and need package-scoped access to outer lexicals).Fix: Add
public boolean sawBeginOrSubtoLexer.consumeIdentifier()sets it on the first occurrence ofBEGIN,sub,use, orno. Aftertokenize(), the alias loop runs only whensawBeginOrSubis true.For the benchmark (a
whileloop with no subs), this eliminates the alias loop entirely.2. Avoid
BitSet.clone()for empty BitSets insnapShot()ScopedSymbolTable.snapShot()unconditionally cloned three warning-flag BitSets. These are empty in the common case (nouse warningspragmas active). Usenew BitSet()instead ofclone()when the source is empty — same pattern already applied inenterScope().Benchmark
dev/bench/benchmark_eval_string.pl, 3-run median on the same machine:Testing
makepasses (BUILD SUCCESSFUL)master(verified)eval "while (...) { ... }"correctly executes without alias loopeval "sub foo { ... }",eval "BEGIN { ... }",eval "use strict"all work correctlyCloses
Addresses items 3 and 4 from issue #1961 (items 1 and 2 were already done in PR #1940; item 5 is not safe because
LexerTokenfields are mutated by the parser).🤖 Generated with Claude Code