Skip to content

Commit 49c4051

Browse files
author
Nat!
committed
* simplify mulle_objc_object_call for debugging
1 parent 0d4f928 commit 49c4051

5 files changed

+185
-41
lines changed

src/mulle-objc-call.c

+38-6
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,45 @@
5757

5858
#pragma mark - non-inline API calls
5959

60-
61-
// we can't do the FCS code here, because its just super slow if
60+
//
61+
// mulle_objc_object_call is what objc_msgSend is on other runtimes
62+
// (at least in -O0)
63+
//
64+
// MEMO: this has been rewritten for 0.24. The main advantage is, that this
65+
// function will not explode a stack trace as much with non-inlined
66+
// functions in DEBUG configuration. The second major advantage is
67+
// that in a C debugger, once you go into mulle_objc_object_call you
68+
// can just step over _mulle_objc_object_get_imp_inline_full_no_fcs and
69+
// then step into (*f)( obj, methodid, parameter) in most cases.
70+
//
71+
// We don't do the FCS code here, because its just super slow if
6272
// the constant isn't known.
63-
// This is like call_cache_collision, except that we still need do check the
64-
// first cache entry.
73+
//
6574
MULLE_C_NEVER_INLINE
6675
void *mulle_objc_object_call( void *obj,
6776
mulle_objc_methodid_t methodid,
6877
void *parameter)
6978
{
70-
return( mulle_objc_object_call_inline_full( obj, methodid, parameter));
79+
mulle_objc_implementation_t f;
80+
81+
if( MULLE_C_UNLIKELY( ! obj))
82+
return( obj);
83+
84+
// INFO: in a C debugger, 'next' over this function call
85+
f = _mulle_objc_object_get_imp_inline_full_no_fcs( obj, methodid);
86+
87+
// INFO: in a C debugger, 'step' into this to reach the Objective-C method
88+
// when the `f` has been cached. Otherwise:
89+
//
90+
// if `f` is _mulle_objc_object_call2_needcache you will need to
91+
// step to _mulle_objc_object_call_class_slow. This will happen once
92+
// per class on the very first method.
93+
//
94+
// if `f` is _mulle_objc_object_callback_cache_miss, the call to the
95+
// Objective-C method will be at the end of the function
96+
//
97+
98+
return( (*f)( obj, methodid, parameter));
7199
}
72100

73101

@@ -77,7 +105,11 @@ void *_mulle_objc_object_call( void *obj,
77105
mulle_objc_methodid_t methodid,
78106
void *parameter)
79107
{
80-
return( _mulle_objc_object_call_inline_full( obj, methodid, parameter));
108+
mulle_objc_implementation_t f;
109+
110+
f = _mulle_objc_object_get_imp_inline_full_no_fcs( obj, methodid);
111+
// don't use invoke, because the checking will have been done in icache->call_cache_miss
112+
return( (*f)( obj, methodid, parameter));
81113
}
82114

83115

src/mulle-objc-call.h

+77
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,17 @@ void mulle_objc_implementation_debug( mulle_objc_implementation_t imp,
103103
}
104104

105105

106+
MULLE_C_ALWAYS_INLINE
107+
static inline void *
108+
_mulle_objc_implementation_invoke( mulle_objc_implementation_t imp,
109+
void *self,
110+
mulle_objc_methodid_t sel,
111+
void *parameter)
112+
{
113+
return( (*imp)( self, sel, parameter));
114+
}
115+
116+
106117

107118
MULLE_C_ALWAYS_INLINE
108119
static inline void *
@@ -119,6 +130,7 @@ static inline void *
119130
}
120131

121132

133+
122134
//
123135
// calls are always "nofail", whereas lookup can fail (and return nil)
124136
// calls can return nil too, often, do but that's not a fail
@@ -163,6 +175,18 @@ MULLE_C_ALWAYS_INLINE static inline void *
163175

164176
#ifdef __MULLE_OBJC_FCS__
165177

178+
MULLE_C_ALWAYS_INLINE
179+
static inline void *
180+
_mulle_objc_fastmethodtable_get_imp( struct _mulle_objc_fastmethodtable *table,
181+
unsigned int index)
182+
{
183+
mulle_objc_implementation_t imp;
184+
185+
imp = (mulle_objc_implementation_t) _mulle_atomic_pointer_read( &table->methods[ index].pointer);
186+
return( imp);
187+
}
188+
189+
166190
MULLE_C_ALWAYS_INLINE
167191
static inline void *
168192
_mulle_objc_fastmethodtable_invoke( void *obj,
@@ -297,6 +321,59 @@ static inline void *
297321
}
298322

299323

324+
MULLE_C_ALWAYS_INLINE
325+
static inline void *
326+
_mulle_objc_object_get_imp_inline_full_no_fcs( void *obj,
327+
mulle_objc_methodid_t methodid)
328+
{
329+
mulle_objc_implementation_t f;
330+
struct _mulle_objc_cache *cache;
331+
struct _mulle_objc_impcache *icache;
332+
struct _mulle_objc_cacheentry *entries;
333+
struct _mulle_objc_cacheentry *entry;
334+
struct _mulle_objc_class *cls;
335+
mulle_objc_cache_uint_t mask;
336+
mulle_objc_cache_uint_t offset;
337+
338+
//
339+
// with tagged pointers inlining starts to become useless, because this
340+
// _mulle_objc_object_get_isa function produces too much code IMO
341+
//
342+
cls = _mulle_objc_object_get_isa( obj);
343+
344+
assert( methodid);
345+
346+
// MEMO: When inlining, we are "fine" if the cache is stale
347+
entries = _mulle_objc_cachepivot_get_entries_atomic( &cls->cachepivot.pivot);
348+
cache = _mulle_objc_cacheentry_get_cache_from_entries( entries);
349+
mask = cache->mask; // preshifted so we can just AND it to entries
350+
offset = (mulle_objc_cache_uint_t) methodid;
351+
for(;;)
352+
{
353+
offset = (mulle_objc_cache_uint_t) offset & mask;
354+
entry = (void *) &((char *) entries)[ offset];
355+
356+
if( MULLE_C_LIKELY( entry->key.uniqueid == methodid))
357+
{
358+
f = (mulle_objc_implementation_t) _mulle_atomic_pointer_read_nonatomic( &entry->value.pointer);
359+
break;
360+
}
361+
362+
if( ! entry->key.uniqueid)
363+
{
364+
icache = _mulle_objc_cache_get_impcache_from_cache( cache);
365+
f = icache->callback.call_cache_miss;
366+
break;
367+
}
368+
offset += sizeof( struct _mulle_objc_cacheentry);
369+
}
370+
371+
// don't use invoke, because the checking will be done in icache->call_cache_miss
372+
return( f);
373+
}
374+
375+
376+
300377
//
301378
// same as above, but we don't stop at the first miss. This adds some looping
302379
// code to the inlined function, you might or might not deep acceptable. So

src/mulle-objc-class-initialize.c

+25-12
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,9 @@ static void
191191
struct _mulle_objc_universe *universe;
192192
struct _mulle_objc_searcharguments search;
193193
struct _mulle_objc_searchresult result;
194+
mulle_objc_implementation_t imp;
194195
int preserve;
195196
int is_initialize;
196-
mulle_objc_implementation_t imp;
197197

198198
preserve = errno;
199199

@@ -523,10 +523,12 @@ static void *_mulle_objc_object_call_class_slow( void *obj,
523523
{
524524
struct _mulle_objc_method *method;
525525
mulle_objc_implementation_t imp;
526+
void *result;
526527

527528
method = mulle_objc_class_search_method_nofail( cls, methodid);
528529
imp = _mulle_objc_method_get_implementation( method);
529-
return( mulle_objc_implementation_invoke( imp, obj, methodid, parameter));
530+
result = mulle_objc_implementation_invoke( imp, obj, methodid, parameter);
531+
return( result);
530532
}
531533

532534

@@ -537,11 +539,13 @@ static void *_mulle_objc_object_call2_slow( void *obj,
537539
struct _mulle_objc_class *cls;
538540
struct _mulle_objc_method *method;
539541
mulle_objc_implementation_t imp;
542+
void *result;
540543

541544
cls = _mulle_objc_object_get_isa( obj);
542545
method = mulle_objc_class_search_method_nofail( cls, methodid);
543546
imp = _mulle_objc_method_get_implementation( method);
544-
return( mulle_objc_implementation_invoke( imp, obj, methodid, parameter));
547+
result = mulle_objc_implementation_invoke( imp, obj, methodid, parameter);
548+
return( result);
545549
}
546550

547551

@@ -554,12 +558,14 @@ static void *
554558
{
555559
struct _mulle_objc_method *method;
556560
mulle_objc_implementation_t imp;
561+
void *result;
557562

558563
MULLE_C_UNUSED( obj);
559564

560565
method = _mulle_objc_class_supersearch_method_nofail( cls, superid);
561566
imp = _mulle_objc_method_get_implementation( method);
562-
return( mulle_objc_implementation_invoke( imp, obj, methodid, parameter));
567+
result = mulle_objc_implementation_invoke( imp, obj, methodid, parameter);
568+
return( result);
563569
}
564570

565571

@@ -583,8 +589,11 @@ static void *_mulle_objc_object_call_class_needcache( void *obj,
583589
void *parameter,
584590
struct _mulle_objc_class *cls)
585591
{
592+
void *result;
593+
586594
_mulle_objc_class_setup( cls);
587-
return( _mulle_objc_object_call_class_slow( obj, methodid, parameter, cls));
595+
result = _mulle_objc_object_call_class_slow( obj, methodid, parameter, cls);
596+
return( result);
588597
}
589598

590599

@@ -594,29 +603,33 @@ static void *_mulle_objc_object_call2_needcache( void *obj,
594603
void *parameter)
595604
{
596605
struct _mulle_objc_class *cls;
606+
void *result;
597607

598-
cls = _mulle_objc_object_get_isa( (struct _mulle_objc_object *) obj);
599-
return( _mulle_objc_object_call_class_needcache( obj, methodid, parameter, cls));
608+
cls = _mulle_objc_object_get_isa( (struct _mulle_objc_object *) obj);
609+
result = _mulle_objc_object_call_class_needcache( obj, methodid, parameter, cls);
610+
return( result);
600611
}
601612

602613

603614
static void *
604615
_mulle_objc_object_call_super_needcache( void *obj,
605-
mulle_objc_methodid_t methodid,
606-
void *parameter,
607-
mulle_objc_superid_t superid,
608-
struct _mulle_objc_class *cls)
616+
mulle_objc_methodid_t methodid,
617+
void *parameter,
618+
mulle_objc_superid_t superid,
619+
struct _mulle_objc_class *cls)
609620
{
610621
mulle_objc_implementation_t imp;
611622
struct _mulle_objc_method *method;
623+
void *result;
612624

613625
// happens when we do +[super initialize] in +initialize
614626
_mulle_objc_class_setup( cls);
615627

616628
// this is slow and uncached as we need it
617629
method = _mulle_objc_class_search_supermethod_nofail( cls, superid);
618630
imp = _mulle_objc_method_get_implementation( method);
619-
return( mulle_objc_implementation_invoke( imp, obj, methodid, parameter));
631+
result = mulle_objc_implementation_invoke( imp, obj, methodid, parameter);
632+
return( result);
620633
}
621634

622635

src/mulle-objc-load.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -1434,17 +1434,17 @@ void mulle_objc_universe_assert_loadinfo( struct _mulle_objc_universe *univer
14341434
{
14351435
mulle_objc_loadinfo_dump( info, "loadinfo: ", universe);
14361436
mulle_objc_universe_fail_inconsistency( universe,
1437-
"mulle_objc_universe %p: the universe is configured for "
1438-
"thread affine objects, but classes are compiled differently",
1437+
"mulle_objc_universe %p: the runtime is compiled for "
1438+
"thread affine objects -fobjc-tao, but classes are compiled -fno-objc-tao",
14391439
universe);
14401440
}
14411441
#else
14421442
if( load_tao)
14431443
{
14441444
mulle_objc_loadinfo_dump( info, "loadinfo: ", universe);
14451445
mulle_objc_universe_fail_inconsistency( universe,
1446-
"mulle_objc_universe %p: the universe is not configured for "
1447-
"thread affine objects, but classes are compiled differently",
1446+
"mulle_objc_universe %p: the runtime is compiled for "
1447+
"no thread affine objects -fno-objc-tao, but classes are compiled -fobjc-tao",
14481448
universe);
14491449
}
14501450
#endif

0 commit comments

Comments
 (0)