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