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
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
# 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
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();
}

#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();
			}

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

of_method_not_found_stret(void *st, id obj, SEL sel)
		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);
}
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
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

#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();

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
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}
	stmfd	sp!, {r0-r4, lr}
	fstmfdd	sp!, {d0-d7}

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

	blx	_object_getClass

	ldr	r1, L_sel_forwardingTargetForSelector_$indirect_L0
L0:
	ldr	r1, [pc, r1]
	mov	r1, r4
	stmfd	sp!, {r1}
	blx	_class_respondsToSelector
	ldmfd	sp!, {r1}

	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-r3, lr}
	ldmfd	sp!, {r1-r4, lr}

	b	_objc_msgSend

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

.align 2
_of_forward_stret:
	stmfd	sp!, {r0-r3, lr}
	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

	ldr	r1, L_sel_forwardingTargetForSelector_$indirect_L1
L1:
	ldr	r1, [pc, r1]
	mov	r1, r4
	stmfd	sp!, {r1}
	blx	_class_respondsToSelector
	ldmfd	sp!, {r1}

	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-r3, lr}
	ldmfd	sp!, {r2-r4, lr}

	b	_objc_msgSend_stret

fail_stret:
	fldmfdd	sp!, {d0-d7}
	ldmfd	sp!, {r0-r3, lr}
	ldmfd	sp!, {r0-r4, lr}
	mov	r0, r1
	mov	r1, r2
	b	_of_method_not_found
	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
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
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
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:
	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
	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
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
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

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, 212(r1)
	lwz	r4, 216(r1)
	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
	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
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
	movq	%rax, %rdi

	testq	%rdi, %rdi
	testq	%rax, %rax
	jz	fail

	cmpq	-0x10(%rbp), %rdi
	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
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
	movq	%rax, %rsi

	testq	%rsi, %rsi
	testq	%rax, %rax
	jz	fail_stret

	cmpq	-0x18(%rbp), %rsi
	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

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), %rdi
	movq	-0x20(%rbp), %rsi
	movq	-0x18(%rbp), %rsi
	movq	-0x20(%rbp), %rdx

	movq	%rbp, %rsp
	popq	%rbp

	jmp	_of_method_not_found
	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
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
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
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
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
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-r3, lr}
	stmfd	sp!, {r0-r4, lr}
	fstmfdd	sp!, {d0-d7}

	ldr	r1, sel_forwardingTargetForSelector_$indirect_L0
	ldr	r4, sel_forwardingTargetForSelector_$indirect_L0
.L0:
	add	r1, pc
	stmfd	sp!, {r1}
	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)
	ldmfd	sp!, {r1}

	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-r3, lr}
	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-r3, lr}
	stmfd	sp!, {r0-r4, lr}
	fstmfdd	sp!, {d0-d7}

	mov	r0, r1
	ldr	r1, sel_forwardingTargetForSelector_$indirect_L1
	ldr	r4, sel_forwardingTargetForSelector_$indirect_L1
.L1:
	add	r1, pc
	stmfd	sp!, {r1}
	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)
	ldmfd	sp!, {r1}

	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-r3, lr}
	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
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, -72
	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	$gp, 0($sp)
	sw	$ra, 4($sp)
	sw	$a0, 8($sp)
	sw	$a1, 12($sp)
	sw	$a2, 16($sp)
	sw	$a3, 20($sp)
	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, 24($sp)
	sw	$9, 28($sp)
	sw	$10, 32($sp)
	sw	$11, 36($sp)
	sw	$8, 44($sp)
	sw	$9, 48($sp)
	sw	$10, 52($sp)
	sw	$11, 56($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)
	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	$a1, %got(sel_forwardingTargetForSelector_)($gp)
	lw	$s1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$a1, %hi(sel_forwardingTargetForSelector_)
	lui	$s1, %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
	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
#endif

	lw	$gp, 0($sp)
	lw	$a0, 8($sp)
	move	$gp, $s0
	lw	$a0, 28($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)
	move	$a1, $s1
	lw	$a2, 32($sp)
#ifdef __PIC__
	move	$t9, $v0
	jalr	$t9
#else
	jalr	$v0
#endif
	sw	$v0, 8($sp)

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

	sw	$v0, 28($sp)

	lw	$gp, 0($sp)
	move	$gp, $s0
	move	$a0, $v0
	lw	$a1, 12($sp)
	lw	$a1, 32($sp)
#ifdef __PIC__
	lw	$t9, %call16(objc_msg_lookup)($gp)
	jalr	$t9
#else
	jal	objc_msg_lookup
	jal_pic	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)
	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, 36($sp)
	lw	$10, 32($sp)
	lw	$9, 28($sp)
	lw	$8, 24($sp)
	lw	$11, 56($sp)
	lw	$10, 52($sp)
	lw	$9, 48($sp)
	lw	$8, 44($sp)
#endif
	lw	$a3, 20($sp)
	lw	$a2, 16($sp)
	lw	$a1, 12($sp)
	lw	$a0, 8($sp)
	lw	$ra, 4($sp)
	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, 72
	addiu	$sp, $sp, 96

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

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, -72
	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	$gp, 0($sp)
	sw	$ra, 4($sp)
	sw	$a0, 8($sp)
	sw	$a1, 12($sp)
	sw	$a2, 16($sp)
	sw	$a3, 20($sp)
	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, 24($sp)
	sw	$9, 28($sp)
	sw	$10, 32($sp)
	sw	$11, 36($sp)
	sw	$8, 44($sp)
	sw	$9, 48($sp)
	sw	$10, 52($sp)
	sw	$11, 56($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)
	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	$a0, $a1
	move	$s0, $gp
#ifdef __PIC__
	lw	$a1, %got(sel_forwardingTargetForSelector_)($gp)
	lw	$s1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$a1, %hi(sel_forwardingTargetForSelector_)
	lui	$s1, %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
	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
#endif

	lw	$gp, 0($sp)
	lw	$a0, 12($sp)
	move	$gp, $s0
	lw	$a0, 32($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)
	move	$a1, $s1
	lw	$a2, 36($sp)
#ifdef __PIC__
	move	$t9, $v0
	jalr	$t9
#else
	jalr	$v0
#endif
	sw	$v0, 12($sp)

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

	sw	$v0, 32($sp)

	lw	$gp, 0($sp)
	move	$gp, $s0
	move	$a0, $v0
	lw	$a1, 16($sp)
	lw	$a1, 36($sp)
#ifdef __PIC__
	lw	$t9, %call16(objc_msg_lookup_stret)($gp)
	jalr	$t9
#else
	jal	objc_msg_lookup_stret
	jal_pic	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)
	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, 36($sp)
	lw	$10, 32($sp)
	lw	$9, 28($sp)
	lw	$8, 24($sp)
	lw	$11, 56($sp)
	lw	$10, 52($sp)
	lw	$9, 48($sp)
	lw	$8, 44($sp)
#endif
	lw	$a3, 20($sp)
	lw	$a2, 16($sp)
	lw	$a1, 12($sp)
	lw	$a0, 8($sp)
	lw	$ra, 4($sp)
	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, 72
	addiu	$sp, $sp, 96

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

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
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
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
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
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
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
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
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
.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_handler@PLT
	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_not_found_handler
generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret
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
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 _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
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
.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_handler(PLT)
	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
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 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
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
.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
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
	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_handler)($gp)
	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
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 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
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
.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
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
	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_not_found_handler
generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret
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
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
.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
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
	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_not_found_handler
generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret
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
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
.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
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
	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_not_found_handler
generate_lookup _objc_msg_lookup_stret _objc_not_found_handler_stret
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
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"

IMP (*objc_forward_handler)(id, SEL) = NULL;
IMP (*objc_forward_handler_stret)(id, SEL) = NULL;
static void *forward_handler = NULL;
static void *forward_handler_stret = NULL;

static IMP
common_not_found_handler(id obj, SEL sel, IMP (*lookup)(id, SEL),
common_method_not_found(id obj, SEL sel, IMP (*lookup)(id, SEL), void *forward)
    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);
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
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_handler != NULL)
		return forward_handler(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_not_found_handler(id obj, SEL sel)
objc_method_not_found(id obj, SEL sel)
{
	return common_not_found_handler(obj, sel, objc_msg_lookup,
	    objc_forward_handler);
	return common_method_not_found(obj, sel, objc_msg_lookup,
	    forward_handler);
}

IMP
objc_not_found_handler_stret(id obj, SEL sel)
objc_method_not_found_stret(id obj, SEL sel)
{
	return common_not_found_handler(obj, sel, objc_msg_lookup_stret,
	    objc_forward_handler_stret);
	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_handler)(id, SEL))
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_handler(obj, sel);
		return not_found(obj, sel);

	return imp;
}

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

IMP
objc_msg_lookup_stret(id obj, SEL sel)
{
	return common_lookup(obj, sel, objc_not_found_handler_stret);
	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_handler)(id, 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_handler(super->self, sel);
		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_not_found_handler);
	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_not_found_handler_stret);
	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
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 IMP (*objc_forward_handler)(id, SEL);
extern void objc_setForwardHandler(void*, void*);
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);

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
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;
- (bool)forwardingTargetTest: (intptr_t)a0
			    : (intptr_t)a1
			    : (double)a2
			    : (double)a3;
- (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)notExistant;
- (struct stret_test)notExistantStRet;
- (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
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;
		return nil;

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

	abort();
}
@end

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

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

	return true;
	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
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])
	TEST(@"-[forwardingTargetForSelector:] with variable arguments",
				   : 2.75] == 0x12345678)
	TEST(@"-[forwardingTargetForSelector:] variable arguments",
	   [([t forwardingTargetVarArgTest: FMT, ARGS]) isEqual: RESULT])
	TEST(@"-[forwardingTargetForSelector:] with fp return",
	TEST(@"-[forwardingTargetForSelector:] fp return",
	    [t forwardingTargetFPRetTest] == 12345678.00006103515625)
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	TEST(@"-[forwardingTargetForSelector:] with struct return",
	TEST(@"-[forwardingTargetForSelector:] struct return",
	    !memcmp([t forwardingTargetStRetTest].s,
	    "abcdefghijklmnopqrstuvwxyz", 27))
# endif
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] with nil target",
	    OFNotImplementedException, [t notExistant])
	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:] with nil target + "
	    @"stret", OFNotImplementedException, [t notExistantStRet])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target + "
	    @"stret", OFNotImplementedException,
	    [t forwardingTargetNilStRetTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target + "
	    @"stret", OFNotImplementedException,
	    [t forwardingTargetSelfStRetTest])
# endif
#endif

	[pool drain];
}
@end