JIT: Stack allocate non-escaping strings - #129202

Closed
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings
Closed

JIT: Stack allocate non-escaping strings#129202
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Now that we intrinsified String.FastAllocateString, I guess it wouldn't hurt to enable escape analysis for it by repeating what we do for normal arrays. Most strings leak into other string APIs which actually don't escape, but we don't do IPA today. As is, this PR enables 74 strings to be stack-allocated (mostly in libraries_tests_no_tiered_compilation.run)

Stack allocate non-escaping System.String instances created via
String.FastAllocateString when the length is a compile-time constant,
reusing the existing array stack-allocation machinery.
At object-allocator time a string allocation is modelled as
FastAllocateString(pMT, length) and is treated like a char[] array via a
new OAT_NEWSTR allocation kind. The call is retyped to a native pointer,
gets a StackArrayLocal arg and the GTF_CALL_M_STACK_ARRAY flag, and is
later expanded in fgExpandStackArrayAllocations into method-table and
length stores (the length field offset is the only difference from
arrays). The stack object uses a non-GC block layout sized for the
header, chars and null terminator, capped by JitObjectStackAllocationSize.
Gated by the new DOTNET_JitObjectStackAllocationString config (on by
default). R2R is not yet supported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 01:18
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CoreCLR JIT object stack allocation support to cover System.String.FastAllocateString call sites (in addition to newarr), enabling escape analysis to stack-allocate eligible constant-length strings and expanding them via the existing stack-array allocation expansion path.

Changes:

  • Teach ObjectAllocator to recognize String.FastAllocateString(pMT, length) as a stack-allocation candidate (OAT_NEWSTR) when length is a compile-time constant.
  • Reuse the stack-array allocation machinery to represent and expand stack-allocated strings (extra StackArrayLocal arg, retype to native pointer, and late expansion in fgExpandStackArrayAllocations).
  • Add config/metrics/method-flag plumbing for string stack allocation (JitObjectStackAllocationString, new JIT metrics, OMF_HAS_FASTSTRINGALLOC).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.cppAssign a fresh non-heap VN for stack-allocated FastAllocateString calls flagged with GTF_CALL_M_STACK_ARRAY.
src/coreclr/jit/objectalloc.hAdd OAT_NEWSTR and the MorphAllocObjNodeHelperStr helper declaration.
src/coreclr/jit/objectalloc.cppDetect FastAllocateString candidates, size-check strings, and morph eligible ones into the existing stack-array allocation path.
src/coreclr/jit/jitmetadatalist.hAdd new JIT metrics for string allocation and stack-allocated strings.
src/coreclr/jit/jitconfigvalues.hAdd JitObjectStackAllocationString config switch.
src/coreclr/jit/importercalls.cppFlag methods containing FastAllocateString so escape analysis runs; also mark ThrowIfNull as special (non-fallthrough).
src/coreclr/jit/helperexpansion.cppExtend stack-array expansion to also expand stack-allocated FastAllocateString by using the string length field offset.
src/coreclr/jit/compiler.hAdd OMF_HAS_FASTSTRINGALLOC method flag.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
@EgorBo
EgorBo marked this pull request as ready for review June 10, 2026 13:13
EgorBoand others added 2 commits June 10, 2026 15:29
Fold the near-duplicate MorphAllocObjNodeHelperStr into
MorphAllocObjNodeHelperArr (parameterized by isString) and unify the
array/string detection in AllocationKind, since a stack-allocated string
is just a char array with a different header. No functional change:
SuperPMI asmdiffs are identical to the previous commit across
libraries.pmi, coreclr_tests, libraries_tests and benchmarks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment on lines +190 to +191
if ((m_compiler->optMethodFlags & OMF_HAS_NEWOBJ) == 0 && (m_compiler->optMethodFlags & OMF_HAS_NEWARRAY) == 0 &&
(m_compiler->optMethodFlags & OMF_HAS_FASTSTRINGALLOC) == 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, is it worth just making this something like:

if ((m_compiler->optMethodFlags & OMF_OBJALLOC_MASK) == 0)

Where OMF_OBJALLOC_MASK = OMF_HAS_NEWOBJ | OMF_HAS_NEWARRAY | OMF_HAS_FASTSTRINGALLOC?

These lines aren't the worst, but every time we add one more check I think it gets a little less readable and having a way to check it all at once is nice.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although, we probably should hide these under getters, most OMF flags are already hidden behind them

Comment threadsrc/coreclr/jit/objectalloc.cpp
CopilotAI review requested due to automatic review settings June 26, 2026 01:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

@AndyAyersMS you wanted to take a look on this too

@EgorBo
EgorBo requested a review from AndyAyersMSJune 26, 2026 12:14

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some test cases? The existing test pattern is a bit annoying but AI can probably mimic it without problems.

Comment threadsrc/coreclr/jit/objectalloc.cpp
EgorBoand others added 2 commits July 6, 2026 18:58
Verify that non-escaping, constant-length strings produced by char.ToString(),
char.ToString(char), string equality of a ToString() result, and Rune.ToString()
are stack-allocated (the String.FastAllocateString call is removed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Let's postpone this till we get some meaningful diffs

@EgorBoEgorBo closed this Jul 7, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 7, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@EgorBo@AndyAyersMS@tannergooding
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

JIT: Stack allocate non-escaping strings - #129202

Closed
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings
Closed

JIT: Stack allocate non-escaping strings#129202
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Now that we intrinsified String.FastAllocateString, I guess it wouldn't hurt to enable escape analysis for it by repeating what we do for normal arrays. Most strings leak into other string APIs which actually don't escape, but we don't do IPA today. As is, this PR enables 74 strings to be stack-allocated (mostly in libraries_tests_no_tiered_compilation.run)

Stack allocate non-escaping System.String instances created via
String.FastAllocateString when the length is a compile-time constant,
reusing the existing array stack-allocation machinery.
At object-allocator time a string allocation is modelled as
FastAllocateString(pMT, length) and is treated like a char[] array via a
new OAT_NEWSTR allocation kind. The call is retyped to a native pointer,
gets a StackArrayLocal arg and the GTF_CALL_M_STACK_ARRAY flag, and is
later expanded in fgExpandStackArrayAllocations into method-table and
length stores (the length field offset is the only difference from
arrays). The stack object uses a non-GC block layout sized for the
header, chars and null terminator, capped by JitObjectStackAllocationSize.
Gated by the new DOTNET_JitObjectStackAllocationString config (on by
default). R2R is not yet supported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 01:18
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CoreCLR JIT object stack allocation support to cover System.String.FastAllocateString call sites (in addition to newarr), enabling escape analysis to stack-allocate eligible constant-length strings and expanding them via the existing stack-array allocation expansion path.

Changes:

  • Teach ObjectAllocator to recognize String.FastAllocateString(pMT, length) as a stack-allocation candidate (OAT_NEWSTR) when length is a compile-time constant.
  • Reuse the stack-array allocation machinery to represent and expand stack-allocated strings (extra StackArrayLocal arg, retype to native pointer, and late expansion in fgExpandStackArrayAllocations).
  • Add config/metrics/method-flag plumbing for string stack allocation (JitObjectStackAllocationString, new JIT metrics, OMF_HAS_FASTSTRINGALLOC).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.cppAssign a fresh non-heap VN for stack-allocated FastAllocateString calls flagged with GTF_CALL_M_STACK_ARRAY.
src/coreclr/jit/objectalloc.hAdd OAT_NEWSTR and the MorphAllocObjNodeHelperStr helper declaration.
src/coreclr/jit/objectalloc.cppDetect FastAllocateString candidates, size-check strings, and morph eligible ones into the existing stack-array allocation path.
src/coreclr/jit/jitmetadatalist.hAdd new JIT metrics for string allocation and stack-allocated strings.
src/coreclr/jit/jitconfigvalues.hAdd JitObjectStackAllocationString config switch.
src/coreclr/jit/importercalls.cppFlag methods containing FastAllocateString so escape analysis runs; also mark ThrowIfNull as special (non-fallthrough).
src/coreclr/jit/helperexpansion.cppExtend stack-array expansion to also expand stack-allocated FastAllocateString by using the string length field offset.
src/coreclr/jit/compiler.hAdd OMF_HAS_FASTSTRINGALLOC method flag.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
@EgorBo
EgorBo marked this pull request as ready for review June 10, 2026 13:13
EgorBoand others added 2 commits June 10, 2026 15:29
Fold the near-duplicate MorphAllocObjNodeHelperStr into
MorphAllocObjNodeHelperArr (parameterized by isString) and unify the
array/string detection in AllocationKind, since a stack-allocated string
is just a char array with a different header. No functional change:
SuperPMI asmdiffs are identical to the previous commit across
libraries.pmi, coreclr_tests, libraries_tests and benchmarks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment on lines +190 to +191
if ((m_compiler->optMethodFlags & OMF_HAS_NEWOBJ) == 0 && (m_compiler->optMethodFlags & OMF_HAS_NEWARRAY) == 0 &&
(m_compiler->optMethodFlags & OMF_HAS_FASTSTRINGALLOC) == 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, is it worth just making this something like:

if ((m_compiler->optMethodFlags & OMF_OBJALLOC_MASK) == 0)

Where OMF_OBJALLOC_MASK = OMF_HAS_NEWOBJ | OMF_HAS_NEWARRAY | OMF_HAS_FASTSTRINGALLOC?

These lines aren't the worst, but every time we add one more check I think it gets a little less readable and having a way to check it all at once is nice.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although, we probably should hide these under getters, most OMF flags are already hidden behind them

Comment threadsrc/coreclr/jit/objectalloc.cpp
CopilotAI review requested due to automatic review settings June 26, 2026 01:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

@AndyAyersMS you wanted to take a look on this too

@EgorBo
EgorBo requested a review from AndyAyersMSJune 26, 2026 12:14

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some test cases? The existing test pattern is a bit annoying but AI can probably mimic it without problems.

Comment threadsrc/coreclr/jit/objectalloc.cpp
EgorBoand others added 2 commits July 6, 2026 18:58
Verify that non-escaping, constant-length strings produced by char.ToString(),
char.ToString(char), string equality of a ToString() result, and Rune.ToString()
are stack-allocated (the String.FastAllocateString call is removed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Let's postpone this till we get some meaningful diffs

@EgorBoEgorBo closed this Jul 7, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 7, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@EgorBo@AndyAyersMS@tannergooding
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

JIT: Stack allocate non-escaping strings - #129202

Closed
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings
Closed

JIT: Stack allocate non-escaping strings#129202
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Now that we intrinsified String.FastAllocateString, I guess it wouldn't hurt to enable escape analysis for it by repeating what we do for normal arrays. Most strings leak into other string APIs which actually don't escape, but we don't do IPA today. As is, this PR enables 74 strings to be stack-allocated (mostly in libraries_tests_no_tiered_compilation.run)

Stack allocate non-escaping System.String instances created via
String.FastAllocateString when the length is a compile-time constant,
reusing the existing array stack-allocation machinery.
At object-allocator time a string allocation is modelled as
FastAllocateString(pMT, length) and is treated like a char[] array via a
new OAT_NEWSTR allocation kind. The call is retyped to a native pointer,
gets a StackArrayLocal arg and the GTF_CALL_M_STACK_ARRAY flag, and is
later expanded in fgExpandStackArrayAllocations into method-table and
length stores (the length field offset is the only difference from
arrays). The stack object uses a non-GC block layout sized for the
header, chars and null terminator, capped by JitObjectStackAllocationSize.
Gated by the new DOTNET_JitObjectStackAllocationString config (on by
default). R2R is not yet supported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 01:18
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CoreCLR JIT object stack allocation support to cover System.String.FastAllocateString call sites (in addition to newarr), enabling escape analysis to stack-allocate eligible constant-length strings and expanding them via the existing stack-array allocation expansion path.

Changes:

  • Teach ObjectAllocator to recognize String.FastAllocateString(pMT, length) as a stack-allocation candidate (OAT_NEWSTR) when length is a compile-time constant.
  • Reuse the stack-array allocation machinery to represent and expand stack-allocated strings (extra StackArrayLocal arg, retype to native pointer, and late expansion in fgExpandStackArrayAllocations).
  • Add config/metrics/method-flag plumbing for string stack allocation (JitObjectStackAllocationString, new JIT metrics, OMF_HAS_FASTSTRINGALLOC).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.cppAssign a fresh non-heap VN for stack-allocated FastAllocateString calls flagged with GTF_CALL_M_STACK_ARRAY.
src/coreclr/jit/objectalloc.hAdd OAT_NEWSTR and the MorphAllocObjNodeHelperStr helper declaration.
src/coreclr/jit/objectalloc.cppDetect FastAllocateString candidates, size-check strings, and morph eligible ones into the existing stack-array allocation path.
src/coreclr/jit/jitmetadatalist.hAdd new JIT metrics for string allocation and stack-allocated strings.
src/coreclr/jit/jitconfigvalues.hAdd JitObjectStackAllocationString config switch.
src/coreclr/jit/importercalls.cppFlag methods containing FastAllocateString so escape analysis runs; also mark ThrowIfNull as special (non-fallthrough).
src/coreclr/jit/helperexpansion.cppExtend stack-array expansion to also expand stack-allocated FastAllocateString by using the string length field offset.
src/coreclr/jit/compiler.hAdd OMF_HAS_FASTSTRINGALLOC method flag.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
@EgorBo
EgorBo marked this pull request as ready for review June 10, 2026 13:13
EgorBoand others added 2 commits June 10, 2026 15:29
Fold the near-duplicate MorphAllocObjNodeHelperStr into
MorphAllocObjNodeHelperArr (parameterized by isString) and unify the
array/string detection in AllocationKind, since a stack-allocated string
is just a char array with a different header. No functional change:
SuperPMI asmdiffs are identical to the previous commit across
libraries.pmi, coreclr_tests, libraries_tests and benchmarks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment on lines +190 to +191
if ((m_compiler->optMethodFlags & OMF_HAS_NEWOBJ) == 0 && (m_compiler->optMethodFlags & OMF_HAS_NEWARRAY) == 0 &&
(m_compiler->optMethodFlags & OMF_HAS_FASTSTRINGALLOC) == 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, is it worth just making this something like:

if ((m_compiler->optMethodFlags & OMF_OBJALLOC_MASK) == 0)

Where OMF_OBJALLOC_MASK = OMF_HAS_NEWOBJ | OMF_HAS_NEWARRAY | OMF_HAS_FASTSTRINGALLOC?

These lines aren't the worst, but every time we add one more check I think it gets a little less readable and having a way to check it all at once is nice.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although, we probably should hide these under getters, most OMF flags are already hidden behind them

Comment threadsrc/coreclr/jit/objectalloc.cpp
CopilotAI review requested due to automatic review settings June 26, 2026 01:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

@AndyAyersMS you wanted to take a look on this too

@EgorBo
EgorBo requested a review from AndyAyersMSJune 26, 2026 12:14

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some test cases? The existing test pattern is a bit annoying but AI can probably mimic it without problems.

Comment threadsrc/coreclr/jit/objectalloc.cpp
EgorBoand others added 2 commits July 6, 2026 18:58
Verify that non-escaping, constant-length strings produced by char.ToString(),
char.ToString(char), string equality of a ToString() result, and Rune.ToString()
are stack-allocated (the String.FastAllocateString call is removed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Let's postpone this till we get some meaningful diffs

@EgorBoEgorBo closed this Jul 7, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 7, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@EgorBo@AndyAyersMS@tannergooding
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

JIT: Stack allocate non-escaping strings - #129202

Closed
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings
Closed

JIT: Stack allocate non-escaping strings#129202
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Now that we intrinsified String.FastAllocateString, I guess it wouldn't hurt to enable escape analysis for it by repeating what we do for normal arrays. Most strings leak into other string APIs which actually don't escape, but we don't do IPA today. As is, this PR enables 74 strings to be stack-allocated (mostly in libraries_tests_no_tiered_compilation.run)

Stack allocate non-escaping System.String instances created via
String.FastAllocateString when the length is a compile-time constant,
reusing the existing array stack-allocation machinery.
At object-allocator time a string allocation is modelled as
FastAllocateString(pMT, length) and is treated like a char[] array via a
new OAT_NEWSTR allocation kind. The call is retyped to a native pointer,
gets a StackArrayLocal arg and the GTF_CALL_M_STACK_ARRAY flag, and is
later expanded in fgExpandStackArrayAllocations into method-table and
length stores (the length field offset is the only difference from
arrays). The stack object uses a non-GC block layout sized for the
header, chars and null terminator, capped by JitObjectStackAllocationSize.
Gated by the new DOTNET_JitObjectStackAllocationString config (on by
default). R2R is not yet supported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 01:18
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CoreCLR JIT object stack allocation support to cover System.String.FastAllocateString call sites (in addition to newarr), enabling escape analysis to stack-allocate eligible constant-length strings and expanding them via the existing stack-array allocation expansion path.

Changes:

  • Teach ObjectAllocator to recognize String.FastAllocateString(pMT, length) as a stack-allocation candidate (OAT_NEWSTR) when length is a compile-time constant.
  • Reuse the stack-array allocation machinery to represent and expand stack-allocated strings (extra StackArrayLocal arg, retype to native pointer, and late expansion in fgExpandStackArrayAllocations).
  • Add config/metrics/method-flag plumbing for string stack allocation (JitObjectStackAllocationString, new JIT metrics, OMF_HAS_FASTSTRINGALLOC).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.cppAssign a fresh non-heap VN for stack-allocated FastAllocateString calls flagged with GTF_CALL_M_STACK_ARRAY.
src/coreclr/jit/objectalloc.hAdd OAT_NEWSTR and the MorphAllocObjNodeHelperStr helper declaration.
src/coreclr/jit/objectalloc.cppDetect FastAllocateString candidates, size-check strings, and morph eligible ones into the existing stack-array allocation path.
src/coreclr/jit/jitmetadatalist.hAdd new JIT metrics for string allocation and stack-allocated strings.
src/coreclr/jit/jitconfigvalues.hAdd JitObjectStackAllocationString config switch.
src/coreclr/jit/importercalls.cppFlag methods containing FastAllocateString so escape analysis runs; also mark ThrowIfNull as special (non-fallthrough).
src/coreclr/jit/helperexpansion.cppExtend stack-array expansion to also expand stack-allocated FastAllocateString by using the string length field offset.
src/coreclr/jit/compiler.hAdd OMF_HAS_FASTSTRINGALLOC method flag.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
@EgorBo
EgorBo marked this pull request as ready for review June 10, 2026 13:13
EgorBoand others added 2 commits June 10, 2026 15:29
Fold the near-duplicate MorphAllocObjNodeHelperStr into
MorphAllocObjNodeHelperArr (parameterized by isString) and unify the
array/string detection in AllocationKind, since a stack-allocated string
is just a char array with a different header. No functional change:
SuperPMI asmdiffs are identical to the previous commit across
libraries.pmi, coreclr_tests, libraries_tests and benchmarks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment on lines +190 to +191
if ((m_compiler->optMethodFlags & OMF_HAS_NEWOBJ) == 0 && (m_compiler->optMethodFlags & OMF_HAS_NEWARRAY) == 0 &&
(m_compiler->optMethodFlags & OMF_HAS_FASTSTRINGALLOC) == 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, is it worth just making this something like:

if ((m_compiler->optMethodFlags & OMF_OBJALLOC_MASK) == 0)

Where OMF_OBJALLOC_MASK = OMF_HAS_NEWOBJ | OMF_HAS_NEWARRAY | OMF_HAS_FASTSTRINGALLOC?

These lines aren't the worst, but every time we add one more check I think it gets a little less readable and having a way to check it all at once is nice.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although, we probably should hide these under getters, most OMF flags are already hidden behind them

Comment threadsrc/coreclr/jit/objectalloc.cpp
CopilotAI review requested due to automatic review settings June 26, 2026 01:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

@AndyAyersMS you wanted to take a look on this too

@EgorBo
EgorBo requested a review from AndyAyersMSJune 26, 2026 12:14

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some test cases? The existing test pattern is a bit annoying but AI can probably mimic it without problems.

Comment threadsrc/coreclr/jit/objectalloc.cpp
EgorBoand others added 2 commits July 6, 2026 18:58
Verify that non-escaping, constant-length strings produced by char.ToString(),
char.ToString(char), string equality of a ToString() result, and Rune.ToString()
are stack-allocated (the String.FastAllocateString call is removed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Let's postpone this till we get some meaningful diffs

@EgorBoEgorBo closed this Jul 7, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 7, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@EgorBo@AndyAyersMS@tannergooding
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

JIT: Stack allocate non-escaping strings - #129202

Closed
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings
Closed

JIT: Stack allocate non-escaping strings#129202
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Now that we intrinsified String.FastAllocateString, I guess it wouldn't hurt to enable escape analysis for it by repeating what we do for normal arrays. Most strings leak into other string APIs which actually don't escape, but we don't do IPA today. As is, this PR enables 74 strings to be stack-allocated (mostly in libraries_tests_no_tiered_compilation.run)

Stack allocate non-escaping System.String instances created via
String.FastAllocateString when the length is a compile-time constant,
reusing the existing array stack-allocation machinery.
At object-allocator time a string allocation is modelled as
FastAllocateString(pMT, length) and is treated like a char[] array via a
new OAT_NEWSTR allocation kind. The call is retyped to a native pointer,
gets a StackArrayLocal arg and the GTF_CALL_M_STACK_ARRAY flag, and is
later expanded in fgExpandStackArrayAllocations into method-table and
length stores (the length field offset is the only difference from
arrays). The stack object uses a non-GC block layout sized for the
header, chars and null terminator, capped by JitObjectStackAllocationSize.
Gated by the new DOTNET_JitObjectStackAllocationString config (on by
default). R2R is not yet supported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 01:18
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CoreCLR JIT object stack allocation support to cover System.String.FastAllocateString call sites (in addition to newarr), enabling escape analysis to stack-allocate eligible constant-length strings and expanding them via the existing stack-array allocation expansion path.

Changes:

  • Teach ObjectAllocator to recognize String.FastAllocateString(pMT, length) as a stack-allocation candidate (OAT_NEWSTR) when length is a compile-time constant.
  • Reuse the stack-array allocation machinery to represent and expand stack-allocated strings (extra StackArrayLocal arg, retype to native pointer, and late expansion in fgExpandStackArrayAllocations).
  • Add config/metrics/method-flag plumbing for string stack allocation (JitObjectStackAllocationString, new JIT metrics, OMF_HAS_FASTSTRINGALLOC).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.cppAssign a fresh non-heap VN for stack-allocated FastAllocateString calls flagged with GTF_CALL_M_STACK_ARRAY.
src/coreclr/jit/objectalloc.hAdd OAT_NEWSTR and the MorphAllocObjNodeHelperStr helper declaration.
src/coreclr/jit/objectalloc.cppDetect FastAllocateString candidates, size-check strings, and morph eligible ones into the existing stack-array allocation path.
src/coreclr/jit/jitmetadatalist.hAdd new JIT metrics for string allocation and stack-allocated strings.
src/coreclr/jit/jitconfigvalues.hAdd JitObjectStackAllocationString config switch.
src/coreclr/jit/importercalls.cppFlag methods containing FastAllocateString so escape analysis runs; also mark ThrowIfNull as special (non-fallthrough).
src/coreclr/jit/helperexpansion.cppExtend stack-array expansion to also expand stack-allocated FastAllocateString by using the string length field offset.
src/coreclr/jit/compiler.hAdd OMF_HAS_FASTSTRINGALLOC method flag.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
@EgorBo
EgorBo marked this pull request as ready for review June 10, 2026 13:13
EgorBoand others added 2 commits June 10, 2026 15:29
Fold the near-duplicate MorphAllocObjNodeHelperStr into
MorphAllocObjNodeHelperArr (parameterized by isString) and unify the
array/string detection in AllocationKind, since a stack-allocated string
is just a char array with a different header. No functional change:
SuperPMI asmdiffs are identical to the previous commit across
libraries.pmi, coreclr_tests, libraries_tests and benchmarks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment on lines +190 to +191
if ((m_compiler->optMethodFlags & OMF_HAS_NEWOBJ) == 0 && (m_compiler->optMethodFlags & OMF_HAS_NEWARRAY) == 0 &&
(m_compiler->optMethodFlags & OMF_HAS_FASTSTRINGALLOC) == 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, is it worth just making this something like:

if ((m_compiler->optMethodFlags & OMF_OBJALLOC_MASK) == 0)

Where OMF_OBJALLOC_MASK = OMF_HAS_NEWOBJ | OMF_HAS_NEWARRAY | OMF_HAS_FASTSTRINGALLOC?

These lines aren't the worst, but every time we add one more check I think it gets a little less readable and having a way to check it all at once is nice.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although, we probably should hide these under getters, most OMF flags are already hidden behind them

Comment threadsrc/coreclr/jit/objectalloc.cpp
CopilotAI review requested due to automatic review settings June 26, 2026 01:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

@AndyAyersMS you wanted to take a look on this too

@EgorBo
EgorBo requested a review from AndyAyersMSJune 26, 2026 12:14

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some test cases? The existing test pattern is a bit annoying but AI can probably mimic it without problems.

Comment threadsrc/coreclr/jit/objectalloc.cpp
EgorBoand others added 2 commits July 6, 2026 18:58
Verify that non-escaping, constant-length strings produced by char.ToString(),
char.ToString(char), string equality of a ToString() result, and Rune.ToString()
are stack-allocated (the String.FastAllocateString call is removed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Let's postpone this till we get some meaningful diffs

@EgorBoEgorBo closed this Jul 7, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 7, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@EgorBo@AndyAyersMS@tannergooding
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

JIT: Stack allocate non-escaping strings - #129202

Closed
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings
Closed

JIT: Stack allocate non-escaping strings#129202
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Now that we intrinsified String.FastAllocateString, I guess it wouldn't hurt to enable escape analysis for it by repeating what we do for normal arrays. Most strings leak into other string APIs which actually don't escape, but we don't do IPA today. As is, this PR enables 74 strings to be stack-allocated (mostly in libraries_tests_no_tiered_compilation.run)

Stack allocate non-escaping System.String instances created via
String.FastAllocateString when the length is a compile-time constant,
reusing the existing array stack-allocation machinery.
At object-allocator time a string allocation is modelled as
FastAllocateString(pMT, length) and is treated like a char[] array via a
new OAT_NEWSTR allocation kind. The call is retyped to a native pointer,
gets a StackArrayLocal arg and the GTF_CALL_M_STACK_ARRAY flag, and is
later expanded in fgExpandStackArrayAllocations into method-table and
length stores (the length field offset is the only difference from
arrays). The stack object uses a non-GC block layout sized for the
header, chars and null terminator, capped by JitObjectStackAllocationSize.
Gated by the new DOTNET_JitObjectStackAllocationString config (on by
default). R2R is not yet supported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 01:18
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CoreCLR JIT object stack allocation support to cover System.String.FastAllocateString call sites (in addition to newarr), enabling escape analysis to stack-allocate eligible constant-length strings and expanding them via the existing stack-array allocation expansion path.

Changes:

  • Teach ObjectAllocator to recognize String.FastAllocateString(pMT, length) as a stack-allocation candidate (OAT_NEWSTR) when length is a compile-time constant.
  • Reuse the stack-array allocation machinery to represent and expand stack-allocated strings (extra StackArrayLocal arg, retype to native pointer, and late expansion in fgExpandStackArrayAllocations).
  • Add config/metrics/method-flag plumbing for string stack allocation (JitObjectStackAllocationString, new JIT metrics, OMF_HAS_FASTSTRINGALLOC).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.cppAssign a fresh non-heap VN for stack-allocated FastAllocateString calls flagged with GTF_CALL_M_STACK_ARRAY.
src/coreclr/jit/objectalloc.hAdd OAT_NEWSTR and the MorphAllocObjNodeHelperStr helper declaration.
src/coreclr/jit/objectalloc.cppDetect FastAllocateString candidates, size-check strings, and morph eligible ones into the existing stack-array allocation path.
src/coreclr/jit/jitmetadatalist.hAdd new JIT metrics for string allocation and stack-allocated strings.
src/coreclr/jit/jitconfigvalues.hAdd JitObjectStackAllocationString config switch.
src/coreclr/jit/importercalls.cppFlag methods containing FastAllocateString so escape analysis runs; also mark ThrowIfNull as special (non-fallthrough).
src/coreclr/jit/helperexpansion.cppExtend stack-array expansion to also expand stack-allocated FastAllocateString by using the string length field offset.
src/coreclr/jit/compiler.hAdd OMF_HAS_FASTSTRINGALLOC method flag.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
@EgorBo
EgorBo marked this pull request as ready for review June 10, 2026 13:13
EgorBoand others added 2 commits June 10, 2026 15:29
Fold the near-duplicate MorphAllocObjNodeHelperStr into
MorphAllocObjNodeHelperArr (parameterized by isString) and unify the
array/string detection in AllocationKind, since a stack-allocated string
is just a char array with a different header. No functional change:
SuperPMI asmdiffs are identical to the previous commit across
libraries.pmi, coreclr_tests, libraries_tests and benchmarks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment on lines +190 to +191
if ((m_compiler->optMethodFlags & OMF_HAS_NEWOBJ) == 0 && (m_compiler->optMethodFlags & OMF_HAS_NEWARRAY) == 0 &&
(m_compiler->optMethodFlags & OMF_HAS_FASTSTRINGALLOC) == 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, is it worth just making this something like:

if ((m_compiler->optMethodFlags & OMF_OBJALLOC_MASK) == 0)

Where OMF_OBJALLOC_MASK = OMF_HAS_NEWOBJ | OMF_HAS_NEWARRAY | OMF_HAS_FASTSTRINGALLOC?

These lines aren't the worst, but every time we add one more check I think it gets a little less readable and having a way to check it all at once is nice.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although, we probably should hide these under getters, most OMF flags are already hidden behind them

Comment threadsrc/coreclr/jit/objectalloc.cpp
CopilotAI review requested due to automatic review settings June 26, 2026 01:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

@AndyAyersMS you wanted to take a look on this too

@EgorBo
EgorBo requested a review from AndyAyersMSJune 26, 2026 12:14

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some test cases? The existing test pattern is a bit annoying but AI can probably mimic it without problems.

Comment threadsrc/coreclr/jit/objectalloc.cpp
EgorBoand others added 2 commits July 6, 2026 18:58
Verify that non-escaping, constant-length strings produced by char.ToString(),
char.ToString(char), string equality of a ToString() result, and Rune.ToString()
are stack-allocated (the String.FastAllocateString call is removed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Let's postpone this till we get some meaningful diffs

@EgorBoEgorBo closed this Jul 7, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 7, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@EgorBo@AndyAyersMS@tannergooding
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

JIT: Stack allocate non-escaping strings - #129202

Closed
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings
Closed

JIT: Stack allocate non-escaping strings#129202
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Now that we intrinsified String.FastAllocateString, I guess it wouldn't hurt to enable escape analysis for it by repeating what we do for normal arrays. Most strings leak into other string APIs which actually don't escape, but we don't do IPA today. As is, this PR enables 74 strings to be stack-allocated (mostly in libraries_tests_no_tiered_compilation.run)

Stack allocate non-escaping System.String instances created via
String.FastAllocateString when the length is a compile-time constant,
reusing the existing array stack-allocation machinery.
At object-allocator time a string allocation is modelled as
FastAllocateString(pMT, length) and is treated like a char[] array via a
new OAT_NEWSTR allocation kind. The call is retyped to a native pointer,
gets a StackArrayLocal arg and the GTF_CALL_M_STACK_ARRAY flag, and is
later expanded in fgExpandStackArrayAllocations into method-table and
length stores (the length field offset is the only difference from
arrays). The stack object uses a non-GC block layout sized for the
header, chars and null terminator, capped by JitObjectStackAllocationSize.
Gated by the new DOTNET_JitObjectStackAllocationString config (on by
default). R2R is not yet supported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 01:18
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CoreCLR JIT object stack allocation support to cover System.String.FastAllocateString call sites (in addition to newarr), enabling escape analysis to stack-allocate eligible constant-length strings and expanding them via the existing stack-array allocation expansion path.

Changes:

  • Teach ObjectAllocator to recognize String.FastAllocateString(pMT, length) as a stack-allocation candidate (OAT_NEWSTR) when length is a compile-time constant.
  • Reuse the stack-array allocation machinery to represent and expand stack-allocated strings (extra StackArrayLocal arg, retype to native pointer, and late expansion in fgExpandStackArrayAllocations).
  • Add config/metrics/method-flag plumbing for string stack allocation (JitObjectStackAllocationString, new JIT metrics, OMF_HAS_FASTSTRINGALLOC).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.cppAssign a fresh non-heap VN for stack-allocated FastAllocateString calls flagged with GTF_CALL_M_STACK_ARRAY.
src/coreclr/jit/objectalloc.hAdd OAT_NEWSTR and the MorphAllocObjNodeHelperStr helper declaration.
src/coreclr/jit/objectalloc.cppDetect FastAllocateString candidates, size-check strings, and morph eligible ones into the existing stack-array allocation path.
src/coreclr/jit/jitmetadatalist.hAdd new JIT metrics for string allocation and stack-allocated strings.
src/coreclr/jit/jitconfigvalues.hAdd JitObjectStackAllocationString config switch.
src/coreclr/jit/importercalls.cppFlag methods containing FastAllocateString so escape analysis runs; also mark ThrowIfNull as special (non-fallthrough).
src/coreclr/jit/helperexpansion.cppExtend stack-array expansion to also expand stack-allocated FastAllocateString by using the string length field offset.
src/coreclr/jit/compiler.hAdd OMF_HAS_FASTSTRINGALLOC method flag.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
@EgorBo
EgorBo marked this pull request as ready for review June 10, 2026 13:13
EgorBoand others added 2 commits June 10, 2026 15:29
Fold the near-duplicate MorphAllocObjNodeHelperStr into
MorphAllocObjNodeHelperArr (parameterized by isString) and unify the
array/string detection in AllocationKind, since a stack-allocated string
is just a char array with a different header. No functional change:
SuperPMI asmdiffs are identical to the previous commit across
libraries.pmi, coreclr_tests, libraries_tests and benchmarks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment on lines +190 to +191
if ((m_compiler->optMethodFlags & OMF_HAS_NEWOBJ) == 0 && (m_compiler->optMethodFlags & OMF_HAS_NEWARRAY) == 0 &&
(m_compiler->optMethodFlags & OMF_HAS_FASTSTRINGALLOC) == 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, is it worth just making this something like:

if ((m_compiler->optMethodFlags & OMF_OBJALLOC_MASK) == 0)

Where OMF_OBJALLOC_MASK = OMF_HAS_NEWOBJ | OMF_HAS_NEWARRAY | OMF_HAS_FASTSTRINGALLOC?

These lines aren't the worst, but every time we add one more check I think it gets a little less readable and having a way to check it all at once is nice.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although, we probably should hide these under getters, most OMF flags are already hidden behind them

Comment threadsrc/coreclr/jit/objectalloc.cpp
CopilotAI review requested due to automatic review settings June 26, 2026 01:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

@AndyAyersMS you wanted to take a look on this too

@EgorBo
EgorBo requested a review from AndyAyersMSJune 26, 2026 12:14

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some test cases? The existing test pattern is a bit annoying but AI can probably mimic it without problems.

Comment threadsrc/coreclr/jit/objectalloc.cpp
EgorBoand others added 2 commits July 6, 2026 18:58
Verify that non-escaping, constant-length strings produced by char.ToString(),
char.ToString(char), string equality of a ToString() result, and Rune.ToString()
are stack-allocated (the String.FastAllocateString call is removed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Let's postpone this till we get some meaningful diffs

@EgorBoEgorBo closed this Jul 7, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 7, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@EgorBo@AndyAyersMS@tannergooding
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

JIT: Stack allocate non-escaping strings - #129202

Closed
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings
Closed

JIT: Stack allocate non-escaping strings#129202
EgorBo wants to merge 8 commits into
dotnet:mainfrom
EgorBo:egorbo/jit-stackalloc-strings

Conversation

@EgorBo

@EgorBoEgorBo commented Jun 10, 2026

Copy link
Copy Markdown
Member

Now that we intrinsified String.FastAllocateString, I guess it wouldn't hurt to enable escape analysis for it by repeating what we do for normal arrays. Most strings leak into other string APIs which actually don't escape, but we don't do IPA today. As is, this PR enables 74 strings to be stack-allocated (mostly in libraries_tests_no_tiered_compilation.run)

Stack allocate non-escaping System.String instances created via
String.FastAllocateString when the length is a compile-time constant,
reusing the existing array stack-allocation machinery.
At object-allocator time a string allocation is modelled as
FastAllocateString(pMT, length) and is treated like a char[] array via a
new OAT_NEWSTR allocation kind. The call is retyped to a native pointer,
gets a StackArrayLocal arg and the GTF_CALL_M_STACK_ARRAY flag, and is
later expanded in fgExpandStackArrayAllocations into method-table and
length stores (the length field offset is the only difference from
arrays). The stack object uses a non-GC block layout sized for the
header, chars and null terminator, capped by JitObjectStackAllocationSize.
Gated by the new DOTNET_JitObjectStackAllocationString config (on by
default). R2R is not yet supported.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 01:18
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 10, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends CoreCLR JIT object stack allocation support to cover System.String.FastAllocateString call sites (in addition to newarr), enabling escape analysis to stack-allocate eligible constant-length strings and expanding them via the existing stack-array allocation expansion path.

Changes:

  • Teach ObjectAllocator to recognize String.FastAllocateString(pMT, length) as a stack-allocation candidate (OAT_NEWSTR) when length is a compile-time constant.
  • Reuse the stack-array allocation machinery to represent and expand stack-allocated strings (extra StackArrayLocal arg, retype to native pointer, and late expansion in fgExpandStackArrayAllocations).
  • Add config/metrics/method-flag plumbing for string stack allocation (JitObjectStackAllocationString, new JIT metrics, OMF_HAS_FASTSTRINGALLOC).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/coreclr/jit/valuenum.cppAssign a fresh non-heap VN for stack-allocated FastAllocateString calls flagged with GTF_CALL_M_STACK_ARRAY.
src/coreclr/jit/objectalloc.hAdd OAT_NEWSTR and the MorphAllocObjNodeHelperStr helper declaration.
src/coreclr/jit/objectalloc.cppDetect FastAllocateString candidates, size-check strings, and morph eligible ones into the existing stack-array allocation path.
src/coreclr/jit/jitmetadatalist.hAdd new JIT metrics for string allocation and stack-allocated strings.
src/coreclr/jit/jitconfigvalues.hAdd JitObjectStackAllocationString config switch.
src/coreclr/jit/importercalls.cppFlag methods containing FastAllocateString so escape analysis runs; also mark ThrowIfNull as special (non-fallthrough).
src/coreclr/jit/helperexpansion.cppExtend stack-array expansion to also expand stack-allocated FastAllocateString by using the string length field offset.
src/coreclr/jit/compiler.hAdd OMF_HAS_FASTSTRINGALLOC method flag.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
@EgorBo
EgorBo marked this pull request as ready for review June 10, 2026 13:13
EgorBoand others added 2 commits June 10, 2026 15:29
Fold the near-duplicate MorphAllocObjNodeHelperStr into
MorphAllocObjNodeHelperArr (parameterized by isString) and unify the
array/string detection in AllocationKind, since a stack-allocated string
is just a char array with a different header. No functional change:
SuperPMI asmdiffs are identical to the previous commit across
libraries.pmi, coreclr_tests, libraries_tests and benchmarks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 10, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment on lines +190 to +191
if ((m_compiler->optMethodFlags & OMF_HAS_NEWOBJ) == 0 && (m_compiler->optMethodFlags & OMF_HAS_NEWARRAY) == 0 &&
(m_compiler->optMethodFlags & OMF_HAS_FASTSTRINGALLOC) == 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, is it worth just making this something like:

if ((m_compiler->optMethodFlags & OMF_OBJALLOC_MASK) == 0)

Where OMF_OBJALLOC_MASK = OMF_HAS_NEWOBJ | OMF_HAS_NEWARRAY | OMF_HAS_FASTSTRINGALLOC?

These lines aren't the worst, but every time we add one more check I think it gets a little less readable and having a way to check it all at once is nice.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although, we probably should hide these under getters, most OMF flags are already hidden behind them

Comment threadsrc/coreclr/jit/objectalloc.cpp
CopilotAI review requested due to automatic review settings June 26, 2026 01:13

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

@AndyAyersMS you wanted to take a look on this too

@EgorBo
EgorBo requested a review from AndyAyersMSJune 26, 2026 12:14

@AndyAyersMSAndyAyersMS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some test cases? The existing test pattern is a bit annoying but AI can probably mimic it without problems.

Comment threadsrc/coreclr/jit/objectalloc.cpp
EgorBoand others added 2 commits July 6, 2026 18:58
Verify that non-escaping, constant-length strings produced by char.ToString(),
char.ToString(char), string equality of a ToString() result, and Rune.ToString()
are stack-allocated (the String.FastAllocateString call is removed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:35

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/objectalloc.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 6, 2026 17:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
Comment threadsrc/coreclr/jit/objectalloc.cpp
@EgorBo

Copy link
Copy Markdown
MemberAuthor

Let's postpone this till we get some meaningful diffs

@EgorBoEgorBo closed this Jul 7, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 7, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@EgorBo@AndyAyersMS@tannergooding