* @APPLE_LICENSE_HEADER_START@
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
*
http://www.opensource.apple.com/apsl/
and read it before using this
* file.
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
* @APPLE_LICENSE_HEADER_END@
#
ifndef
_OBJC_RUNTIME_NEW_H
#
define
_OBJC_RUNTIME_NEW_H
#
if
__LP64__
typedef
uint32_t mask_t;
#
else
typedef
uint16_t mask_t;
#
endif
typedef
uintptr_t SEL;
struct
swift_class_t;
enum
Atomicity { Atomic = true, NotAtomic = false };
struct
bucket_t {
private
:
#
if
__arm64__
uintptr_t _imp;
SEL _sel;
#
else
SEL _sel;
uintptr_t _imp;
#
endif
uintptr_t modifierForSEL(SEL newSel)
const
{
return
(uintptr_t)&_imp ^ (uintptr_t)newSel;
uintptr_t signIMP(IMP newImp, SEL newSel)
const
{
if
(!newImp)
return
0;
return
(uintptr_t)
ptrauth_auth_and_resign(newImp,
ptrauth_key_function_pointer, 0,
ptrauth_key_process_dependent_code,
modifierForSEL(newSel));
public
:
inline SEL sel()
const
{
return
_sel; }
inline IMP imp()
const
{
if
(!_imp)
return
nil;
return
(IMP)
ptrauth_auth_and_resign((
const
void
*)_imp,
ptrauth_key_process_dependent_code,
modifierForSEL(_sel),
ptrauth_key_function_pointer, 0);
template <Atomicity>
void
set(SEL newSel, IMP newImp);
struct
cache_t {
struct
bucket_t *_buckets;
mask_t _mask;
mask_t _occupied;
public
:
struct
bucket_t *buckets();
mask_t mask();
mask_t occupied();
void
incrementOccupied();
void
setBucketsAndMask(
struct
bucket_t *newBuckets, mask_t newMask);
void
initializeToEmpty();
mask_t capacity();
bool isConstantEmptyCache();
bool canBeFreed();
static
size_t bytesForCapacity(uint32_t cap);
static
struct
bucket_t * endMarker(
struct
bucket_t *b, uint32_t cap);
void
expand();
void
reallocate(mask_t oldCapacity, mask_t newCapacity);
struct
bucket_t * find(SEL sel, id receiver);
static
void
bad_cache(id receiver, SEL sel, Class isa) __attribute__((noreturn));
typedef
struct
classref * classref_t;
template <typename Element, typename List, uint32_t FlagMask>
struct
entsize_list_tt {
uint32_t entsizeAndFlags;
uint32_t count;
Element first;
uint32_t entsize()
const
{
return
entsizeAndFlags & ~FlagMask;
uint32_t flags()
const
{
return
entsizeAndFlags & FlagMask;
Element& getOrEnd(uint32_t i)
const
{
assert(i <= count);
return
*(Element *)((uint8_t *)&first + i*entsize());
Element& get(uint32_t i)
const
{
assert(i < count);
return
getOrEnd(i);
size_t byteSize()
const
{
return
byteSize(entsize(), count);
static
size_t byteSize(uint32_t entsize, uint32_t count) {
return
sizeof
(entsize_list_tt) + (count-1)*entsize;
List *duplicate()
const
{
auto
*dup = (List *)calloc(this->byteSize(), 1);
dup->entsizeAndFlags = this->entsizeAndFlags;
dup->count = this->count;
std
::copy(begin(), end(), dup->begin());
return
dup;
struct
iterator;
const
iterator begin()
const
{
return
iterator(*static_cast<
const
List*>(this), 0);
iterator begin() {
return
iterator(*static_cast<
const
List*>(this), 0);
const
iterator end()
const
{
return
iterator(*static_cast<
const
List*>(this), count);
iterator end() {
return
iterator(*static_cast<
const
List*>(this), count);
struct
iterator {
uint32_t entsize;
uint32_t index;
Element* element;
typedef
std::random_access_iterator_tag iterator_category;
typedef
Element value_type;
typedef
ptrdiff_t difference_type;
typedef
Element* pointer;
typedef
Element& reference;
iterator() { }
iterator(
const
List& list, uint32_t start = 0)
: entsize(list.entsize())
, index(start)
, element(&list.getOrEnd(start))
const
iterator& operator += (ptrdiff_t delta) {
element = (Element*)((uint8_t *)element + delta*entsize);
index += (int32_t)delta;
return
*this;
const
iterator& operator -= (ptrdiff_t delta) {
element = (Element*)((uint8_t *)element - delta*entsize);
index -= (int32_t)delta;
return
*this;
const
iterator operator + (ptrdiff_t delta)
const
{
return
iterator(*this) += delta;
const
iterator operator - (ptrdiff_t delta)
const
{
return
iterator(*this) -= delta;
iterator& operator ++ () { *this += 1;
return
*this; }
iterator& operator -- () { *this -= 1;
return
*this; }
iterator operator ++ (
int
) {
iterator result(*this); *this += 1;
return
result;
iterator operator -- (
int
) {
iterator result(*this); *this -= 1;
return
result;
ptrdiff_t operator - (
const
iterator& rhs)
const
{
return
(ptrdiff_t)this->index - (ptrdiff_t)rhs.index;
Element& operator * ()
const
{
return
*element; }
Element* operator -> ()
const
{
return
element; }
operator Element& ()
const
{
return
*element; }
bool operator == (
const
iterator& rhs)
const
{
return
this->element == rhs.element;
bool operator != (
const
iterator& rhs)
const
{
return
this->element != rhs.element;
bool operator < (
const
iterator& rhs)
const
{
return
this->element < rhs.element;
bool operator > (
const
iterator& rhs)
const
{
return
this->element > rhs.element;
struct
method_t {
SEL name;
const
char
*types;
MethodListIMP imp;
struct
SortBySELAddress :
public std::binary_function<
const
method_t&,
const
method_t&, bool>
bool operator() (
const
method_t& lhs,
const
method_t& rhs)
{
return
lhs.name < rhs.name; }
struct
ivar_t {
#
if
__x86_64__
#
endif
int32_t *offset;
const
char
*name;
const
char
*type;
uint32_t alignment_raw;
uint32_t size;
uint32_t alignment()
const
{
if
(alignment_raw == ~(uint32_t)0)
return
1U << WORD_SHIFT;
return
1 << alignment_raw;
struct
property_t {
const
char
*name;
const
char
*attributes;
struct
method_list_t : entsize_list_tt<method_t, method_list_t, 0x3> {
bool isFixedUp()
const
;
void
setFixedUp();
uint32_t indexOfMethod(
const
method_t *meth)
const
{
uint32_t i =
(uint32_t)(((uintptr_t)meth - (uintptr_t)this) / entsize());
assert(i < count);
return
i;
struct
ivar_list_t : entsize_list_tt<ivar_t, ivar_list_t, 0> {
bool containsIvar(Ivar ivar)
const
{
return
(ivar >= (Ivar)&*begin() && ivar < (Ivar)&*end());
struct
property_list_t : entsize_list_tt<property_t, property_list_t, 0> {
typedef
uintptr_t protocol_ref_t;