-
Notifications
You must be signed in to change notification settings - Fork 10.5k
runtime: Move String implementation stubs that want need the auto-rel… #12312
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
Changes from 4 commits
ec5f40f
513303f
16552c0
75a82d7
a4aad80
362f910
e015d71
f691657
f9c0049
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
//===--- SwiftNativeNSXXXBaseARC.mm - Runtime stubs that require ARC ------===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
#include "swift/Runtime/Config.h" | ||
|
||
#if SWIFT_OBJC_INTEROP | ||
|
||
#import <Foundation/Foundation.h> | ||
#import <CoreFoundation/CoreFoundation.h> | ||
#include <objc/NSObject.h> | ||
#include <objc/runtime.h> | ||
#include <objc/objc.h> | ||
|
||
/// The following two routines need to be implemented in ARC because | ||
/// decomposedStringWithCanonicalMapping returns its result autoreleased. And we | ||
/// want ARC to insert 'objc_retainAutoreleasedReturnValue' and the necessary | ||
/// markers for the hand-off. | ||
|
||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE | ||
size_t swift_stdlib_NSStringHashValue(NSString *NS_RELEASES_ARGUMENT str, | ||
bool isASCII) { | ||
return isASCII ? str.hash : str.decomposedStringWithCanonicalMapping.hash; | ||
} | ||
|
||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE | ||
size_t | ||
swift_stdlib_NSStringHashValuePointer(void *opaque, bool isASCII) { | ||
NSString __unsafe_unretained *str = | ||
(__bridge NSString __unsafe_unretained *)opaque; | ||
return isASCII ? str.hash : str.decomposedStringWithCanonicalMapping.hash; | ||
} | ||
|
||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE | ||
NS_RETURNS_RETAINED NSString * | ||
swift_stdlib_NSStringLowercaseString(NSString *NS_RELEASES_ARGUMENT str) { | ||
return str.lowercaseString; | ||
} | ||
|
||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE | ||
NS_RETURNS_RETAINED NSString * | ||
swift_stdlib_NSStringUppercaseString(NSString *NS_RELEASES_ARGUMENT str) { | ||
return str.uppercaseString; | ||
} | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// RUN: %empty-directory(%t) | ||
// RUN: %target-build-swift -O %s -o %t/StringMemoryTest | ||
// RUN: %target-run %t/StringMemoryTest | %FileCheck %s | ||
|
||
// REQUIRES: optimized_stdlib | ||
// REQUIRES: executable_test | ||
// REQUIRES: objc_interop | ||
|
||
// The autorelease return optimizaion seems to be failing in the simulator. | ||
// XFAIL: CPU=i386 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we just don't do it there. @rjmccall? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, seems to be the case. I tried with a pure objective-c app and we also leak there on an i386 simulator rdar://34863458 |
||
|
||
import Foundation | ||
|
||
let str = "abcdefg\u{A758}hijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\u{A759}" | ||
let str2 = "abcdefg\u{A759}hijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\u{A758}" | ||
|
||
@inline(never) | ||
func lookup(_ str: String, _ dict: [String: Int]) -> Bool { | ||
if let _ = dict[str] { | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
@inline(never) | ||
func uppercase(_ str: String) -> String { | ||
return str.uppercased() | ||
} | ||
|
||
@inline(never) | ||
func lowercase(_ str: String) -> String { | ||
return str.lowercased() | ||
} | ||
|
||
/// Make sure the hash function does not leak. | ||
|
||
let dict = [ "foo" : 1] | ||
for _ in 0 ..< 10_000_000 { | ||
if lookup("\u{1F1E7}\u{1F1E7}", dict) { | ||
print("Found?!") | ||
} | ||
if uppercase(str) == "A" { | ||
print("Found?!") | ||
} | ||
if lowercase(str2) == "A" { | ||
print("Found?!") | ||
} | ||
} | ||
|
||
// CHECK-NOT: Found?! | ||
// CHECK: Not found | ||
|
||
print("Not found") | ||
|
||
var usage = rusage() | ||
getrusage(RUSAGE_SELF, &usage) | ||
|
||
// CHECK: success | ||
// CHECK-NOT: failure | ||
|
||
// We should not need 50MB for this. | ||
if usage.ru_maxrss > 50 * 1024 * 1024 { | ||
print("failure - should not need 50MB!") | ||
} else { | ||
print("success") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// UNSUPPORTED: linux | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to make this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point |
||
// RUN: otool -tvV %platform-module-dir/libswiftCore.dylib | %FileCheck %s --check-prefix=CHECK-%target-cpu | ||
|
||
// Verify the autorelease return optimization sequence. | ||
|
||
/// Test x86-64: | ||
|
||
// CHECK-x86_64-LABEL: _swift_stdlib_NSStringHashValue: | ||
// CHECK-x86_64-NOT: ret | ||
// CHECK-x86_64: movq {{.*}}(%rip), %rsi ## Objc selector ref: decomposedStringWithCanonicalMapping | ||
// CHECK-x86_64: movq {{.*}}(%rip), [[MSG:%.*]] ## Objc message: -[%rdi decomposedStringWithCanonicalMapping] | ||
// CHECK-x86_64: callq *[[MSG]] | ||
// CHECK-x86_64: movq %rax, %rdi | ||
// CHECK-x86_64: callq {{.*}} ## symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-x86_64: ret | ||
|
||
|
||
// CHECK-x86_64-LABEL: _swift_stdlib_NSStringHashValuePointer: | ||
// CHECK-x86_64-NOT: ret | ||
// CHECK-x86_64: movq {{.*}}(%rip), %rsi ## Objc selector ref: decomposedStringWithCanonicalMapping | ||
// CHECK-x86_64: movq {{.*}}(%rip), [[MSG:%.*]] ## Objc message: -[%rdi decomposedStringWithCanonicalMapping] | ||
// CHECK-x86_64: callq *[[MSG]] | ||
// CHECK-x86_64: movq %rax, %rdi | ||
// CHECK-x86_64: callq {{.*}} ## symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-x86_64: ret | ||
|
||
/// Test i386: | ||
|
||
// CHECK-i386-LABEL: _swift_stdlib_NSStringHashValue: | ||
// CHECK-i386-NOT: ret | ||
// CHECK-i386: calll {{.*}} ## symbol stub for: _objc_msgSend | ||
// CHECK-i386: movl %ebp, %ebp | ||
// CHECK-i386: calll {{.*}} ## symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-i386: ret | ||
// CHECK-i386-LABEL: _swift_stdlib_NSStringHashValuePointer: | ||
// CHECK-i386-NOT: ret | ||
// CHECK-i386: calll {{.*}} ## symbol stub for: _objc_msgSend | ||
// CHECK-i386: movl %ebp, %ebp | ||
// CHECK-i386: calll {{.*}} ## symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-i386: ret | ||
|
||
/// Test armv7: | ||
|
||
// CHECK-armv7-LABEL: _swift_stdlib_NSStringHashValue: | ||
// CHECK-armv7-NOT: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7: blx {{.*}} @ symbol stub for: _objc_msgSend | ||
// CHECK-armv7: mov r7, r7 | ||
// CHECK-armv7: blx {{.*}} @ symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-armv7: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7-LABEL: _swift_stdlib_NSStringHashValuePointer: | ||
// CHECK-armv7-NOT: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7: blx {{.*}} @ symbol stub for: _objc_msgSend | ||
// CHECK-armv7: mov r7, r7 | ||
// CHECK-armv7: blx {{.*}} @ symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-armv7: pop {{.*}}pc{{.*}} | ||
|
||
/// Test armv7s: | ||
|
||
// CHECK-armv7s-LABEL: _swift_stdlib_NSStringHashValue: | ||
// CHECK-armv7s-NOT: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7s: blx {{.*}} @ symbol stub for: _objc_msgSend | ||
// CHECK-armv7s: mov r7, r7 | ||
// CHECK-armv7s: blx {{.*}} @ symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-armv7s: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7s-LABEL: _swift_stdlib_NSStringHashValuePointer: | ||
// CHECK-armv7s-NOT: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7s: blx {{.*}} @ symbol stub for: _objc_msgSend | ||
// CHECK-armv7s: mov r7, r7 | ||
// CHECK-armv7s: blx {{.*}} @ symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-armv7s: pop {{.*}}pc{{.*}} | ||
|
||
|
||
/// Test armv7k: | ||
|
||
// CHECK-armv7k-LABEL: _swift_stdlib_NSStringHashValue: | ||
// CHECK-armv7k-NOT: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7k: blx {{.*}} @ symbol stub for: _objc_msgSend | ||
// CHECK-armv7k: mov r7, r7 | ||
// CHECK-armv7k: blx {{.*}} @ symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-armv7k: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7k-LABEL: _swift_stdlib_NSStringHashValuePointer: | ||
// CHECK-armv7k-NOT: pop {{.*}}pc{{.*}} | ||
// CHECK-armv7k: blx {{.*}} @ symbol stub for: _objc_msgSend | ||
// CHECK-armv7k: mov r7, r7 | ||
// CHECK-armv7k: blx {{.*}} @ symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-armv7k: pop {{.*}}pc{{.*}} | ||
|
||
/// Test arm64: | ||
|
||
// CHECK-arm64-LABEL: _swift_stdlib_NSStringHashValue: | ||
// CHECK-arm64-NOT: ret | ||
// CHECK-arm64: bl {{.*}} ; Objc message: -[x0 decomposedStringWithCanonicalMapping] | ||
// CHECK-arm64: mov x29, x29 | ||
// CHECK-arm64: bl {{.*}} ; symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-arm64: ret | ||
// CHECK-arm64-LABEL: _swift_stdlib_NSStringHashValuePointer: | ||
// CHECK-arm64-NOT: ret | ||
// CHECK-arm64: bl {{.*}} ; Objc message: -[x0 decomposedStringWithCanonicalMapping] | ||
// CHECK-arm64: mov x29, x29 | ||
// CHECK-arm64: bl {{.*}} ; symbol stub for: _objc_retainAutoreleasedReturnValue | ||
// CHECK-arm64: ret |
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.
Nitpick: this shouldn't be a doc comment.