-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Place dispatch cells in dehydrated section #78748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,7 @@ | |
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
|
|
||
| using Internal.Text; | ||
| using Internal.TypeSystem; | ||
|
|
||
| using Debug = System.Diagnostics.Debug; | ||
|
|
@@ -14,17 +14,15 @@ namespace ILCompiler.DependencyAnalysis | |
| /// Represents a section of the executable where interface dispatch cells and their slot information | ||
| /// is stored. | ||
| /// </summary> | ||
| public class InterfaceDispatchCellSectionNode : ArrayOfEmbeddedDataNode<InterfaceDispatchCellNode> | ||
| public class InterfaceDispatchCellSectionNode : DehydratableObjectNode, ISymbolDefinitionNode | ||
| { | ||
| public InterfaceDispatchCellSectionNode(NodeFactory factory) | ||
| : base("__InterfaceDispatchCellSection_Start", "__InterfaceDispatchCellSection_End", new DispatchCellComparer(factory)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to emit the end symbol separately now? What are the end symbols used for in general - is it just bookkeeping to make the exe easier to inspect? Or are they used at runtime?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We didn't need an end symbol for this one - the structure of the base class just required one. We have some tables where the start and end symbols are used to figure out the length of the table. But dispatch cells are individually addressable and there's no code to enumerate all the dispatch cells (we don't have a purpose for such code) - end symbol is not needed. |
||
| { | ||
| } | ||
|
|
||
| protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) | ||
| protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly) | ||
| { | ||
| if (relocsOnly) | ||
| return; | ||
| return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, Array.Empty<ISymbolDefinitionNode>()); | ||
|
|
||
| var builder = new ObjectDataBuilder(factory, relocsOnly); | ||
| builder.AddSymbol(this); | ||
|
|
||
| // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the | ||
| // synchronization mechanism of the two values in the runtime. | ||
|
|
@@ -48,7 +46,7 @@ protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, No | |
| // | ||
| int runLength = 0; | ||
| int currentSlot = NoSlot; | ||
| foreach (InterfaceDispatchCellNode node in NodesList) | ||
| foreach (InterfaceDispatchCellNode node in new SortedSet<InterfaceDispatchCellNode>(factory.MetadataManager.GetInterfaceDispatchCells(), new DispatchCellComparer(factory))) | ||
| { | ||
| MethodDesc targetMethod = node.TargetMethod; | ||
| int targetSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType); | ||
|
|
@@ -83,10 +81,23 @@ protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, No | |
| builder.EmitZeroPointer(); | ||
| builder.EmitNaturalInt(currentSlot); | ||
| } | ||
|
|
||
| return builder.ToObjectData(); | ||
| } | ||
|
|
||
| public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) | ||
| => sb.Append(nameMangler.CompilationUnitPrefix).Append("__InterfaceDispatchCellSection_Start"); | ||
| protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) => ObjectNodeSection.DataSection; | ||
| protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); | ||
|
|
||
| public override int ClassCode => -1389343; | ||
|
|
||
| public int Offset => 0; | ||
|
|
||
| public override bool IsShareable => false; | ||
|
|
||
| public override bool StaticDependenciesAreComputed => true; | ||
|
|
||
| /// <summary> | ||
| /// Comparer that groups interface dispatch cells by their slot number. | ||
| /// </summary> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checking my understanding - before this change, all of the object data we were dehydrating had zeros in place of the relocs, but now some other component is writing an offset there, right?
Is this the place where the offset is written?
runtime/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
Lines 103 to 104 in d4d12c5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, this matches how it's represented in the object file as well. The relocation is basically an addend - if the value is all zeros, the effect is that the address of the relocation target is written. But if it's non-zero, we get a "displaced" pointer to the target of the relocation (the displacement is the value that was originally stored there). If we know the target is going to be aligned, we sometimes use displacement as a way to get "spare bits". Those bits get masked off before dereferencing the pointer at runtime and can indicate the thing the pointer points to (like in the above case, they indicate
CachePointerIsInterfaceRelativePointer).