A %json~ ... %% reader-macro literal that contains an array anywhere in it builds as an empty object {} under -jit in some compilation contexts — and the minimal repro also corrupts the heap at exit. Interpreted execution is always correct.
Minimal repro
require daslib/json_boost
[export]
def main {
var a = %json~ [1, 2, 3] %%
print("bare array: {write_json(a)}\n")
var b = %json~ { "xs" : [1, 2, 3] } %%
print("nested array: {write_json(b)}\n")
}
$ bin/Release/daslang.exe probe.das # interpreted — correct
bare array: [ 1, 2, 3 ]
nested array: { "xs" : [ 1, 2, 3 ] }
$ bin/Release/daslang.exe -jit probe.das # JIT — both collapse, then heap corruption
bare array: {}
nested array: {}
deleting 000000DF186FE540 80, which is not a chunk pointer (or chunk size mismatch)
[daslang atexit] FATAL: g_envTotal=1 at exit (Initialize/Shutdown not balanced)
Object-only literals (no arrays anywhere) are fine under -jit.
Context-dependence — the interesting part
The same literal misbehaves or works depending on the compilation context, which smells like generic-instance selection/mangling rather than a plain emitter hole:
| Context |
-jit result |
Bare program root ([export] def main, repro above) |
broken ({} + heap corruption at exit) |
Minimal dastest file (one [test], requires only testing_boost + json_boost) |
correct |
tests/json/test_json_edge.das (has %json~ [1, 2, 3] %% at line ~656) |
correct, 128/128 |
utils/dasllama-ladder/test_ladder_store.das (dastest file with a wide require graph: sqlite_migrate + sql_linq + json_boost + a path-required module) |
broken — every array-bearing literal parses back as non-array |
In the broken dastest case there is no crash, just wrong values; the crash shows on the program-root repro. Suspect: the reader macro's array construction lowers through to_array_move(JsonValue?[N]) / to_table_move(...) generic instances, and under -jit the wrong instance (or a bad specialization) gets bound in some instance mixes — possibly related to the known generic-mangling hash-collision class (instances differing only in inner qualifiers).
Environment
- master
9fc37bc08 (2026-08-10) + a few site-only commits, Windows 11, MSVC Release build, dasLLVM JIT (-jit), fresh DLL cache (cache-miss codegen in every run above).
- Found while writing
utils/dasllama-ladder/test_ladder_store.das (the dasllama.io arc); that suite runs interpreted as a workaround (which is also the extended_checks lane for utils services, so nothing regressed in CI).
A
%json~ ... %%reader-macro literal that contains an array anywhere in it builds as an empty object{}under-jitin some compilation contexts — and the minimal repro also corrupts the heap at exit. Interpreted execution is always correct.Minimal repro
Object-only literals (no arrays anywhere) are fine under
-jit.Context-dependence — the interesting part
The same literal misbehaves or works depending on the compilation context, which smells like generic-instance selection/mangling rather than a plain emitter hole:
-jitresult[export] def main, repro above){}+ heap corruption at exit)[test], requires onlytesting_boost+json_boost)tests/json/test_json_edge.das(has%json~ [1, 2, 3] %%at line ~656)utils/dasllama-ladder/test_ladder_store.das(dastest file with a wide require graph: sqlite_migrate + sql_linq + json_boost + a path-required module)In the broken dastest case there is no crash, just wrong values; the crash shows on the program-root repro. Suspect: the reader macro's array construction lowers through
to_array_move(JsonValue?[N])/to_table_move(...)generic instances, and under-jitthe wrong instance (or a bad specialization) gets bound in some instance mixes — possibly related to the known generic-mangling hash-collision class (instances differing only in inner qualifiers).Environment
9fc37bc08(2026-08-10) + a few site-only commits, Windows 11, MSVC Release build, dasLLVM JIT (-jit), fresh DLL cache (cache-miss codegen in every run above).utils/dasllama-ladder/test_ladder_store.das(the dasllama.io arc); that suite runs interpreted as a workaround (which is also theextended_checkslane for utils services, so nothing regressed in CI).