ObjFW  Check-in [0c332aa2d2]

Overview
Comment:Rework forwarding API and ABI.

It matches the Apple API and ABI now and the forwarding handler itself
determines whether it should forward or not.

This moves handling of +[resolve{Class,Instance}Method:] to the runtime
and allows adding new kinds of forwarding without changing the runtime.

Also fixes a potential stack problem in the forwarding for MIPS.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0c332aa2d2fbd36a76322a7e3e30228078384f576cf1933c75e860e3239edc7f
User & Date: js on 2013-12-27 02:07:14
Other Links: manifest | tags
Context
2013-12-30
13:47
Don't enter tests/plugin twice. check-in: 72c41bbf69 user: js tags: trunk
2013-12-27
02:07
Rework forwarding API and ABI. check-in: 0c332aa2d2 user: js tags: trunk
2013-12-25
14:34
PLATFORMS.md: Add a section about forwarding. check-in: 5f2b90222e user: js tags: trunk
Changes

Modified src/OFObject.m from [e741aba66a] to [a55f4922cc].

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# import "threading.h"
#endif

#if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR)
extern id of_forward(id, SEL, ...);
extern struct stret of_forward_stret(id, SEL, ...);
#else
# define of_forward NULL
# define of_forward_stret NULL
#endif

struct pre_ivar {
	int32_t retainCount;
	struct pre_mem *firstMem, *lastMem;
#if !defined(OF_HAVE_ATOMIC_OPS) && defined(OF_HAVE_THREADS)
	of_spinlock_t retainCountSpinlock;







|
|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# import "threading.h"
#endif

#if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR)
extern id of_forward(id, SEL, ...);
extern struct stret of_forward_stret(id, SEL, ...);
#else
# define of_forward of_method_not_found
# define of_forward_stret of_method_not_found_stret
#endif

struct pre_ivar {
	int32_t retainCount;
	struct pre_mem *firstMem, *lastMem;
#if !defined(OF_HAVE_ATOMIC_OPS) && defined(OF_HAVE_THREADS)
	of_spinlock_t retainCountSpinlock;
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
	/*
	 * Just in case doesNotRecognizeSelector: returned, even though it must
	 * never return.
	 */
	abort();
}

#ifdef OF_OBJFW_RUNTIME
static IMP
commonForwardHandler(id obj, SEL sel, IMP (*lookup)(id, SEL), IMP forward)
{
	/* Try resolveClassMethod:/resolveInstanceMethod: */
	if (class_isMetaClass(object_getClass(obj))) {
		if ([obj respondsToSelector: @selector(resolveClassMethod:)] &&
		    [obj resolveClassMethod: sel]) {
			if (![obj respondsToSelector: sel]) {
				fprintf(stderr, "Runtime error: [%s "
				    "resolveClassMethod: %s] returned true "
				    "without adding the method!\n",
				    class_getName(obj), sel_getName(sel));
				abort();
			}

			return lookup(obj, sel);
		}
	} else {
		Class c = object_getClass(obj);

		if ([c respondsToSelector: @selector(resolveInstanceMethod:)] &&
		    [c resolveInstanceMethod: sel]) {
			if (![obj respondsToSelector: sel]) {
				fprintf(stderr, "Runtime error: [%s "
				    "resolveInstanceMethod: %s] returned true "
				    "without adding the method!\n",
				    class_getName(object_getClass(obj)),
				    sel_getName(sel));
				abort();
			}

			return lookup(obj, sel);
		}
	}

#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
	if (class_respondsToSelector(object_getClass(obj),
	    @selector(forwardingTargetForSelector:))) {
		id target = [obj forwardingTargetForSelector: sel];

		if (target != nil && target != obj)
			return forward;
	}
#endif

	of_method_not_found(obj, sel);
	return NULL;
}

static IMP
forwardHandler(id obj, SEL sel)
{
	return commonForwardHandler(obj, sel, objc_msg_lookup, (IMP)of_forward);
}

static IMP
forwardHandlerStret(id obj, SEL sel)
{
	return commonForwardHandler(obj, sel,
	    objc_msg_lookup_stret, (IMP)of_forward_stret);
}
#endif

#ifndef HAVE_OBJC_ENUMERATIONMUTATION
void
objc_enumerationMutation(id object)
{
	enumerationMutationHandler(object);
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<

<
<
<
<
<
<
<
<
<
<
<
<
<
<







133
134
135
136
137
138
139















140




141










142














143

144














145
146
147
148
149
150
151
	/*
	 * Just in case doesNotRecognizeSelector: returned, even though it must
	 * never return.
	 */
	abort();
}
















void




of_method_not_found_stret(void *st, id obj, SEL sel)










{














	of_method_not_found(obj, sel);

}















#ifndef HAVE_OBJC_ENUMERATIONMUTATION
void
objc_enumerationMutation(id object)
{
	enumerationMutationHandler(object);
}
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
@implementation OFObject
+ (void)load
{
#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
	objc_setUncaughtExceptionHandler(uncaughtExceptionHandler);
#endif

#if defined(OF_OBJFW_RUNTIME)
	objc_forward_handler = forwardHandler;
	objc_forward_handler_stret = forwardHandlerStret;
#elif defined(OF_APPLE_RUNTIME) && \
    defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR)
	objc_setForwardHandler(of_forward, of_forward_stret);
#endif

#ifdef HAVE_OBJC_ENUMERATIONMUTATION
	objc_setEnumerationMutationHandler(enumerationMutationHandler);
#endif

#if defined(HAVE_ARC4RANDOM)
	of_hash_seed = arc4random();







<
<
<
<
<

<







217
218
219
220
221
222
223





224

225
226
227
228
229
230
231
@implementation OFObject
+ (void)load
{
#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
	objc_setUncaughtExceptionHandler(uncaughtExceptionHandler);
#endif






	objc_setForwardHandler(of_forward, of_forward_stret);


#ifdef HAVE_OBJC_ENUMERATIONMUTATION
	objc_setEnumerationMutationHandler(enumerationMutationHandler);
#endif

#if defined(HAVE_ARC4RANDOM)
	of_hash_seed = arc4random();

Modified src/forwarding/apple-forwarding-arm.S from [71a0f74942] to [a9ffa0e379].

28
29
30
31
32
33
34
35
36




37
38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74




75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
.section __DATA, __objc_imageinfo, regular, no_dead_strip
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
.arm
.align 2
_of_forward:
	stmfd	sp!, {r0-r3, lr}
	fstmfdd	sp!, {d0-d7}





	blx	_object_getClass

	ldr	r1, L_sel_forwardingTargetForSelector_$indirect_L0
L0:
	ldr	r1, [pc, r1]
	stmfd	sp!, {r1}
	blx	_class_respondsToSelector
	ldmfd	sp!, {r1}
	cmp	r0, #0
	beq	fail

	ldr	r0, [sp, #64]

	ldr	r2, [sp, #68]
	blx	_objc_msgSend

	cmp	r0, #0
	beq	fail

	ldr	r1, [sp, #64]
	cmp	r0, r1
	beq	fail

	fldmfdd	sp!, {d0-d7}
	add	sp, sp, #4	@ throw away r0
	ldmfd	sp!, {r1-r3, lr}

	b	_objc_msgSend

fail:
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r3, lr}
	b	_of_method_not_found

.align 2
_of_forward_stret:
	stmfd	sp!, {r0-r3, lr}
	fstmfdd	sp!, {d0-d7}





	mov	r0, r1
	blx	_object_getClass

	ldr	r1, L_sel_forwardingTargetForSelector_$indirect_L1
L1:
	ldr	r1, [pc, r1]
	stmfd	sp!, {r1}
	blx	_class_respondsToSelector
	ldmfd	sp!, {r1}
	cmp	r0, #0
	beq	fail_stret

	ldr	r0, [sp, #68]

	ldr	r2, [sp, #72]
	blx	_objc_msgSend

	cmp	r0, #0
	beq	fail_stret

	ldr	r1, [sp, #68]
	cmp	r0, r1
	beq	fail_stret

	mov	r1, r0

	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0}
	add	sp, sp, #4	@ throw away r1
	ldmfd	sp!, {r2-r3, lr}

	b	_objc_msgSend_stret

fail_stret:
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r3, lr}
	mov	r0, r1
	mov	r1, r2
	b	_of_method_not_found

.data_region
L_sel_forwardingTargetForSelector_$indirect_L0:
	.long L_sel_forwardingTargetForSelector_-(L0+8)
L_sel_forwardingTargetForSelector_$indirect_L1:
	.long L_sel_forwardingTargetForSelector_-(L1+8)
.end_data_region







|

>
>
>
>



<
<
|
<

|




>





<






|





|




|

>
>
>
>




<
<
|
<

|




>





<









|





|
<
<
|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43


44

45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83


84

85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112


113
114
115
116
117
118
119
120
.section __DATA, __objc_imageinfo, regular, no_dead_strip
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
.arm
.align 2
_of_forward:
	stmfd	sp!, {r0-r4, lr}
	fstmfdd	sp!, {d0-d7}

	ldr	r4, L_sel_forwardingTargetForSelector_$indirect_L0
L0:
	ldr	r4, [pc, r4]

	blx	_object_getClass



	mov	r1, r4

	blx	_class_respondsToSelector

	cmp	r0, #0
	beq	fail

	ldr	r0, [sp, #64]
	mov	r1, r4
	ldr	r2, [sp, #68]
	blx	_objc_msgSend

	cmp	r0, #0
	beq	fail

	ldr	r1, [sp, #64]
	cmp	r0, r1
	beq	fail

	fldmfdd	sp!, {d0-d7}
	add	sp, sp, #4	@ throw away r0
	ldmfd	sp!, {r1-r4, lr}

	b	_objc_msgSend

fail:
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}
	b	_of_method_not_found

.align 2
_of_forward_stret:
	stmfd	sp!, {r0-r4, lr}
	fstmfdd	sp!, {d0-d7}

	ldr	r4, L_sel_forwardingTargetForSelector_$indirect_L1
L1:
	ldr	r4, [pc, r4]

	mov	r0, r1
	blx	_object_getClass



	mov	r1, r4

	blx	_class_respondsToSelector

	cmp	r0, #0
	beq	fail_stret

	ldr	r0, [sp, #68]
	mov	r1, r4
	ldr	r2, [sp, #72]
	blx	_objc_msgSend

	cmp	r0, #0
	beq	fail_stret

	ldr	r1, [sp, #68]
	cmp	r0, r1
	beq	fail_stret

	mov	r1, r0

	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0}
	add	sp, sp, #4	@ throw away r1
	ldmfd	sp!, {r2-r4, lr}

	b	_objc_msgSend_stret

fail_stret:
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}


	b	_of_method_not_found_stret

.data_region
L_sel_forwardingTargetForSelector_$indirect_L0:
	.long L_sel_forwardingTargetForSelector_-(L0+8)
L_sel_forwardingTargetForSelector_$indirect_L1:
	.long L_sel_forwardingTargetForSelector_-(L1+8)
.end_data_region

Modified src/forwarding/apple-forwarding-arm64.S from [bd6425afa7] to [8cba7c9e68].

52
53
54
55
56
57
58

59
60
61
62
63
64
65

	adrp	x19, L_sel_forwardingTargetForSelector_@PAGE
	add	x19, x19, L_sel_forwardingTargetForSelector_@PAGEOFF
	ldr	x19, [x19]

	mov	x1, x19
	bl	_class_respondsToSelector

	cbz	x0, fail

	ldp	x0, x2, [sp]
	mov	x1, x19
	bl	_objc_msgSend

	cbz	x0, fail







>







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

	adrp	x19, L_sel_forwardingTargetForSelector_@PAGE
	add	x19, x19, L_sel_forwardingTargetForSelector_@PAGEOFF
	ldr	x19, [x19]

	mov	x1, x19
	bl	_class_respondsToSelector

	cbz	x0, fail

	ldp	x0, x2, [sp]
	mov	x1, x19
	bl	_objc_msgSend

	cbz	x0, fail

Modified src/forwarding/apple-forwarding-i386.S from [8a15676211] to [d1c0103e06].

34
35
36
37
38
39
40

41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L0:

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	L_sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	fail

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	movl	L_sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	movl	12(%ebp), %eax
	movl	%eax, 8(%esp)
	call	_objc_msgSend

	testl	%eax, %eax
	jz	fail

	cmpl	8(%ebp), %eax
	je	fail

	movl	%eax, 8(%ebp)

	addl	$20, %esp
	popl	%ebx







>








>













<







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L0:

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	L_sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	fail

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	movl	L_sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	movl	12(%ebp), %eax
	movl	%eax, 8(%esp)
	call	_objc_msgSend

	testl	%eax, %eax
	jz	fail

	cmpl	8(%ebp), %eax
	je	fail

	movl	%eax, 8(%ebp)

	addl	$20, %esp
	popl	%ebx
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L1:

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	L_sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	fail_stret

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	movl	L_sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	movl	16(%ebp), %eax
	movl	%eax, 8(%esp)
	call	_objc_msgSend

	testl	%eax, %eax
	jz	fail_stret

	cmpl	12(%ebp), %eax
	je	fail_stret

	movl	%eax, 12(%ebp)

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	_objc_msgSend_stret

fail_stret:
	movl	12(%ebp), %eax
	movl	%eax, 8(%ebp)
	movl	16(%ebp), %eax
	movl	%eax, 12(%ebp)

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	_of_method_not_found

get_eip:
	movl	(%esp), %ebx
	ret







>








>













<












<
<
<
<
<




|




84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122
123
124
125





126
127
128
129
130
131
132
133
134
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L1:

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	L_sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	fail_stret

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	movl	L_sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	movl	16(%ebp), %eax
	movl	%eax, 8(%esp)
	call	_objc_msgSend

	testl	%eax, %eax
	jz	fail_stret

	cmpl	12(%ebp), %eax
	je	fail_stret

	movl	%eax, 12(%ebp)

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	_objc_msgSend_stret

fail_stret:





	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	_of_method_not_found_stret

get_eip:
	movl	(%esp), %ebx
	ret

Modified src/forwarding/apple-forwarding-ppc.S from [a34378a6db] to [744faa6cfb].

68
69
70
71
72
73
74

75
76

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
	bl	_object_getClass

	bl	L0
L0:
	mflr	r13
	addis	r13, r13, ha16(L_sel_forwardingTargetForSelector_-L0)
	lwz	r13, lo16(L_sel_forwardingTargetForSelector_-L0)(r13)

	mr	r4, r13
	bl	_class_respondsToSelector

	cmpwi	r3, 0
	beq-	fail

	lwz	r3, 216(r1)
	mr	r4, r13
	lwz	r5, 220(r1)
	bl	_objc_msgSend

	cmpwi	r3, 0
	beq-	fail

	lwz	r4, 216(r1)
	cmpw	r3, r4
	beq-	fail

	/* Restore all arguments and r13, except r3 */
	lwz	r4, 220(r1)
	lwz	r5, 56(r1)







>


>










<







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
	bl	_object_getClass

	bl	L0
L0:
	mflr	r13
	addis	r13, r13, ha16(L_sel_forwardingTargetForSelector_-L0)
	lwz	r13, lo16(L_sel_forwardingTargetForSelector_-L0)(r13)

	mr	r4, r13
	bl	_class_respondsToSelector

	cmpwi	r3, 0
	beq-	fail

	lwz	r3, 216(r1)
	mr	r4, r13
	lwz	r5, 220(r1)
	bl	_objc_msgSend

	cmpwi	r3, 0
	beq-	fail

	lwz	r4, 216(r1)
	cmpw	r3, r4
	beq-	fail

	/* Restore all arguments and r13, except r3 */
	lwz	r4, 220(r1)
	lwz	r5, 56(r1)
170
171
172
173
174
175
176

177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	bl	_object_getClass

	bl	L1
L1:
	mflr	r13
	addis	r13, r13, ha16(L_sel_forwardingTargetForSelector_-L1)
	lwz	r13, lo16(L_sel_forwardingTargetForSelector_-L1)(r13)

	mr	r4, r13
	bl	_class_respondsToSelector

	cmpwi	r3, 0
	beq-	fail_stret

	lwz	r3, 212(r1)
	mr	r4, r13
	lwz	r5, 216(r1)
	bl	_objc_msgSend

	cmpwi	r3, 0
	beq-	fail_stret

	lwz	r4, 212(r1)
	cmpw	r3, r4
	beq-	fail_stret

	mr	r4, r3

	/* Restore all arguments and r13, except r4 */







>


>










<







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
	bl	_object_getClass

	bl	L1
L1:
	mflr	r13
	addis	r13, r13, ha16(L_sel_forwardingTargetForSelector_-L1)
	lwz	r13, lo16(L_sel_forwardingTargetForSelector_-L1)(r13)

	mr	r4, r13
	bl	_class_respondsToSelector

	cmpwi	r3, 0
	beq-	fail_stret

	lwz	r3, 212(r1)
	mr	r4, r13
	lwz	r5, 216(r1)
	bl	_objc_msgSend

	cmpwi	r3, 0
	beq-	fail_stret

	lwz	r4, 212(r1)
	cmpw	r3, r4
	beq-	fail_stret

	mr	r4, r3

	/* Restore all arguments and r13, except r4 */
221
222
223
224
225
226
227
228
229

230
231
232
233
234
235
	addi	r1, r1, 184
	lwz	r0, 8(r1)
	mtlr	r0

	b	_objc_msgSend_stret

fail_stret:
	lwz	r3, 212(r1)
	lwz	r4, 216(r1)


	addi	r1, r1, 184
	lwz	r0, 8(r1)
	mtlr	r0

	b	_of_method_not_found







|
|
>





|
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
	addi	r1, r1, 184
	lwz	r0, 8(r1)
	mtlr	r0

	b	_objc_msgSend_stret

fail_stret:
	lwz	r3, 208(r1)
	lwz	r4, 212(r1)
	lwz	r5, 216(r1)

	addi	r1, r1, 184
	lwz	r0, 8(r1)
	mtlr	r0

	b	_of_method_not_found_stret

Modified src/forwarding/apple-forwarding-x86_64.S from [b4c76d8ed5] to [541a8f5d95].

52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72


73
74
75
76
77
78
79
	movdqa	%xmm7, -0xC0(%rbp)

	call	_object_getClass

	movq	%rax, %rdi
	movq	L_sel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector

	testq	%rax, %rax
	jz	fail

	movq	-0x10(%rbp), %rdi
	movq	L_sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	_objc_msgSend
	movq	%rax, %rdi

	testq	%rdi, %rdi
	jz	fail

	cmpq	-0x10(%rbp), %rdi
	je	fail



	/* Restore all arguments, except %rdi */
	movdqa	-0xC0(%rbp), %xmm7
	movdqa	-0xB0(%rbp), %xmm6
	movdqa	-0xA0(%rbp), %xmm5
	movdqa	-0x90(%rbp), %xmm4
	movdqa	-0x80(%rbp), %xmm3







>







<

|

<
|

>
>







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69

70
71
72
73
74
75
76
77
78
79
80
	movdqa	%xmm7, -0xC0(%rbp)

	call	_object_getClass

	movq	%rax, %rdi
	movq	L_sel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector

	testq	%rax, %rax
	jz	fail

	movq	-0x10(%rbp), %rdi
	movq	L_sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	_objc_msgSend


	testq	%rax, %rax
	jz	fail

	cmpq	-0x10(%rbp), %rax
	je	fail

	movq	%rax, %rdi

	/* Restore all arguments, except %rdi */
	movdqa	-0xC0(%rbp), %xmm7
	movdqa	-0xB0(%rbp), %xmm6
	movdqa	-0xA0(%rbp), %xmm5
	movdqa	-0x90(%rbp), %xmm4
	movdqa	-0x80(%rbp), %xmm3
132
133
134
135
136
137
138
139
140
141
142
143
144
145


146
147
148
149
150
151
152
	testq	%rax, %rax
	jz	fail_stret

	movq	-0x18(%rbp), %rdi
	movq	L_sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	_objc_msgSend
	movq	%rax, %rsi

	testq	%rsi, %rsi
	jz	fail_stret

	cmpq	-0x18(%rbp), %rsi
	je	fail_stret



	/* Restore all arguments, except %rsi */
	movdqa	-0xC0(%rbp), %xmm7
	movdqa	-0xB0(%rbp), %xmm6
	movdqa	-0xA0(%rbp), %xmm5
	movdqa	-0x90(%rbp), %xmm4
	movdqa	-0x80(%rbp), %xmm3







<

|

<
|

>
>







133
134
135
136
137
138
139

140
141
142

143
144
145
146
147
148
149
150
151
152
153
	testq	%rax, %rax
	jz	fail_stret

	movq	-0x18(%rbp), %rdi
	movq	L_sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	_objc_msgSend


	testq	%rax, %rax
	jz	fail_stret

	cmpq	-0x18(%rbp), %rax
	je	fail_stret

	movq	%rax, %rsi

	/* Restore all arguments, except %rsi */
	movdqa	-0xC0(%rbp), %xmm7
	movdqa	-0xB0(%rbp), %xmm6
	movdqa	-0xA0(%rbp), %xmm5
	movdqa	-0x90(%rbp), %xmm4
	movdqa	-0x80(%rbp), %xmm3
162
163
164
165
166
167
168

169
170
171
172
173
174
175

	movq	%rbp, %rsp
	popq	%rbp

	jmp	_objc_msgSend_stret

fail_stret:

	movq	-0x18(%rbp), %rdi
	movq	-0x20(%rbp), %rsi

	movq	%rbp, %rsp
	popq	%rbp

	jmp	_of_method_not_found







>
|
|




|
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

	movq	%rbp, %rsp
	popq	%rbp

	jmp	_objc_msgSend_stret

fail_stret:
	movq	-0x10(%rbp), %rdi
	movq	-0x18(%rbp), %rsi
	movq	-0x20(%rbp), %rdx

	movq	%rbp, %rsp
	popq	%rbp

	jmp	_of_method_not_found_stret

Modified src/forwarding/forwarding-amd64-elf.S from [6c6e2ed7b7] to [55f7a74c19].

36
37
38
39
40
41
42



43







44

45
46
47
48






49
50
51
52
53
54
55
	movdqa	%xmm2, -0x70(%rbp)
	movdqa	%xmm3, -0x80(%rbp)
	movdqa	%xmm4, -0x90(%rbp)
	movdqa	%xmm5, -0xA0(%rbp)
	movdqa	%xmm6, -0xB0(%rbp)
	movdqa	%xmm7, -0xC0(%rbp)




	leaq	sel_forwardingTargetForSelector_(%rip), %rsi







	call	objc_msg_lookup@PLT

	movq	-0x10(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	*%rax






	movq	%rax, -0x10(%rbp)

	movq	%rax, %rdi
	movq	-0x18(%rbp), %rsi
	call	objc_msg_lookup@PLT
	movq	%rax, %r11








>
>
>

>
>
>
>
>
>
>

>




>
>
>
>
>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	movdqa	%xmm2, -0x70(%rbp)
	movdqa	%xmm3, -0x80(%rbp)
	movdqa	%xmm4, -0x90(%rbp)
	movdqa	%xmm5, -0xA0(%rbp)
	movdqa	%xmm6, -0xB0(%rbp)
	movdqa	%xmm7, -0xC0(%rbp)

	call	object_getClass@PLT

	movq	%rax, %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	class_respondsToSelector@PLT

	testq	%rax, %rax
	jz	fail

	movq	-0x10(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	objc_msg_lookup@PLT

	movq	-0x10(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	fail
	cmpq	-0x10(%rbp), %rax
	je	fail

	movq	%rax, -0x10(%rbp)

	movq	%rax, %rdi
	movq	-0x18(%rbp), %rsi
	call	objc_msg_lookup@PLT
	movq	%rax, %r11

70
71
72
73
74
75
76









77
78
79
80
81
82
83
	movq	-0x10(%rbp), %rdi
	movq	-0x8(%rbp), %rax

	movq	%rbp, %rsp
	popq	%rbp

	jmpq     *%r11









.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
	pushq	%rbp
	movq	%rsp, %rbp








>
>
>
>
>
>
>
>
>







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
	movq	-0x10(%rbp), %rdi
	movq	-0x8(%rbp), %rax

	movq	%rbp, %rsp
	popq	%rbp

	jmpq     *%r11

fail:
	movq	-0x10(%rbp), %rdi
	movq	-0x18(%rbp), %rsi

	movq	%rbp, %rsp
	popq	%rbp

	jmp	of_method_not_found@PLT
.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
	pushq	%rbp
	movq	%rsp, %rbp

96
97
98
99
100
101
102



103







104

105
106
107
108






109
110
111
112
113
114
115
	movdqa	%xmm3, -0x80(%rbp)
	movdqa	%xmm4, -0x90(%rbp)
	movdqa	%xmm5, -0xA0(%rbp)
	movdqa	%xmm6, -0xB0(%rbp)
	movdqa	%xmm7, -0xC0(%rbp)

	movq	%rsi, %rdi



	leaq	sel_forwardingTargetForSelector_(%rip), %rsi







	call	objc_msg_lookup@PLT

	movq	-0x18(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	*%rax






	movq	%rax, -0x18(%rbp)

	movq	%rax, %rdi
	movq	-0x20(%rbp), %rsi
	call	objc_msg_lookup_stret@PLT
	movq	%rax, %r11








>
>
>

>
>
>
>
>
>
>

>




>
>
>
>
>
>







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
	movdqa	%xmm3, -0x80(%rbp)
	movdqa	%xmm4, -0x90(%rbp)
	movdqa	%xmm5, -0xA0(%rbp)
	movdqa	%xmm6, -0xB0(%rbp)
	movdqa	%xmm7, -0xC0(%rbp)

	movq	%rsi, %rdi
	call	object_getClass@PLT

	movq	%rax, %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	class_respondsToSelector@PLT

	testq	%rax, %rax
	jz	fail_stret

	movq	-0x18(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	objc_msg_lookup@PLT

	movq	-0x18(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	fail_stret
	cmpq	-0x18(%rbp), %rax
	je	fail_stret

	movq	%rax, -0x18(%rbp)

	movq	%rax, %rdi
	movq	-0x20(%rbp), %rsi
	call	objc_msg_lookup_stret@PLT
	movq	%rax, %r11

130
131
132
133
134
135
136










137
138
139
140
141
142
143
	movq	-0x10(%rbp), %rdi
	movq	-0x8(%rbp), %rax

	movq	%rbp, %rsp
	popq	%rbp

	jmpq     *%r11










.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

init:
	leaq	module(%rip), %rdi
	jmp	__objc_exec_class@PLT








>
>
>
>
>
>
>
>
>
>







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	movq	-0x10(%rbp), %rdi
	movq	-0x8(%rbp), %rax

	movq	%rbp, %rsp
	popq	%rbp

	jmpq     *%r11

fail_stret:
	movq	-0x10(%rbp), %rdi
	movq	-0x18(%rbp), %rsi
	movq	-0x20(%rbp), %rdx

	movq	%rbp, %rsp
	popq	%rbp

	jmp	of_method_not_found_stret@PLT
.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

init:
	leaq	module(%rip), %rdi
	jmp	__objc_exec_class@PLT

Modified src/forwarding/forwarding-arm-elf.S from [78ba43410f] to [81907b6d08].

15
16
17
18
19
20
21
22
23
24
25
26
27
28










29
30
31
32
33

34
35






36
37
38
39
40
41
42
43
44
45





46
47
48
49
50
51
52
53
54
55
56
57











58
59
60
61
62

63
64
65






66
67
68
69
70
71
72
73
74





75
76
77
78
79
80
81
 */

.globl of_forward
.globl of_forward_stret

.section .text
of_forward:
	stmfd	sp!, {r0-r3, lr}
	fstmfdd	sp!, {d0-d7}

	ldr	r1, sel_forwardingTargetForSelector_$indirect_L0
.L0:
	add	r1, pc
	stmfd	sp!, {r1}










	bl	objc_msg_lookup(PLT)
	ldmfd	sp!, {r1}

	mov	r12, r0
	ldr	r0, [sp, #64]

	ldr	r2, [sp, #68]
	blx	r12







	str	r0, [sp, #64]
	ldr	r1, [sp, #68]
	bl	objc_msg_lookup(PLT)

	mov	r12, r0
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r3, lr}

	bx	r12





.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
	stmfd	sp!, {r0-r3, lr}
	fstmfdd	sp!, {d0-d7}

	mov	r0, r1
	ldr	r1, sel_forwardingTargetForSelector_$indirect_L1
.L1:
	add	r1, pc
	stmfd	sp!, {r1}











	bl	objc_msg_lookup(PLT)
	ldmfd	sp!, {r1}

	mov	r12, r0
	ldr	r0, [sp, #68]

	ldr	r2, [sp, #72]
	blx	r12







	str	r0, [sp, #68]
	ldr	r1, [sp, #72]
	bl	objc_msg_lookup_stret(PLT)

	mov	r12, r0
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r3, lr}

	bx	r12





.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

init:
	ldr	r0, module_indirect_L2
.L2:
	add	r0, pc







|


|

|
|
>
>
>
>
>
>
>
>
>
>

<



>


>
>
>
>
>
>







|


>
>
>
>
>




|


<
|

|
|
>
>
>
>
>
>
>
>
>
>
>

<



>



>
>
>
>
>
>






|


>
>
>
>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
 */

.globl of_forward
.globl of_forward_stret

.section .text
of_forward:
	stmfd	sp!, {r0-r4, lr}
	fstmfdd	sp!, {d0-d7}

	ldr	r4, sel_forwardingTargetForSelector_$indirect_L0
.L0:
	add	r4, pc

	bl	object_getClass(PLT)

	mov	r1, r4
	bl	class_respondsToSelector(PLT)

	cmp	r0, #0
	beq	fail

	ldr	r0, [sp, #64]
	mov	r1, r4
	bl	objc_msg_lookup(PLT)


	mov	r12, r0
	ldr	r0, [sp, #64]
	mov	r1, r4
	ldr	r2, [sp, #68]
	blx	r12

	cmp	r0, #0
	beq	fail
	ldr	r1, [sp, #64]
	cmp	r0, r1
	beq	fail

	str	r0, [sp, #64]
	ldr	r1, [sp, #68]
	bl	objc_msg_lookup(PLT)

	mov	r12, r0
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}

	bx	r12

fail:
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}
	b	of_method_not_found(PLT)
.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
	stmfd	sp!, {r0-r4, lr}
	fstmfdd	sp!, {d0-d7}


	ldr	r4, sel_forwardingTargetForSelector_$indirect_L1
.L1:
	add	r4, pc

	mov	r0, r1
	bl	object_getClass(PLT)

	mov	r1, r4
	bl	class_respondsToSelector(PLT)

	cmp	r0, #0
	beq	fail_stret

	ldr	r0, [sp, #68]
	mov	r1, r4
	bl	objc_msg_lookup(PLT)


	mov	r12, r0
	ldr	r0, [sp, #68]
	mov	r1, r4
	ldr	r2, [sp, #72]
	blx	r12

	cmp	r0, #0
	beq	fail_stret
	ldr	r1, [sp, #68]
	cmp	r0, r1
	beq	fail_stret

	str	r0, [sp, #68]
	ldr	r1, [sp, #72]
	bl	objc_msg_lookup_stret(PLT)

	mov	r12, r0
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}

	bx	r12

fail_stret:
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}
	b	of_method_not_found_stret(PLT)
.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

init:
	ldr	r0, module_indirect_L2
.L2:
	add	r0, pc

Modified src/forwarding/forwarding-mips-elf.S from [ee8ef78a0b] to [685a078982].

12
13
14
15
16
17
18


















19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66

67
68




69



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89






90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118



119
120
121
122
123
124
125
126


127





128



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178


179
180




181



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201






202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230



231
232
233
234
235
236
237
238


239






240



241
242
243
244
245
246
247
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

.globl of_forward
.globl of_forward_stret



















.section .text
of_forward:
#ifdef __PIC__
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
#endif

	addiu	$sp, $sp, -72

	/*
	 * O32: The registers for floating point arguments don't need to be
	 * saved, as the ABI specifies that all remaining arguments are passed
	 * in integer registers if the first argument is passed in an integer
	 * register. This is always the case, as the first argument is always
	 * self.
	 */
	sw	$gp, 0($sp)
	sw	$ra, 4($sp)



	sw	$a0, 8($sp)
	sw	$a1, 12($sp)
	sw	$a2, 16($sp)
	sw	$a3, 20($sp)
#ifdef __mips_eabi
	/* For some reason, $a4-$a8 are not always defined */
	sw	$8, 24($sp)
	sw	$9, 28($sp)
	sw	$10, 32($sp)
	sw	$11, 36($sp)

	swc1	$f12, 40($sp)
	swc1	$f13, 44($sp)
	swc1	$f14, 48($sp)
	swc1	$f15, 52($sp)
	swc1	$f16, 56($sp)
	swc1	$f17, 60($sp)
	swc1	$f18, 64($sp)
	swc1	$f19, 68($sp)
#endif


#ifdef __PIC__
	lw	$a1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$a1, %hi(sel_forwardingTargetForSelector_)
#endif
	addiu	$a1, $a1, %lo(sel_forwardingTargetForSelector_)
#ifdef __PIC__

	lw	$t9, %call16(objc_msg_lookup)($gp)
	jalr	$t9




#else



	jal	objc_msg_lookup
#endif

	lw	$gp, 0($sp)
	lw	$a0, 8($sp)
#ifdef __PIC__
	lw	$a1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$a1, %hi(sel_forwardingTargetForSelector_)
#endif
	addiu	$a1, $a1, %lo(sel_forwardingTargetForSelector_)
	lw	$a2, 12($sp)
#ifdef __PIC__
	move	$t9, $v0
	jalr	$t9
#else
	jalr	$v0
#endif
	sw	$v0, 8($sp)







	lw	$gp, 0($sp)
	move	$a0, $v0
	lw	$a1, 12($sp)
#ifdef __PIC__
	lw	$t9, %call16(objc_msg_lookup)($gp)
	jalr	$t9
#else
	jal	objc_msg_lookup
#endif

#ifdef __mips_eabi
	lwc1	$f19, 68($sp)
	lwc1	$f18, 64($sp)
	lwc1	$f17, 60($sp)
	lwc1	$f16, 56($sp)
	lwc1	$f15, 52($sp)
	lwc1	$f14, 48($sp)
	lwc1	$f13, 44($sp)
	lwc1	$f12, 40($sp)

	lw	$11, 36($sp)
	lw	$10, 32($sp)
	lw	$9, 28($sp)
	lw	$8, 24($sp)
#endif
	lw	$a3, 20($sp)
	lw	$a2, 16($sp)
	lw	$a1, 12($sp)
	lw	$a0, 8($sp)



	lw	$ra, 4($sp)

	addiu	$sp, $sp, 72

#ifdef __PIC__
	move	$t9, $v0
	jr	$t9
#else


	jr	$v0





#endif



.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
#ifdef __PIC__
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
#endif

	addiu	$sp, $sp, -72

	/*
	 * O32: The registers for floating point arguments don't need to be
	 * saved, as the ABI specifies that all remaining arguments are passed
	 * in integer registers if the first argument is passed in an integer
	 * register. This is always the case, as the first argument is always
	 * self.
	 */
	sw	$gp, 0($sp)
	sw	$ra, 4($sp)



	sw	$a0, 8($sp)
	sw	$a1, 12($sp)
	sw	$a2, 16($sp)
	sw	$a3, 20($sp)
#ifdef __mips_eabi
	/* For some reason, $a4-$a8 are not always defined */
	sw	$8, 24($sp)
	sw	$9, 28($sp)
	sw	$10, 32($sp)
	sw	$11, 36($sp)

	swc1	$f12, 40($sp)
	swc1	$f13, 44($sp)
	swc1	$f14, 48($sp)
	swc1	$f15, 52($sp)
	swc1	$f16, 56($sp)
	swc1	$f17, 60($sp)
	swc1	$f18, 64($sp)
	swc1	$f19, 68($sp)
#endif

	move	$a0, $a1
#ifdef __PIC__
	lw	$a1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$a1, %hi(sel_forwardingTargetForSelector_)
#endif
	addiu	$a1, $a1, %lo(sel_forwardingTargetForSelector_)
#ifdef __PIC__


	lw	$t9, %call16(objc_msg_lookup)($gp)
	jalr	$t9




#else



	jal	objc_msg_lookup
#endif

	lw	$gp, 0($sp)
	lw	$a0, 12($sp)
#ifdef __PIC__
	lw	$a1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$a1, %hi(sel_forwardingTargetForSelector_)
#endif
	addiu	$a1, $a1, %lo(sel_forwardingTargetForSelector_)
	lw	$a2, 16($sp)
#ifdef __PIC__
	move	$t9, $v0
	jalr	$t9
#else
	jalr	$v0
#endif
	sw	$v0, 12($sp)







	lw	$gp, 0($sp)
	move	$a0, $v0
	lw	$a1, 16($sp)
#ifdef __PIC__
	lw	$t9, %call16(objc_msg_lookup_stret)($gp)
	jalr	$t9
#else
	jal	objc_msg_lookup_stret
#endif

#ifdef __mips_eabi
	lwc1	$f19, 68($sp)
	lwc1	$f18, 64($sp)
	lwc1	$f17, 60($sp)
	lwc1	$f16, 56($sp)
	lwc1	$f15, 52($sp)
	lwc1	$f14, 48($sp)
	lwc1	$f13, 44($sp)
	lwc1	$f12, 40($sp)

	lw	$11, 36($sp)
	lw	$10, 32($sp)
	lw	$9, 28($sp)
	lw	$8, 24($sp)
#endif
	lw	$a3, 20($sp)
	lw	$a2, 16($sp)
	lw	$a1, 12($sp)
	lw	$a0, 8($sp)



	lw	$ra, 4($sp)

	addiu	$sp, $sp, 72

#ifdef __PIC__
	move	$t9, $v0
	jr	$t9
#else


	jr	$v0






#endif



.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

init:
#ifdef __PIC__
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|








<
|
>
>
>
|
|
|
|


|
|
|
|

|
|
|
|
|
|
|
|


>

|

|

|
|
>
|
|
>
>
>
>
|
>
>
>
|
<

|
|
<
<
<
<
<
|
|
<


<
<
<
<

>
>
>
>
>
>
|

|
<
<
<
<
|
<


|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
>
>
>
|

|

<


|
>
>
|
>
>
>
>
>
|
>
>
>










|








<
|
>
>
>
|
|
|
|


|
|
|
|

|
|
|
|
|
|
|
|


|

|

|

|
|
>
>
|
|
>
>
>
>
|
>
>
>
|
<

|
|
<
<
<
<
<
|
|
<


<
<
<
<

>
>
>
>
>
>
|

|
<
<
<
<
|
<


|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
>
>
>
|

|

<


|
>
>
|
>
>
>
>
>
>
|
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100
101
102





103
104

105
106




107
108
109
110
111
112
113
114
115
116




117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

225
226
227





228
229

230
231




232
233
234
235
236
237
238
239
240
241




242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

.globl of_forward
.globl of_forward_stret

#ifdef __PIC__
.macro j_pic symbol
	lw	$t9, %call16(\symbol)($gp)
	jr	$t9
.endm
.macro jal_pic symbol
	lw	$t9, %call16(\symbol)($gp)
	jalr	$t9
.endm
#else
.macro j_pic symbol
	j	\symbol
.endm
.macro jal_pic symbol
	jal	\symbol
.endm
#endif

.section .text
of_forward:
#ifdef __PIC__
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
#endif

	addiu	$sp, $sp, -96

	/*
	 * O32: The registers for floating point arguments don't need to be
	 * saved, as the ABI specifies that all remaining arguments are passed
	 * in integer registers if the first argument is passed in an integer
	 * register. This is always the case, as the first argument is always
	 * self.
	 */

	sw	$ra, 16($sp)
	sw	$s0, 20($sp)
	sw	$s1, 24($sp)

	sw	$a0, 28($sp)
	sw	$a1, 32($sp)
	sw	$a2, 36($sp)
	sw	$a3, 40($sp)
#ifdef __mips_eabi
	/* For some reason, $a4-$a8 are not always defined */
	sw	$8, 44($sp)
	sw	$9, 48($sp)
	sw	$10, 52($sp)
	sw	$11, 56($sp)

	swc1	$f12, 60($sp)
	swc1	$f13, 64($sp)
	swc1	$f14, 68($sp)
	swc1	$f15, 72($sp)
	swc1	$f16, 76($sp)
	swc1	$f17, 80($sp)
	swc1	$f18, 84($sp)
	swc1	$f19, 88($sp)
#endif

	move	$s0, $gp
#ifdef __PIC__
	lw	$s1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$s1, %hi(sel_forwardingTargetForSelector_)
#endif
	addiu	$s1, $s1, %lo(sel_forwardingTargetForSelector_)

	jal_pic	object_getClass

	move	$gp, $s0
	move	$a0, $v0
	move	$a1, $s1
	jal_pic	class_respondsToSelector
	beqz	$v0, fail

	move	$gp, $s0
	lw	$a0, 28($sp)
	move	$a1, $s1
	jal_pic	objc_msg_lookup


	move	$gp, $s0
	lw	$a0, 28($sp)





	move	$a1, $s1
	lw	$a2, 32($sp)

	move	$t9, $v0
	jalr	$t9





	beqz	$v0, fail
	lw	$t0, 28($sp)
	beq	$v0, $t0, fail

	sw	$v0, 28($sp)

	move	$gp, $s0
	move	$a0, $v0
	lw	$a1, 32($sp)




	jal_pic	objc_msg_lookup


#ifdef __mips_eabi
	lwc1	$f19, 88($sp)
	lwc1	$f18, 84($sp)
	lwc1	$f17, 80($sp)
	lwc1	$f16, 76($sp)
	lwc1	$f15, 72($sp)
	lwc1	$f14, 68($sp)
	lwc1	$f13, 64($sp)
	lwc1	$f12, 60($sp)

	lw	$11, 56($sp)
	lw	$10, 52($sp)
	lw	$9, 48($sp)
	lw	$8, 44($sp)
#endif
	lw	$a3, 40($sp)
	lw	$a2, 36($sp)
	lw	$a1, 32($sp)
	lw	$a0, 28($sp)

	lw	$s1, 24($sp)
	lw	$s0, 20($sp)
	lw	$ra, 16($sp)

	addiu	$sp, $sp, 96


	move	$t9, $v0
	jr	$t9

fail:
	move	$gp, $s0

	lw	$a1, 32($sp)
	lw	$a0, 28($sp)
	lw	$s1, 24($sp)
	lw	$s0, 20($sp)
	lw	$ra, 16($sp)

	addiu	$sp, $sp, 96

	j_pic	of_method_not_found
.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
#ifdef __PIC__
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
#endif

	addiu	$sp, $sp, -96

	/*
	 * O32: The registers for floating point arguments don't need to be
	 * saved, as the ABI specifies that all remaining arguments are passed
	 * in integer registers if the first argument is passed in an integer
	 * register. This is always the case, as the first argument is always
	 * self.
	 */

	sw	$ra, 16($sp)
	sw	$s0, 20($sp)
	sw	$s1, 24($sp)

	sw	$a0, 28($sp)
	sw	$a1, 32($sp)
	sw	$a2, 36($sp)
	sw	$a3, 40($sp)
#ifdef __mips_eabi
	/* For some reason, $a4-$a8 are not always defined */
	sw	$8, 44($sp)
	sw	$9, 48($sp)
	sw	$10, 52($sp)
	sw	$11, 56($sp)

	swc1	$f12, 60($sp)
	swc1	$f13, 64($sp)
	swc1	$f14, 68($sp)
	swc1	$f15, 72($sp)
	swc1	$f16, 76($sp)
	swc1	$f17, 80($sp)
	swc1	$f18, 84($sp)
	swc1	$f19, 88($sp)
#endif

	move	$s0, $gp
#ifdef __PIC__
	lw	$s1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$s1, %hi(sel_forwardingTargetForSelector_)
#endif
	addiu	$s1, $s1, %lo(sel_forwardingTargetForSelector_)

	move	$a0, $a1
	jal_pic	object_getClass

	move	$gp, $s0
	move	$a0, $v0
	move	$a1, $s1
	jal_pic	class_respondsToSelector
	beqz	$v0, fail_stret

	move	$gp, $s0
	lw	$a0, 32($sp)
	move	$a1, $s1
	jal_pic	objc_msg_lookup


	move	$gp, $s0
	lw	$a0, 32($sp)





	move	$a1, $s1
	lw	$a2, 36($sp)

	move	$t9, $v0
	jalr	$t9





	beqz	$v0, fail_stret
	lw	$t0, 32($sp)
	beq	$v0, $t0, fail_stret

	sw	$v0, 32($sp)

	move	$gp, $s0
	move	$a0, $v0
	lw	$a1, 36($sp)




	jal_pic	objc_msg_lookup_stret


#ifdef __mips_eabi
	lwc1	$f19, 88($sp)
	lwc1	$f18, 84($sp)
	lwc1	$f17, 80($sp)
	lwc1	$f16, 76($sp)
	lwc1	$f15, 72($sp)
	lwc1	$f14, 68($sp)
	lwc1	$f13, 64($sp)
	lwc1	$f12, 60($sp)

	lw	$11, 56($sp)
	lw	$10, 52($sp)
	lw	$9, 48($sp)
	lw	$8, 44($sp)
#endif
	lw	$a3, 40($sp)
	lw	$a2, 36($sp)
	lw	$a1, 32($sp)
	lw	$a0, 28($sp)

	lw	$s1, 24($sp)
	lw	$s0, 20($sp)
	lw	$ra, 16($sp)

	addiu	$sp, $sp, 96


	move	$t9, $v0
	jr	$t9

fail_stret:
	move	$gp, $s0

	lw	$a2, 36($sp)
	lw	$a1, 32($sp)
	lw	$a0, 28($sp)
	lw	$s1, 24($sp)
	lw	$s0, 20($sp)
	lw	$ra, 16($sp)

	addiu	$sp, $sp, 96

	j_pic	of_method_not_found_stret
.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

init:
#ifdef __PIC__
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)

Modified src/forwarding/forwarding-ppc-elf.S from [8b57a5618e] to [09cadab137].

39
40
41
42
43
44
45










46
47
48
49
50
51
52
53
54
55







56
57
58
59
60
61
62
	stfd	%f3, 56(%r1)
	stfd	%f4, 64(%r1)
	stfd	%f5, 72(%r1)
	stfd	%f6, 80(%r1)
	stfd	%f7, 88(%r1)
	stfd	%f8, 96(%r1)











	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	objc_msg_lookup@plt
	mtctr	%r3

	lwz	%r3, 8(%r1)
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	lwz	%r5, 12(%r1)
	bctrl







	stw	%r3, 8(%r1)

	lwz	%r4, 12(%r1)
	bl	objc_msg_lookup@plt
	mtctr	%r3

	/* Restore all arguments */







>
>
>
>
>
>
>
>
>
>










>
>
>
>
>
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
	stfd	%f3, 56(%r1)
	stfd	%f4, 64(%r1)
	stfd	%f5, 72(%r1)
	stfd	%f6, 80(%r1)
	stfd	%f7, 88(%r1)
	stfd	%f8, 96(%r1)

	bl	object_getClass@plt

	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	class_respondsToSelector@plt

	cmpwi	%r3, 0
	beq-	fail

	lwz	%r3, 8(%r1)
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	objc_msg_lookup@plt
	mtctr	%r3

	lwz	%r3, 8(%r1)
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	lwz	%r5, 12(%r1)
	bctrl

	cmpwi	%r3, 0
	beq-	fail
	lwz	%r4, 8(%r1)
	cmpw	%r3, %r4
	beq-	fail

	stw	%r3, 8(%r1)

	lwz	%r4, 12(%r1)
	bl	objc_msg_lookup@plt
	mtctr	%r3

	/* Restore all arguments */
79
80
81
82
83
84
85










86
87
88
89
90
91
92
	lfd	%f7, 88(%r1)
	lfd	%f8, 96(%r1)

	lwz	%r0, 116(%r1)
	mtlr	%r0
	addi	%r1, %r1, 112
	bctr










.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
	stwu	%r1, -112(%r1)
	mflr	%r0
	stw	%r0, 116(%r1)







>
>
>
>
>
>
>
>
>
>







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
	lfd	%f7, 88(%r1)
	lfd	%f8, 96(%r1)

	lwz	%r0, 116(%r1)
	mtlr	%r0
	addi	%r1, %r1, 112
	bctr

fail:
	lwz	%r3, 8(%r1)
	lwz	%r4, 12(%r1)

	lwz	%r0, 116(%r1)
	mtlr	%r0
	addi	%r1, %r1, 112

	b	of_method_not_found@plt
.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
	stwu	%r1, -112(%r1)
	mflr	%r0
	stw	%r0, 116(%r1)
108
109
110
111
112
113
114










115
116
117
118
119
120
121
122
123
124







125
126
127
128
129
130
131
	stfd	%f4, 64(%r1)
	stfd	%f5, 72(%r1)
	stfd	%f6, 80(%r1)
	stfd	%f7, 88(%r1)
	stfd	%f8, 96(%r1)

	mr	%r3, %r4










	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	objc_msg_lookup@plt
	mtctr	%r3

	lwz	%r3, 12(%r1)
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	lwz	%r5, 16(%r1)
	bctrl







	stw	%r3, 12(%r1)

	lwz	%r4, 16(%r1)
	bl	objc_msg_lookup_stret@plt
	mtctr	%r3

	/* Restore all arguments */







>
>
>
>
>
>
>
>
>
>










>
>
>
>
>
>
>







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
	stfd	%f4, 64(%r1)
	stfd	%f5, 72(%r1)
	stfd	%f6, 80(%r1)
	stfd	%f7, 88(%r1)
	stfd	%f8, 96(%r1)

	mr	%r3, %r4
	bl	object_getClass@plt

	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	class_respondsToSelector@plt

	cmpwi	%r3, 0
	beq-	fail_stret

	lwz	%r3, 12(%r1)
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	objc_msg_lookup@plt
	mtctr	%r3

	lwz	%r3, 12(%r1)
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	lwz	%r5, 16(%r1)
	bctrl

	cmpwi	%r3, 0
	beq-	fail_stret
	lwz	%r4, 12(%r1)
	cmpw	%r3, %r4
	beq-	fail_stret

	stw	%r3, 12(%r1)

	lwz	%r4, 16(%r1)
	bl	objc_msg_lookup_stret@plt
	mtctr	%r3

	/* Restore all arguments */
148
149
150
151
152
153
154











155
156
157
158
159
160
161
	lfd	%f7, 88(%r1)
	lfd	%f8, 96(%r1)

	lwz	%r0, 116(%r1)
	mtlr	%r0
	addi	%r1, %r1, 112
	bctr











.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

init:
	lis	%r3, module@ha
	la	%r3, module@l(%r3)
	b	__objc_exec_class@plt







>
>
>
>
>
>
>
>
>
>
>







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
	lfd	%f7, 88(%r1)
	lfd	%f8, 96(%r1)

	lwz	%r0, 116(%r1)
	mtlr	%r0
	addi	%r1, %r1, 112
	bctr

fail_stret:
	lwz	%r3, 8(%r1)
	lwz	%r4, 12(%r1)
	lwz	%r5, 16(%r1)

	lwz	%r0, 116(%r1)
	mtlr	%r0
	addi	%r1, %r1, 112

	b	of_method_not_found_stret@plt
.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

init:
	lis	%r3, module@ha
	la	%r3, module@l(%r3)
	b	__objc_exec_class@plt

Modified src/forwarding/forwarding-x86-elf.S from [79691a7caf] to [0ee5fb8e08].

23
24
25
26
27
28
29















30
31
32
33
34
35
36
37
38
39
40
41
42
43





44
45
46
47
48
49
50
51









52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68















69
70
71
72
73
74
75
76
77
78
79
80
81
82





83
84
85
86
87
88
89
90









91
92
93
94
95
96
97
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L0:















	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	objc_msg_lookup-.L0(%ebx), %eax
	call	*%eax

	movl	8(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	12(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax






	movl	%eax, 8(%ebp)
	movl	%eax, (%esp)
	movl	12(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	objc_msg_lookup-.L0(%ebx), %eax
	call	*%eax










	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L1:















	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	objc_msg_lookup-.L1(%ebx), %eax
	call	*%eax

	movl	12(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	16(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax






	movl	%eax, 12(%ebp)
	movl	%eax, (%esp)
	movl	16(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	objc_msg_lookup_stret-.L1(%ebx), %eax
	call	*%eax










	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














>
>
>
>
>








>
>
>
>
>
>
>
>
>

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














>
>
>
>
>








>
>
>
>
>
>
>
>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L0:

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	leal	object_getClass-.L0(%ebx), %eax
	call	*%eax

	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	class_respondsToSelector-.L0(%ebx), %eax
	call	*%eax

	testl	%eax, %eax
	jz	fail

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	objc_msg_lookup-.L0(%ebx), %eax
	call	*%eax

	movl	8(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	12(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	fail
	cmpl	8(%ebp), %eax
	je	fail

	movl	%eax, 8(%ebp)
	movl	%eax, (%esp)
	movl	12(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	objc_msg_lookup-.L0(%ebx), %eax
	call	*%eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

fail:
	leal	of_method_not_found-.L0(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type of_forward, %function
.size of_forward, .-of_forward

of_forward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L1:

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	leal	object_getClass-.L1(%ebx), %eax
	call	*%eax

	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	class_respondsToSelector-.L1(%ebx), %eax
	call	*%eax

	testl	%eax, %eax
	jz	fail_stret

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	objc_msg_lookup-.L1(%ebx), %eax
	call	*%eax

	movl	12(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	16(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	fail_stret
	cmpl	12(%ebp), %eax
	je	fail_stret

	movl	%eax, 12(%ebp)
	movl	%eax, (%esp)
	movl	16(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	objc_msg_lookup_stret-.L1(%ebx), %eax
	call	*%eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

fail_stret:
	leal	of_method_not_found_stret-.L1(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type of_forward_stret, %function
.size of_forward_stret, .-of_forward_stret

Modified src/forwarding/forwarding-x86-win32.S from [972226c4ef] to [8abd7a71aa].

23
24
25
26
27
28
29















30
31
32
33
34
35
36
37
38
39
40
41
42
43





44
45
46
47
48
49
50
51









52
53
54
55
56
57
58
59
60
61
62
63
64
65
66















67
68
69
70
71
72
73
74
75
76
77
78
79
80





81
82
83
84
85
86
87
88









89
90
91
92
93
94
95
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L0:















	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	_objc_msg_lookup-.L0(%ebx), %eax
	call	*%eax

	movl	8(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	12(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax






	movl	%eax, 8(%ebp)
	movl	%eax, (%esp)
	movl	12(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	_objc_msg_lookup-.L0(%ebx), %eax
	call	*%eax










	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

_of_forward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L1:















	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	_objc_msg_lookup-.L1(%ebx), %eax
	call	*%eax

	movl	12(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	16(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax






	movl	%eax, 12(%ebp)
	movl	%eax, (%esp)
	movl	16(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	_objc_msg_lookup_stret-.L1(%ebx), %eax
	call	*%eax










	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

init:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














>
>
>
>
>








>
>
>
>
>
>
>
>
>















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














>
>
>
>
>








>
>
>
>
>
>
>
>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L0:

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	leal	_object_getClass-.L0(%ebx), %eax
	call	*%eax

	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	_class_respondsToSelector-.L0(%ebx), %eax
	call	*%eax

	testl	%eax, %eax
	jz	fail

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	_objc_msg_lookup-.L0(%ebx), %eax
	call	*%eax

	movl	8(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_-.L0(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	12(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	fail
	cmpl	8(%ebp), %eax
	je	fail

	movl	%eax, 8(%ebp)
	movl	%eax, (%esp)
	movl	12(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	_objc_msg_lookup-.L0(%ebx), %eax
	call	*%eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

fail:
	leal	_of_method_not_found-.L0(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

_of_forward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
.L1:

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	leal	_object_getClass-.L1(%ebx), %eax
	call	*%eax

	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	_class_respondsToSelector-.L1(%ebx), %eax
	call	*%eax

	testl	%eax, %eax
	jz	fail_stret

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %eax
	movl	%eax, 4(%esp)
	leal	_objc_msg_lookup-.L1(%ebx), %eax
	call	*%eax

	movl	12(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_-.L1(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	16(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	fail_stret
	cmpl	12(%ebp), %eax
	je	fail_stret

	movl	%eax, 12(%ebp)
	movl	%eax, (%esp)
	movl	16(%ebp), %eax
	movl	%eax, 4(%esp)
	leal	_objc_msg_lookup_stret-.L1(%ebx), %eax
	call	*%eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

fail_stret:
	leal	_of_method_not_found_stret-.L1(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

init:

Modified src/runtime/lookup-asm/lookup-asm-amd64-elf.S from [0076c67932] to [6dd8fa4deb].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found_handler
\name:
	testq	%rdi, %rdi
	jz	ret_nil

	movq	(%rdi), %r8
	movq	64(%r8), %r8

.main_\name:
	movq	(%rsi), %rax
	movzbl	%ah, %ecx
	movzbl	%al, %edx
#ifdef OF_SELUID24
	shrl	$16, %eax

	movq	(%r8,%rax,8), %r8
#endif
	movq	(%r8,%rcx,8), %r8
	movq	(%r8,%rdx,8), %rax

	testq	%rax, %rax
	jz	\not_found_handler@PLT

	ret
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	movq	(%rdi), %rax
	testq	%rax, %rax
	jz	ret_nil

	movq	8(%rdi), %r8
	movq	64(%r8), %r8
	movq	%rdi, %rax
	jmp	.main_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_not_found_handler
generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	leaq	nil_method(%rip), %rax
	ret








|




















|




















|
|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	testq	%rdi, %rdi
	jz	ret_nil

	movq	(%rdi), %r8
	movq	64(%r8), %r8

.main_\name:
	movq	(%rsi), %rax
	movzbl	%ah, %ecx
	movzbl	%al, %edx
#ifdef OF_SELUID24
	shrl	$16, %eax

	movq	(%r8,%rax,8), %r8
#endif
	movq	(%r8,%rcx,8), %r8
	movq	(%r8,%rdx,8), %rax

	testq	%rax, %rax
	jz	\not_found@PLT

	ret
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	movq	(%rdi), %rax
	testq	%rax, %rax
	jz	ret_nil

	movq	8(%rdi), %r8
	movq	64(%r8), %r8
	movq	%rdi, %rax
	jmp	.main_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	leaq	nil_method(%rip), %rax
	ret

Modified src/runtime/lookup-asm/lookup-asm-amd64-macho.S from [9f2fcb9422] to [9d19d61727].

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

	movq	8(%rdi), %r8
	movq	64(%r8), %r8
	movq	%rdi, %rax
	jmp	Lmain$1
.endmacro

generate_lookup _objc_msg_lookup, _objc_not_found_handler
generate_lookup _objc_msg_lookup_stret, _objc_not_found_handler_stret
generate_lookup_super _objc_msg_lookup_super, _objc_msg_lookup
generate_lookup_super _objc_msg_lookup_super_stret, _objc_msg_lookup_stret

ret_nil:
	leaq	nil_method(%rip), %rax
	ret

nil_method:
	movq	%rdi, %rax
	ret







|
|










56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

	movq	8(%rdi), %r8
	movq	64(%r8), %r8
	movq	%rdi, %rax
	jmp	Lmain$1
.endmacro

generate_lookup _objc_msg_lookup, _objc_method_not_found
generate_lookup _objc_msg_lookup_stret, _objc_method_not_found_stret
generate_lookup_super _objc_msg_lookup_super, _objc_msg_lookup
generate_lookup_super _objc_msg_lookup_super_stret, _objc_msg_lookup_stret

ret_nil:
	leaq	nil_method(%rip), %rax
	ret

nil_method:
	movq	%rdi, %rax
	ret

Modified src/runtime/lookup-asm/lookup-asm-arm-elf.S from [79afacfbeb] to [3a32fa73f7].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found_handler
\name:
	cmp	r0, #0
	beq	ret_nil

	ldr	r2, [r0, #0]
	ldr	r2, [r2, #32]

.main_\name:
#ifdef OF_SELUID24
	ldrb	r3, [r1, #2]
	ldr	r2, [r2, r3, lsl #2]
#endif
	ldrb	r3, [r1, #1]
	ldr	r2, [r2, r3, lsl #2]
	ldrb	r3, [r1, #0]
	ldr	r2, [r2, r3, lsl #2]

	cmp	r2, #0
	beq	\not_found_handler(PLT)

	mov	r0, r2
	bx	lr
.type \name, %function
.size \name, .-\name
.endm








|


















|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	cmp	r0, #0
	beq	ret_nil

	ldr	r2, [r0, #0]
	ldr	r2, [r2, #32]

.main_\name:
#ifdef OF_SELUID24
	ldrb	r3, [r1, #2]
	ldr	r2, [r2, r3, lsl #2]
#endif
	ldrb	r3, [r1, #1]
	ldr	r2, [r2, r3, lsl #2]
	ldrb	r3, [r1, #0]
	ldr	r2, [r2, r3, lsl #2]

	cmp	r2, #0
	beq	\not_found(PLT)

	mov	r0, r2
	bx	lr
.type \name, %function
.size \name, .-\name
.endm

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
	ldr	r2, [r2, #32]

	b	.main_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_not_found_handler
generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	adr	r0, nil_method
	bx	lr








|
|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
	ldr	r2, [r2, #32]

	b	.main_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	adr	r0, nil_method
	bx	lr

Modified src/runtime/lookup-asm/lookup-asm-mips-elf.S from [48cdec849d] to [45689ef5fd].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found_handler
\name:
	beqz	$a0, .ret_nil_\name

	lw	$t0, 0($a0)
	lw	$t0, 32($t0)

.main_\name:







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	beqz	$a0, .ret_nil_\name

	lw	$t0, 0($a0)
	lw	$t0, 32($t0)

.main_\name:
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
	lw	$t0, 0($t0)
	addu	$t0, $t0, $t3
	lw	$t0, 0($t0)

#ifdef __PIC__
	beqz	$t0, .forward_\name
#else
	beqz	$t0, \not_found_handler
#endif

	move	$v0, $t0
	j	$ra

.ret_nil_\name:
#ifdef __PIC__
	addiu	$v0, $t9, nil_method-\name
#else
	la	$v0, nil_method
#endif
	j	$ra

#ifdef __PIC__
.forward_\name:
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
	addiu	$gp, $gp, .forward_\name-\name

	lw	$t9, %call16(\not_found_handler)($gp)
	jr	$t9
#endif
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup







|




















|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
	lw	$t0, 0($t0)
	addu	$t0, $t0, $t3
	lw	$t0, 0($t0)

#ifdef __PIC__
	beqz	$t0, .forward_\name
#else
	beqz	$t0, \not_found
#endif

	move	$v0, $t0
	j	$ra

.ret_nil_\name:
#ifdef __PIC__
	addiu	$v0, $t9, nil_method-\name
#else
	la	$v0, nil_method
#endif
	j	$ra

#ifdef __PIC__
.forward_\name:
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
	addiu	$gp, $gp, .forward_\name-\name

	lw	$t9, %call16(\not_found)($gp)
	jr	$t9
#endif
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
	la	$v0, nil_method
#endif
	j	$ra
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_not_found_handler
generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

nil_method:
	move	$v0, $zero
	j	$ra

#ifdef __linux__
.section .note.GNU-stack, "", %progbits
#endif







|
|










109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
	la	$v0, nil_method
#endif
	j	$ra
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

nil_method:
	move	$v0, $zero
	j	$ra

#ifdef __linux__
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-ppc-elf.S from [43dfa59b3f] to [69f3a9eceb].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found_handler
\name:
	cmpwi	%r3, 0
	beq-	ret_nil

	lwz	%r5, 0(%r3)
	lwz	%r5, 32(%r5)








|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	cmpwi	%r3, 0
	beq-	ret_nil

	lwz	%r5, 0(%r3)
	lwz	%r5, 32(%r5)

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
	cmpwi	%r5, 0
	beq-	.forward_\name

	mr	%r3, %r5
	blr

.forward_\name:
	b	\not_found_handler@plt
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	lwz	%r5, 0(%r3)
	cmpwi	%r5, 0
	beq-	ret_nil

	lwz	%r5, 4(%r3)
	lwz	%r5, 32(%r5)

	b	.main_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_not_found_handler
generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	mflr	%r0
	bl	get_pc
	mtlr	%r0







|


















|
|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
	cmpwi	%r5, 0
	beq-	.forward_\name

	mr	%r3, %r5
	blr

.forward_\name:
	b	\not_found@plt
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	lwz	%r5, 0(%r3)
	cmpwi	%r5, 0
	beq-	ret_nil

	lwz	%r5, 4(%r3)
	lwz	%r5, 32(%r5)

	b	.main_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	mflr	%r0
	bl	get_pc
	mtlr	%r0

Modified src/runtime/lookup-asm/lookup-asm-x86-elf.S from [537ccf37ee] to [ea4c3fd137].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found_handler
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	ret_nil

	movl	(%edx), %edx
	movl	32(%edx), %edx







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	ret_nil

	movl	(%edx), %edx
	movl	32(%edx), %edx
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
	jz	.forward_\name

	ret

.forward_\name:
	call	get_eip
.forward_L0_\name:
	addl	$\not_found_handler-.forward_L0_\name, %eax
	jmp	*%eax
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	movl	4(%esp), %edx
	cmpl	$0, (%edx)
	je	ret_nil

	movl	4(%edx), %edx
	movl	32(%edx), %edx
	jmp	.main_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_not_found_handler
generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	call	get_eip
.L0:
	addl	$nil_method-.L0, %eax







|


















|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
	jz	.forward_\name

	ret

.forward_\name:
	call	get_eip
.forward_L0_\name:
	addl	$\not_found-.forward_L0_\name, %eax
	jmp	*%eax
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	movl	4(%esp), %edx
	cmpl	$0, (%edx)
	je	ret_nil

	movl	4(%edx), %edx
	movl	32(%edx), %edx
	jmp	.main_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	call	get_eip
.L0:
	addl	$nil_method-.L0, %eax

Modified src/runtime/lookup-asm/lookup-asm-x86-win32.S from [33d9469129] to [a61203a836].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

.globl _objc_msg_lookup
.globl _objc_msg_lookup_stret
.globl _objc_msg_lookup_super
.globl _objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found_handler
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	ret_nil

	movl	(%edx), %edx
	movl	32(%edx), %edx







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

.globl _objc_msg_lookup
.globl _objc_msg_lookup_stret
.globl _objc_msg_lookup_super
.globl _objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	ret_nil

	movl	(%edx), %edx
	movl	32(%edx), %edx
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
	jz	.forward_\name

	ret

.forward_\name:
	call	get_eip
.forward_L0_\name:
	addl	$\not_found_handler-.forward_L0_\name, %eax
	jmp	*%eax
.endm

.macro generate_lookup_super name lookup
\name:
	movl	4(%esp), %edx
	cmpl	$0, (%edx)
	je	ret_nil

	movl	4(%edx), %edx
	movl	32(%edx), %edx
	jmp	.main_\lookup
.endm

generate_lookup _objc_msg_lookup _objc_not_found_handler
generate_lookup _objc_msg_lookup_stret _objc_not_found_handler_stret
generate_lookup_super _objc_msg_lookup_super _objc_msg_lookup
generate_lookup_super _objc_msg_lookup_super_stret _objc_msg_lookup_stret

ret_nil:
	call	get_eip
.L0:
	addl	$nil_method-.L0, %eax







|














|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
	jz	.forward_\name

	ret

.forward_\name:
	call	get_eip
.forward_L0_\name:
	addl	$\not_found-.forward_L0_\name, %eax
	jmp	*%eax
.endm

.macro generate_lookup_super name lookup
\name:
	movl	4(%esp), %edx
	cmpl	$0, (%edx)
	je	ret_nil

	movl	4(%edx), %edx
	movl	32(%edx), %edx
	jmp	.main_\lookup
.endm

generate_lookup _objc_msg_lookup _objc_method_not_found
generate_lookup _objc_msg_lookup_stret _objc_method_not_found_stret
generate_lookup_super _objc_msg_lookup_super _objc_msg_lookup
generate_lookup_super _objc_msg_lookup_super_stret _objc_msg_lookup_stret

ret_nil:
	call	get_eip
.L0:
	addl	$nil_method-.L0, %eax

Modified src/runtime/lookup.m from [1c3a42c0f8] to [5baad6528e].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <stdlib.h>

#import "runtime.h"
#import "runtime-private.h"
#import "macros.h"

IMP (*objc_forward_handler)(id, SEL) = NULL;
IMP (*objc_forward_handler_stret)(id, SEL) = NULL;

static IMP
common_not_found_handler(id obj, SEL sel, IMP (*lookup)(id, SEL),
    IMP (*forward_handler)(id, SEL))
{
	bool is_class = object_getClass(obj)->info & OBJC_CLASS_INFO_METACLASS;

	if (!(object_getClass(obj)->info & OBJC_CLASS_INFO_INITIALIZED)) {
		Class cls = (is_class ? (Class)obj : object_getClass(obj));

		objc_initialize_class(cls);







|
|


|
<







19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>

#import "runtime.h"
#import "runtime-private.h"
#import "macros.h"

static void *forward_handler = NULL;
static void *forward_handler_stret = NULL;

static IMP
common_method_not_found(id obj, SEL sel, IMP (*lookup)(id, SEL), void *forward)

{
	bool is_class = object_getClass(obj)->info & OBJC_CLASS_INFO_METACLASS;

	if (!(object_getClass(obj)->info & OBJC_CLASS_INFO_INITIALIZED)) {
		Class cls = (is_class ? (Class)obj : object_getClass(obj));

		objc_initialize_class(cls);
50
51
52
53
54
55
56































57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
		 * The reason for this is that a call to super is not possible
		 * before a message to the class has been sent and it thus has
		 * been initialized together with its superclasses.
		 */
		return lookup(obj, sel);
	}
































	if (forward_handler != NULL)
		return forward_handler(obj, sel);

	OBJC_ERROR("Selector %c[%s] is not implemented for class %s!",
	    (is_class ? '+' : '-'), sel_getName(sel), object_getClassName(obj));
}

IMP
objc_not_found_handler(id obj, SEL sel)
{
	return common_not_found_handler(obj, sel, objc_msg_lookup,
	    objc_forward_handler);
}

IMP
objc_not_found_handler_stret(id obj, SEL sel)
{
	return common_not_found_handler(obj, sel, objc_msg_lookup_stret,
	    objc_forward_handler_stret);







}

bool
class_respondsToSelector(Class cls, SEL sel)
{
	if (cls == Nil)
		return false;

	return (objc_sparsearray_get(cls->dtable, (uint32_t)sel->uid) != NULL);
}

#ifndef OF_ASM_LOOKUP
static id
nil_method(id self, SEL _cmd)
{
	return nil;
}

static OF_INLINE IMP
common_lookup(id obj, SEL sel, IMP (*not_found_handler)(id, SEL))
{
	IMP imp;

	if (obj == nil)
		return (IMP)nil_method;

	imp = objc_sparsearray_get(object_getClass(obj)->dtable,
	    (uint32_t)sel->uid);

	if (imp == NULL)
		return not_found_handler(obj, sel);

	return imp;
}

IMP
objc_msg_lookup(id obj, SEL sel)
{
	return common_lookup(obj, sel, objc_not_found_handler);
}

IMP
objc_msg_lookup_stret(id obj, SEL sel)
{
	return common_lookup(obj, sel, objc_not_found_handler_stret);
}

static OF_INLINE IMP
common_lookup_super(struct objc_super *super, SEL sel,
    IMP (*not_found_handler)(id, SEL))
{
	IMP imp;

	if (super->self == nil)
		return (IMP)nil_method;

	imp = objc_sparsearray_get(super->cls->dtable, (uint32_t)sel->uid);

	if (imp == NULL)
		return not_found_handler(super->self, sel);

	return imp;
}

IMP
objc_msg_lookup_super(struct objc_super *super, SEL sel)
{
	return common_lookup_super(super, sel, objc_not_found_handler);
}

IMP
objc_msg_lookup_super_stret(struct objc_super *super, SEL sel)
{
	return common_lookup_super(super, sel, objc_not_found_handler_stret);
}
#endif







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|






|

|
|



|

|
|
>
>
>
>
>
>
>



















|










|







|





|




|









|







|





|


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
		 * The reason for this is that a call to super is not possible
		 * before a message to the class has been sent and it thus has
		 * been initialized together with its superclasses.
		 */
		return lookup(obj, sel);
	}

	/* Try resolveClassMethod:/resolveInstanceMethod: */
	if (class_isMetaClass(object_getClass(obj))) {
		Class cls = object_getClass(obj);

		if (class_respondsToSelector(cls,
		    @selector(resolveClassMethod:)) &&
		    [obj resolveClassMethod: sel]) {
			if (!class_respondsToSelector(cls, sel))
				OBJC_ERROR("[%s resolveClassMethod: %s] "
				    "returned true without adding the method!",
				    class_getName(obj), sel_getName(sel));

			return lookup(obj, sel);
		}
	} else {
		Class cls = object_getClass(obj);
		Class metacls = object_getClass(cls);

		if (class_respondsToSelector(metacls,
		    @selector(resolveInstanceMethod:)) &&
		    [cls resolveInstanceMethod: sel]) {
			if (!class_respondsToSelector(cls, sel))
				OBJC_ERROR("[%s resolveInstanceMethod: %s] "
				    "returned true without adding the method!",
				    class_getName(object_getClass(obj)),
				    sel_getName(sel));

			return lookup(obj, sel);
		}
	}

	if (forward != NULL)
		return forward;

	OBJC_ERROR("Selector %c[%s] is not implemented for class %s!",
	    (is_class ? '+' : '-'), sel_getName(sel), object_getClassName(obj));
}

IMP
objc_method_not_found(id obj, SEL sel)
{
	return common_method_not_found(obj, sel, objc_msg_lookup,
	    forward_handler);
}

IMP
objc_method_not_found_stret(id obj, SEL sel)
{
	return common_method_not_found(obj, sel, objc_msg_lookup_stret,
	    forward_handler_stret);
}

void
objc_setForwardHandler(void *forward, void *forward_stret)
{
	forward_handler = forward;
	forward_handler_stret = forward_stret;
}

bool
class_respondsToSelector(Class cls, SEL sel)
{
	if (cls == Nil)
		return false;

	return (objc_sparsearray_get(cls->dtable, (uint32_t)sel->uid) != NULL);
}

#ifndef OF_ASM_LOOKUP
static id
nil_method(id self, SEL _cmd)
{
	return nil;
}

static OF_INLINE IMP
common_lookup(id obj, SEL sel, IMP (*not_found)(id, SEL))
{
	IMP imp;

	if (obj == nil)
		return (IMP)nil_method;

	imp = objc_sparsearray_get(object_getClass(obj)->dtable,
	    (uint32_t)sel->uid);

	if (imp == NULL)
		return not_found(obj, sel);

	return imp;
}

IMP
objc_msg_lookup(id obj, SEL sel)
{
	return common_lookup(obj, sel, objc_method_not_found);
}

IMP
objc_msg_lookup_stret(id obj, SEL sel)
{
	return common_lookup(obj, sel, objc_method_not_found_stret);
}

static OF_INLINE IMP
common_lookup_super(struct objc_super *super, SEL sel,
    IMP (*not_found)(id, SEL))
{
	IMP imp;

	if (super->self == nil)
		return (IMP)nil_method;

	imp = objc_sparsearray_get(super->cls->dtable, (uint32_t)sel->uid);

	if (imp == NULL)
		return not_found(super->self, sel);

	return imp;
}

IMP
objc_msg_lookup_super(struct objc_super *super, SEL sel)
{
	return common_lookup_super(super, sel, objc_method_not_found);
}

IMP
objc_msg_lookup_super_stret(struct objc_super *super, SEL sel)
{
	return common_lookup_super(super, sel, objc_method_not_found_stret);
}
#endif

Modified src/runtime/runtime.h from [bd61ad8aad] to [86f17c06b0].

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
extern const char* object_getClassName(id);
extern const char* protocol_getName(Protocol*);
extern bool protocol_isEqual(Protocol*, Protocol*);
extern bool protocol_conformsToProtocol(Protocol*, Protocol*);
extern void objc_exit(void);
extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(
    objc_uncaught_exception_handler);
extern IMP (*objc_forward_handler)(id, SEL);
extern IMP (*objc_forward_handler_stret)(id, SEL);
extern id objc_autorelease(id);
extern void* objc_autoreleasePoolPush(void);
extern void objc_autoreleasePoolPop(void*);
extern id _objc_rootAutorelease(id);
/* Used by the compiler, but can be called manually. */
extern IMP objc_msg_lookup(id, SEL);
extern IMP objc_msg_lookup_stret(id, SEL);







|
<







204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
extern const char* object_getClassName(id);
extern const char* protocol_getName(Protocol*);
extern bool protocol_isEqual(Protocol*, Protocol*);
extern bool protocol_conformsToProtocol(Protocol*, Protocol*);
extern void objc_exit(void);
extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(
    objc_uncaught_exception_handler);
extern void objc_setForwardHandler(void*, void*);

extern id objc_autorelease(id);
extern void* objc_autoreleasePoolPush(void);
extern void objc_autoreleasePoolPop(void*);
extern id _objc_rootAutorelease(id);
/* Used by the compiler, but can be called manually. */
extern IMP objc_msg_lookup(id, SEL);
extern IMP objc_msg_lookup_stret(id, SEL);

Modified tests/ForwardingTests.m from [9c077ad9ee] to [aba6c5c543].

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58

59
60
61
62
63
64
65

@interface ForwardingTest: OFObject
@end

@interface ForwardingTest (Test)
+ (void)test;
- (void)test;
- (bool)forwardingTargetTest: (intptr_t)a0
			    : (intptr_t)a1
			    : (double)a2
			    : (double)a3;
- (OFString*)forwardingTargetVarArgTest: (OFConstantString*)fmt, ...;
- (long double)forwardingTargetFPRetTest;
- (struct stret_test)forwardingTargetStRetTest;
- (void)notExistant;

- (struct stret_test)notExistantStRet;

@end

@interface ForwardingTarget: OFObject
@end

static void
test(id self, SEL _cmd)







|
|
|
|



|
>
|
>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

@interface ForwardingTest: OFObject
@end

@interface ForwardingTest (Test)
+ (void)test;
- (void)test;
- (uint32_t)forwardingTargetTest: (intptr_t)a0
				: (intptr_t)a1
				: (double)a2
				: (double)a3;
- (OFString*)forwardingTargetVarArgTest: (OFConstantString*)fmt, ...;
- (long double)forwardingTargetFPRetTest;
- (struct stret_test)forwardingTargetStRetTest;
- (void)forwardingTargetNilTest;
- (void)forwardingTargetSelfTest;
- (struct stret_test)forwardingTargetNilStRetTest;
- (struct stret_test)forwardingTargetSelfStRetTest;
@end

@interface ForwardingTarget: OFObject
@end

static void
test(id self, SEL _cmd)
112
113
114
115
116
117
118


119






120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

	if (sel_isEqual(selector, @selector(forwardingTargetTest::::)) ||
	    sel_isEqual(selector, @selector(forwardingTargetVarArgTest:)) ||
	    sel_isEqual(selector, @selector(forwardingTargetFPRetTest)) ||
	    sel_isEqual(selector, @selector(forwardingTargetStRetTest)))
		return (id)((char*)target + (ptrdiff_t)add);



	return nil;






}
@end

@implementation ForwardingTarget
- (bool)forwardingTargetTest: (intptr_t)a0
			    : (intptr_t)a1
			    : (double)a2
			    : (double)a3
{
	OF_ENSURE(self == target);

	if (a0 != 0xDEADBEEF)
		return false;
	if (a1 != -1)
		return false;
	if (a2 != 1.25)
		return false;
	if (a3 != 2.75)
		return false;

	return true;
}

- (OFString*)forwardingTargetVarArgTest: (OFConstantString*)fmt, ...
{
	va_list args;
	OFString *ret;








>
>
|
>
>
>
>
>
>




|
|
|
|




|

|

|

|

|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

	if (sel_isEqual(selector, @selector(forwardingTargetTest::::)) ||
	    sel_isEqual(selector, @selector(forwardingTargetVarArgTest:)) ||
	    sel_isEqual(selector, @selector(forwardingTargetFPRetTest)) ||
	    sel_isEqual(selector, @selector(forwardingTargetStRetTest)))
		return (id)((char*)target + (ptrdiff_t)add);

	if (sel_isEqual(selector, @selector(forwardingTargetNilTest)) ||
	    sel_isEqual(selector, @selector(forwardingTargetNilStRetTest)))
		return nil;

	if (sel_isEqual(selector, @selector(forwardingTargetSelfTest)) ||
	    sel_isEqual(selector, @selector(forwardingTargetSelfStRetTest)))
		return self;

	abort();
}
@end

@implementation ForwardingTarget
- (uint32_t)forwardingTargetTest: (intptr_t)a0
				: (intptr_t)a1
				: (double)a2
				: (double)a3
{
	OF_ENSURE(self == target);

	if (a0 != 0xDEADBEEF)
		return 0;
	if (a1 != -1)
		return 0;
	if (a2 != 1.25)
		return 0;
	if (a3 != 2.75)
		return 0;

	return 0x12345678;
}

- (OFString*)forwardingTargetVarArgTest: (OFConstantString*)fmt, ...
{
	va_list args;
	OFString *ret;

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211


212
213
214




215
216
217
218
219
220

#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
	target = [[[ForwardingTarget alloc] init] autorelease];
	TEST(@"-[forwardingTargetForSelector:]",
	    [t forwardingTargetTest: 0xDEADBEEF
				   : -1
				   : 1.25
				   : 2.75])
	TEST(@"-[forwardingTargetForSelector:] with variable arguments",
	   [([t forwardingTargetVarArgTest: FMT, ARGS]) isEqual: RESULT])
	TEST(@"-[forwardingTargetForSelector:] with fp return",
	    [t forwardingTargetFPRetTest] == 12345678.00006103515625)
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	TEST(@"-[forwardingTargetForSelector:] with struct return",
	    !memcmp([t forwardingTargetStRetTest].s,
	    "abcdefghijklmnopqrstuvwxyz", 27))
# endif
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] with nil target",
	    OFNotImplementedException, [t notExistant])


# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] with nil target + "
	    @"stret", OFNotImplementedException, [t notExistantStRet])




# endif
#endif

	[pool drain];
}
@end







|
|

|


|



|
|
>
>

|
|
>
>
>
>






203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236

#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
	target = [[[ForwardingTarget alloc] init] autorelease];
	TEST(@"-[forwardingTargetForSelector:]",
	    [t forwardingTargetTest: 0xDEADBEEF
				   : -1
				   : 1.25
				   : 2.75] == 0x12345678)
	TEST(@"-[forwardingTargetForSelector:] variable arguments",
	   [([t forwardingTargetVarArgTest: FMT, ARGS]) isEqual: RESULT])
	TEST(@"-[forwardingTargetForSelector:] fp return",
	    [t forwardingTargetFPRetTest] == 12345678.00006103515625)
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	TEST(@"-[forwardingTargetForSelector:] struct return",
	    !memcmp([t forwardingTargetStRetTest].s,
	    "abcdefghijklmnopqrstuvwxyz", 27))
# endif
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target",
	    OFNotImplementedException, [t forwardingTargetNilTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target",
	    OFNotImplementedException, [t forwardingTargetSelfTest])
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target + "
	    @"stret", OFNotImplementedException,
	    [t forwardingTargetNilStRetTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target + "
	    @"stret", OFNotImplementedException,
	    [t forwardingTargetSelfStRetTest])
# endif
#endif

	[pool drain];
}
@end