blob: 6a971d1ac5a26e3c831c4f9834b75925fdc64730 [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_RT_ENTRY_VISIBILITY
HeapObject *swift_allocObject(HeapMetadata const *metadata,
size_t requiredSize,
size_t requiredAlignmentMask)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
HeapObject *(*SWIFT_CC(RegisterPreservingCC) _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);
/// A structure that's two pointers in size.
///
/// C functions can use the TwoWordPair::Return type to return a value in
/// two registers, compatible with Swift's calling convention for tuples
/// and structs of two word-sized elements.
template<typename A, typename B>
struct TwoWordPair {
A first;
B second;
TwoWordPair() = default;
TwoWordPair(A first, B second);
// FIXME: rdar://36755525 clang miscompiles swiftcall functions
// Structs are returned indirectly on these platforms, but we want to return
// in registers, so cram the result into an unsigned long long.
// Use an enum class with implicit conversions so we don't dirty C callers
// too much.
#if __arm__ || __i386__ || defined(__CYGWIN__) || defined(_MSC_VER)
#if defined(__CYGWIN__)
enum class Return : unsigned __int128 {};
#else
enum class Return : unsigned long long {};
#endif
operator Return() const {
union {
TwoWordPair value;
Return mangled;
} reinterpret = {*this};
return reinterpret.mangled;
}
/*implicit*/ TwoWordPair(Return r) {
union {
Return mangled;
TwoWordPair value;
} reinterpret = {r};
*this = reinterpret.value;
}
#else
using Return = TwoWordPair;
#endif
};
template<typename A, typename B>
inline TwoWordPair<A,B>::TwoWordPair(A first, B second)
: first(first), second(second)
{
static_assert(sizeof(A) == sizeof(void*),
"first type must be word-sized");
static_assert(sizeof(B) == sizeof(void*),
"second type must be word-sized");
static_assert(alignof(TwoWordPair) == alignof(void*),
"pair must be word-aligned");
}
using BoxPair = TwoWordPair<HeapObject *, OpaqueValue *>;
/// 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_RUNTIME_EXPORT
BoxPair::Return swift_allocBox(Metadata const *type);
SWIFT_RUNTIME_EXPORT
BoxPair::Return (*_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_RUNTIME_EXPORT
BoxPair::Return 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_RT_ENTRY_VISIBILITY
void *swift_slowAlloc(size_t bytes, size_t alignMask)
SWIFT_CC(RegisterPreservingCC);
// If the caller cannot promise to zero the object during destruction,
// then call these corresponding APIs:
SWIFT_RT_ENTRY_VISIBILITY
void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask)
SWIFT_CC(RegisterPreservingCC);
/// 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_RT_ENTRY_VISIBILITY
HeapObject *swift_retain(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
HeapObject *(*SWIFT_CC(RegisterPreservingCC) _swift_retain)(HeapObject *object);
SWIFT_RT_ENTRY_VISIBILITY
HeapObject *swift_retain_n(HeapObject *object, uint32_t n)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
HeapObject *(*SWIFT_CC(RegisterPreservingCC)
_swift_retain_n)(HeapObject *object, uint32_t n);
SWIFT_RT_ENTRY_VISIBILITY
HeapObject *swift_nonatomic_retain(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
HeapObject *(*SWIFT_CC(RegisterPreservingCC)
_swift_nonatomic_retain)(HeapObject *object);
SWIFT_RT_ENTRY_VISIBILITY
HeapObject* swift_nonatomic_retain_n(HeapObject *object, uint32_t n)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
HeapObject *(*SWIFT_CC(RegisterPreservingCC)
_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_RT_ENTRY_VISIBILITY
HeapObject *swift_tryRetain(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
HeapObject * (* SWIFT_CC(RegisterPreservingCC) _swift_tryRetain)(HeapObject *);
/// Returns true if an object is in the process of being deallocated.
SWIFT_RUNTIME_EXPORT
bool swift_isDeallocating(HeapObject *object);
SWIFT_RUNTIME_EXPORT
bool (* SWIFT_CC(RegisterPreservingCC) _swift_isDeallocating)(HeapObject *);
/// Attempts to atomically pin an object and increment its reference
/// count. Returns nil if the object was already pinned.
///
/// The standard protocol is that the caller is responsible for
/// calling swift_unpin on the return value.
///
/// The object reference may not be nil.
SWIFT_RT_ENTRY_VISIBILITY
HeapObject *swift_tryPin(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RT_ENTRY_VISIBILITY
HeapObject *swift_nonatomic_tryPin(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
/// Given that an object is pinned, atomically unpin it and decrement
/// the reference count.
///
/// The object reference may be nil (to simplify the protocol).
SWIFT_RT_ENTRY_VISIBILITY
void swift_unpin(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RT_ENTRY_VISIBILITY
void swift_nonatomic_unpin(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
/// 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_RT_ENTRY_VISIBILITY
void swift_release(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
void (*SWIFT_CC(RegisterPreservingCC)
_swift_release)(HeapObject *object);
SWIFT_RT_ENTRY_VISIBILITY
void swift_nonatomic_release(HeapObject *object)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
void (*SWIFT_CC(RegisterPreservingCC)
_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_RT_ENTRY_VISIBILITY
void swift_release_n(HeapObject *object, uint32_t n)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
void (*SWIFT_CC(RegisterPreservingCC)
_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_RT_ENTRY_VISIBILITY
void swift_nonatomic_release_n(HeapObject *object, uint32_t n)
SWIFT_CC(RegisterPreservingCC);
SWIFT_RUNTIME_EXPORT
void (*SWIFT_CC(RegisterPreservingCC)
_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);
/// 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 pointer a reference to an object that uses Swift
/// reference counting and is either uniquely referenced or pinned?
SWIFT_RUNTIME_EXPORT
bool swift_isUniquelyReferencedOrPinnedNonObjC_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 non-null BridgeObject a unique or pinned reference to an
/// object that uses Swift reference counting?
SWIFT_RUNTIME_EXPORT
bool swift_isUniquelyReferencedOrPinnedNonObjC_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 native Swift pointer a non-null unique or pinned reference
/// to an object?
SWIFT_RT_ENTRY_VISIBILITY
bool swift_isUniquelyReferencedOrPinned_native(
const struct HeapObject *) SWIFT_CC(RegisterPreservingCC);
/// Is this non-null native Swift pointer a unique reference to
/// an object?
SWIFT_RT_ENTRY_VISIBILITY
bool swift_isUniquelyReferenced_nonNull_native(
const struct HeapObject *) SWIFT_CC(RegisterPreservingCC);
/// Does this non-null native Swift pointer refer to an object that
/// is either uniquely referenced or pinned?
SWIFT_RT_ENTRY_VISIBILITY
bool swift_isUniquelyReferencedOrPinned_nonNull_native(
const struct HeapObject *) SWIFT_CC(RegisterPreservingCC);
/// 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_RT_ENTRY_VISIBILITY
void swift_deallocObject(HeapObject *object, size_t allocatedSize,
size_t allocatedAlignMask)
SWIFT_CC(RegisterPreservingCC);
/// 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_RT_ENTRY_VISIBILITY
void swift_deallocUninitializedObject(HeapObject *object, size_t allocatedSize,
size_t allocatedAlignMask)
SWIFT_CC(RegisterPreservingCC);
/// 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_RT_ENTRY_VISIBILITY
HeapObject *swift_unownedRetain(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
/// Decrement the unowned retain count.
SWIFT_RT_ENTRY_VISIBILITY
void swift_unownedRelease(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
/// Increment the unowned retain count.
SWIFT_RT_ENTRY_VISIBILITY
void *swift_nonatomic_unownedRetain(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
/// Decrement the unowned retain count.
SWIFT_RT_ENTRY_VISIBILITY
void swift_nonatomic_unownedRelease(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
/// Increment the unowned retain count by n.
SWIFT_RT_ENTRY_VISIBILITY
HeapObject *swift_unownedRetain_n(HeapObject *value, int n)
SWIFT_CC(RegisterPreservingCC);
/// Decrement the unowned retain count by n.
SWIFT_RT_ENTRY_VISIBILITY
void swift_unownedRelease_n(HeapObject *value, int n)
SWIFT_CC(RegisterPreservingCC);
/// Increment the unowned retain count by n.
SWIFT_RT_ENTRY_VISIBILITY
HeapObject *swift_nonatomic_unownedRetain_n(HeapObject *value, int n)
SWIFT_CC(RegisterPreservingCC);
/// Decrement the unowned retain count by n.
SWIFT_RT_ENTRY_VISIBILITY
void swift_nonatomic_unownedRelease_n(HeapObject *value, int n)
SWIFT_CC(RegisterPreservingCC);
/// Increment the strong retain count of an object, aborting if it has
/// been deallocated.
SWIFT_RT_ENTRY_VISIBILITY
HeapObject *swift_unownedRetainStrong(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
/// Increment the strong retain count of an object, aborting if it has
/// been deallocated.
SWIFT_RT_ENTRY_VISIBILITY
HeapObject *swift_nonatomic_unownedRetainStrong(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
/// 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_RT_ENTRY_VISIBILITY
void swift_unownedRetainStrongAndRelease(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
/// 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_RT_ENTRY_VISIBILITY
void swift_nonatomic_unownedRetainStrongAndRelease(HeapObject *value)
SWIFT_CC(RegisterPreservingCC);
/// 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)
SWIFT_CC(DefaultCC);
/// Increment the strong retain count of a bridged object by n.
SWIFT_RUNTIME_EXPORT
void *swift_bridgeObjectRetain_n(void *value, int n)
SWIFT_CC(DefaultCC);
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_bridgeObjectRetain(void *value)
SWIFT_CC(DefaultCC);
/// Increment the strong retain count of a bridged object by n.
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_bridgeObjectRetain_n(void *value, int n)
SWIFT_CC(DefaultCC);
/*****************************************************************************/
/************************ 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_unknownRetain(void *value)
SWIFT_CC(DefaultCC);
/// Increment the strong retain count of an object which might not be a native
/// Swift object by n.
SWIFT_RUNTIME_EXPORT
void *swift_unknownRetain_n(void *value, int n)
SWIFT_CC(DefaultCC);
/// Increment the strong retain count of an object which might not be a native
/// Swift object.
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_unknownRetain(void *value)
SWIFT_CC(DefaultCC);
/// Increment the strong retain count of an object which might not be a native
/// Swift object by n.
SWIFT_RUNTIME_EXPORT
void *swift_nonatomic_unknownRetain_n(void *value, int n)
SWIFT_CC(DefaultCC);
#else
static inline void *swift_unknownRetain(void *value)
SWIFT_CC(DefaultCC) {
return swift_retain(static_cast<HeapObject *>(value));
}
static inline void *swift_unknownRetain_n(void *value, int n)
SWIFT_CC(DefaultCC) {
return swift_retain_n(static_cast<HeapObject *>(value), n);
}
static inline void *swift_nonatomic_unknownRetain(void *value)
SWIFT_CC(DefaultCC) {
return swift_nonatomic_retain(static_cast<HeapObject *>(value));
}
static inline void *swift_nonatomic_unknownRetain_n(void *value, int n)
SWIFT_CC(DefaultCC) {
return swift_nonatomic_retain_n(static_cast<HeapObject *>(value), n);
}
#endif /* SWIFT_OBJC_INTEROP */
SWIFT_RUNTIME_EXPORT
void swift_bridgeObjectRelease(void *value)
SWIFT_CC(DefaultCC);
/// Decrement the strong retain count of a bridged object by n.
SWIFT_RUNTIME_EXPORT
void swift_bridgeObjectRelease_n(void *value, int n)
SWIFT_CC(DefaultCC);
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_bridgeObjectRelease(void *value)
SWIFT_CC(DefaultCC);
/// Decrement the strong retain count of a bridged object by n.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_bridgeObjectRelease_n(void *value, int n)
SWIFT_CC(DefaultCC);
#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_unknownRelease(void *value)
SWIFT_CC(DefaultCC);
/// Decrement the strong retain count of an object which might not be a native
/// Swift object by n.
SWIFT_RUNTIME_EXPORT
void swift_unknownRelease_n(void *value, int n)
SWIFT_CC(DefaultCC);
/// Decrement the strong retain count of an object which might not be a native
/// Swift object.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_unknownRelease(void *value)
SWIFT_CC(DefaultCC);
/// Decrement the strong retain count of an object which might not be a native
/// Swift object by n.
SWIFT_RUNTIME_EXPORT
void swift_nonatomic_unknownRelease_n(void *value, int n)
SWIFT_CC(DefaultCC);
#else
static inline void swift_unknownRelease(void *value)
SWIFT_CC(RegisterPreservingCC) {
swift_release(static_cast<HeapObject *>(value));
}
static inline void swift_unknownRelease_n(void *value, int n)
SWIFT_CC(RegisterPreservingCC) {
swift_release_n(static_cast<HeapObject *>(value), n);
}
static inline void swift_nonatomic_unknownRelease(void *value)
SWIFT_CC(RegisterPreservingCC) {
swift_nonatomic_release(static_cast<HeapObject *>(value));
}
static inline void swift_nonatomic_unknownRelease_n(void *value, int n)
SWIFT_CC(RegisterPreservingCC) {
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_unknownWeakInit(WeakReference *ref, void *value);
#else
static inline WeakReference *swift_unknownWeakInit(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_unknownWeakAssign(WeakReference *ref, void *value);
#else
static inline WeakReference *swift_unknownWeakAssign(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_unknownWeakLoadStrong(WeakReference *ref);
#else
static inline void *swift_unknownWeakLoadStrong(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_unknownWeakLoadStrong, but leaving the reference in an
/// uninitialized state.
///
/// \param ref - never null
/// \return can be null
SWIFT_RUNTIME_EXPORT
void *swift_unknownWeakTakeStrong(WeakReference *ref);
#else
static inline void *swift_unknownWeakTakeStrong(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_unknownWeakDestroy(WeakReference *object);
#else
static inline void swift_unknownWeakDestroy(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_unknownWeakCopyInit(WeakReference *dest,
WeakReference *src);
#else
static inline WeakReference *swift_unknownWeakCopyInit(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_unknownWeakTakeInit(WeakReference *dest,
WeakReference *src);
#else
static inline WeakReference *swift_unknownWeakTakeInit(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_unknownWeakCopyAssign(WeakReference *dest,
WeakReference *src);
#else
static inline WeakReference *swift_unknownWeakCopyAssign(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_unknownWeakTakeAssign(WeakReference *dest,
WeakReference *src);
#else
static inline WeakReference *swift_unknownWeakTakeAssign(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_unknownUnownedInit(UnownedReference *ref, void *value);
#else
static inline UnownedReference *swift_unknownUnownedInit(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_unknownUnownedAssign(UnownedReference *ref,
void *value);
#else
static inline UnownedReference *
swift_unknownUnownedAssign(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_unknownUnownedLoadStrong(UnownedReference *ref);
#else
static inline void *swift_unknownUnownedLoadStrong(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_unknownUnownedTakeStrong(UnownedReference *ref);
#else
static inline void *swift_unknownUnownedTakeStrong(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_unknownUnownedDestroy(UnownedReference *ref);
#else
static inline void swift_unknownUnownedDestroy(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_unknownUnownedCopyInit(UnownedReference *dest,
UnownedReference *src);
#else
static inline UnownedReference *
swift_unknownUnownedCopyInit(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_unknownUnownedTakeInit(UnownedReference *dest,
UnownedReference *src);
#else
static inline UnownedReference *
swift_unknownUnownedTakeInit(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_unknownUnownedCopyAssign(UnownedReference *dest,
UnownedReference *src);
#else
static inline UnownedReference *
swift_unknownUnownedCopyAssign(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_unknownUnownedTakeAssign(UnownedReference *dest,
UnownedReference *src);
#else
static inline UnownedReference *
swift_unknownUnownedTakeAssign(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_unknownUnownedIsEqual(UnownedReference *ref, void *value);
#else
static inline bool swift_unknownUnownedIsEqual(UnownedReference *ref,
void *value) {
return swift_unownedIsEqual(ref, static_cast<HeapObject *>(value));
}
#endif /* SWIFT_OBJC_INTEROP */
/// 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
TwoWordPair<const char *, uintptr_t>::Return
swift_getTypeName(const Metadata *type, bool qualified);
} // end namespace swift
#endif /* SWIFT_RUNTIME_ALLOC_H */