Drop the module-level scratch parsing buffer's reference to the last
buffer it read from.
The scratch is reinit-pointed at a caller's buffer on every numeric
extraction and never cleared, so after a parse it silently pins the
ENTIRE source buffer (hundreds of MB on large models) until the next
extraction repoints it. That was invisible while the model itself
held the source, but once spillSourceToExternalStore releases the
model's copy this scratch became the last thing keeping it alive
(found via heap-snapshot retainer chain:
Context[parsingBufferReusable] → ParsingBuffer.buffer → source).
Called from the model's spill and cache-release paths; safe at any
time because every use reinits the scratch first.
Drop the module-level scratch parsing buffer's reference to the last buffer it read from.
The scratch is
reinit-pointed at a caller's buffer on every numeric extraction and never cleared, so after a parse it silently pins the ENTIRE source buffer (hundreds of MB on large models) until the next extraction repoints it. That was invisible while the model itself held the source, but oncespillSourceToExternalStorereleases the model's copy this scratch became the last thing keeping it alive (found via heap-snapshot retainer chain:Context[parsingBufferReusable] → ParsingBuffer.buffer → source). Called from the model's spill and cache-release paths; safe at any time because every use reinits the scratch first.