]> git.saurik.com Git - apple/objc4.git/blame - runtime/Messengers.subproj/objc-msg-i386.s
objc4-709.1.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-i386.s
CommitLineData
13d88034 1/*
b3962a83 2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
13d88034 3 *
b3962a83 4 * @APPLE_LICENSE_HEADER_START@
390d5862
A
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
13d88034
A
12 *
13 * The Original Code and all software distributed under the License are
390d5862 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
13d88034
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
390d5862
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
13d88034
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
7af964d1 23
8972963c 24#include <TargetConditionals.h>
c1e772c4 25#if defined(__i386__) && !TARGET_OS_SIMULATOR
7af964d1 26
13d88034
A
27/********************************************************************
28 ********************************************************************
29 **
30 ** objc-msg-i386.s - i386 code to support objc messaging.
31 **
32 ********************************************************************
33 ********************************************************************/
34
13d88034 35
390d5862
A
36/********************************************************************
37* Data used by the ObjC runtime.
38*
39********************************************************************/
40
41.data
390d5862 42
13d88034
A
43// _objc_entryPoints and _objc_exitPoints are used by objc
44// to get the critical regions for which method caches
45// cannot be garbage collected.
46
31875a97 47.align 2
b3962a83 48.private_extern _objc_entryPoints
13d88034 49_objc_entryPoints:
1f20c7a7
A
50 .long __cache_getImp
51 .long __cache_getMethod
13d88034 52 .long _objc_msgSend
809271e4 53 .long _objc_msgSend_fpret
13d88034
A
54 .long _objc_msgSend_stret
55 .long _objc_msgSendSuper
56 .long _objc_msgSendSuper_stret
57 .long 0
58
b3962a83 59.private_extern _objc_exitPoints
13d88034 60_objc_exitPoints:
1f20c7a7
A
61 .long LGetImpExit
62 .long LGetMethodExit
13d88034 63 .long LMsgSendExit
809271e4 64 .long LMsgSendFpretExit
13d88034
A
65 .long LMsgSendStretExit
66 .long LMsgSendSuperExit
67 .long LMsgSendSuperStretExit
68 .long 0
13d88034 69
2bfd4448 70
7257e56c
A
71/********************************************************************
72* List every exit insn from every messenger for debugger use.
73* Format:
74* (
75* 1 word instruction's address
76* 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
77* )
78* 1 word zero
79*
80* ENTER is the start of a dispatcher
81* FAST_EXIT is method dispatch
82* SLOW_EXIT is uncached method lookup
83* NIL_EXIT is returning zero from a message sent to nil
84* These must match objc-gdb.h.
85********************************************************************/
86
87#define ENTER 1
88#define FAST_EXIT 2
89#define SLOW_EXIT 3
90#define NIL_EXIT 4
91
92.section __DATA,__objc_msg_break
93.globl _gdb_objc_messenger_breakpoints
94_gdb_objc_messenger_breakpoints:
95// contents populated by the macros below
96
97.macro MESSENGER_START
984:
99 .section __DATA,__objc_msg_break
100 .long 4b
101 .long ENTER
102 .text
103.endmacro
104.macro MESSENGER_END_FAST
1054:
106 .section __DATA,__objc_msg_break
107 .long 4b
108 .long FAST_EXIT
109 .text
110.endmacro
111.macro MESSENGER_END_SLOW
1124:
113 .section __DATA,__objc_msg_break
114 .long 4b
115 .long SLOW_EXIT
116 .text
117.endmacro
118.macro MESSENGER_END_NIL
1194:
120 .section __DATA,__objc_msg_break
121 .long 4b
122 .long NIL_EXIT
123 .text
124.endmacro
125
126
13d88034
A
127/********************************************************************
128 *
129 * Common offsets.
130 *
131 ********************************************************************/
132
390d5862
A
133 self = 4
134 super = 4
135 selector = 8
136 marg_size = 12
137 marg_list = 16
138 first_arg = 12
13d88034 139
390d5862 140 struct_addr = 4
13d88034 141
390d5862
A
142 self_stret = 8
143 super_stret = 8
144 selector_stret = 12
145 marg_size_stret = 16
146 marg_list_stret = 20
13d88034
A
147
148
149/********************************************************************
150 *
151 * Structure definitions.
152 *
153 ********************************************************************/
154
155// objc_super parameter to sendSuper
390d5862
A
156 receiver = 0
157 class = 4
13d88034
A
158
159// Selected field offsets in class structure
390d5862
A
160 isa = 0
161 cache = 32
13d88034
A
162
163// Method descriptor
390d5862
A
164 method_name = 0
165 method_imp = 8
13d88034
A
166
167// Cache header
390d5862
A
168 mask = 0
169 occupied = 4
170 buckets = 8 // variable length array
13d88034
A
171
172#if defined(OBJC_INSTRUMENTED)
173// Cache instrumentation data, follows buckets
390d5862
A
174 hitCount = 0
175 hitProbes = hitCount + 4
176 maxHitProbes = hitProbes + 4
177 missCount = maxHitProbes + 4
178 missProbes = missCount + 4
179 maxMissProbes = missProbes + 4
180 flushCount = maxMissProbes + 4
181 flushedEntries = flushCount + 4
13d88034
A
182
183// Buckets in CacheHitHistogram and CacheMissHistogram
390d5862 184 CACHE_HISTOGRAM_SIZE = 512
13d88034
A
185#endif
186
187
13d88034
A
188//////////////////////////////////////////////////////////////////////
189//
190// ENTRY functionName
191//
192// Assembly directives to begin an exported function.
193//
194// Takes: functionName - name of the exported function
195//////////////////////////////////////////////////////////////////////
196
197.macro ENTRY
198 .text
199 .globl $0
200 .align 4, 0x90
201$0:
202.endmacro
203
8972963c
A
204.macro STATIC_ENTRY
205 .text
206 .private_extern $0
207 .align 4, 0x90
208$0:
209.endmacro
210
13d88034
A
211//////////////////////////////////////////////////////////////////////
212//
213// END_ENTRY functionName
214//
215// Assembly directives to end an exported function. Just a placeholder,
216// a close-parenthesis for ENTRY, until it is needed for something.
217//
218// Takes: functionName - name of the exported function
219//////////////////////////////////////////////////////////////////////
220
221.macro END_ENTRY
222.endmacro
223
224//////////////////////////////////////////////////////////////////////
225//
bf52b13b 226// CALL_MCOUNTER
13d88034 227//
bf52b13b
A
228// Calls mcount() profiling routine. Must be called immediately on
229// function entry, before any prologue executes.
13d88034 230//
13d88034 231//////////////////////////////////////////////////////////////////////
13d88034
A
232
233.macro CALL_MCOUNTER
234#ifdef PROFILE
bf52b13b 235 // Current stack contents: ret
13d88034
A
236 pushl %ebp
237 movl %esp,%ebp
b3962a83 238 subl $$8,%esp
bf52b13b 239 // Current stack contents: ret, ebp, pad, pad
8972963c 240 call mcount
13d88034
A
241 movl %ebp,%esp
242 popl %ebp
243#endif
244.endmacro
245
246
247/////////////////////////////////////////////////////////////////////
248//
249//
1f20c7a7 250// CacheLookup WORD_RETURN | STRUCT_RETURN, MSG_SEND | MSG_SENDSUPER | CACHE_GET, cacheMissLabel
13d88034
A
251//
252// Locate the implementation for a selector in a class method cache.
253//
254// Takes: WORD_RETURN (first parameter is at sp+4)
390d5862
A
255// STRUCT_RETURN (struct address is at sp+4, first parameter at sp+8)
256// MSG_SEND (first parameter is receiver)
257// MSG_SENDSUPER (first parameter is address of objc_super structure)
258// CACHE_GET (first parameter is class; return method triplet)
b3962a83
A
259// selector in %ecx
260// class to search in %edx
13d88034
A
261//
262// cacheMissLabel = label to branch to iff method is not cached
263//
390d5862
A
264// On exit: (found) MSG_SEND and MSG_SENDSUPER: return imp in eax
265// (found) CACHE_GET: return method triplet in eax
266// (not found) jumps to cacheMissLabel
13d88034
A
267//
268/////////////////////////////////////////////////////////////////////
269
270
271// Values to specify to method lookup macros whether the return type of
272// the method is word or structure.
390d5862
A
273WORD_RETURN = 0
274STRUCT_RETURN = 1
13d88034
A
275
276// Values to specify to method lookup macros whether the first argument
277// is an object/class reference or a 'objc_super' structure.
390d5862
A
278MSG_SEND = 0 // first argument is receiver, search the isa
279MSG_SENDSUPER = 1 // first argument is objc_super, search the class
280CACHE_GET = 2 // first argument is class, search that class
13d88034
A
281
282.macro CacheLookup
283
284// load variables and save caller registers.
13d88034
A
285
286 pushl %edi // save scratch register
b3962a83 287 movl cache(%edx), %edi // cache = class->cache
13d88034
A
288 pushl %esi // save scratch register
289
290#if defined(OBJC_INSTRUMENTED)
291 pushl %ebx // save non-volatile register
292 pushl %eax // save cache pointer
293 xorl %ebx, %ebx // probeCount = 0
294#endif
b3962a83 295 movl mask(%edi), %esi // mask = cache->mask
13d88034 296 movl %ecx, %edx // index = selector
b3962a83 297 shrl $$2, %edx // index = selector >> 2
13d88034
A
298
299// search the receiver's cache
7af964d1
A
300// ecx = selector
301// edi = cache
302// esi = mask
303// edx = index
304// eax = method (soon)
1f20c7a7 305LMsgSendProbeCache_$0_$1_$2:
13d88034 306#if defined(OBJC_INSTRUMENTED)
b3962a83 307 addl $$1, %ebx // probeCount += 1
13d88034
A
308#endif
309 andl %esi, %edx // index &= mask
7af964d1 310 movl buckets(%edi, %edx, 4), %eax // meth = cache->buckets[index]
13d88034
A
311
312 testl %eax, %eax // check for end of bucket
1f20c7a7 313 je LMsgSendCacheMiss_$0_$1_$2 // go to cache miss code
13d88034 314 cmpl method_name(%eax), %ecx // check for method name match
1f20c7a7 315 je LMsgSendCacheHit_$0_$1_$2 // go handle cache hit
b3962a83 316 addl $$1, %edx // bump index ...
1f20c7a7 317 jmp LMsgSendProbeCache_$0_$1_$2 // ... and loop
13d88034
A
318
319// not found in cache: restore state and go to callers handler
1f20c7a7 320LMsgSendCacheMiss_$0_$1_$2:
13d88034
A
321#if defined(OBJC_INSTRUMENTED)
322 popl %edx // retrieve cache pointer
323 movl mask(%edx), %esi // mask = cache->mask
324 testl %esi, %esi // a mask of zero is only for the...
1f20c7a7 325 je LMsgSendMissInstrumentDone_$0_$1_$2 // ... emptyCache, do not record anything
13d88034
A
326
327 // locate and update the CacheInstrumentation structure
b3962a83
A
328 addl $$1, %esi // entryCount = mask + 1
329 shll $$2, %esi // tableSize = entryCount * sizeof(entry)
13d88034
A
330 addl $buckets, %esi // offset = buckets + tableSize
331 addl %edx, %esi // cacheData = &cache->buckets[mask+1]
332
333 movl missCount(%esi), %edi //
b3962a83 334 addl $$1, %edi //
13d88034
A
335 movl %edi, missCount(%esi) // cacheData->missCount += 1
336 movl missProbes(%esi), %edi //
337 addl %ebx, %edi //
338 movl %edi, missProbes(%esi) // cacheData->missProbes += probeCount
339 movl maxMissProbes(%esi), %edi// if (cacheData->maxMissProbes < probeCount)
340 cmpl %ebx, %edi //
1f20c7a7 341 jge LMsgSendMaxMissProbeOK_$0_$1_$2 //
13d88034 342 movl %ebx, maxMissProbes(%esi)// cacheData->maxMissProbes = probeCount
1f20c7a7 343LMsgSendMaxMissProbeOK_$0_$1_$2:
13d88034
A
344
345 // update cache miss probe histogram
346 cmpl $CACHE_HISTOGRAM_SIZE, %ebx // pin probeCount to max index
1f20c7a7 347 jl LMsgSendMissHistoIndexSet_$0_$1_$2
13d88034 348 movl $(CACHE_HISTOGRAM_SIZE-1), %ebx
1f20c7a7 349LMsgSendMissHistoIndexSet_$0_$1_$2:
13d88034 350 LEA_STATIC_DATA %esi, _CacheMissHistogram, EXTERNAL_SYMBOL
b3962a83 351 shll $$2, %ebx // convert probeCount to histogram index
13d88034
A
352 addl %ebx, %esi // calculate &CacheMissHistogram[probeCount<<2]
353 movl 0(%esi), %edi // get current tally
b3962a83 354 addl $$1, %edi //
13d88034 355 movl %edi, 0(%esi) // tally += 1
1f20c7a7 356LMsgSendMissInstrumentDone_$0_$1_$2:
13d88034
A
357 popl %ebx // restore non-volatile register
358#endif
359
360.if $0 == WORD_RETURN // Regular word return
361.if $1 == MSG_SEND // MSG_SEND
362 popl %esi // restore callers register
363 popl %edi // restore callers register
cd5f04f5
A
364 movl self(%esp), %edx // get messaged object
365 movl isa(%edx), %eax // get objects class
1f20c7a7 366.elseif $1 == MSG_SENDSUPER // MSG_SENDSUPER
13d88034
A
367 // replace "super" arg with "receiver"
368 movl super+8(%esp), %edi // get super structure
cd5f04f5
A
369 movl receiver(%edi), %edx // get messaged object
370 movl %edx, super+8(%esp) // make it the first argument
13d88034
A
371 movl class(%edi), %eax // get messaged class
372 popl %esi // restore callers register
373 popl %edi // restore callers register
1f20c7a7
A
374.else // CACHE_GET
375 popl %esi // restore callers register
376 popl %edi // restore callers register
13d88034
A
377.endif
378.else // Struct return
379.if $1 == MSG_SEND // MSG_SEND (stret)
380 popl %esi // restore callers register
381 popl %edi // restore callers register
cd5f04f5
A
382 movl self_stret(%esp), %edx // get messaged object
383 movl isa(%edx), %eax // get objects class
1f20c7a7 384.elseif $1 == MSG_SENDSUPER // MSG_SENDSUPER (stret)
13d88034
A
385 // replace "super" arg with "receiver"
386 movl super_stret+8(%esp), %edi// get super structure
cd5f04f5
A
387 movl receiver(%edi), %edx // get messaged object
388 movl %edx, super_stret+8(%esp)// make it the first argument
13d88034
A
389 movl class(%edi), %eax // get messaged class
390 popl %esi // restore callers register
391 popl %edi // restore callers register
1f20c7a7
A
392.else // CACHE_GET
393 !! This should not happen.
13d88034
A
394.endif
395.endif
396
cd5f04f5
A
397 // edx = receiver
398 // ecx = selector
399 // eax = class
13d88034
A
400 jmp $2 // go to callers handler
401
402// eax points to matching cache entry
403 .align 4, 0x90
1f20c7a7 404LMsgSendCacheHit_$0_$1_$2:
13d88034
A
405#if defined(OBJC_INSTRUMENTED)
406 popl %edx // retrieve cache pointer
407 movl mask(%edx), %esi // mask = cache->mask
408 testl %esi, %esi // a mask of zero is only for the...
1f20c7a7 409 je LMsgSendHitInstrumentDone_$0_$1_$2 // ... emptyCache, do not record anything
13d88034
A
410
411 // locate and update the CacheInstrumentation structure
b3962a83
A
412 addl $$1, %esi // entryCount = mask + 1
413 shll $$2, %esi // tableSize = entryCount * sizeof(entry)
13d88034
A
414 addl $buckets, %esi // offset = buckets + tableSize
415 addl %edx, %esi // cacheData = &cache->buckets[mask+1]
416
417 movl hitCount(%esi), %edi
b3962a83 418 addl $$1, %edi
13d88034
A
419 movl %edi, hitCount(%esi) // cacheData->hitCount += 1
420 movl hitProbes(%esi), %edi
421 addl %ebx, %edi
422 movl %edi, hitProbes(%esi) // cacheData->hitProbes += probeCount
423 movl maxHitProbes(%esi), %edi// if (cacheData->maxHitProbes < probeCount)
424 cmpl %ebx, %edi
1f20c7a7 425 jge LMsgSendMaxHitProbeOK_$0_$1_$2
13d88034 426 movl %ebx, maxHitProbes(%esi)// cacheData->maxHitProbes = probeCount
1f20c7a7 427LMsgSendMaxHitProbeOK_$0_$1_$2:
13d88034
A
428
429 // update cache hit probe histogram
430 cmpl $CACHE_HISTOGRAM_SIZE, %ebx // pin probeCount to max index
1f20c7a7 431 jl LMsgSendHitHistoIndexSet_$0_$1_$2
13d88034 432 movl $(CACHE_HISTOGRAM_SIZE-1), %ebx
1f20c7a7 433LMsgSendHitHistoIndexSet_$0_$1_$2:
13d88034 434 LEA_STATIC_DATA %esi, _CacheHitHistogram, EXTERNAL_SYMBOL
b3962a83 435 shll $$2, %ebx // convert probeCount to histogram index
13d88034
A
436 addl %ebx, %esi // calculate &CacheHitHistogram[probeCount<<2]
437 movl 0(%esi), %edi // get current tally
b3962a83 438 addl $$1, %edi //
13d88034 439 movl %edi, 0(%esi) // tally += 1
1f20c7a7 440LMsgSendHitInstrumentDone_$0_$1_$2:
13d88034
A
441 popl %ebx // restore non-volatile register
442#endif
443
444// load implementation address, restore state, and we're done
1f20c7a7
A
445.if $1 == CACHE_GET
446 // method triplet is already in eax
447.else
13d88034 448 movl method_imp(%eax), %eax // imp = method->method_imp
1f20c7a7 449.endif
13d88034
A
450
451.if $0 == WORD_RETURN // Regular word return
452.if $1 == MSG_SENDSUPER // MSG_SENDSUPER
453 // replace "super" arg with "self"
454 movl super+8(%esp), %edi
455 movl receiver(%edi), %esi
456 movl %esi, super+8(%esp)
457.endif
458.else // Struct return
459.if $1 == MSG_SENDSUPER // MSG_SENDSUPER (stret)
460 // replace "super" arg with "self"
461 movl super_stret+8(%esp), %edi
462 movl receiver(%edi), %esi
463 movl %esi, super_stret+8(%esp)
464.endif
465.endif
466
467 // restore caller registers
468 popl %esi
469 popl %edi
470.endmacro
471
472
473/////////////////////////////////////////////////////////////////////
474//
475// MethodTableLookup WORD_RETURN | STRUCT_RETURN, MSG_SEND | MSG_SENDSUPER
476//
477// Takes: WORD_RETURN (first parameter is at sp+4)
478// STRUCT_RETURN (struct address is at sp+4, first parameter at sp+8)
479// MSG_SEND (first parameter is receiver)
480// MSG_SENDSUPER (first parameter is address of objc_super structure)
481//
cd5f04f5
A
482// edx = receiver
483// ecx = selector
484// eax = class
485// (all set by CacheLookup's miss case)
486//
2bfd4448
A
487// Stack must be at 0xXXXXXXXc on entrance.
488//
cd5f04f5
A
489// On exit: esp unchanged
490// imp in eax
13d88034
A
491//
492/////////////////////////////////////////////////////////////////////
493
13d88034 494.macro MethodTableLookup
7257e56c 495 MESSENGER_END_SLOW
31875a97
A
496
497 // stack has return address and nothing else
498 subl $$(12+5*16), %esp
499
500 movdqa %xmm3, 4*16(%esp)
501 movdqa %xmm2, 3*16(%esp)
502 movdqa %xmm1, 2*16(%esp)
503 movdqa %xmm0, 1*16(%esp)
504
505 movl %eax, 8(%esp) // class
506 movl %ecx, 4(%esp) // selector
507 movl %edx, 0(%esp) // receiver
cd5f04f5 508 call __class_lookupMethodAndLoadCache3
31875a97
A
509
510 movdqa 4*16(%esp), %xmm3
511 movdqa 3*16(%esp), %xmm2
512 movdqa 2*16(%esp), %xmm1
513 movdqa 1*16(%esp), %xmm0
514
515 addl $$(12+5*16), %esp // pop parameters
13d88034
A
516.endmacro
517
1f20c7a7
A
518
519/********************************************************************
7af964d1 520 * Method _cache_getMethod(Class cls, SEL sel, IMP msgForward_internal_imp)
1f20c7a7
A
521 *
522 * If found, returns method triplet pointer.
523 * If not found, returns NULL.
524 *
525 * NOTE: _cache_getMethod never returns any cache entry whose implementation
7257e56c 526 * is _objc_msgForward_impcache. It returns 1 instead. This prevents thread-
1f20c7a7 527 * safety and memory management bugs in _class_lookupMethodAndLoadCache.
390d5862
A
528 * See _class_lookupMethodAndLoadCache for details.
529 *
7257e56c 530 * _objc_msgForward_impcache is passed as a parameter because it's more
7af964d1 531 * efficient to do the (PIC) lookup once in the caller than repeatedly here.
1f20c7a7
A
532 ********************************************************************/
533
8972963c 534 STATIC_ENTRY __cache_getMethod
1f20c7a7 535
b3962a83
A
536// load the class and selector
537 movl selector(%esp), %ecx
538 movl self(%esp), %edx
1f20c7a7
A
539
540// do lookup
390d5862 541 CacheLookup WORD_RETURN, CACHE_GET, LGetMethodMiss
1f20c7a7
A
542
543// cache hit, method triplet in %eax
7257e56c
A
544 movl first_arg(%esp), %ecx // check for _objc_msgForward_impcache
545 cmpl method_imp(%eax), %ecx // if (imp==_objc_msgForward_impcache)
7af964d1 546 je 1f // return (Method)1
390d5862 547 ret // else return method triplet address
7af964d1
A
5481: movl $1, %eax
549 ret
1f20c7a7
A
550
551LGetMethodMiss:
552// cache miss, return nil
390d5862
A
553 xorl %eax, %eax // zero %eax
554 ret
1f20c7a7
A
555
556LGetMethodExit:
390d5862 557 END_ENTRY __cache_getMethod
1f20c7a7
A
558
559
560/********************************************************************
561 * IMP _cache_getImp(Class cls, SEL sel)
562 *
563 * If found, returns method implementation.
564 * If not found, returns NULL.
565 ********************************************************************/
566
8972963c 567 STATIC_ENTRY __cache_getImp
1f20c7a7 568
b3962a83
A
569// load the class and selector
570 movl selector(%esp), %ecx
571 movl self(%esp), %edx
1f20c7a7
A
572
573// do lookup
390d5862 574 CacheLookup WORD_RETURN, CACHE_GET, LGetImpMiss
1f20c7a7
A
575
576// cache hit, method triplet in %eax
390d5862
A
577 movl method_imp(%eax), %eax // return method imp
578 ret
1f20c7a7
A
579
580LGetImpMiss:
581// cache miss, return nil
390d5862
A
582 xorl %eax, %eax // zero %eax
583 ret
1f20c7a7
A
584
585LGetImpExit:
390d5862 586 END_ENTRY __cache_getImp
1f20c7a7
A
587
588
13d88034
A
589/********************************************************************
590 *
591 * id objc_msgSend(id self, SEL _cmd,...);
592 *
593 ********************************************************************/
594
595 ENTRY _objc_msgSend
7257e56c 596 MESSENGER_START
bf52b13b 597 CALL_MCOUNTER
13d88034 598
b3962a83
A
599// load receiver and selector
600 movl selector(%esp), %ecx
13d88034
A
601 movl self(%esp), %eax
602
603// check whether receiver is nil
604 testl %eax, %eax
605 je LMsgSendNilSelf
606
b3962a83 607// receiver (in %eax) is non-nil: search the cache
390d5862 608LMsgSendReceiverOk:
b3962a83 609 movl isa(%eax), %edx // class = self->isa
13d88034 610 CacheLookup WORD_RETURN, MSG_SEND, LMsgSendCacheMiss
7af964d1 611 xor %edx, %edx // set nonstret for msgForward_internal
7257e56c 612 MESSENGER_END_FAST
7af964d1 613 jmp *%eax
13d88034
A
614
615// cache miss: go search the method lists
616LMsgSendCacheMiss:
617 MethodTableLookup WORD_RETURN, MSG_SEND
7af964d1 618 xor %edx, %edx // set nonstret for msgForward_internal
13d88034
A
619 jmp *%eax // goto *imp
620
390d5862 621// message sent to nil: redirect to nil receiver, if any
13d88034 622LMsgSendNilSelf:
bf52b13b
A
623 // %eax is already zero
624 movl $0,%edx
31875a97 625 xorps %xmm0, %xmm0
13d88034 626LMsgSendDone:
7257e56c 627 MESSENGER_END_NIL
13d88034
A
628 ret
629
390d5862
A
630// guaranteed non-nil entry point (disabled for now)
631// .globl _objc_msgSendNonNil
632// _objc_msgSendNonNil:
633// movl self(%esp), %eax
634// jmp LMsgSendReceiverOk
635
13d88034
A
636LMsgSendExit:
637 END_ENTRY _objc_msgSend
638
639/********************************************************************
640 *
641 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
642 *
643 * struct objc_super {
644 * id receiver;
645 * Class class;
646 * };
647 ********************************************************************/
648
649 ENTRY _objc_msgSendSuper
7257e56c 650 MESSENGER_START
bf52b13b 651 CALL_MCOUNTER
13d88034 652
b3962a83
A
653// load selector and class to search
654 movl super(%esp), %eax // struct objc_super
655 movl selector(%esp), %ecx
656 movl class(%eax), %edx // struct objc_super->class
13d88034 657
b3962a83 658// search the cache (class in %edx)
13d88034 659 CacheLookup WORD_RETURN, MSG_SENDSUPER, LMsgSendSuperCacheMiss
7af964d1 660 xor %edx, %edx // set nonstret for msgForward_internal
7257e56c 661 MESSENGER_END_FAST
13d88034
A
662 jmp *%eax // goto *imp
663
664// cache miss: go search the method lists
665LMsgSendSuperCacheMiss:
666 MethodTableLookup WORD_RETURN, MSG_SENDSUPER
7af964d1 667 xor %edx, %edx // set nonstret for msgForward_internal
13d88034
A
668 jmp *%eax // goto *imp
669
b3962a83
A
670// ignored selector: return self
671LMsgSendSuperIgnored:
672 movl super(%esp), %eax
673 movl receiver(%eax), %eax
7257e56c 674 MESSENGER_END_NIL
b3962a83
A
675 ret
676
13d88034
A
677LMsgSendSuperExit:
678 END_ENTRY _objc_msgSendSuper
679
680/********************************************************************
681 * id objc_msgSendv(id self, SEL _cmd, unsigned size, marg_list frame);
682 *
683 * On entry:
684 * (sp+4) is the message receiver,
685 * (sp+8) is the selector,
686 * (sp+12) is the size of the marg_list, in bytes,
687 * (sp+16) is the address of the marg_list
688 *
689 ********************************************************************/
690
691 ENTRY _objc_msgSendv
692
693#if defined(KERNEL)
694 trap // _objc_msgSendv is not for the kernel
695#else
696 pushl %ebp
697 movl %esp, %ebp
bf52b13b 698 // stack is currently aligned assuming no extra arguments
13d88034
A
699 movl (marg_list+4)(%ebp), %edx
700 addl $8, %edx // skip self & selector
701 movl (marg_size+4)(%ebp), %ecx
2bfd4448 702 subl $8, %ecx // skip self & selector
13d88034 703 shrl $2, %ecx
2bfd4448
A
704 je LMsgSendvArgsOK
705
bf52b13b 706 // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
2bfd4448
A
707 movl %ecx, %eax // 16-byte align stack
708 andl $3, %eax
709 shll $2, %eax
bf52b13b
A
710 subl $16, %esp
711 addl %eax, %esp
2bfd4448 712
13d88034
A
713LMsgSendvArgLoop:
714 decl %ecx
715 movl 0(%edx, %ecx, 4), %eax
716 pushl %eax
717 jg LMsgSendvArgLoop
718
719LMsgSendvArgsOK:
720 movl (selector+4)(%ebp), %ecx
721 pushl %ecx
722 movl (self+4)(%ebp),%ecx
723 pushl %ecx
724 call _objc_msgSend
725 movl %ebp,%esp
726 popl %ebp
727
728 ret
729#endif
730 END_ENTRY _objc_msgSendv
731
809271e4
A
732/********************************************************************
733 *
734 * double objc_msgSend_fpret(id self, SEL _cmd,...);
735 *
736 ********************************************************************/
737
738 ENTRY _objc_msgSend_fpret
7257e56c 739 MESSENGER_START
bf52b13b 740 CALL_MCOUNTER
809271e4 741
b3962a83
A
742// load receiver and selector
743 movl selector(%esp), %ecx
809271e4
A
744 movl self(%esp), %eax
745
746// check whether receiver is nil
747 testl %eax, %eax
748 je LMsgSendFpretNilSelf
749
b3962a83 750// receiver (in %eax) is non-nil: search the cache
809271e4 751LMsgSendFpretReceiverOk:
b3962a83 752 movl isa(%eax), %edx // class = self->isa
809271e4 753 CacheLookup WORD_RETURN, MSG_SEND, LMsgSendFpretCacheMiss
7af964d1 754 xor %edx, %edx // set nonstret for msgForward_internal
7257e56c 755 MESSENGER_END_FAST
809271e4
A
756 jmp *%eax // goto *imp
757
758// cache miss: go search the method lists
759LMsgSendFpretCacheMiss:
760 MethodTableLookup WORD_RETURN, MSG_SEND
7af964d1 761 xor %edx, %edx // set nonstret for msgForward_internal
809271e4
A
762 jmp *%eax // goto *imp
763
764// message sent to nil: redirect to nil receiver, if any
765LMsgSendFpretNilSelf:
8070259c 766 // %eax is already zero
809271e4
A
767 fldz
768LMsgSendFpretDone:
7257e56c 769 MESSENGER_END_NIL
809271e4
A
770 ret
771
772LMsgSendFpretExit:
773 END_ENTRY _objc_msgSend_fpret
774
775/********************************************************************
776 * double objc_msgSendv_fpret(id self, SEL _cmd, unsigned size, marg_list frame);
777 *
778 * On entry:
779 * (sp+4) is the message receiver,
780 * (sp+8) is the selector,
781 * (sp+12) is the size of the marg_list, in bytes,
782 * (sp+16) is the address of the marg_list
783 *
784 ********************************************************************/
785
786 ENTRY _objc_msgSendv_fpret
787
788#if defined(KERNEL)
789 trap // _objc_msgSendv is not for the kernel
790#else
791 pushl %ebp
792 movl %esp, %ebp
793 // stack is currently aligned assuming no extra arguments
794 movl (marg_list+4)(%ebp), %edx
795 addl $8, %edx // skip self & selector
796 movl (marg_size+4)(%ebp), %ecx
797 subl $8, %ecx // skip self & selector
798 shrl $2, %ecx
799 je LMsgSendvFpretArgsOK
800
801 // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
802 movl %ecx, %eax // 16-byte align stack
803 andl $3, %eax
804 shll $2, %eax
805 subl $16, %esp
806 addl %eax, %esp
807
808LMsgSendvFpretArgLoop:
809 decl %ecx
810 movl 0(%edx, %ecx, 4), %eax
811 pushl %eax
812 jg LMsgSendvFpretArgLoop
813
814LMsgSendvFpretArgsOK:
815 movl (selector+4)(%ebp), %ecx
816 pushl %ecx
817 movl (self+4)(%ebp),%ecx
818 pushl %ecx
819 call _objc_msgSend_fpret
820 movl %ebp,%esp
821 popl %ebp
822
823 ret
824#endif
825 END_ENTRY _objc_msgSendv_fpret
826
13d88034
A
827/********************************************************************
828 *
829 * void objc_msgSend_stret(void *st_addr , id self, SEL _cmd, ...);
830 *
831 *
832 * objc_msgSend_stret is the struct-return form of msgSend.
833 * The ABI calls for (sp+4) to be used as the address of the structure
834 * being returned, with the parameters in the succeeding locations.
835 *
836 * On entry: (sp+4)is the address where the structure is returned,
837 * (sp+8) is the message receiver,
838 * (sp+12) is the selector
839 ********************************************************************/
840
841 ENTRY _objc_msgSend_stret
7257e56c 842 MESSENGER_START
bf52b13b 843 CALL_MCOUNTER
13d88034 844
b3962a83 845// load receiver and selector
13d88034 846 movl self_stret(%esp), %eax
b3962a83 847 movl (selector_stret)(%esp), %ecx
13d88034
A
848
849// check whether receiver is nil
850 testl %eax, %eax
851 je LMsgSendStretNilSelf
852
b3962a83 853// receiver (in %eax) is non-nil: search the cache
390d5862 854LMsgSendStretReceiverOk:
b3962a83 855 movl isa(%eax), %edx // class = self->isa
13d88034 856 CacheLookup STRUCT_RETURN, MSG_SEND, LMsgSendStretCacheMiss
7af964d1 857 movl $1, %edx // set stret for objc_msgForward
7257e56c 858 MESSENGER_END_FAST
13d88034
A
859 jmp *%eax // goto *imp
860
861// cache miss: go search the method lists
862LMsgSendStretCacheMiss:
863 MethodTableLookup STRUCT_RETURN, MSG_SEND
7af964d1 864 movl $1, %edx // set stret for objc_msgForward
13d88034
A
865 jmp *%eax // goto *imp
866
390d5862 867// message sent to nil: redirect to nil receiver, if any
13d88034 868LMsgSendStretNilSelf:
7257e56c 869 MESSENGER_END_NIL
390d5862
A
870 ret $4 // pop struct return address (#2995932)
871
872// guaranteed non-nil entry point (disabled for now)
873// .globl _objc_msgSendNonNil_stret
874// _objc_msgSendNonNil_stret:
bf52b13b 875// CALL_MCOUNTER
390d5862
A
876// movl self_stret(%esp), %eax
877// jmp LMsgSendStretReceiverOk
13d88034
A
878
879LMsgSendStretExit:
880 END_ENTRY _objc_msgSend_stret
881
882/********************************************************************
883 *
884 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
885 *
886 * struct objc_super {
887 * id receiver;
888 * Class class;
889 * };
890 *
891 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
892 * The ABI calls for (sp+4) to be used as the address of the structure
893 * being returned, with the parameters in the succeeding registers.
894 *
895 * On entry: (sp+4)is the address where the structure is returned,
896 * (sp+8) is the address of the objc_super structure,
897 * (sp+12) is the selector
898 *
899 ********************************************************************/
900
901 ENTRY _objc_msgSendSuper_stret
7257e56c 902 MESSENGER_START
bf52b13b 903 CALL_MCOUNTER
13d88034 904
b3962a83
A
905// load selector and class to search
906 movl super_stret(%esp), %eax // struct objc_super
907 movl (selector_stret)(%esp), %ecx // get selector
908 movl class(%eax), %edx // struct objc_super->class
13d88034 909
b3962a83 910// search the cache (class in %edx)
13d88034 911 CacheLookup STRUCT_RETURN, MSG_SENDSUPER, LMsgSendSuperStretCacheMiss
7af964d1 912 movl $1, %edx // set stret for objc_msgForward
7257e56c 913 MESSENGER_END_FAST
13d88034
A
914 jmp *%eax // goto *imp
915
916// cache miss: go search the method lists
917LMsgSendSuperStretCacheMiss:
918 MethodTableLookup STRUCT_RETURN, MSG_SENDSUPER
7af964d1 919 movl $1, %edx // set stret for objc_msgForward
13d88034
A
920 jmp *%eax // goto *imp
921
13d88034
A
922LMsgSendSuperStretExit:
923 END_ENTRY _objc_msgSendSuper_stret
924
925
926/********************************************************************
b3962a83 927 * void objc_msgSendv_stret(void *st_addr, id self, SEL _cmd, unsigned size, marg_list frame);
13d88034
A
928 *
929 * objc_msgSendv_stret is the struct-return form of msgSendv.
b3962a83
A
930 * This function does not use the struct-return ABI; instead, the
931 * structure return address is passed as a normal parameter.
13d88034
A
932 *
933 * On entry: (sp+4) is the address in which the returned struct is put,
934 * (sp+8) is the message receiver,
935 * (sp+12) is the selector,
936 * (sp+16) is the size of the marg_list, in bytes,
937 * (sp+20) is the address of the marg_list
938 *
939 ********************************************************************/
940
941 ENTRY _objc_msgSendv_stret
942
943#if defined(KERNEL)
944 trap // _objc_msgSendv_stret is not for the kernel
945#else
946 pushl %ebp
947 movl %esp, %ebp
bf52b13b 948 subl $12, %esp // align stack assuming no extra arguments
13d88034
A
949 movl (marg_list_stret+4)(%ebp), %edx
950 addl $8, %edx // skip self & selector
951 movl (marg_size_stret+4)(%ebp), %ecx
952 subl $5, %ecx // skip self & selector
953 shrl $2, %ecx
954 jle LMsgSendvStretArgsOK
2bfd4448 955
bf52b13b 956 // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
2bfd4448
A
957 movl %ecx, %eax // 16-byte align stack
958 andl $3, %eax
959 shll $2, %eax
bf52b13b 960 subl $16, %esp
2bfd4448
A
961 addl %eax, %esp
962
13d88034
A
963LMsgSendvStretArgLoop:
964 decl %ecx
965 movl 0(%edx, %ecx, 4), %eax
966 pushl %eax
967 jg LMsgSendvStretArgLoop
968
969LMsgSendvStretArgsOK:
970 movl (selector_stret+4)(%ebp), %ecx
971 pushl %ecx
972 movl (self_stret+4)(%ebp),%ecx
973 pushl %ecx
974 movl (struct_addr+4)(%ebp),%ecx
975 pushl %ecx
976 call _objc_msgSend_stret
977 movl %ebp,%esp
978 popl %ebp
979
980 ret
981#endif
982 END_ENTRY _objc_msgSendv_stret
983
984
985/********************************************************************
986 *
987 * id _objc_msgForward(id self, SEL _cmd,...);
988 *
989 ********************************************************************/
990
b3962a83
A
991// _FwdSel is @selector(forward::), set up in map_images().
992// ALWAYS dereference _FwdSel to get to "forward::" !!
993 .data
994 .align 2
995 .private_extern _FwdSel
996_FwdSel: .long 0
13d88034
A
997
998 .cstring
b3962a83 999 .align 2
cd5f04f5 1000LUnkSelStr: .ascii "Does not recognize selector %s (while forwarding %s)\0"
b3962a83 1001
8070259c
A
1002 .non_lazy_symbol_pointer
1003L_forward_handler:
1004 .indirect_symbol __objc_forward_handler
1005 .long 0
1006L_forward_stret_handler:
1007 .indirect_symbol __objc_forward_stret_handler
1008 .long 0
b3962a83 1009
7257e56c 1010 STATIC_ENTRY __objc_msgForward_impcache
7af964d1
A
1011 // Method cache version
1012
1013 // THIS IS NOT A CALLABLE C FUNCTION
1014 // Out-of-band register %edx is nonzero for stret, zero otherwise
7257e56c
A
1015
1016 MESSENGER_START
1017 nop
1018 MESSENGER_END_SLOW
7af964d1
A
1019
1020 // Check return type (stret or not)
1021 testl %edx, %edx
1022 jnz __objc_msgForward_stret
1023 jmp __objc_msgForward
1024
7257e56c 1025 END_ENTRY _objc_msgForward_impcache
13d88034 1026
7af964d1 1027
13d88034 1028 ENTRY __objc_msgForward
7af964d1 1029 // Non-struct return version
13d88034 1030
b3962a83
A
1031 // Get PIC base into %edx
1032 call L__objc_msgForward$pic_base
1033L__objc_msgForward$pic_base:
1034 popl %edx
1035
b3962a83 1036 // Call user handler, if any
8070259c
A
1037 movl L_forward_handler-L__objc_msgForward$pic_base(%edx),%ecx
1038 movl (%ecx), %ecx
b3962a83
A
1039 testl %ecx, %ecx // if not NULL
1040 je 1f // skip to default handler
1041 jmp *%ecx // call __objc_forward_handler
10421:
1043 // No user handler
1044 // Push stack frame
13d88034 1045 pushl %ebp
b3962a83
A
1046 movl %esp, %ebp
1047
1048 // Die if forwarding "forward::"
2bfd4448 1049 movl (selector+4)(%ebp), %eax
b3962a83 1050 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%ecx
13d88034 1051 cmpl %ecx, %eax
13d88034
A
1052 je LMsgForwardError
1053
b3962a83 1054 // Call [receiver forward:sel :margs]
2bfd4448
A
1055 subl $8, %esp // 16-byte align the stack
1056 leal (self+4)(%ebp), %ecx
b3962a83
A
1057 pushl %ecx // &margs
1058 pushl %eax // sel
1059 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%ecx
1060 pushl %ecx // forward::
1061 pushl (self+4)(%ebp) // receiver
1062
13d88034 1063 call _objc_msgSend
b3962a83
A
1064
1065 movl %ebp, %esp
13d88034
A
1066 popl %ebp
1067 ret
1068
13d88034 1069LMsgForwardError:
cd5f04f5
A
1070 // Call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
1071 subl $8, %esp // 16-byte align the stack
1072 pushl (selector+4+4)(%ebp) // the forwarded selector
b3962a83 1073 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%eax
13d88034
A
1074 pushl %eax
1075 leal LUnkSelStr-L__objc_msgForward$pic_base(%edx),%eax
1076 pushl %eax
2bfd4448 1077 pushl (self+4)(%ebp)
8972963c 1078 call ___objc_error // never returns
13d88034 1079
7af964d1
A
1080 END_ENTRY __objc_msgForward
1081
1082
1083 ENTRY __objc_msgForward_stret
1084 // Struct return version
13d88034 1085
b3962a83
A
1086 // Get PIC base into %edx
1087 call L__objc_msgForwardStret$pic_base
13d88034 1088L__objc_msgForwardStret$pic_base:
b3962a83
A
1089 popl %edx
1090
1091 // Call user handler, if any
8070259c
A
1092 movl L_forward_stret_handler-L__objc_msgForwardStret$pic_base(%edx), %ecx
1093 movl (%ecx), %ecx
b3962a83
A
1094 testl %ecx, %ecx // if not NULL
1095 je 1f // skip to default handler
1096 jmp *%ecx // call __objc_forward_stret_handler
10971:
1098 // No user handler
1099 // Push stack frame
1100 pushl %ebp
1101 movl %esp, %ebp
1102
1103 // Die if forwarding "forward::"
1104 movl (selector_stret+4)(%ebp), %eax
1105 movl _FwdSel-L__objc_msgForwardStret$pic_base(%edx), %ecx
13d88034 1106 cmpl %ecx, %eax
13d88034
A
1107 je LMsgForwardStretError
1108
b3962a83 1109 // Call [receiver forward:sel :margs]
2bfd4448
A
1110 subl $8, %esp // 16-byte align the stack
1111 leal (self_stret+4)(%ebp), %ecx
b3962a83
A
1112 pushl %ecx // &margs
1113 pushl %eax // sel
1114 movl _FwdSel-L__objc_msgForwardStret$pic_base(%edx),%ecx
1115 pushl %ecx // forward::
1116 pushl (self_stret+4)(%ebp) // receiver
1117
1f20c7a7 1118 call _objc_msgSend
b3962a83
A
1119
1120 movl %ebp, %esp
13d88034 1121 popl %ebp
390d5862 1122 ret $4 // pop struct return address (#2995932)
13d88034 1123
13d88034 1124LMsgForwardStretError:
cd5f04f5
A
1125 // Call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSelector)
1126 subl $8, %esp // 16-byte align the stack
1127 pushl (selector_stret+4+4)(%ebp) // the forwarded selector
b3962a83 1128 leal _FwdSel-L__objc_msgForwardStret$pic_base(%edx),%eax
13d88034
A
1129 pushl %eax
1130 leal LUnkSelStr-L__objc_msgForwardStret$pic_base(%edx),%eax
1131 pushl %eax
2bfd4448 1132 pushl (self_stret+4)(%ebp)
8972963c 1133 call ___objc_error // never returns
13d88034 1134
7af964d1 1135 END_ENTRY __objc_msgForward_stret
13d88034 1136
2bfd4448 1137
b3962a83
A
1138 ENTRY _method_invoke
1139
1140 movl selector(%esp), %ecx
1141 movl method_name(%ecx), %edx
1142 movl method_imp(%ecx), %eax
1143 movl %edx, selector(%esp)
1144 jmp *%eax
1145
1146 END_ENTRY _method_invoke
1147
1148
1149 ENTRY _method_invoke_stret
1150
1151 movl selector_stret(%esp), %ecx
1152 movl method_name(%ecx), %edx
1153 movl method_imp(%ecx), %eax
1154 movl %edx, selector_stret(%esp)
1155 jmp *%eax
1156
1157 END_ENTRY _method_invoke_stret
7af964d1 1158
7257e56c
A
1159
1160.section __DATA,__objc_msg_break
1161.long 0
1162.long 0
1163
7af964d1 1164#endif