* @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
#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
#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<const method_t&,
+ const method_t&, bool>
+ {
+ 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 {
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 {
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 {
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 {
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 {
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