-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Expand the work from #73491 to support more MPE layouts. #74145
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
Conversation
…s also switches the MPE layout code to exclusively use the new code. The key observation: existing reflection metadata seems to already provide enough information in all cases, so we can abandon an earlier effort to add spare bitmask data. Resolves rdar://129281368
@swift-ci Please test |
@@ -74,7 +74,16 @@ class BitMask { | |||
|
|||
BitMask(unsigned sizeInBytes, uint64_t sourceMask): size(sizeInBytes) { | |||
mask = (uint8_t *)calloc(1, sizeInBytes); | |||
memcpy(mask, &sourceMask, sizeInBytes); | |||
if (!mask) { |
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.
This is just here to further harden the bit mask code against allocation failures. Allocation failures can occur in this code when clients try to use RemoteMirror to decipher type data from random chunks of memory.
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.
Should we also have a limit on sizeInBytes
so we don't read garbage and then successfully, but unhappily, allocate 500TB of memory?
@@ -315,6 +315,7 @@ BitMask BuiltinTypeInfo::getSpareBits(TypeConverter &TC, bool &hasAddrOnly) cons | |||
mask.keepOnlyMostSignificantBits(getSize() * 8 - intSize); | |||
return mask; | |||
} else if ( | |||
Name == "ypXp" || // Any.Type |
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.
There are doubtless other pointer types that need to expose spare bits. I expect some further iteration of this specific test here.
@@ -578,7 +579,9 @@ class NoPayloadEnumTypeInfo: public EnumTypeInfo { | |||
} | |||
|
|||
BitMask getSpareBits(TypeConverter &TC, bool &hasAddrOnly) const override { | |||
return BitMask::zeroMask(getSize()); | |||
auto mask = BitMask(getSize(), maskForCount(getNumCases())); |
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.
Bug fix: Non-payload enums do in fact export spare bits from the tag value.
@@ -648,7 +651,17 @@ class SinglePayloadEnumTypeInfo: public EnumTypeInfo { | |||
} | |||
|
|||
BitMask getSpareBits(TypeConverter &TC, bool &hasAddrOnly) const override { | |||
return BitMask::zeroMask(getSize()); | |||
FieldInfo PayloadCase = getCases()[0]; |
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.
Single payload enums also export spare bits from the tag. This is a bit more complex than the non-payload case above just because of the manipulations needed to ensure we have a tag and to ensure we don't inadvertently try to export spare bits from the payload.
@@ -2103,44 +2120,11 @@ class EnumTypeInfoBuilder { | |||
} | |||
} | |||
|
|||
// See if we have MPE bit mask information from the compiler... |
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.
Previously, I tried having the compiler export a "multi-payload enum descriptor" with a complete copy of the spare bit mask. I was never happy with this approach because it potentially adds a lot of bulk to the reflection metadata. Fortunately, the new code has shown we shouldn't need such information from the compiler and this PR rips all of that logic out of RemoteMirror. I'll file a separate PR to remove the never-completely-implemented compiler support for generating this data.
@@ -0,0 +1,74 @@ | |||
// RUN: %empty-directory(%t) |
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.
New test case builds a separate resilient library and verifies that we can project values from enums defined in that library.
@@ -74,7 +74,16 @@ class BitMask { | |||
|
|||
BitMask(unsigned sizeInBytes, uint64_t sourceMask): size(sizeInBytes) { | |||
mask = (uint8_t *)calloc(1, sizeInBytes); | |||
memcpy(mask, &sourceMask, sizeInBytes); | |||
if (!mask) { |
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.
Should we also have a limit on sizeInBytes
so we don't read garbage and then successfully, but unhappily, allocate 500TB of memory?
These bit masks can never be larger than the Size of the type in question, so I think the right place for such a check would be in the top-level layout code. Maybe reject any attempt to lay out a type whose Size is larger than 1TB? |
And since |
Thanks! I appreciate the extra comments. |
I'd suggest a limit more like 1MB, but if we already have a an implicit 4GB limit then that doesn't have to be done right here and now. |
If an Int type makes no sense (it has a nonsensical number of extra inhabitants, for example), ignore it rather than treating it as a non-Int type. Rename `isIntType()` to `intTypeBitSize()` to better document what this function actually returns.
…nums RemoteMirror gets called on lots of malformed type information, due to memory corruption bugs or even clients that ask RemoteMirror to decode a chunk of memory to test whether or not it might be valid type data. In any case, we need to be a little cautious here. In this case, I've chosen to ignore any enum whose in-memory size (according to the metadata) is over 1 MiB. We can easily adjust this limit up if experience shows there really are legitimate enums this large in the wild.
@swift-ci Please test Linux Platform |
I added a 1MiB limit and fixed a mis-handling of broken integer type information. The Linux test failed for some reason I don't understand. I may have to spin up a Linux VM here and see if I can duplicate it. |
@swift-ci Please test |
I noted that a lot of resilience tests are limited to only run on macOS. I may take a poke at this particular one later, but for now I've limited it to macOS only. |
…fixes Expand the work from swiftlang#73491 to support more MPE layouts. This is also switches the MPE layout code to exclusively use the new approach. The key observation: existing reflection metadata seems to already provide enough information in all cases, so we can abandon an earlier effort to add spare bitmask data. There is some risk that the old code may have handled some enums that aren't (yet) fully supported by the new code. However, I did a bunch of experiments and found that our existing test cases have decent coverage of the major capabilities and I've also added a new test case specifically to exercise enum layouts being accessed resiliently. So if there are regressions from this change, they should be minor and easily fixed. Resolves rdar://129281368
…fixes Expand the work from swiftlang#73491 to support more MPE layouts. This is also switches the MPE layout code to exclusively use the new approach. The key observation: existing reflection metadata seems to already provide enough information in all cases, so we can abandon an earlier effort to add spare bitmask data. There is some risk that the old code may have handled some enums that aren't (yet) fully supported by the new code. However, I did a bunch of experiments and found that our existing test cases have decent coverage of the major capabilities and I've also added a new test case specifically to exercise enum layouts being accessed resiliently. So if there are regressions from this change, they should be minor and easily fixed. Resolves rdar://129281368
This is also switches the MPE layout code to exclusively use the new approach. The key observation: existing reflection metadata seems to already provide enough information in all cases, so we can abandon an earlier effort to add spare bitmask data.
There is some risk that the old code may have handled some enums that aren't (yet) fully supported by the new code. However, I did a bunch of experiments and found that our existing test cases have decent coverage of the major capabilities and I've also added a new test case specifically to exercise enum layouts being accessed resiliently. So if there are regressions from this change, they should be minor and easily fixed.
Resolves rdar://129281368