OSDN Git Service

* sh.c (sh_gimplify_va_arg_expr): Don't call pass_by_reference.
[pf3gnuchains/gcc-fork.git] / libobjc / sendmsg.c
index 06fc9ba..f0b5bbb 100644 (file)
@@ -1,21 +1,21 @@
 /* GNU Objective C Runtime message lookup 
    Copyright (C) 1993, 1995, 1996, 1997, 1998,
-   2001, 2002 Free Software Foundation, Inc.
+   2001, 2002, 2004 Free Software Foundation, Inc.
    Contributed by Kresten Krab Thorup
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify it under the
+GCC is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2, or (at your option) any later version.
 
-GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.
 
 You should have received a copy of the GNU General Public License along with
-GNU CC; see the file COPYING.  If not, write to the Free Software
+GCC; see the file COPYING.  If not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
@@ -25,13 +25,19 @@ Boston, MA 02111-1307, USA.  */
    however invalidate any other reasons why the executable file might be
    covered by the GNU General Public License.  */
 
+/* FIXME: This file has no business including tm.h.  */
+/* FIXME: This should be using libffi instead of __builtin_apply
+   and friends.  */
+
 #include "tconfig.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "runtime.h"
 #include "sarray.h"
 #include "encoding.h"
 #include "runtime-info.h"
 
-/* this is how we hack STRUCT_VALUE to be 1 or 0 */
+/* This is how we hack STRUCT_VALUE to be 1 or 0.   */
 #define gen_rtx(args...) 1
 #define gen_rtx_MEM(args...) 1
 #define gen_rtx_REG(args...) 1
@@ -76,10 +82,10 @@ static id
 __objc_block_forward (id, SEL, ...);
 static Method_t search_for_method_in_hierarchy (Class class, SEL sel);
 Method_t search_for_method_in_list (MethodList_t list, SEL op);
-id nil_method (id, SEL, ...);
+id nil_method (id, SEL);
 
 /* Given a selector, return the proper forwarding implementation. */
-__inline__
+inline
 IMP
 __objc_get_forward_imp (SEL sel)
 {
@@ -111,10 +117,18 @@ __objc_get_forward_imp (SEL sel)
 }
 
 /* Given a class and selector, return the selector's implementation.  */
-__inline__
+inline
 IMP
 get_imp (Class class, SEL sel)
 {
+  /* In a vanilla implementation we would first check if the dispatch
+     table is installed.  Here instead, to get more speed in the
+     standard case (that the dispatch table is installed) we first try
+     to get the imp using brute force.  Only if that fails, we do what
+     we should have been doing from the very beginning, that is, check
+     if the dispatch table needs to be installed, install it if it's
+     not installed, and retrieve the imp from the table if it's
+     installed.  */
   void *res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
   if (res == 0)
     {
@@ -123,7 +137,16 @@ get_imp (Class class, SEL sel)
        {
          /* The dispatch table needs to be installed. */
          objc_mutex_lock (__objc_runtime_mutex);
-         __objc_install_dispatch_table_for_class (class);
+
+          /* Double-checked locking pattern: Check
+             __objc_uninstalled_dtable again in case another thread
+             installed the dtable while we were waiting for the lock
+             to be released.  */
+         if (class->dtable == __objc_uninstalled_dtable)
+           {
+             __objc_install_dispatch_table_for_class (class);
+           }
+
          objc_mutex_unlock (__objc_runtime_mutex);
          /* Call ourselves with the installed dispatch table
             and get the real method */
@@ -131,10 +154,22 @@ get_imp (Class class, SEL sel)
        }
       else
        {
-         /* The dispatch table has been installed so the
-            method just doesn't exist for the class.
-            Return the forwarding implementation. */
-         res = __objc_get_forward_imp (sel);
+         /* The dispatch table has been installed.  */
+
+         /* Get the method from the dispatch table (we try to get it
+           again in case another thread has installed the dtable just
+           after we invoked sarray_get_safe, but before we checked
+           class->dtable == __objc_uninstalled_dtable).
+         */
+         res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
+         if (res == 0)
+           {
+             /* The dispatch table has been installed, and the method
+                is not in the dispatch table.  So the method just
+                doesn't exist for the class.  Return the forwarding
+                implementation. */
+             res = __objc_get_forward_imp (sel);
+           }
        }
     }
   return res;
@@ -143,7 +178,7 @@ get_imp (Class class, SEL sel)
 /* Query if an object can respond to a selector, returns YES if the
 object implements the selector otherwise NO.  Does not check if the
 method can be forwarded. */
-__inline__
+inline
 BOOL
 __objc_responds_to (id object, SEL sel)
 {
@@ -153,7 +188,10 @@ __objc_responds_to (id object, SEL sel)
   if (object->class_pointer->dtable == __objc_uninstalled_dtable)
     {
       objc_mutex_lock (__objc_runtime_mutex);
-      __objc_install_dispatch_table_for_class (object->class_pointer);
+      if (object->class_pointer->dtable == __objc_uninstalled_dtable)
+       {
+         __objc_install_dispatch_table_for_class (object->class_pointer);
+       }
       objc_mutex_unlock (__objc_runtime_mutex);
     }
 
@@ -165,7 +203,7 @@ __objc_responds_to (id object, SEL sel)
 /* This is the lookup function.  All entries in the table are either a 
    valid method *or* zero.  If zero then either the dispatch table
    needs to be installed or it doesn't exist and forwarding is attempted. */
-__inline__
+inline
 IMP
 objc_msg_lookup (id receiver, SEL op)
 {
@@ -188,16 +226,25 @@ objc_msg_lookup (id receiver, SEL op)
            }
          else
            {
-             /* The dispatch table has been installed so the
-                method just doesn't exist for the class.
-                Attempt to forward the method. */
-             result = __objc_get_forward_imp (op);
+             /* The dispatch table has been installed.  Check again
+                if the method exists (just in case the dispatch table
+                has been installed by another thread after we did the
+                previous check that the method exists).
+             */
+             result = sarray_get_safe (receiver->class_pointer->dtable,
+                                       (sidx)op->sel_id);
+             if (result == 0)
+               {
+                 /* If the method still just doesn't exist for the
+                    class, attempt to forward the method. */
+                 result = __objc_get_forward_imp (op);
+               }
            }
        }
       return result;
     }
   else
-    return nil_method;
+    return (IMP)nil_method;
 }
 
 IMP
@@ -206,7 +253,7 @@ objc_msg_lookup_super (Super_t super, SEL sel)
   if (super->self)
     return get_imp (super->class, sel);
   else
-    return nil_method;
+    return (IMP)nil_method;
 }
 
 int method_get_sizeof_arguments (Method *);
@@ -235,13 +282,16 @@ __objc_init_dispatch_tables ()
 static void
 __objc_init_install_dtable (id receiver, SEL op __attribute__ ((__unused__)))
 {
+  objc_mutex_lock (__objc_runtime_mutex);
+  
   /* This may happen, if the programmer has taken the address of a 
      method before the dtable was initialized... too bad for him! */
   if (receiver->class_pointer->dtable != __objc_uninstalled_dtable)
-    return;
-
-  objc_mutex_lock (__objc_runtime_mutex);
-
+    {
+      objc_mutex_unlock (__objc_runtime_mutex);
+      return;
+    }
+  
   if (CLS_ISCLASS (receiver->class_pointer))
     {
       /* receiver is an ordinary object */
@@ -415,28 +465,14 @@ __objc_update_dispatch_table_for_class (Class class)
 
    This one is only called for categories. Class objects have their
    methods installed right away, and their selectors are made into
-   SEL's by the function __objc_register_selectors_from_class. */ 
+   SEL's by the function __objc_register_selectors_from_class. */
 void
 class_add_method_list (Class class, MethodList_t list)
 {
-  int i;
-
   /* Passing of a linked list is not allowed.  Do multiple calls.  */
   assert (! list->method_next);
 
-  /* Check for duplicates.  */
-  for (i = 0; i < list->method_count; ++i)
-    {
-      Method_t method = &list->method_list[i];
-
-      if (method->method_name)  /* Sometimes these are NULL */
-       {
-         /* This is where selector names are transmogrified to SEL's */
-         method->method_name = 
-           sel_register_typed_name ((const char *) method->method_name,
-                                    method->method_types);
-       }
-    }
+  __objc_register_selectors_from_list(list);
 
   /* Add the methods to the class's method list.  */
   list->method_next = class->methods;
@@ -657,7 +693,7 @@ __objc_print_dtable_stats ()
 /* Returns the uninstalled dispatch table indicator.
  If a class' dispatch table points to __objc_uninstalled_dtable
  then that means it needs its dispatch table to be installed. */
-__inline__
+inline
 struct sarray *
 objc_get_uninstalled_dtable ()
 {