Skip to content

The JIT cache no longer crashes a run that compiles two or more modules - #549

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-jit-cache-embedded-types
Oct 11, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
fix-jit-cache-embedded-types

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Fixes native_ts_graphics finding 7 (docs/bugs/native-ts-graphics-findings.md, filed in #548): with the JIT cache on (the default), a program importing a .ts module crashed the compiler with 0xC0000005 before running, even from an empty cache.

Cause: the cache compiles each module in an MLIRContext of its own. getEmbeddedTypeBuiltins / getEmbeddedTypeNoBuiltins kept the built-in types (i32, f32, Opaque, ...) in a function-local static llvm::StringMap<mlir::Type>, made once in the first module's context. Every later module in the run got types from a context destroyed by then (the crash is the NoneType TypeID compare in isGenericParameters on a freed type). The default library's declarations name such types, so every import crashed with it; without it (--no-default-lib, as the suite runs) only a module naming one itself did.

Fix: the map is a member of MLIRGenImpl, made on first use, so it lives exactly as long as one module's generation. lookup instead of operator[]: same null type for an unknown name, without inserting it.

Test: test-jit-cache-embedded-types (jit-cache/embedded_types.ts importing embedded_types_module.ts, both naming i32 / i64 / f32), run through jit-cache-empty.cmake, which empties the cache first: a test-runner test keeps its cache beside the source and compiles nothing from its second run on. It crashes 3/3 on main and passes with the fix.

Verified on Release:

  • docs/bugs/ntg_jit_cache_import.ts with the default library, from an empty cache: 42, done on the first run (crashed before).
  • jit-cache/imports_diamond.ts with the default library, empty cache: passes (crashed before).
  • ctest -j 16 -C Release: 100% of 3977 passed.

🤖 Generated with Claude Code

The JIT cache compiles each module in an MLIRContext of its own, but the
built-in types (i32, f32, Opaque, ...) were kept in a function-local static
map, made once in the first module's context. Every later module in the run
got types from a context already destroyed: 0xC0000005 in the compiler. The
default library's declarations name such types, so every program importing
a .ts module crashed (native_ts_graphics finding 7). The map is now a member
of MLIRGenImpl, made on first use per module.

Regression test test-jit-cache-embedded-types runs from an empty cache
every time (jit-cache-empty.cmake); a test-runner test keeps its cache
beside the source and compiles nothing from its second run on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 2c6594e into main Oct 11, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-jit-cache-embedded-types branch October 11, 2026 16:33
ASDAlexander77 added a commit that referenced this pull request Oct 12, 2026
…558)

Every repro in docs/bugs passes on main, or fails as TypeScript does:
the native_ts_graphics findings were fixed by #535-#544 and #549 (the
`let s = 0` one by design, with a warning since #544), testFallThrough,
generic_in_generic and array_of_ifaces_cast by #538, #542 and #543, and
bug14 and bug21 aren't valid TypeScript. Each fix has its regression
test in tslang/test/tester, and the findings document is in the history
and in those PRs, so the folder goes.

Its interop notes stay, in docs/c-cpp-header-import.md: a `string`
returned by a C function is its `char*`, not a copy; `number` is a
`double`; and a nullable `Ref<T>` field is spelled `Ref<T> | null`.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant