]> gcc.gnu.org Git - gcc.git/blame - gcc/objc/sendmsg.c
More system.h cutover patches:
[gcc.git] / gcc / objc / sendmsg.c
CommitLineData
c72fc2d9 1/* GNU Objective C Runtime message lookup
eb0bc1e9 2 Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
0994488a 3 Contributed by Kresten Krab Thorup
c72fc2d9
TW
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify it under the
0994488a
RK
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 2, or (at your option) any later version.
c72fc2d9
TW
10
11GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
0994488a
RK
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14details.
c72fc2d9
TW
15
16You should have received a copy of the GNU General Public License along with
0994488a 17GNU CC; see the file COPYING. If not, write to the Free Software
0af195cf
RK
18Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
c72fc2d9
TW
20
21/* As a special exception, if you link this library with files compiled with
22 GCC to produce an executable, this does not cause the resulting executable
23 to be covered by the GNU General Public License. This exception does not
24 however invalidate any other reasons why the executable file might be
25 covered by the GNU General Public License. */
26
a39d31bc 27#include "../tconfig.h"
c72fc2d9 28#include "runtime.h"
991d3e71 29#include "sarray.h"
772fa04a 30#include "encoding.h"
3ac2735b 31#include "runtime-info.h"
c72fc2d9 32
a39d31bc
KKT
33/* this is how we hack STRUCT_VALUE to be 1 or 0 */
34#define gen_rtx(args...) 1
35#define rtx int
36
14499ba4 37#if !defined(STRUCT_VALUE) || STRUCT_VALUE == 0
a39d31bc
KKT
38#define INVISIBLE_STRUCT_RETURN 1
39#else
40#define INVISIBLE_STRUCT_RETURN 0
41#endif
42
c72fc2d9 43/* The uninstalled dispatch table */
d50e6b7b 44struct sarray* __objc_uninstalled_dtable = 0; /* !T:MUTEX */
c72fc2d9
TW
45
46/* Send +initialize to class */
0994488a 47static void __objc_send_initialize(Class);
c72fc2d9 48
0994488a 49static void __objc_install_dispatch_table_for_class (Class);
c72fc2d9
TW
50
51/* Forward declare some functions */
c72fc2d9 52static void __objc_init_install_dtable(id, SEL);
ad248234
RK
53
54/* Various forwarding functions that are used based upon the
55 return type for the selector.
56 __objc_block_forward for structures.
57 __objc_double_forward for floats/doubles.
58 __objc_word_forward for pointers or types that fit in registers.
59 */
60static double __objc_double_forward(id, SEL, ...);
a39d31bc
KKT
61static id __objc_word_forward(id, SEL, ...);
62typedef struct { id many[8]; } __big;
63#if INVISIBLE_STRUCT_RETURN
64static __big
65#else
66static id
67#endif
68__objc_block_forward(id, SEL, ...);
0994488a 69static Method_t search_for_method_in_hierarchy (Class class, SEL sel);
255e0bab 70Method_t search_for_method_in_list(MethodList_t list, SEL op);
c72fc2d9
TW
71id nil_method(id, SEL, ...);
72
14499ba4
RK
73/* Given a selector, return the proper forwarding implementation. */
74__inline__
75IMP
76__objc_get_forward_imp (SEL sel)
77{
78 const char *t = sel->sel_types;
79
3ac2735b
JL
80 if (t && (*t == '[' || *t == '(' || *t == '{')
81#ifdef OBJC_MAX_STRUCT_BY_VALUE
82 && objc_sizeof_type(t) > OBJC_MAX_STRUCT_BY_VALUE
83#endif
84 )
14499ba4
RK
85 return (IMP)__objc_block_forward;
86 else if (t && (*t == 'f' || *t == 'd'))
87 return (IMP)__objc_double_forward;
88 else
89 return (IMP)__objc_word_forward;
90}
91
c72fc2d9 92/* Given a class and selector, return the selector's implementation. */
b840bfb0 93__inline__
2691a622 94IMP
0994488a 95get_imp (Class class, SEL sel)
c72fc2d9 96{
3ac2735b 97 void* res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
a39d31bc
KKT
98 if (res == 0)
99 {
14499ba4
RK
100 /* Not a valid method */
101 if(class->dtable == __objc_uninstalled_dtable)
102 {
103 /* The dispatch table needs to be installed. */
104 objc_mutex_lock(__objc_runtime_mutex);
105 __objc_install_dispatch_table_for_class (class);
106 objc_mutex_unlock(__objc_runtime_mutex);
107 /* Call ourselves with the installed dispatch table
108 and get the real method */
109 res = get_imp(class, sel);
110 }
a39d31bc 111 else
14499ba4
RK
112 {
113 /* The dispatch table has been installed so the
114 method just doesn't exist for the class.
115 Return the forwarding implementation. */
116 res = __objc_get_forward_imp(sel);
117 }
a39d31bc
KKT
118 }
119 return res;
c72fc2d9
TW
120}
121
14499ba4
RK
122/* Query if an object can respond to a selector, returns YES if the
123object implements the selector otherwise NO. Does not check if the
124method can be forwarded. */
125__inline__
126BOOL
d408c5da
KKT
127__objc_responds_to (id object, SEL sel)
128{
14499ba4
RK
129 void* res;
130
131 /* Install dispatch table if need be */
132 if (object->class_pointer->dtable == __objc_uninstalled_dtable)
a39d31bc 133 {
d50e6b7b 134 objc_mutex_lock(__objc_runtime_mutex);
a39d31bc 135 __objc_install_dispatch_table_for_class (object->class_pointer);
d50e6b7b 136 objc_mutex_unlock(__objc_runtime_mutex);
a39d31bc 137 }
14499ba4
RK
138
139 /* Get the method from the dispatch table */
3ac2735b 140 res = sarray_get_safe (object->class_pointer->dtable, (size_t) sel->sel_id);
a39d31bc 141 return (res != 0);
d408c5da
KKT
142}
143
c72fc2d9 144/* This is the lookup function. All entries in the table are either a
14499ba4
RK
145 valid method *or* zero. If zero then either the dispatch table
146 needs to be installed or it doesn't exist and forwarding is attempted. */
147__inline__
148IMP
c72fc2d9
TW
149objc_msg_lookup(id receiver, SEL op)
150{
a39d31bc 151 IMP result;
c72fc2d9 152 if(receiver)
a39d31bc 153 {
3ac2735b
JL
154 result = sarray_get_safe (receiver->class_pointer->dtable,
155 (sidx)op->sel_id);
a39d31bc
KKT
156 if (result == 0)
157 {
14499ba4
RK
158 /* Not a valid method */
159 if(receiver->class_pointer->dtable == __objc_uninstalled_dtable)
160 {
161 /* The dispatch table needs to be installed.
162 This happens on the very first method call to the class. */
163 __objc_init_install_dtable(receiver, op);
164
165 /* Get real method for this in newly installed dtable */
166 result = get_imp(receiver->class_pointer, op);
167 }
a39d31bc 168 else
14499ba4
RK
169 {
170 /* The dispatch table has been installed so the
171 method just doesn't exist for the class.
172 Attempt to forward the method. */
173 result = __objc_get_forward_imp(op);
174 }
a39d31bc
KKT
175 }
176 return result;
177 }
c72fc2d9
TW
178 else
179 return nil_method;
180}
181
182IMP
183objc_msg_lookup_super (Super_t super, SEL sel)
184{
185 if (super->self)
186 return get_imp (super->class, sel);
187 else
188 return nil_method;
189}
190
a39d31bc
KKT
191int method_get_sizeof_arguments (Method*);
192
c72fc2d9 193retval_t
772fa04a 194objc_msg_sendv(id object, SEL op, arglist_t arg_frame)
c72fc2d9 195{
772fa04a
KKT
196 Method* m = class_get_instance_method(object->class_pointer, op);
197 const char *type;
198 *((id*)method_get_first_argument (m, arg_frame, &type)) = object;
199 *((SEL*)method_get_next_argument (arg_frame, &type)) = op;
200 return __builtin_apply((apply_t)m->method_imp,
c72fc2d9 201 arg_frame,
772fa04a 202 method_get_sizeof_arguments (m));
c72fc2d9
TW
203}
204
14499ba4
RK
205void
206__objc_init_dispatch_tables()
c72fc2d9 207{
c72fc2d9 208 __objc_uninstalled_dtable
14499ba4 209 = sarray_new(200, 0);
c72fc2d9
TW
210}
211
14499ba4
RK
212/* This function is called by objc_msg_lookup when the
213 dispatch table needs to be installed; thus it is called once
214 for each class, namely when the very first message is sent to it. */
215static void
216__objc_init_install_dtable(id receiver, SEL op)
c72fc2d9 217{
c72fc2d9
TW
218 /* This may happen, if the programmer has taken the address of a
219 method before the dtable was initialized... too bad for him! */
220 if(receiver->class_pointer->dtable != __objc_uninstalled_dtable)
14499ba4 221 return;
c72fc2d9 222
d50e6b7b
RK
223 objc_mutex_lock(__objc_runtime_mutex);
224
c72fc2d9
TW
225 if(CLS_ISCLASS(receiver->class_pointer))
226 {
227 /* receiver is an ordinary object */
228 assert(CLS_ISCLASS(receiver->class_pointer));
229
230 /* install instance methods table */
231 __objc_install_dispatch_table_for_class (receiver->class_pointer);
232
233 /* call +initialize -- this will in turn install the factory
234 dispatch table if not already done :-) */
235 __objc_send_initialize(receiver->class_pointer);
236 }
237 else
238 {
239 /* receiver is a class object */
0994488a 240 assert(CLS_ISCLASS((Class)receiver));
c72fc2d9
TW
241 assert(CLS_ISMETA(receiver->class_pointer));
242
243 /* Install real dtable for factory methods */
244 __objc_install_dispatch_table_for_class (receiver->class_pointer);
a39d31bc
KKT
245
246 if (strcmp (sel_get_name (op), "initialize"))
0994488a 247 __objc_send_initialize((Class)receiver);
c72fc2d9 248 else
0994488a 249 CLS_SETINITIALIZED((Class)receiver);
c72fc2d9 250 }
d50e6b7b 251 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9 252}
c72fc2d9
TW
253
254/* Install dummy table for class which causes the first message to
255 that class (or instances hereof) to be initialized properly */
14499ba4
RK
256void
257__objc_install_premature_dtable(Class class)
c72fc2d9 258{
c72fc2d9
TW
259 assert(__objc_uninstalled_dtable);
260 class->dtable = __objc_uninstalled_dtable;
c72fc2d9
TW
261}
262
263/* Send +initialize to class if not already done */
14499ba4
RK
264static void
265__objc_send_initialize(Class class)
c72fc2d9 266{
c72fc2d9
TW
267 /* This *must* be a class object */
268 assert(CLS_ISCLASS(class));
269 assert(!CLS_ISMETA(class));
270
271 if (!CLS_ISINITIALIZED(class))
272 {
273 CLS_SETINITIALIZED(class);
274 CLS_SETINITIALIZED(class->class_pointer);
275
276 if(class->super_class)
277 __objc_send_initialize(class->super_class);
4be7cc98
RS
278
279 {
a142e7cc
RK
280 SEL op = sel_register_name ("initialize");
281 Class tmpclass = class;
282 IMP imp = 0;
4be7cc98 283
a142e7cc
RK
284 while (!imp && tmpclass) {
285 MethodList_t method_list = tmpclass->class_pointer->methods;
286
287 while(!imp && method_list) {
4be7cc98 288 int i;
a142e7cc 289 Method_t method;
4be7cc98 290
a142e7cc
RK
291 for (i=0;i<method_list->method_count;i++) {
292 method = &(method_list->method_list[i]);
7084b319
RK
293 if (method->method_name
294 && method->method_name->sel_id == op->sel_id) {
a142e7cc
RK
295 imp = method->method_imp;
296 break;
4be7cc98 297 }
a142e7cc 298 }
4be7cc98 299
4be7cc98 300 method_list = method_list->method_next;
a142e7cc 301
4be7cc98 302 }
a142e7cc
RK
303
304 tmpclass = tmpclass->super_class;
305 }
306 if (imp)
307 (*imp)((id)class, op);
308
4be7cc98 309 }
c72fc2d9 310 }
7084b319
RK
311}
312
313/* Walk on the methods list of class and install the methods in the reverse
314 order of the lists. Since methods added by categories are before the methods
315 of class in the methods list, this allows categories to substitute methods
3ac2735b
JL
316 declared in class. However if more than one category replaces the same
317 method nothing is guaranteed about what method will be used.
7084b319
RK
318 Assumes that __objc_runtime_mutex is locked down. */
319static void
320__objc_install_methods_in_dtable (Class class, MethodList_t method_list)
321{
322 int i;
323
324 if (!method_list)
325 return;
326
327 if (method_list->method_next)
328 __objc_install_methods_in_dtable (class, method_list->method_next);
329
330 for (i = 0; i < method_list->method_count; i++)
331 {
332 Method_t method = &(method_list->method_list[i]);
333 sarray_at_put_safe (class->dtable,
334 (sidx) method->method_name->sel_id,
335 method->method_imp);
336 }
337}
c72fc2d9 338
d50e6b7b 339/* Assumes that __objc_runtime_mutex is locked down. */
c72fc2d9 340static void
0994488a 341__objc_install_dispatch_table_for_class (Class class)
c72fc2d9 342{
0994488a 343 Class super;
c72fc2d9 344
d408c5da
KKT
345 /* If the class has not yet had it's class links resolved, we must
346 re-compute all class links */
347 if(!CLS_ISRESOLV(class))
348 __objc_resolve_class_links();
349
350 super = class->super_class;
351
c72fc2d9
TW
352 if (super != 0 && (super->dtable == __objc_uninstalled_dtable))
353 __objc_install_dispatch_table_for_class (super);
354
9faa82d8 355 /* Allocate dtable if necessary */
c72fc2d9
TW
356 if (super == 0)
357 {
d50e6b7b 358 objc_mutex_lock(__objc_runtime_mutex);
a39d31bc 359 class->dtable = sarray_new (__objc_selector_max_index, 0);
d50e6b7b 360 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9
TW
361 }
362 else
363 class->dtable = sarray_lazy_copy (super->dtable);
364
7084b319 365 __objc_install_methods_in_dtable (class, class->methods);
c72fc2d9
TW
366}
367
14499ba4
RK
368void
369__objc_update_dispatch_table_for_class (Class class)
c72fc2d9 370{
0994488a 371 Class next;
d50e6b7b 372 struct sarray *arr;
c72fc2d9
TW
373
374 /* not yet installed -- skip it */
c72fc2d9 375 if (class->dtable == __objc_uninstalled_dtable)
c72fc2d9
TW
376 return;
377
d50e6b7b
RK
378 objc_mutex_lock(__objc_runtime_mutex);
379
380 arr = class->dtable;
772fa04a 381 __objc_install_premature_dtable (class); /* someone might require it... */
d50e6b7b
RK
382 sarray_free (arr); /* release memory */
383
2a7c93ee
RK
384 /* could have been lazy... */
385 __objc_install_dispatch_table_for_class (class);
c72fc2d9
TW
386
387 if (class->subclass_list) /* Traverse subclasses */
388 for (next = class->subclass_list; next; next = next->sibling_class)
389 __objc_update_dispatch_table_for_class (next);
772fa04a 390
d50e6b7b 391 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9
TW
392}
393
394
395/* This function adds a method list to a class. This function is
396 typically called by another function specific to the run-time. As
d50e6b7b 397 such this function does not worry about thread safe issues.
c72fc2d9
TW
398
399 This one is only called for categories. Class objects have their
9faa82d8 400 methods installed right away, and their selectors are made into
c72fc2d9
TW
401 SEL's by the function __objc_register_selectors_from_class. */
402void
0994488a 403class_add_method_list (Class class, MethodList_t list)
c72fc2d9
TW
404{
405 int i;
406
407 /* Passing of a linked list is not allowed. Do multiple calls. */
408 assert (!list->method_next);
409
410 /* Check for duplicates. */
411 for (i = 0; i < list->method_count; ++i)
412 {
413 Method_t method = &list->method_list[i];
414
415 if (method->method_name) /* Sometimes these are NULL */
416 {
9faa82d8 417 /* This is where selector names are transmogrified to SEL's */
a39d31bc
KKT
418 method->method_name =
419 sel_register_typed_name ((const char*)method->method_name,
420 method->method_types);
c72fc2d9
TW
421 }
422 }
423
424 /* Add the methods to the class's method list. */
425 list->method_next = class->methods;
426 class->methods = list;
c72fc2d9 427
7084b319
RK
428 /* Update the dispatch table of class */
429 __objc_update_dispatch_table_for_class (class);
430}
c72fc2d9
TW
431
432Method_t
0994488a 433class_get_instance_method(Class class, SEL op)
c72fc2d9
TW
434{
435 return search_for_method_in_hierarchy(class, op);
436}
437
438Method_t
0994488a 439class_get_class_method(MetaClass class, SEL op)
c72fc2d9
TW
440{
441 return search_for_method_in_hierarchy(class, op);
442}
443
444
445/* Search for a method starting from the current class up its hierarchy.
446 Return a pointer to the method's method structure if found. NULL
447 otherwise. */
448
449static Method_t
0994488a 450search_for_method_in_hierarchy (Class cls, SEL sel)
c72fc2d9
TW
451{
452 Method_t method = NULL;
0994488a 453 Class class;
c72fc2d9
TW
454
455 if (! sel_is_mapped (sel))
456 return NULL;
457
458 /* Scan the method list of the class. If the method isn't found in the
459 list then step to its super class. */
460 for (class = cls; ((! method) && class); class = class->super_class)
461 method = search_for_method_in_list (class->methods, sel);
462
463 return method;
464}
465
466
467
468/* Given a linked list of method and a method's name. Search for the named
469 method's method structure. Return a pointer to the method's method
470 structure if found. NULL otherwise. */
255e0bab 471Method_t
c72fc2d9
TW
472search_for_method_in_list (MethodList_t list, SEL op)
473{
474 MethodList_t method_list = list;
475
476 if (! sel_is_mapped (op))
477 return NULL;
478
479 /* If not found then we'll search the list. */
480 while (method_list)
481 {
482 int i;
483
484 /* Search the method list. */
485 for (i = 0; i < method_list->method_count; ++i)
486 {
487 Method_t method = &method_list->method_list[i];
488
489 if (method->method_name)
a39d31bc 490 if (method->method_name->sel_id == op->sel_id)
c72fc2d9
TW
491 return method;
492 }
493
494 /* The method wasn't found. Follow the link to the next list of
495 methods. */
496 method_list = method_list->method_next;
497 }
498
499 return NULL;
500}
501
a39d31bc
KKT
502static retval_t __objc_forward (id object, SEL sel, arglist_t args);
503
ad248234 504/* Forwarding pointers/integers through the normal registers */
a39d31bc
KKT
505static id
506__objc_word_forward (id rcv, SEL op, ...)
507{
508 void *args, *res;
509
510 args = __builtin_apply_args ();
511 res = __objc_forward (rcv, op, args);
512 if (res)
513 __builtin_return (res);
514 else
515 return res;
516}
517
ad248234
RK
518/* Specific routine for forwarding floats/double because of
519 architectural differences on some processors. i386s for
520 example which uses a floating point stack versus general
521 registers for floating point numbers. This forward routine
2a7c93ee 522 makes sure that GCC restores the proper return values */
ad248234
RK
523static double
524__objc_double_forward (id rcv, SEL op, ...)
525{
526 void *args, *res;
527
528 args = __builtin_apply_args ();
529 res = __objc_forward (rcv, op, args);
530 __builtin_return (res);
531}
532
a39d31bc
KKT
533#if INVISIBLE_STRUCT_RETURN
534static __big
535#else
536static id
537#endif
538__objc_block_forward (id rcv, SEL op, ...)
539{
540 void *args, *res;
541
542 args = __builtin_apply_args ();
543 res = __objc_forward (rcv, op, args);
544 if (res)
545 __builtin_return (res);
3ac2735b
JL
546 else
547#if INVISIBLE_STRUCT_RETURN
548 return (__big) {{0, 0, 0, 0, 0, 0, 0, 0}};
549#else
550 return nil;
551#endif
a39d31bc
KKT
552}
553
c72fc2d9 554
9faa82d8 555/* This function is installed in the dispatch table for all methods which are
c72fc2d9 556 not implemented. Thus, it is called when a selector is not recognized. */
a39d31bc
KKT
557static retval_t
558__objc_forward (id object, SEL sel, arglist_t args)
c72fc2d9
TW
559{
560 IMP imp;
d50e6b7b 561 static SEL frwd_sel = 0; /* !T:SAFE2 */
c72fc2d9
TW
562 SEL err_sel;
563
564 /* first try if the object understands forward:: */
a39d31bc
KKT
565 if (!frwd_sel)
566 frwd_sel = sel_get_any_uid("forward::");
567
568 if (__objc_responds_to (object, frwd_sel))
c72fc2d9 569 {
a39d31bc
KKT
570 imp = get_imp(object->class_pointer, frwd_sel);
571 return (*imp)(object, frwd_sel, sel, args);
c72fc2d9
TW
572 }
573
574 /* If the object recognizes the doesNotRecognize: method then we're going
575 to send it. */
a39d31bc
KKT
576 err_sel = sel_get_any_uid ("doesNotRecognize:");
577 if (__objc_responds_to (object, err_sel))
c72fc2d9 578 {
a39d31bc 579 imp = get_imp (object->class_pointer, err_sel);
c72fc2d9
TW
580 return (*imp) (object, err_sel, sel);
581 }
582
583 /* The object doesn't recognize the method. Check for responding to
584 error:. If it does then sent it. */
585 {
a39d31bc
KKT
586 size_t strlen (const char*);
587 char msg[256 + strlen ((const char*)sel_get_name (sel))
588 + strlen ((const char*)object->class_pointer->name)];
c72fc2d9
TW
589
590 sprintf (msg, "(%s) %s does not recognize %s",
591 (CLS_ISMETA(object->class_pointer)
592 ? "class"
593 : "instance" ),
594 object->class_pointer->name, sel_get_name (sel));
595
a39d31bc
KKT
596 err_sel = sel_get_any_uid ("error:");
597 if (__objc_responds_to (object, err_sel))
598 {
599 imp = get_imp (object->class_pointer, err_sel);
600 return (*imp) (object, sel_get_any_uid ("error:"), msg);
601 }
c72fc2d9
TW
602
603 /* The object doesn't respond to doesNotRecognize: or error:; Therefore,
604 a default action is taken. */
eb0bc1e9 605 objc_error (object, OBJC_ERR_UNIMPLEMENTED, "%s\n", msg);
3ac2735b
JL
606
607 return 0;
c72fc2d9
TW
608 }
609}
610
14499ba4
RK
611void
612__objc_print_dtable_stats()
c72fc2d9
TW
613{
614 int total = 0;
d50e6b7b
RK
615
616 objc_mutex_lock(__objc_runtime_mutex);
617
c72fc2d9 618 printf("memory usage: (%s)\n",
c72fc2d9
TW
619#ifdef OBJC_SPARSE2
620 "2-level sparse arrays"
621#else
622 "3-level sparse arrays"
c72fc2d9
TW
623#endif
624 );
625
2a7c93ee 626 printf("arrays: %d = %ld bytes\n", narrays,
3ac2735b 627 (long)narrays*sizeof(struct sarray));
c72fc2d9 628 total += narrays*sizeof(struct sarray);
2a7c93ee 629 printf("buckets: %d = %ld bytes\n", nbuckets,
3ac2735b 630 (long)nbuckets*sizeof(struct sbucket));
c72fc2d9
TW
631 total += nbuckets*sizeof(struct sbucket);
632
3ac2735b 633 printf("idxtables: %d = %ld bytes\n", idxsize, (long)idxsize*sizeof(void*));
c72fc2d9 634 total += idxsize*sizeof(void*);
c72fc2d9
TW
635 printf("-----------------------------------\n");
636 printf("total: %d bytes\n", total);
637 printf("===================================\n");
d50e6b7b
RK
638
639 objc_mutex_unlock(__objc_runtime_mutex);
a7ab3794 640}
c72fc2d9 641
14499ba4
RK
642/* Returns the uninstalled dispatch table indicator.
643 If a class' dispatch table points to __objc_uninstalled_dtable
644 then that means it needs its dispatch table to be installed. */
7136f132
RK
645__inline__
646struct sarray*
647objc_get_uninstalled_dtable()
648{
649 return __objc_uninstalled_dtable;
650}
This page took 0.482547 seconds and 5 git commands to generate.