') + ')', '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('^' + ".*" + ', '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" + ', '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('^' + ".*" + ', '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); } })(); })(); JIT: Model GS cookie check in LSRA by jakobbotsch · Pull Request #120192 · dotnet/runtime · GitHub
Skip to content

JIT: Model GS cookie check in LSRA - #120192

Merged
jakobbotsch merged 5 commits into
dotnet:mainfrom
jakobbotsch:fix-119949
Oct 15, 2025
Merged

JIT: Model GS cookie check in LSRA#120192
jakobbotsch merged 5 commits into
dotnet:mainfrom
jakobbotsch:fix-119949

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

Also switch the register used when generating the check if there is a tailcall in the block on x64. This allows us to enable fast tailcalls out of methods with GS cookie checks on x64.

Fix#119949

Also switch the register used when generating the check if there is a
tailcall in the block on x64. This allows us to enable fast tailcalls
out of methods with GS cookie checks on x64.
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Sep 29, 2025
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@jakobbotsch
jakobbotsch marked this pull request as ready for review October 6, 2025 14:43
CopilotAI review requested due to automatic review settings October 6, 2025 14:43

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 enables fast tail calls from methods that require GS (Guard Stack) security cookie checks on x64 by modeling the GS cookie check in LSRA (Linear Scan Register Allocator) and adapting register selection for tail call scenarios. Previously, fast tail calls were disabled for methods with GS cookie checks on x64 due to compatibility requirements.

  • Removes the restriction that prevented fast tail calls from methods with GS cookie checks on x64
  • Models GS cookie checks in LSRA to properly handle register allocation conflicts
  • Introduces dynamic register selection for GS cookie checks based on whether a tail call is present

Reviewed Changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/tests/JIT/opt/Tailcall/TailcallVerifyWithPrefix.ilRemoves test case Condition17 that is no longer needed
src/coreclr/jit/targetriscv64.hReplaces individual register definitions with register mask for GS cookie temps
src/coreclr/jit/targetloongarch64.hReplaces individual register definitions with register mask for GS cookie temps
src/coreclr/jit/targetarm64.hReplaces individual register definitions with register mask for GS cookie temps
src/coreclr/jit/targetarm.hReplaces individual register definitions with register mask for GS cookie temps
src/coreclr/jit/morph.cppRemoves x64-specific restriction preventing fast tail calls with GS cookie checks
src/coreclr/jit/lsraxarch.cppAdds logic to exclude GS cookie temp registers from control expression candidates for fast tail calls
src/coreclr/jit/lsrariscv64.cppUpdates to use new centralized GS cookie temp register selection
src/coreclr/jit/lsraloongarch64.cppUpdates to use new centralized GS cookie temp register selection
src/coreclr/jit/lsrabuild.cppAdds LSRA modeling for GS cookie checks by inserting register kills
src/coreclr/jit/lsraarmarch.cppUpdates to use new centralized GS cookie temp register selection
src/coreclr/jit/lower.cppRemoves assertion that prevented GS cookie checks in fast tail calls on x64
src/coreclr/jit/codegenxarch.cppSimplifies GS cookie check implementation and removes tail call specific logic
src/coreclr/jit/codegenriscv64.cppUpdates GS cookie check to use dynamic register selection
src/coreclr/jit/codegenloongarch64.cppUpdates GS cookie check to use dynamic register selection
src/coreclr/jit/codegeninterface.hAdds declaration for new genGetGSCookieTempRegs method
src/coreclr/jit/codegencommon.cppImplements centralized logic for GS cookie temp register selection
src/coreclr/jit/codegenarmarch.cppUpdates GS cookie check to use dynamic register selection
src/coreclr/jit/codegen.hUpdates genEmitGSCookieCheck method signature to use tailCall parameter

Comment threadsrc/tests/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

PTAL @dotnet/jit-contrib

Diffs. Some minor size regressions because the proper encoding of the kill seems to perturb LSRA a little bit, making it pick some other registers with larger encoding. Rarely some improvements when we now tailcall out of some more methods.

@jakobbotsch
jakobbotsch requested a review from a teamOctober 6, 2025 14:47
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Ping @dotnet/jit-contrib. Anyone up for reviewing this backend PR? 🙂

kg
kg approved these changes Oct 10, 2025

@kgkg 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.

LGTM but a review from someone who knows JIT better would be good. I don't see anything risky in here though.

Random thought: Do we need GS cookie checks before throws, too?

@AndyAyersMS

Copy link
Copy Markdown
Member

LGTM but a review from someone who knows JIT better would be good. I don't see anything risky in here though.

Random thought: Do we need GS cookie checks before throws, too?

I believe the runtime will do cookie checks as it walks the stack / unwinds, so we only need to do these checks for normal returns.

@jakobbotsch
jakobbotsch merged commit 98de027 into dotnet:mainOct 15, 2025
148 checks passed
@jakobbotsch
jakobbotsch deleted the fix-119949 branch October 15, 2025 11:10
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 15, 2025
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.

[RuntimeAsync] GS check at returns should be modeled via a register kill in LSRA

4 participants

@jakobbotsch@AndyAyersMS@kg