xref: /dragonfly/contrib/gcc-4.7/libobjc/methods.c (revision e4b17023)
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
method_getName(struct objc_method * method)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 *
method_getTypeEncoding(struct objc_method * method)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
method_getImplementation(struct objc_method * method)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 *
method_getDescription(struct objc_method * method)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 **
class_copyMethodList(Class class_,unsigned int * numberOfReturnedMethods)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
method_setImplementation(struct objc_method * method,IMP implementation)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
method_exchangeImplementations(struct objc_method * method_a,struct objc_method * method_b)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 }
178