X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/931d76980ee9b20d6b3874de126bea74a92a4f9c..be19c556083cc197be55acbd05db76ec6dc2e0c4:/include/wx/cocoa/objc/objc_uniquifying.h diff --git a/include/wx/cocoa/objc/objc_uniquifying.h b/include/wx/cocoa/objc/objc_uniquifying.h index db7c17aa1e..a8a10e7a55 100644 --- a/include/wx/cocoa/objc/objc_uniquifying.h +++ b/include/wx/cocoa/objc/objc_uniquifying.h @@ -15,6 +15,28 @@ #ifndef __WX_COCOA_OBJC_CLASS_H__ #define __WX_COCOA_OBJC_CLASS_H__ +/* A note about this header: +Nothing in here is guaranteed to exist in future versions of wxCocoa. There +are other ways of adding Objective-C classes at runtime and a future wxCocoa +might use these instead of this ugly hack. You may use this header file in +your own wxCocoa code if you need your own Objective-C classes to be +unqiuified. + +You cannot turn this on for 64-bit mode. It will not compile due to opaque +Objective-C data structures and it is not needed because it is a workaround +for a bug that does not exist in the 64-bit runtime. + +You should not use this when wxCocoa is built as a dynamic library. This has +only been tested for the case when wxCocoa is built as a static library and +statically linked to user code to form a loadable bundle (e.g. a Cocoa plugin). +It forces each plugin (when multiple wxCocoa-using plugins are used) to use +its own internal Objective-C classes which is desirable when wxCocoa is +statically linked to the rest of the code. + +Do not use uniquifying on your principal class. That one should be named +differently for different bundles. + */ + #if wxUSE_OBJC_UNIQUIFYING // objc_getClass and stuff @@ -61,6 +83,32 @@ struct UniquifiedName } }; +/*! @function HidePointerFromGC + @abstract Returns an l-value whose location the compiler cannot know. + @discussion + The compiler-generated Objective-C class structures are located in the static data area. + They are by design Objective-C objects in their own right which makes the compiler issue + write barriers as if they were located in the GC-managed heap as most Objective-C objects. + + By accepting and returning a reference to any pointer type we can set any i-var of an + Objective-C object that is a pointer to another Objective-C object without the compiler + generating an objc_assign_ivar write barrier. It will instad generate an + objc_assign_strongCast write barrier which is the appropriate write-barrier when assigning + pointers to Objective-C objects located in unknown memory. + + For instance: + Class *someClass = ...; + HidePointerFromGC(someClass->isa) = ...; + */ +template +inline ObjcType * & HidePointerFromGC(ObjcType * &p) __attribute__((always_inline)); + +template +inline ObjcType * & HidePointerFromGC(ObjcType * &p) +{ + return p; +} + template class wxObjcClassInitializer { @@ -109,9 +157,9 @@ private: // In any object hierarchy a metaclass's metaclass is always the root class's metaclass // Therefore, our superclass's metaclass's metaclass should already be the root class's metaclass - theClassData.isa->isa = theClassData.super_class->isa->isa; + HidePointerFromGC(theClassData.isa->isa) = theClassData.super_class->isa->isa; // A metaclass's superclass is always the superclass's metaclass. - theClassData.isa->super_class = theClassData.super_class->isa; + HidePointerFromGC(theClassData.isa->super_class) = theClassData.super_class->isa; // Fix up the compiler generated metaclass struct to use the new name theClassData.isa->name = sm_theUniquifiedClassName; @@ -157,7 +205,7 @@ struct objc_class* wx_GetObjcClass_ ## ObjcClass(); // _s_objc_class_ptr_ObjcClass: // .long L_OBJC_CLASS_ObjcClass // Once that static symbol is defined, the function implementation is easy for GCC to generate. -// Do note that return &s_objc_class_data_ObjcClass won't work. The code is wrong in the case. +// Do note that return &s_objc_class_data_ObjcClass won't work. The code is wrong in this case. #define WX_IMPLEMENT_OBJC_GET_COMPILED_CLASS(ObjcClass) \ extern "C" objc_class s_objc_class_data_ ## ObjcClass asm("L_OBJC_CLASS_" #ObjcClass); \ static objc_class * s_objc_class_ptr_ ## ObjcClass = &s_objc_class_data_ ## ObjcClass; \ @@ -230,7 +278,7 @@ inline objc_class * wxObjcCompilerInformation::GetCompiledClass() \ } // TODO: __x86_64__, __ppc64__ -#else // Can't wrie inline asm to bust into __OBJC segment +#else // Can't write inline asm to bust into __OBJC segment // This won't be used since the generic implementation takes precedence. #warning "Don't know how to implement wxObjcCompilerInformation::GetCompiledClass on this platform" @@ -248,6 +296,16 @@ inline objc_class * wxObjcCompilerInformation::GetCompiledClass() \ return objc_getClass(#ObjcSuperClass); \ } +// The WX_IMPLEMENT_OBJC_GET_UNIQUIFIED_SUPERCLASS macro implements the template +// specialization to get the superclass when the superclass is another uniquified +// Objective-C class. +#define WX_IMPLEMENT_OBJC_GET_UNIQUIFIED_SUPERCLASS(ObjcClass,ObjcSuperClass) \ + template <> \ + inline objc_class* wxObjcCompilerInformation::GetSuperclass() \ + { \ + return wx_GetObjcClass_ ## ObjcSuperClass(); \ + } + // The WX_IMPLEMENT_OBJC_CLASS_NAME macro implements the template specialization // of the sm_theClassName constant. As soon as this specialization is in place // sizeof(sm_theClassName) will return the number of bytes at compile time. @@ -255,17 +313,31 @@ inline objc_class * wxObjcCompilerInformation::GetCompiledClass() \ template <> \ const char wxObjcCompilerInformation::sm_theClassName[] = #ObjcClass; -// The WX_IMPLEMENT_GET_OBJC_CLASS macro combines all of these together and adds -// a global wx_GetObjcClass_ObjcClass() function. -#define WX_IMPLEMENT_GET_OBJC_CLASS(ObjcClass,ObjcSuperClass) \ - WX_IMPLEMENT_OBJC_GET_COMPILED_CLASS(ObjcClass) \ - WX_IMPLEMENT_OBJC_GET_SUPERCLASS(ObjcClass,ObjcSuperClass) \ - WX_IMPLEMENT_OBJC_CLASS_NAME(ObjcClass) \ +// The WX_IMPLEMENT_OBJC_GET_OBJC_CLASS macro is the final one that actually provides +// the wx_GetObjcClass_XXX function that will be called in lieu of asking the Objective-C +// runtime for the class. All the others are really machinery to make this happen. +#define WX_IMPLEMENT_OBJC_GET_OBJC_CLASS(ObjcClass) \ objc_class* wx_GetObjcClass_ ## ObjcClass() \ { \ return wxObjcClassInitializer::Get(); \ } +// The WX_IMPLEMENT_GET_OBJC_CLASS macro combines all of these together +// for the case when the superclass is a non-uniquified class. +#define WX_IMPLEMENT_GET_OBJC_CLASS(ObjcClass,ObjcSuperClass) \ + WX_IMPLEMENT_OBJC_GET_COMPILED_CLASS(ObjcClass) \ + WX_IMPLEMENT_OBJC_GET_SUPERCLASS(ObjcClass,ObjcSuperClass) \ + WX_IMPLEMENT_OBJC_CLASS_NAME(ObjcClass) \ + WX_IMPLEMENT_OBJC_GET_OBJC_CLASS(ObjcClass) + +// The WX_IMPLEMENT_GET_OBJC_CLASS_WITH_UNIQUIFIED_SUPERCLASS macro combines all +// of these together for the case when the superclass is another uniquified class. +#define WX_IMPLEMENT_GET_OBJC_CLASS_WITH_UNIQUIFIED_SUPERCLASS(ObjcClass,ObjcSuperClass) \ + WX_IMPLEMENT_OBJC_GET_COMPILED_CLASS(ObjcClass) \ + WX_IMPLEMENT_OBJC_GET_UNIQUIFIED_SUPERCLASS(ObjcClass,ObjcSuperClass) \ + WX_IMPLEMENT_OBJC_CLASS_NAME(ObjcClass) \ + WX_IMPLEMENT_OBJC_GET_OBJC_CLASS(ObjcClass) + // The WX_GET_OBJC_CLASS macro is intended to wrap the class name when the class // is used as a message receiver (e.g. for calling class methods). When // class name uniquifying is used, this calls the global function implemented @@ -278,6 +350,8 @@ inline objc_class * wxObjcCompilerInformation::GetCompiledClass() \ #define WX_DECLARE_GET_OBJC_CLASS(ObjcClass,ObjcSuperClass) // Define WX_IMPLEMENT_GET_OBJC_CLASS as nothing #define WX_IMPLEMENT_GET_OBJC_CLASS(ObjcClass,ObjcSuperClass) +// Define WX_IMPLEMENT_GET_OBJC_CLASS_WITH_UNIQUIFIED_SUPERCLASS as nothing +#define WX_IMPLEMENT_GET_OBJC_CLASS_WITH_UNIQUIFIED_SUPERCLASS(ObjcClass,ObjcSuperClass) // Define WX_GET_OBJC_CLASS macro to output the class name and let the compiler do the normal thing // The WX_GET_OBJC_CLASS macro is intended to wrap the class name when the class