[cdac] Implement NibbleMap lookup and tests - #108403

Merged
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone
Oct 8, 2024
Merged

[cdac] Implement NibbleMap lookup and tests#108403
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone

Conversation

@lambdageek

@lambdageeklambdageek commented Sep 30, 2024

Copy link
Copy Markdown
Member

The execution manager uses a nibble map to quickly map program counter pointers to the beginnings of the native code for the managed method.

Implement the lookup algorithm for a nibble map.

Start adding unit tests for the nibble map

Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.

@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 30, 2024
@lambdageeklambdageek added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 30, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

The execution manager uses a nibble map to quickly map program counter
pointers to the beginnings of the native code for the managed method.
Implement the lookup algorithm for a nibble map.
Start adding unit tests for the nibble map
Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 5c161e9 to 51d7696CompareOctober 7, 2024 23:40
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 51d7696 to 4182125CompareOctober 7, 2024 23:51

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

I have two design questions, but other than that it looks good.

// We will then align the map index to the start of the current map unit (map index 8) and move back to the previous map unit (map index 7)
// At that point, we scan backwards for non-zero map units. Since there are none, we return null.

internal class NibbleMap

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.

Should we think about putting version numbers on these classes. For instance, we know that there are more optimal forms of the NibbleMap that we might implement in the future, and I don't want to get rid of the existing code here, as it could be used to support an old version of the runtime. Do we want to think about calling these things NibbleMap_1 or something?

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.

yep. we could do it now, or we could do it when we have a second algorithm. NibbleMap doesn't leak out of the ExecutionManager contract, so we can cross that bridge when we get to it (also maybe we'll have better names than _1 and _2)

public bool Equals(TargetCodePointer x, TargetCodePointer y) => x.Value == y.Value;
public int GetHashCode(TargetCodePointer obj) => obj.Value.GetHashCode();

public TargetPointer AsTargetPointer => new(Value);

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.

On ARM32 platforms should this strip off the thumb bit? For reference, on ARM32 Thumb2 targets, the lowest bit is typically set on a code address, to indicate that the pointer refers to a code using the Thumb2 instruction set instead of the ARM instruction set.

I see this as a potential problem around the conversion to ulong here, as well as the AsTargetPointer api.

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.

yea that's a good idea. Elsewhere (in the PrecodeStubs contract) I have an explicit helper that strips off the thumb bit:

internalTargetPointerCodePointerReadableInstrPointer(TargetCodePointercodePointer){// Mask off the thumb bit, if we're on arm32, to get the actual instruction pointerulonginstrPointer=(ulong)codePointer.AsTargetPointer&MachineDescriptor.CodePointerToInstrPointerMask.Value;returnnewTargetPointer(instrPointer);}

I couldn't decide if that's something we want on the TargetCodePointer or on the Target (or on a contract, as I've prototyped it so far)

I think on TargetCodePointer makes the most sense, but then i'll need to store the mask in the code pointer instance at creation time (or make the conversion to a TargetPointer depend on the current target) - and i wasn't sure about the usability of that approach

@lambdageek
lambdageek merged commit 9d923b8 into dotnet:mainOct 8, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 8, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@lambdageek@filipnavara@davidwrighton@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n 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;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} 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

[cdac] Implement NibbleMap lookup and tests - #108403

Merged
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone
Oct 8, 2024
Merged

[cdac] Implement NibbleMap lookup and tests#108403
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone

Conversation

@lambdageek

@lambdageeklambdageek commented Sep 30, 2024

Copy link
Copy Markdown
Member

The execution manager uses a nibble map to quickly map program counter pointers to the beginnings of the native code for the managed method.

Implement the lookup algorithm for a nibble map.

Start adding unit tests for the nibble map

Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.

@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 30, 2024
@lambdageeklambdageek added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 30, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

The execution manager uses a nibble map to quickly map program counter
pointers to the beginnings of the native code for the managed method.
Implement the lookup algorithm for a nibble map.
Start adding unit tests for the nibble map
Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 5c161e9 to 51d7696CompareOctober 7, 2024 23:40
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 51d7696 to 4182125CompareOctober 7, 2024 23:51

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

I have two design questions, but other than that it looks good.

// We will then align the map index to the start of the current map unit (map index 8) and move back to the previous map unit (map index 7)
// At that point, we scan backwards for non-zero map units. Since there are none, we return null.

internal class NibbleMap

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.

Should we think about putting version numbers on these classes. For instance, we know that there are more optimal forms of the NibbleMap that we might implement in the future, and I don't want to get rid of the existing code here, as it could be used to support an old version of the runtime. Do we want to think about calling these things NibbleMap_1 or something?

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.

yep. we could do it now, or we could do it when we have a second algorithm. NibbleMap doesn't leak out of the ExecutionManager contract, so we can cross that bridge when we get to it (also maybe we'll have better names than _1 and _2)

public bool Equals(TargetCodePointer x, TargetCodePointer y) => x.Value == y.Value;
public int GetHashCode(TargetCodePointer obj) => obj.Value.GetHashCode();

public TargetPointer AsTargetPointer => new(Value);

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.

On ARM32 platforms should this strip off the thumb bit? For reference, on ARM32 Thumb2 targets, the lowest bit is typically set on a code address, to indicate that the pointer refers to a code using the Thumb2 instruction set instead of the ARM instruction set.

I see this as a potential problem around the conversion to ulong here, as well as the AsTargetPointer api.

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.

yea that's a good idea. Elsewhere (in the PrecodeStubs contract) I have an explicit helper that strips off the thumb bit:

internalTargetPointerCodePointerReadableInstrPointer(TargetCodePointercodePointer){// Mask off the thumb bit, if we're on arm32, to get the actual instruction pointerulonginstrPointer=(ulong)codePointer.AsTargetPointer&MachineDescriptor.CodePointerToInstrPointerMask.Value;returnnewTargetPointer(instrPointer);}

I couldn't decide if that's something we want on the TargetCodePointer or on the Target (or on a contract, as I've prototyped it so far)

I think on TargetCodePointer makes the most sense, but then i'll need to store the mask in the code pointer instance at creation time (or make the conversion to a TargetPointer depend on the current target) - and i wasn't sure about the usability of that approach

@lambdageek
lambdageek merged commit 9d923b8 into dotnet:mainOct 8, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 8, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

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

[cdac] Implement NibbleMap lookup and tests - #108403

Merged
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone
Oct 8, 2024
Merged

[cdac] Implement NibbleMap lookup and tests#108403
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone

Conversation

@lambdageek

@lambdageeklambdageek commented Sep 30, 2024

Copy link
Copy Markdown
Member

The execution manager uses a nibble map to quickly map program counter pointers to the beginnings of the native code for the managed method.

Implement the lookup algorithm for a nibble map.

Start adding unit tests for the nibble map

Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.

@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 30, 2024
@lambdageeklambdageek added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 30, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

The execution manager uses a nibble map to quickly map program counter
pointers to the beginnings of the native code for the managed method.
Implement the lookup algorithm for a nibble map.
Start adding unit tests for the nibble map
Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 5c161e9 to 51d7696CompareOctober 7, 2024 23:40
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 51d7696 to 4182125CompareOctober 7, 2024 23:51

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

I have two design questions, but other than that it looks good.

// We will then align the map index to the start of the current map unit (map index 8) and move back to the previous map unit (map index 7)
// At that point, we scan backwards for non-zero map units. Since there are none, we return null.

internal class NibbleMap

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.

Should we think about putting version numbers on these classes. For instance, we know that there are more optimal forms of the NibbleMap that we might implement in the future, and I don't want to get rid of the existing code here, as it could be used to support an old version of the runtime. Do we want to think about calling these things NibbleMap_1 or something?

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.

yep. we could do it now, or we could do it when we have a second algorithm. NibbleMap doesn't leak out of the ExecutionManager contract, so we can cross that bridge when we get to it (also maybe we'll have better names than _1 and _2)

public bool Equals(TargetCodePointer x, TargetCodePointer y) => x.Value == y.Value;
public int GetHashCode(TargetCodePointer obj) => obj.Value.GetHashCode();

public TargetPointer AsTargetPointer => new(Value);

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.

On ARM32 platforms should this strip off the thumb bit? For reference, on ARM32 Thumb2 targets, the lowest bit is typically set on a code address, to indicate that the pointer refers to a code using the Thumb2 instruction set instead of the ARM instruction set.

I see this as a potential problem around the conversion to ulong here, as well as the AsTargetPointer api.

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.

yea that's a good idea. Elsewhere (in the PrecodeStubs contract) I have an explicit helper that strips off the thumb bit:

internalTargetPointerCodePointerReadableInstrPointer(TargetCodePointercodePointer){// Mask off the thumb bit, if we're on arm32, to get the actual instruction pointerulonginstrPointer=(ulong)codePointer.AsTargetPointer&MachineDescriptor.CodePointerToInstrPointerMask.Value;returnnewTargetPointer(instrPointer);}

I couldn't decide if that's something we want on the TargetCodePointer or on the Target (or on a contract, as I've prototyped it so far)

I think on TargetCodePointer makes the most sense, but then i'll need to store the mask in the code pointer instance at creation time (or make the conversion to a TargetPointer depend on the current target) - and i wasn't sure about the usability of that approach

@lambdageek
lambdageek merged commit 9d923b8 into dotnet:mainOct 8, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 8, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

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

[cdac] Implement NibbleMap lookup and tests - #108403

Merged
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone
Oct 8, 2024
Merged

[cdac] Implement NibbleMap lookup and tests#108403
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone

Conversation

@lambdageek

@lambdageeklambdageek commented Sep 30, 2024

Copy link
Copy Markdown
Member

The execution manager uses a nibble map to quickly map program counter pointers to the beginnings of the native code for the managed method.

Implement the lookup algorithm for a nibble map.

Start adding unit tests for the nibble map

Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.

@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 30, 2024
@lambdageeklambdageek added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 30, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

The execution manager uses a nibble map to quickly map program counter
pointers to the beginnings of the native code for the managed method.
Implement the lookup algorithm for a nibble map.
Start adding unit tests for the nibble map
Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 5c161e9 to 51d7696CompareOctober 7, 2024 23:40
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 51d7696 to 4182125CompareOctober 7, 2024 23:51

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

I have two design questions, but other than that it looks good.

// We will then align the map index to the start of the current map unit (map index 8) and move back to the previous map unit (map index 7)
// At that point, we scan backwards for non-zero map units. Since there are none, we return null.

internal class NibbleMap

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.

Should we think about putting version numbers on these classes. For instance, we know that there are more optimal forms of the NibbleMap that we might implement in the future, and I don't want to get rid of the existing code here, as it could be used to support an old version of the runtime. Do we want to think about calling these things NibbleMap_1 or something?

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.

yep. we could do it now, or we could do it when we have a second algorithm. NibbleMap doesn't leak out of the ExecutionManager contract, so we can cross that bridge when we get to it (also maybe we'll have better names than _1 and _2)

public bool Equals(TargetCodePointer x, TargetCodePointer y) => x.Value == y.Value;
public int GetHashCode(TargetCodePointer obj) => obj.Value.GetHashCode();

public TargetPointer AsTargetPointer => new(Value);

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.

On ARM32 platforms should this strip off the thumb bit? For reference, on ARM32 Thumb2 targets, the lowest bit is typically set on a code address, to indicate that the pointer refers to a code using the Thumb2 instruction set instead of the ARM instruction set.

I see this as a potential problem around the conversion to ulong here, as well as the AsTargetPointer api.

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.

yea that's a good idea. Elsewhere (in the PrecodeStubs contract) I have an explicit helper that strips off the thumb bit:

internalTargetPointerCodePointerReadableInstrPointer(TargetCodePointercodePointer){// Mask off the thumb bit, if we're on arm32, to get the actual instruction pointerulonginstrPointer=(ulong)codePointer.AsTargetPointer&MachineDescriptor.CodePointerToInstrPointerMask.Value;returnnewTargetPointer(instrPointer);}

I couldn't decide if that's something we want on the TargetCodePointer or on the Target (or on a contract, as I've prototyped it so far)

I think on TargetCodePointer makes the most sense, but then i'll need to store the mask in the code pointer instance at creation time (or make the conversion to a TargetPointer depend on the current target) - and i wasn't sure about the usability of that approach

@lambdageek
lambdageek merged commit 9d923b8 into dotnet:mainOct 8, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 8, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@lambdageek@filipnavara@davidwrighton@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } 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

[cdac] Implement NibbleMap lookup and tests - #108403

Merged
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone
Oct 8, 2024
Merged

[cdac] Implement NibbleMap lookup and tests#108403
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone

Conversation

@lambdageek

@lambdageeklambdageek commented Sep 30, 2024

Copy link
Copy Markdown
Member

The execution manager uses a nibble map to quickly map program counter pointers to the beginnings of the native code for the managed method.

Implement the lookup algorithm for a nibble map.

Start adding unit tests for the nibble map

Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.

@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 30, 2024
@lambdageeklambdageek added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 30, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

The execution manager uses a nibble map to quickly map program counter
pointers to the beginnings of the native code for the managed method.
Implement the lookup algorithm for a nibble map.
Start adding unit tests for the nibble map
Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 5c161e9 to 51d7696CompareOctober 7, 2024 23:40
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 51d7696 to 4182125CompareOctober 7, 2024 23:51

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

I have two design questions, but other than that it looks good.

// We will then align the map index to the start of the current map unit (map index 8) and move back to the previous map unit (map index 7)
// At that point, we scan backwards for non-zero map units. Since there are none, we return null.

internal class NibbleMap

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.

Should we think about putting version numbers on these classes. For instance, we know that there are more optimal forms of the NibbleMap that we might implement in the future, and I don't want to get rid of the existing code here, as it could be used to support an old version of the runtime. Do we want to think about calling these things NibbleMap_1 or something?

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.

yep. we could do it now, or we could do it when we have a second algorithm. NibbleMap doesn't leak out of the ExecutionManager contract, so we can cross that bridge when we get to it (also maybe we'll have better names than _1 and _2)

public bool Equals(TargetCodePointer x, TargetCodePointer y) => x.Value == y.Value;
public int GetHashCode(TargetCodePointer obj) => obj.Value.GetHashCode();

public TargetPointer AsTargetPointer => new(Value);

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.

On ARM32 platforms should this strip off the thumb bit? For reference, on ARM32 Thumb2 targets, the lowest bit is typically set on a code address, to indicate that the pointer refers to a code using the Thumb2 instruction set instead of the ARM instruction set.

I see this as a potential problem around the conversion to ulong here, as well as the AsTargetPointer api.

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.

yea that's a good idea. Elsewhere (in the PrecodeStubs contract) I have an explicit helper that strips off the thumb bit:

internalTargetPointerCodePointerReadableInstrPointer(TargetCodePointercodePointer){// Mask off the thumb bit, if we're on arm32, to get the actual instruction pointerulonginstrPointer=(ulong)codePointer.AsTargetPointer&MachineDescriptor.CodePointerToInstrPointerMask.Value;returnnewTargetPointer(instrPointer);}

I couldn't decide if that's something we want on the TargetCodePointer or on the Target (or on a contract, as I've prototyped it so far)

I think on TargetCodePointer makes the most sense, but then i'll need to store the mask in the code pointer instance at creation time (or make the conversion to a TargetPointer depend on the current target) - and i wasn't sure about the usability of that approach

@lambdageek
lambdageek merged commit 9d923b8 into dotnet:mainOct 8, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 8, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

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

[cdac] Implement NibbleMap lookup and tests - #108403

Merged
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone
Oct 8, 2024
Merged

[cdac] Implement NibbleMap lookup and tests#108403
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone

Conversation

@lambdageek

@lambdageeklambdageek commented Sep 30, 2024

Copy link
Copy Markdown
Member

The execution manager uses a nibble map to quickly map program counter pointers to the beginnings of the native code for the managed method.

Implement the lookup algorithm for a nibble map.

Start adding unit tests for the nibble map

Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.

@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 30, 2024
@lambdageeklambdageek added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 30, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

The execution manager uses a nibble map to quickly map program counter
pointers to the beginnings of the native code for the managed method.
Implement the lookup algorithm for a nibble map.
Start adding unit tests for the nibble map
Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 5c161e9 to 51d7696CompareOctober 7, 2024 23:40
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 51d7696 to 4182125CompareOctober 7, 2024 23:51

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

I have two design questions, but other than that it looks good.

// We will then align the map index to the start of the current map unit (map index 8) and move back to the previous map unit (map index 7)
// At that point, we scan backwards for non-zero map units. Since there are none, we return null.

internal class NibbleMap

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.

Should we think about putting version numbers on these classes. For instance, we know that there are more optimal forms of the NibbleMap that we might implement in the future, and I don't want to get rid of the existing code here, as it could be used to support an old version of the runtime. Do we want to think about calling these things NibbleMap_1 or something?

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.

yep. we could do it now, or we could do it when we have a second algorithm. NibbleMap doesn't leak out of the ExecutionManager contract, so we can cross that bridge when we get to it (also maybe we'll have better names than _1 and _2)

public bool Equals(TargetCodePointer x, TargetCodePointer y) => x.Value == y.Value;
public int GetHashCode(TargetCodePointer obj) => obj.Value.GetHashCode();

public TargetPointer AsTargetPointer => new(Value);

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.

On ARM32 platforms should this strip off the thumb bit? For reference, on ARM32 Thumb2 targets, the lowest bit is typically set on a code address, to indicate that the pointer refers to a code using the Thumb2 instruction set instead of the ARM instruction set.

I see this as a potential problem around the conversion to ulong here, as well as the AsTargetPointer api.

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.

yea that's a good idea. Elsewhere (in the PrecodeStubs contract) I have an explicit helper that strips off the thumb bit:

internalTargetPointerCodePointerReadableInstrPointer(TargetCodePointercodePointer){// Mask off the thumb bit, if we're on arm32, to get the actual instruction pointerulonginstrPointer=(ulong)codePointer.AsTargetPointer&MachineDescriptor.CodePointerToInstrPointerMask.Value;returnnewTargetPointer(instrPointer);}

I couldn't decide if that's something we want on the TargetCodePointer or on the Target (or on a contract, as I've prototyped it so far)

I think on TargetCodePointer makes the most sense, but then i'll need to store the mask in the code pointer instance at creation time (or make the conversion to a TargetPointer depend on the current target) - and i wasn't sure about the usability of that approach

@lambdageek
lambdageek merged commit 9d923b8 into dotnet:mainOct 8, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 8, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

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

[cdac] Implement NibbleMap lookup and tests - #108403

Merged
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone
Oct 8, 2024
Merged

[cdac] Implement NibbleMap lookup and tests#108403
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone

Conversation

@lambdageek

@lambdageeklambdageek commented Sep 30, 2024

Copy link
Copy Markdown
Member

The execution manager uses a nibble map to quickly map program counter pointers to the beginnings of the native code for the managed method.

Implement the lookup algorithm for a nibble map.

Start adding unit tests for the nibble map

Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.

@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 30, 2024
@lambdageeklambdageek added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 30, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

The execution manager uses a nibble map to quickly map program counter
pointers to the beginnings of the native code for the managed method.
Implement the lookup algorithm for a nibble map.
Start adding unit tests for the nibble map
Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 5c161e9 to 51d7696CompareOctober 7, 2024 23:40
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 51d7696 to 4182125CompareOctober 7, 2024 23:51

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

I have two design questions, but other than that it looks good.

// We will then align the map index to the start of the current map unit (map index 8) and move back to the previous map unit (map index 7)
// At that point, we scan backwards for non-zero map units. Since there are none, we return null.

internal class NibbleMap

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.

Should we think about putting version numbers on these classes. For instance, we know that there are more optimal forms of the NibbleMap that we might implement in the future, and I don't want to get rid of the existing code here, as it could be used to support an old version of the runtime. Do we want to think about calling these things NibbleMap_1 or something?

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.

yep. we could do it now, or we could do it when we have a second algorithm. NibbleMap doesn't leak out of the ExecutionManager contract, so we can cross that bridge when we get to it (also maybe we'll have better names than _1 and _2)

public bool Equals(TargetCodePointer x, TargetCodePointer y) => x.Value == y.Value;
public int GetHashCode(TargetCodePointer obj) => obj.Value.GetHashCode();

public TargetPointer AsTargetPointer => new(Value);

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.

On ARM32 platforms should this strip off the thumb bit? For reference, on ARM32 Thumb2 targets, the lowest bit is typically set on a code address, to indicate that the pointer refers to a code using the Thumb2 instruction set instead of the ARM instruction set.

I see this as a potential problem around the conversion to ulong here, as well as the AsTargetPointer api.

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.

yea that's a good idea. Elsewhere (in the PrecodeStubs contract) I have an explicit helper that strips off the thumb bit:

internalTargetPointerCodePointerReadableInstrPointer(TargetCodePointercodePointer){// Mask off the thumb bit, if we're on arm32, to get the actual instruction pointerulonginstrPointer=(ulong)codePointer.AsTargetPointer&MachineDescriptor.CodePointerToInstrPointerMask.Value;returnnewTargetPointer(instrPointer);}

I couldn't decide if that's something we want on the TargetCodePointer or on the Target (or on a contract, as I've prototyped it so far)

I think on TargetCodePointer makes the most sense, but then i'll need to store the mask in the code pointer instance at creation time (or make the conversion to a TargetPointer depend on the current target) - and i wasn't sure about the usability of that approach

@lambdageek
lambdageek merged commit 9d923b8 into dotnet:mainOct 8, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 8, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

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

[cdac] Implement NibbleMap lookup and tests - #108403

Merged
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone
Oct 8, 2024
Merged

[cdac] Implement NibbleMap lookup and tests#108403
lambdageek merged 10 commits into
dotnet:mainfrom
lambdageek:cdac-nibblemap-standalone

Conversation

@lambdageek

@lambdageeklambdageek commented Sep 30, 2024

Copy link
Copy Markdown
Member

The execution manager uses a nibble map to quickly map program counter pointers to the beginnings of the native code for the managed method.

Implement the lookup algorithm for a nibble map.

Start adding unit tests for the nibble map

Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.

@ghostghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Sep 30, 2024
@lambdageeklambdageek added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 30, 2024
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

The execution manager uses a nibble map to quickly map program counter
pointers to the beginnings of the native code for the managed method.
Implement the lookup algorithm for a nibble map.
Start adding unit tests for the nibble map
Also for testing in MockMemorySpace simplify ReaderContext, there's nothing special about the descriptor HeapFragments anymore. We can use a uniform reader.
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
Comment threaddocs/design/datacontracts/ExecutionManager.md Outdated
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 5c161e9 to 51d7696CompareOctober 7, 2024 23:40
@lambdageek
lambdageekforce-pushed the cdac-nibblemap-standalone branch from 51d7696 to 4182125CompareOctober 7, 2024 23:51

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

I have two design questions, but other than that it looks good.

// We will then align the map index to the start of the current map unit (map index 8) and move back to the previous map unit (map index 7)
// At that point, we scan backwards for non-zero map units. Since there are none, we return null.

internal class NibbleMap

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.

Should we think about putting version numbers on these classes. For instance, we know that there are more optimal forms of the NibbleMap that we might implement in the future, and I don't want to get rid of the existing code here, as it could be used to support an old version of the runtime. Do we want to think about calling these things NibbleMap_1 or something?

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.

yep. we could do it now, or we could do it when we have a second algorithm. NibbleMap doesn't leak out of the ExecutionManager contract, so we can cross that bridge when we get to it (also maybe we'll have better names than _1 and _2)

public bool Equals(TargetCodePointer x, TargetCodePointer y) => x.Value == y.Value;
public int GetHashCode(TargetCodePointer obj) => obj.Value.GetHashCode();

public TargetPointer AsTargetPointer => new(Value);

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.

On ARM32 platforms should this strip off the thumb bit? For reference, on ARM32 Thumb2 targets, the lowest bit is typically set on a code address, to indicate that the pointer refers to a code using the Thumb2 instruction set instead of the ARM instruction set.

I see this as a potential problem around the conversion to ulong here, as well as the AsTargetPointer api.

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.

yea that's a good idea. Elsewhere (in the PrecodeStubs contract) I have an explicit helper that strips off the thumb bit:

internalTargetPointerCodePointerReadableInstrPointer(TargetCodePointercodePointer){// Mask off the thumb bit, if we're on arm32, to get the actual instruction pointerulonginstrPointer=(ulong)codePointer.AsTargetPointer&MachineDescriptor.CodePointerToInstrPointerMask.Value;returnnewTargetPointer(instrPointer);}

I couldn't decide if that's something we want on the TargetCodePointer or on the Target (or on a contract, as I've prototyped it so far)

I think on TargetCodePointer makes the most sense, but then i'll need to store the mask in the code pointer instance at creation time (or make the conversion to a TargetPointer depend on the current target) - and i wasn't sure about the usability of that approach

@lambdageek
lambdageek merged commit 9d923b8 into dotnet:mainOct 8, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Nov 8, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@lambdageek@filipnavara@davidwrighton@max-charlamb