OSDN Git Service

2012-03-08 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / libobjc / methods.c
1 /* GNU Objective C Runtime method related functions.
2    Copyright (C) 2010 Free Software Foundation, Inc.
3    Contributed by Nicola Pero
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 3, or (at your option) any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14 details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 <http://www.gnu.org/licenses/>.  */
24
25 #include "objc-private/common.h"
26 #include "objc/runtime.h"
27 #include "objc-private/module-abi-8.h" /* For runtime structures.   */
28 #include "objc/thr.h"
29 #include "objc-private/runtime.h"      /* For __objc_runtime_mutex.  */
30 #include <stdlib.h>                    /* For malloc.  */
31
32 SEL
33 method_getName (struct objc_method * method)
34 {
35   if (method == NULL)
36     return NULL;
37
38   return method->method_name;
39 }
40
41 const char *
42 method_getTypeEncoding (struct objc_method * method)
43 {
44   if (method == NULL)
45     return NULL;
46
47   return method->method_types;
48 }
49
50 IMP
51 method_getImplementation (struct objc_method * method)
52 {
53   if (method == NULL)
54     return NULL;
55
56   return method->method_imp;
57 }
58
59 struct objc_method_description *
60 method_getDescription (struct objc_method * method)
61 {
62   /* Note that the following returns NULL if method is NULL, which is
63      fine.  */
64   return (struct objc_method_description *)method;
65 }
66
67 struct objc_method **
68 class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods)
69 {
70   unsigned int count = 0;
71   struct objc_method **returnValue = NULL;
72   struct objc_method_list* method_list;
73
74   if (class_ == Nil)
75     {
76       if (numberOfReturnedMethods)
77         *numberOfReturnedMethods = 0;
78       return NULL;
79     }
80
81   /* Lock the runtime mutex because the class methods may be
82      concurrently modified.  */
83   objc_mutex_lock (__objc_runtime_mutex);
84
85   /* Count how many methods we have.  */
86   method_list = class_->methods;
87
88   while (method_list)
89     {
90       count = count + method_list->method_count;
91       method_list = method_list->method_next;
92     }
93
94   if (count != 0)
95     {
96       unsigned int i = 0;
97       
98       /* Allocate enough memory to hold them.  */
99       returnValue 
100         = (struct objc_method **)(malloc (sizeof (struct objc_method *) 
101                                           * (count + 1)));
102       
103       /* Copy the methods.  */
104       method_list = class_->methods;
105       
106       while (method_list)
107         {
108           int j;
109           for (j = 0; j < method_list->method_count; j++)
110             {
111               returnValue[i] = &(method_list->method_list[j]);
112               i++;
113             }
114           method_list = method_list->method_next;
115         }
116       
117       returnValue[i] = NULL;
118     }
119
120   objc_mutex_unlock (__objc_runtime_mutex);
121
122   if (numberOfReturnedMethods)
123     *numberOfReturnedMethods = count;
124
125   return returnValue;
126 }
127
128 IMP
129 method_setImplementation (struct objc_method * method, IMP implementation)
130 {
131   IMP old_implementation;
132
133   if (method == NULL  ||  implementation == NULL)
134     return NULL;
135
136   /* We lock the runtime mutex so that concurrent calls to change the
137      same method won't conflict with each other.  */
138   objc_mutex_lock (__objc_runtime_mutex);
139
140   old_implementation = method->method_imp;
141   method->method_imp = implementation;
142
143   /* That was easy :-).  But now we need to find all classes that use
144      this method, and update the IMP in the dispatch tables.  */
145   __objc_update_classes_with_methods (method, NULL);
146
147   objc_mutex_unlock (__objc_runtime_mutex);
148
149   return old_implementation;
150 }
151
152 void
153 method_exchangeImplementations (struct objc_method * method_a, struct objc_method * method_b)
154 {
155   IMP old_implementation_a;
156   IMP old_implementation_b;
157
158   if (method_a == NULL  ||  method_b == NULL)
159     return;
160
161   /* We lock the runtime mutex so that concurrent calls to exchange
162      similar methods won't conflict with each other.  Each of them
163      should be atomic.  */
164   objc_mutex_lock (__objc_runtime_mutex);
165
166   old_implementation_a = method_a->method_imp;
167   old_implementation_b = method_b->method_imp;
168
169   method_a->method_imp = old_implementation_b;
170   method_b->method_imp = old_implementation_a;
171
172   /* That was easy :-).  But now we need to find all classes that use
173      these methods, and update the IMP in the dispatch tables.  */
174   __objc_update_classes_with_methods (method_a, method_b);
175
176   objc_mutex_unlock (__objc_runtime_mutex);
177 }