1
2
3
4
5
6
7
8
9
10
11
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
|
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "asm_support_arm.S"
/*
* Portable invocation stub.
* On entry:
* r0 = method pointer
* r1 = argument array or NULL for no argument methods
* r2 = size of argument array in bytes
* r3 = (managed) thread pointer
* [sp] = JValue* result
* [sp + 4] = result type char
*/
ENTRY art_portable_invoke_stub
push {r0, r4, r5, r9, r11, lr} @ spill regs
.cfi_adjust_cfa_offset 24
.cfi_rel_offset r0, 0
.cfi_rel_offset r4, 4
.cfi_rel_offset r5, 8
.cfi_rel_offset r9, 12
.cfi_rel_offset r11, 16
.cfi_rel_offset lr, 20
mov r11, sp @ save the stack pointer
.cfi_def_cfa_register r11
mov r9, r3 @ move managed thread pointer into r9
mov r4, #SUSPEND_CHECK_INTERVAL @ reset r4 to suspend check interval
add r5, r2, #16 @ create space for method pointer in frame
and r5, #0xFFFFFFF0 @ align frame size to 16 bytes
sub sp, r5 @ reserve stack space for argument array
add r0, sp, #4 @ pass stack pointer + method ptr as dest for memcpy
bl memcpy @ memcpy (dest, src, bytes)
ldr r0, [r11] @ restore method*
ldr r1, [sp, #4] @ copy arg value for r1
ldr r2, [sp, #8] @ copy arg value for r2
ldr r3, [sp, #12] @ copy arg value for r3
mov ip, #0 @ set ip to 0
str ip, [sp] @ store NULL for method* at bottom of frame
add sp, #16 @ first 4 args are not passed on stack for portable
ldr ip, [r0, #MIRROR_ART_METHOD_PORTABLE_CODE_OFFSET_32] @ get pointer to the code
blx ip @ call the method
mov sp, r11 @ restore the stack pointer
.cfi_def_cfa_register sp
ldr ip, [sp, #24] @ load the result pointer
strd r0, [ip] @ store r0/r1 into result pointer
pop {r0, r4, r5, r9, r11, pc} @ restore spill regs
END art_portable_invoke_stub
.extern artPortableProxyInvokeHandler
ENTRY art_portable_proxy_invoke_handler
@ Fake callee save ref and args frame set up, note portable doesn't use callee save frames.
@ TODO: just save the registers that are needed in artPortableProxyInvokeHandler.
push {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves
.cfi_adjust_cfa_offset 40
.cfi_rel_offset r1, 0
.cfi_rel_offset r2, 4
.cfi_rel_offset r3, 8
.cfi_rel_offset r5, 12
.cfi_rel_offset r6, 16
.cfi_rel_offset r7, 20
.cfi_rel_offset r8, 24
.cfi_rel_offset r10, 28
.cfi_rel_offset r11, 32
.cfi_rel_offset lr, 36
sub sp, #8 @ 2 words of space, bottom word will hold Method*
.cfi_adjust_cfa_offset 8
@ Begin argument set up.
str r0, [sp, #0] @ place proxy method at bottom of frame
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
blx artPortableProxyInvokeHandler @ (Method* proxy method, receiver, Thread*, SP)
ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_
ldr lr, [sp, #44] @ restore lr
add sp, #48 @ pop frame
.cfi_adjust_cfa_offset -48
bx lr @ return
END art_portable_proxy_invoke_handler
.extern artPortableResolutionTrampoline
ENTRY art_portable_resolution_trampoline
@ Fake callee save ref and args frame set up, note portable doesn't use callee save frames.
@ TODO: just save the registers that are needed in artPortableResolutionTrampoline.
push {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves
.cfi_adjust_cfa_offset 40
.cfi_rel_offset r1, 0
.cfi_rel_offset r2, 4
.cfi_rel_offset r3, 8
.cfi_rel_offset r5, 12
.cfi_rel_offset r6, 16
.cfi_rel_offset r7, 20
.cfi_rel_offset r8, 24
.cfi_rel_offset r10, 28
.cfi_rel_offset r11, 32
.cfi_rel_offset lr, 36
sub sp, #8 @ 2 words of space, bottom word will hold Method*
.cfi_adjust_cfa_offset 8
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
blx artPortableResolutionTrampoline @ (Method* called, receiver, Thread*, SP)
cmp r0, #0 @ is code pointer null?
beq 1f @ goto exception
mov r12, r0
ldr r0, [sp, #0] @ load resolved method in r0
ldr r1, [sp, #8] @ restore non-callee save r1
ldrd r2, [sp, #12] @ restore non-callee saves r2-r3
ldr lr, [sp, #44] @ restore lr
add sp, #48 @ rewind sp
.cfi_adjust_cfa_offset -48
bx r12 @ tail-call into actual code
.cfi_adjust_cfa_offset 48 @ Reset unwind info so following code unwinds.
1:
ldr r1, [sp, #8] @ restore non-callee save r1
ldrd r2, [sp, #12] @ restore non-callee saves r2-r3
ldr lr, [sp, #44] @ restore lr
add sp, #48 @ rewind sp
.cfi_adjust_cfa_offset -48
bx lr
END art_portable_resolution_trampoline
.extern artPortableToInterpreterBridge
ENTRY art_portable_to_interpreter_bridge
@ Fake callee save ref and args frame set up, note portable doesn't use callee save frames.
@ TODO: just save the registers that are needed in artPortableToInterpreterBridge.
push {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves
.cfi_adjust_cfa_offset 40
.cfi_rel_offset r1, 0
.cfi_rel_offset r2, 4
.cfi_rel_offset r3, 8
.cfi_rel_offset r5, 12
.cfi_rel_offset r6, 16
.cfi_rel_offset r7, 20
.cfi_rel_offset r8, 24
.cfi_rel_offset r10, 28
.cfi_rel_offset r11, 32
.cfi_rel_offset lr, 36
sub sp, #8 @ 2 words of space, bottom word will hold Method*
.cfi_adjust_cfa_offset 8
mov r1, r9 @ pass Thread::Current
mov r2, sp @ pass SP
blx artPortableToInterpreterBridge @ (Method* method, Thread*, SP)
ldr lr, [sp, #44] @ restore lr
add sp, #48 @ pop frame
.cfi_adjust_cfa_offset -48
bx lr @ return
END art_portable_to_interpreter_bridge
UNIMPLEMENTED art_portable_imt_conflict_trampoline
|