Skip to content

RemoteMirror: Project some multi-payload enums #30357

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

Merged
merged 3 commits into from
Mar 12, 2020

Conversation

tbkka
Copy link
Contributor

@tbkka tbkka commented Mar 11, 2020

This builds on #30161 by adding support for the most basic form of multi-payload enum.

As before, the swift_reflection_projectEnum call should return false for any enum that it is unable to project, so adopters should continue to fall back to whatever mechanism they were using before if it fails.

This is one part of rdar://31666592

@tbkka tbkka requested a review from slavapestov March 11, 2020 17:08
tbkka added 2 commits March 11, 2020 10:22
…nums

According to the compiler code, the payload area is reused by treating the first
min(4, payload size) bytes as an n-byte integer.  The previous code didn't
handle 3-byte integers.

Mostly, this just means simplifying the `readInteger` function to handle
arbitrary byte lengths (requiring only that it's less than the length of the
destination integer variable).  I've also made a tentative stab at handling
big-endian architectures here.
This handles multi-payload enums with fixed
layouts that don't use spare payload bits.
It includes XI calculations that allow us to
handle single-payload enums where the payload
ultimately includes a multi-payload enum
(For example, on 32-bit platforms, String uses
a multi-payload enum, so this now supports single-payload
enums carrying Strings.)
@tbkka tbkka force-pushed the tbkka-remoteMirror-projectEnum branch from 76f29fb to 13853c1 Compare March 11, 2020 17:23
@tbkka
Copy link
Contributor Author

tbkka commented Mar 11, 2020

@swift-ci Please test

Copy link
Contributor

@slavapestov slavapestov left a comment

Choose a reason for hiding this comment

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

@jckarter should take a look at this as well.

@slavapestov
Copy link
Contributor

Basically, if all payload cases have a fixed size known at compile time in all resilience domains where the enum is visible (this is a bit tricky), you want to use spare bits. Since the compiler makes the decision it should also be the one to emit the descriptor that tells you where the spare bits are. Otherwise, you use the much simpler dynamic layout algorithm that the runtime uses in swift_getEnumCaseMultiPayload().

Also do we have a way to project single payload enums yet? The interesting thing to do here is to know which non-payload case is active.

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 13853c1

@tbkka
Copy link
Contributor Author

tbkka commented Mar 11, 2020

@slavapestov -- PR #30161 added the projectEnum API and implemented the no-payload and single-payload cases, with some follow-up fixes in #30281 and #30301.

@tbkka
Copy link
Contributor Author

tbkka commented Mar 11, 2020

@slavapestov -- If spare bits handling requires associated compiler changes, any concerns about merging this partial support and tackling that in a separate PR? Users of this API just need to be confident that this code will either project the enum correctly or return false indicating it was unable to decode the enum.

@tbkka tbkka requested a review from jckarter March 11, 2020 19:14
@tbkka
Copy link
Contributor Author

tbkka commented Mar 11, 2020

Swift-CI failure looks entirely unrelated, so I'll retry.

@tbkka
Copy link
Contributor Author

tbkka commented Mar 11, 2020

@swift-ci Please test macOS

@tbkka
Copy link
Contributor Author

tbkka commented Mar 11, 2020

Windows CI caught a typo. Restarting CI bots...

@tbkka
Copy link
Contributor Author

tbkka commented Mar 11, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 13853c1

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 13853c1

Copy link
Contributor Author

@tbkka tbkka left a comment

Choose a reason for hiding this comment

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

I added a few signpost comments to help reviewers understand this change.

case RecordKind::MultiPayloadEnum:// XXX TODO
return false;

case RecordKind::MultiPayloadEnum: {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This block of code counts XIs in MultiPayloadEnums and returns the digested result for an enclosing single-payload enum to use.

/// Returns false if the operation failed, the request size is not
/// 1, 2, 4, or 8, or the request size is larger than the provided destination.
/// Returns false if the operation failed, or the request size is
/// larger than the provided destination.
template <typename IntegerType>
bool readInteger(RemoteAddress address, size_t bytes, IntegerType *dest) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

A more flexible readInteger that can read integers with an arbitrary number of bytes, from 1 to sizeof(*dest). In particular, this is needed for handling 3-byte integers that can occur when storing enum tag indexes in the payload area.

@@ -801,7 +801,50 @@ class ReflectionContext
}

case RecordKind::MultiPayloadEnum: {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This block of code actually identifies the current case for multi-payload enums. Today, it only handles enums that use a separate tag (as inferred from the size data exposed in the type information). For other enum layouts it returns false to indicate that it is unable to parse that particular enum.

// CHECK-NEXT: (enum reflect_Enum_value.SinglePayloadEnumWithMultiPayloadEnumPayload)
// CHECK-NEXT: Value: .alsoC

reflect(enumValue: Optional<Optional<SinglePayloadEnumWithMultiPayloadEnumPayload>>.some(.none))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test, in particular, verifies that XIs are being properly counted in the multi-payload enum for use by the surrounding single-payload optionals.

// CHECK-NEXT: (enum reflect_Enum_value.SinglePayloadEnumWithMultiPayloadEnumPayload)))
// CHECK-NEXT: Value: .some(.none)

enum SmallMultiPayload {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The code internally handles payloads with size >= 4 in a different path (to avoid overflow issues on 32-bit platforms). So the test above is repeated with a multi-payload enum that has a 2-byte payload area.

@slavapestov
Copy link
Contributor

I added a few more comments just to summarize our chat discussion for other reviewers. Nothing new for you here.

@tbkka tbkka merged commit ee36c1c into swiftlang:master Mar 12, 2020
@jckarter
Copy link
Contributor

It might be fun to deploy the utils/type-layout-fuzzer.py script to generate random enums and see if we can generate test cases against them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants