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

[SR-6823] [StringGuts] Bridging benchmark regressions #49372

Open
milseman mannequin opened this issue Jan 24, 2018 · 7 comments
Open

[SR-6823] [StringGuts] Bridging benchmark regressions #49372

milseman mannequin opened this issue Jan 24, 2018 · 7 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. standard library Area: Standard library umbrella

Comments

@milseman
Copy link
Mannequin

milseman mannequin commented Jan 24, 2018

Previous ID SR-6823
Radar rdar://problem/36825359
Original Reporter @milseman
Type Bug

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Standard Library
Labels Bug
Assignee shajrawi (JIRA)
Priority Medium

md5: 9dfd601b63da74d8eacc0fdb401a3614

Issue Description:

Regression from #14046

When bridging in from Cocoa, we check to see if we were originally a Swift type. However, we’re drowning in dynamic type checks. We need a faster way of doing this. I was able to hack around about half this regression from ARC. There’s also still more ARC than strictly needed.

ObjectiveCBridgeStubFromNSString

I’m going to assume all of the following are the same issue, but I haven’t inspected each profile deeply yet. There’s a chance that fixing this won’t fix all of those, and if that’s the case we’ll spin off a separate JIRA.

ObjectiveCBridgeFromNSString
ObjectiveCBridgeFromNSArrayAnyObjectForced
ObjectiveCBridgeFromNSArrayAnyObjectToString
ObjectiveCBridgeFromNSStringForced
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced
ObjectiveCBridgeFromNSSetAnyObjectToString
ObjectiveCBridgeToNSSet
ObjectiveCBridgeToNSDictionary
ObjectiveCBridgeStubFromNSStringRef

@milseman
Copy link
Mannequin Author

milseman mannequin commented Jan 24, 2018

Erik, do you think someone can help me find an alternative? We probably don't need all of the machinery of dynamic casts etc. This could just be a load of the meta type and pointer compare, but I couldn't get any alternatives to stick when I tried a month ago.

@milseman
Copy link
Mannequin Author

milseman mannequin commented Jan 24, 2018

(probably just silly ignorance of the right method on my part).

Here's the relevant code:

@_versioned
@inline(never) // Hide the CF dependency
internal
func _makeCocoaStringGuts(_ cocoaString: _CocoaString) -> _StringGuts {
  if let ascii = cocoaString as? _ASCIIStringStorage {
    return _StringGuts(ascii)
  } else if let utf16 = cocoaString as? _UTF16StringStorage {
    return _StringGuts(utf16)
  } else if let wrapped = cocoaString as? _NSContiguousString {
    return wrapped._guts
  } else if _isObjCTaggedPointer(cocoaString) {
    return _StringGuts(_taggedCocoaObject: cocoaString)
  }

_ASCIIStringStorage / _UTF16StringStorage are type aliases of a generic type:

internal typealias _ASCIIStringStorage = _SwiftStringStorage<UInt8>
internal typealias _UTF16StringStorage = _SwiftStringStorage<UTF16.CodeUnit>

Inside the disassembly, I see calls to getGenericMetadata and dynamicCastClass. Are we not statically producing meta types for those two? Can I force us to, or should I de-generic it? It's only generic for 1-byte vs 2-byte storage, and we could always duplicate code if we must.

@milseman
Copy link
Mannequin Author

milseman mannequin commented Jan 24, 2018

CC @belkadan @gottesmm in case it's a resilience thing, and if there's a way around this

@milseman
Copy link
Mannequin Author

milseman mannequin commented Jan 24, 2018

@swift-ci create

@belkadan
Copy link
Contributor

I don't think that's a resilience thing, though I'm not 100% sure. I don't think generic types get statically instantiated, ever.

You could avoid dynamicCastClass by using type(of: cocoaString) == _ASCIIStringStorage, which defines away subclasses. (And then do unsafeDowncast to avoid checking again once you've done that.)

@milseman
Copy link
Mannequin Author

milseman mannequin commented Jan 25, 2018

I'm trying that in #14148 it helps a tiny bit.

Joe S., I looked into this further and there's definitely an extra retain/release pair inside makeCocoaStringGuts that's contributing here. I attached the disassembled CFG. There you can see CFCocoaStringCreateCopy creates a +1 reference and stores it in r14 (this is "immutableCopy" in the source). We bundle it up in a bridgeObject, which retains it again. Then, we release r14.

Also notice that there's a constant folding opportunity here: loc_31878a's basic block calls retain on a known-value. Eliminating this makes the analysis simpler: the _swift_unknownRelease should be moved into loc_31878a, and the bridgeObject retain in loc_318775 is eliminated.

@milseman
Copy link
Mannequin Author

milseman mannequin commented Jan 25, 2018

That was harder to explain in prose than I thought. Attached a version with red lines through what should be eliminated and a green arrow for the move.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. standard library Area: Standard library umbrella
Projects
None yet
Development

No branches or pull requests

1 participant