dotnet/runtimelab

[Projection tooling] Implement algorithm deciding whether a struct should be projected as class or struct

Closed this issue · 4 comments

Struct should be projected as a struct if:

  • Struct needs to be marked as frozen, every member of this struct has to be either trivial or marked as frozen (recursively)
  • Structs needs to be POD/Trivial / Bitwise Movable

I did look into swift code - tried to find a better way to determine whether to project something as a struct or as class. There is a field on ValueWitnessTable called IsNotInline which seems to be true whenever the struct will be passes as a pointer. Link. However this value will also be true for frozen structs which exceed the lowering threshold (4 machine words). Have we looked into that before?

An alternative is to recursively traverse struct children - this however means that all of struct children have to processed before a projection involving a struct can be made - which means building up the type database of multiple modules before a single projection can be made.

cc: @jkoritzinsky @stephen-hawley @kotlarmilos @matouskozak

Having a complete type database seems more reliable to me.

Having a complete type database seems more reliable to me.

+1. We can assume that projection tooling will process modules in a correct order.

We might not be able to read ValueWitnessTable if target is not macOS. I suggest that the projection tooling emits a Debug.Assert for IsNotInline flag to ensures that the projections match the expected lowering, but the ABI file should be treated as the source of truth.

Great! I then propose the following design:

Assumption: Tooling will process modules in correct order. Processing each module will result in a type database file.

When processing a new module the tooling will first parse the ABI and build a graph of dependencies for each type. Dependencies will go into two categories (same module / other modules).

Then in a post-processing step the tooling will process the graph and compute the necessary information. Doing this in correct order will ensure that when processing a node either its dependencies reside in one of the type databases for previous modules or have been processed earlier. After the processing is finished the tooling will lock the type database and save it.