Skip to content
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

Simplify methodtable #96466

Merged
merged 21 commits into from
Jan 11, 2024
Merged

Conversation

davidwrighton
Copy link
Member

@davidwrighton davidwrighton commented Jan 4, 2024

In particular, simplify access to fields of the MethodTable structure

Historically, this structure had a great many optional fields in it with several mechanisms for identifying them. As we've been working on CoreCLR, we've eliminated many of these excess fields, to the point where we likely have a final list of all expandable fields associated with the MethodTable, and we have space to make access to fields somewhat simpler.

Notably, this is an effort to reduce the number of memory reads and calculations necessary to find the various parts of a MethodTable. With this change, I believe that all data directly associated the MethodTable struct can be accessed with no more than 2 pointer chasing memory accesses and possibly reading 1 set of flags. This should simplify much of the codegen around this structure, although performance is likely unaffected, as most of the slow paths were very well optimized by native PGO technologies.

…e and the GetLoaderModule path somewhat more complex

- GetModule is more commonly used
- GetLoaderModule is still pretty cheap. It just has 1 extra memory indirection.
- This change adds 1 pointer to the size of all allocated types, which is a bit unfortunate, but it isn't that expensive.

Adjust LoaderHeap handling to pass around LoaderAllocators instead, this is useful for passing through a LoaderAllocator to the CreateMinimalMethodTable code.
- This reduces the complexity of looking it up (it is now straightforward code)
- Also adjust WFLAGS2 so that there are only 8 bits used in it
… into following the MethodTableWriteableData
…bleData at a fixed offset

- Access to this thing will no longer require computing the number of virtuals
- By being located at a fixed offset, it becomes simpler to debug manually should that be necessary
- Performance of this should be nicely maintained
…rol multipurpose slot allocation behavior anymore
- Make DAC a bit more robust against failure
- Fix issue where now that the DispatchMap is being constructed before the MethodTable, we cannot assert if a MethodDesc is virtual
- Array MethodTables now return FALSE for HasSameTypeDefAs
- This required a tweak in CEEInfo::embedGenericHandle to make it behave consistently with previous behavior
@davidwrighton davidwrighton marked this pull request as ready for review January 9, 2024 21:19
};


PTR_Module m_pLoaderModule;
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason for m_pLoaderModule to be here and not in the MethodTable?

Copy link
Member Author

Choose a reason for hiding this comment

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

No strong reason, I was trying to avoid growing the MethodTable structure, as growth has a (very) small impact on v-table slots due to the limited range of a mov instruction on x64, but its not a critical issue.

Effectively, there is a small size optimization to be had in generated code for virtual function access where if the offset of the vtable chunk index is less than 256 bytes from the start of the MethodTable, we can use a 3 byte instruction instead of a 6 byte instruction. It's not significant for throughput perf, but historically I remember seeing some not completely negligible impact on code size for ngen images when adjusting the size of MethodTable. However, of course, ngen is no longer a thing, so perhaps I shouldn't worry about that, and looking at the data, I see that it would only matter for virtual table slots 25-32 if we moved two pointer sized values down from MethodTableWriteableData to MethodTable, which probably isn't significant at all. (Possibly my memories are from the really before times, when we didn't have vtable chunks, and this change would have effected vtable slots 7 and 8, which are fairly common in code bases)

From what I can see the m_pLoaderModule's only real perf sensitive use is as part of statics lookup, and I'm planning to make that simpler in a followon checkin, which is why I didn't keep it at the MethodTable level, but you are correct, it probably would be fine as a field of MethodTable (along with the m_hExposedClassObject field which also has most of the same properties) I'd love to hear if anyone else has an opinion here.

Copy link
Member

Choose a reason for hiding this comment

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

I think that the state in this PR is fine. We can fine-tune it in follow up changes.

{
return dac_cast<PTR_GenericsStaticsInfo>(dac_cast<TADDR>(pWriteableData) - sizeof(GenericsStaticsInfo));
}
}; // struct MethodTableWriteableData
Copy link
Member

Choose a reason for hiding this comment

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

Should MethodTableWriteableData be renamed to something that better captures its current purpose? Like MethodTableAuxiliary data?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, great, that's such a nice name. I didn't have a good one in mind, so I wasn't changing it, but MethodTableAuxiliaryData is a distinct improvement, especially since the writeable concept doesn't make any sense anymore.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

LGTM. Thank you!

src/coreclr/vm/methodtablebuilder.cpp Outdated Show resolved Hide resolved
src/coreclr/vm/methodtablebuilder.cpp Outdated Show resolved Hide resolved
Comment on lines 10334 to 10335
// This also disables IBC logging until the type is sufficiently initialized so
// it needs to be done early
Copy link
Member

Choose a reason for hiding this comment

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

Is this comment still relevant?

Copy link
Member Author

Choose a reason for hiding this comment

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

No. This comment could be deleted. I'll do that in a followon PR.


size_t prependedAllocationSpace = 0;

prependedAllocationSpace = nonVirtualSlots * sizeof(TADDR);
Copy link
Member

Choose a reason for hiding this comment

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

Just initialize prependedAllocationSpace to this instead of 0?

@AaronRobinsonMSFT
Copy link
Member

The only other thing I'd ask is if there is anything that needs to be updated in the BoTR. I did a quick check and nothing jumped out, but it would be helpful if you could do a quick check.

@davidwrighton
Copy link
Member Author

@AaronRobinsonMSFT I've taken a quick look at the BoTR. All these details have apparently fallen under the category of trivial details not mentioned in the docs.

@davidwrighton davidwrighton merged commit 3c5b23f into dotnet:main Jan 11, 2024
108 of 111 checks passed
tmds pushed a commit to tmds/runtime that referenced this pull request Jan 23, 2024
In particular, simplify access to fields of the MethodTable structure

Historically, this structure had a great many optional fields in it with several mechanisms for identifying them. As we've been working on CoreCLR, we've eliminated many of these excess fields, to the point where we likely have a final list of all expandable fields associated with the MethodTable, and we have space to make access to fields somewhat simpler.

Notably, this is an effort to reduce the number of memory reads and calculations necessary to find the various parts of a MethodTable. With this change, I believe that all data directly associated the MethodTable struct can be accessed with no more than 2 pointer chasing memory accesses and possibly reading 1 set of flags. This should simplify much of the codegen around this structure, although performance is likely unaffected, as most of the slow paths were very well optimized by native PGO technologies.
@github-actions github-actions bot locked and limited conversation to collaborators Feb 11, 2024
Sign up for free to 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