X-Git-Url: https://git.saurik.com/apple/objc4.git/blobdiff_plain/ee974f79090efc52c8d37c74dff5abadabf50296..8972963c21fb120c80c09e06536ba4aa7eb98af3:/runtime/objc-runtime-new.h diff --git a/runtime/objc-runtime-new.h b/runtime/objc-runtime-new.h index 1f84e36..64e8736 100644 --- a/runtime/objc-runtime-new.h +++ b/runtime/objc-runtime-new.h @@ -21,6 +21,11 @@ * @APPLE_LICENSE_HEADER_END@ */ +#ifndef _OBJC_RUNTIME_NEW_H +#define _OBJC_RUNTIME_NEW_H + +__BEGIN_DECLS + // Values for class_ro_t->flags // These are emitted by the compiler and are part of the ABI. // class is a metaclass @@ -35,6 +40,11 @@ #define RO_HIDDEN (1<<4) // class has attribute(objc_exception): OBJC_EHTYPE_$_ThisClass is non-weak #define RO_EXCEPTION (1<<5) +// this bit is available for reassignment +// #define RO_REUSE_ME (1<<6) +// class compiled with -fobjc-arr (automatic retain/release) +#define RO_IS_ARR (1<<7) + // class is in an unloadable bundle - must never be set by compiler #define RO_FROM_BUNDLE (1<<29) // class is unrealized future class - must never be set by compiler @@ -67,17 +77,119 @@ #define RW_SPECIALIZED_VTABLE (1<<22) // class instances may have associative references #define RW_INSTANCES_HAVE_ASSOCIATED_OBJECTS (1<<21) +// class or superclass has .cxx_construct/destruct implementations +#define RW_HAS_CXX_STRUCTORS (1<<20) +// class has instance-specific GC layout +#define RW_HAS_INSTANCE_SPECIFIC_LAYOUT (1 << 19) +// class or superclass has non-trivial .release_ivars implementation +#define RW_HAS_IVAR_RELEASER (1<<18) +// class or superclass has custom retain/release/autorelease/retainCount impl +#define RW_HAS_CUSTOM_RR (1<<17) -typedef struct method_t { +struct method_t { SEL name; const char *types; IMP imp; -} method_t; + + struct SortBySELAddress : + public std::binary_function + { + bool operator() (const method_t& lhs, + const method_t& rhs) + { return lhs.name < rhs.name; } + }; +}; typedef struct method_list_t { - uint32_t entsize_NEVER_USE; // low 2 bits used for fixup markers + uint32_t entsize_NEVER_USE; // high bits used for fixup markers uint32_t count; - struct method_t first; + method_t first; + + uint32_t getEntsize() const { + return entsize_NEVER_USE & ~(uint32_t)3; + } + uint32_t getCount() const { + return count; + } + method_t& get(uint32_t i) const { + return *(method_t *)((uint8_t *)&first + i*getEntsize()); + } + + // iterate methods, taking entsize into account + // fixme need a proper const_iterator + struct method_iterator { + uint32_t entsize; + uint32_t index; // keeping track of this saves a divide in operator- + method_t* method; + + typedef std::random_access_iterator_tag iterator_category; + typedef method_t value_type; + typedef ptrdiff_t difference_type; + typedef method_t* pointer; + typedef method_t& reference; + + method_iterator() { } + + method_iterator(const method_list_t& mlist, uint32_t start = 0) + : entsize(mlist.getEntsize()) + , index(start) + , method(&mlist.get(start)) + { } + + const method_iterator& operator += (ptrdiff_t count) { + method = (method_t*)((uint8_t *)method + count*entsize); + index += (int32_t)count; + return *this; + } + const method_iterator& operator -= (ptrdiff_t count) { + method = (method_t*)((uint8_t *)method - count*entsize); + index -= (int32_t)count; + return *this; + } + const method_iterator operator + (ptrdiff_t count) const { + return method_iterator(*this) += count; + } + const method_iterator operator - (ptrdiff_t count) const { + return method_iterator(*this) -= count; + } + + method_iterator& operator ++ () { *this += 1; return *this; } + method_iterator& operator -- () { *this -= 1; return *this; } + method_iterator operator ++ (int) { + method_iterator result(*this); *this += 1; return result; + } + method_iterator operator -- (int) { + method_iterator result(*this); *this -= 1; return result; + } + + ptrdiff_t operator - (const method_iterator& rhs) const { + return (ptrdiff_t)this->index - (ptrdiff_t)rhs.index; + } + + method_t& operator * () const { return *method; } + method_t* operator -> () const { return method; } + + operator method_t& () const { return *method; } + + bool operator == (const method_iterator& rhs) { + return this->method == rhs.method; + } + bool operator != (const method_iterator& rhs) { + return this->method != rhs.method; + } + + bool operator < (const method_iterator& rhs) { + return this->method < rhs.method; + } + bool operator > (const method_iterator& rhs) { + return this->method > rhs.method; + } + }; + + method_iterator begin() const { return method_iterator(*this, 0); } + method_iterator end() const { return method_iterator(*this, getCount()); } + } method_list_t; typedef struct ivar_t { @@ -94,9 +206,20 @@ typedef struct ivar_t { typedef struct ivar_list_t { uint32_t entsize; uint32_t count; - struct ivar_t first; + ivar_t first; } ivar_list_t; +typedef struct objc_property { + const char *name; + const char *attributes; +} property_t; + +typedef struct property_list_t { + uint32_t entsize; + uint32_t count; + property_t first; +} property_list_t; + typedef uintptr_t protocol_ref_t; // protocol_t *, but unremapped typedef struct protocol_t { @@ -107,7 +230,7 @@ typedef struct protocol_t { method_list_t *classMethods; method_list_t *optionalInstanceMethods; method_list_t *optionalClassMethods; - struct objc_property_list *instanceProperties; + property_list_t *instanceProperties; } protocol_t; typedef struct protocol_list_t { @@ -132,7 +255,7 @@ typedef struct class_ro_t { const ivar_list_t * ivars; const uint8_t * weakIvarLayout; - const struct objc_property_list *baseProperties; + const property_list_t *baseProperties; } class_ro_t; typedef struct class_rw_t { @@ -141,20 +264,63 @@ typedef struct class_rw_t { const class_ro_t *ro; - struct method_list_t **methods; + method_list_t **methods; struct chained_property_list *properties; - struct protocol_list_t ** protocols; + const protocol_list_t ** protocols; struct class_t *firstSubclass; struct class_t *nextSiblingClass; } class_rw_t; +// We cannot store flags in the low bits of the 'data' field until we work with +// the 'leaks' team to not think that objc is leaking memory. See radar 8955342 +// for more info. +#define CLASS_FAST_FLAGS_VIA_RW_DATA 0 + typedef struct class_t { struct class_t *isa; struct class_t *superclass; Cache cache; IMP *vtable; - class_rw_t *data; + uintptr_t data_NEVER_USE; // class_rw_t * plus flags + + class_rw_t *data() const { +#if CLASS_FAST_FLAGS_VIA_RW_DATA + return (class_rw_t *)(data_NEVER_USE & ~3UL); +#else + return (class_rw_t *)data_NEVER_USE; +#endif + } + void setData(class_rw_t *newData) { +#if CLASS_FAST_FLAGS_VIA_RW_DATA + uintptr_t flags = (uintptr_t)data_NEVER_USE & 3UL; + data_NEVER_USE = (uintptr_t)newData | flags; +#else + data_NEVER_USE = (uintptr_t)newData; +#endif + } + + bool hasCustomRR() const { +#if CLASS_FAST_FLAGS_VIA_RW_DATA + return data_NEVER_USE & 1UL; +#else + return (data()->flags & RW_HAS_CUSTOM_RR); +#endif + } + void setHasCustomRR(); + void unsetHasCustomRR(); + + bool hasIvarReleaser() const { + return (data()->flags & RW_HAS_IVAR_RELEASER); + } + void setHasIvarReleaser(); + + bool isRootClass() const { + return superclass == NULL; + } + bool isRootMetaclass() const { + return isa == this; + } } class_t; typedef struct category_t { @@ -163,10 +329,20 @@ typedef struct category_t { struct method_list_t *instanceMethods; struct method_list_t *classMethods; struct protocol_list_t *protocols; - struct objc_property_list *instanceProperties; + struct property_list_t *instanceProperties; } category_t; struct objc_super2 { id receiver; Class current_class; }; + +typedef struct { + IMP imp; + SEL sel; +} message_ref_t; + + +__END_DECLS + +#endif