blob: 8fbcb99d37f2906930d17fe993037ca9b47d7988 [file] [log] [blame]
//===--- HeapObject.h - Swift Language Allocation ABI -----------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Swift Allocation ABI
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_RUNTIME_ALLOC_H
#define SWIFT_RUNTIME_ALLOC_H
#include <cstddef>
#include <cstdint>
#include "swift/Runtime/Config.h"
#if SWIFT_OBJC_INTEROP
#include <objc/objc.h>
#endif // SWIFT_OBJC_INTEROP
// Bring in the definition of HeapObject
#include "../../../stdlib/public/SwiftShims/HeapObject.h"
namespace swift {
struct InProcess;
template <typename Runtime> struct TargetMetadata;
using Metadata = TargetMetadata<InProcess>;
template <typename Runtime> struct TargetHeapMetadata;
using HeapMetadata = TargetHeapMetadata<InProcess>;
struct OpaqueValue;
/// Allocates a new heap object. The returned memory is
/// uninitialized outside of the heap-object header. The object
/// has an initial retain count of 1, and its metadata is set to
/// the given value.
///
/// At some point "soon after return", it will become an
/// invariant that metadata->getSize(returnValue) will equal
/// requiredSize.
///
/// Either aborts or throws a swift exception if the allocation fails.
///
/// \param requiredSize - the required size of the allocation,
/// including the header
/// \param requiredAlignmentMask - the required alignment of the allocation;
/// always one less than a power of 2 that's at least alignof(void*)
/// \return never null
///
/// POSSIBILITIES: The argument order is fair game. It may be useful
/// to have a variant which guarantees zero-initialized memory.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_allocObject(HeapMetadata const *metadata,
size_t requiredSize,
size_t requiredAlignmentMask);
/// Initializes the object header of a stack allocated object.
///
/// \param metadata - the object's metadata which is stored in the header
/// \param object - the pointer to the object's memory on the stack
/// \returns the passed object pointer.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_initStackObject(HeapMetadata const *metadata,
HeapObject *object);
/// Initializes the object header of a static object which is statically
/// allocated in the data section.
///
/// \param metadata - the object's metadata which is stored in the header
/// \param object - the address of the object in the data section. It is assumed
/// that at offset -1 there is a swift_once token allocated.
/// \returns the passed object pointer.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_initStaticObject(HeapMetadata const *metadata,
HeapObject *object);
/// Performs verification that the lifetime of a stack allocated object has
/// ended. It aborts if the reference counts of the object indicate that the
/// object did escape to some other location.
SWIFT_RUNTIME_EXPORT
void swift_verifyEndOfLifetime(HeapObject *object);
struct BoxPair {
HeapObject *object;
OpaqueValue *buffer;
};
/// Allocates a heap object that can contain a value of the given type.
/// Returns a Box structure containing a HeapObject* pointer to the
/// allocated object, and a pointer to the value inside the heap object.
/// The value pointer points to an uninitialized buffer of size and alignment
/// appropriate to store a value of the given type.
/// The heap object has an initial retain count of 1, and its metadata is set
/// such that destroying the heap object destroys the contained value.
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
BoxPair swift_allocBox(Metadata const *type);
/// Performs a uniqueness check on the pointer to a box structure. If the check
/// fails allocates a new box and stores the pointer in the buffer.
///
/// if (!isUnique(buffer[0]))
/// buffer[0] = swift_allocBox(type)
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
size_t alignMask);
/// Returns the address of a heap object representing all empty box types.
SWIFT_RUNTIME_EXPORT
HeapObject* swift_allocEmptyBox();
// Allocate plain old memory. This is the generalized entry point
// Never returns nil. The returned memory is uninitialized.
//
// An "alignment mask" is just the alignment (a power of 2) minus 1.
SWIFT_RUNTIME_EXPORT
void *swift_slowAlloc(size_t bytes, size_t alignMask);
// If the caller cannot promise to zero the object during destruction,
// then call these corresponding APIs:
SWIFT_RUNTIME_EXPORT
void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask);
/// Atomically increments the retain count of an object.
///
/// \param object - may be null, in which case this is a no-op
///
/// \return object - we return the object because this enables tail call
/// optimization and the argument register to be live through the call on
/// architectures whose argument and return register is the same register.
///
/// POSSIBILITIES: We may end up wanting a bunch of different variants:
/// - the general version which correctly handles null values, swift
/// objects, and ObjC objects
/// - a variant that assumes that its operand is a swift object
/// - a variant that can safely use non-atomic operations
/// - maybe a variant that can assume a non-null object
/// It may also prove worthwhile to have this use a custom CC
/// which preserves a larger set of registers.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_retain(HeapObject *object);
SWIFT_RUNTIME_EXPORT
HeapObject *swift_retain_n(HeapObject *object, uint32_t n);
SWIFT_RUNTIME_EXPORT
HeapObject *swift_nonatomic_retain(HeapObject *object);
SWIFT_RUNTIME_EXPORT
HeapObject* swift_nonatomic_retain_n(HeapObject *object, uint32_t n);
/// Atomically increments the reference count of an object, unless it has
/// already been destroyed. Returns nil if the object is dead.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_tryRetain(HeapObject *object);
/// Returns true if an object is in the process of being deallocated.
SWIFT_RUNTIME_EXPORT
bool swift_isDeallocating(HeapObject *object);
/// Atomically decrements the retain count of an object. If the
/// retain count reaches zero, the object is destroyed as follows:
///
/// size_t allocSize = object->metadata->destroy(object);
/// if (allocSize) swift_deallocObject(object, allocSize);
///
/// \param object - may be null, in which case this is a no-op
///
/// POSSIBILITIES: We may end up wanting a bunch of different variants:
/// - the general version which correctly handles null values, swift
/// objects, and ObjC objects
/// - a variant that assumes that its operand is a swift object
/// - a variant that can safely use non-atomic operations
/// - maybe a variant that can assume a non-null object
/// It's unlikely that a custom CC would be beneficial here.
SWIFT_RUNTIME_EXPORT
void swift_release(HeapObject *object);
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_release(HeapObject *object);
/// Atomically decrements the retain count of an object n times. If the retain
/// count reaches zero, the object is destroyed
SWIFT_RUNTIME_EXPORT
void swift_release_n(HeapObject *object, uint32_t n);
/// Sets the RC_DEALLOCATING_FLAG flag. This is done non-atomically.
/// The strong reference count of \p object must be 1 and no other thread may
/// retain the object during executing this function.
SWIFT_RUNTIME_EXPORT
void swift_setDeallocating(HeapObject *object);
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_release_n(HeapObject *object, uint32_t n);
// Refcounting observation hooks for memory tools. Don't use these.
SWIFT_RUNTIME_EXPORT
size_t swift_retainCount(HeapObject *object);
SWIFT_RUNTIME_EXPORT
size_t swift_unownedRetainCount(HeapObject *object);
SWIFT_RUNTIME_EXPORT
size_t swift_weakRetainCount(HeapObject *object);
/// Is this pointer a non-null unique reference to an object
/// that uses Swift reference counting?
SWIFT_RUNTIME_EXPORT
bool swift_isUniquelyReferencedNonObjC(const void *);
/// Is this non-null pointer a unique reference to an object
/// that uses Swift reference counting?
SWIFT_RUNTIME_EXPORT
bool swift_isUniquelyReferencedNonObjC_nonNull(const void *);
/// Is this non-null BridgeObject a unique reference to an object
/// that uses Swift reference counting?
SWIFT_RUNTIME_EXPORT
bool swift_isUniquelyReferencedNonObjC_nonNull_bridgeObject(
uintptr_t bits);
/// Is this native Swift pointer a non-null unique reference to
/// an object?
SWIFT_RUNTIME_EXPORT
bool swift_isUniquelyReferenced_native(const struct HeapObject *);
/// Is this non-null native Swift pointer a unique reference to
/// an object?
SWIFT_RUNTIME_EXPORT
bool swift_isUniquelyReferenced_nonNull_native(const struct HeapObject *);
/// Is this native Swift pointer non-null and has a reference count greater than
/// one.
/// This runtime call will print an error message with file name and location if
/// the closure is escaping but it will not abort.
///
/// \p type: 0 - withoutActuallyEscaping verification
/// Was the closure passed to a withoutActuallyEscaping block
/// escaped in the block?
/// 1 - @objc closure sentinel verfication
/// Was the closure passed to Objective-C escaped?
SWIFT_RUNTIME_EXPORT
bool swift_isEscapingClosureAtFileLocation(const struct HeapObject *object,
const unsigned char *filename,
int32_t filenameLength,
int32_t line,
int32_t column,
unsigned type);
/// Deallocate the given memory.
///
/// It must have been returned by swift_allocObject and the strong reference
/// must have the RC_DEALLOCATING_FLAG flag set, but otherwise the object is
/// in an unknown state.
///
/// \param object - never null
/// \param allocatedSize - the allocated size of the object from the
/// program's perspective, i.e. the value
/// \param allocatedAlignMask - the alignment requirement that was passed
/// to allocObject
///
/// POSSIBILITIES: It may be useful to have a variant which
/// requires the object to have been fully zeroed from offsets
/// sizeof(SwiftHeapObject) to allocatedSize.
SWIFT_RUNTIME_EXPORT
void swift_deallocObject(HeapObject *object, size_t allocatedSize,
size_t allocatedAlignMask);
/// Deallocate an uninitialized object with a strong reference count of +1.
///
/// It must have been returned by swift_allocObject, but otherwise the object is
/// in an unknown state.
///
/// \param object - never null
/// \param allocatedSize - the allocated size of the object from the
/// program's perspective, i.e. the value
/// \param allocatedAlignMask - the alignment requirement that was passed
/// to allocObject
///
SWIFT_RUNTIME_EXPORT
void swift_deallocUninitializedObject(HeapObject *object, size_t allocatedSize,
size_t allocatedAlignMask);
/// Deallocate the given memory.
///
/// It must have been returned by swift_allocObject, possibly used as an
/// Objective-C class instance, and the strong reference must have the
/// RC_DEALLOCATING_FLAG flag set, but otherwise the object is in an unknown
/// state.
///
/// \param object - never null
/// \param allocatedSize - the allocated size of the object from the
/// program's perspective, i.e. the value
/// \param allocatedAlignMask - the alignment requirement that was passed
/// to allocObject
///
/// POSSIBILITIES: It may be useful to have a variant which
/// requires the object to have been fully zeroed from offsets
/// sizeof(SwiftHeapObject) to allocatedSize.
SWIFT_RUNTIME_EXPORT
void swift_deallocClassInstance(HeapObject *object,
size_t allocatedSize,
size_t allocatedAlignMask);
/// Deallocate the given memory after destroying instance variables.
///
/// Destroys instance variables in classes more derived than the given metatype.
///
/// It must have been returned by swift_allocObject, possibly used as an
/// Objective-C class instance, and the strong reference must be equal to 1.
///
/// \param object - may be null
/// \param type - most derived class whose instance variables do not need to
/// be destroyed
/// \param allocatedSize - the allocated size of the object from the
/// program's perspective, i.e. the value
/// \param allocatedAlignMask - the alignment requirement that was passed
/// to allocObject
SWIFT_RUNTIME_EXPORT
void swift_deallocPartialClassInstance(HeapObject *object,
const HeapMetadata *type,
size_t allocatedSize,
size_t allocatedAlignMask);
/// Deallocate the given memory allocated by swift_allocBox; it was returned
/// by swift_allocBox but is otherwise in an unknown state. The given Metadata
/// pointer must be the same metadata pointer that was passed to swift_allocBox
/// when the memory was allocated.
SWIFT_RUNTIME_EXPORT
void swift_deallocBox(HeapObject *object);
/// Project the value out of a box. `object` must have been allocated
/// using `swift_allocBox`, or by the compiler using a statically-emitted
/// box metadata object.
SWIFT_RUNTIME_EXPORT
OpaqueValue *swift_projectBox(HeapObject *object);
/// RAII object that wraps a Swift heap object and releases it upon
/// destruction.
class SwiftRAII {
HeapObject *object;
public:
SwiftRAII(HeapObject *obj, bool AlreadyRetained) : object(obj) {
if (!AlreadyRetained)
swift_retain(obj);
}
~SwiftRAII() {
if (object)
swift_release(object);
}
SwiftRAII(const SwiftRAII &other) {
swift_retain(*other);
object = *other;
;
}
SwiftRAII(SwiftRAII &&other) : object(*other) {
other.object = nullptr;
}
SwiftRAII &operator=(const SwiftRAII &other) {
if (object)
swift_release(object);
swift_retain(*other);
object = *other;
return *this;
}
SwiftRAII &operator=(SwiftRAII &&other) {
if (object)
swift_release(object);
object = *other;
other.object = nullptr;
return *this;
}
HeapObject *operator *() const { return object; }
};
/*****************************************************************************/
/**************************** UNOWNED REFERENCES *****************************/
/*****************************************************************************/
/// An unowned reference in memory. This is ABI.
struct UnownedReference {
HeapObject *Value;
};
/// Increment the unowned retain count.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_unownedRetain(HeapObject *value);
/// Decrement the unowned retain count.
SWIFT_RUNTIME_EXPORT
void swift_unownedRelease(HeapObject *value);
/// Increment the unowned retain count.
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_unownedRetain(HeapObject *value);
/// Decrement the unowned retain count.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_unownedRelease(HeapObject *value);
/// Increment the unowned retain count by n.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_unownedRetain_n(HeapObject *value, int n);
/// Decrement the unowned retain count by n.
SWIFT_RUNTIME_EXPORT
void swift_unownedRelease_n(HeapObject *value, int n);
/// Increment the unowned retain count by n.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_nonatomic_unownedRetain_n(HeapObject *value, int n);
/// Decrement the unowned retain count by n.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_unownedRelease_n(HeapObject *value, int n);
/// Increment the strong retain count of an object, aborting if it has
/// been deallocated.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_unownedRetainStrong(HeapObject *value);
/// Increment the strong retain count of an object, aborting if it has
/// been deallocated.
SWIFT_RUNTIME_EXPORT
HeapObject *swift_nonatomic_unownedRetainStrong(HeapObject *value);
/// Increment the strong retain count of an object which may have been
/// deallocated, aborting if it has been deallocated, and decrement its
/// unowned reference count.
SWIFT_RUNTIME_EXPORT
void swift_unownedRetainStrongAndRelease(HeapObject *value);
/// Increment the strong retain count of an object which may have been
/// deallocated, aborting if it has been deallocated, and decrement its
/// unowned reference count.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_unownedRetainStrongAndRelease(HeapObject *value);
/// Aborts if the object has been deallocated.
SWIFT_RUNTIME_EXPORT
void swift_unownedCheck(HeapObject *value);
static inline void swift_unownedInit(UnownedReference *ref, HeapObject *value) {
ref->Value = value;
swift_unownedRetain(value);
}
static inline void swift_unownedAssign(UnownedReference *ref,
HeapObject *value) {
auto oldValue = ref->Value;
if (value != oldValue) {
swift_unownedRetain(value);
ref->Value = value;
swift_unownedRelease(oldValue);
}
}
static inline HeapObject *swift_unownedLoadStrong(UnownedReference *ref) {
auto value = ref->Value;
swift_unownedRetainStrong(value);
return value;
}
static inline void *swift_unownedTakeStrong(UnownedReference *ref) {
auto value = ref->Value;
swift_unownedRetainStrongAndRelease(value);
return value;
}
static inline void swift_unownedDestroy(UnownedReference *ref) {
swift_unownedRelease(ref->Value);
}
static inline void swift_unownedCopyInit(UnownedReference *dest,
UnownedReference *src) {
dest->Value = src->Value;
swift_unownedRetain(dest->Value);
}
static inline void swift_unownedTakeInit(UnownedReference *dest,
UnownedReference *src) {
dest->Value = src->Value;
}
static inline void swift_unownedCopyAssign(UnownedReference *dest,
UnownedReference *src) {
auto newValue = src->Value;
auto oldValue = dest->Value;
if (newValue != oldValue) {
dest->Value = newValue;
swift_unownedRetain(newValue);
swift_unownedRelease(oldValue);
}
}
static inline void swift_unownedTakeAssign(UnownedReference *dest,
UnownedReference *src) {
auto newValue = src->Value;
auto oldValue = dest->Value;
dest->Value = newValue;
swift_unownedRelease(oldValue);
}
static inline bool swift_unownedIsEqual(UnownedReference *ref,
HeapObject *value) {
bool isEqual = ref->Value == value;
if (isEqual)
swift_unownedCheck(value);
return isEqual;
}
/*****************************************************************************/
/****************************** WEAK REFERENCES ******************************/
/*****************************************************************************/
// Defined in Runtime/WeakReference.h
class WeakReference;
/// Initialize a weak reference.
///
/// \param ref - never null
/// \param value - can be null
/// \return ref
SWIFT_RUNTIME_EXPORT
WeakReference *swift_weakInit(WeakReference *ref, HeapObject *value);
/// Assign a new value to a weak reference.
///
/// \param ref - never null
/// \param value - can be null
/// \return ref
SWIFT_RUNTIME_EXPORT
WeakReference *swift_weakAssign(WeakReference *ref, HeapObject *value);
/// Load a value from a weak reference. If the current value is a
/// non-null object that has begun deallocation, returns null;
/// otherwise, retains the object before returning.
///
/// \param ref - never null
/// \return can be null
SWIFT_RUNTIME_EXPORT
HeapObject *swift_weakLoadStrong(WeakReference *ref);
/// Load a value from a weak reference as if by swift_weakLoadStrong,
/// but leaving the reference in an uninitialized state.
///
/// \param ref - never null
/// \return can be null
SWIFT_RUNTIME_EXPORT
HeapObject *swift_weakTakeStrong(WeakReference *ref);
/// Destroy a weak reference.
///
/// \param ref - never null, but can refer to a null object
SWIFT_RUNTIME_EXPORT
void swift_weakDestroy(WeakReference *ref);
/// Copy initialize a weak reference.
///
/// \param dest - never null, but can refer to a null object
/// \param src - never null, but can refer to a null object
/// \return dest
SWIFT_RUNTIME_EXPORT
WeakReference *swift_weakCopyInit(WeakReference *dest, WeakReference *src);
/// Take initialize a weak reference.
///
/// \param dest - never null, but can refer to a null object
/// \param src - never null, but can refer to a null object
/// \return dest
SWIFT_RUNTIME_EXPORT
WeakReference *swift_weakTakeInit(WeakReference *dest, WeakReference *src);
/// Copy assign a weak reference.
///
/// \param dest - never null, but can refer to a null object
/// \param src - never null, but can refer to a null object
/// \return dest
SWIFT_RUNTIME_EXPORT
WeakReference *swift_weakCopyAssign(WeakReference *dest, WeakReference *src);
/// Take assign a weak reference.
///
/// \param dest - never null, but can refer to a null object
/// \param src - never null, but can refer to a null object
/// \return dest
SWIFT_RUNTIME_EXPORT
WeakReference *swift_weakTakeAssign(WeakReference *dest, WeakReference *src);
/*****************************************************************************/
/************************* OTHER REFERENCE-COUNTING **************************/
/*****************************************************************************/
SWIFT_RUNTIME_EXPORT
void *swift_bridgeObjectRetain(void *value);
/// Increment the strong retain count of a bridged object by n.
SWIFT_RUNTIME_EXPORT
void *swift_bridgeObjectRetain_n(void *value, int n);
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_bridgeObjectRetain(void *value);
/// Increment the strong retain count of a bridged object by n.
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_bridgeObjectRetain_n(void *value, int n);
/*****************************************************************************/
/************************ UNKNOWN REFERENCE-COUNTING *************************/
/*****************************************************************************/
#if SWIFT_OBJC_INTEROP
/// Increment the strong retain count of an object which might not be a native
/// Swift object.
SWIFT_RUNTIME_EXPORT
void *swift_unknownObjectRetain(void *value);
/// Increment the strong retain count of an object which might not be a native
/// Swift object by n.
SWIFT_RUNTIME_EXPORT
void *swift_unknownObjectRetain_n(void *value, int n);
/// Increment the strong retain count of an object which might not be a native
/// Swift object.
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_unknownObjectRetain(void *value);
/// Increment the strong retain count of an object which might not be a native
/// Swift object by n.
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_unknownObjectRetain_n(void *value, int n);
#else
static inline void *swift_unknownObjectRetain(void *value) {
return swift_retain(static_cast<HeapObject *>(value));
}
static inline void *swift_unknownObjectRetain_n(void *value, int n) {
return swift_retain_n(static_cast<HeapObject *>(value), n);
}
static inline void *swift_nonatomic_unknownObjectRetain(void *value) {
return swift_nonatomic_retain(static_cast<HeapObject *>(value));
}
static inline void *swift_nonatomic_unknownObjectRetain_n(void *value, int n) {
return swift_nonatomic_retain_n(static_cast<HeapObject *>(value), n);
}
#endif // SWIFT_OBJC_INTEROP
SWIFT_RUNTIME_EXPORT
void swift_bridgeObjectRelease(void *value);
/// Decrement the strong retain count of a bridged object by n.
SWIFT_RUNTIME_EXPORT
void swift_bridgeObjectRelease_n(void *value, int n);
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_bridgeObjectRelease(void *value);
/// Decrement the strong retain count of a bridged object by n.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_bridgeObjectRelease_n(void *value, int n);
#if SWIFT_OBJC_INTEROP
/// Decrement the strong retain count of an object which might not be a native
/// Swift object.
SWIFT_RUNTIME_EXPORT
void swift_unknownObjectRelease(void *value);
/// Decrement the strong retain count of an object which might not be a native
/// Swift object by n.
SWIFT_RUNTIME_EXPORT
void swift_unknownObjectRelease_n(void *value, int n);
/// Decrement the strong retain count of an object which might not be a native
/// Swift object.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_unknownObjectRelease(void *value);
/// Decrement the strong retain count of an object which might not be a native
/// Swift object by n.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_unknownObjectRelease_n(void *value, int n);
#else
static inline void swift_unknownObjectRelease(void *value) {
swift_release(static_cast<HeapObject *>(value));
}
static inline void swift_unknownObjectRelease_n(void *value, int n) {
swift_release_n(static_cast<HeapObject *>(value), n);
}
static inline void swift_nonatomic_unknownObjectRelease(void *value) {
swift_nonatomic_release(static_cast<HeapObject *>(value));
}
static inline void swift_nonatomic_unknownObjectRelease_n(void *value, int n) {
swift_nonatomic_release_n(static_cast<HeapObject *>(value), n);
}
#endif // SWIFT_OBJC_INTEROP
/*****************************************************************************/
/************************** UNKNOWN WEAK REFERENCES **************************/
/*****************************************************************************/
#if SWIFT_OBJC_INTEROP
/// Initialize a weak reference.
///
/// \param ref - never null
/// \param value - not necessarily a native Swift object; can be null
/// \return ref
SWIFT_RUNTIME_EXPORT
WeakReference *swift_unknownObjectWeakInit(WeakReference *ref, void *value);
#else
static inline WeakReference *swift_unknownObjectWeakInit(WeakReference *ref,
void *value) {
return swift_weakInit(ref, static_cast<HeapObject *>(value));
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Assign a new value to a weak reference.
///
/// \param ref - never null
/// \param value - not necessarily a native Swift object; can be null
/// \return ref
SWIFT_RUNTIME_EXPORT
WeakReference *swift_unknownObjectWeakAssign(WeakReference *ref, void *value);
#else
static inline WeakReference *swift_unknownObjectWeakAssign(WeakReference *ref,
void *value) {
return swift_weakAssign(ref, static_cast<HeapObject *>(value));
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Load a value from a weak reference, much like swift_weakLoadStrong
/// but without requiring the variable to refer to a native Swift object.
///
/// \param ref - never null
/// \return can be null
SWIFT_RUNTIME_EXPORT
void *swift_unknownObjectWeakLoadStrong(WeakReference *ref);
#else
static inline void *swift_unknownObjectWeakLoadStrong(WeakReference *ref) {
return static_cast<void *>(swift_weakLoadStrong(ref));
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Load a value from a weak reference as if by
/// swift_unknownObjectWeakLoadStrong, but leaving the reference in an
/// uninitialized state.
///
/// \param ref - never null
/// \return can be null
SWIFT_RUNTIME_EXPORT
void *swift_unknownObjectWeakTakeStrong(WeakReference *ref);
#else
static inline void *swift_unknownObjectWeakTakeStrong(WeakReference *ref) {
return static_cast<void *>(swift_weakTakeStrong(ref));
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Destroy a weak reference variable that might not refer to a native
/// Swift object.
SWIFT_RUNTIME_EXPORT
void swift_unknownObjectWeakDestroy(WeakReference *object);
#else
static inline void swift_unknownObjectWeakDestroy(WeakReference *object) {
swift_weakDestroy(object);
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Copy-initialize a weak reference variable from one that might not
/// refer to a native Swift object.
/// \return dest
SWIFT_RUNTIME_EXPORT
WeakReference *swift_unknownObjectWeakCopyInit(WeakReference *dest,
WeakReference *src);
#else
static inline WeakReference *
swift_unknownObjectWeakCopyInit(WeakReference *dest, WeakReference *src) {
return swift_weakCopyInit(dest, src);
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Take-initialize a weak reference variable from one that might not
/// refer to a native Swift object.
/// \return dest
SWIFT_RUNTIME_EXPORT
WeakReference *swift_unknownObjectWeakTakeInit(WeakReference *dest,
WeakReference *src);
#else
static inline WeakReference *
swift_unknownObjectWeakTakeInit(WeakReference *dest, WeakReference *src) {
return swift_weakTakeInit(dest, src);
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Copy-assign a weak reference variable from another when either
/// or both variables might not refer to a native Swift object.
/// \return dest
SWIFT_RUNTIME_EXPORT
WeakReference *swift_unknownObjectWeakCopyAssign(WeakReference *dest,
WeakReference *src);
#else
static inline WeakReference *
swift_unknownObjectWeakCopyAssign(WeakReference *dest, WeakReference *src) {
return swift_weakCopyAssign(dest, src);
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Take-assign a weak reference variable from another when either
/// or both variables might not refer to a native Swift object.
/// \return dest
SWIFT_RUNTIME_EXPORT
WeakReference *swift_unknownObjectWeakTakeAssign(WeakReference *dest,
WeakReference *src);
#else
static inline WeakReference *
swift_unknownObjectWeakTakeAssign(WeakReference *dest, WeakReference *src) {
return swift_weakTakeAssign(dest, src);
}
#endif // SWIFT_OBJC_INTEROP
/*****************************************************************************/
/************************ UNKNOWN UNOWNED REFERENCES *************************/
/*****************************************************************************/
#if SWIFT_OBJC_INTEROP
/// Initialize an unowned reference to an object with unknown reference
/// counting.
/// \return ref
SWIFT_RUNTIME_EXPORT
UnownedReference *swift_unknownObjectUnownedInit(UnownedReference *ref,
void *value);
#else
static inline UnownedReference *
swift_unknownObjectUnownedInit(UnownedReference *ref, void *value) {
swift_unownedInit(ref, static_cast<HeapObject*>(value));
return ref;
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Assign to an unowned reference holding an object with unknown reference
/// counting.
/// \return ref
SWIFT_RUNTIME_EXPORT
UnownedReference *swift_unknownObjectUnownedAssign(UnownedReference *ref,
void *value);
#else
static inline UnownedReference *
swift_unknownObjectUnownedAssign(UnownedReference *ref, void *value) {
swift_unownedAssign(ref, static_cast<HeapObject*>(value));
return ref;
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Load from an unowned reference to an object with unknown reference
/// counting.
SWIFT_RUNTIME_EXPORT
void *swift_unknownObjectUnownedLoadStrong(UnownedReference *ref);
#else
static inline void *
swift_unknownObjectUnownedLoadStrong(UnownedReference *ref) {
return swift_unownedLoadStrong(ref);
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Take from an unowned reference to an object with unknown reference
/// counting.
SWIFT_RUNTIME_EXPORT
void *swift_unknownObjectUnownedTakeStrong(UnownedReference *ref);
#else
static inline void *
swift_unknownObjectUnownedTakeStrong(UnownedReference *ref) {
return swift_unownedTakeStrong(ref);
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Destroy an unowned reference to an object with unknown reference counting.
SWIFT_RUNTIME_EXPORT
void swift_unknownObjectUnownedDestroy(UnownedReference *ref);
#else
static inline void swift_unknownObjectUnownedDestroy(UnownedReference *ref) {
swift_unownedDestroy(ref);
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Copy-initialize an unowned reference variable from one that might not
/// refer to a native Swift object.
/// \return dest
SWIFT_RUNTIME_EXPORT
UnownedReference *swift_unknownObjectUnownedCopyInit(UnownedReference *dest,
UnownedReference *src);
#else
static inline UnownedReference *
swift_unknownObjectUnownedCopyInit(UnownedReference *dest,
UnownedReference *src) {
swift_unownedCopyInit(dest, src);
return dest;
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Take-initialize an unowned reference variable from one that might not
/// refer to a native Swift object.
SWIFT_RUNTIME_EXPORT
UnownedReference *swift_unknownObjectUnownedTakeInit(UnownedReference *dest,
UnownedReference *src);
#else
static inline UnownedReference *
swift_unknownObjectUnownedTakeInit(UnownedReference *dest,
UnownedReference *src) {
swift_unownedTakeInit(dest, src);
return dest;
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Copy-assign an unowned reference variable from another when either
/// or both variables might not refer to a native Swift object.
/// \return dest
SWIFT_RUNTIME_EXPORT
UnownedReference *swift_unknownObjectUnownedCopyAssign(UnownedReference *dest,
UnownedReference *src);
#else
static inline UnownedReference *
swift_unknownObjectUnownedCopyAssign(UnownedReference *dest,
UnownedReference *src) {
swift_unownedCopyAssign(dest, src);
return dest;
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Take-assign an unowned reference variable from another when either
/// or both variables might not refer to a native Swift object.
/// \return dest
SWIFT_RUNTIME_EXPORT
UnownedReference *swift_unknownObjectUnownedTakeAssign(UnownedReference *dest,
UnownedReference *src);
#else
static inline UnownedReference *
swift_unknownObjectUnownedTakeAssign(UnownedReference *dest,
UnownedReference *src) {
swift_unownedTakeAssign(dest, src);
return dest;
}
#endif // SWIFT_OBJC_INTEROP
#if SWIFT_OBJC_INTEROP
/// Return `*ref == value` when ref might not refer to a native Swift object.
/// Does not halt when *ref is a dead object as long as *ref != value.
SWIFT_RUNTIME_EXPORT
bool swift_unknownObjectUnownedIsEqual(UnownedReference *ref, void *value);
#else
static inline bool swift_unknownObjectUnownedIsEqual(UnownedReference *ref,
void *value) {
return swift_unownedIsEqual(ref, static_cast<HeapObject *>(value));
}
#endif // SWIFT_OBJC_INTEROP
struct TypeNamePair {
const char *data;
uintptr_t length;
};
/// Return the name of a Swift type represented by a metadata object.
/// func _getTypeName(_ type: Any.Type, qualified: Bool)
/// -> (UnsafePointer<UInt8>, Int)
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
TypeNamePair
swift_getTypeName(const Metadata *type, bool qualified);
/// Return the mangled name of a Swift type represented by a metadata object.
/// func _getMangledTypeName(_ type: Any.Type)
/// -> (UnsafePointer<UInt8>, Int)
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
TypeNamePair
swift_getMangledTypeName(const Metadata *type);
} // end namespace swift
#if SWIFT_OBJC_INTEROP
/// Standard ObjC lifecycle methods for Swift objects
#define STANDARD_OBJC_METHOD_IMPLS_FOR_SWIFT_OBJECTS \
- (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); \
} \
- (NSUInteger)retainCount { \
return swift::swift_retainCount(reinterpret_cast<HeapObject *>(self)); \
} \
- (BOOL)_isDeallocating { \
return swift_isDeallocating(reinterpret_cast<HeapObject *>(self)); \
} \
- (BOOL)_tryRetain { \
return swift_tryRetain(reinterpret_cast<HeapObject*>(self)) != nullptr; \
} \
- (BOOL)allowsWeakReference { \
return !swift_isDeallocating(reinterpret_cast<HeapObject *>(self)); \
} \
- (BOOL)retainWeakReference { \
return swift_tryRetain(reinterpret_cast<HeapObject*>(self)) != nullptr; \
} \
- (void)_setWeaklyReferenced { \
auto heapObj = reinterpret_cast<HeapObject *>(self); \
heapObj->refCounts.setPureSwiftDeallocation(false); \
} \
- (void)_noteAssociatedObjects { \
auto heapObj = reinterpret_cast<HeapObject *>(self); \
heapObj->refCounts.setPureSwiftDeallocation(false); \
} \
- (void)dealloc { \
swift_rootObjCDealloc(reinterpret_cast<HeapObject *>(self)); \
}
#endif // SWIFT_OBJC_INTEROP
#endif // SWIFT_RUNTIME_ALLOC_H