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