(OBJC_VERSION): Increment version.
authorRichard Kenner <kenner@gcc.gnu.org>
Sat, 15 Mar 1997 12:56:13 +0000 (07:56 -0500)
committerRichard Kenner <kenner@gcc.gnu.org>
Sat, 15 Mar 1997 12:56:13 +0000 (07:56 -0500)
(objc_send_load, __objc_send_load): New functions.
(__objc_send_message_in_list): New function.
(__objc_force_linking): New function.
(__objc_exec_class): Don't call _objc_load_callback here.
(__objc_exec_class): Access statics from their new place in the defs variable.

From-SVN: r13709

gcc/objc/init.c

index b95f38b..fe64bf4 100644 (file)
@@ -27,7 +27,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* The version number of this runtime.  This must match the number 
    defined in gcc (objc-act.c) */
-#define OBJC_VERSION 7
+#define OBJC_VERSION 8
 #define PROTOCOL_VERSION 2
 
 /* This list contains all modules currently loaded into the runtime */
@@ -67,6 +67,25 @@ extern SEL
 __sel_register_typed_name (const char *name, const char *types, 
                           struct objc_selector *orig, BOOL is_const);
 
+/* Send +load to all classes and categories from a module that implement
+   this method */
+static void __objc_send_load(Module_t module);
+
+/* This list contains all the classes in the runtime system for whom their
+   superclasses are not yet know to the runtime. */
+static struct objc_list* unresolved_classes = 0;
+
+/* Static function used to references the Object and NXConstantString classes. */
+static void
+__objc_force_linking (void)
+{
+  extern void __objc_linking (void);
+  __objc_linking ();
+
+  /* Call the function to avoid compiler warning */
+  __objc_force_linking ();
+}
+
 /* Run through the statics list, removing modules as soon as all its statics
    have been initialized.  */
 static void
@@ -143,6 +162,10 @@ __objc_exec_class (Module_t module)
   /* The symbol table (defined in objc-api.h) generated by gcc */
   Symtab_t symtab = module->symtab;
 
+  /* The statics in this module */
+  struct objc_static_instances **statics
+    = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
+
   /* Entry used to traverse hash lists */
   struct objc_list** cell;
 
@@ -196,6 +219,7 @@ __objc_exec_class (Module_t module)
   for (i = 0; i < symtab->cls_def_cnt; ++i)
     {
       Class class = (Class) symtab->defs[i];
+      const char* superclass = (char*)class->super_class;
 
       /* Make sure we have what we think.  */
       assert (CLS_ISCLASS(class));
@@ -216,8 +240,10 @@ __objc_exec_class (Module_t module)
       if (class->protocols)
        __objc_init_protocols (class->protocols);
 
-      if (_objc_load_callback)
-       _objc_load_callback(class, 0);
+      /* Check to see if the superclass is known in this point. If it's not
+        add the class to the unresolved_classes list. */
+      if (superclass && !objc_lookup_class (superclass))
+       unresolved_classes = list_cons (class, unresolved_classes);
    }
 
   /* Process category information from the module.  */
@@ -260,8 +286,8 @@ __objc_exec_class (Module_t module)
        }
     }
 
-  if (module->statics)
-    uninitialized_statics = list_cons (module->statics, uninitialized_statics);
+  if (statics)
+    uninitialized_statics = list_cons (statics, uninitialized_statics);
   if (uninitialized_statics)
     objc_init_statics ();
 
@@ -306,9 +332,118 @@ __objc_exec_class (Module_t module)
       unclaimed_proto_list = 0;
     }
 
+  objc_send_load ();
+
   objc_mutex_unlock(__objc_runtime_mutex);
 }
 
+void objc_send_load (void)
+{
+  if (!__objc_module_list)
+    return;
+  /* Try to find out if all the classes loaded so far also have their
+     superclasses known to the runtime. We suppose that the objects that are
+     allocated in the +load method are in general of a class declared in the
+     same module. */
+  if (unresolved_classes)
+    {
+      Class class = unresolved_classes->head;
+
+      while (objc_lookup_class ((char*)class->super_class))
+       {
+         list_remove_head (&unresolved_classes);
+         if (unresolved_classes)
+           class = unresolved_classes->head;
+         else
+           break;
+       }
+
+      /*
+       * If we still have classes for which we don't have yet their super
+       * classes known to the runtime we don't send the +load messages.
+       */
+      if (unresolved_classes)
+       return;
+    }
+
+  /* Special check to allow sending messages to constant strings in +load
+     methods. If the class is not yet known, even if all the classes are known,
+     delay sending of +load. */
+  if (!objc_lookup_class ("NXConstantString"))
+    return;
+
+  /* Iterate over all modules in the __objc_module_list and call on them the
+     __objc_send_load function that sends the +load message. */
+  list_mapcar (__objc_module_list, (void(*)(void*))__objc_send_load);
+  list_free (__objc_module_list);
+  __objc_module_list = NULL;
+}
+
+static void
+__objc_send_message_in_list (MethodList_t method_list, id object, SEL op)
+{
+  while (method_list)
+    {
+      int i;
+
+      /* Search the method list. */
+      for (i = 0; i < method_list->method_count; i++)
+       {
+         Method_t mth = &method_list->method_list[i];
+
+         if (mth->method_name && sel_eq (mth->method_name, op))
+           {
+             /* The method was found. */
+             (*mth->method_imp) (object, mth->method_name);
+             break;
+           }
+       }
+      method_list = method_list->method_next;
+    }
+}
+
+static void
+__objc_send_load(Module_t module)
+{
+  /* The runtime mutex is locked in this point */
+
+  Symtab_t symtab = module->symtab;
+  static SEL load_sel = 0;
+  int i;
+
+  if (!load_sel)
+    load_sel = sel_register_name ("load");
+
+  /* Iterate thru classes defined in this module and send them the +load
+     message if they implement it. At this point all methods defined in
+     categories were added to the corresponding class, so all the +load
+     methods of categories are in their corresponding classes. */
+  for (i = 0; i < symtab->cls_def_cnt; i++)
+    {
+      Class class = (Class) symtab->defs[i];
+      MethodList_t method_list = class->class_pointer->methods;
+
+      __objc_send_message_in_list (method_list, (id)class, load_sel);
+
+      /* Call the _objc_load_callback for this class. */
+      if (_objc_load_callback)
+       _objc_load_callback(class, 0);
+    }
+
+  /* Call the _objc_load_callback for categories. Don't register the instance
+     methods as class methods for categories to root classes since they were
+     already added in the class. */
+  for (i = 0; i < symtab->cat_def_cnt; i++)
+    {
+      Category_t category = symtab->defs[i + symtab->cls_def_cnt];
+      Class class = objc_lookup_class (category->class_name);
+      
+      if (_objc_load_callback)
+       _objc_load_callback(class, category);
+    }
+}
+
 /* Sanity check the version of gcc used to compile `module'*/
 static void init_check_module_version(Module_t module)
 {