blob: a55dbb6b2d23f540b1aa367faee9d30838b1778a [file] [log] [blame]
Ian Rogersef7d42f2014-01-06 12:55:46 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "asm_support_x86_64.S"
18
19// For x86, the CFA is esp+4, the address above the pushed return address on the stack.
20
21 /*
22 * Macro that sets up the callee save frame to conform with
23 * Runtime::CreateCalleeSaveMethod(kSaveAll)
24 */
25MACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME)
Andreas Gampebf6b92a2014-03-05 16:11:04 -080026 // R10 := Runtime::Current()
27 movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
28 movq (%r10), %r10
Ian Rogers47d00c02014-04-16 17:33:27 -070029 // Save callee save registers to agree with core spills bitmap.
Andreas Gampebf6b92a2014-03-05 16:11:04 -080030 PUSH r15 // Callee save.
31 PUSH r14 // Callee save.
32 PUSH r13 // Callee save.
33 PUSH r12 // Callee save.
34 PUSH rbp // Callee save.
35 PUSH rbx // Callee save.
Ian Rogers44d6ff12014-03-06 23:11:11 -080036 subq MACRO_LITERAL(8), %rsp // Space for Method* (also aligns the frame).
Andreas Gampebf6b92a2014-03-05 16:11:04 -080037 CFI_ADJUST_CFA_OFFSET(8)
Ian Rogers47d00c02014-04-16 17:33:27 -070038 // R10 := ArtMethod* for save all callee save frame method.
Andreas Gampebf6b92a2014-03-05 16:11:04 -080039 movq RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
40 // Store ArtMethod* to bottom of stack.
41 movq %r10, 0(%rsp)
Andreas Gampe5c1e4352014-04-21 19:28:24 -070042
43 // Ugly compile-time check, but we only have the preprocessor.
44 // Last +8: implicit return address pushed on stack when caller made call.
45#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 6*8 + 8 + 8)
46#error "SAVE_ALL_CALLEE_SAVE_FRAME(X86_64) size not as expected."
47#endif
Ian Rogersef7d42f2014-01-06 12:55:46 -080048END_MACRO
49
50 /*
51 * Macro that sets up the callee save frame to conform with
52 * Runtime::CreateCalleeSaveMethod(kRefsOnly)
53 */
54MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME)
Ian Rogers47d00c02014-04-16 17:33:27 -070055 // R10 := Runtime::Current()
56 movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
57 movq (%r10), %r10
58 // Save callee and GPR args, mixed together to agree with core spills bitmap.
59 PUSH r15 // Callee save.
60 PUSH r14 // Callee save.
61 PUSH r13 // Callee save.
62 PUSH r12 // Callee save.
63 PUSH rbp // Callee save.
64 PUSH rbx // Callee save.
65 subq MACRO_LITERAL(8), %rsp // Space for Method* (also aligns the frame).
66 CFI_ADJUST_CFA_OFFSET(8)
67 // R10 := ArtMethod* for refs only callee save frame method.
68 movq RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
69 // Store ArtMethod* to bottom of stack.
70 movq %r10, 0(%rsp)
Andreas Gampe5c1e4352014-04-21 19:28:24 -070071
72 // Ugly compile-time check, but we only have the preprocessor.
73 // Last +8: implicit return address pushed on stack when caller made call.
74#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 6*8 + 8 + 8)
75#error "REFS_ONLY_CALLEE_SAVE_FRAME(X86_64) size not as expected."
76#endif
Ian Rogersef7d42f2014-01-06 12:55:46 -080077END_MACRO
78
79MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME)
Ian Rogers47d00c02014-04-16 17:33:27 -070080 addq MACRO_LITERAL(8), %rsp
81 CFI_ADJUST_CFA_OFFSET(-8)
82 // TODO: optimize by not restoring callee-saves restored by the ABI
83 POP rbx
84 POP rbp
85 POP r12
86 POP r13
87 POP r14
88 POP r15
Ian Rogersef7d42f2014-01-06 12:55:46 -080089END_MACRO
90
91 /*
92 * Macro that sets up the callee save frame to conform with
93 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
94 */
95MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME)
Ian Rogers936b37f2014-02-14 00:52:24 -080096 // R10 := Runtime::Current()
97 movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10
98 movq (%r10), %r10
99 // Save callee and GPR args, mixed together to agree with core spills bitmap.
100 PUSH r15 // Callee save.
101 PUSH r14 // Callee save.
102 PUSH r13 // Callee save.
103 PUSH r12 // Callee save.
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800104 PUSH r9 // Quick arg 5.
105 PUSH r8 // Quick arg 4.
106 PUSH rsi // Quick arg 1.
Ian Rogers936b37f2014-02-14 00:52:24 -0800107 PUSH rbp // Callee save.
108 PUSH rbx // Callee save.
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800109 PUSH rdx // Quick arg 2.
110 PUSH rcx // Quick arg 3.
Ian Rogers936b37f2014-02-14 00:52:24 -0800111 // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*.
Ian Rogers44d6ff12014-03-06 23:11:11 -0800112 subq MACRO_LITERAL(80), %rsp
Ian Rogers936b37f2014-02-14 00:52:24 -0800113 CFI_ADJUST_CFA_OFFSET(80)
114 // R10 := ArtMethod* for ref and args callee save frame method.
115 movq RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
116 // Save FPRs.
117 movq %xmm0, 16(%rsp)
118 movq %xmm1, 24(%rsp)
119 movq %xmm2, 32(%rsp)
120 movq %xmm3, 40(%rsp)
121 movq %xmm4, 48(%rsp)
122 movq %xmm5, 56(%rsp)
123 movq %xmm6, 64(%rsp)
124 movq %xmm7, 72(%rsp)
125 // Store ArtMethod* to bottom of stack.
126 movq %r10, 0(%rsp)
Andreas Gampe5c1e4352014-04-21 19:28:24 -0700127
128 // Ugly compile-time check, but we only have the preprocessor.
129 // Last +8: implicit return address pushed on stack when caller made call.
130#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 11*8 + 80 + 8)
131#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(X86_64) size not as expected."
132#endif
Ian Rogersef7d42f2014-01-06 12:55:46 -0800133END_MACRO
134
135MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME)
Ian Rogers936b37f2014-02-14 00:52:24 -0800136 // Restore FPRs.
137 movq 16(%rsp), %xmm0
138 movq 24(%rsp), %xmm1
139 movq 32(%rsp), %xmm2
140 movq 40(%rsp), %xmm3
141 movq 48(%rsp), %xmm4
142 movq 56(%rsp), %xmm5
143 movq 64(%rsp), %xmm6
144 movq 72(%rsp), %xmm7
Ian Rogers44d6ff12014-03-06 23:11:11 -0800145 addq MACRO_LITERAL(80), %rsp
Ian Rogers936b37f2014-02-14 00:52:24 -0800146 CFI_ADJUST_CFA_OFFSET(-80)
Ian Rogersbefbd572014-03-06 01:13:39 -0800147 // Restore callee and GPR args, mixed together to agree with core spills bitmap.
Ian Rogers936b37f2014-02-14 00:52:24 -0800148 POP rcx
149 POP rdx
150 POP rbx
151 POP rbp
152 POP rsi
153 POP r8
154 POP r9
155 POP r12
156 POP r13
157 POP r14
158 POP r15
Ian Rogersef7d42f2014-01-06 12:55:46 -0800159END_MACRO
160
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800161
Ian Rogersef7d42f2014-01-06 12:55:46 -0800162 /*
163 * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
164 * exception is Thread::Current()->exception_.
165 */
166MACRO0(DELIVER_PENDING_EXCEPTION)
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800167 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save callee saves for throw
168 // (Thread*, SP) setup
169 movq %gs:THREAD_SELF_OFFSET, %rdi
170 movq %rsp, %rsi
171 call PLT_SYMBOL(artDeliverPendingExceptionFromCode) // artDeliverPendingExceptionFromCode(Thread*, SP)
Ian Rogers47d00c02014-04-16 17:33:27 -0700172 UNREACHABLE
Ian Rogersef7d42f2014-01-06 12:55:46 -0800173END_MACRO
174
175MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
176 DEFINE_FUNCTION VAR(c_name, 0)
Ian Rogers47d00c02014-04-16 17:33:27 -0700177 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context
178 // Outgoing argument set up
179 movq %rsp, %rsi // pass SP
180 movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current()
181 call PLT_VAR(cxx_name, 1) // cxx_name(Thread*, SP)
182 UNREACHABLE
Ian Rogersef7d42f2014-01-06 12:55:46 -0800183 END_FUNCTION VAR(c_name, 0)
184END_MACRO
185
186MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
187 DEFINE_FUNCTION VAR(c_name, 0)
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700188 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context
189 // Outgoing argument set up
Ian Rogers47d00c02014-04-16 17:33:27 -0700190 movq %rsp, %rdx // pass SP
191 movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current()
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700192 call PLT_VAR(cxx_name, 1) // cxx_name(arg1, Thread*, SP)
Ian Rogers47d00c02014-04-16 17:33:27 -0700193 UNREACHABLE
Ian Rogersef7d42f2014-01-06 12:55:46 -0800194 END_FUNCTION VAR(c_name, 0)
195END_MACRO
196
197MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
198 DEFINE_FUNCTION VAR(c_name, 0)
Ian Rogers47d00c02014-04-16 17:33:27 -0700199 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context
200 // Outgoing argument set up
201 movq %rsp, %rcx // pass SP
202 movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current()
203 call PLT_VAR(cxx_name, 1) // cxx_name(Thread*, SP)
204 UNREACHABLE
Ian Rogersef7d42f2014-01-06 12:55:46 -0800205 END_FUNCTION VAR(c_name, 0)
206END_MACRO
207
208 /*
209 * Called by managed code to create and deliver a NullPointerException.
210 */
211NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
212
213 /*
214 * Called by managed code to create and deliver an ArithmeticException.
215 */
216NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
217
218 /*
219 * Called by managed code to create and deliver a StackOverflowError.
220 */
221NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode
222
223 /*
224 * Called by managed code, saves callee saves and then calls artThrowException
225 * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
226 */
227ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode
228
229 /*
230 * Called by managed code to create and deliver a NoSuchMethodError.
231 */
232ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode
233
234 /*
235 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
236 * index, arg2 holds limit.
237 */
238TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
239
240 /*
241 * All generated callsites for interface invokes and invocation slow paths will load arguments
242 * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
243 * the method_idx. This wrapper will save arg1-arg3, load the caller's Method*, align the
244 * stack and call the appropriate C helper.
245 * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
246 *
247 * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
248 * of the target Method* in r0 and method->code_ in r1.
249 *
250 * If unsuccessful, the helper will return NULL/NULL. There will bea pending exception in the
251 * thread and we branch to another stub to deliver it.
252 *
253 * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
254 * pointing back to the original caller.
255 */
256MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name)
257 DEFINE_FUNCTION VAR(c_name, 0)
258 int3
259 int3
260 END_FUNCTION VAR(c_name, 0)
261END_MACRO
262
263INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline
264INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
265
266INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
267INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
268INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
269INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
270
Ian Rogers936b37f2014-02-14 00:52:24 -0800271
272 /*
273 * Helper for quick invocation stub to set up XMM registers. Assumes r10 == shorty,
274 * r11 == arg_array. Clobbers r10, r11 and al. Branches to xmm_setup_finished if it encounters
275 * the end of the shorty.
276 */
277MACRO2(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, finished)
2781: // LOOP
279 movb (%r10), %al // al := *shorty
Ian Rogers44d6ff12014-03-06 23:11:11 -0800280 addq MACRO_LITERAL(1), %r10 // shorty++
281 cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto xmm_setup_finished
Ian Rogers936b37f2014-02-14 00:52:24 -0800282 je VAR(finished, 1)
Ian Rogers44d6ff12014-03-06 23:11:11 -0800283 cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto FOUND_DOUBLE
Ian Rogers936b37f2014-02-14 00:52:24 -0800284 je 2f
Ian Rogers44d6ff12014-03-06 23:11:11 -0800285 cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto FOUND_FLOAT
Ian Rogers936b37f2014-02-14 00:52:24 -0800286 je 3f
Ian Rogers44d6ff12014-03-06 23:11:11 -0800287 addq MACRO_LITERAL(4), %r11 // arg_array++
Ian Rogers936b37f2014-02-14 00:52:24 -0800288 // Handle extra space in arg array taken by a long.
Ian Rogers44d6ff12014-03-06 23:11:11 -0800289 cmpb MACRO_LITERAL(74), %al // if (al != 'J') goto LOOP
Ian Rogers936b37f2014-02-14 00:52:24 -0800290 jne 1b
Ian Rogers44d6ff12014-03-06 23:11:11 -0800291 addq MACRO_LITERAL(4), %r11 // arg_array++
Ian Rogers936b37f2014-02-14 00:52:24 -0800292 jmp 1b // goto LOOP
2932: // FOUND_DOUBLE
294 movsd (%r11), REG_VAR(xmm_reg, 0)
Ian Rogers44d6ff12014-03-06 23:11:11 -0800295 addq MACRO_LITERAL(8), %r11 // arg_array+=2
Ian Rogers936b37f2014-02-14 00:52:24 -0800296 jmp 4f
2973: // FOUND_FLOAT
298 movss (%r11), REG_VAR(xmm_reg, 0)
Ian Rogers44d6ff12014-03-06 23:11:11 -0800299 addq MACRO_LITERAL(4), %r11 // arg_array++
Ian Rogers936b37f2014-02-14 00:52:24 -08003004:
301END_MACRO
302
303 /*
304 * Helper for quick invocation stub to set up GPR registers. Assumes r10 == shorty,
305 * r11 == arg_array. Clobbers r10, r11 and al. Branches to gpr_setup_finished if it encounters
306 * the end of the shorty.
307 */
308MACRO3(LOOP_OVER_SHORTY_LOADING_GPRS, gpr_reg64, gpr_reg32, finished)
3091: // LOOP
310 movb (%r10), %al // al := *shorty
Ian Rogers44d6ff12014-03-06 23:11:11 -0800311 addq MACRO_LITERAL(1), %r10 // shorty++
312 cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto gpr_setup_finished
Ian Rogers936b37f2014-02-14 00:52:24 -0800313 je VAR(finished, 2)
Ian Rogers44d6ff12014-03-06 23:11:11 -0800314 cmpb MACRO_LITERAL(74), %al // if (al == 'J') goto FOUND_LONG
Ian Rogers936b37f2014-02-14 00:52:24 -0800315 je 2f
Ian Rogers44d6ff12014-03-06 23:11:11 -0800316 cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto SKIP_FLOAT
Ian Rogers936b37f2014-02-14 00:52:24 -0800317 je 3f
Ian Rogers44d6ff12014-03-06 23:11:11 -0800318 cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto SKIP_DOUBLE
Ian Rogers936b37f2014-02-14 00:52:24 -0800319 je 4f
320 movl (%r11), REG_VAR(gpr_reg32, 1)
Ian Rogers44d6ff12014-03-06 23:11:11 -0800321 addq MACRO_LITERAL(4), %r11 // arg_array++
Ian Rogers936b37f2014-02-14 00:52:24 -0800322 jmp 5f
3232: // FOUND_LONG
324 movq (%r11), REG_VAR(gpr_reg64, 0)
Ian Rogers44d6ff12014-03-06 23:11:11 -0800325 addq MACRO_LITERAL(8), %r11 // arg_array+=2
Ian Rogers936b37f2014-02-14 00:52:24 -0800326 jmp 5f
3273: // SKIP_FLOAT
Ian Rogers44d6ff12014-03-06 23:11:11 -0800328 addq MACRO_LITERAL(4), %r11 // arg_array++
Ian Rogers936b37f2014-02-14 00:52:24 -0800329 jmp 1b
3304: // SKIP_DOUBLE
Ian Rogers44d6ff12014-03-06 23:11:11 -0800331 addq MACRO_LITERAL(8), %r11 // arg_array+=2
Ian Rogers936b37f2014-02-14 00:52:24 -0800332 jmp 1b
3335:
334END_MACRO
335
Ian Rogersef7d42f2014-01-06 12:55:46 -0800336 /*
337 * Quick invocation stub.
Ian Rogers0177e532014-02-11 16:30:46 -0800338 * On entry:
339 * [sp] = return address
340 * rdi = method pointer
Ian Rogers936b37f2014-02-14 00:52:24 -0800341 * rsi = argument array that must at least contain the this pointer.
Ian Rogers0177e532014-02-11 16:30:46 -0800342 * rdx = size of argument array in bytes
343 * rcx = (managed) thread pointer
344 * r8 = JValue* result
345 * r9 = char* shorty
Ian Rogersef7d42f2014-01-06 12:55:46 -0800346 */
347DEFINE_FUNCTION art_quick_invoke_stub
Ian Rogers936b37f2014-02-14 00:52:24 -0800348 // Set up argument XMM registers.
349 leaq 1(%r9), %r10 // R10 := shorty + 1 ; ie skip return arg character.
350 leaq 4(%rsi), %r11 // R11 := arg_array + 4 ; ie skip this pointer.
351 LOOP_OVER_SHORTY_LOADING_XMMS xmm0, .Lxmm_setup_finished
352 LOOP_OVER_SHORTY_LOADING_XMMS xmm1, .Lxmm_setup_finished
353 LOOP_OVER_SHORTY_LOADING_XMMS xmm2, .Lxmm_setup_finished
354 LOOP_OVER_SHORTY_LOADING_XMMS xmm3, .Lxmm_setup_finished
355 LOOP_OVER_SHORTY_LOADING_XMMS xmm4, .Lxmm_setup_finished
356 LOOP_OVER_SHORTY_LOADING_XMMS xmm5, .Lxmm_setup_finished
357 LOOP_OVER_SHORTY_LOADING_XMMS xmm6, .Lxmm_setup_finished
358 LOOP_OVER_SHORTY_LOADING_XMMS xmm7, .Lxmm_setup_finished
359 .balign 16
360.Lxmm_setup_finished:
361 PUSH rbp // Save rbp.
362 PUSH r8 // Save r8/result*.
363 PUSH r9 // Save r9/shorty*.
Ian Rogers47d00c02014-04-16 17:33:27 -0700364 movq %rsp, %rbp // Copy value of stack pointer into base pointer.
Ian Rogers936b37f2014-02-14 00:52:24 -0800365 CFI_DEF_CFA_REGISTER(rbp)
366 movl %edx, %r10d
367 addl LITERAL(64), %edx // Reserve space for return addr, method*, rbp, r8 and r9 in frame.
368 andl LITERAL(0xFFFFFFF0), %edx // Align frame size to 16 bytes.
369 subl LITERAL(32), %edx // Remove space for return address, rbp, r8 and r9.
370 subq %rdx, %rsp // Reserve stack space for argument array.
371 movq LITERAL(0), (%rsp) // Store NULL for method*
372 movl %r10d, %ecx // Place size of args in rcx.
373 movq %rdi, %rax // RAX := method to be called
374 movq %rsi, %r11 // R11 := arg_array
375 leaq 8(%rsp), %rdi // Rdi is pointing just above the method* in the stack arguments.
376 // Copy arg array into stack.
377 rep movsb // while (rcx--) { *rdi++ = *rsi++ }
378 leaq 1(%r9), %r10 // R10 := shorty + 1 ; ie skip return arg character
379 movq %rax, %rdi // RDI := method to be called
380 movl (%r11), %esi // RSI := this pointer
381 addq LITERAL(4), %r11 // arg_array++
382 LOOP_OVER_SHORTY_LOADING_GPRS rdx, edx, .Lgpr_setup_finished
383 LOOP_OVER_SHORTY_LOADING_GPRS rcx, ecx, .Lgpr_setup_finished
384 LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, .Lgpr_setup_finished
385 LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, .Lgpr_setup_finished
386.Lgpr_setup_finished:
387 call *METHOD_QUICK_CODE_OFFSET(%rdi) // Call the method.
388 movq %rbp, %rsp // Restore stack pointer.
389 CFI_DEF_CFA_REGISTER(rsp)
390 POP r9 // Pop r9 - shorty*.
391 POP r8 // Pop r8 - result*.
392 POP rbp // Pop rbp
393 cmpb LITERAL(68), (%r9) // Test if result type char == 'D'.
394 je .Lreturn_double_quick
395 cmpb LITERAL(70), (%r9) // Test if result type char == 'F'.
396 je .Lreturn_float_quick
397 movq %rax, (%r8) // Store the result assuming its a long, int or Object*
398 ret
399.Lreturn_double_quick:
400 movsd %xmm0, (%r8) // Store the double floating point result.
401 ret
402.Lreturn_float_quick:
403 movss %xmm0, (%r8) // Store the floating point result.
404 ret
405END_FUNCTION art_quick_invoke_stub
406
407 /*
408 * Quick invocation stub.
409 * On entry:
410 * [sp] = return address
411 * rdi = method pointer
412 * rsi = argument array or NULL if no arguments.
413 * rdx = size of argument array in bytes
414 * rcx = (managed) thread pointer
415 * r8 = JValue* result
416 * r9 = char* shorty
417 */
418DEFINE_FUNCTION art_quick_invoke_static_stub
419 // Set up argument XMM registers.
420 leaq 1(%r9), %r10 // R10 := shorty + 1 ; ie skip return arg character
421 movq %rsi, %r11 // R11 := arg_array
422 LOOP_OVER_SHORTY_LOADING_XMMS xmm0, .Lxmm_setup_finished2
423 LOOP_OVER_SHORTY_LOADING_XMMS xmm1, .Lxmm_setup_finished2
424 LOOP_OVER_SHORTY_LOADING_XMMS xmm2, .Lxmm_setup_finished2
425 LOOP_OVER_SHORTY_LOADING_XMMS xmm3, .Lxmm_setup_finished2
426 LOOP_OVER_SHORTY_LOADING_XMMS xmm4, .Lxmm_setup_finished2
427 LOOP_OVER_SHORTY_LOADING_XMMS xmm5, .Lxmm_setup_finished2
428 LOOP_OVER_SHORTY_LOADING_XMMS xmm6, .Lxmm_setup_finished2
429 LOOP_OVER_SHORTY_LOADING_XMMS xmm7, .Lxmm_setup_finished2
430 .balign 16
431.Lxmm_setup_finished2:
432 PUSH rbp // Save rbp.
433 PUSH r8 // Save r8/result*.
434 PUSH r9 // Save r9/shorty*.
Ian Rogers47d00c02014-04-16 17:33:27 -0700435 movq %rsp, %rbp // Copy value of stack pointer into base pointer.
Ian Rogers936b37f2014-02-14 00:52:24 -0800436 CFI_DEF_CFA_REGISTER(rbp)
437 movl %edx, %r10d
438 addl LITERAL(64), %edx // Reserve space for return addr, method*, rbp, r8 and r9 in frame.
439 andl LITERAL(0xFFFFFFF0), %edx // Align frame size to 16 bytes.
440 subl LITERAL(32), %edx // Remove space for return address, rbp, r8 and r9.
441 subq %rdx, %rsp // Reserve stack space for argument array.
442 movq LITERAL(0), (%rsp) // Store NULL for method*
443 movl %r10d, %ecx // Place size of args in rcx.
444 movq %rdi, %rax // RAX := method to be called
445 movq %rsi, %r11 // R11 := arg_array
446 leaq 8(%rsp), %rdi // Rdi is pointing just above the method* in the stack arguments.
447 // Copy arg array into stack.
448 rep movsb // while (rcx--) { *rdi++ = *rsi++ }
449 leaq 1(%r9), %r10 // R10 := shorty + 1 ; ie skip return arg character
450 movq %rax, %rdi // RDI := method to be called
451 LOOP_OVER_SHORTY_LOADING_GPRS rsi, esi, .Lgpr_setup_finished2
452 LOOP_OVER_SHORTY_LOADING_GPRS rdx, edx, .Lgpr_setup_finished2
453 LOOP_OVER_SHORTY_LOADING_GPRS rcx, ecx, .Lgpr_setup_finished2
454 LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, .Lgpr_setup_finished2
455 LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, .Lgpr_setup_finished2
456.Lgpr_setup_finished2:
457 call *METHOD_QUICK_CODE_OFFSET(%rdi) // Call the method.
458 movq %rbp, %rsp // Restore stack pointer.
459 CFI_DEF_CFA_REGISTER(rsp)
460 POP r9 // Pop r9 - shorty*.
461 POP r8 // Pop r8 - result*.
462 POP rbp // Pop rbp
463 cmpb LITERAL(68), (%r9) // Test if result type char == 'D'.
464 je .Lreturn_double_quick2
465 cmpb LITERAL(70), (%r9) // Test if result type char == 'F'.
466 je .Lreturn_float_quick2
467 movq %rax, (%r8) // Store the result assuming its a long, int or Object*
468 ret
469.Lreturn_double_quick2:
470 movsd %xmm0, (%r8) // Store the double floating point result.
471 ret
472.Lreturn_float_quick2:
473 movss %xmm0, (%r8) // Store the floating point result.
474 ret
Ian Rogers1a570662014-03-12 01:02:21 -0700475END_FUNCTION art_quick_invoke_static_stub
Ian Rogersef7d42f2014-01-06 12:55:46 -0800476
477MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
478 DEFINE_FUNCTION VAR(c_name, 0)
Ian Rogers47d00c02014-04-16 17:33:27 -0700479 UNTESTED
480 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
481 // Outgoing argument set up
482 movq %rsp, %rsi // pass SP
483 movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current()
484 call PLT_VAR(cxx_name, 1) // cxx_name(Thread*, SP)
485 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
486 CALL_MACRO(return_macro, 2) // return or deliver exception
Ian Rogersef7d42f2014-01-06 12:55:46 -0800487 END_FUNCTION VAR(c_name, 0)
488END_MACRO
489
490MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
491 DEFINE_FUNCTION VAR(c_name, 0)
Ian Rogers47d00c02014-04-16 17:33:27 -0700492 UNTESTED
493 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
494 // Outgoing argument set up
495 movq %rsp, %rdx // pass SP
496 movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current()
497 call PLT_VAR(cxx_name, 1) // cxx_name(arg0, Thread*, SP)
498 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
499 CALL_MACRO(return_macro, 2) // return or deliver exception
Ian Rogersef7d42f2014-01-06 12:55:46 -0800500 END_FUNCTION VAR(c_name, 0)
501END_MACRO
502
503MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
504 DEFINE_FUNCTION VAR(c_name, 0)
Ian Rogers47d00c02014-04-16 17:33:27 -0700505 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
506 // Outgoing argument set up
507 movq %rsp, %rcx // pass SP
508 movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current()
509 call PLT_VAR(cxx_name, 1) // cxx_name(arg0, arg1, Thread*, SP)
510 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
511 CALL_MACRO(return_macro, 2) // return or deliver exception
Ian Rogersef7d42f2014-01-06 12:55:46 -0800512 END_FUNCTION VAR(c_name, 0)
513END_MACRO
514
515MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro)
516 DEFINE_FUNCTION VAR(c_name, 0)
Ian Rogers47d00c02014-04-16 17:33:27 -0700517 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC
518 // Outgoing argument set up
519 movq %rsp, %r8 // pass SP
520 movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current()
521 call PLT_VAR(cxx_name, 1) // cxx_name(arg0, arg1, arg2, Thread*, SP)
Andreas Gampe00c1e6d2014-04-25 15:47:13 -0700522 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
Ian Rogers47d00c02014-04-16 17:33:27 -0700523 CALL_MACRO(return_macro, 2) // return or deliver exception
Ian Rogersef7d42f2014-01-06 12:55:46 -0800524 END_FUNCTION VAR(c_name, 0)
525END_MACRO
526
527MACRO0(RETURN_IF_RESULT_IS_NON_ZERO)
Ian Rogers47d00c02014-04-16 17:33:27 -0700528 testq %rax, %rax // rax == 0 ?
529 jz 1f // if rax == 0 goto 1
Ian Rogersef7d42f2014-01-06 12:55:46 -0800530 ret // return
5311: // deliver exception on current thread
532 DELIVER_PENDING_EXCEPTION
533END_MACRO
534
535MACRO0(RETURN_IF_EAX_ZERO)
Ian Rogersef7d42f2014-01-06 12:55:46 -0800536 testl %eax, %eax // eax == 0 ?
537 jnz 1f // if eax != 0 goto 1
538 ret // return
5391: // deliver exception on current thread
540 DELIVER_PENDING_EXCEPTION
541END_MACRO
542
543MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION)
Ian Rogers936b37f2014-02-14 00:52:24 -0800544 movq %gs:THREAD_EXCEPTION_OFFSET, %rcx // get exception field
545 testq %rcx, %rcx // rcx == 0 ?
546 jnz 1f // if rcx != 0 goto 1
547 ret // return
5481: // deliver exception on current thread
Ian Rogersef7d42f2014-01-06 12:55:46 -0800549 DELIVER_PENDING_EXCEPTION
550END_MACRO
551
552// Generate the allocation entrypoints for each allocator.
553// TODO: use arch/quick_alloc_entrypoints.S. Currently we don't as we need to use concatenation
554// macros to work around differences between OS/X's as and binutils as (OS/X lacks named arguments
555// to macros and the VAR macro won't concatenate arguments properly), this also breaks having
556// multi-line macros that use each other (hence using 1 macro per newline below).
557#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(c_suffix, cxx_suffix) \
558 TWO_ARG_DOWNCALL art_quick_alloc_object ## c_suffix, artAllocObjectFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
559#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(c_suffix, cxx_suffix) \
560 TWO_ARG_DOWNCALL art_quick_alloc_object_resolved ## c_suffix, artAllocObjectFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
561#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(c_suffix, cxx_suffix) \
562 TWO_ARG_DOWNCALL art_quick_alloc_object_initialized ## c_suffix, artAllocObjectFromCodeInitialized ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
563#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
564 TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check ## c_suffix, artAllocObjectFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
565#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(c_suffix, cxx_suffix) \
566 THREE_ARG_DOWNCALL art_quick_alloc_array ## c_suffix, artAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
567#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(c_suffix, cxx_suffix) \
568 THREE_ARG_DOWNCALL art_quick_alloc_array_resolved ## c_suffix, artAllocArrayFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
569#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
570 THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check ## c_suffix, artAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
571#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(c_suffix, cxx_suffix) \
572 THREE_ARG_DOWNCALL art_quick_check_and_alloc_array ## c_suffix, artCheckAndAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
573#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \
574 THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check ## c_suffix, artCheckAndAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO
575
576GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc, DlMalloc)
577GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc, DlMalloc)
578GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc, DlMalloc)
579GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
580GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc, DlMalloc)
581GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc, DlMalloc)
582GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
583GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc, DlMalloc)
584GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc)
585
586GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc_instrumented, DlMallocInstrumented)
587GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented)
588GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc_instrumented, DlMallocInstrumented)
589GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
590GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented)
591GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented)
592GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
593GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented)
594GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented)
595
596GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc)
597GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc, RosAlloc)
598GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc, RosAlloc)
599GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
600GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc, RosAlloc)
601GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc, RosAlloc)
602GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
603GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc, RosAlloc)
604GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc)
605
606GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc_instrumented, RosAllocInstrumented)
607GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented)
608GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc_instrumented, RosAllocInstrumented)
609GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
610GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented)
611GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented)
612GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
613GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented)
614GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented)
615
616GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer, BumpPointer)
617GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer, BumpPointer)
618GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer, BumpPointer)
619GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
620GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer, BumpPointer)
621GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer, BumpPointer)
622GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
623GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer, BumpPointer)
624GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer)
625
626GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer_instrumented, BumpPointerInstrumented)
627GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented)
628GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer_instrumented, BumpPointerInstrumented)
629GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
630GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented)
631GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented)
632GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
633GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented)
634GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented)
635
636GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB)
637GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab, TLAB)
638GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab, TLAB)
639GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB)
640GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab, TLAB)
641GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB)
642GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB)
643GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab, TLAB)
644GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB)
645
646GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab_instrumented, TLABInstrumented)
647GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab_instrumented, TLABInstrumented)
648GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab_instrumented, TLABInstrumented)
649GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
650GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented)
651GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab_instrumented, TLABInstrumented)
652GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
653GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented)
654GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented)
655
656TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO
657TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO
658TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO
659TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO
660
661TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
662
663DEFINE_FUNCTION art_quick_lock_object
Alexei Zavjalov80c79342014-05-02 16:45:40 +0700664 testl %edi, %edi // Null check object/rdi.
665 jz .Lslow_lock
666.Lretry_lock:
667 movl LOCK_WORD_OFFSET(%edi), %ecx // ecx := lock word.
668 test LITERAL(0xC0000000), %ecx // Test the 2 high bits.
669 jne .Lslow_lock // Slow path if either of the two high bits are set.
670 movl %gs:THREAD_ID_OFFSET, %edx // edx := thread id
671 test %ecx, %ecx
672 jnz .Lalready_thin // Lock word contains a thin lock.
673 // unlocked case - %edx holds thread id with count of 0
674 xor %eax, %eax // eax == 0 for comparison with lock word in cmpxchg
675 lock cmpxchg %edx, LOCK_WORD_OFFSET(%edi)
676 jnz .Lretry_lock // cmpxchg failed retry
677 ret
678.Lalready_thin:
679 cmpw %cx, %dx // do we hold the lock already?
680 jne .Lslow_lock
681 addl LITERAL(65536), %ecx // increment recursion count
682 test LITERAL(0xC0000000), %ecx // overflowed if either of top two bits are set
683 jne .Lslow_lock // count overflowed so go slow
684 movl %ecx, LOCK_WORD_OFFSET(%edi) // update lockword, cmpxchg not necessary as we hold lock
685 ret
686.Lslow_lock:
687 SETUP_REF_ONLY_CALLEE_SAVE_FRAME
688 movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current()
689 movq %rsp, %rdx // pass SP
690 call PLT_SYMBOL(artLockObjectFromCode) // artLockObjectFromCode(object, Thread*, SP)
691 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
692 RETURN_IF_EAX_ZERO
Ian Rogersef7d42f2014-01-06 12:55:46 -0800693END_FUNCTION art_quick_lock_object
694
695DEFINE_FUNCTION art_quick_unlock_object
Alexei Zavjalov80c79342014-05-02 16:45:40 +0700696 testl %edi, %edi // null check object/edi
697 jz .Lslow_unlock
698 movl LOCK_WORD_OFFSET(%edi), %ecx // ecx := lock word
699 movl %gs:THREAD_ID_OFFSET, %edx // edx := thread id
700 test %ecx, %ecx
701 jb .Lslow_unlock // lock word contains a monitor
702 cmpw %cx, %dx // does the thread id match?
703 jne .Lslow_unlock
704 cmpl LITERAL(65536), %ecx
705 jae .Lrecursive_thin_unlock
706 movl LITERAL(0), LOCK_WORD_OFFSET(%edi)
707 ret
708.Lrecursive_thin_unlock:
709 subl LITERAL(65536), %ecx
710 mov %ecx, LOCK_WORD_OFFSET(%edi)
711 ret
712.Lslow_unlock:
713 SETUP_REF_ONLY_CALLEE_SAVE_FRAME
714 movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current()
715 movq %rsp, %rdx // pass SP
716 call PLT_SYMBOL(artUnlockObjectFromCode) // artUnlockObjectFromCode(object, Thread*, SP)
717 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
718 RETURN_IF_EAX_ZERO
Ian Rogersef7d42f2014-01-06 12:55:46 -0800719END_FUNCTION art_quick_unlock_object
720
721DEFINE_FUNCTION art_quick_is_assignable
722 int3
723 int3
724END_FUNCTION art_quick_is_assignable
725
726DEFINE_FUNCTION art_quick_check_cast
Andreas Gampe525cde22014-04-22 15:44:50 -0700727 PUSH rdi // Save args for exc
728 PUSH rsi
729 call PLT_SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass)
730 testq %rax, %rax
731 jz 1f // jump forward if not assignable
732 addq LITERAL(16), %rsp // pop arguments
733 CFI_ADJUST_CFA_OFFSET(-16)
734 ret
7351:
736 POP rsi // Pop arguments
737 POP rdi
738 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context
739 mov %rsp, %rcx // pass SP
740 mov %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current()
741 call PLT_SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*, SP)
742 int3 // unreached
Ian Rogersef7d42f2014-01-06 12:55:46 -0800743END_FUNCTION art_quick_check_cast
744
Andreas Gampef4e910b2014-04-29 16:55:52 -0700745
Ian Rogersef7d42f2014-01-06 12:55:46 -0800746 /*
747 * Entry from managed code for array put operations of objects where the value being stored
748 * needs to be checked for compatibility.
Andreas Gampef4e910b2014-04-29 16:55:52 -0700749 *
750 * Currently all the parameters should fit into the 32b portions of the registers. Index always
751 * will. So we optimize for a tighter encoding. The 64b versions are in comments.
752 *
753 * rdi(edi) = array, rsi(esi) = index, rdx(edx) = value
Ian Rogersef7d42f2014-01-06 12:55:46 -0800754 */
Andreas Gampef4e910b2014-04-29 16:55:52 -0700755DEFINE_FUNCTION art_quick_aput_obj_with_null_and_bound_check
756 testl %edi, %edi
757// testq %rdi, %rdi
758 jnz art_quick_aput_obj_with_bound_check_local
759 jmp art_quick_throw_null_pointer_exception_local
760END_FUNCTION art_quick_aput_obj_with_null_and_bound_check
761
762
763DEFINE_FUNCTION art_quick_aput_obj_with_bound_check
764 movl ARRAY_LENGTH_OFFSET(%edi), %ebx
765// movl ARRAY_LENGTH_OFFSET(%rdi), %ebx // This zero-extends, so value(%rbx)=value(%ebx)
766 cmpl %ebx, %esi
767 jb art_quick_aput_obj_local
768 mov %esi, %edi
769// mov %rsi, %rdi
770 mov %ebx, %esi
771// mov %rbx, %rsi
772 jmp art_quick_throw_array_bounds_local
773END_FUNCTION art_quick_aput_obj_with_bound_check
774
775
776DEFINE_FUNCTION art_quick_aput_obj
777 testl %edx, %edx // store of null
778// test %rdx, %rdx
779 jz .Ldo_aput_null
780 movl CLASS_OFFSET(%edi), %ebx
781// movq CLASS_OFFSET(%rdi), %rbx
782 movl CLASS_COMPONENT_TYPE_OFFSET(%ebx), %ebx
783// movq CLASS_COMPONENT_TYPE_OFFSET(%rbx), %rbx
784 cmpl CLASS_OFFSET(%edx), %ebx // value's type == array's component type - trivial assignability
785// cmpq CLASS_OFFSET(%rdx), %rbx
786 jne .Lcheck_assignability
787.Ldo_aput:
788 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4)
789// movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4)
790 movq %gs:THREAD_CARD_TABLE_OFFSET, %rdx
791 shrl LITERAL(7), %edi
792// shrl LITERAL(7), %rdi
793 movb %dl, (%rdx, %rdi) // Note: this assumes that top 32b of %rdi are zero
794 ret
795.Ldo_aput_null:
796 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4)
797// movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4)
798 ret
799.Lcheck_assignability:
800 // Save arguments.
801 PUSH rdi
802 PUSH rsi
803 PUSH rdx
804 subq LITERAL(8), %rsp // Alignment padding.
805 CFI_ADJUST_CFA_OFFSET(8)
806
807 // "Uncompress" = do nothing, as already zero-extended on load.
808 movl CLASS_OFFSET(%edx), %esi // Pass arg2 = value's class.
809 movq %rbx, %rdi // Pass arg1 = array's component type.
810
811 call PLT_SYMBOL(artIsAssignableFromCode) // (Class* a, Class* b)
812
813 // Exception?
814 testq %rax, %rax
815 jz .Lthrow_array_store_exception
816
817 // Restore arguments.
818 addq LITERAL(8), %rsp
819 CFI_ADJUST_CFA_OFFSET(-8)
820 POP rdx
821 POP rsi
822 POP rdi
823
824 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4)
825// movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4)
826 movq %gs:THREAD_CARD_TABLE_OFFSET, %rdx
827 shrl LITERAL(7), %edi
828// shrl LITERAL(7), %rdi
829 movb %dl, (%rdx, %rdi) // Note: this assumes that top 32b of %rdi are zero
830// movb %dl, (%rdx, %rdi)
831 ret
832.Lthrow_array_store_exception:
833 // Restore arguments.
834 addq LITERAL(8), %rsp
835 CFI_ADJUST_CFA_OFFSET(-8)
836 POP rdx
837 POP rsi
838 POP rdi
839
840 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // Save all registers as basis for long jump context.
841
842 // Outgoing argument set up.
843 movq %rsp, %rcx // Pass arg 4 = SP.
844 movq %rdx, %rsi // Pass arg 2 = value.
845 movq %gs:THREAD_SELF_OFFSET, %rdx // Pass arg 3 = Thread::Current().
846 // Pass arg 1 = array.
847
848 call PLT_SYMBOL(artThrowArrayStoreException) // (array, value, Thread*, SP)
849 int3 // unreached
850END_FUNCTION art_quick_aput_obj
Andreas Gampe525cde22014-04-22 15:44:50 -0700851
852// TODO: This is quite silly on X86_64 now.
853DEFINE_FUNCTION art_quick_memcpy
854 call PLT_SYMBOL(memcpy) // (void*, const void*, size_t)
855 ret
856END_FUNCTION art_quick_memcpy
Ian Rogersef7d42f2014-01-06 12:55:46 -0800857
858NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
859
860UNIMPLEMENTED art_quick_fmod
861UNIMPLEMENTED art_quick_fmodf
862UNIMPLEMENTED art_quick_l2d
863UNIMPLEMENTED art_quick_l2f
864UNIMPLEMENTED art_quick_d2l
865UNIMPLEMENTED art_quick_f2l
866UNIMPLEMENTED art_quick_idivmod
867UNIMPLEMENTED art_quick_ldiv
868UNIMPLEMENTED art_quick_lmod
869UNIMPLEMENTED art_quick_lmul
870UNIMPLEMENTED art_quick_lshl
871UNIMPLEMENTED art_quick_lshr
872UNIMPLEMENTED art_quick_lushr
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700873
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700874
875MACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
876 DEFINE_FUNCTION VAR(c_name, 0)
877 movq 8(%rsp), %rsi // pass referrer
878 SETUP_REF_ONLY_CALLEE_SAVE_FRAME
879 // arg0 is in rdi
880 movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current()
881 movq %rsp, %rcx // pass SP
882 call PLT_VAR(cxx_name, 1) // cxx_name(arg0, referrer, Thread*, SP)
883 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
884 CALL_MACRO(return_macro, 2)
885 END_FUNCTION VAR(c_name, 0)
886END_MACRO
887
888MACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
889 DEFINE_FUNCTION VAR(c_name, 0)
890 movq 8(%rsp), %rdx // pass referrer
891 SETUP_REF_ONLY_CALLEE_SAVE_FRAME
892 // arg0 and arg1 are in rdi/rsi
893 movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current()
894 movq %rsp, %r8 // pass SP
895 call PLT_VAR(cxx_name, 1) // (arg0, arg1, referrer, Thread*, SP)
896 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
897 CALL_MACRO(return_macro, 2)
898 END_FUNCTION VAR(c_name, 0)
899END_MACRO
900
901MACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
902 DEFINE_FUNCTION VAR(c_name, 0)
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700903 movq 8(%rsp), %rcx // pass referrer
904 SETUP_REF_ONLY_CALLEE_SAVE_FRAME
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700905 // arg0, arg1, and arg2 are in rdi/rsi/rdx
906 movq %gs:THREAD_SELF_OFFSET, %r8 // pass Thread::Current()
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700907 movq %rsp, %r9 // pass SP
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700908 call PLT_VAR(cxx_name, 1) // cxx_name(arg0, arg1, arg2, referrer, Thread*, SP)
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700909 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700910 CALL_MACRO(return_macro, 2) // return or deliver exception
911 END_FUNCTION VAR(c_name, 0)
912END_MACRO
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700913
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700914
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700915THREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCode, RETURN_IF_EAX_ZERO
916THREE_ARG_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCode, RETURN_IF_EAX_ZERO
917THREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCode, RETURN_IF_EAX_ZERO
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700918
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700919TWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
920TWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
921TWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700922
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700923TWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCode, RETURN_IF_EAX_ZERO
924TWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCode, RETURN_IF_EAX_ZERO
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700925
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700926ONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
927ONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
928ONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700929
Andreas Gampe9d4e5e22014-05-06 08:29:48 -0700930// This is singled out as the argument order is different.
Alexei Zavjalov8d07e2d2014-05-05 23:36:14 +0700931DEFINE_FUNCTION art_quick_set64_static
932 movq %rsi, %rdx // pass new_val
933 movq 8(%rsp), %rsi // pass referrer
934 SETUP_REF_ONLY_CALLEE_SAVE_FRAME
935 // field_idx is in rdi
936 movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current()
937 movq %rsp, %r8 // pass SP
938 call PLT_SYMBOL(artSet64StaticFromCode) // (field_idx, referrer, new_val, Thread*, SP)
939 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address
940 RETURN_IF_EAX_ZERO // return or deliver exception
941END_FUNCTION art_quick_set64_static
942
Ian Rogersb7dabf52014-03-12 12:11:54 -0700943
944DEFINE_FUNCTION art_quick_proxy_invoke_handler
945 // Save callee and GPR args, mixed together to agree with core spills bitmap of ref. and args
946 // callee save frame.
947 PUSH r15 // Callee save.
948 PUSH r14 // Callee save.
949 PUSH r13 // Callee save.
950 PUSH r12 // Callee save.
951 PUSH r9 // Quick arg 5.
952 PUSH r8 // Quick arg 4.
953 PUSH rsi // Quick arg 1.
954 PUSH rbp // Callee save.
955 PUSH rbx // Callee save.
956 PUSH rdx // Quick arg 2.
957 PUSH rcx // Quick arg 3.
958 // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*.
959 subq LITERAL(80), %rsp
960 CFI_ADJUST_CFA_OFFSET(80)
961 // Save FPRs.
962 movq %xmm0, 16(%rsp)
963 movq %xmm1, 24(%rsp)
964 movq %xmm2, 32(%rsp)
965 movq %xmm3, 40(%rsp)
966 movq %xmm4, 48(%rsp)
967 movq %xmm5, 56(%rsp)
968 movq %xmm6, 64(%rsp)
969 movq %xmm7, 72(%rsp)
970 // Store proxy method to bottom of stack.
971 movq %rdi, 0(%rsp)
972 movq %gs:THREAD_SELF_OFFSET, %rdx // Pass Thread::Current().
973 movq %rsp, %rcx // Pass SP.
974 call PLT_SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP)
975 movq %rax, %xmm0 // Copy return value in case of float returns.
976 addq LITERAL(168), %rsp // Pop arguments.
977 CFI_ADJUST_CFA_OFFSET(-168)
978 RETURN_OR_DELIVER_PENDING_EXCEPTION
979END_FUNCTION art_quick_proxy_invoke_handler
Ian Rogersef7d42f2014-01-06 12:55:46 -0800980
981 /*
982 * Called to resolve an imt conflict.
983 */
984UNIMPLEMENTED art_quick_imt_conflict_trampoline
Ian Rogers936b37f2014-02-14 00:52:24 -0800985
Ian Rogersbefbd572014-03-06 01:13:39 -0800986DEFINE_FUNCTION art_quick_resolution_trampoline
987 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
988 movq %gs:THREAD_SELF_OFFSET, %rdx
989 movq %rsp, %rcx
990 call PLT_SYMBOL(artQuickResolutionTrampoline) // (called, receiver, Thread*, SP)
991 movq %rax, %r10 // Remember returned code pointer in R10.
Ian Rogers1a570662014-03-12 01:02:21 -0700992 movq (%rsp), %rdi // Load called method into RDI.
Ian Rogersbefbd572014-03-06 01:13:39 -0800993 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
994 testq %r10, %r10 // If code pointer is NULL goto deliver pending exception.
995 jz 1f
996 jmp *%r10 // Tail call into method.
9971:
998 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
999 DELIVER_PENDING_EXCEPTION
1000END_FUNCTION art_quick_resolution_trampoline
1001
1002/* Generic JNI frame layout:
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001003 *
1004 * #-------------------#
1005 * | |
1006 * | caller method... |
1007 * #-------------------# <--- SP on entry
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001008 *
1009 * |
1010 * V
1011 *
1012 * #-------------------#
1013 * | caller method... |
1014 * #-------------------#
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001015 * | Return |
1016 * | R15 | callee save
1017 * | R14 | callee save
1018 * | R13 | callee save
1019 * | R12 | callee save
1020 * | R9 | arg5
1021 * | R8 | arg4
1022 * | RSI/R6 | arg1
1023 * | RBP/R5 | callee save
1024 * | RBX/R3 | callee save
1025 * | RDX/R2 | arg2
1026 * | RCX/R1 | arg3
1027 * | XMM7 | float arg 8
1028 * | XMM6 | float arg 7
1029 * | XMM5 | float arg 6
1030 * | XMM4 | float arg 5
1031 * | XMM3 | float arg 4
1032 * | XMM2 | float arg 3
1033 * | XMM1 | float arg 2
1034 * | XMM0 | float arg 1
1035 * | Padding |
1036 * | RDI/Method* | <- sp
1037 * #-------------------#
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001038 * | Scratch Alloca | 5K scratch space
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001039 * #---------#---------#
1040 * | | sp* |
1041 * | Tramp. #---------#
1042 * | args | thread |
1043 * | Tramp. #---------#
1044 * | | method |
1045 * #-------------------# <--- SP on artQuickGenericJniTrampoline
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001046 *
1047 * |
1048 * v artQuickGenericJniTrampoline
1049 *
1050 * #-------------------#
1051 * | caller method... |
1052 * #-------------------#
1053 * | Return |
1054 * | Callee-Save Data |
1055 * #-------------------#
1056 * | SIRT |
1057 * #-------------------#
1058 * | Method* | <--- (1)
1059 * #-------------------#
1060 * | local ref cookie | // 4B
1061 * | SIRT size | // 4B TODO: roll into call stack alignment?
1062 * #-------------------#
1063 * | JNI Call Stack |
1064 * #-------------------# <--- SP on native call
1065 * | |
1066 * | Stack for Regs | The trampoline assembly will pop these values
1067 * | | into registers for native call
1068 * #-------------------#
1069 * | Native code ptr |
1070 * #-------------------#
1071 * | Free scratch |
1072 * #-------------------#
1073 * | Ptr to (1) | <--- RSP
1074 * #-------------------#
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001075 */
Andreas Gampe2da88232014-02-27 12:26:20 -08001076 /*
1077 * Called to do a generic JNI down-call
1078 */
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001079DEFINE_FUNCTION art_quick_generic_jni_trampoline
1080 // Save callee and GPR args, mixed together to agree with core spills bitmap.
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001081 PUSH r15 // Callee save.
1082 PUSH r14 // Callee save.
1083 PUSH r13 // Callee save.
1084 PUSH r12 // Callee save.
1085 PUSH r9 // Quick arg 5.
1086 PUSH r8 // Quick arg 4.
1087 PUSH rsi // Quick arg 1.
1088 PUSH rbp // Callee save.
1089 PUSH rbx // Callee save.
1090 PUSH rdx // Quick arg 2.
1091 PUSH rcx // Quick arg 3.
1092 // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*.
1093 subq LITERAL(80), %rsp
1094 CFI_ADJUST_CFA_OFFSET(80)
1095 // Save FPRs.
1096 movq %xmm0, 16(%rsp)
1097 movq %xmm1, 24(%rsp)
1098 movq %xmm2, 32(%rsp)
1099 movq %xmm3, 40(%rsp)
1100 movq %xmm4, 48(%rsp)
1101 movq %xmm5, 56(%rsp)
1102 movq %xmm6, 64(%rsp)
1103 movq %xmm7, 72(%rsp)
1104 // Store native ArtMethod* to bottom of stack.
1105 movq %rdi, 0(%rsp)
1106 movq %rsp, %rbp // save SP at callee-save frame
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001107 movq %rsp, %rbx
1108 CFI_DEF_CFA_REGISTER(rbx)
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001109 //
1110 // reserve a lot of space
1111 //
1112 // 4 local state ref
1113 // 4 padding
1114 // 4196 4k scratch space, enough for 2x 256 8-byte parameters (TODO: SIRT overhead?)
1115 // 16 SIRT member fields ?
1116 // + 112 14x 8-byte stack-2-register space
1117 // ------
1118 // 4332
1119 // 16-byte aligned: 4336
1120 // Note: 14x8 = 7*16, so the stack stays aligned for the native call...
1121 // Also means: the padding is somewhere in the middle
Andreas Gampec147b002014-03-06 18:11:06 -08001122 //
1123 //
1124 // New test: use 5K and release
1125 // 5k = 5120
1126 subq LITERAL(5120), %rsp
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001127 // prepare for artQuickGenericJniTrampoline call
1128 // (Thread*, SP)
1129 // rdi rsi <= C calling convention
1130 // gs:... rbp <= where they are
1131 movq %gs:THREAD_SELF_OFFSET, %rdi
1132 movq %rbp, %rsi
Ian Rogersbefbd572014-03-06 01:13:39 -08001133 call PLT_SYMBOL(artQuickGenericJniTrampoline) // (Thread*, sp)
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001134
1135 // At the bottom of the alloca we now have the name pointer to the method=bottom of callee-save
1136 // get the adjusted frame pointer
1137 popq %rbp
1138
1139 // Check for error, negative value.
1140 test %rax, %rax
Ian Rogerse0dcd462014-03-08 15:21:04 -08001141 js .Lentry_error
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001142
1143 // release part of the alloca, get the code pointer
Andreas Gampec147b002014-03-06 18:11:06 -08001144 addq %rax, %rsp
Andreas Gampec147b002014-03-06 18:11:06 -08001145 popq %rax
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001146
Andreas Gampec147b002014-03-06 18:11:06 -08001147 // pop from the register-passing alloca region
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001148 // what's the right layout?
1149 popq %rdi
1150 popq %rsi
1151 popq %rdx
1152 popq %rcx
1153 popq %r8
1154 popq %r9
1155 // TODO: skip floating point if unused, some flag.
1156 movq 0(%rsp), %xmm0
1157 movq 8(%rsp), %xmm1
1158 movq 16(%rsp), %xmm2
1159 movq 24(%rsp), %xmm3
1160 movq 32(%rsp), %xmm4
1161 movq 40(%rsp), %xmm5
1162 movq 48(%rsp), %xmm6
1163 movq 56(%rsp), %xmm7
1164 addq LITERAL(64), %rsp // floating-point done
1165 // native call
Ian Rogerse0dcd462014-03-08 15:21:04 -08001166 call *%rax // Stack should be aligned 16B without the return addr?
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001167 // result sign extension is handled in C code
1168 // prepare for artQuickGenericJniEndTrampoline call
1169 // (Thread*, SP, result, result_f)
1170 // rdi rsi rdx rcx <= C calling convention
1171 // gs:... rbp rax xmm0 <= where they are
1172 movq %gs:THREAD_SELF_OFFSET, %rdi
1173 movq %rbp, %rsi
1174 movq %rax, %rdx
1175 movq %xmm0, %rcx
1176 call PLT_SYMBOL(artQuickGenericJniEndTrampoline)
Ian Rogerse0dcd462014-03-08 15:21:04 -08001177
1178 // Tear down the alloca.
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001179 movq %rbx, %rsp
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001180 CFI_DEF_CFA_REGISTER(rsp)
Ian Rogerse0dcd462014-03-08 15:21:04 -08001181
1182 // Pending exceptions possible.
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001183 // TODO: use cmpq, needs direct encoding because of gas bug
Ian Rogerse0dcd462014-03-08 15:21:04 -08001184 movq %gs:THREAD_EXCEPTION_OFFSET, %rcx
1185 test %rcx, %rcx
1186 jnz .Lexception_in_native
1187
1188 // Tear down the callee-save frame.
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001189 // Load FPRs.
1190 // movq %xmm0, 16(%rsp) // doesn't make sense!!!
1191 movq 24(%rsp), %xmm1 // neither does this!!!
1192 movq 32(%rsp), %xmm2
1193 movq 40(%rsp), %xmm3
1194 movq 48(%rsp), %xmm4
1195 movq 56(%rsp), %xmm5
1196 movq 64(%rsp), %xmm6
1197 movq 72(%rsp), %xmm7
1198 // was 80 bytes
1199 addq LITERAL(80), %rsp
1200 CFI_ADJUST_CFA_OFFSET(-80)
1201 // Save callee and GPR args, mixed together to agree with core spills bitmap.
1202 POP rcx // Arg.
1203 POP rdx // Arg.
1204 POP rbx // Callee save.
1205 POP rbp // Callee save.
1206 POP rsi // Arg.
1207 POP r8 // Arg.
1208 POP r9 // Arg.
1209 POP r12 // Callee save.
1210 POP r13 // Callee save.
1211 POP r14 // Callee save.
1212 POP r15 // Callee save.
1213 // store into fpr, for when it's a fpr return...
1214 movq %rax, %xmm0
1215 ret
Ian Rogerse0dcd462014-03-08 15:21:04 -08001216.Lentry_error:
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001217 movq %rbx, %rsp
1218 CFI_DEF_CFA_REGISTER(rsp)
Ian Rogerse0dcd462014-03-08 15:21:04 -08001219.Lexception_in_native:
Ian Rogerse0dcd462014-03-08 15:21:04 -08001220 // TODO: the SIRT contains the this pointer which is used by the debugger for exception
1221 // delivery.
Andreas Gampe36fea8d2014-03-10 13:37:40 -07001222 movq %xmm0, 16(%rsp) // doesn't make sense!!!
1223 movq 24(%rsp), %xmm1 // neither does this!!!
1224 movq 32(%rsp), %xmm2
1225 movq 40(%rsp), %xmm3
1226 movq 48(%rsp), %xmm4
1227 movq 56(%rsp), %xmm5
1228 movq 64(%rsp), %xmm6
1229 movq 72(%rsp), %xmm7
1230 // was 80 bytes
1231 addq LITERAL(80), %rsp
1232 CFI_ADJUST_CFA_OFFSET(-80)
1233 // Save callee and GPR args, mixed together to agree with core spills bitmap.
1234 POP rcx // Arg.
1235 POP rdx // Arg.
1236 POP rbx // Callee save.
1237 POP rbp // Callee save.
1238 POP rsi // Arg.
1239 POP r8 // Arg.
1240 POP r9 // Arg.
1241 POP r12 // Callee save.
1242 POP r13 // Callee save.
1243 POP r14 // Callee save.
1244 POP r15 // Callee save.
1245
Andreas Gampebf6b92a2014-03-05 16:11:04 -08001246 DELIVER_PENDING_EXCEPTION
1247END_FUNCTION art_quick_generic_jni_trampoline
Andreas Gampe2da88232014-02-27 12:26:20 -08001248
Ian Rogers936b37f2014-02-14 00:52:24 -08001249 /*
1250 * Called to bridge from the quick to interpreter ABI. On entry the arguments match those
1251 * of a quick call:
1252 * RDI = method being called / to bridge to.
1253 * RSI, RDX, RCX, R8, R9 are arguments to that method.
1254 */
1255DEFINE_FUNCTION art_quick_to_interpreter_bridge
1256 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // Set up frame and save arguments.
1257 movq %gs:THREAD_SELF_OFFSET, %rsi // RSI := Thread::Current()
1258 movq %rsp, %rdx // RDX := sp
1259 call PLT_SYMBOL(artQuickToInterpreterBridge) // (method, Thread*, SP)
1260 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME // TODO: no need to restore arguments in this case.
1261 movq %rax, %xmm0 // Place return value also into floating point return value.
1262 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception
1263END_FUNCTION art_quick_to_interpreter_bridge
Ian Rogersef7d42f2014-01-06 12:55:46 -08001264
1265 /*
1266 * Routine that intercepts method calls and returns.
1267 */
1268UNIMPLEMENTED art_quick_instrumentation_entry
1269UNIMPLEMENTED art_quick_instrumentation_exit
1270
1271 /*
1272 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization
1273 * will long jump to the upcall with a special exception of -1.
1274 */
1275UNIMPLEMENTED art_quick_deoptimize
1276
1277UNIMPLEMENTED art_quick_indexof
Alexei Zavjalov315ccab2014-05-01 23:24:05 +07001278
1279 /*
1280 * String's compareTo.
1281 *
1282 * On entry:
1283 * rdi: this string object (known non-null)
1284 * rsi: comp string object (known non-null)
1285 */
1286DEFINE_FUNCTION art_quick_string_compareto
1287 movl STRING_COUNT_OFFSET(%edi), %r8d
1288 movl STRING_COUNT_OFFSET(%esi), %r9d
1289 movl STRING_VALUE_OFFSET(%edi), %r10d
1290 movl STRING_VALUE_OFFSET(%esi), %r11d
1291 movl STRING_OFFSET_OFFSET(%edi), %eax
1292 movl STRING_OFFSET_OFFSET(%esi), %ecx
1293 /* Build pointers to the start of string data */
1294 leal STRING_DATA_OFFSET(%r10d, %eax, 2), %esi
1295 leal STRING_DATA_OFFSET(%r11d, %ecx, 2), %edi
1296 /* Calculate min length and count diff */
1297 movl %r8d, %ecx
1298 movl %r8d, %eax
1299 subl %r9d, %eax
1300 cmovg %r9d, %ecx
1301 /*
1302 * At this point we have:
1303 * eax: value to return if first part of strings are equal
1304 * ecx: minimum among the lengths of the two strings
1305 * esi: pointer to this string data
1306 * edi: pointer to comp string data
1307 */
1308 jecxz .Lkeep_length
1309 repe cmpsw // find nonmatching chars in [%esi] and [%edi], up to length %ecx
1310 jne .Lnot_equal
1311.Lkeep_length:
1312 ret
1313 .balign 16
1314.Lnot_equal:
1315 movzwl -2(%esi), %eax // get last compared char from this string
1316 movzwl -2(%edi), %ecx // get last compared char from comp string
1317 subl %ecx, %eax // return the difference
1318 ret
1319END_FUNCTION art_quick_string_compareto
1320
Ian Rogersef7d42f2014-01-06 12:55:46 -08001321UNIMPLEMENTED art_quick_memcmp16