1/* 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 19MACRO0(SETUP_FP_CALLEE_SAVE_FRAME) 20 // Create space for ART FP callee-saved registers 21 subq MACRO_LITERAL(4 * 8), %rsp 22 CFI_ADJUST_CFA_OFFSET(4 * 8) 23 movq %xmm12, 0(%rsp) 24 movq %xmm13, 8(%rsp) 25 movq %xmm14, 16(%rsp) 26 movq %xmm15, 24(%rsp) 27END_MACRO 28 29MACRO0(RESTORE_FP_CALLEE_SAVE_FRAME) 30 // Restore ART FP callee-saved registers 31 movq 0(%rsp), %xmm12 32 movq 8(%rsp), %xmm13 33 movq 16(%rsp), %xmm14 34 movq 24(%rsp), %xmm15 35 addq MACRO_LITERAL(4 * 8), %rsp 36 CFI_ADJUST_CFA_OFFSET(- 4 * 8) 37END_MACRO 38 39// For x86, the CFA is esp+4, the address above the pushed return address on the stack. 40 41 /* 42 * Macro that sets up the callee save frame to conform with 43 * Runtime::CreateCalleeSaveMethod(kSaveAll) 44 */ 45MACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME) 46#if defined(__APPLE__) 47 int3 48 int3 49#else 50 // R10 := Runtime::Current() 51 movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10 52 movq (%r10), %r10 53 // Save callee save registers to agree with core spills bitmap. 54 PUSH r15 // Callee save. 55 PUSH r14 // Callee save. 56 PUSH r13 // Callee save. 57 PUSH r12 // Callee save. 58 PUSH rbp // Callee save. 59 PUSH rbx // Callee save. 60 // Create space for FPR args, plus padding for alignment 61 subq LITERAL(4 * 8), %rsp 62 CFI_ADJUST_CFA_OFFSET(4 * 8) 63 // Save FPRs. 64 movq %xmm12, 0(%rsp) 65 movq %xmm13, 8(%rsp) 66 movq %xmm14, 16(%rsp) 67 movq %xmm15, 24(%rsp) 68 subq MACRO_LITERAL(8), %rsp // Space for Method* (also aligns the frame). 69 CFI_ADJUST_CFA_OFFSET(8) 70 // R10 := ArtMethod* for save all callee save frame method. 71 THIS_LOAD_REQUIRES_READ_BARRIER 72 movq RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10 73 // Store ArtMethod* to bottom of stack. 74 movq %r10, 0(%rsp) 75 76 // Ugly compile-time check, but we only have the preprocessor. 77 // Last +8: implicit return address pushed on stack when caller made call. 78#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 6*8 + 4*8 + 8 + 8) 79#error "SAVE_ALL_CALLEE_SAVE_FRAME(X86_64) size not as expected." 80#endif 81#endif // __APPLE__ 82END_MACRO 83 84 /* 85 * Macro that sets up the callee save frame to conform with 86 * Runtime::CreateCalleeSaveMethod(kRefsOnly) 87 */ 88MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME) 89#if defined(__APPLE__) 90 int3 91 int3 92#else 93 // R10 := Runtime::Current() 94 movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10 95 movq (%r10), %r10 96 // Save callee and GPR args, mixed together to agree with core spills bitmap. 97 PUSH r15 // Callee save. 98 PUSH r14 // Callee save. 99 PUSH r13 // Callee save. 100 PUSH r12 // Callee save. 101 PUSH rbp // Callee save. 102 PUSH rbx // Callee save. 103 // Create space for FPR args, plus padding for alignment 104 subq LITERAL(8 + 4*8), %rsp 105 CFI_ADJUST_CFA_OFFSET(8 + 4*8) 106 // Save FPRs. 107 movq %xmm12, 8(%rsp) 108 movq %xmm13, 16(%rsp) 109 movq %xmm14, 24(%rsp) 110 movq %xmm15, 32(%rsp) 111 // R10 := ArtMethod* for refs only callee save frame method. 112 THIS_LOAD_REQUIRES_READ_BARRIER 113 movq RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10 114 // Store ArtMethod* to bottom of stack. 115 movq %r10, 0(%rsp) 116 117 // Ugly compile-time check, but we only have the preprocessor. 118 // Last +8: implicit return address pushed on stack when caller made call. 119#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 6*8 + 4*8 + 8 + 8) 120#error "REFS_ONLY_CALLEE_SAVE_FRAME(X86_64) size not as expected." 121#endif 122#endif // __APPLE__ 123END_MACRO 124 125MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME) 126 movq 8(%rsp), %xmm12 127 movq 16(%rsp), %xmm13 128 movq 24(%rsp), %xmm14 129 movq 32(%rsp), %xmm15 130 addq LITERAL(8 + 4*8), %rsp 131 CFI_ADJUST_CFA_OFFSET(-8 - 4*8) 132 // TODO: optimize by not restoring callee-saves restored by the ABI 133 POP rbx 134 POP rbp 135 POP r12 136 POP r13 137 POP r14 138 POP r15 139END_MACRO 140 141 /* 142 * Macro that sets up the callee save frame to conform with 143 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs) 144 */ 145MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME) 146#if defined(__APPLE__) 147 int3 148 int3 149#else 150 // R10 := Runtime::Current() 151 movq _ZN3art7Runtime9instance_E@GOTPCREL(%rip), %r10 152 movq (%r10), %r10 153 // Save callee and GPR args, mixed together to agree with core spills bitmap. 154 PUSH r15 // Callee save. 155 PUSH r14 // Callee save. 156 PUSH r13 // Callee save. 157 PUSH r12 // Callee save. 158 PUSH r9 // Quick arg 5. 159 PUSH r8 // Quick arg 4. 160 PUSH rsi // Quick arg 1. 161 PUSH rbp // Callee save. 162 PUSH rbx // Callee save. 163 PUSH rdx // Quick arg 2. 164 PUSH rcx // Quick arg 3. 165 // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*. 166 subq MACRO_LITERAL(80 + 4 * 8), %rsp 167 CFI_ADJUST_CFA_OFFSET(80 + 4 * 8) 168 // R10 := ArtMethod* for ref and args callee save frame method. 169 THIS_LOAD_REQUIRES_READ_BARRIER 170 movq RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10 171 // Save FPRs. 172 movq %xmm0, 16(%rsp) 173 movq %xmm1, 24(%rsp) 174 movq %xmm2, 32(%rsp) 175 movq %xmm3, 40(%rsp) 176 movq %xmm4, 48(%rsp) 177 movq %xmm5, 56(%rsp) 178 movq %xmm6, 64(%rsp) 179 movq %xmm7, 72(%rsp) 180 movq %xmm12, 80(%rsp) 181 movq %xmm13, 88(%rsp) 182 movq %xmm14, 96(%rsp) 183 movq %xmm15, 104(%rsp) 184 // Store ArtMethod* to bottom of stack. 185 movq %r10, 0(%rsp) 186 187 // Ugly compile-time check, but we only have the preprocessor. 188 // Last +8: implicit return address pushed on stack when caller made call. 189#if (FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE != 11*8 + 4*8 + 80 + 8) 190#error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(X86_64) size not as expected." 191#endif 192#endif // __APPLE__ 193END_MACRO 194 195MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME) 196 // Restore FPRs. 197 movq 16(%rsp), %xmm0 198 movq 24(%rsp), %xmm1 199 movq 32(%rsp), %xmm2 200 movq 40(%rsp), %xmm3 201 movq 48(%rsp), %xmm4 202 movq 56(%rsp), %xmm5 203 movq 64(%rsp), %xmm6 204 movq 72(%rsp), %xmm7 205 movq 80(%rsp), %xmm12 206 movq 88(%rsp), %xmm13 207 movq 96(%rsp), %xmm14 208 movq 104(%rsp), %xmm15 209 addq MACRO_LITERAL(80 + 4 * 8), %rsp 210 CFI_ADJUST_CFA_OFFSET(-(80 + 4 * 8)) 211 // Restore callee and GPR args, mixed together to agree with core spills bitmap. 212 POP rcx 213 POP rdx 214 POP rbx 215 POP rbp 216 POP rsi 217 POP r8 218 POP r9 219 POP r12 220 POP r13 221 POP r14 222 POP r15 223END_MACRO 224 225 226 /* 227 * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending 228 * exception is Thread::Current()->exception_. 229 */ 230MACRO0(DELIVER_PENDING_EXCEPTION) 231 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save callee saves for throw 232 // (Thread*, SP) setup 233 movq %gs:THREAD_SELF_OFFSET, %rdi 234 movq %rsp, %rsi 235 call SYMBOL(artDeliverPendingExceptionFromCode) // artDeliverPendingExceptionFromCode(Thread*, SP) 236 UNREACHABLE 237END_MACRO 238 239MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 240 DEFINE_FUNCTION VAR(c_name, 0) 241 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 242 // Outgoing argument set up 243 movq %rsp, %rsi // pass SP 244 movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current() 245 call VAR(cxx_name, 1) // cxx_name(Thread*, SP) 246 UNREACHABLE 247 END_FUNCTION VAR(c_name, 0) 248END_MACRO 249 250MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 251 DEFINE_FUNCTION VAR(c_name, 0) 252 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 253 // Outgoing argument set up 254 movq %rsp, %rdx // pass SP 255 movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current() 256 call VAR(cxx_name, 1) // cxx_name(arg1, Thread*, SP) 257 UNREACHABLE 258 END_FUNCTION VAR(c_name, 0) 259END_MACRO 260 261MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 262 DEFINE_FUNCTION VAR(c_name, 0) 263 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 264 // Outgoing argument set up 265 movq %rsp, %rcx // pass SP 266 movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() 267 call VAR(cxx_name, 1) // cxx_name(Thread*, SP) 268 UNREACHABLE 269 END_FUNCTION VAR(c_name, 0) 270END_MACRO 271 272 /* 273 * Called by managed code to create and deliver a NullPointerException. 274 */ 275NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode 276 277 /* 278 * Called by managed code to create and deliver an ArithmeticException. 279 */ 280NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode 281 282 /* 283 * Called by managed code to create and deliver a StackOverflowError. 284 */ 285NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode 286 287 /* 288 * Called by managed code, saves callee saves and then calls artThrowException 289 * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception. 290 */ 291ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode 292 293 /* 294 * Called by managed code to create and deliver a NoSuchMethodError. 295 */ 296ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode 297 298 /* 299 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds 300 * index, arg2 holds limit. 301 */ 302TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode 303 304 /* 305 * All generated callsites for interface invokes and invocation slow paths will load arguments 306 * as usual - except instead of loading arg0/rdi with the target Method*, arg0/rdi will contain 307 * the method_idx. This wrapper will save arg1-arg3, load the caller's Method*, align the 308 * stack and call the appropriate C helper. 309 * NOTE: "this" is first visible argument of the target, and so can be found in arg1/rsi. 310 * 311 * The helper will attempt to locate the target and return a 128-bit result in rax/rdx consisting 312 * of the target Method* in rax and method->code_ in rdx. 313 * 314 * If unsuccessful, the helper will return NULL/????. There will be a pending exception in the 315 * thread and we branch to another stub to deliver it. 316 * 317 * On success this wrapper will restore arguments and *jump* to the target, leaving the return 318 * location on the stack. 319 * 320 * Adapted from x86 code. 321 */ 322MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name) 323 DEFINE_FUNCTION VAR(c_name, 0) 324 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save callee saves in case allocation triggers GC 325 // Helper signature is always 326 // (method_idx, *this_object, *caller_method, *self, sp) 327 328 movl FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE(%rsp), %edx // pass caller Method* 329 movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread 330 movq %rsp, %r8 // pass SP 331 332 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, caller method*, Thread*, SP) 333 // save the code pointer 334 movq %rax, %rdi 335 movq %rdx, %rax 336 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 337 338 testq %rdi, %rdi 339 jz 1f 340 341 // Tail call to intended method. 342 jmp *%rax 3431: 344 DELIVER_PENDING_EXCEPTION 345 END_FUNCTION VAR(c_name, 0) 346END_MACRO 347 348INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline 349INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck 350 351INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck 352INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck 353INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck 354INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck 355 356 357 /* 358 * Helper for quick invocation stub to set up XMM registers. Assumes r10 == shorty, 359 * r11 == arg_array. Clobbers r10, r11 and al. Branches to xmm_setup_finished if it encounters 360 * the end of the shorty. 361 */ 362MACRO2(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, finished) 3631: // LOOP 364 movb (%r10), %al // al := *shorty 365 addq MACRO_LITERAL(1), %r10 // shorty++ 366 cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto xmm_setup_finished 367 je VAR(finished, 1) 368 cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto FOUND_DOUBLE 369 je 2f 370 cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto FOUND_FLOAT 371 je 3f 372 addq MACRO_LITERAL(4), %r11 // arg_array++ 373 // Handle extra space in arg array taken by a long. 374 cmpb MACRO_LITERAL(74), %al // if (al != 'J') goto LOOP 375 jne 1b 376 addq MACRO_LITERAL(4), %r11 // arg_array++ 377 jmp 1b // goto LOOP 3782: // FOUND_DOUBLE 379 movsd (%r11), REG_VAR(xmm_reg, 0) 380 addq MACRO_LITERAL(8), %r11 // arg_array+=2 381 jmp 4f 3823: // FOUND_FLOAT 383 movss (%r11), REG_VAR(xmm_reg, 0) 384 addq MACRO_LITERAL(4), %r11 // arg_array++ 3854: 386END_MACRO 387 388 /* 389 * Helper for quick invocation stub to set up GPR registers. Assumes r10 == shorty, 390 * r11 == arg_array. Clobbers r10, r11 and al. Branches to gpr_setup_finished if it encounters 391 * the end of the shorty. 392 */ 393MACRO3(LOOP_OVER_SHORTY_LOADING_GPRS, gpr_reg64, gpr_reg32, finished) 3941: // LOOP 395 movb (%r10), %al // al := *shorty 396 addq MACRO_LITERAL(1), %r10 // shorty++ 397 cmpb MACRO_LITERAL(0), %al // if (al == '\0') goto gpr_setup_finished 398 je VAR(finished, 2) 399 cmpb MACRO_LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 400 je 2f 401 cmpb MACRO_LITERAL(70), %al // if (al == 'F') goto SKIP_FLOAT 402 je 3f 403 cmpb MACRO_LITERAL(68), %al // if (al == 'D') goto SKIP_DOUBLE 404 je 4f 405 movl (%r11), REG_VAR(gpr_reg32, 1) 406 addq MACRO_LITERAL(4), %r11 // arg_array++ 407 jmp 5f 4082: // FOUND_LONG 409 movq (%r11), REG_VAR(gpr_reg64, 0) 410 addq MACRO_LITERAL(8), %r11 // arg_array+=2 411 jmp 5f 4123: // SKIP_FLOAT 413 addq MACRO_LITERAL(4), %r11 // arg_array++ 414 jmp 1b 4154: // SKIP_DOUBLE 416 addq MACRO_LITERAL(8), %r11 // arg_array+=2 417 jmp 1b 4185: 419END_MACRO 420 421 /* 422 * Quick invocation stub. 423 * On entry: 424 * [sp] = return address 425 * rdi = method pointer 426 * rsi = argument array that must at least contain the this pointer. 427 * rdx = size of argument array in bytes 428 * rcx = (managed) thread pointer 429 * r8 = JValue* result 430 * r9 = char* shorty 431 */ 432DEFINE_FUNCTION art_quick_invoke_stub 433#if defined(__APPLE__) 434 int3 435 int3 436#else 437 // Set up argument XMM registers. 438 leaq 1(%r9), %r10 // R10 := shorty + 1 ; ie skip return arg character. 439 leaq 4(%rsi), %r11 // R11 := arg_array + 4 ; ie skip this pointer. 440 LOOP_OVER_SHORTY_LOADING_XMMS xmm0, .Lxmm_setup_finished 441 LOOP_OVER_SHORTY_LOADING_XMMS xmm1, .Lxmm_setup_finished 442 LOOP_OVER_SHORTY_LOADING_XMMS xmm2, .Lxmm_setup_finished 443 LOOP_OVER_SHORTY_LOADING_XMMS xmm3, .Lxmm_setup_finished 444 LOOP_OVER_SHORTY_LOADING_XMMS xmm4, .Lxmm_setup_finished 445 LOOP_OVER_SHORTY_LOADING_XMMS xmm5, .Lxmm_setup_finished 446 LOOP_OVER_SHORTY_LOADING_XMMS xmm6, .Lxmm_setup_finished 447 LOOP_OVER_SHORTY_LOADING_XMMS xmm7, .Lxmm_setup_finished 448 .balign 16 449.Lxmm_setup_finished: 450 PUSH rbp // Save rbp. 451 PUSH r8 // Save r8/result*. 452 PUSH r9 // Save r9/shorty*. 453 movq %rsp, %rbp // Copy value of stack pointer into base pointer. 454 CFI_DEF_CFA_REGISTER(rbp) 455 456 movl %edx, %r10d 457 addl LITERAL(60), %edx // Reserve space for return addr, StackReference<method>, rbp, 458 // r8 and r9 in frame. 459 andl LITERAL(0xFFFFFFF0), %edx // Align frame size to 16 bytes. 460 subl LITERAL(32), %edx // Remove space for return address, rbp, r8 and r9. 461 subq %rdx, %rsp // Reserve stack space for argument array. 462 463#if (STACK_REFERENCE_SIZE != 4) 464#error "STACK_REFERENCE_SIZE(X86_64) size not as expected." 465#endif 466 movl LITERAL(0), (%rsp) // Store NULL for method* 467 468 movl %r10d, %ecx // Place size of args in rcx. 469 movq %rdi, %rax // RAX := method to be called 470 movq %rsi, %r11 // R11 := arg_array 471 leaq 4(%rsp), %rdi // Rdi is pointing just above the StackReference<method> in the 472 // stack arguments. 473 // Copy arg array into stack. 474 rep movsb // while (rcx--) { *rdi++ = *rsi++ } 475 leaq 1(%r9), %r10 // R10 := shorty + 1 ; ie skip return arg character 476 movq %rax, %rdi // RDI := method to be called 477 movl (%r11), %esi // RSI := this pointer 478 addq LITERAL(4), %r11 // arg_array++ 479 LOOP_OVER_SHORTY_LOADING_GPRS rdx, edx, .Lgpr_setup_finished 480 LOOP_OVER_SHORTY_LOADING_GPRS rcx, ecx, .Lgpr_setup_finished 481 LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, .Lgpr_setup_finished 482 LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, .Lgpr_setup_finished 483.Lgpr_setup_finished: 484 call *METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. 485 movq %rbp, %rsp // Restore stack pointer. 486 CFI_DEF_CFA_REGISTER(rsp) 487 POP r9 // Pop r9 - shorty*. 488 POP r8 // Pop r8 - result*. 489 POP rbp // Pop rbp 490 cmpb LITERAL(68), (%r9) // Test if result type char == 'D'. 491 je .Lreturn_double_quick 492 cmpb LITERAL(70), (%r9) // Test if result type char == 'F'. 493 je .Lreturn_float_quick 494 movq %rax, (%r8) // Store the result assuming its a long, int or Object* 495 ret 496.Lreturn_double_quick: 497 movsd %xmm0, (%r8) // Store the double floating point result. 498 ret 499.Lreturn_float_quick: 500 movss %xmm0, (%r8) // Store the floating point result. 501 ret 502#endif // __APPLE__ 503END_FUNCTION art_quick_invoke_stub 504 505 /* 506 * Quick invocation stub. 507 * On entry: 508 * [sp] = return address 509 * rdi = method pointer 510 * rsi = argument array or NULL if no arguments. 511 * rdx = size of argument array in bytes 512 * rcx = (managed) thread pointer 513 * r8 = JValue* result 514 * r9 = char* shorty 515 */ 516DEFINE_FUNCTION art_quick_invoke_static_stub 517#if defined(__APPLE__) 518 int3 519 int3 520#else 521 // Set up argument XMM registers. 522 leaq 1(%r9), %r10 // R10 := shorty + 1 ; ie skip return arg character 523 movq %rsi, %r11 // R11 := arg_array 524 LOOP_OVER_SHORTY_LOADING_XMMS xmm0, .Lxmm_setup_finished2 525 LOOP_OVER_SHORTY_LOADING_XMMS xmm1, .Lxmm_setup_finished2 526 LOOP_OVER_SHORTY_LOADING_XMMS xmm2, .Lxmm_setup_finished2 527 LOOP_OVER_SHORTY_LOADING_XMMS xmm3, .Lxmm_setup_finished2 528 LOOP_OVER_SHORTY_LOADING_XMMS xmm4, .Lxmm_setup_finished2 529 LOOP_OVER_SHORTY_LOADING_XMMS xmm5, .Lxmm_setup_finished2 530 LOOP_OVER_SHORTY_LOADING_XMMS xmm6, .Lxmm_setup_finished2 531 LOOP_OVER_SHORTY_LOADING_XMMS xmm7, .Lxmm_setup_finished2 532 .balign 16 533.Lxmm_setup_finished2: 534 PUSH rbp // Save rbp. 535 PUSH r8 // Save r8/result*. 536 PUSH r9 // Save r9/shorty*. 537 movq %rsp, %rbp // Copy value of stack pointer into base pointer. 538 CFI_DEF_CFA_REGISTER(rbp) 539 540 movl %edx, %r10d 541 addl LITERAL(60), %edx // Reserve space for return addr, StackReference<method>, rbp, 542 // r8 and r9 in frame. 543 andl LITERAL(0xFFFFFFF0), %edx // Align frame size to 16 bytes. 544 subl LITERAL(32), %edx // Remove space for return address, rbp, r8 and r9. 545 subq %rdx, %rsp // Reserve stack space for argument array. 546 547#if (STACK_REFERENCE_SIZE != 4) 548#error "STACK_REFERENCE_SIZE(X86_64) size not as expected." 549#endif 550 movl LITERAL(0), (%rsp) // Store NULL for method* 551 552 movl %r10d, %ecx // Place size of args in rcx. 553 movq %rdi, %rax // RAX := method to be called 554 movq %rsi, %r11 // R11 := arg_array 555 leaq 4(%rsp), %rdi // Rdi is pointing just above the StackReference<method> in the 556 // stack arguments. 557 // Copy arg array into stack. 558 rep movsb // while (rcx--) { *rdi++ = *rsi++ } 559 leaq 1(%r9), %r10 // R10 := shorty + 1 ; ie skip return arg character 560 movq %rax, %rdi // RDI := method to be called 561 LOOP_OVER_SHORTY_LOADING_GPRS rsi, esi, .Lgpr_setup_finished2 562 LOOP_OVER_SHORTY_LOADING_GPRS rdx, edx, .Lgpr_setup_finished2 563 LOOP_OVER_SHORTY_LOADING_GPRS rcx, ecx, .Lgpr_setup_finished2 564 LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, .Lgpr_setup_finished2 565 LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, .Lgpr_setup_finished2 566.Lgpr_setup_finished2: 567 call *METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method. 568 movq %rbp, %rsp // Restore stack pointer. 569 CFI_DEF_CFA_REGISTER(rsp) 570 POP r9 // Pop r9 - shorty*. 571 POP r8 // Pop r8 - result*. 572 POP rbp // Pop rbp 573 cmpb LITERAL(68), (%r9) // Test if result type char == 'D'. 574 je .Lreturn_double_quick2 575 cmpb LITERAL(70), (%r9) // Test if result type char == 'F'. 576 je .Lreturn_float_quick2 577 movq %rax, (%r8) // Store the result assuming its a long, int or Object* 578 ret 579.Lreturn_double_quick2: 580 movsd %xmm0, (%r8) // Store the double floating point result. 581 ret 582.Lreturn_float_quick2: 583 movss %xmm0, (%r8) // Store the floating point result. 584 ret 585#endif // __APPLE__ 586END_FUNCTION art_quick_invoke_static_stub 587 588 /* 589 * Long jump stub. 590 * On entry: 591 * rdi = gprs 592 * rsi = fprs 593 */ 594DEFINE_FUNCTION art_quick_do_long_jump 595#if defined(__APPLE__) 596 int3 597 int3 598#else 599 // Restore FPRs. 600 movq 0(%rsi), %xmm0 601 movq 8(%rsi), %xmm1 602 movq 16(%rsi), %xmm2 603 movq 24(%rsi), %xmm3 604 movq 32(%rsi), %xmm4 605 movq 40(%rsi), %xmm5 606 movq 48(%rsi), %xmm6 607 movq 56(%rsi), %xmm7 608 movq 64(%rsi), %xmm8 609 movq 72(%rsi), %xmm9 610 movq 80(%rsi), %xmm10 611 movq 88(%rsi), %xmm11 612 movq 96(%rsi), %xmm12 613 movq 104(%rsi), %xmm13 614 movq 112(%rsi), %xmm14 615 movq 120(%rsi), %xmm15 616 // Restore FPRs. 617 movq %rdi, %rsp // RSP points to gprs. 618 // Load all registers except RSP and RIP with values in gprs. 619 popq %r15 620 popq %r14 621 popq %r13 622 popq %r12 623 popq %r11 624 popq %r10 625 popq %r9 626 popq %r8 627 popq %rdi 628 popq %rsi 629 popq %rbp 630 addq LITERAL(8), %rsp // Skip rsp 631 popq %rbx 632 popq %rdx 633 popq %rcx 634 popq %rax 635 popq %rsp // Load stack pointer. 636 ret // From higher in the stack pop rip. 637#endif // __APPLE__ 638END_FUNCTION art_quick_do_long_jump 639 640MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 641 DEFINE_FUNCTION VAR(c_name, 0) 642 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 643 // Outgoing argument set up 644 movq %rsp, %rsi // pass SP 645 movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current() 646 call VAR(cxx_name, 1) // cxx_name(Thread*, SP) 647 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 648 CALL_MACRO(return_macro, 2) // return or deliver exception 649 END_FUNCTION VAR(c_name, 0) 650END_MACRO 651 652MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 653 DEFINE_FUNCTION VAR(c_name, 0) 654 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 655 // Outgoing argument set up 656 movq %rsp, %rdx // pass SP 657 movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current() 658 call VAR(cxx_name, 1) // cxx_name(arg0, Thread*, SP) 659 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 660 CALL_MACRO(return_macro, 2) // return or deliver exception 661 END_FUNCTION VAR(c_name, 0) 662END_MACRO 663 664MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 665 DEFINE_FUNCTION VAR(c_name, 0) 666 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 667 // Outgoing argument set up 668 movq %rsp, %rcx // pass SP 669 movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() 670 call VAR(cxx_name, 1) // cxx_name(arg0, arg1, Thread*, SP) 671 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 672 CALL_MACRO(return_macro, 2) // return or deliver exception 673 END_FUNCTION VAR(c_name, 0) 674END_MACRO 675 676MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 677 DEFINE_FUNCTION VAR(c_name, 0) 678 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 679 // Outgoing argument set up 680 movq %rsp, %r8 // pass SP 681 movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current() 682 call VAR(cxx_name, 1) // cxx_name(arg0, arg1, arg2, Thread*, SP) 683 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 684 CALL_MACRO(return_macro, 2) // return or deliver exception 685 END_FUNCTION VAR(c_name, 0) 686END_MACRO 687 688MACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) 689 DEFINE_FUNCTION VAR(c_name, 0) 690 movl 8(%rsp), %esi // pass referrer 691 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 692 // arg0 is in rdi 693 movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() 694 movq %rsp, %rcx // pass SP 695 call VAR(cxx_name, 1) // cxx_name(arg0, referrer, Thread*, SP) 696 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 697 CALL_MACRO(return_macro, 2) 698 END_FUNCTION VAR(c_name, 0) 699END_MACRO 700 701MACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) 702 DEFINE_FUNCTION VAR(c_name, 0) 703 movl 8(%rsp), %edx // pass referrer 704 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 705 // arg0 and arg1 are in rdi/rsi 706 movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current() 707 movq %rsp, %r8 // pass SP 708 call VAR(cxx_name, 1) // (arg0, arg1, referrer, Thread*, SP) 709 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 710 CALL_MACRO(return_macro, 2) 711 END_FUNCTION VAR(c_name, 0) 712END_MACRO 713 714MACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) 715 DEFINE_FUNCTION VAR(c_name, 0) 716 movl 8(%rsp), %ecx // pass referrer 717 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 718 // arg0, arg1, and arg2 are in rdi/rsi/rdx 719 movq %gs:THREAD_SELF_OFFSET, %r8 // pass Thread::Current() 720 movq %rsp, %r9 // pass SP 721 call VAR(cxx_name, 1) // cxx_name(arg0, arg1, arg2, referrer, Thread*, SP) 722 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 723 CALL_MACRO(return_macro, 2) // return or deliver exception 724 END_FUNCTION VAR(c_name, 0) 725END_MACRO 726 727MACRO0(RETURN_IF_RESULT_IS_NON_ZERO) 728 testq %rax, %rax // rax == 0 ? 729 jz 1f // if rax == 0 goto 1 730 ret // return 7311: // deliver exception on current thread 732 DELIVER_PENDING_EXCEPTION 733END_MACRO 734 735MACRO0(RETURN_IF_EAX_ZERO) 736 testl %eax, %eax // eax == 0 ? 737 jnz 1f // if eax != 0 goto 1 738 ret // return 7391: // deliver exception on current thread 740 DELIVER_PENDING_EXCEPTION 741END_MACRO 742 743MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION) 744 movq %gs:THREAD_EXCEPTION_OFFSET, %rcx // get exception field 745 testq %rcx, %rcx // rcx == 0 ? 746 jnz 1f // if rcx != 0 goto 1 747 ret // return 7481: // deliver exception on current thread 749 DELIVER_PENDING_EXCEPTION 750END_MACRO 751 752// Generate the allocation entrypoints for each allocator. 753// TODO: use arch/quick_alloc_entrypoints.S. Currently we don't as we need to use concatenation 754// macros to work around differences between OS/X's as and binutils as (OS/X lacks named arguments 755// to macros and the VAR macro won't concatenate arguments properly), this also breaks having 756// multi-line macros that use each other (hence using 1 macro per newline below). 757#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(c_suffix, cxx_suffix) \ 758 TWO_ARG_DOWNCALL art_quick_alloc_object ## c_suffix, artAllocObjectFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 759#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(c_suffix, cxx_suffix) \ 760 TWO_ARG_DOWNCALL art_quick_alloc_object_resolved ## c_suffix, artAllocObjectFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 761#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(c_suffix, cxx_suffix) \ 762 TWO_ARG_DOWNCALL art_quick_alloc_object_initialized ## c_suffix, artAllocObjectFromCodeInitialized ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 763#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \ 764 TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check ## c_suffix, artAllocObjectFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 765#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(c_suffix, cxx_suffix) \ 766 THREE_ARG_DOWNCALL art_quick_alloc_array ## c_suffix, artAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 767#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(c_suffix, cxx_suffix) \ 768 THREE_ARG_DOWNCALL art_quick_alloc_array_resolved ## c_suffix, artAllocArrayFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 769#define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \ 770 THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check ## c_suffix, artAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 771#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(c_suffix, cxx_suffix) \ 772 THREE_ARG_DOWNCALL art_quick_check_and_alloc_array ## c_suffix, artCheckAndAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 773#define GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \ 774 THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check ## c_suffix, artCheckAndAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO 775 776GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc, DlMalloc) 777GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc, DlMalloc) 778GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc, DlMalloc) 779GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc) 780GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc, DlMalloc) 781GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc, DlMalloc) 782GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc) 783GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc, DlMalloc) 784GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc, DlMalloc) 785 786GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_dlmalloc_instrumented, DlMallocInstrumented) 787GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented) 788GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_dlmalloc_instrumented, DlMallocInstrumented) 789GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented) 790GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented) 791GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_dlmalloc_instrumented, DlMallocInstrumented) 792GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented) 793GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_dlmalloc_instrumented, DlMallocInstrumented) 794GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_dlmalloc_instrumented, DlMallocInstrumented) 795 796GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc, RosAlloc) 797GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc, RosAlloc) 798GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc, RosAlloc) 799GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc, RosAlloc) 800GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc, RosAlloc) 801GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc, RosAlloc) 802GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc) 803GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc, RosAlloc) 804GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc, RosAlloc) 805 806GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_rosalloc_instrumented, RosAllocInstrumented) 807GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented) 808GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_rosalloc_instrumented, RosAllocInstrumented) 809GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented) 810GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented) 811GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_rosalloc_instrumented, RosAllocInstrumented) 812GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented) 813GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_rosalloc_instrumented, RosAllocInstrumented) 814GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_rosalloc_instrumented, RosAllocInstrumented) 815 816GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer, BumpPointer) 817GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer, BumpPointer) 818GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer, BumpPointer) 819GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer) 820GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer, BumpPointer) 821GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer, BumpPointer) 822GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer) 823GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer, BumpPointer) 824GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer, BumpPointer) 825 826GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_bump_pointer_instrumented, BumpPointerInstrumented) 827GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented) 828GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_bump_pointer_instrumented, BumpPointerInstrumented) 829GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented) 830GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented) 831GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_bump_pointer_instrumented, BumpPointerInstrumented) 832GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented) 833GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_bump_pointer_instrumented, BumpPointerInstrumented) 834GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_bump_pointer_instrumented, BumpPointerInstrumented) 835 836GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab, TLAB) 837GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab, TLAB) 838GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab, TLAB) 839GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB) 840GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab, TLAB) 841GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB) 842GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB) 843GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab, TLAB) 844GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB) 845 846GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT(_tlab_instrumented, TLABInstrumented) 847GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab_instrumented, TLABInstrumented) 848GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab_instrumented, TLABInstrumented) 849GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented) 850GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented) 851GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab_instrumented, TLABInstrumented) 852GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented) 853GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY(_tlab_instrumented, TLABInstrumented) 854GENERATE_ALLOC_ENTRYPOINTS_CHECK_AND_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab_instrumented, TLABInstrumented) 855 856TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_RESULT_IS_NON_ZERO 857TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_RESULT_IS_NON_ZERO 858TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO 859TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO 860 861TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO 862 863DEFINE_FUNCTION art_quick_lock_object 864 testl %edi, %edi // Null check object/rdi. 865 jz .Lslow_lock 866.Lretry_lock: 867 movl LOCK_WORD_OFFSET(%edi), %ecx // ecx := lock word. 868 test LITERAL(0xC0000000), %ecx // Test the 2 high bits. 869 jne .Lslow_lock // Slow path if either of the two high bits are set. 870 movl %gs:THREAD_ID_OFFSET, %edx // edx := thread id 871 test %ecx, %ecx 872 jnz .Lalready_thin // Lock word contains a thin lock. 873 // unlocked case - %edx holds thread id with count of 0 874 xor %eax, %eax // eax == 0 for comparison with lock word in cmpxchg 875 lock cmpxchg %edx, LOCK_WORD_OFFSET(%edi) 876 jnz .Lretry_lock // cmpxchg failed retry 877 ret 878.Lalready_thin: 879 cmpw %cx, %dx // do we hold the lock already? 880 jne .Lslow_lock 881 addl LITERAL(65536), %ecx // increment recursion count 882 test LITERAL(0xC0000000), %ecx // overflowed if either of top two bits are set 883 jne .Lslow_lock // count overflowed so go slow 884 movl %ecx, LOCK_WORD_OFFSET(%edi) // update lockword, cmpxchg not necessary as we hold lock 885 ret 886.Lslow_lock: 887 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 888 movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current() 889 movq %rsp, %rdx // pass SP 890 call SYMBOL(artLockObjectFromCode) // artLockObjectFromCode(object, Thread*, SP) 891 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 892 RETURN_IF_EAX_ZERO 893END_FUNCTION art_quick_lock_object 894 895DEFINE_FUNCTION art_quick_unlock_object 896 testl %edi, %edi // null check object/edi 897 jz .Lslow_unlock 898 movl LOCK_WORD_OFFSET(%edi), %ecx // ecx := lock word 899 movl %gs:THREAD_ID_OFFSET, %edx // edx := thread id 900 test LITERAL(0xC0000000), %ecx 901 jnz .Lslow_unlock // lock word contains a monitor 902 cmpw %cx, %dx // does the thread id match? 903 jne .Lslow_unlock 904 cmpl LITERAL(65536), %ecx 905 jae .Lrecursive_thin_unlock 906 movl LITERAL(0), LOCK_WORD_OFFSET(%edi) 907 ret 908.Lrecursive_thin_unlock: 909 subl LITERAL(65536), %ecx 910 mov %ecx, LOCK_WORD_OFFSET(%edi) 911 ret 912.Lslow_unlock: 913 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 914 movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current() 915 movq %rsp, %rdx // pass SP 916 call SYMBOL(artUnlockObjectFromCode) // artUnlockObjectFromCode(object, Thread*, SP) 917 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 918 RETURN_IF_EAX_ZERO 919END_FUNCTION art_quick_unlock_object 920 921DEFINE_FUNCTION art_quick_check_cast 922 PUSH rdi // Save args for exc 923 PUSH rsi 924 SETUP_FP_CALLEE_SAVE_FRAME 925 call SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass) 926 testq %rax, %rax 927 jz 1f // jump forward if not assignable 928 RESTORE_FP_CALLEE_SAVE_FRAME 929 addq LITERAL(16), %rsp // pop arguments 930 CFI_ADJUST_CFA_OFFSET(-16) 931 932 ret 9331: 934 RESTORE_FP_CALLEE_SAVE_FRAME 935 POP rsi // Pop arguments 936 POP rdi 937 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 938 mov %rsp, %rcx // pass SP 939 mov %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() 940 call SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*, SP) 941 int3 // unreached 942END_FUNCTION art_quick_check_cast 943 944 945 /* 946 * Entry from managed code for array put operations of objects where the value being stored 947 * needs to be checked for compatibility. 948 * 949 * Currently all the parameters should fit into the 32b portions of the registers. Index always 950 * will. So we optimize for a tighter encoding. The 64b versions are in comments. 951 * 952 * rdi(edi) = array, rsi(esi) = index, rdx(edx) = value 953 */ 954DEFINE_FUNCTION art_quick_aput_obj_with_null_and_bound_check 955#if defined(__APPLE__) 956 int3 957 int3 958#else 959 testl %edi, %edi 960// testq %rdi, %rdi 961 jnz art_quick_aput_obj_with_bound_check 962 jmp art_quick_throw_null_pointer_exception 963#endif // __APPLE__ 964END_FUNCTION art_quick_aput_obj_with_null_and_bound_check 965 966 967DEFINE_FUNCTION art_quick_aput_obj_with_bound_check 968#if defined(__APPLE__) 969 int3 970 int3 971#else 972 movl ARRAY_LENGTH_OFFSET(%edi), %ecx 973// movl ARRAY_LENGTH_OFFSET(%rdi), %ecx // This zero-extends, so value(%rcx)=value(%ecx) 974 cmpl %ecx, %esi 975 jb art_quick_aput_obj 976 mov %esi, %edi 977// mov %rsi, %rdi 978 mov %ecx, %esi 979// mov %rcx, %rsi 980 jmp art_quick_throw_array_bounds 981#endif // __APPLE__ 982END_FUNCTION art_quick_aput_obj_with_bound_check 983 984 985DEFINE_FUNCTION art_quick_aput_obj 986 testl %edx, %edx // store of null 987// test %rdx, %rdx 988 jz .Ldo_aput_null 989 movl CLASS_OFFSET(%edi), %ecx 990// movq CLASS_OFFSET(%rdi), %rcx 991 movl CLASS_COMPONENT_TYPE_OFFSET(%ecx), %ecx 992// movq CLASS_COMPONENT_TYPE_OFFSET(%rcx), %rcx 993 cmpl CLASS_OFFSET(%edx), %ecx // value's type == array's component type - trivial assignability 994// cmpq CLASS_OFFSET(%rdx), %rcx 995 jne .Lcheck_assignability 996.Ldo_aput: 997 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4) 998// movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4) 999 movq %gs:THREAD_CARD_TABLE_OFFSET, %rdx 1000 shrl LITERAL(7), %edi 1001// shrl LITERAL(7), %rdi 1002 movb %dl, (%rdx, %rdi) // Note: this assumes that top 32b of %rdi are zero 1003 ret 1004.Ldo_aput_null: 1005 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4) 1006// movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4) 1007 ret 1008.Lcheck_assignability: 1009 // Save arguments. 1010 PUSH rdi 1011 PUSH rsi 1012 PUSH rdx 1013 subq LITERAL(8), %rsp // Alignment padding. 1014 CFI_ADJUST_CFA_OFFSET(8) 1015 SETUP_FP_CALLEE_SAVE_FRAME 1016 1017 // "Uncompress" = do nothing, as already zero-extended on load. 1018 movl CLASS_OFFSET(%edx), %esi // Pass arg2 = value's class. 1019 movq %rcx, %rdi // Pass arg1 = array's component type. 1020 1021 call SYMBOL(artIsAssignableFromCode) // (Class* a, Class* b) 1022 1023 // Exception? 1024 testq %rax, %rax 1025 jz .Lthrow_array_store_exception 1026 1027 RESTORE_FP_CALLEE_SAVE_FRAME 1028 // Restore arguments. 1029 addq LITERAL(8), %rsp 1030 CFI_ADJUST_CFA_OFFSET(-8) 1031 POP rdx 1032 POP rsi 1033 POP rdi 1034 1035 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%edi, %esi, 4) 1036// movq %rdx, OBJECT_ARRAY_DATA_OFFSET(%rdi, %rsi, 4) 1037 movq %gs:THREAD_CARD_TABLE_OFFSET, %rdx 1038 shrl LITERAL(7), %edi 1039// shrl LITERAL(7), %rdi 1040 movb %dl, (%rdx, %rdi) // Note: this assumes that top 32b of %rdi are zero 1041// movb %dl, (%rdx, %rdi) 1042 ret 1043.Lthrow_array_store_exception: 1044 RESTORE_FP_CALLEE_SAVE_FRAME 1045 // Restore arguments. 1046 addq LITERAL(8), %rsp 1047 CFI_ADJUST_CFA_OFFSET(-8) 1048 POP rdx 1049 POP rsi 1050 POP rdi 1051 1052 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // Save all registers as basis for long jump context. 1053 1054 // Outgoing argument set up. 1055 movq %rsp, %rcx // Pass arg 4 = SP. 1056 movq %rdx, %rsi // Pass arg 2 = value. 1057 movq %gs:THREAD_SELF_OFFSET, %rdx // Pass arg 3 = Thread::Current(). 1058 // Pass arg 1 = array. 1059 1060 call SYMBOL(artThrowArrayStoreException) // (array, value, Thread*, SP) 1061 int3 // unreached 1062END_FUNCTION art_quick_aput_obj 1063 1064// TODO: This is quite silly on X86_64 now. 1065DEFINE_FUNCTION art_quick_memcpy 1066 call PLT_SYMBOL(memcpy) // (void*, const void*, size_t) 1067 ret 1068END_FUNCTION art_quick_memcpy 1069 1070NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret 1071 1072UNIMPLEMENTED art_quick_ldiv 1073UNIMPLEMENTED art_quick_lmod 1074UNIMPLEMENTED art_quick_lmul 1075UNIMPLEMENTED art_quick_lshl 1076UNIMPLEMENTED art_quick_lshr 1077UNIMPLEMENTED art_quick_lushr 1078 1079THREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCode, RETURN_IF_EAX_ZERO 1080THREE_ARG_DOWNCALL art_quick_set64_instance, artSet64InstanceFromCode, RETURN_IF_EAX_ZERO 1081THREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCode, RETURN_IF_EAX_ZERO 1082 1083TWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1084TWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1085TWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1086 1087TWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCode, RETURN_IF_EAX_ZERO 1088TWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCode, RETURN_IF_EAX_ZERO 1089 1090ONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1091ONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1092ONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1093 1094// This is singled out as the argument order is different. 1095DEFINE_FUNCTION art_quick_set64_static 1096 movq %rsi, %rdx // pass new_val 1097 movl 8(%rsp), %esi // pass referrer 1098 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 1099 // field_idx is in rdi 1100 movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current() 1101 movq %rsp, %r8 // pass SP 1102 call SYMBOL(artSet64StaticFromCode) // (field_idx, referrer, new_val, Thread*, SP) 1103 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 1104 RETURN_IF_EAX_ZERO // return or deliver exception 1105END_FUNCTION art_quick_set64_static 1106 1107 1108DEFINE_FUNCTION art_quick_proxy_invoke_handler 1109 // Save callee and GPR args, mixed together to agree with core spills bitmap of ref. and args 1110 // callee save frame. 1111 PUSH r15 // Callee save. 1112 PUSH r14 // Callee save. 1113 PUSH r13 // Callee save. 1114 PUSH r12 // Callee save. 1115 PUSH r9 // Quick arg 5. 1116 PUSH r8 // Quick arg 4. 1117 PUSH rsi // Quick arg 1. 1118 PUSH rbp // Callee save. 1119 PUSH rbx // Callee save. 1120 PUSH rdx // Quick arg 2. 1121 PUSH rcx // Quick arg 3. 1122 // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*. 1123 subq LITERAL(80 + 4*8), %rsp 1124 CFI_ADJUST_CFA_OFFSET(80 + 4*8) 1125 // Save FPRs. 1126 movq %xmm0, 16(%rsp) 1127 movq %xmm1, 24(%rsp) 1128 movq %xmm2, 32(%rsp) 1129 movq %xmm3, 40(%rsp) 1130 movq %xmm4, 48(%rsp) 1131 movq %xmm5, 56(%rsp) 1132 movq %xmm6, 64(%rsp) 1133 movq %xmm7, 72(%rsp) 1134 movq %xmm12, 80(%rsp) 1135 movq %xmm13, 88(%rsp) 1136 movq %xmm14, 96(%rsp) 1137 movq %xmm15, 104(%rsp) 1138 // Store proxy method to bottom of stack. 1139 movq %rdi, 0(%rsp) 1140 movq %gs:THREAD_SELF_OFFSET, %rdx // Pass Thread::Current(). 1141 movq %rsp, %rcx // Pass SP. 1142 call SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP) 1143 movq %rax, %xmm0 // Copy return value in case of float returns. 1144 addq LITERAL(168 + 4*8), %rsp // Pop arguments. 1145 CFI_ADJUST_CFA_OFFSET(-168 - 4*8) 1146 RETURN_OR_DELIVER_PENDING_EXCEPTION 1147END_FUNCTION art_quick_proxy_invoke_handler 1148 1149 /* 1150 * Called to resolve an imt conflict. 1151 * rax is a hidden argument that holds the target method's dex method index. 1152 */ 1153DEFINE_FUNCTION art_quick_imt_conflict_trampoline 1154#if defined(__APPLE__) 1155 int3 1156 int3 1157#else 1158 movl 8(%rsp), %edi // load caller Method* 1159 movl METHOD_DEX_CACHE_METHODS_OFFSET(%rdi), %edi // load dex_cache_resolved_methods 1160 movl OBJECT_ARRAY_DATA_OFFSET(%rdi, %rax, 4), %edi // load the target method 1161 jmp art_quick_invoke_interface_trampoline 1162#endif // __APPLE__ 1163END_FUNCTION art_quick_imt_conflict_trampoline 1164 1165DEFINE_FUNCTION art_quick_resolution_trampoline 1166 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1167 movq %gs:THREAD_SELF_OFFSET, %rdx 1168 movq %rsp, %rcx 1169 call SYMBOL(artQuickResolutionTrampoline) // (called, receiver, Thread*, SP) 1170 movq %rax, %r10 // Remember returned code pointer in R10. 1171 movq (%rsp), %rdi // Load called method into RDI. 1172 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1173 testq %r10, %r10 // If code pointer is NULL goto deliver pending exception. 1174 jz 1f 1175 jmp *%r10 // Tail call into method. 11761: 1177 DELIVER_PENDING_EXCEPTION 1178END_FUNCTION art_quick_resolution_trampoline 1179 1180/* Generic JNI frame layout: 1181 * 1182 * #-------------------# 1183 * | | 1184 * | caller method... | 1185 * #-------------------# <--- SP on entry 1186 * 1187 * | 1188 * V 1189 * 1190 * #-------------------# 1191 * | caller method... | 1192 * #-------------------# 1193 * | Return | 1194 * | R15 | callee save 1195 * | R14 | callee save 1196 * | R13 | callee save 1197 * | R12 | callee save 1198 * | R9 | arg5 1199 * | R8 | arg4 1200 * | RSI/R6 | arg1 1201 * | RBP/R5 | callee save 1202 * | RBX/R3 | callee save 1203 * | RDX/R2 | arg2 1204 * | RCX/R1 | arg3 1205 * | XMM7 | float arg 8 1206 * | XMM6 | float arg 7 1207 * | XMM5 | float arg 6 1208 * | XMM4 | float arg 5 1209 * | XMM3 | float arg 4 1210 * | XMM2 | float arg 3 1211 * | XMM1 | float arg 2 1212 * | XMM0 | float arg 1 1213 * | Padding | 1214 * | RDI/Method* | <- sp 1215 * #-------------------# 1216 * | Scratch Alloca | 5K scratch space 1217 * #---------#---------# 1218 * | | sp* | 1219 * | Tramp. #---------# 1220 * | args | thread | 1221 * | Tramp. #---------# 1222 * | | method | 1223 * #-------------------# <--- SP on artQuickGenericJniTrampoline 1224 * 1225 * | 1226 * v artQuickGenericJniTrampoline 1227 * 1228 * #-------------------# 1229 * | caller method... | 1230 * #-------------------# 1231 * | Return | 1232 * | Callee-Save Data | 1233 * #-------------------# 1234 * | handle scope | 1235 * #-------------------# 1236 * | Method* | <--- (1) 1237 * #-------------------# 1238 * | local ref cookie | // 4B 1239 * | handle scope size | // 4B TODO: roll into call stack alignment? 1240 * #-------------------# 1241 * | JNI Call Stack | 1242 * #-------------------# <--- SP on native call 1243 * | | 1244 * | Stack for Regs | The trampoline assembly will pop these values 1245 * | | into registers for native call 1246 * #-------------------# 1247 * | Native code ptr | 1248 * #-------------------# 1249 * | Free scratch | 1250 * #-------------------# 1251 * | Ptr to (1) | <--- RSP 1252 * #-------------------# 1253 */ 1254 /* 1255 * Called to do a generic JNI down-call 1256 */ 1257DEFINE_FUNCTION_NO_HIDE art_quick_generic_jni_trampoline 1258 // Save callee and GPR args, mixed together to agree with core spills bitmap. 1259 PUSH r15 // Callee save. 1260 PUSH r14 // Callee save. 1261 PUSH r13 // Callee save. 1262 PUSH r12 // Callee save. 1263 PUSH r9 // Quick arg 5. 1264 PUSH r8 // Quick arg 4. 1265 PUSH rsi // Quick arg 1. 1266 PUSH rbp // Callee save. 1267 PUSH rbx // Callee save. 1268 PUSH rdx // Quick arg 2. 1269 PUSH rcx // Quick arg 3. 1270 // Create space for FPR args and create 2 slots, 1 of padding and 1 for the ArtMethod*. 1271 subq LITERAL(80 + 4*8), %rsp 1272 CFI_ADJUST_CFA_OFFSET(80 + 4*8) 1273 // Save FPRs. 1274 movq %xmm0, 16(%rsp) 1275 movq %xmm1, 24(%rsp) 1276 movq %xmm2, 32(%rsp) 1277 movq %xmm3, 40(%rsp) 1278 movq %xmm4, 48(%rsp) 1279 movq %xmm5, 56(%rsp) 1280 movq %xmm6, 64(%rsp) 1281 movq %xmm7, 72(%rsp) 1282 movq %xmm12, 80(%rsp) 1283 movq %xmm13, 88(%rsp) 1284 movq %xmm14, 96(%rsp) 1285 movq %xmm15, 104(%rsp) 1286 movq %rdi, 0(%rsp) // Store native ArtMethod* to bottom of stack. 1287 movq %rsp, %rbp // save SP at (old) callee-save frame 1288 CFI_DEF_CFA_REGISTER(rbp) 1289 // 1290 // reserve a lot of space 1291 // 1292 // 4 local state ref 1293 // 4 padding 1294 // 4196 4k scratch space, enough for 2x 256 8-byte parameters (TODO: handle scope overhead?) 1295 // 16 handle scope member fields ? 1296 // + 112 14x 8-byte stack-2-register space 1297 // ------ 1298 // 4332 1299 // 16-byte aligned: 4336 1300 // Note: 14x8 = 7*16, so the stack stays aligned for the native call... 1301 // Also means: the padding is somewhere in the middle 1302 // 1303 // 1304 // New test: use 5K and release 1305 // 5k = 5120 1306 subq LITERAL(5120), %rsp 1307 // prepare for artQuickGenericJniTrampoline call 1308 // (Thread*, SP) 1309 // rdi rsi <= C calling convention 1310 // gs:... rbp <= where they are 1311 movq %gs:THREAD_SELF_OFFSET, %rdi 1312 movq %rbp, %rsi 1313 call SYMBOL(artQuickGenericJniTrampoline) // (Thread*, sp) 1314 1315 // The C call will have registered the complete save-frame on success. 1316 // The result of the call is: 1317 // %rax: pointer to native code, 0 on error. 1318 // %rdx: pointer to the bottom of the used area of the alloca, can restore stack till there. 1319 1320 // Check for error = 0. 1321 test %rax, %rax 1322 jz .Lentry_error 1323 1324 // Release part of the alloca. 1325 movq %rdx, %rsp 1326 1327 // pop from the register-passing alloca region 1328 // what's the right layout? 1329 popq %rdi 1330 popq %rsi 1331 popq %rdx 1332 popq %rcx 1333 popq %r8 1334 popq %r9 1335 // TODO: skip floating point if unused, some flag. 1336 movq 0(%rsp), %xmm0 1337 movq 8(%rsp), %xmm1 1338 movq 16(%rsp), %xmm2 1339 movq 24(%rsp), %xmm3 1340 movq 32(%rsp), %xmm4 1341 movq 40(%rsp), %xmm5 1342 movq 48(%rsp), %xmm6 1343 movq 56(%rsp), %xmm7 1344 addq LITERAL(64), %rsp // floating-point done 1345 1346 // native call 1347 call *%rax 1348 1349 // result sign extension is handled in C code 1350 // prepare for artQuickGenericJniEndTrampoline call 1351 // (Thread*, result, result_f) 1352 // rdi rsi rdx <= C calling convention 1353 // gs:... rax xmm0 <= where they are 1354 movq %gs:THREAD_SELF_OFFSET, %rdi 1355 movq %rax, %rsi 1356 movq %xmm0, %rdx 1357 call SYMBOL(artQuickGenericJniEndTrampoline) 1358 1359 // Tear down the alloca. 1360 movq %rbp, %rsp 1361 CFI_DEF_CFA_REGISTER(rsp) 1362 1363 // Pending exceptions possible. 1364 // TODO: use cmpq, needs direct encoding because of gas bug 1365 movq %gs:THREAD_EXCEPTION_OFFSET, %rcx 1366 test %rcx, %rcx 1367 jnz .Lexception_in_native 1368 1369 // Tear down the callee-save frame. 1370 // Load FPRs. 1371 // movq %xmm0, 16(%rsp) // doesn't make sense!!! 1372 movq 24(%rsp), %xmm1 // neither does this!!! 1373 movq 32(%rsp), %xmm2 1374 movq 40(%rsp), %xmm3 1375 movq 48(%rsp), %xmm4 1376 movq 56(%rsp), %xmm5 1377 movq 64(%rsp), %xmm6 1378 movq 72(%rsp), %xmm7 1379 movq 80(%rsp), %xmm12 1380 movq 88(%rsp), %xmm13 1381 movq 96(%rsp), %xmm14 1382 movq 104(%rsp), %xmm15 1383 // was 80 bytes 1384 addq LITERAL(80 + 4*8), %rsp 1385 CFI_ADJUST_CFA_OFFSET(-80 - 4*8) 1386 // Save callee and GPR args, mixed together to agree with core spills bitmap. 1387 POP rcx // Arg. 1388 POP rdx // Arg. 1389 POP rbx // Callee save. 1390 POP rbp // Callee save. 1391 POP rsi // Arg. 1392 POP r8 // Arg. 1393 POP r9 // Arg. 1394 POP r12 // Callee save. 1395 POP r13 // Callee save. 1396 POP r14 // Callee save. 1397 POP r15 // Callee save. 1398 // store into fpr, for when it's a fpr return... 1399 movq %rax, %xmm0 1400 ret 1401.Lentry_error: 1402 movq %rbp, %rsp 1403 CFI_DEF_CFA_REGISTER(rsp) 1404.Lexception_in_native: 1405 // TODO: the handle scope contains the this pointer which is used by the debugger for exception 1406 // delivery. 1407 movq %xmm0, 16(%rsp) // doesn't make sense!!! 1408 movq 24(%rsp), %xmm1 // neither does this!!! 1409 movq 32(%rsp), %xmm2 1410 movq 40(%rsp), %xmm3 1411 movq 48(%rsp), %xmm4 1412 movq 56(%rsp), %xmm5 1413 movq 64(%rsp), %xmm6 1414 movq 72(%rsp), %xmm7 1415 movq 80(%rsp), %xmm12 1416 movq 88(%rsp), %xmm13 1417 movq 96(%rsp), %xmm14 1418 movq 104(%rsp), %xmm15 1419 // was 80 + 32 bytes 1420 addq LITERAL(80 + 4*8), %rsp 1421 CFI_ADJUST_CFA_OFFSET(-80 - 4*8) 1422 // Save callee and GPR args, mixed together to agree with core spills bitmap. 1423 POP rcx // Arg. 1424 POP rdx // Arg. 1425 POP rbx // Callee save. 1426 POP rbp // Callee save. 1427 POP rsi // Arg. 1428 POP r8 // Arg. 1429 POP r9 // Arg. 1430 POP r12 // Callee save. 1431 POP r13 // Callee save. 1432 POP r14 // Callee save. 1433 POP r15 // Callee save. 1434 1435 DELIVER_PENDING_EXCEPTION 1436END_FUNCTION art_quick_generic_jni_trampoline 1437 1438 /* 1439 * Called to bridge from the quick to interpreter ABI. On entry the arguments match those 1440 * of a quick call: 1441 * RDI = method being called / to bridge to. 1442 * RSI, RDX, RCX, R8, R9 are arguments to that method. 1443 */ 1444DEFINE_FUNCTION_NO_HIDE art_quick_to_interpreter_bridge 1445 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // Set up frame and save arguments. 1446 movq %gs:THREAD_SELF_OFFSET, %rsi // RSI := Thread::Current() 1447 movq %rsp, %rdx // RDX := sp 1448 call SYMBOL(artQuickToInterpreterBridge) // (method, Thread*, SP) 1449 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME // TODO: no need to restore arguments in this case. 1450 movq %rax, %xmm0 // Place return value also into floating point return value. 1451 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1452END_FUNCTION art_quick_to_interpreter_bridge 1453 1454 /* 1455 * Routine that intercepts method calls and returns. 1456 */ 1457DEFINE_FUNCTION art_quick_instrumentation_entry 1458#if defined(__APPLE__) 1459 int3 1460 int3 1461#else 1462 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1463 1464 movq %rdi, %r12 // Preserve method pointer in a callee-save. 1465 1466 movq %gs:THREAD_SELF_OFFSET, %rdx // Pass thread. 1467 movq %rsp, %rcx // Pass SP. 1468 movq FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE-8(%rsp), %r8 // Pass return PC. 1469 1470 call SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Object*, Thread*, SP, LR) 1471 1472 // %rax = result of call. 1473 movq %r12, %rdi // Reload method pointer. 1474 1475 leaq art_quick_instrumentation_exit(%rip), %r12 // Set up return through instrumentation 1476 movq %r12, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE-8(%rsp) // exit. 1477 1478 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1479 1480 jmp *%rax // Tail call to intended method. 1481#endif // __APPLE__ 1482END_FUNCTION art_quick_instrumentation_entry 1483 1484DEFINE_FUNCTION art_quick_instrumentation_exit 1485 pushq LITERAL(0) // Push a fake return PC as there will be none on the stack. 1486 1487 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 1488 1489 // We need to save rax and xmm0. We could use a callee-save from SETUP_REF_ONLY, but then 1490 // we would need to fully restore it. As there are a good number of callee-save registers, it 1491 // seems easier to have an extra small stack area. But this should be revisited. 1492 1493 movq %rsp, %rsi // Pass SP. 1494 1495 PUSH rax // Save integer result. 1496 subq LITERAL(8), %rsp // Save floating-point result. 1497 CFI_ADJUST_CFA_OFFSET(8) 1498 movq %xmm0, (%rsp) 1499 1500 movq %gs:THREAD_SELF_OFFSET, %rdi // Pass Thread. 1501 movq %rax, %rdx // Pass integer result. 1502 movq %xmm0, %rcx // Pass floating-point result. 1503 1504 call SYMBOL(artInstrumentationMethodExitFromCode) // (Thread*, SP, gpr_res, fpr_res) 1505 1506 movq %rax, %rdi // Store return PC 1507 movq %rdx, %rsi // Store second return PC in hidden arg. 1508 1509 movq (%rsp), %xmm0 // Restore floating-point result. 1510 addq LITERAL(8), %rsp 1511 CFI_ADJUST_CFA_OFFSET(-8) 1512 POP rax // Restore integer result. 1513 1514 addq LITERAL(FRAME_SIZE_REFS_ONLY_CALLEE_SAVE), %rsp // Drop save frame and fake return pc. 1515 1516 jmp *%rdi // Return. 1517END_FUNCTION art_quick_instrumentation_exit 1518 1519 /* 1520 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization 1521 * will long jump to the upcall with a special exception of -1. 1522 */ 1523DEFINE_FUNCTION art_quick_deoptimize 1524 pushq %rsi // Fake that we were called. Use hidden arg. 1525 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 1526 // Stack should be aligned now. 1527 movq %rsp, %rsi // Pass SP. 1528 movq %gs:THREAD_SELF_OFFSET, %rdi // Pass Thread. 1529 call SYMBOL(artDeoptimize) // artDeoptimize(Thread*, SP) 1530 int3 // Unreachable. 1531END_FUNCTION art_quick_deoptimize 1532 1533 1534 /* 1535 * String's compareTo. 1536 * 1537 * On entry: 1538 * rdi: this string object (known non-null) 1539 * rsi: comp string object (known non-null) 1540 */ 1541DEFINE_FUNCTION art_quick_string_compareto 1542 movl STRING_COUNT_OFFSET(%edi), %r8d 1543 movl STRING_COUNT_OFFSET(%esi), %r9d 1544 movl STRING_VALUE_OFFSET(%edi), %r10d 1545 movl STRING_VALUE_OFFSET(%esi), %r11d 1546 movl STRING_OFFSET_OFFSET(%edi), %eax 1547 movl STRING_OFFSET_OFFSET(%esi), %ecx 1548 /* Build pointers to the start of string data */ 1549 leal STRING_DATA_OFFSET(%r10d, %eax, 2), %esi 1550 leal STRING_DATA_OFFSET(%r11d, %ecx, 2), %edi 1551 /* Calculate min length and count diff */ 1552 movl %r8d, %ecx 1553 movl %r8d, %eax 1554 subl %r9d, %eax 1555 cmovg %r9d, %ecx 1556 /* 1557 * At this point we have: 1558 * eax: value to return if first part of strings are equal 1559 * ecx: minimum among the lengths of the two strings 1560 * esi: pointer to this string data 1561 * edi: pointer to comp string data 1562 */ 1563 jecxz .Lkeep_length 1564 repe cmpsw // find nonmatching chars in [%esi] and [%edi], up to length %ecx 1565 jne .Lnot_equal 1566.Lkeep_length: 1567 ret 1568 .balign 16 1569.Lnot_equal: 1570 movzwl -2(%esi), %eax // get last compared char from this string 1571 movzwl -2(%edi), %ecx // get last compared char from comp string 1572 subl %ecx, %eax // return the difference 1573 ret 1574END_FUNCTION art_quick_string_compareto 1575 1576UNIMPLEMENTED art_quick_memcmp16 1577 1578DEFINE_FUNCTION art_quick_assignable_from_code 1579 SETUP_FP_CALLEE_SAVE_FRAME 1580 call SYMBOL(artIsAssignableFromCode) // (const mirror::Class*, const mirror::Class*) 1581 RESTORE_FP_CALLEE_SAVE_FRAME 1582 ret 1583END_FUNCTION art_quick_assignable_from_code 1584 1585 1586// Return from a nested signal: 1587// Entry: 1588// rdi: address of jmp_buf in TLS 1589 1590DEFINE_FUNCTION art_nested_signal_return 1591 // first arg to longjmp is already in correct register 1592 movq LITERAL(1), %rsi // second arg to longjmp (1) 1593 call PLT_SYMBOL(longjmp) 1594 int3 // won't get here 1595END_FUNCTION art_nested_signal_return 1596 1597 1598