mirror of
https://github.com/darlinghq/darling-objc4.git
synced 2024-11-26 21:50:26 +00:00
407 lines
12 KiB
C
407 lines
12 KiB
C
/*
|
|
* Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
|
|
*
|
|
* @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_OLD_H
|
|
#define _OBJC_RUNTIME_OLD_H
|
|
|
|
#include "objc-private.h"
|
|
|
|
#define CLS_CLASS 0x1
|
|
#define CLS_META 0x2
|
|
#define CLS_INITIALIZED 0x4
|
|
#define CLS_POSING 0x8
|
|
#define CLS_MAPPED 0x10
|
|
#define CLS_FLUSH_CACHE 0x20
|
|
#define CLS_GROW_CACHE 0x40
|
|
#define CLS_NEED_BIND 0x80
|
|
#define CLS_METHOD_ARRAY 0x100
|
|
// the JavaBridge constructs classes with these markers
|
|
#define CLS_JAVA_HYBRID 0x200
|
|
#define CLS_JAVA_CLASS 0x400
|
|
// thread-safe +initialize
|
|
#define CLS_INITIALIZING 0x800
|
|
// bundle unloading
|
|
#define CLS_FROM_BUNDLE 0x1000
|
|
// C++ ivar support
|
|
#define CLS_HAS_CXX_STRUCTORS 0x2000
|
|
// Lazy method list arrays
|
|
#define CLS_NO_METHOD_ARRAY 0x4000
|
|
// +load implementation
|
|
#define CLS_HAS_LOAD_METHOD 0x8000
|
|
// objc_allocateClassPair API
|
|
#define CLS_CONSTRUCTING 0x10000
|
|
// visibility=hidden
|
|
#define CLS_HIDDEN 0x20000
|
|
// available for use; was CLS_FINALIZE_ON_MAIN_THREAD
|
|
#define CLS_40000 0x40000
|
|
// Lazy property list arrays
|
|
#define CLS_NO_PROPERTY_ARRAY 0x80000
|
|
// +load implementation
|
|
#define CLS_CONNECTED 0x100000
|
|
#define CLS_LOADED 0x200000
|
|
// objc_allocateClassPair API
|
|
#define CLS_CONSTRUCTED 0x400000
|
|
// class is leaf for cache flushing
|
|
#define CLS_LEAF 0x800000
|
|
// class instances may have associative references
|
|
#define CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS 0x1000000
|
|
// available for use; was CLS_HAS_INSTANCE_SPECIFIC_LAYOUT
|
|
#define CLS_2000000 0x2000000
|
|
// class compiled with ARC
|
|
#define CLS_IS_ARC 0x4000000
|
|
// class is not ARC but has ARC-style weak ivar layout
|
|
#define CLS_HAS_WEAK_WITHOUT_ARC 0x8000000
|
|
|
|
|
|
// Terminator for array of method lists
|
|
#define END_OF_METHODS_LIST ((struct old_method_list*)-1)
|
|
|
|
#define ISCLASS(cls) (((cls)->info & CLS_CLASS) != 0)
|
|
#define ISMETA(cls) (((cls)->info & CLS_META) != 0)
|
|
#define GETMETA(cls) (ISMETA(cls) ? (cls) : (cls)->ISA())
|
|
|
|
|
|
struct old_class_ext {
|
|
uint32_t size;
|
|
const uint8_t *weak_ivar_layout;
|
|
struct old_property_list **propertyLists;
|
|
};
|
|
|
|
struct old_category {
|
|
char *category_name;
|
|
char *class_name;
|
|
struct old_method_list *instance_methods;
|
|
struct old_method_list *class_methods;
|
|
struct old_protocol_list *protocols;
|
|
// Fields below this point are in version 7 or later only.
|
|
uint32_t size;
|
|
struct old_property_list *instance_properties;
|
|
// Check size for fields below this point.
|
|
struct old_property_list *class_properties;
|
|
|
|
bool hasClassPropertiesField() const {
|
|
return size >= offsetof(old_category, class_properties) + sizeof(class_properties);
|
|
}
|
|
};
|
|
|
|
struct old_ivar {
|
|
char *ivar_name;
|
|
char *ivar_type;
|
|
int ivar_offset;
|
|
#ifdef __LP64__
|
|
int space;
|
|
#endif
|
|
};
|
|
|
|
struct old_ivar_list {
|
|
int ivar_count;
|
|
#ifdef __LP64__
|
|
int space;
|
|
#endif
|
|
/* variable length structure */
|
|
struct old_ivar ivar_list[1];
|
|
};
|
|
|
|
|
|
struct old_method {
|
|
SEL method_name;
|
|
char *method_types;
|
|
IMP method_imp;
|
|
};
|
|
|
|
struct old_method_list {
|
|
void *obsolete;
|
|
|
|
int method_count;
|
|
#ifdef __LP64__
|
|
int space;
|
|
#endif
|
|
/* variable length structure */
|
|
struct old_method method_list[1];
|
|
};
|
|
|
|
struct old_protocol {
|
|
Class isa;
|
|
const char *protocol_name;
|
|
struct old_protocol_list *protocol_list;
|
|
struct objc_method_description_list *instance_methods;
|
|
struct objc_method_description_list *class_methods;
|
|
};
|
|
|
|
struct old_protocol_list {
|
|
struct old_protocol_list *next;
|
|
long count;
|
|
struct old_protocol *list[1];
|
|
};
|
|
|
|
struct old_protocol_ext {
|
|
uint32_t size;
|
|
struct objc_method_description_list *optional_instance_methods;
|
|
struct objc_method_description_list *optional_class_methods;
|
|
struct old_property_list *instance_properties;
|
|
const char **extendedMethodTypes;
|
|
struct old_property_list *class_properties;
|
|
|
|
bool hasClassPropertiesField() const {
|
|
return size >= offsetof(old_protocol_ext, class_properties) + sizeof(class_properties);
|
|
}
|
|
};
|
|
|
|
|
|
struct old_property {
|
|
const char *name;
|
|
const char *attributes;
|
|
};
|
|
|
|
struct old_property_list {
|
|
uint32_t entsize;
|
|
uint32_t count;
|
|
struct old_property first;
|
|
};
|
|
|
|
|
|
struct objc_class : objc_object {
|
|
Class superclass;
|
|
const char *name;
|
|
uint32_t version;
|
|
uint32_t info;
|
|
uint32_t instance_size;
|
|
struct old_ivar_list *ivars;
|
|
struct old_method_list **methodLists;
|
|
Cache cache;
|
|
struct old_protocol_list *protocols;
|
|
// CLS_EXT only
|
|
const uint8_t *ivar_layout;
|
|
struct old_class_ext *ext;
|
|
|
|
void setInfo(uint32_t set) {
|
|
OSAtomicOr32Barrier(set, (volatile uint32_t *)&info);
|
|
}
|
|
|
|
void clearInfo(uint32_t clear) {
|
|
OSAtomicXor32Barrier(clear, (volatile uint32_t *)&info);
|
|
}
|
|
|
|
|
|
// set and clear must not overlap
|
|
void changeInfo(uint32_t set, uint32_t clear) {
|
|
ASSERT((set & clear) == 0);
|
|
|
|
uint32_t oldf, newf;
|
|
do {
|
|
oldf = this->info;
|
|
newf = (oldf | set) & ~clear;
|
|
} while (!OSAtomicCompareAndSwap32Barrier(oldf, newf, (volatile int32_t *)&info));
|
|
}
|
|
|
|
bool hasCxxCtor() {
|
|
// set_superclass propagates the flag from the superclass.
|
|
return info & CLS_HAS_CXX_STRUCTORS;
|
|
}
|
|
|
|
bool hasCxxDtor() {
|
|
return hasCxxCtor(); // one bit for both ctor and dtor
|
|
}
|
|
|
|
// Return YES if the class's ivars are managed by ARC,
|
|
// or the class is MRC but has ARC-style weak ivars.
|
|
bool hasAutomaticIvars() {
|
|
return info & (CLS_IS_ARC | CLS_HAS_WEAK_WITHOUT_ARC);
|
|
}
|
|
|
|
// Return YES if the class's ivars are managed by ARC.
|
|
bool isARC() {
|
|
return info & CLS_IS_ARC;
|
|
}
|
|
|
|
bool hasCustomRR() {
|
|
return true;
|
|
}
|
|
|
|
bool hasCustomAWZ() {
|
|
return true;
|
|
}
|
|
|
|
bool forbidsAssociatedObjects() {
|
|
// Old runtime doesn't support forbidding associated objects.
|
|
return false;
|
|
}
|
|
|
|
bool instancesHaveAssociatedObjects() {
|
|
return info & CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS;
|
|
}
|
|
|
|
void setInstancesHaveAssociatedObjects() {
|
|
setInfo(CLS_INSTANCES_HAVE_ASSOCIATED_OBJECTS);
|
|
}
|
|
|
|
bool shouldGrowCache() {
|
|
return info & CLS_GROW_CACHE;
|
|
}
|
|
|
|
void setShouldGrowCache(bool grow) {
|
|
if (grow) setInfo(CLS_GROW_CACHE);
|
|
else clearInfo(CLS_GROW_CACHE);
|
|
}
|
|
|
|
// +initialize bits are stored on the metaclass only
|
|
bool isInitializing() {
|
|
return getMeta()->info & CLS_INITIALIZING;
|
|
}
|
|
|
|
// +initialize bits are stored on the metaclass only
|
|
void setInitializing() {
|
|
getMeta()->setInfo(CLS_INITIALIZING);
|
|
}
|
|
|
|
// +initialize bits are stored on the metaclass only
|
|
bool isInitialized() {
|
|
return getMeta()->info & CLS_INITIALIZED;
|
|
}
|
|
|
|
// +initialize bits are stored on the metaclass only
|
|
void setInitialized() {
|
|
getMeta()->changeInfo(CLS_INITIALIZED, CLS_INITIALIZING);
|
|
}
|
|
|
|
bool isLoadable() {
|
|
// A class registered for +load is ready for +load to be called
|
|
// if it is connected.
|
|
return isConnected();
|
|
}
|
|
|
|
IMP getLoadMethod();
|
|
|
|
bool isFuture();
|
|
|
|
bool isConnected();
|
|
|
|
const char *mangledName() { return name; }
|
|
const char *demangledName() { return name; }
|
|
const char *nameForLogging() { return name; }
|
|
|
|
bool isRootClass() {
|
|
return superclass == nil;
|
|
}
|
|
|
|
bool isRootMetaclass() {
|
|
return ISA() == (Class)this;
|
|
}
|
|
|
|
bool isMetaClass() {
|
|
return info & CLS_META;
|
|
}
|
|
|
|
// NOT identical to this->ISA() when this is a metaclass
|
|
Class getMeta() {
|
|
if (isMetaClass()) return (Class)this;
|
|
else return this->ISA();
|
|
}
|
|
|
|
// May be unaligned depending on class's ivars.
|
|
uint32_t unalignedInstanceStart() {
|
|
// This is not simply superclass->instance_size.
|
|
// superclass->instance_size is padded to its sizeof() boundary,
|
|
// which may envelop one of this class's ivars.
|
|
// That in turn would break ARC-style ivar layouts.
|
|
// Instead, we use the address of this class's first ivar when possible.
|
|
if (!superclass) return 0;
|
|
if (!ivars || ivars->ivar_count == 0) return superclass->instance_size;
|
|
return ivars->ivar_list[0].ivar_offset;
|
|
}
|
|
|
|
// Class's instance start rounded up to a pointer-size boundary.
|
|
// This is used for ARC layout bitmaps.
|
|
uint32_t alignedInstanceStart() {
|
|
return word_align(unalignedInstanceStart());
|
|
}
|
|
|
|
|
|
// May be unaligned depending on class's ivars.
|
|
uint32_t unalignedInstanceSize() {
|
|
return instance_size;
|
|
}
|
|
|
|
// Class's ivar size rounded up to a pointer-size boundary.
|
|
uint32_t alignedInstanceSize() {
|
|
return word_align(unalignedInstanceSize());
|
|
}
|
|
|
|
size_t instanceSize(size_t extraBytes) {
|
|
size_t size = alignedInstanceSize() + extraBytes;
|
|
// CF requires all objects be at least 16 bytes.
|
|
if (size < 16) size = 16;
|
|
return size;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
#include "hashtable2.h"
|
|
|
|
__BEGIN_DECLS
|
|
|
|
#define oldprotocol(proto) ((struct old_protocol *)proto)
|
|
#define oldmethod(meth) ((struct old_method *)meth)
|
|
#define oldcategory(cat) ((struct old_category *)cat)
|
|
#define oldivar(ivar) ((struct old_ivar *)ivar)
|
|
#define oldproperty(prop) ((struct old_property *)prop)
|
|
|
|
extern NXHashTable *class_hash;
|
|
|
|
extern void unload_class(Class cls);
|
|
|
|
extern IMP lookupNamedMethodInMethodList(struct old_method_list *mlist, const char *meth_name);
|
|
extern void _objc_insertMethods(Class cls, struct old_method_list *mlist, struct old_category *cat);
|
|
extern void _objc_removeMethods(Class cls, struct old_method_list *mlist);
|
|
extern void _objc_flush_caches (Class cls);
|
|
extern bool _class_addProperties(Class cls, struct old_property_list *additions);
|
|
extern bool _class_hasLoadMethod(Class cls);
|
|
extern void change_class_references(Class imposter, Class original, Class copy, bool changeSuperRefs);
|
|
extern void flush_marked_caches(void);
|
|
extern void set_superclass(Class cls, Class supercls, bool cls_is_new);
|
|
extern void try_free(const void *p);
|
|
|
|
extern struct old_property *property_list_nth(const struct old_property_list *plist, uint32_t i);
|
|
extern struct old_property **copyPropertyList(struct old_property_list *plist, unsigned int *outCount);
|
|
|
|
extern struct objc_method_description * lookup_protocol_method(struct old_protocol *proto, SEL aSel, bool isRequiredMethod, bool isInstanceMethod, bool recursive);
|
|
|
|
// used by flush_caches outside objc-cache.m
|
|
extern void _cache_flush(Class cls);
|
|
#ifdef OBJC_INSTRUMENTED
|
|
extern unsigned int LinearFlushCachesCount;
|
|
extern unsigned int LinearFlushCachesVisitedCount;
|
|
extern unsigned int MaxLinearFlushCachesVisitedCount;
|
|
extern unsigned int NonlinearFlushCachesCount;
|
|
extern unsigned int NonlinearFlushCachesClassCount;
|
|
extern unsigned int NonlinearFlushCachesVisitedCount;
|
|
extern unsigned int MaxNonlinearFlushCachesVisitedCount;
|
|
extern unsigned int IdealFlushCachesCount;
|
|
extern unsigned int MaxIdealFlushCachesCount;
|
|
#endif
|
|
|
|
__END_DECLS
|
|
|
|
#endif
|