mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Rather than swizzle the superclass of these bridging classes at +load time, have the compiler set their ObjC runtime base classes, using a "@_swift_native_objc_runtime_base" attribute that tells the compiler to use a different implicit base class from SwiftObject. This lets the runtime shed its last lingering +loads, and should overall be more robust, since it doesn't rely on static initialization order or deprecated ObjC runtime calls. Swift SVN r28219
176 lines
5.8 KiB
Plaintext
176 lines
5.8 KiB
Plaintext
//===--- SwiftNativeNSXXXBase.mm.gyb - Cocoa classes with fast refcounts --===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Classes derived from ObjC bases but that use native swift reference
|
|
// counting, layout, and allocation.
|
|
//
|
|
// These classes declare a native Swift object header and override the
|
|
// NSObject methods that do reference counting to use it accordingly.
|
|
// We can only do this trick with objc classes that are known not to
|
|
// use the storage where Swift places its native object header. This
|
|
// takes care of how the classes are handled from Objective-C code.
|
|
// _NSSwiftArrayBase, _NSSwiftDictionaryBase, _NSSwiftSetBase
|
|
// _NSSwiftSetBase, _NSSwiftStringBase
|
|
//
|
|
// To trick Swift into using its fast refcounting and allocation
|
|
// directly (rather than going through objc_msgSend to arrive at the
|
|
// implementations defined here), we define subclasses on the Swift
|
|
// side but hide the inheritance relationship from the Swift compiler
|
|
// and only establish it dynamically, in the '+ load' method of each
|
|
// class defined here.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import <CoreFoundation/CoreFoundation.h>
|
|
#include <objc/NSObject.h>
|
|
#include <objc/runtime.h>
|
|
#if __has_include(<objc/objc-internal.h>)
|
|
#include <objc/objc-internal.h>
|
|
#endif
|
|
#include "swift/Runtime/HeapObject.h"
|
|
#include "swift/Runtime/Metadata.h"
|
|
#include "swift/Runtime/ObjCBridge.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "Private.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <mutex>
|
|
|
|
// Redeclare these just we check them.
|
|
extern "C" id _objc_rootAutorelease(id);
|
|
|
|
using namespace swift;
|
|
|
|
% for Class in ('Array', 'Dictionary', 'Set', 'String', 'Enumerator'):
|
|
@interface _SwiftNativeNS${Class}Base : NS${Class}
|
|
{
|
|
// TODO: Workaround for rdar://problem/18950072
|
|
// SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
|
|
uint32_t __magic_refCount;
|
|
uint32_t __magic_weakRefCount;
|
|
}
|
|
@end
|
|
|
|
@implementation _SwiftNativeNS${Class}Base
|
|
|
|
- (id)retain {
|
|
auto SELF = reinterpret_cast<HeapObject *>(self);
|
|
swift_retain(SELF);
|
|
return self;
|
|
}
|
|
- (oneway void)release {
|
|
auto SELF = reinterpret_cast<HeapObject *>(self);
|
|
swift_release(SELF);
|
|
}
|
|
- (id)autorelease {
|
|
return _objc_rootAutorelease(self);
|
|
}
|
|
|
|
- (BOOL)_tryRetain {
|
|
auto SELF = reinterpret_cast<HeapObject *>(self);
|
|
return (bool)swift_tryRetain(SELF);
|
|
}
|
|
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
|
|
- (void)dealloc {
|
|
_swift_deallocClassInstance(reinterpret_cast<HeapObject *>(self));
|
|
}
|
|
#pragma clang diagnostic pop
|
|
|
|
@end
|
|
% end
|
|
|
|
extern "C" bool
|
|
swift_stdlib_NSObject_isEqual(NSObject *NS_RELEASES_ARGUMENT lhs,
|
|
NSObject *NS_RELEASES_ARGUMENT rhs) {
|
|
bool Result = (lhs == rhs) || [lhs isEqual:rhs];
|
|
swift_unknownRelease(lhs);
|
|
swift_unknownRelease(rhs);
|
|
return Result;
|
|
}
|
|
|
|
extern "C" int32_t swift_stdlib_compareNSStringDeterministicUnicodeCollation(
|
|
NSString *NS_RELEASES_ARGUMENT lhs, NSString *NS_RELEASES_ARGUMENT rhs) {
|
|
// 'kCFCompareNonliteral' actually means "normalize to NFD".
|
|
int Result = CFStringCompare((__bridge CFStringRef)lhs,
|
|
(__bridge CFStringRef)rhs, kCFCompareNonliteral);
|
|
swift_unknownRelease(lhs);
|
|
swift_unknownRelease(rhs);
|
|
return Result;
|
|
}
|
|
|
|
extern "C" size_t
|
|
swift_stdlib_NSStringNFDHashValue(NSString *NS_RELEASES_ARGUMENT str) {
|
|
int Result = str.decomposedStringWithCanonicalMapping.hash;
|
|
swift_unknownRelease(str);
|
|
return Result;
|
|
}
|
|
|
|
// For strings we know only have ASCII
|
|
extern "C" size_t
|
|
swift_stdlib_NSStringASCIIHashValue(NSString *NS_RELEASES_ARGUMENT str) {
|
|
int Result = str.hash;
|
|
swift_unknownRelease(str);
|
|
return Result;
|
|
}
|
|
|
|
extern "C" bool swift_stdlib_NSStringHasPrefixNFD(NSString *theString,
|
|
NSString *prefix) {
|
|
auto Length = CFStringGetLength((__bridge CFStringRef)theString);
|
|
int Result = CFStringFindWithOptions(
|
|
(__bridge CFStringRef)theString, (__bridge CFStringRef)prefix,
|
|
CFRangeMake(0, Length), kCFCompareAnchored | kCFCompareNonliteral,
|
|
nullptr);
|
|
swift_unknownRelease(theString);
|
|
swift_unknownRelease(prefix);
|
|
return Result;
|
|
}
|
|
|
|
extern "C" bool
|
|
swift_stdlib_NSStringHasSuffixNFD(NSString *NS_RELEASES_ARGUMENT theString,
|
|
NSString *NS_RELEASES_ARGUMENT suffix) {
|
|
auto Length = CFStringGetLength((__bridge CFStringRef)theString);
|
|
int Result = CFStringFindWithOptions(
|
|
(__bridge CFStringRef)theString, (__bridge CFStringRef)suffix,
|
|
CFRangeMake(0, Length),
|
|
kCFCompareAnchored | kCFCompareBackwards | kCFCompareNonliteral, nullptr);
|
|
swift_unknownRelease(theString);
|
|
swift_unknownRelease(suffix);
|
|
return Result;
|
|
}
|
|
|
|
extern "C" NS_RETURNS_RETAINED NSString *
|
|
swift_stdlib_NSStringLowercaseString(NSString *NS_RELEASES_ARGUMENT str) {
|
|
NSString *Result = objc_retain(str.lowercaseString);
|
|
swift_unknownRelease(str);
|
|
return Result;
|
|
}
|
|
|
|
extern "C" NS_RETURNS_RETAINED NSString *
|
|
swift_stdlib_NSStringUppercaseString(NSString *NS_RELEASES_ARGUMENT str) {
|
|
NSString *Result = objc_retain(str.uppercaseString);
|
|
swift_unknownRelease(str);
|
|
return Result;
|
|
}
|
|
|
|
extern "C" void swift_stdlib_CFSetGetValues(NSSet *NS_RELEASES_ARGUMENT set,
|
|
const void **values) {
|
|
CFSetGetValues((__bridge CFSetRef)set, values);
|
|
swift_unknownRelease(set);
|
|
}
|
|
|
|
// ${'Local Variables'}:
|
|
// eval: (read-only-mode 1)
|
|
// End:
|