Motivation
Surfaced during the #69 RegExp folder rollout (commit b968a9e). Compile mode buckets 443 RegExp tests as Fail — meaning they execute to completion but produce values that don't match the expected output. This is distinct from the interpreter, which mostly buckets these as RuntimeError.
Distribution (excluding the Symbol-keyed cluster tracked separately):
| Subdirectory |
Compile Fail count |
prototype/exec |
21 |
prototype/test |
16 |
prototype/toString |
5 |
prototype/multiline |
6 |
prototype/ignoreCase |
6 |
prototype/global |
6 |
prototype/unicode |
4 |
prototype/sticky |
4 |
escape |
16 |
regexp-modifiers |
9 |
| (other small subdirs) |
~50 |
| Total non-Symbol |
~145 |
Plus ~155 in the Symbol.X cluster (#101) which is filed separately.
Why compile vs interp diverges
In interp mode the same tests bucket as RuntimeError (e.g., calling RegExp.prototype.exec on a non-RegExp receiver throws). In compile mode they bucket as Fail, which means the compiled IL produces some return value (probably null, undefined, or [object Object]) instead of the spec-mandated TypeError. This pattern strongly suggests:
- Missing receiver-type check in compile-mode prototype dispatch — interp throws, compile happily proceeds with garbage receiver.
- Wrong default return — compile-mode
exec/test may emit a fallback that returns null when match fails, masking that the regex itself never ran.
- Property accessor desugaring —
r.global, r.multiline, etc. are spec-defined as getters on RegExp.prototype. Compile mode may be reading a per-instance field instead of invoking the getter, which would leak undefined for inherited or boxed regex objects.
Suggested approach
Three-step investigation:
- Pick one Fail-bucket test from each subdirectory above, run
dotnet run --compile on it, and capture the actual emitted output vs the expected. This will localize whether the bug is in IL emission for obj.exec(...), in the prototype property getters, or in the underlying RegExpBuiltinExec shim.
- Diff the IL emitted for
r.exec('abc') between a freshly-compiled test and the analogous interpreter call site (Interpreter.Properties.cs EvaluateGet / Interpreter.Calls.cs).
- Cross-check with #101 — the Symbol-keyed dispatch fix may share the same root cause as some of these.
Acceptance
- Compile-mode RegExp
Fail count drops by at least 100, with affected tests moving to Pass or a more specific bucket.
- For any test that remains failing, the bucket changes from
Fail to a more diagnostic bucket (RuntimeError with a real message rather than a silent wrong return).
- No interp-mode regressions.
Related
Part of #69. Sibling clusters: #100, #101.
Motivation
Surfaced during the #69 RegExp folder rollout (commit b968a9e). Compile mode buckets 443 RegExp tests as
Fail— meaning they execute to completion but produce values that don't match the expected output. This is distinct from the interpreter, which mostly buckets these asRuntimeError.Distribution (excluding the Symbol-keyed cluster tracked separately):
prototype/execprototype/testprototype/toStringprototype/multilineprototype/ignoreCaseprototype/globalprototype/unicodeprototype/stickyescaperegexp-modifiersPlus ~155 in the Symbol.X cluster (#101) which is filed separately.
Why compile vs interp diverges
In interp mode the same tests bucket as
RuntimeError(e.g., callingRegExp.prototype.execon a non-RegExp receiver throws). In compile mode they bucket asFail, which means the compiled IL produces some return value (probablynull,undefined, or[object Object]) instead of the spec-mandated TypeError. This pattern strongly suggests:exec/testmay emit a fallback that returnsnullwhen match fails, masking that the regex itself never ran.r.global,r.multiline, etc. are spec-defined as getters onRegExp.prototype. Compile mode may be reading a per-instance field instead of invoking the getter, which would leak undefined for inherited or boxed regex objects.Suggested approach
Three-step investigation:
dotnet run --compileon it, and capture the actual emitted output vs the expected. This will localize whether the bug is in IL emission forobj.exec(...), in the prototype property getters, or in the underlyingRegExpBuiltinExecshim.r.exec('abc')between a freshly-compiled test and the analogous interpreter call site (Interpreter.Properties.csEvaluateGet/Interpreter.Calls.cs).Acceptance
Failcount drops by at least 100, with affected tests moving toPassor a more specific bucket.Failto a more diagnostic bucket (RuntimeErrorwith a real message rather than a silent wrong return).Related
Part of #69. Sibling clusters: #100, #101.