bug-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFA/base] GSObjCRuntime (Part 3: Access functions to Method structu


From: David Ayers
Subject: Re: [RFA/base] GSObjCRuntime (Part 3: Access functions to Method structures)
Date: Wed, 11 Jun 2003 16:21:34 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030507

Based on Richard's comments, I've decided to name new functions which

- are *not* +load-safe with GSObjC-prefix,
- *are* +load-safe with a simple GS-prefix,
- implement a +load-safe variants of GSObjC functions with GSC-prefix.

This patch only includes new functions which are +load-safe. Independant of the name the new functions explicitly state whether they are +load-safe or not. A follow up patch will contain further documentation about which functions are +load-safe and which are not.

If someone comes up with a better solution please speak up now. :-)

OK, here it is:

       * Headers/gnustep/base/objc-gnu2next.h: Remove simple mappings for
       class_get_class_method they cannot work due to different
       parameter expectations.  Added mapping from NeXT->GNU runtime.
       The other way does not work.  Added simple mapping for internal
       flush function __objc_update_dispatch_table_for_class and
       _objc_flush_caches.

       * Headers/gnustep/base/GSObjCRuntime.h/m:
       Added typedef for GSMethod.
       (GSGetInstanceMethod): New function.
       (GSGetClassMethod): Ditto.
       (GSGetInstanceMethodNotInherited): Ditto.
       (GSGetClassMethodNotInherited): Ditto.
       (GSFlushMethodCacheForClass): Ditto.
       (flush_method_cache_for_class): Removed function which is replaced
       by GSFlushMethodCacheForClass.
       (GSObjCGetMethod): Removed function which is replaced by
       GSGetInstanceMethod and GSGetClassMethod.
       (GSObjCReplaceMethod): Removed function.

Please note that I have added (or rather renamed and exposed) a function to invalidate the method cache a class keeps. This patch also includes a cleanup of objc-gnu2next.h which contained an invalid mapping for class_get_class_method/call_getClassMethod. It also removes the superceded imlementations of my previos extensions. Once this patch is committed, a corresponding patch for GDL2 will also be committed.

Save objections, I will commit this in a couple of days.


Cheers,
David

Index: Headers/gnustep/base/GSObjCRuntime.h
===================================================================
RCS file: 
/cvsroot/gnustep/gnustep/core/base/Headers/gnustep/base/GSObjCRuntime.h,v
retrieving revision 1.16
diff -u -r1.16 GSObjCRuntime.h
--- Headers/gnustep/base/GSObjCRuntime.h        7 Jun 2003 17:37:02 -0000       
1.16
+++ Headers/gnustep/base/GSObjCRuntime.h        11 Jun 2003 13:51:54 -0000
@@ -1,5 +1,5 @@
 /** Interface to ObjC runtime for GNUStep
-   Copyright (C) 1995, 1997, 2000, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1997, 2000, 2002, 2003 Free Software Foundation, Inc.
 
    Written by:  Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
    Date: 1995
@@ -113,6 +113,14 @@
 
 #include <gnustep/base/objc-gnu2next.h>
 
+/*
+ * This section includes runtime functions
+ * to query and manipulate the ObjC runtime structures.
+ * These functions take care to not use ObjC code so
+ * that they can safely be used in +(void)load implementations
+ * where applicable.
+ */
+
 #define GS_STATIC_INLINE static inline
 
 /*
@@ -261,6 +269,87 @@
     return 0;
   return sel_get_type(this);
 }
+
+
+/*
+ * Unfortunately the definition of the symbol 'Method'
+ * is incompatible between the GNU and NeXT/Apple runtimes.
+ * We introduce GSMethod to allow portability.
+ */
+typedef struct objc_method *GSMethod;
+
+/**
+ * Returns the pointer to the instance method structure
+ * for the selector in the specified class.  This function searches
+ * the specified class and its superclasses.<br/>
+ * To obtain the implementation pointer IMP use returnValue->method_imp
+ * which should be safe across all runtimes.<br/>
+ * It should be safe to use this function in +load implementations.
+ */
+GS_STATIC_INLINE GSMethod
+GSGetInstanceMethod(Class class, SEL sel)
+{
+  return class_get_instance_method(class, sel);
+}
+
+/**
+ * Returns the pointer to the instance method structure
+ * for the selector in the specified class.  This function searches
+ * the specified class and its superclasses.<br/>
+ * To obtain the implementation pointer IMP use returnValue->method_imp
+ * which should be safe across all runtimes.<br/>
+ * It should be safe to use this function in +load implementations.
+ */
+GS_STATIC_INLINE GSMethod
+GSGetClassMethod(Class class, SEL sel)
+{
+  /*
+    We do not rely on the mapping supplied in objc_gnu2next.h
+    because we want to be explicit about the fact 
+    that the expected parameters are different.
+    Therefor we refrain from simply using class_getClassMethod().
+  */
+#ifdef NeXT_RUNTIME
+  return class_getClassMethod(class, sel);
+#else
+  return class_get_class_method(class->class_pointer, sel);
+#endif
+}
+
+/**
+ * Returns the pointer to the instance method structure
+ * for the selector in the specified class.  This function only searches
+ * the specified class and not its superclasses.<br/>
+ * To obtain the implementation pointer IMP use returnValue->method_imp
+ * which should be safe across all runtimes.<br/>
+ * It should be safe to use this function in +load implementations.
+ */
+GS_EXPORT GSMethod
+GSGetInstanceMethodNotInherited(Class class, SEL sel);
+
+/**
+ * Returns the pointer to the class method structure
+ * for the selector in the specified class.  This function only searches
+ * the specified class and not its superclasses.<br/>
+ * To obtain the implementation pointer IMP use returnValue->method_imp
+ * which should be safe across all runtimes.<br/>
+ * It should be safe to use this function in +load implementations.
+ */
+GS_EXPORT GSMethod
+GSGetClassMethodNotInherited(Class class, SEL sel);
+
+/**
+ * Flushes the cached method dispatch table for the class.
+ * Call this function after any manipulations in the method structures.<br/>
+ * It should be safe to use this function in +load implementations.
+ */
+GS_STATIC_INLINE void
+GSFlushMethodCacheForClass (Class class)
+{
+  extern void __objc_update_dispatch_table_for_class (Class);
+  __objc_update_dispatch_table_for_class (class);
+}
+
 
 
 GS_STATIC_INLINE Class
Index: Headers/gnustep/base/objc-gnu2next.h
===================================================================
RCS file: 
/cvsroot/gnustep/gnustep/core/base/Headers/gnustep/base/objc-gnu2next.h,v
retrieving revision 1.38
diff -u -r1.38 objc-gnu2next.h
--- Headers/gnustep/base/objc-gnu2next.h        3 Mar 2003 10:01:29 -0000       
1.38
+++ Headers/gnustep/base/objc-gnu2next.h        11 Jun 2003 13:51:54 -0000
@@ -63,7 +63,6 @@
 
 #define class_create_instance(CLASS)   class_createInstance(CLASS, 0)
 #define class_get_instance_method      class_getInstanceMethod
-#define class_get_class_method                 class_getClassMethod
 #define class_add_method_list          class_addMethods
 #define class_set_version              class_setVersion
 #define class_get_version              class_getVersion
@@ -79,6 +78,8 @@
 #define sel_get_uid                    sel_getUid
 #define sel_eq(s1, s2)                         (s1 == s2)
 
+#define __objc_update_dispatch_table_for_class  _objc_flush_caches
+
 /* There's no support for typed sels in NeXT. These may not work */
 #define sel_get_typed_uid(_s, _t)      sel_getUid(_s)
 #define sel_get_any_typed_uid          sel_getUid
@@ -245,7 +246,6 @@
  */
 #define class_createInstance(CLASS, X) class_create_instance(CLASS)
 #define class_getInstanceMethod                class_get_instance_method
-#define class_getClassMethod           class_get_class_method 
 #define class_addMethods               class_add_method_list
 #define class_setVersion               class_set_version
 #define class_getVersion               class_get_version
@@ -259,6 +259,11 @@
 #define sel_getName                    sel_get_name
 #define sel_getUid                     sel_get_any_uid
 
+#define _objc_flush_caches              __objc_update_dispatch_table_for_class
+
+#define class_getClassMethod(CLASS, SEL)       \
+  class_get_class_method((CLASS)->class_pointer, (SEL))
+ 
 #define        class_nextMethodList(aClass,anIterator) ({\
   if (*(anIterator) == 0) \
     *((struct objc_method_list**)(anIterator)) = (aClass)->methods; \
Index: Source/Additions/GSObjCRuntime.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Source/Additions/GSObjCRuntime.m,v
retrieving revision 1.19
diff -u -r1.19 GSObjCRuntime.m
--- Source/Additions/GSObjCRuntime.m    7 Jun 2003 09:45:51 -0000       1.19
+++ Source/Additions/GSObjCRuntime.m    11 Jun 2003 13:51:54 -0000
@@ -659,65 +659,19 @@
 
 #endif /* NeXT runtime */
 
-static void
-flush_method_cache_for_class (Class class)
+/* See header for documentation. */
+GSMethod
+GSGetInstanceMethodNotInherited (Class class, SEL sel)
 {
-#if NeXT_RUNTIME
-      void _objc_flush_caches (Class);
-      _objc_flush_caches (class);
-#else
-      void __objc_update_dispatch_table_for_class (Class);
-      __objc_update_dispatch_table_for_class (class);
-#endif
+  return search_for_method_in_class (class, sel);
 }
 
-IMP
-GSObjCGetMethod (Class class, SEL sel)
+/* See header for documentation. */
+GSMethod
+GSGetClassMethodNotInhertited (Class class, SEL sel)
 {
-  struct objc_method *method;
-  IMP imp;
-
-  imp = NULL;
-  method = search_for_method_in_class (class, sel);
-
-  if (method != NULL)
-    {
-      imp = method->method_imp;
-    }
-
-  return imp;
-}
-
-IMP
-GSObjCReplaceMethod (Class class, SEL sel, IMP imp)
-{
-  struct objc_method *method;
-  IMP oImp; 
-
-  oImp = NULL;
-  method = search_for_method_in_class (class, sel);
-  if (method != NULL)
-    {
-      oImp = method->method_imp;
-      method->method_imp = imp;
-      flush_method_cache_for_class(class);
-      if (behavior_debug)
-       {
-         fprintf(stderr, "replaced implementation for %s in %s.\n",
-                 sel_get_name(sel), class->name); 
-       }
-    }
-  else
-    {
-      if (behavior_debug)
-       {
-         fprintf(stderr, "could not replaced implementation for %s in %s.\n",
-                 sel_get_name(sel), class != NULL ? class->name : "<NULL>"); 
-       }
-    }
-  return oImp;
+  return search_for_method_in_class (class->class_pointer, sel);
 }
-
 
 
 /**

reply via email to

[Prev in Thread] Current Thread [Next in Thread]