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

[Dynamic Casting] Overhauled Runtime #33561

Merged
merged 15 commits into from
Aug 27, 2020

Conversation

tbkka
Copy link
Contributor

@tbkka tbkka commented Aug 20, 2020

This is a completely refactored version of the core swift_dynamicCast
runtime method. (Separated out from PR #29658 )

This fixes a number of bugs, especially in the handling of multiply-wrapped
types such as Optional within Any. The result should be much closer to the
behavior specified by docs/DynamicCasting.md.

Most of the type-specific logic is simply copied over from the
earlier implementation, but the overall structure has been changed
to be uniformly recursive. In particular, this provides consistent
handling of Optional, existentials, Any and other common "box"
types along all paths. The consistent structure should also be
easier to update in the future with new general types.

Benchmarking does not show any noticable performance implications.

Temporarily, the old implementation is still available. Setting the
environment variable SWIFT_OLD_DYNAMIC_CAST_RUNTIME before launching a program
will use the old runtime implementation. This is only to facilitate testing;
once the new implementation is stable, I expect to completely remove the old
implementation.

Partially Resolves: SR-1999 SR-2289 SR-4552 SR-6126 SR-8964

This is a completely refactored version of the core swift_dynamicCast
runtime method.

This fixes a number of bugs, especially in the handling of multiply-wrapped
types such as Optional within Any.  The result should be much closer to the
behavior specified by `docs/DynamicCasting.md`.

Most of the type-specific logic is simply copied over from the
earlier implementation, but the overall structure has been changed
to be uniformly recursive.  In particular, this provides uniform
handling of Optional, existentials, Any and other common "box"
types along all paths.  The consistent structure should also be
easier to update in the future with new general types.

Benchmarking does not show any noticable performance implications.

**Temporarily**, the old implementation is still available.  Setting the
environment variable `SWIFT_OLD_DYNAMIC_CAST_RUNTIME` before launching a program
will use the old runtime implementation.  This is only to facilitate testing;
once the new implementation is stable, I expect to completely remove the old
implementation.
The old `tryCastFromNil` could never fail (hence doesn't need to "try") and
doesn't need all the arguments we were giving it.
We know this memoization makes a big difference for String,
but the wins for Dictionary are less clear.  It's easy to
add it back later if it proves helpful.
Copy link
Contributor

@mikeash mikeash left a comment

Choose a reason for hiding this comment

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

I got partway through reviewing this today and thought I'd send the comments I have so far. More to come, presumably.

stdlib/public/runtime/DynamicCast.cpp Show resolved Hide resolved
stdlib/public/runtime/DynamicCast.cpp Outdated Show resolved Hide resolved
stdlib/public/runtime/DynamicCast.cpp Outdated Show resolved Hide resolved
stdlib/public/runtime/DynamicCast.cpp Show resolved Hide resolved
stdlib/public/runtime/DynamicCast.cpp Show resolved Hide resolved
stdlib/public/runtime/DynamicCast.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@mikeash mikeash left a comment

Choose a reason for hiding this comment

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

Read through the rest of it. Didn't see a whole lot!

Overall, this looks fantastic. It's very clear, both in details and in the overall structure. I definitely feel like I'd be able to take a bug report and go straight to the relevant code, rather than stepping through line by line waiting to see where something went wrong like I often did with the old code. Thanks very much for taking this on and seeing it through.

stdlib/public/runtime/DynamicCast.cpp Show resolved Hide resolved
stdlib/public/runtime/DynamicCast.cpp Show resolved Hide resolved
Clarify the unreachable messaging a bit:
* "Unexpected" means I knew about it but thought it could
  never appear here
* "Unknown" means I didn't know about it when I wrote this code
@tbkka
Copy link
Contributor Author

tbkka commented Aug 26, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - df82a0f

@tbkka
Copy link
Contributor Author

tbkka commented Aug 26, 2020

Looks like I failed to properly mark some code that depends on Obj-C interop.

@tbkka
Copy link
Contributor Author

tbkka commented Aug 26, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 2acaa1a

@tbkka
Copy link
Contributor Author

tbkka commented Aug 26, 2020

Linux had an unexpected "PASS" of some of the casting tests because of a mis-match between build optimizations.

The test in question should not be marked as XFAIL for optimized mode, because it ignores the test mode and always builds without optimizations. (It always builds without optimizations because the point of the test is to exercise runtime functions that are not called when the compiler can optimize the cast in question.)

I've removed the XFAIL marker.

@tbkka
Copy link
Contributor Author

tbkka commented Aug 26, 2020

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 2acaa1a

@tbkka
Copy link
Contributor Author

tbkka commented Aug 26, 2020

Invalid SHA

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 2acaa1a

@tbkka
Copy link
Contributor Author

tbkka commented Aug 26, 2020

Also invalid SHA

@tbkka
Copy link
Contributor Author

tbkka commented Aug 26, 2020

@swift-ci Please test Windows platform

@tbkka
Copy link
Contributor Author

tbkka commented Aug 27, 2020

@swift-ci Please test

@tbkka
Copy link
Contributor Author

tbkka commented Aug 27, 2020

@swift-ci Please benchmark

@tbkka
Copy link
Contributor Author

tbkka commented Aug 27, 2020

@swift-ci Please test Windows platform

@swift-ci
Copy link
Contributor

Performance: -O

Regression OLD NEW DELTA RATIO
ProtocolConformance 34 44 +29.4% 0.77x (?)
ObjectiveCBridgeFromNSDictionaryAnyObjectForced 4550 5500 +20.9% 0.83x (?)
ObjectiveCBridgeFromNSDictionaryAnyObject 26300 29900 +13.7% 0.88x (?)
EqualStringSubstring 22 25 +13.6% 0.88x (?)
ObjectiveCBridgeFromNSSetAnyObjectForced 3100 3520 +13.5% 0.88x (?)
 
Improvement OLD NEW DELTA RATIO
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced 26200 23600 -9.9% 1.11x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToString 25000 22800 -8.8% 1.10x (?)
Set.isSubset.Int.Empty 53 49 -7.5% 1.08x (?)
DictionaryOfAnyHashableStrings_lookup 3696 3432 -7.1% 1.08x (?)
ObjectiveCBridgeStubFromArrayOfNSString2 2010 1870 -7.0% 1.07x (?)

Code size: -O

Performance: -Osize

Regression OLD NEW DELTA RATIO
ProtocolConformance 36 45 +25.0% 0.80x (?)
ObjectiveCBridgeFromNSDictionaryAnyObjectForced 4550 5450 +19.8% 0.83x (?)
ObjectiveCBridgeFromNSSetAnyObjectForced 3100 3520 +13.5% 0.88x (?)
ObjectiveCBridgeFromNSArrayAnyObject 14700 16100 +9.5% 0.91x (?)
EqualSubstringString 22 24 +9.1% 0.92x (?)
ObjectiveCBridgeFromNSDictionaryAnyObject 26100 28400 +8.8% 0.92x (?)
ObjectiveCBridgeFromNSArrayAnyObjectForced 4040 4380 +8.4% 0.92x (?)
 
Improvement OLD NEW DELTA RATIO
FlattenListLoop 1527 929 -39.2% 1.64x (?)
ArrayPlusEqualSingleElementCollection 470 423 -10.0% 1.11x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToString 25000 22700 -9.2% 1.10x (?)
ArrayLiteral2 115 105 -8.7% 1.10x (?)
DictionaryOfAnyHashableStrings_lookup 3720 3432 -7.7% 1.08x (?)
DictionaryBridge 452 418 -7.5% 1.08x (?)
Set.isSubset.Seq.Int.Empty 133 123 -7.5% 1.08x (?)

Code size: -Osize

Performance: -Onone

Regression OLD NEW DELTA RATIO
ObjectiveCBridgeFromNSSetAnyObjectForced 3380 3880 +14.8% 0.87x (?)
ObjectiveCBridgeFromNSDictionaryAnyObject 27000 30800 +14.1% 0.88x (?)
ObjectiveCBridgeFromNSArrayAnyObjectForced 5580 6360 +14.0% 0.88x (?)
ObjectiveCBridgeFromNSDictionaryAnyObjectForced 6600 7500 +13.6% 0.88x (?)
ProtocolConformance 135 149 +10.4% 0.91x (?)
ObjectiveCBridgeFromNSArrayAnyObject 15800 17400 +10.1% 0.91x (?)
ObjectiveCBridgeStubFromNSString 554 599 +8.1% 0.92x (?)
 
Improvement OLD NEW DELTA RATIO
ArrayAppendUTF16Substring 48240 43812 -9.2% 1.10x (?)
DictionaryOfAnyHashableStrings_lookup 4032 3768 -6.5% 1.07x (?)

Code size: -swiftlibs

How to read the data The tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.

If you see any unexpected regressions, you should consider fixing the
regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false
alarms. Unexpected regressions which are marked with '(?)' are probably noise.
If you see regressions which you cannot explain you can try to run the
benchmarks again. If regressions still show up, please consult with the
performance team (@eeckstein).

Hardware Overview
  Model Name: Mac mini
  Model Identifier: Macmini8,1
  Processor Name: 6-Core Intel Core i7
  Processor Speed: 3.2 GHz
  Number of Processors: 1
  Total Number of Cores: 6
  L2 Cache (per Core): 256 KB
  L3 Cache: 12 MB
  Memory: 64 GB

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 0a413f0

@tbkka
Copy link
Contributor Author

tbkka commented Aug 27, 2020

@swift-ci Please test

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.

3 participants