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.S" 18#include "interpreter/cfi_asm_support.h" 19 20#include "arch/quick_alloc_entrypoints.S" 21 22// For x86, the CFA is esp+4, the address above the pushed return address on the stack. 23 24 /* 25 * Macro that sets up the callee save frame to conform with 26 * Runtime::CreateCalleeSaveMethod(kSaveAllCalleeSaves) 27 */ 28MACRO2(SETUP_SAVE_ALL_CALLEE_SAVES_FRAME, got_reg, temp_reg) 29 PUSH edi // Save callee saves (ebx is saved/restored by the upcall) 30 PUSH esi 31 PUSH ebp 32 subl MACRO_LITERAL(12), %esp // Grow stack by 3 words. 33 CFI_ADJUST_CFA_OFFSET(12) 34 LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg 35 // Push save all callee-save method. 36 pushl RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET(REG_VAR(temp_reg)) 37 CFI_ADJUST_CFA_OFFSET(4) 38 // Store esp as the top quick frame. 39 movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET 40 // Ugly compile-time check, but we only have the preprocessor. 41 // Last +4: implicit return address pushed on stack when caller made call. 42#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 3*4 + 16 + 4) 43#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(X86) size not as expected." 44#endif 45END_MACRO 46 47 /* 48 * Macro that sets up the callee save frame to conform with 49 * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly) 50 */ 51MACRO2(SETUP_SAVE_REFS_ONLY_FRAME, got_reg, temp_reg) 52 PUSH edi // Save callee saves (ebx is saved/restored by the upcall) 53 PUSH esi 54 PUSH ebp 55 subl MACRO_LITERAL(12), %esp // Grow stack by 3 words. 56 CFI_ADJUST_CFA_OFFSET(12) 57 LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg 58 // Push save all callee-save method. 59 pushl RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET(REG_VAR(temp_reg)) 60 CFI_ADJUST_CFA_OFFSET(4) 61 // Store esp as the top quick frame. 62 movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET 63 64 // Ugly compile-time check, but we only have the preprocessor. 65 // Last +4: implicit return address pushed on stack when caller made call. 66#if (FRAME_SIZE_SAVE_REFS_ONLY != 3*4 + 16 + 4) 67#error "FRAME_SIZE_SAVE_REFS_ONLY(X86) size not as expected." 68#endif 69END_MACRO 70 71 /* 72 * Macro that sets up the callee save frame to conform with 73 * Runtime::CreateCalleeSaveMethod(kSaveRefsOnly) 74 * and preserves the value of got_reg at entry. 75 */ 76MACRO2(SETUP_SAVE_REFS_ONLY_FRAME_PRESERVE_GOT_REG, got_reg, temp_reg) 77 PUSH edi // Save callee saves (ebx is saved/restored by the upcall) 78 PUSH esi 79 PUSH ebp 80 PUSH RAW_VAR(got_reg) // Save got_reg 81 subl MACRO_LITERAL(8), %esp // Grow stack by 2 words. 82 CFI_ADJUST_CFA_OFFSET(8) 83 84 LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg 85 // Push save all callee-save method. 86 pushl RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET(REG_VAR(temp_reg)) 87 CFI_ADJUST_CFA_OFFSET(4) 88 // Store esp as the top quick frame. 89 movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET 90 // Restore got_reg. 91 movl 12(%esp), REG_VAR(got_reg) 92 CFI_RESTORE(RAW_VAR(got_reg)) 93 94 // Ugly compile-time check, but we only have the preprocessor. 95 // Last +4: implicit return address pushed on stack when caller made call. 96#if (FRAME_SIZE_SAVE_REFS_ONLY != 3*4 + 16 + 4) 97#error "FRAME_SIZE_SAVE_REFS_ONLY(X86) size not as expected." 98#endif 99END_MACRO 100 101MACRO0(RESTORE_SAVE_REFS_ONLY_FRAME) 102 addl MACRO_LITERAL(16), %esp // Unwind stack up to saved values 103 CFI_ADJUST_CFA_OFFSET(-16) 104 POP ebp // Restore callee saves (ebx is saved/restored by the upcall) 105 POP esi 106 POP edi 107END_MACRO 108 109 /* 110 * Macro that sets up the callee save frame to conform with 111 * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs) 112 */ 113MACRO2(SETUP_SAVE_REFS_AND_ARGS_FRAME, got_reg, temp_reg) 114 SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY 115 116 LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg 117 // Push save all callee-save method. 118 pushl RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET(REG_VAR(temp_reg)) 119 CFI_ADJUST_CFA_OFFSET(4) 120 // Store esp as the stop quick frame. 121 movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET 122END_MACRO 123 124 /* 125 * Macro that sets up the callee save frame to conform with 126 * Runtime::CreateCalleeSaveMethod(kSaveRefsAndArgs) where the method is passed in EAX. 127 */ 128MACRO0(SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_EAX) 129 SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY 130 131 pushl %eax // Store the ArtMethod reference at the bottom of the stack. 132 CFI_ADJUST_CFA_OFFSET(4) 133 // Store esp as the stop quick frame. 134 movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET 135END_MACRO 136 137// Restore register and jump to routine 138// Inputs: EDI contains pointer to code. 139// Notes: Need to pop EAX too (restores Method*) 140MACRO0(RESTORE_SAVE_REFS_AND_ARGS_FRAME_AND_JUMP) 141 POP eax // Restore Method* 142 143 // Restore FPRs. 144 movsd 0(%esp), %xmm0 145 movsd 8(%esp), %xmm1 146 movsd 16(%esp), %xmm2 147 movsd 24(%esp), %xmm3 148 149 addl MACRO_LITERAL(32), %esp // Remove FPRs. 150 CFI_ADJUST_CFA_OFFSET(-32) 151 152 POP ecx // Restore args except eax 153 POP edx 154 POP ebx 155 POP ebp // Restore callee saves 156 POP esi 157 xchgl 0(%esp),%edi // restore EDI and place code pointer as only value on stack 158 ret 159END_MACRO 160 161 /* 162 * Macro that sets up the callee save frame to conform with 163 * Runtime::CreateCalleeSaveMethod(kSaveEverything) 164 * when EDI and ESI are already saved. 165 */ 166MACRO3(SETUP_SAVE_EVERYTHING_FRAME_EDI_ESI_SAVED, got_reg, temp_reg, runtime_method_offset = RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET) 167 // Save core registers from highest to lowest to agree with core spills bitmap. 168 // EDI and ESI, or at least placeholders for them, are already on the stack. 169 PUSH ebp 170 PUSH ebx 171 PUSH edx 172 PUSH ecx 173 PUSH eax 174 // Create space for FPR registers and stack alignment padding. 175 subl MACRO_LITERAL(12 + 8 * 8), %esp 176 CFI_ADJUST_CFA_OFFSET(12 + 8 * 8) 177 // Save FPRs. 178 movsd %xmm0, 12(%esp) 179 movsd %xmm1, 20(%esp) 180 movsd %xmm2, 28(%esp) 181 movsd %xmm3, 36(%esp) 182 movsd %xmm4, 44(%esp) 183 movsd %xmm5, 52(%esp) 184 movsd %xmm6, 60(%esp) 185 movsd %xmm7, 68(%esp) 186 187 LOAD_RUNTIME_INSTANCE \temp_reg, \got_reg 188 // Push save everything callee-save method. 189 pushl \runtime_method_offset(REG_VAR(temp_reg)) 190 CFI_ADJUST_CFA_OFFSET(4) 191 // Store esp as the stop quick frame. 192 movl %esp, %fs:THREAD_TOP_QUICK_FRAME_OFFSET 193 194 // Ugly compile-time check, but we only have the preprocessor. 195 // Last +4: implicit return address pushed on stack when caller made call. 196#if (FRAME_SIZE_SAVE_EVERYTHING != 7*4 + 8*8 + 12 + 4 + 4) 197#error "FRAME_SIZE_SAVE_EVERYTHING(X86) size not as expected." 198#endif 199END_MACRO 200 201 /* 202 * Macro that sets up the callee save frame to conform with 203 * Runtime::CreateCalleeSaveMethod(kSaveEverything) 204 * when EDI is already saved. 205 */ 206MACRO3(SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED, got_reg, temp_reg, runtime_method_offset = RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET) 207 // Save core registers from highest to lowest to agree with core spills bitmap. 208 // EDI, or at least a placeholder for it, is already on the stack. 209 PUSH esi 210 SETUP_SAVE_EVERYTHING_FRAME_EDI_ESI_SAVED RAW_VAR(got_reg), RAW_VAR(temp_reg), \runtime_method_offset 211END_MACRO 212 213 /* 214 * Macro that sets up the callee save frame to conform with 215 * Runtime::CreateCalleeSaveMethod(kSaveEverything) 216 */ 217MACRO3(SETUP_SAVE_EVERYTHING_FRAME, got_reg, temp_reg, runtime_method_offset = RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET) 218 PUSH edi 219 SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED RAW_VAR(got_reg), RAW_VAR(temp_reg), \runtime_method_offset 220END_MACRO 221 222MACRO0(RESTORE_SAVE_EVERYTHING_FRAME_FRPS) 223 // Restore FPRs. Method and padding is still on the stack. 224 movsd 16(%esp), %xmm0 225 movsd 24(%esp), %xmm1 226 movsd 32(%esp), %xmm2 227 movsd 40(%esp), %xmm3 228 movsd 48(%esp), %xmm4 229 movsd 56(%esp), %xmm5 230 movsd 64(%esp), %xmm6 231 movsd 72(%esp), %xmm7 232END_MACRO 233 234MACRO0(RESTORE_SAVE_EVERYTHING_FRAME_GPRS_EXCEPT_EAX) 235 // Restore core registers (except eax). 236 POP ecx 237 POP edx 238 POP ebx 239 POP ebp 240 POP esi 241 POP edi 242END_MACRO 243 244MACRO0(RESTORE_SAVE_EVERYTHING_FRAME) 245 RESTORE_SAVE_EVERYTHING_FRAME_FRPS 246 247 // Remove save everything callee save method, stack alignment padding and FPRs. 248 addl MACRO_LITERAL(16 + 8 * 8), %esp 249 CFI_ADJUST_CFA_OFFSET(-(16 + 8 * 8)) 250 251 POP eax 252 RESTORE_SAVE_EVERYTHING_FRAME_GPRS_EXCEPT_EAX 253END_MACRO 254 255MACRO0(RESTORE_SAVE_EVERYTHING_FRAME_KEEP_EAX) 256 RESTORE_SAVE_EVERYTHING_FRAME_FRPS 257 258 // Remove save everything callee save method, stack alignment padding and FPRs, skip EAX. 259 addl MACRO_LITERAL(16 + 8 * 8 + 4), %esp 260 CFI_ADJUST_CFA_OFFSET(-(16 + 8 * 8 + 4)) 261 262 RESTORE_SAVE_EVERYTHING_FRAME_GPRS_EXCEPT_EAX 263END_MACRO 264 265 /* 266 * Macro that calls through to artDeliverPendingExceptionFromCode, where the pending 267 * exception is Thread::Current()->exception_. 268 */ 269MACRO0(DELIVER_PENDING_EXCEPTION) 270 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save callee saves for throw 271 DELIVER_PENDING_EXCEPTION_FRAME_READY 272END_MACRO 273 274MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 275 DEFINE_FUNCTION VAR(c_name) 276 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save all registers as basis for long jump context 277 // Outgoing argument set up 278 subl MACRO_LITERAL(12), %esp // alignment padding 279 CFI_ADJUST_CFA_OFFSET(12) 280 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 281 CFI_ADJUST_CFA_OFFSET(4) 282 call CALLVAR(cxx_name) // cxx_name(Thread*) 283 UNREACHABLE 284 END_FUNCTION VAR(c_name) 285END_MACRO 286 287MACRO2(NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING, c_name, cxx_name) 288 DEFINE_FUNCTION VAR(c_name) 289 SETUP_SAVE_EVERYTHING_FRAME ebx, ebx // save all registers as basis for long jump context 290 // Outgoing argument set up 291 subl MACRO_LITERAL(12), %esp // alignment padding 292 CFI_ADJUST_CFA_OFFSET(12) 293 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 294 CFI_ADJUST_CFA_OFFSET(4) 295 call CALLVAR(cxx_name) // cxx_name(Thread*) 296 UNREACHABLE 297 END_FUNCTION VAR(c_name) 298END_MACRO 299 300MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 301 DEFINE_FUNCTION VAR(c_name) 302 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save all registers as basis for long jump context 303 // Outgoing argument set up 304 subl MACRO_LITERAL(8), %esp // alignment padding 305 CFI_ADJUST_CFA_OFFSET(8) 306 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 307 CFI_ADJUST_CFA_OFFSET(4) 308 PUSH eax // pass arg1 309 call CALLVAR(cxx_name) // cxx_name(arg1, Thread*) 310 UNREACHABLE 311 END_FUNCTION VAR(c_name) 312END_MACRO 313 314MACRO2(TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING, c_name, cxx_name) 315 DEFINE_FUNCTION VAR(c_name) 316 SETUP_SAVE_EVERYTHING_FRAME ebx, ebx // save all registers as basis for long jump context 317 // Outgoing argument set up 318 PUSH eax // alignment padding 319 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 320 CFI_ADJUST_CFA_OFFSET(4) 321 PUSH ecx // pass arg2 322 PUSH eax // pass arg1 323 call CALLVAR(cxx_name) // cxx_name(arg1, arg2, Thread*) 324 UNREACHABLE 325 END_FUNCTION VAR(c_name) 326END_MACRO 327 328 /* 329 * Called by managed code to create and deliver a NullPointerException. 330 */ 331NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode 332 333 /* 334 * Call installed by a signal handler to create and deliver a NullPointerException. 335 */ 336DEFINE_FUNCTION_CUSTOM_CFA art_quick_throw_null_pointer_exception_from_signal, 2 * __SIZEOF_POINTER__ 337 // Fault address and return address were saved by the fault handler. 338 // Save all registers as basis for long jump context; EDI will replace fault address later. 339 SETUP_SAVE_EVERYTHING_FRAME_EDI_SAVED ebx, ebx 340 // Retrieve fault address and save EDI. 341 movl (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%esp), %eax 342 movl %edi, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)(%esp) 343 CFI_REL_OFFSET(%edi, (FRAME_SIZE_SAVE_EVERYTHING - 2 * __SIZEOF_POINTER__)) 344 // Outgoing argument set up 345 subl MACRO_LITERAL(8), %esp // alignment padding 346 CFI_ADJUST_CFA_OFFSET(8) 347 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 348 CFI_ADJUST_CFA_OFFSET(4) 349 PUSH eax // pass arg1 350 call SYMBOL(artThrowNullPointerExceptionFromSignal) // (addr, self) 351 UNREACHABLE 352END_FUNCTION art_quick_throw_null_pointer_exception 353 354 /* 355 * Called by managed code to create and deliver an ArithmeticException. 356 */ 357NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_div_zero, artThrowDivZeroFromCode 358 359 /* 360 * Called by managed code to create and deliver a StackOverflowError. 361 */ 362NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode 363 364 /* 365 * Called by managed code, saves callee saves and then calls artThrowException 366 * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception. 367 */ 368ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode 369 370 /* 371 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds 372 * index, arg2 holds limit. 373 */ 374TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_array_bounds, artThrowArrayBoundsFromCode 375 376 /* 377 * Called by managed code to create and deliver a StringIndexOutOfBoundsException 378 * as if thrown from a call to String.charAt(). Arg1 holds index, arg2 holds limit. 379 */ 380TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_string_bounds, artThrowStringBoundsFromCode 381 382 /* 383 * All generated callsites for interface invokes and invocation slow paths will load arguments 384 * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain 385 * the method_idx. This wrapper will save arg1-arg3 and call the appropriate C helper. 386 * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1. 387 * 388 * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting 389 * of the target Method* in r0 and method->code_ in r1. 390 * 391 * If unsuccessful, the helper will return null/null and there will be a pending exception in the 392 * thread and we branch to another stub to deliver it. 393 * 394 * On success this wrapper will restore arguments and *jump* to the target, leaving the lr 395 * pointing back to the original caller. 396 */ 397MACRO1(INVOKE_TRAMPOLINE_BODY, cxx_name) 398 SETUP_SAVE_REFS_AND_ARGS_FRAME ebx, ebx 399 movl %esp, %edx // remember SP 400 401 // Outgoing argument set up 402 PUSH edx // pass SP 403 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 404 CFI_ADJUST_CFA_OFFSET(4) 405 PUSH ecx // pass arg2 406 PUSH eax // pass arg1 407 call CALLVAR(cxx_name) // cxx_name(arg1, arg2, Thread*, SP) 408 movl %edx, %edi // save code pointer in EDI 409 addl MACRO_LITERAL(20), %esp // Pop arguments skip eax 410 CFI_ADJUST_CFA_OFFSET(-20) 411 412 // Restore FPRs. 413 movsd 0(%esp), %xmm0 414 movsd 8(%esp), %xmm1 415 movsd 16(%esp), %xmm2 416 movsd 24(%esp), %xmm3 417 418 // Remove space for FPR args. 419 addl MACRO_LITERAL(4 * 8), %esp 420 CFI_ADJUST_CFA_OFFSET(-4 * 8) 421 422 POP ecx // Restore args except eax 423 POP edx 424 POP ebx 425 POP ebp // Restore callee saves 426 POP esi 427 // Swap EDI callee save with code pointer. 428 xchgl %edi, (%esp) 429 testl %eax, %eax // Branch forward if exception pending. 430 jz 1f 431 // Tail call to intended method. 432 ret 4331: 434 addl MACRO_LITERAL(4), %esp // Pop code pointer off stack 435 CFI_ADJUST_CFA_OFFSET(-4) 436 DELIVER_PENDING_EXCEPTION 437END_MACRO 438MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name) 439 DEFINE_FUNCTION VAR(c_name) 440 INVOKE_TRAMPOLINE_BODY RAW_VAR(cxx_name) 441 END_FUNCTION VAR(c_name) 442END_MACRO 443 444INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck 445 446INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck 447INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck 448INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck 449INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck 450 451 /* 452 * Helper for quick invocation stub to set up XMM registers. 453 * Increments shorty and arg_array and clobbers temp_char. 454 * Branches to finished if it encounters the end of the shorty. 455 */ 456MACRO5(LOOP_OVER_SHORTY_LOADING_XMMS, xmm_reg, shorty, arg_array, temp_char, finished) 4571: // LOOP 458 movb (REG_VAR(shorty)), REG_VAR(temp_char) // temp_char := *shorty 459 addl MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 460 cmpb MACRO_LITERAL(0), REG_VAR(temp_char) // if (temp_char == '\0') 461 je VAR(finished) // goto finished 462 cmpb MACRO_LITERAL(68), REG_VAR(temp_char) // if (temp_char == 'D') 463 je 2f // goto FOUND_DOUBLE 464 cmpb MACRO_LITERAL(70), REG_VAR(temp_char) // if (temp_char == 'F') 465 je 3f // goto FOUND_FLOAT 466 addl MACRO_LITERAL(4), REG_VAR(arg_array) // arg_array++ 467 // Handle extra space in arg array taken by a long. 468 cmpb MACRO_LITERAL(74), REG_VAR(temp_char) // if (temp_char != 'J') 469 jne 1b // goto LOOP 470 addl MACRO_LITERAL(4), REG_VAR(arg_array) // arg_array++ 471 jmp 1b // goto LOOP 4722: // FOUND_DOUBLE 473 movsd (REG_VAR(arg_array)), REG_VAR(xmm_reg) 474 addl MACRO_LITERAL(8), REG_VAR(arg_array) // arg_array+=2 475 jmp 4f 4763: // FOUND_FLOAT 477 movss (REG_VAR(arg_array)), REG_VAR(xmm_reg) 478 addl MACRO_LITERAL(4), REG_VAR(arg_array) // arg_array++ 4794: 480END_MACRO 481 482 /* 483 * Helper for quick invocation stub to set up GPR registers. 484 * Increments shorty and arg_array, and returns the current short character in 485 * temp_char. Branches to finished if it encounters the end of the shorty. 486 */ 487MACRO4(SKIP_OVER_FLOATS, shorty, arg_array, temp_char, finished) 4881: // LOOP: 489 movb (REG_VAR(shorty)), REG_VAR(temp_char) // temp_char := *shorty 490 addl MACRO_LITERAL(1), REG_VAR(shorty) // shorty++ 491 cmpb MACRO_LITERAL(0), REG_VAR(temp_char) // if (temp_char == '\0') 492 je VAR(finished) // goto finished 493 cmpb MACRO_LITERAL(70), REG_VAR(temp_char) // if (temp_char == 'F') 494 je 3f // goto SKIP_FLOAT 495 cmpb MACRO_LITERAL(68), REG_VAR(temp_char) // if (temp_char == 'D') 496 je 4f // goto SKIP_DOUBLE 497 jmp 5f // goto end 4983: // SKIP_FLOAT 499 addl MACRO_LITERAL(4), REG_VAR(arg_array) // arg_array++ 500 jmp 1b // goto LOOP 5014: // SKIP_DOUBLE 502 addl MACRO_LITERAL(8), REG_VAR(arg_array) // arg_array+=2 503 jmp 1b // goto LOOP 5045: 505END_MACRO 506 507 /* 508 * Quick invocation stub (non-static). 509 * On entry: 510 * [sp] = return address 511 * [sp + 4] = method pointer 512 * [sp + 8] = argument array or null for no argument methods 513 * [sp + 12] = size of argument array in bytes 514 * [sp + 16] = (managed) thread pointer 515 * [sp + 20] = JValue* result 516 * [sp + 24] = shorty 517 */ 518DEFINE_FUNCTION art_quick_invoke_stub 519 // Save the non-volatiles. 520 PUSH ebp // save ebp 521 PUSH ebx // save ebx 522 PUSH esi // save esi 523 PUSH edi // save edi 524 // Set up argument XMM registers. 525 mov 24+16(%esp), %esi // ESI := shorty + 1 ; ie skip return arg character. 526 addl LITERAL(1), %esi 527 mov 8+16(%esp), %edi // EDI := arg_array + 4 ; ie skip this pointer. 528 addl LITERAL(4), %edi 529 // Clobbers ESI, EDI, EAX. 530 LOOP_OVER_SHORTY_LOADING_XMMS xmm0, esi, edi, al, .Lxmm_setup_finished 531 LOOP_OVER_SHORTY_LOADING_XMMS xmm1, esi, edi, al, .Lxmm_setup_finished 532 LOOP_OVER_SHORTY_LOADING_XMMS xmm2, esi, edi, al, .Lxmm_setup_finished 533 LOOP_OVER_SHORTY_LOADING_XMMS xmm3, esi, edi, al, .Lxmm_setup_finished 534 .balign 16 535.Lxmm_setup_finished: 536 mov %esp, %ebp // copy value of stack pointer into base pointer 537 CFI_DEF_CFA_REGISTER(ebp) 538 mov 28(%ebp), %ebx // get arg array size 539 // reserve space for return addr, method*, ebx, ebp, esi, and edi in frame 540 addl LITERAL(36), %ebx 541 // align frame size to 16 bytes 542 andl LITERAL(0xFFFFFFF0), %ebx 543 subl LITERAL(20), %ebx // remove space for return address, ebx, ebp, esi and edi 544 subl %ebx, %esp // reserve stack space for argument array 545 546 movl LITERAL(0), (%esp) // store null for method* 547 548 // Copy arg array into stack. 549 movl 28(%ebp), %ecx // ECX = size of args 550 movl 24(%ebp), %esi // ESI = argument array 551 leal 4(%esp), %edi // EDI = just after Method* in stack arguments 552 rep movsb // while (ecx--) { *edi++ = *esi++ } 553 554 mov 40(%ebp), %esi // ESI := shorty + 1 ; ie skip return arg character. 555 addl LITERAL(1), %esi 556 mov 24(%ebp), %edi // EDI := arg_array 557 mov 0(%edi), %ecx // ECX := this pointer 558 addl LITERAL(4), %edi // EDI := arg_array + 4 ; ie skip this pointer. 559 560 // Enumerate the possible cases for loading GPRS. 561 // edx (and maybe ebx): 562 SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished 563 cmpb LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 564 je .LfirstLong 565 // Must be an integer value. 566 movl (%edi), %edx 567 addl LITERAL(4), %edi // arg_array++ 568 569 // Now check ebx 570 SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished 571 // Must be first word of a long, or an integer. First word of long doesn't 572 // go into EBX, but can be loaded there anyways, as it is harmless. 573 movl (%edi), %ebx 574 jmp .Lgpr_setup_finished 575.LfirstLong: 576 movl (%edi), %edx 577 movl 4(%edi), %ebx 578 // Nothing left to load. 579.Lgpr_setup_finished: 580 mov 20(%ebp), %eax // move method pointer into eax 581 call *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method 582 mov %ebp, %esp // restore stack pointer 583 CFI_DEF_CFA_REGISTER(esp) 584 POP edi // pop edi 585 POP esi // pop esi 586 POP ebx // pop ebx 587 POP ebp // pop ebp 588 mov 20(%esp), %ecx // get result pointer 589 mov %eax, (%ecx) // store the result assuming its a long, int or Object* 590 mov %edx, 4(%ecx) // store the other half of the result 591 mov 24(%esp), %edx // get the shorty 592 cmpb LITERAL(68), (%edx) // test if result type char == 'D' 593 je .Lreturn_double_quick 594 cmpb LITERAL(70), (%edx) // test if result type char == 'F' 595 je .Lreturn_float_quick 596 ret 597.Lreturn_double_quick: 598 movsd %xmm0, (%ecx) // store the floating point result 599 ret 600.Lreturn_float_quick: 601 movss %xmm0, (%ecx) // store the floating point result 602 ret 603END_FUNCTION art_quick_invoke_stub 604 605 /* 606 * Quick invocation stub (static). 607 * On entry: 608 * [sp] = return address 609 * [sp + 4] = method pointer 610 * [sp + 8] = argument array or null for no argument methods 611 * [sp + 12] = size of argument array in bytes 612 * [sp + 16] = (managed) thread pointer 613 * [sp + 20] = JValue* result 614 * [sp + 24] = shorty 615 */ 616DEFINE_FUNCTION art_quick_invoke_static_stub 617 // Save the non-volatiles. 618 PUSH ebp // save ebp 619 PUSH ebx // save ebx 620 PUSH esi // save esi 621 PUSH edi // save edi 622 // Set up argument XMM registers. 623 mov 24+16(%esp), %esi // ESI := shorty + 1 ; ie skip return arg character. 624 addl LITERAL(1), %esi 625 mov 8+16(%esp), %edi // EDI := arg_array 626 // Clobbers ESI, EDI, EAX. 627 LOOP_OVER_SHORTY_LOADING_XMMS xmm0, esi, edi, al, .Lxmm_setup_finished2 628 LOOP_OVER_SHORTY_LOADING_XMMS xmm1, esi, edi, al, .Lxmm_setup_finished2 629 LOOP_OVER_SHORTY_LOADING_XMMS xmm2, esi, edi, al, .Lxmm_setup_finished2 630 LOOP_OVER_SHORTY_LOADING_XMMS xmm3, esi, edi, al, .Lxmm_setup_finished2 631 .balign 16 632.Lxmm_setup_finished2: 633 mov %esp, %ebp // copy value of stack pointer into base pointer 634 CFI_DEF_CFA_REGISTER(ebp) 635 mov 28(%ebp), %ebx // get arg array size 636 // reserve space for return addr, method*, ebx, ebp, esi, and edi in frame 637 addl LITERAL(36), %ebx 638 // align frame size to 16 bytes 639 andl LITERAL(0xFFFFFFF0), %ebx 640 subl LITERAL(20), %ebx // remove space for return address, ebx, ebp, esi and edi 641 subl %ebx, %esp // reserve stack space for argument array 642 643 movl LITERAL(0), (%esp) // store null for method* 644 645 // Copy arg array into stack. 646 movl 28(%ebp), %ecx // ECX = size of args 647 movl 24(%ebp), %esi // ESI = argument array 648 leal 4(%esp), %edi // EDI = just after Method* in stack arguments 649 rep movsb // while (ecx--) { *edi++ = *esi++ } 650 651 mov 40(%ebp), %esi // ESI := shorty + 1 ; ie skip return arg character. 652 addl LITERAL(1), %esi 653 mov 24(%ebp), %edi // EDI := arg_array 654 655 // Enumerate the possible cases for loading GPRS. 656 // ecx (and maybe edx) 657 SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2 658 cmpb LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 659 je .LfirstLong2 660 // Must be an integer value. Load into ECX. 661 movl (%edi), %ecx 662 addl LITERAL(4), %edi // arg_array++ 663 664 // Now check edx (and maybe ebx). 665 SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2 666 cmpb LITERAL(74), %al // if (al == 'J') goto FOUND_LONG 667 je .LSecondLong2 668 // Must be an integer. Load into EDX. 669 movl (%edi), %edx 670 addl LITERAL(4), %edi // arg_array++ 671 672 // Is there anything for ebx? 673 SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2 674 // Must be first word of a long, or an integer. First word of long doesn't 675 // go into EBX, but can be loaded there anyways, as it is harmless. 676 movl (%edi), %ebx 677 jmp .Lgpr_setup_finished2 678.LSecondLong2: 679 // EDX:EBX is long. That is all. 680 movl (%edi), %edx 681 movl 4(%edi), %ebx 682 jmp .Lgpr_setup_finished2 683.LfirstLong2: 684 // ECX:EDX is a long 685 movl (%edi), %ecx 686 movl 4(%edi), %edx 687 addl LITERAL(8), %edi // arg_array += 2 688 689 // Anything for EBX? 690 SKIP_OVER_FLOATS esi, edi, al, .Lgpr_setup_finished2 691 // Must be first word of a long, or an integer. First word of long doesn't 692 // go into EBX, but can be loaded there anyways, as it is harmless. 693 movl (%edi), %ebx 694 jmp .Lgpr_setup_finished2 695 // Nothing left to load. 696.Lgpr_setup_finished2: 697 mov 20(%ebp), %eax // move method pointer into eax 698 call *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method 699 mov %ebp, %esp // restore stack pointer 700 CFI_DEF_CFA_REGISTER(esp) 701 POP edi // pop edi 702 POP esi // pop esi 703 POP ebx // pop ebx 704 POP ebp // pop ebp 705 mov 20(%esp), %ecx // get result pointer 706 mov %eax, (%ecx) // store the result assuming its a long, int or Object* 707 mov %edx, 4(%ecx) // store the other half of the result 708 mov 24(%esp), %edx // get the shorty 709 cmpb LITERAL(68), (%edx) // test if result type char == 'D' 710 je .Lreturn_double_quick2 711 cmpb LITERAL(70), (%edx) // test if result type char == 'F' 712 je .Lreturn_float_quick2 713 ret 714.Lreturn_double_quick2: 715 movsd %xmm0, (%ecx) // store the floating point result 716 ret 717.Lreturn_float_quick2: 718 movss %xmm0, (%ecx) // store the floating point result 719 ret 720END_FUNCTION art_quick_invoke_static_stub 721 722MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 723 DEFINE_FUNCTION VAR(c_name) 724 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 725 // Outgoing argument set up 726 subl MACRO_LITERAL(8), %esp // push padding 727 CFI_ADJUST_CFA_OFFSET(8) 728 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 729 CFI_ADJUST_CFA_OFFSET(4) 730 PUSH eax // pass arg1 731 call CALLVAR(cxx_name) // cxx_name(arg1, Thread*) 732 addl MACRO_LITERAL(16), %esp // pop arguments 733 CFI_ADJUST_CFA_OFFSET(-16) 734 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 735 CALL_MACRO(return_macro) // return or deliver exception 736 END_FUNCTION VAR(c_name) 737END_MACRO 738 739MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 740 DEFINE_FUNCTION VAR(c_name) 741 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 742 // Outgoing argument set up 743 PUSH eax // push padding 744 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 745 CFI_ADJUST_CFA_OFFSET(4) 746 PUSH ecx // pass arg2 747 PUSH eax // pass arg1 748 call CALLVAR(cxx_name) // cxx_name(arg1, arg2, Thread*) 749 addl MACRO_LITERAL(16), %esp // pop arguments 750 CFI_ADJUST_CFA_OFFSET(-16) 751 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 752 CALL_MACRO(return_macro) // return or deliver exception 753 END_FUNCTION VAR(c_name) 754END_MACRO 755 756MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 757 DEFINE_FUNCTION VAR(c_name) 758 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 759 // Outgoing argument set up 760 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 761 CFI_ADJUST_CFA_OFFSET(4) 762 PUSH edx // pass arg3 763 PUSH ecx // pass arg2 764 PUSH eax // pass arg1 765 call CALLVAR(cxx_name) // cxx_name(arg1, arg2, arg3, Thread*) 766 addl MACRO_LITERAL(16), %esp // pop arguments 767 CFI_ADJUST_CFA_OFFSET(-16) 768 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 769 CALL_MACRO(return_macro) // return or deliver exception 770 END_FUNCTION VAR(c_name) 771END_MACRO 772 773MACRO3(FOUR_ARG_DOWNCALL, c_name, cxx_name, return_macro) 774 DEFINE_FUNCTION VAR(c_name) 775 SETUP_SAVE_REFS_ONLY_FRAME_PRESERVE_GOT_REG ebx, ebx // save ref containing registers for GC 776 777 // Outgoing argument set up 778 subl MACRO_LITERAL(12), %esp // alignment padding 779 CFI_ADJUST_CFA_OFFSET(12) 780 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 781 CFI_ADJUST_CFA_OFFSET(4) 782 PUSH ebx // pass arg4 783 PUSH edx // pass arg3 784 PUSH ecx // pass arg2 785 PUSH eax // pass arg1 786 call CALLVAR(cxx_name) // cxx_name(arg1, arg2, arg3, arg4, Thread*) 787 addl MACRO_LITERAL(32), %esp // pop arguments 788 CFI_ADJUST_CFA_OFFSET(-32) 789 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 790 CALL_MACRO(return_macro) // return or deliver exception 791 END_FUNCTION VAR(c_name) 792END_MACRO 793 794MACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) 795 DEFINE_FUNCTION VAR(c_name) 796 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 797 // Outgoing argument set up 798 subl MACRO_LITERAL(8), %esp // alignment padding 799 CFI_ADJUST_CFA_OFFSET(8) 800 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 801 CFI_ADJUST_CFA_OFFSET(4) 802 PUSH eax // pass arg1 803 call CALLVAR(cxx_name) // cxx_name(arg1, Thread*) 804 addl MACRO_LITERAL(16), %esp // pop arguments 805 CFI_ADJUST_CFA_OFFSET(-16) 806 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 807 CALL_MACRO(return_macro) // return or deliver exception 808 END_FUNCTION VAR(c_name) 809END_MACRO 810 811MACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) 812 DEFINE_FUNCTION VAR(c_name) 813 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 814 // Outgoing argument set up 815 PUSH eax // alignment padding 816 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 817 CFI_ADJUST_CFA_OFFSET(4) 818 PUSH ecx // pass arg2 819 PUSH eax // pass arg1 820 call CALLVAR(cxx_name) // cxx_name(arg1, arg2, referrer, Thread*) 821 addl MACRO_LITERAL(16), %esp // pop arguments 822 CFI_ADJUST_CFA_OFFSET(-16) 823 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 824 CALL_MACRO(return_macro) // return or deliver exception 825 END_FUNCTION VAR(c_name) 826END_MACRO 827 828MACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro) 829 DEFINE_FUNCTION VAR(c_name) 830 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 831 // Outgoing argument set up 832 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 833 CFI_ADJUST_CFA_OFFSET(4) 834 PUSH edx // pass arg3 835 PUSH ecx // pass arg2 836 PUSH eax // pass arg1 837 call CALLVAR(cxx_name) // cxx_name(arg1, arg2, arg3, Thread*) 838 addl LITERAL(16), %esp // pop arguments 839 CFI_ADJUST_CFA_OFFSET(-32) 840 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 841 CALL_MACRO(return_macro) // return or deliver exception 842 END_FUNCTION VAR(c_name) 843END_MACRO 844 845 /* 846 * Macro for resolution and initialization of indexed DEX file 847 * constants such as classes and strings. 848 */ 849MACRO3(ONE_ARG_SAVE_EVERYTHING_DOWNCALL, c_name, cxx_name, runtime_method_offset = RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET) 850 DEFINE_FUNCTION VAR(c_name) 851 SETUP_SAVE_EVERYTHING_FRAME ebx, ebx, \runtime_method_offset // save ref containing registers for GC 852 // Outgoing argument set up 853 subl MACRO_LITERAL(8), %esp // push padding 854 CFI_ADJUST_CFA_OFFSET(8) 855 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 856 CFI_ADJUST_CFA_OFFSET(4) 857 PUSH eax // pass the index of the constant as arg1 858 call CALLVAR(cxx_name) // cxx_name(arg1, Thread*) 859 addl MACRO_LITERAL(16), %esp // pop arguments 860 CFI_ADJUST_CFA_OFFSET(-16) 861 testl %eax, %eax // If result is null, deliver the OOME. 862 jz 1f 863 CFI_REMEMBER_STATE 864 RESTORE_SAVE_EVERYTHING_FRAME_KEEP_EAX // restore frame up to return address 865 ret // return 866 CFI_RESTORE_STATE_AND_DEF_CFA(esp, FRAME_SIZE_SAVE_EVERYTHING) 8671: 868 DELIVER_PENDING_EXCEPTION_FRAME_READY 869 END_FUNCTION VAR(c_name) 870END_MACRO 871 872MACRO2(ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT, c_name, cxx_name) 873 ONE_ARG_SAVE_EVERYTHING_DOWNCALL \c_name, \cxx_name, RUNTIME_SAVE_EVERYTHING_FOR_CLINIT_METHOD_OFFSET 874END_MACRO 875 876MACRO0(RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER) 877 testl %eax, %eax // eax == 0 ? 878 jz 1f // if eax == 0 goto 1 879 ret // return 8801: // deliver exception on current thread 881 DELIVER_PENDING_EXCEPTION 882END_MACRO 883 884MACRO0(RETURN_IF_EAX_ZERO) 885 testl %eax, %eax // eax == 0 ? 886 jnz 1f // if eax != 0 goto 1 887 ret // return 8881: // deliver exception on current thread 889 DELIVER_PENDING_EXCEPTION 890END_MACRO 891 892MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION) 893 cmpl MACRO_LITERAL(0),%fs:THREAD_EXCEPTION_OFFSET // exception field == 0 ? 894 jne 1f // if exception field != 0 goto 1 895 ret // return 8961: // deliver exception on current thread 897 DELIVER_PENDING_EXCEPTION 898END_MACRO 899 900// Generate the allocation entrypoints for each allocator. 901GENERATE_ALLOC_ENTRYPOINTS_FOR_NON_TLAB_ALLOCATORS 902 903// Comment out allocators that have x86 specific asm. 904// Region TLAB: 905// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_region_tlab, RegionTLAB) 906// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_region_tlab, RegionTLAB) 907GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB) 908GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_OBJECT(_region_tlab, RegionTLAB) 909// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_region_tlab, RegionTLAB) 910// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED8(_region_tlab, RegionTLAB) 911// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED16(_region_tlab, RegionTLAB) 912// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED32(_region_tlab, RegionTLAB) 913// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED64(_region_tlab, RegionTLAB) 914GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(_region_tlab, RegionTLAB) 915GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_CHARS(_region_tlab, RegionTLAB) 916GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_STRING(_region_tlab, RegionTLAB) 917// Normal TLAB: 918// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_tlab, TLAB) 919// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab, TLAB) 920GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB) 921GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_OBJECT(_tlab, TLAB) 922// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB) 923// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED8(_tlab, TLAB) 924// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED16(_tlab, TLAB) 925// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED32(_tlab, TLAB) 926// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED64(_tlab, TLAB) 927GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(_tlab, TLAB) 928GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_CHARS(_tlab, TLAB) 929GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_STRING(_tlab, TLAB) 930 931// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_rosalloc, RosAlloc). 932MACRO2(ART_QUICK_ALLOC_OBJECT_ROSALLOC, c_name, cxx_name) 933 DEFINE_FUNCTION VAR(c_name) 934 // Fast path rosalloc allocation. 935 // eax: type/return value 936 // ecx, ebx, edx: free 937 movl %fs:THREAD_SELF_OFFSET, %ebx // ebx = thread 938 // Check if the thread local allocation 939 // stack has room 940 movl THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx), %ecx 941 cmpl THREAD_LOCAL_ALLOC_STACK_END_OFFSET(%ebx), %ecx 942 jae .Lslow_path\c_name 943 944 movl MIRROR_CLASS_OBJECT_SIZE_ALLOC_FAST_PATH_OFFSET(%eax), %ecx // Load the object size (ecx) 945 // Check if the size is for a thread 946 // local allocation. Also does the 947 // finalizable and initialization check. 948 cmpl LITERAL(ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE), %ecx 949 ja .Lslow_path\c_name 950 shrl LITERAL(ROSALLOC_BRACKET_QUANTUM_SIZE_SHIFT), %ecx // Calculate the rosalloc bracket index 951 // from object size. 952 // Load thread local rosalloc run (ebx) 953 // Subtract __SIZEOF_POINTER__ to subtract 954 // one from edi as there is no 0 byte run 955 // and the size is already aligned. 956 movl (THREAD_ROSALLOC_RUNS_OFFSET - __SIZEOF_POINTER__)(%ebx, %ecx, __SIZEOF_POINTER__), %ebx 957 // Load free_list head (edi), 958 // this will be the return value. 959 movl (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)(%ebx), %ecx 960 jecxz .Lslow_path\c_name 961 // Point of no slow path. Won't go to 962 // the slow path from here on. 963 // Load the next pointer of the head 964 // and update head of free list with 965 // next pointer 966 movl ROSALLOC_SLOT_NEXT_OFFSET(%ecx), %edx 967 movl %edx, (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_HEAD_OFFSET)(%ebx) 968 // Decrement size of free list by 1 969 decl (ROSALLOC_RUN_FREE_LIST_OFFSET + ROSALLOC_RUN_FREE_LIST_SIZE_OFFSET)(%ebx) 970 // Store the class pointer in the 971 // header. This also overwrites the 972 // next pointer. The offsets are 973 // asserted to match. 974#if ROSALLOC_SLOT_NEXT_OFFSET != MIRROR_OBJECT_CLASS_OFFSET 975#error "Class pointer needs to overwrite next pointer." 976#endif 977 POISON_HEAP_REF eax 978 movl %eax, MIRROR_OBJECT_CLASS_OFFSET(%ecx) 979 movl %fs:THREAD_SELF_OFFSET, %ebx // ebx = thread 980 // Push the new object onto the thread 981 // local allocation stack and 982 // increment the thread local 983 // allocation stack top. 984 movl THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx), %eax 985 movl %ecx, (%eax) 986 addl LITERAL(COMPRESSED_REFERENCE_SIZE), %eax 987 movl %eax, THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET(%ebx) 988 // No fence needed for x86. 989 movl %ecx, %eax // Move object to return register 990 ret 991.Lslow_path\c_name: 992 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 993 // Outgoing argument set up 994 subl LITERAL(8), %esp // alignment padding 995 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 996 CFI_ADJUST_CFA_OFFSET(4) 997 PUSH eax 998 call SYMBOL(artAllocObjectFromCodeResolvedRosAlloc) // cxx_name(arg0, Thread*) 999 addl LITERAL(16), %esp // pop arguments 1000 CFI_ADJUST_CFA_OFFSET(-16) 1001 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 1002 RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // return or deliver exception 1003 END_FUNCTION VAR(c_name) 1004END_MACRO 1005 1006ART_QUICK_ALLOC_OBJECT_ROSALLOC art_quick_alloc_object_resolved_rosalloc, artAllocObjectFromCodeResolvedRosAlloc 1007ART_QUICK_ALLOC_OBJECT_ROSALLOC art_quick_alloc_object_initialized_rosalloc, artAllocObjectFromCodeInitializedRosAlloc 1008 1009// The common fast path code for art_quick_alloc_object_resolved/initialized_tlab 1010// and art_quick_alloc_object_resolved/initialized_region_tlab. 1011// 1012// EAX: type/return_value 1013MACRO1(ALLOC_OBJECT_RESOLVED_TLAB_FAST_PATH, slowPathLabel) 1014 movl %fs:THREAD_SELF_OFFSET, %ebx // ebx = thread 1015 movl THREAD_LOCAL_END_OFFSET(%ebx), %edi // Load thread_local_end. 1016 subl THREAD_LOCAL_POS_OFFSET(%ebx), %edi // Compute the remaining buffer size. 1017 movl MIRROR_CLASS_OBJECT_SIZE_ALLOC_FAST_PATH_OFFSET(%eax), %ecx // Load the object size. 1018 cmpl %edi, %ecx // Check if it fits. 1019 ja VAR(slowPathLabel) 1020 movl THREAD_LOCAL_POS_OFFSET(%ebx), %edx // Load thread_local_pos 1021 // as allocated object. 1022 addl %edx, %ecx // Add the object size. 1023 movl %ecx, THREAD_LOCAL_POS_OFFSET(%ebx) // Update thread_local_pos. 1024 incl THREAD_LOCAL_OBJECTS_OFFSET(%ebx) // Increase thread_local_objects. 1025 // Store the class pointer in the header. 1026 // No fence needed for x86. 1027 POISON_HEAP_REF eax 1028 movl %eax, MIRROR_OBJECT_CLASS_OFFSET(%edx) 1029 movl %edx, %eax 1030 POP edi 1031 ret // Fast path succeeded. 1032END_MACRO 1033 1034// The common slow path code for art_quick_alloc_object_resolved/initialized_tlab 1035// and art_quick_alloc_object_resolved/initialized_region_tlab. 1036MACRO1(ALLOC_OBJECT_RESOLVED_TLAB_SLOW_PATH, cxx_name) 1037 POP edi 1038 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 1039 // Outgoing argument set up 1040 subl LITERAL(8), %esp // alignment padding 1041 CFI_ADJUST_CFA_OFFSET(8) 1042 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1043 CFI_ADJUST_CFA_OFFSET(4) 1044 PUSH eax 1045 call CALLVAR(cxx_name) // cxx_name(arg0, Thread*) 1046 addl LITERAL(16), %esp 1047 CFI_ADJUST_CFA_OFFSET(-16) 1048 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 1049 RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // return or deliver exception 1050END_MACRO 1051 1052MACRO2(ART_QUICK_ALLOC_OBJECT_TLAB, c_name, cxx_name) 1053 DEFINE_FUNCTION VAR(c_name) 1054 // Fast path tlab allocation. 1055 // EAX: type 1056 // EBX, ECX, EDX: free. 1057 PUSH edi 1058 ALLOC_OBJECT_RESOLVED_TLAB_FAST_PATH .Lslow_path\c_name 1059.Lslow_path\c_name: 1060 ALLOC_OBJECT_RESOLVED_TLAB_SLOW_PATH RAW_VAR(cxx_name) 1061 END_FUNCTION VAR(c_name) 1062END_MACRO 1063 1064ART_QUICK_ALLOC_OBJECT_TLAB art_quick_alloc_object_resolved_tlab, artAllocObjectFromCodeResolvedTLAB 1065ART_QUICK_ALLOC_OBJECT_TLAB art_quick_alloc_object_initialized_tlab, artAllocObjectFromCodeInitializedTLAB 1066ART_QUICK_ALLOC_OBJECT_TLAB art_quick_alloc_object_resolved_region_tlab, artAllocObjectFromCodeResolvedRegionTLAB 1067ART_QUICK_ALLOC_OBJECT_TLAB art_quick_alloc_object_initialized_region_tlab, artAllocObjectFromCodeInitializedRegionTLAB 1068 1069// The fast path code for art_quick_alloc_array_region_tlab. 1070// Inputs: EAX: the class, ECX: int32_t component_count, EDX: total_size 1071// Free temp: EBX 1072// Output: EAX: return value. 1073MACRO1(ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED_WITH_SIZE, slowPathLabel) 1074 mov %fs:THREAD_SELF_OFFSET, %ebx // ebx = thread 1075 // Mask out the unaligned part to make sure we are 8 byte aligned. 1076 andl LITERAL(OBJECT_ALIGNMENT_MASK_TOGGLED), %edx 1077 movl THREAD_LOCAL_END_OFFSET(%ebx), %edi 1078 subl THREAD_LOCAL_POS_OFFSET(%ebx), %edi 1079 cmpl %edi, %edx // Check if it fits. 1080 ja RAW_VAR(slowPathLabel) 1081 movl THREAD_LOCAL_POS_OFFSET(%ebx), %edi 1082 addl %edi, %edx // Add the object size. 1083 movl %edx, THREAD_LOCAL_POS_OFFSET(%ebx) // Update thread_local_pos_ 1084 addl LITERAL(1), THREAD_LOCAL_OBJECTS_OFFSET(%ebx) // Increase thread_local_objects. 1085 // Store the class pointer in the 1086 // header. 1087 // No fence needed for x86. 1088 POISON_HEAP_REF eax 1089 movl %eax, MIRROR_OBJECT_CLASS_OFFSET(%edi) 1090 movl %ecx, MIRROR_ARRAY_LENGTH_OFFSET(%edi) 1091 movl %edi, %eax 1092 POP edi 1093 ret // Fast path succeeded. 1094END_MACRO 1095 1096MACRO1(COMPUTE_ARRAY_SIZE_UNKNOWN, slow_path) 1097 // We should never enter here. Code is provided for reference. 1098 int3 1099 // Possibly a large object, go slow. 1100 // Also does negative array size check. 1101 cmpl LITERAL((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_WIDE_ARRAY_DATA_OFFSET) / 8), %ecx 1102 ja RAW_VAR(slow_path) 1103 PUSH ecx 1104 movl %ecx, %edx 1105 movl MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%eax), %ecx // Load component type. 1106 UNPOISON_HEAP_REF ecx 1107 movl MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET(%ecx), %ecx // Load primitive type. 1108 shr MACRO_LITERAL(PRIMITIVE_TYPE_SIZE_SHIFT_SHIFT), %ecx // Get component size shift. 1109 sall %cl, %edx // Calculate array count shifted. 1110 // Add array header + alignment rounding. 1111 add MACRO_LITERAL(MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK), %edx 1112 // Add 4 extra bytes if we are doing a long array. 1113 add MACRO_LITERAL(1), %ecx 1114 and MACRO_LITERAL(4), %ecx 1115#if MIRROR_WIDE_ARRAY_DATA_OFFSET != MIRROR_INT_ARRAY_DATA_OFFSET + 4 1116#error Long array data offset must be 4 greater than int array data offset. 1117#endif 1118 addl %ecx, %edx 1119 POP ecx 1120END_MACRO 1121 1122MACRO1(COMPUTE_ARRAY_SIZE_8, slow_path) 1123 // EAX: mirror::Class* klass, ECX: int32_t component_count 1124 // Possibly a large object, go slow. 1125 // Also does negative array size check. 1126 cmpl LITERAL(MIN_LARGE_OBJECT_THRESHOLD - MIRROR_INT_ARRAY_DATA_OFFSET), %ecx 1127 ja RAW_VAR(slow_path) 1128 // Add array header + alignment rounding. 1129 leal (MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK)(%ecx), %edx 1130END_MACRO 1131 1132MACRO1(COMPUTE_ARRAY_SIZE_16, slow_path) 1133 // EAX: mirror::Class* klass, ECX: int32_t component_count 1134 // Possibly a large object, go slow. 1135 // Also does negative array size check. 1136 cmpl LITERAL((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_INT_ARRAY_DATA_OFFSET) / 2), %ecx 1137 ja RAW_VAR(slow_path) 1138 // Add array header + alignment rounding. 1139 leal ((MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK) / 2)(%ecx), %edx 1140 sall MACRO_LITERAL(1), %edx 1141END_MACRO 1142 1143MACRO1(COMPUTE_ARRAY_SIZE_32, slow_path) 1144 // EAX: mirror::Class* klass, ECX: int32_t component_count 1145 // Possibly a large object, go slow. 1146 // Also does negative array size check. 1147 cmpl LITERAL((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_INT_ARRAY_DATA_OFFSET) / 4), %ecx 1148 ja RAW_VAR(slow_path) 1149 // Add array header + alignment rounding. 1150 leal ((MIRROR_INT_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK) / 4)(%ecx), %edx 1151 sall MACRO_LITERAL(2), %edx 1152END_MACRO 1153 1154MACRO1(COMPUTE_ARRAY_SIZE_64, slow_path) 1155 // EAX: mirror::Class* klass, ECX: int32_t component_count 1156 // Possibly a large object, go slow. 1157 // Also does negative array size check. 1158 cmpl LITERAL((MIN_LARGE_OBJECT_THRESHOLD - MIRROR_WIDE_ARRAY_DATA_OFFSET) / 8), %ecx 1159 ja RAW_VAR(slow_path) 1160 // Add array header + alignment rounding. 1161 leal ((MIRROR_WIDE_ARRAY_DATA_OFFSET + OBJECT_ALIGNMENT_MASK) / 8)(%ecx), %edx 1162 sall MACRO_LITERAL(3), %edx 1163END_MACRO 1164 1165MACRO3(GENERATE_ALLOC_ARRAY_TLAB, c_entrypoint, cxx_name, size_setup) 1166 DEFINE_FUNCTION VAR(c_entrypoint) 1167 // EAX: mirror::Class* klass, ECX: int32_t component_count 1168 PUSH edi 1169 CALL_MACRO(size_setup) .Lslow_path\c_entrypoint 1170 ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED_WITH_SIZE .Lslow_path\c_entrypoint 1171.Lslow_path\c_entrypoint: 1172 POP edi 1173 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 1174 // Outgoing argument set up 1175 PUSH eax // alignment padding 1176 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1177 CFI_ADJUST_CFA_OFFSET(4) 1178 PUSH ecx 1179 PUSH eax 1180 call CALLVAR(cxx_name) // cxx_name(arg0, arg1, Thread*) 1181 addl LITERAL(16), %esp // pop arguments 1182 CFI_ADJUST_CFA_OFFSET(-16) 1183 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 1184 RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // return or deliver exception 1185 END_FUNCTION VAR(c_entrypoint) 1186END_MACRO 1187 1188 1189GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_UNKNOWN 1190GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved8_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_8 1191GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved16_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_16 1192GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved32_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_32 1193GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved64_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, COMPUTE_ARRAY_SIZE_64 1194 1195GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_UNKNOWN 1196GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved8_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_8 1197GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved16_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_16 1198GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved32_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_32 1199GENERATE_ALLOC_ARRAY_TLAB art_quick_alloc_array_resolved64_tlab, artAllocArrayFromCodeResolvedTLAB, COMPUTE_ARRAY_SIZE_64 1200 1201ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_initialize_static_storage, artInitializeStaticStorageFromCode 1202ONE_ARG_SAVE_EVERYTHING_DOWNCALL_FOR_CLINIT art_quick_resolve_type, artResolveTypeFromCode 1203ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_type_and_verify_access, artResolveTypeAndVerifyAccessFromCode 1204ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_handle, artResolveMethodHandleFromCode 1205ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_method_type, artResolveMethodTypeFromCode 1206ONE_ARG_SAVE_EVERYTHING_DOWNCALL art_quick_resolve_string, artResolveStringFromCode 1207 1208TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO 1209 1210DEFINE_FUNCTION art_quick_lock_object 1211 testl %eax, %eax // null check object/eax 1212 jz .Lslow_lock 1213.Lretry_lock: 1214 movl MIRROR_OBJECT_LOCK_WORD_OFFSET(%eax), %ecx // ecx := lock word 1215 test LITERAL(LOCK_WORD_STATE_MASK_SHIFTED), %ecx // test the 2 high bits. 1216 jne .Lslow_lock // slow path if either of the two high bits are set. 1217 movl %ecx, %edx // save lock word (edx) to keep read barrier bits. 1218 andl LITERAL(LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED), %ecx // zero the gc bits. 1219 test %ecx, %ecx 1220 jnz .Lalready_thin // lock word contains a thin lock 1221 // unlocked case - edx: original lock word, eax: obj. 1222 movl %eax, %ecx // remember object in case of retry 1223 movl %edx, %eax // eax: lock word zero except for read barrier bits. 1224 movl %fs:THREAD_ID_OFFSET, %edx // load thread id. 1225 or %eax, %edx // edx: thread id with count of 0 + read barrier bits. 1226 lock cmpxchg %edx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%ecx) // eax: old val, edx: new val. 1227 jnz .Llock_cmpxchg_fail // cmpxchg failed retry 1228 ret 1229.Lalready_thin: // edx: lock word (with high 2 bits zero and original rb bits), eax: obj. 1230 movl %fs:THREAD_ID_OFFSET, %ecx // ecx := thread id 1231 cmpw %cx, %dx // do we hold the lock already? 1232 jne .Lslow_lock 1233 movl %edx, %ecx // copy the lock word to check count overflow. 1234 andl LITERAL(LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED), %ecx // zero the read barrier bits. 1235 addl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %ecx // increment recursion count for overflow check. 1236 test LITERAL(LOCK_WORD_GC_STATE_MASK_SHIFTED), %ecx // overflowed if the first gc state bit is set. 1237 jne .Lslow_lock // count overflowed so go slow 1238 movl %eax, %ecx // save obj to use eax for cmpxchg. 1239 movl %edx, %eax // copy the lock word as the old val for cmpxchg. 1240 addl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %edx // increment recursion count again for real. 1241 // update lockword, cmpxchg necessary for read barrier bits. 1242 lock cmpxchg %edx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%ecx) // eax: old val, edx: new val. 1243 jnz .Llock_cmpxchg_fail // cmpxchg failed retry 1244 ret 1245.Llock_cmpxchg_fail: 1246 movl %ecx, %eax // restore eax 1247 jmp .Lretry_lock 1248.Lslow_lock: 1249 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 1250 // Outgoing argument set up 1251 subl LITERAL(8), %esp // alignment padding 1252 CFI_ADJUST_CFA_OFFSET(8) 1253 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1254 CFI_ADJUST_CFA_OFFSET(4) 1255 PUSH eax // pass object 1256 call SYMBOL(artLockObjectFromCode) // artLockObjectFromCode(object, Thread*) 1257 addl LITERAL(16), %esp // pop arguments 1258 CFI_ADJUST_CFA_OFFSET(-16) 1259 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 1260 RETURN_IF_EAX_ZERO 1261END_FUNCTION art_quick_lock_object 1262 1263DEFINE_FUNCTION art_quick_lock_object_no_inline 1264 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 1265 // Outgoing argument set up 1266 subl LITERAL(8), %esp // alignment padding 1267 CFI_ADJUST_CFA_OFFSET(8) 1268 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1269 CFI_ADJUST_CFA_OFFSET(4) 1270 PUSH eax // pass object 1271 call SYMBOL(artLockObjectFromCode) // artLockObjectFromCode(object, Thread*) 1272 addl LITERAL(16), %esp // pop arguments 1273 CFI_ADJUST_CFA_OFFSET(-16) 1274 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 1275 RETURN_IF_EAX_ZERO 1276END_FUNCTION art_quick_lock_object_no_inline 1277 1278 1279DEFINE_FUNCTION art_quick_unlock_object 1280 testl %eax, %eax // null check object/eax 1281 jz .Lslow_unlock 1282.Lretry_unlock: 1283 movl MIRROR_OBJECT_LOCK_WORD_OFFSET(%eax), %ecx // ecx := lock word 1284 movl %fs:THREAD_ID_OFFSET, %edx // edx := thread id 1285 test LITERAL(LOCK_WORD_STATE_MASK_SHIFTED), %ecx 1286 jnz .Lslow_unlock // lock word contains a monitor 1287 cmpw %cx, %dx // does the thread id match? 1288 jne .Lslow_unlock 1289 movl %ecx, %edx // copy the lock word to detect new count of 0. 1290 andl LITERAL(LOCK_WORD_GC_STATE_MASK_SHIFTED_TOGGLED), %edx // zero the gc bits. 1291 cmpl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %edx 1292 jae .Lrecursive_thin_unlock 1293 // update lockword, cmpxchg necessary for read barrier bits. 1294 movl %eax, %edx // edx: obj 1295 movl %ecx, %eax // eax: old lock word. 1296 andl LITERAL(LOCK_WORD_GC_STATE_MASK_SHIFTED), %ecx // ecx: new lock word zero except original rb bits. 1297#ifndef USE_READ_BARRIER 1298 movl %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx) 1299#else 1300 lock cmpxchg %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx) // eax: old val, ecx: new val. 1301 jnz .Lunlock_cmpxchg_fail // cmpxchg failed retry 1302#endif 1303 ret 1304.Lrecursive_thin_unlock: // ecx: original lock word, eax: obj 1305 // update lockword, cmpxchg necessary for read barrier bits. 1306 movl %eax, %edx // edx: obj 1307 movl %ecx, %eax // eax: old lock word. 1308 subl LITERAL(LOCK_WORD_THIN_LOCK_COUNT_ONE), %ecx // ecx: new lock word with decremented count. 1309#ifndef USE_READ_BARRIER 1310 mov %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx) 1311#else 1312 lock cmpxchg %ecx, MIRROR_OBJECT_LOCK_WORD_OFFSET(%edx) // eax: old val, ecx: new val. 1313 jnz .Lunlock_cmpxchg_fail // cmpxchg failed retry 1314#endif 1315 ret 1316.Lunlock_cmpxchg_fail: // edx: obj 1317 movl %edx, %eax // restore eax 1318 jmp .Lretry_unlock 1319.Lslow_unlock: 1320 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 1321 // Outgoing argument set up 1322 subl LITERAL(8), %esp // alignment padding 1323 CFI_ADJUST_CFA_OFFSET(8) 1324 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1325 CFI_ADJUST_CFA_OFFSET(4) 1326 PUSH eax // pass object 1327 call SYMBOL(artUnlockObjectFromCode) // artUnlockObjectFromCode(object, Thread*) 1328 addl LITERAL(16), %esp // pop arguments 1329 CFI_ADJUST_CFA_OFFSET(-16) 1330 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 1331 RETURN_IF_EAX_ZERO 1332END_FUNCTION art_quick_unlock_object 1333 1334DEFINE_FUNCTION art_quick_unlock_object_no_inline 1335 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 1336 // Outgoing argument set up 1337 subl LITERAL(8), %esp // alignment padding 1338 CFI_ADJUST_CFA_OFFSET(8) 1339 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1340 CFI_ADJUST_CFA_OFFSET(4) 1341 PUSH eax // pass object 1342 call SYMBOL(artUnlockObjectFromCode) // artUnlockObjectFromCode(object, Thread*) 1343 addl LITERAL(16), %esp // pop arguments 1344 CFI_ADJUST_CFA_OFFSET(-16) 1345 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 1346 RETURN_IF_EAX_ZERO 1347END_FUNCTION art_quick_unlock_object_no_inline 1348 1349DEFINE_FUNCTION art_quick_instance_of 1350 PUSH eax // alignment padding 1351 PUSH ecx // pass arg2 - obj->klass 1352 PUSH eax // pass arg1 - checked class 1353 call SYMBOL(artInstanceOfFromCode) // (Object* obj, Class* ref_klass) 1354 addl LITERAL(12), %esp // pop arguments 1355 CFI_ADJUST_CFA_OFFSET(-12) 1356 ret 1357END_FUNCTION art_quick_instance_of 1358 1359DEFINE_FUNCTION art_quick_check_instance_of 1360 // Type check using the bit string passes null as the target class. In that case just throw. 1361 testl %ecx, %ecx 1362 jz .Lthrow_class_cast_exception_for_bitstring_check 1363 1364 PUSH eax // alignment padding 1365 PUSH ecx // pass arg2 - checked class 1366 PUSH eax // pass arg1 - obj 1367 call SYMBOL(artInstanceOfFromCode) // (Object* obj, Class* ref_klass) 1368 testl %eax, %eax 1369 jz .Lthrow_class_cast_exception // jump forward if not assignable 1370 addl LITERAL(12), %esp // pop arguments 1371 CFI_ADJUST_CFA_OFFSET(-12) 1372 ret 1373 CFI_ADJUST_CFA_OFFSET(12) // Reset unwind info so following code unwinds. 1374 1375.Lthrow_class_cast_exception: 1376 POP eax // pop arguments 1377 POP ecx 1378 addl LITERAL(4), %esp 1379 CFI_ADJUST_CFA_OFFSET(-4) 1380 1381.Lthrow_class_cast_exception_for_bitstring_check: 1382 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save all registers as basis for long jump context 1383 // Outgoing argument set up 1384 PUSH eax // alignment padding 1385 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1386 CFI_ADJUST_CFA_OFFSET(4) 1387 PUSH ecx // pass arg2 1388 PUSH eax // pass arg1 1389 call SYMBOL(artThrowClassCastExceptionForObject) // (Object* src, Class* dest, Thread*) 1390 UNREACHABLE 1391END_FUNCTION art_quick_check_instance_of 1392 1393// Restore reg's value if reg is not the same as exclude_reg, otherwise just adjust stack. 1394MACRO2(POP_REG_NE, reg, exclude_reg) 1395 .ifc RAW_VAR(reg), RAW_VAR(exclude_reg) 1396 addl MACRO_LITERAL(4), %esp 1397 CFI_ADJUST_CFA_OFFSET(-4) 1398 .else 1399 POP RAW_VAR(reg) 1400 .endif 1401END_MACRO 1402 1403 /* 1404 * Macro to insert read barrier, only used in art_quick_aput_obj. 1405 * obj_reg and dest_reg are registers, offset is a defined literal such as 1406 * MIRROR_OBJECT_CLASS_OFFSET. 1407 * pop_eax is a boolean flag, indicating if eax is popped after the call. 1408 * TODO: When read barrier has a fast path, add heap unpoisoning support for the fast path. 1409 */ 1410MACRO4(READ_BARRIER, obj_reg, offset, dest_reg, pop_eax) 1411#ifdef USE_READ_BARRIER 1412 PUSH eax // save registers used in art_quick_aput_obj 1413 PUSH ebx 1414 PUSH edx 1415 PUSH ecx 1416 // Outgoing argument set up 1417 pushl MACRO_LITERAL((RAW_VAR(offset))) // pass offset, double parentheses are necessary 1418 CFI_ADJUST_CFA_OFFSET(4) 1419 PUSH RAW_VAR(obj_reg) // pass obj_reg 1420 PUSH eax // pass ref, just pass eax for now since parameter ref is unused 1421 call SYMBOL(artReadBarrierSlow) // artReadBarrierSlow(ref, obj_reg, offset) 1422 // No need to unpoison return value in eax, artReadBarrierSlow() would do the unpoisoning. 1423 .ifnc RAW_VAR(dest_reg), eax 1424 movl %eax, REG_VAR(dest_reg) // save loaded ref in dest_reg 1425 .endif 1426 addl MACRO_LITERAL(12), %esp // pop arguments 1427 CFI_ADJUST_CFA_OFFSET(-12) 1428 POP_REG_NE ecx, RAW_VAR(dest_reg) // Restore args except dest_reg 1429 POP_REG_NE edx, RAW_VAR(dest_reg) 1430 POP_REG_NE ebx, RAW_VAR(dest_reg) 1431 .ifc RAW_VAR(pop_eax), true 1432 POP_REG_NE eax, RAW_VAR(dest_reg) 1433 .endif 1434#else 1435 movl RAW_VAR(offset)(REG_VAR(obj_reg)), REG_VAR(dest_reg) 1436 UNPOISON_HEAP_REF RAW_VAR(dest_reg) 1437#endif // USE_READ_BARRIER 1438END_MACRO 1439 1440DEFINE_FUNCTION art_quick_aput_obj 1441 test %edx, %edx // store of null 1442 jz .Ldo_aput_null 1443 READ_BARRIER eax, MIRROR_OBJECT_CLASS_OFFSET, ebx, true 1444 READ_BARRIER ebx, MIRROR_CLASS_COMPONENT_TYPE_OFFSET, ebx, true 1445 // value's type == array's component type - trivial assignability 1446#if defined(USE_READ_BARRIER) 1447 READ_BARRIER edx, MIRROR_OBJECT_CLASS_OFFSET, eax, false 1448 cmpl %eax, %ebx 1449 POP eax // restore eax from the push in the beginning of READ_BARRIER macro 1450 // This asymmetric push/pop saves a push of eax and maintains stack alignment. 1451#elif defined(USE_HEAP_POISONING) 1452 PUSH eax // save eax 1453 movl MIRROR_OBJECT_CLASS_OFFSET(%edx), %eax 1454 UNPOISON_HEAP_REF eax 1455 cmpl %eax, %ebx 1456 POP eax // restore eax 1457#else 1458 cmpl MIRROR_OBJECT_CLASS_OFFSET(%edx), %ebx 1459#endif 1460 jne .Lcheck_assignability 1461.Ldo_aput: 1462 POISON_HEAP_REF edx 1463 movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) 1464 movl %fs:THREAD_CARD_TABLE_OFFSET, %edx 1465 shrl LITERAL(CARD_TABLE_CARD_SHIFT), %eax 1466 movb %dl, (%edx, %eax) 1467 ret 1468.Ldo_aput_null: 1469 movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) 1470 ret 1471.Lcheck_assignability: 1472 PUSH eax // save arguments 1473 PUSH ecx 1474 PUSH edx 1475#if defined(USE_READ_BARRIER) 1476 subl LITERAL(4), %esp // alignment padding 1477 CFI_ADJUST_CFA_OFFSET(4) 1478 READ_BARRIER edx, MIRROR_OBJECT_CLASS_OFFSET, eax, true 1479 subl LITERAL(4), %esp // alignment padding 1480 CFI_ADJUST_CFA_OFFSET(4) 1481 PUSH eax // pass arg2 - type of the value to be stored 1482#elif defined(USE_HEAP_POISONING) 1483 subl LITERAL(8), %esp // alignment padding 1484 CFI_ADJUST_CFA_OFFSET(8) 1485 movl MIRROR_OBJECT_CLASS_OFFSET(%edx), %eax 1486 UNPOISON_HEAP_REF eax 1487 PUSH eax // pass arg2 - type of the value to be stored 1488#else 1489 subl LITERAL(8), %esp // alignment padding 1490 CFI_ADJUST_CFA_OFFSET(8) 1491 pushl MIRROR_OBJECT_CLASS_OFFSET(%edx) // pass arg2 - type of the value to be stored 1492 CFI_ADJUST_CFA_OFFSET(4) 1493#endif 1494 PUSH ebx // pass arg1 - component type of the array 1495 call SYMBOL(artIsAssignableFromCode) // (Class* a, Class* b) 1496 addl LITERAL(16), %esp // pop arguments 1497 CFI_ADJUST_CFA_OFFSET(-16) 1498 testl %eax, %eax 1499 jz .Lthrow_array_store_exception 1500 POP edx 1501 POP ecx 1502 POP eax 1503 POISON_HEAP_REF edx 1504 movl %edx, MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) // do the aput 1505 movl %fs:THREAD_CARD_TABLE_OFFSET, %edx 1506 shrl LITERAL(CARD_TABLE_CARD_SHIFT), %eax 1507 movb %dl, (%edx, %eax) 1508 ret 1509 CFI_ADJUST_CFA_OFFSET(12) // 3 POP after the jz for unwinding. 1510.Lthrow_array_store_exception: 1511 POP edx 1512 POP ecx 1513 POP eax 1514 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save all registers as basis for long jump context 1515 // Outgoing argument set up 1516 PUSH eax // alignment padding 1517 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1518 CFI_ADJUST_CFA_OFFSET(4) 1519 PUSH edx // pass arg2 - value 1520 PUSH eax // pass arg1 - array 1521 call SYMBOL(artThrowArrayStoreException) // (array, value, Thread*) 1522 UNREACHABLE 1523END_FUNCTION art_quick_aput_obj 1524 1525DEFINE_FUNCTION art_quick_memcpy 1526 SETUP_GOT_NOSAVE ebx // clobbers EBX 1527 PUSH edx // pass arg3 1528 PUSH ecx // pass arg2 1529 PUSH eax // pass arg1 1530 call PLT_SYMBOL(memcpy) // (void*, const void*, size_t) 1531 addl LITERAL(12), %esp // pop arguments 1532 CFI_ADJUST_CFA_OFFSET(-12) 1533 ret 1534END_FUNCTION art_quick_memcpy 1535 1536DEFINE_FUNCTION art_quick_test_suspend 1537 SETUP_SAVE_EVERYTHING_FRAME ebx, ebx, RUNTIME_SAVE_EVERYTHING_FOR_SUSPEND_CHECK_METHOD_OFFSET // save everything for GC 1538 // Outgoing argument set up 1539 subl MACRO_LITERAL(12), %esp // push padding 1540 CFI_ADJUST_CFA_OFFSET(12) 1541 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1542 CFI_ADJUST_CFA_OFFSET(4) 1543 call SYMBOL(artTestSuspendFromCode) // (Thread*) 1544 addl MACRO_LITERAL(16), %esp // pop arguments 1545 CFI_ADJUST_CFA_OFFSET(-16) 1546 RESTORE_SAVE_EVERYTHING_FRAME // restore frame up to return address 1547 ret // return 1548END_FUNCTION art_quick_test_suspend 1549 1550DEFINE_FUNCTION art_quick_d2l 1551 subl LITERAL(12), %esp // alignment padding, room for argument 1552 CFI_ADJUST_CFA_OFFSET(12) 1553 movsd %xmm0, 0(%esp) // arg a 1554 call SYMBOL(art_d2l) // (jdouble a) 1555 addl LITERAL(12), %esp // pop arguments 1556 CFI_ADJUST_CFA_OFFSET(-12) 1557 ret 1558END_FUNCTION art_quick_d2l 1559 1560DEFINE_FUNCTION art_quick_f2l 1561 subl LITERAL(12), %esp // alignment padding 1562 CFI_ADJUST_CFA_OFFSET(12) 1563 movss %xmm0, 0(%esp) // arg a 1564 call SYMBOL(art_f2l) // (jfloat a) 1565 addl LITERAL(12), %esp // pop arguments 1566 CFI_ADJUST_CFA_OFFSET(-12) 1567 ret 1568END_FUNCTION art_quick_f2l 1569 1570DEFINE_FUNCTION art_quick_ldiv 1571 subl LITERAL(12), %esp // alignment padding 1572 CFI_ADJUST_CFA_OFFSET(12) 1573 PUSH ebx // pass arg4 b.hi 1574 PUSH edx // pass arg3 b.lo 1575 PUSH ecx // pass arg2 a.hi 1576 PUSH eax // pass arg1 a.lo 1577 call SYMBOL(artLdiv) // (jlong a, jlong b) 1578 addl LITERAL(28), %esp // pop arguments 1579 CFI_ADJUST_CFA_OFFSET(-28) 1580 ret 1581END_FUNCTION art_quick_ldiv 1582 1583DEFINE_FUNCTION art_quick_lmod 1584 subl LITERAL(12), %esp // alignment padding 1585 CFI_ADJUST_CFA_OFFSET(12) 1586 PUSH ebx // pass arg4 b.hi 1587 PUSH edx // pass arg3 b.lo 1588 PUSH ecx // pass arg2 a.hi 1589 PUSH eax // pass arg1 a.lo 1590 call SYMBOL(artLmod) // (jlong a, jlong b) 1591 addl LITERAL(28), %esp // pop arguments 1592 CFI_ADJUST_CFA_OFFSET(-28) 1593 ret 1594END_FUNCTION art_quick_lmod 1595 1596DEFINE_FUNCTION art_quick_lmul 1597 imul %eax, %ebx // ebx = a.lo(eax) * b.hi(ebx) 1598 imul %edx, %ecx // ecx = b.lo(edx) * a.hi(ecx) 1599 mul %edx // edx:eax = a.lo(eax) * b.lo(edx) 1600 add %ebx, %ecx 1601 add %ecx, %edx // edx += (a.lo * b.hi) + (b.lo * a.hi) 1602 ret 1603END_FUNCTION art_quick_lmul 1604 1605DEFINE_FUNCTION art_quick_lshl 1606 // ecx:eax << edx 1607 xchg %edx, %ecx 1608 shld %cl,%eax,%edx 1609 shl %cl,%eax 1610 test LITERAL(32), %cl 1611 jz 1f 1612 mov %eax, %edx 1613 xor %eax, %eax 16141: 1615 ret 1616END_FUNCTION art_quick_lshl 1617 1618DEFINE_FUNCTION art_quick_lshr 1619 // ecx:eax >> edx 1620 xchg %edx, %ecx 1621 shrd %cl,%edx,%eax 1622 sar %cl,%edx 1623 test LITERAL(32),%cl 1624 jz 1f 1625 mov %edx, %eax 1626 sar LITERAL(31), %edx 16271: 1628 ret 1629END_FUNCTION art_quick_lshr 1630 1631DEFINE_FUNCTION art_quick_lushr 1632 // ecx:eax >>> edx 1633 xchg %edx, %ecx 1634 shrd %cl,%edx,%eax 1635 shr %cl,%edx 1636 test LITERAL(32),%cl 1637 jz 1f 1638 mov %edx, %eax 1639 xor %edx, %edx 16401: 1641 ret 1642END_FUNCTION art_quick_lushr 1643 1644// Note: Functions `art{Get,Set}<Kind>{Static,Instance}FromCompiledCode` are 1645// defined with a macro in runtime/entrypoints/quick/quick_field_entrypoints.cc. 1646 1647ONE_ARG_REF_DOWNCALL art_quick_get_boolean_static, artGetBooleanStaticFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1648ONE_ARG_REF_DOWNCALL art_quick_get_byte_static, artGetByteStaticFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1649ONE_ARG_REF_DOWNCALL art_quick_get_char_static, artGetCharStaticFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1650ONE_ARG_REF_DOWNCALL art_quick_get_short_static, artGetShortStaticFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1651ONE_ARG_REF_DOWNCALL art_quick_get32_static, artGet32StaticFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1652ONE_ARG_REF_DOWNCALL art_quick_get64_static, artGet64StaticFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1653ONE_ARG_REF_DOWNCALL art_quick_get_obj_static, artGetObjStaticFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1654 1655TWO_ARG_REF_DOWNCALL art_quick_get_boolean_instance, artGetBooleanInstanceFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1656TWO_ARG_REF_DOWNCALL art_quick_get_byte_instance, artGetByteInstanceFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1657TWO_ARG_REF_DOWNCALL art_quick_get_char_instance, artGetCharInstanceFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1658TWO_ARG_REF_DOWNCALL art_quick_get_short_instance, artGetShortInstanceFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1659TWO_ARG_REF_DOWNCALL art_quick_get32_instance, artGet32InstanceFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1660TWO_ARG_REF_DOWNCALL art_quick_get64_instance, artGet64InstanceFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1661TWO_ARG_REF_DOWNCALL art_quick_get_obj_instance, artGetObjInstanceFromCompiledCode, RETURN_OR_DELIVER_PENDING_EXCEPTION 1662 1663TWO_ARG_REF_DOWNCALL art_quick_set8_static, artSet8StaticFromCompiledCode, RETURN_IF_EAX_ZERO 1664TWO_ARG_REF_DOWNCALL art_quick_set16_static, artSet16StaticFromCompiledCode, RETURN_IF_EAX_ZERO 1665TWO_ARG_REF_DOWNCALL art_quick_set32_static, artSet32StaticFromCompiledCode, RETURN_IF_EAX_ZERO 1666TWO_ARG_REF_DOWNCALL art_quick_set_obj_static, artSetObjStaticFromCompiledCode, RETURN_IF_EAX_ZERO 1667 1668THREE_ARG_REF_DOWNCALL art_quick_set64_static, artSet64StaticFromCompiledCode, RETURN_IF_EAX_ZERO 1669THREE_ARG_REF_DOWNCALL art_quick_set8_instance, artSet8InstanceFromCompiledCode, RETURN_IF_EAX_ZERO 1670THREE_ARG_REF_DOWNCALL art_quick_set16_instance, artSet16InstanceFromCompiledCode, RETURN_IF_EAX_ZERO 1671THREE_ARG_REF_DOWNCALL art_quick_set32_instance, artSet32InstanceFromCompiledCode, RETURN_IF_EAX_ZERO 1672THREE_ARG_REF_DOWNCALL art_quick_set_obj_instance, artSetObjInstanceFromCompiledCode, RETURN_IF_EAX_ZERO 1673 1674// Call artSet64InstanceFromCode with 4 word size arguments. 1675DEFINE_FUNCTION art_quick_set64_instance 1676 movd %ebx, %xmm0 1677 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 1678 movd %xmm0, %ebx 1679 // Outgoing argument set up 1680 subl LITERAL(12), %esp // alignment padding 1681 CFI_ADJUST_CFA_OFFSET(12) 1682 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1683 CFI_ADJUST_CFA_OFFSET(4) 1684 PUSH ebx // pass high half of new_val 1685 PUSH edx // pass low half of new_val 1686 PUSH ecx // pass object 1687 PUSH eax // pass field_idx 1688 call SYMBOL(artSet64InstanceFromCompiledCode) // (field_idx, Object*, new_val, Thread*) 1689 addl LITERAL(32), %esp // pop arguments 1690 CFI_ADJUST_CFA_OFFSET(-32) 1691 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 1692 RETURN_IF_EAX_ZERO // return or deliver exception 1693END_FUNCTION art_quick_set64_instance 1694 1695DEFINE_FUNCTION art_quick_proxy_invoke_handler 1696 SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_EAX 1697 PUSH esp // pass SP 1698 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1699 CFI_ADJUST_CFA_OFFSET(4) 1700 PUSH ecx // pass receiver 1701 PUSH eax // pass proxy method 1702 call SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP) 1703 movd %eax, %xmm0 // place return value also into floating point return value 1704 movd %edx, %xmm1 1705 punpckldq %xmm1, %xmm0 1706 addl LITERAL(16 + FRAME_SIZE_SAVE_REFS_AND_ARGS - FRAME_SIZE_SAVE_REFS_ONLY), %esp 1707 CFI_ADJUST_CFA_OFFSET(-(16 + FRAME_SIZE_SAVE_REFS_AND_ARGS - FRAME_SIZE_SAVE_REFS_ONLY)) 1708 RESTORE_SAVE_REFS_ONLY_FRAME 1709 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1710END_FUNCTION art_quick_proxy_invoke_handler 1711 1712 /* 1713 * Called to resolve an imt conflict. 1714 * eax is the conflict ArtMethod. 1715 * xmm7 is a hidden argument that holds the target interface method's dex method index. 1716 * 1717 * Note that this stub writes to eax. 1718 * Because of lack of free registers, it also saves and restores edi. 1719 */ 1720DEFINE_FUNCTION art_quick_imt_conflict_trampoline 1721 PUSH EDI 1722 PUSH ESI 1723 PUSH EDX 1724 movl 16(%esp), %edi // Load referrer. 1725 movd %xmm7, %esi // Get target method index stored in xmm7, remember it in ESI. 1726 // If the method is obsolete, just go through the dex cache miss slow path. 1727 // The obsolete flag is set with suspended threads, so we do not need an acquire operation here. 1728 testl LITERAL(ACC_OBSOLETE_METHOD), ART_METHOD_ACCESS_FLAGS_OFFSET(%edi) 1729 jnz .Limt_conflict_trampoline_dex_cache_miss 1730 movl ART_METHOD_DECLARING_CLASS_OFFSET(%edi), %edi // Load declaring class (no read barrier). 1731 movl MIRROR_CLASS_DEX_CACHE_OFFSET(%edi), %edi // Load the DexCache (without read barrier). 1732 UNPOISON_HEAP_REF edi 1733 movl MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET(%edi), %edi // Load the resolved methods. 1734 pushl ART_METHOD_JNI_OFFSET_32(%eax) // Push ImtConflictTable. 1735 CFI_ADJUST_CFA_OFFSET(4) 1736 movl %esi, %eax // Copy the method index from ESI. 1737 andl LITERAL(METHOD_DEX_CACHE_SIZE_MINUS_ONE), %eax // Calculate DexCache method slot index. 1738 leal 0(%edi, %eax, 2 * __SIZEOF_POINTER__), %edi // Load DexCache method slot address. 1739 mov %ecx, %edx // Make EDX:EAX == ECX:EBX so that LOCK CMPXCHG8B makes no changes. 1740 mov %ebx, %eax // (The actual value does not matter.) 1741 lock cmpxchg8b (%edi) // Relaxed atomic load EDX:EAX from the dex cache slot. 1742 popl %edi // Pop ImtConflictTable. 1743 CFI_ADJUST_CFA_OFFSET(-4) 1744 cmp %edx, %esi // Compare method index to see if we had a DexCache method hit. 1745 jne .Limt_conflict_trampoline_dex_cache_miss 1746.Limt_table_iterate: 1747 cmpl %eax, 0(%edi) 1748 jne .Limt_table_next_entry 1749 // We successfully hit an entry in the table. Load the target method 1750 // and jump to it. 1751 movl __SIZEOF_POINTER__(%edi), %eax 1752 CFI_REMEMBER_STATE 1753 POP EDX 1754 POP ESI 1755 POP EDI 1756 jmp *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) 1757 CFI_RESTORE_STATE_AND_DEF_CFA(esp, 16) 1758.Limt_table_next_entry: 1759 // If the entry is null, the interface method is not in the ImtConflictTable. 1760 cmpl LITERAL(0), 0(%edi) 1761 jz .Lconflict_trampoline 1762 // Iterate over the entries of the ImtConflictTable. 1763 addl LITERAL(2 * __SIZEOF_POINTER__), %edi 1764 jmp .Limt_table_iterate 1765.Lconflict_trampoline: 1766 // Call the runtime stub to populate the ImtConflictTable and jump to the 1767 // resolved method. 1768 CFI_REMEMBER_STATE 1769 POP EDX 1770 POP ESI 1771 POP EDI 1772 INVOKE_TRAMPOLINE_BODY artInvokeInterfaceTrampoline 1773 CFI_RESTORE_STATE_AND_DEF_CFA(esp, 16) 1774.Limt_conflict_trampoline_dex_cache_miss: 1775 // We're not creating a proper runtime method frame here, 1776 // artLookupResolvedMethod() is not allowed to walk the stack. 1777 1778 // Save core register args; EDX is already saved. 1779 PUSH ebx 1780 PUSH ecx 1781 1782 // Save FPR args. 1783 subl MACRO_LITERAL(32), %esp 1784 CFI_ADJUST_CFA_OFFSET(32) 1785 movsd %xmm0, 0(%esp) 1786 movsd %xmm1, 8(%esp) 1787 movsd %xmm2, 16(%esp) 1788 movsd %xmm3, 24(%esp) 1789 1790 pushl 32+8+16(%esp) // Pass referrer. 1791 CFI_ADJUST_CFA_OFFSET(4) 1792 pushl %esi // Pass method index. 1793 CFI_ADJUST_CFA_OFFSET(4) 1794 call SYMBOL(artLookupResolvedMethod) // (uint32_t method_index, ArtMethod* referrer) 1795 addl LITERAL(8), %esp // Pop arguments. 1796 CFI_ADJUST_CFA_OFFSET(-8) 1797 1798 // Restore FPR args. 1799 movsd 0(%esp), %xmm0 1800 movsd 8(%esp), %xmm1 1801 movsd 16(%esp), %xmm2 1802 movsd 24(%esp), %xmm3 1803 addl MACRO_LITERAL(32), %esp 1804 CFI_ADJUST_CFA_OFFSET(-32) 1805 1806 // Restore core register args. 1807 POP ecx 1808 POP ebx 1809 1810 cmp LITERAL(0), %eax // If the method wasn't resolved, 1811 je .Lconflict_trampoline // skip the lookup and go to artInvokeInterfaceTrampoline(). 1812 jmp .Limt_table_iterate 1813END_FUNCTION art_quick_imt_conflict_trampoline 1814 1815DEFINE_FUNCTION art_quick_resolution_trampoline 1816 SETUP_SAVE_REFS_AND_ARGS_FRAME ebx, ebx 1817 movl %esp, %edi 1818 PUSH EDI // pass SP. do not just PUSH ESP; that messes up unwinding 1819 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1820 CFI_ADJUST_CFA_OFFSET(4) 1821 PUSH ecx // pass receiver 1822 PUSH eax // pass method 1823 call SYMBOL(artQuickResolutionTrampoline) // (Method* called, receiver, Thread*, SP) 1824 movl %eax, %edi // remember code pointer in EDI 1825 addl LITERAL(16), %esp // pop arguments 1826 CFI_ADJUST_CFA_OFFSET(-16) 1827 test %eax, %eax // if code pointer is null goto deliver pending exception 1828 jz 1f 1829 RESTORE_SAVE_REFS_AND_ARGS_FRAME_AND_JUMP 18301: 1831 RESTORE_SAVE_REFS_AND_ARGS_FRAME 1832 DELIVER_PENDING_EXCEPTION 1833END_FUNCTION art_quick_resolution_trampoline 1834 1835DEFINE_FUNCTION art_quick_generic_jni_trampoline 1836 SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_EAX 1837 movl %esp, %ebp // save SP at callee-save frame 1838 CFI_DEF_CFA_REGISTER(ebp) 1839 subl LITERAL(5120), %esp 1840 // prepare for artQuickGenericJniTrampoline call 1841 // (Thread*, managed_sp, reserved_area) 1842 // (esp) 4(esp) 8(esp) <= C calling convention 1843 // fs:... ebp esp <= where they are 1844 1845 movl %esp, %eax 1846 subl LITERAL(4), %esp // Padding for 16B alignment. 1847 pushl %eax // Pass reserved area. 1848 pushl %ebp // Pass managed frame SP. 1849 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1850 call SYMBOL(artQuickGenericJniTrampoline) // (Thread*, sp) 1851 1852 // The C call will have registered the complete save-frame on success. 1853 // The result of the call is: 1854 // eax: pointer to native code, 0 on error. 1855 // The bottom of the reserved area contains values for arg registers, 1856 // hidden arg register and SP for out args for the call. 1857 1858 // Check for error (class init check or locking for synchronized native method can throw). 1859 test %eax, %eax 1860 jz .Lexception_in_native 1861 1862 // On x86 there are no registers passed, so no native call args to pop here. 1863 1864 // Save code pointer in EDX. 1865 movl %eax, %edx 1866 // Load hidden arg (EAX) for @CriticalNative. 1867 movl 16(%esp), %eax 1868 // Load SP for out args, releasing unneeded reserved area. 1869 movl 20(%esp), %esp 1870 1871 // Native call. 1872 call *%edx 1873 1874 // result sign extension is handled in C code 1875 // prepare for artQuickGenericJniEndTrampoline call 1876 // (Thread*, result, result_f) 1877 // (esp) 4(esp) 12(esp) <= C calling convention 1878 // fs:... eax:edx fp0 <= where they are 1879 1880 subl LITERAL(20), %esp // Padding & pass float result. 1881 fstpl (%esp) 1882 pushl %edx // Pass int result. 1883 pushl %eax 1884 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1885 call SYMBOL(artQuickGenericJniEndTrampoline) 1886 1887 // Pending exceptions possible. 1888 mov %fs:THREAD_EXCEPTION_OFFSET, %ebx 1889 testl %ebx, %ebx 1890 jnz .Lexception_in_native 1891 1892 // Tear down the alloca. 1893 movl %ebp, %esp 1894 CFI_DEF_CFA_REGISTER(esp) 1895 1896 1897 // Tear down the callee-save frame. 1898 // Remove space for FPR args and EAX 1899 addl LITERAL(4 + 4 * 8), %esp 1900 CFI_ADJUST_CFA_OFFSET(-(4 + 4 * 8)) 1901 1902 POP ecx 1903 addl LITERAL(4), %esp // Avoid edx, as it may be part of the result. 1904 CFI_ADJUST_CFA_OFFSET(-4) 1905 POP ebx 1906 POP ebp // Restore callee saves 1907 POP esi 1908 POP edi 1909 // Quick expects the return value to be in xmm0. 1910 movd %eax, %xmm0 1911 movd %edx, %xmm1 1912 punpckldq %xmm1, %xmm0 1913 ret 1914.Lexception_in_native: 1915 pushl %fs:THREAD_TOP_QUICK_FRAME_OFFSET 1916 addl LITERAL(-1), (%esp) // Remove the GenericJNI tag. 1917 movl (%esp), %esp 1918 // Do a call to push a new save-all frame required by the runtime. 1919 call .Lexception_call 1920.Lexception_call: 1921 DELIVER_PENDING_EXCEPTION 1922END_FUNCTION art_quick_generic_jni_trampoline 1923 1924DEFINE_FUNCTION art_quick_to_interpreter_bridge 1925 SETUP_SAVE_REFS_AND_ARGS_FRAME ebx, ebx // save frame 1926 mov %esp, %edx // remember SP 1927 PUSH eax // alignment padding 1928 PUSH edx // pass SP 1929 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1930 CFI_ADJUST_CFA_OFFSET(4) 1931 PUSH eax // pass method 1932 call SYMBOL(artQuickToInterpreterBridge) // (method, Thread*, SP) 1933 addl LITERAL(16), %esp // pop arguments 1934 CFI_ADJUST_CFA_OFFSET(-16) 1935 1936 // Return eax:edx in xmm0 also. 1937 movd %eax, %xmm0 1938 movd %edx, %xmm1 1939 punpckldq %xmm1, %xmm0 1940 1941 addl LITERAL(48), %esp // Remove FPRs and EAX, ECX, EDX, EBX. 1942 CFI_ADJUST_CFA_OFFSET(-48) 1943 1944 POP ebp // Restore callee saves 1945 POP esi 1946 POP edi 1947 1948 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1949END_FUNCTION art_quick_to_interpreter_bridge 1950 1951 /* 1952 * Called by managed code, saves callee saves and then calls artInvokeObsoleteMethod 1953 */ 1954ONE_ARG_RUNTIME_EXCEPTION art_invoke_obsolete_method_stub, artInvokeObsoleteMethod 1955 1956 /* 1957 * Routine that intercepts method calls and returns. 1958 */ 1959DEFINE_FUNCTION art_quick_instrumentation_entry 1960 SETUP_SAVE_REFS_AND_ARGS_FRAME ebx, edx 1961 PUSH eax // Save eax which will be clobbered by the callee-save method. 1962 subl LITERAL(16), %esp // Align stack (12 bytes) and reserve space for the SP argument 1963 CFI_ADJUST_CFA_OFFSET(16) // (4 bytes). We lack the scratch registers to calculate the SP 1964 // right now, so we will just fill it in later. 1965 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1966 CFI_ADJUST_CFA_OFFSET(4) 1967 PUSH ecx // Pass receiver. 1968 PUSH eax // Pass Method*. 1969 leal 32(%esp), %eax // Put original SP into eax 1970 movl %eax, 12(%esp) // set SP 1971 call SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Object*, Thread*, SP) 1972 1973 addl LITERAL(28), %esp // Pop arguments upto saved Method*. 1974 CFI_ADJUST_CFA_OFFSET(-28) 1975 1976 testl %eax, %eax 1977 jz 1f // Test for null return (indicating exception) and handle it. 1978 1979 movl 60(%esp), %edi // Restore edi. 1980 movl %eax, 60(%esp) // Place code* over edi, just under return pc. 1981 movl SYMBOL(art_quick_instrumentation_exit)@GOT(%ebx), %ebx 1982 // Place instrumentation exit as return pc. ebx holds the GOT computed on entry. 1983 movl %ebx, 64(%esp) 1984 movl 0(%esp), %eax // Restore eax. 1985 // Restore FPRs (extra 4 bytes of offset due to EAX push at top). 1986 movsd 8(%esp), %xmm0 1987 movsd 16(%esp), %xmm1 1988 movsd 24(%esp), %xmm2 1989 movsd 32(%esp), %xmm3 1990 1991 // Restore GPRs. 1992 movl 40(%esp), %ecx // Restore ecx. 1993 movl 44(%esp), %edx // Restore edx. 1994 movl 48(%esp), %ebx // Restore ebx. 1995 movl 52(%esp), %ebp // Restore ebp. 1996 movl 56(%esp), %esi // Restore esi. 1997 addl LITERAL(60), %esp // Wind stack back upto code*. 1998 CFI_ADJUST_CFA_OFFSET(-60) 1999 ret // Call method (and pop). 20001: 2001 // Make caller handle exception 2002 addl LITERAL(4), %esp 2003 CFI_ADJUST_CFA_OFFSET(-4) 2004 RESTORE_SAVE_REFS_AND_ARGS_FRAME 2005 DELIVER_PENDING_EXCEPTION 2006END_FUNCTION art_quick_instrumentation_entry 2007 2008DEFINE_FUNCTION_CUSTOM_CFA art_quick_instrumentation_exit, 0 2009 pushl LITERAL(0) // Push a fake return PC as there will be none on the stack. 2010 CFI_ADJUST_CFA_OFFSET(4) 2011 SETUP_SAVE_EVERYTHING_FRAME ebx, ebx 2012 2013 movl %esp, %ecx // Remember SP 2014 subl LITERAL(8), %esp // Align stack. 2015 CFI_ADJUST_CFA_OFFSET(8) 2016 PUSH edx // Save gpr return value. edx and eax need to be together, 2017 // which isn't the case in kSaveEverything frame. 2018 PUSH eax 2019 leal 32(%esp), %eax // Get pointer to fpr_result, in kSaveEverything frame 2020 movl %esp, %edx // Get pointer to gpr_result 2021 PUSH eax // Pass fpr_result 2022 PUSH edx // Pass gpr_result 2023 PUSH ecx // Pass SP 2024 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current. 2025 CFI_ADJUST_CFA_OFFSET(4) 2026 2027 call SYMBOL(artInstrumentationMethodExitFromCode) // (Thread*, SP, gpr_result*, fpr_result*) 2028 // Return result could have been changed if it's a reference. 2029 movl 16(%esp), %ecx 2030 movl %ecx, (80+32)(%esp) 2031 addl LITERAL(32), %esp // Pop arguments and grp_result. 2032 CFI_ADJUST_CFA_OFFSET(-32) 2033 2034 testl %eax, %eax // Check if we returned error. 2035 jz .Ldo_deliver_instrumentation_exception 2036 testl %edx, %edx 2037 jnz .Ldeoptimize 2038 // Normal return. 2039 movl %eax, FRAME_SIZE_SAVE_EVERYTHING-4(%esp) // Set return pc. 2040 RESTORE_SAVE_EVERYTHING_FRAME 2041 ret 2042.Ldeoptimize: 2043 mov %edx, (FRAME_SIZE_SAVE_EVERYTHING-4)(%esp) // Set return pc. 2044 RESTORE_SAVE_EVERYTHING_FRAME 2045 jmp SYMBOL(art_quick_deoptimize) 2046.Ldo_deliver_instrumentation_exception: 2047 DELIVER_PENDING_EXCEPTION_FRAME_READY 2048END_FUNCTION art_quick_instrumentation_exit 2049 2050 /* 2051 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization 2052 * will long jump to the upcall with a special exception of -1. 2053 */ 2054DEFINE_FUNCTION art_quick_deoptimize 2055 SETUP_SAVE_EVERYTHING_FRAME ebx, ebx 2056 subl LITERAL(12), %esp // Align stack. 2057 CFI_ADJUST_CFA_OFFSET(12) 2058 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 2059 CFI_ADJUST_CFA_OFFSET(4) 2060 call SYMBOL(artDeoptimize) // (Thread*) 2061 UNREACHABLE 2062END_FUNCTION art_quick_deoptimize 2063 2064 /* 2065 * Compiled code has requested that we deoptimize into the interpreter. The deoptimization 2066 * will long jump to the interpreter bridge. 2067 */ 2068DEFINE_FUNCTION art_quick_deoptimize_from_compiled_code 2069 SETUP_SAVE_EVERYTHING_FRAME ebx, ebx 2070 subl LITERAL(8), %esp // Align stack. 2071 CFI_ADJUST_CFA_OFFSET(8) 2072 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 2073 CFI_ADJUST_CFA_OFFSET(4) 2074 PUSH eax 2075 call SYMBOL(artDeoptimizeFromCompiledCode) // (DeoptimizationKind, Thread*) 2076 UNREACHABLE 2077END_FUNCTION art_quick_deoptimize_from_compiled_code 2078 2079 /* 2080 * String's compareTo. 2081 * 2082 * On entry: 2083 * eax: this string object (known non-null) 2084 * ecx: comp string object (known non-null) 2085 */ 2086DEFINE_FUNCTION art_quick_string_compareto 2087 PUSH esi // push callee save reg 2088 PUSH edi // push callee save reg 2089 mov MIRROR_STRING_COUNT_OFFSET(%eax), %edx 2090 mov MIRROR_STRING_COUNT_OFFSET(%ecx), %ebx 2091 lea MIRROR_STRING_VALUE_OFFSET(%eax), %esi 2092 lea MIRROR_STRING_VALUE_OFFSET(%ecx), %edi 2093#if (STRING_COMPRESSION_FEATURE) 2094 /* Differ cases */ 2095 shrl LITERAL(1), %edx 2096 jnc .Lstring_compareto_this_is_compressed 2097 shrl LITERAL(1), %ebx 2098 jnc .Lstring_compareto_that_is_compressed 2099 jmp .Lstring_compareto_both_not_compressed 2100.Lstring_compareto_this_is_compressed: 2101 shrl LITERAL(1), %ebx 2102 jnc .Lstring_compareto_both_compressed 2103 /* If (this->IsCompressed() && that->IsCompressed() == false) */ 2104 mov %edx, %eax 2105 subl %ebx, %eax 2106 mov %edx, %ecx 2107 cmovg %ebx, %ecx 2108 /* Going into loop to compare each character */ 2109 jecxz .Lstring_compareto_keep_length // check loop counter (if 0, don't compare) 2110.Lstring_compareto_loop_comparison_this_compressed: 2111 movzbl (%esi), %edx // move *(this_cur_char) byte to long 2112 movzwl (%edi), %ebx // move *(that_cur_char) word to long 2113 addl LITERAL(1), %esi // ++this_cur_char (8-bit) 2114 addl LITERAL(2), %edi // ++that_cur_char (16-bit) 2115 subl %ebx, %edx 2116 loope .Lstring_compareto_loop_comparison_this_compressed 2117 cmovne %edx, %eax // return eax = *(this_cur_char) - *(that_cur_char) 2118 jmp .Lstring_compareto_return 2119.Lstring_compareto_that_is_compressed: 2120 mov %edx, %eax 2121 subl %ebx, %eax 2122 mov %edx, %ecx 2123 cmovg %ebx, %ecx 2124 /* If (this->IsCompressed() == false && that->IsCompressed()) */ 2125 jecxz .Lstring_compareto_keep_length // check loop counter, if 0, don't compare 2126.Lstring_compareto_loop_comparison_that_compressed: 2127 movzwl (%esi), %edx // move *(this_cur_char) word to long 2128 movzbl (%edi), %ebx // move *(that_cur_char) byte to long 2129 addl LITERAL(2), %esi // ++this_cur_char (16-bit) 2130 addl LITERAL(1), %edi // ++that_cur_char (8-bit) 2131 subl %ebx, %edx 2132 loope .Lstring_compareto_loop_comparison_that_compressed 2133 cmovne %edx, %eax 2134 jmp .Lstring_compareto_return // return eax = *(this_cur_char) - *(that_cur_char) 2135.Lstring_compareto_both_compressed: 2136 /* Calculate min length and count diff */ 2137 mov %edx, %ecx 2138 mov %edx, %eax 2139 subl %ebx, %eax 2140 cmovg %ebx, %ecx 2141 jecxz .Lstring_compareto_keep_length 2142 repe cmpsb 2143 je .Lstring_compareto_keep_length 2144 movzbl -1(%esi), %eax // get last compared char from this string (8-bit) 2145 movzbl -1(%edi), %ecx // get last compared char from comp string (8-bit) 2146 jmp .Lstring_compareto_count_difference 2147#endif // STRING_COMPRESSION_FEATURE 2148.Lstring_compareto_both_not_compressed: 2149 /* Calculate min length and count diff */ 2150 mov %edx, %ecx 2151 mov %edx, %eax 2152 subl %ebx, %eax 2153 cmovg %ebx, %ecx 2154 /* 2155 * At this point we have: 2156 * eax: value to return if first part of strings are equal 2157 * ecx: minimum among the lengths of the two strings 2158 * esi: pointer to this string data 2159 * edi: pointer to comp string data 2160 */ 2161 jecxz .Lstring_compareto_keep_length 2162 repe cmpsw // find nonmatching chars in [%esi] and [%edi], up to length %ecx 2163 je .Lstring_compareto_keep_length 2164 movzwl -2(%esi), %eax // get last compared char from this string (16-bit) 2165 movzwl -2(%edi), %ecx // get last compared char from comp string (16-bit) 2166.Lstring_compareto_count_difference: 2167 subl %ecx, %eax 2168.Lstring_compareto_keep_length: 2169.Lstring_compareto_return: 2170 POP edi // pop callee save reg 2171 POP esi // pop callee save reg 2172 ret 2173END_FUNCTION art_quick_string_compareto 2174 2175DEFINE_FUNCTION art_quick_string_builder_append 2176 SETUP_SAVE_REFS_ONLY_FRAME ebx, ebx // save ref containing registers for GC 2177 // Outgoing argument set up 2178 leal FRAME_SIZE_SAVE_REFS_ONLY + __SIZEOF_POINTER__(%esp), %edi // prepare args 2179 push %eax // push padding 2180 CFI_ADJUST_CFA_OFFSET(4) 2181 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 2182 CFI_ADJUST_CFA_OFFSET(4) 2183 push %edi // pass args 2184 CFI_ADJUST_CFA_OFFSET(4) 2185 push %eax // pass format 2186 CFI_ADJUST_CFA_OFFSET(4) 2187 call SYMBOL(artStringBuilderAppend) // (uint32_t, const unit32_t*, Thread*) 2188 addl MACRO_LITERAL(16), %esp // pop arguments 2189 CFI_ADJUST_CFA_OFFSET(-16) 2190 RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address 2191 RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // return or deliver exception 2192END_FUNCTION art_quick_string_builder_append 2193 2194// Create a function `name` calling the ReadBarrier::Mark routine, 2195// getting its argument and returning its result through register 2196// `reg`, saving and restoring all caller-save registers. 2197// 2198// If `reg` is different from `eax`, the generated function follows a 2199// non-standard runtime calling convention: 2200// - register `reg` is used to pass the (sole) argument of this function 2201// (instead of EAX); 2202// - register `reg` is used to return the result of this function 2203// (instead of EAX); 2204// - EAX is treated like a normal (non-argument) caller-save register; 2205// - everything else is the same as in the standard runtime calling 2206// convention (e.g. standard callee-save registers are preserved). 2207MACRO2(READ_BARRIER_MARK_REG, name, reg) 2208 DEFINE_FUNCTION VAR(name) 2209 // Null check so that we can load the lock word. 2210 test REG_VAR(reg), REG_VAR(reg) 2211 jz .Lret_rb_\name 2212.Lnot_null_\name: 2213 // Check the mark bit, if it is 1 return. 2214 testl LITERAL(LOCK_WORD_MARK_BIT_MASK_SHIFTED), MIRROR_OBJECT_LOCK_WORD_OFFSET(REG_VAR(reg)) 2215 jz .Lslow_rb_\name 2216 ret 2217.Lslow_rb_\name: 2218 PUSH eax 2219 mov MIRROR_OBJECT_LOCK_WORD_OFFSET(REG_VAR(reg)), %eax 2220 add LITERAL(LOCK_WORD_STATE_FORWARDING_ADDRESS_OVERFLOW), %eax 2221 // Jump if overflow, the only case where it overflows should be the forwarding address one. 2222 // Taken ~25% of the time. 2223 jnae .Lret_forwarding_address\name 2224 2225 // Save all potentially live caller-save core registers. 2226 mov 0(%esp), %eax 2227 PUSH ecx 2228 PUSH edx 2229 PUSH ebx 2230 // 8-byte align the stack to improve (8-byte) XMM register saving and restoring. 2231 // and create space for caller-save floating-point registers. 2232 subl MACRO_LITERAL(4 + 8 * 8), %esp 2233 CFI_ADJUST_CFA_OFFSET(4 + 8 * 8) 2234 // Save all potentially live caller-save floating-point registers. 2235 movsd %xmm0, 0(%esp) 2236 movsd %xmm1, 8(%esp) 2237 movsd %xmm2, 16(%esp) 2238 movsd %xmm3, 24(%esp) 2239 movsd %xmm4, 32(%esp) 2240 movsd %xmm5, 40(%esp) 2241 movsd %xmm6, 48(%esp) 2242 movsd %xmm7, 56(%esp) 2243 2244 subl LITERAL(4), %esp // alignment padding 2245 CFI_ADJUST_CFA_OFFSET(4) 2246 PUSH RAW_VAR(reg) // pass arg1 - obj from `reg` 2247 call SYMBOL(artReadBarrierMark) // artReadBarrierMark(obj) 2248 .ifnc RAW_VAR(reg), eax 2249 movl %eax, REG_VAR(reg) // return result into `reg` 2250 .endif 2251 addl LITERAL(8), %esp // pop argument and remove padding 2252 CFI_ADJUST_CFA_OFFSET(-8) 2253 2254 // Restore floating-point registers. 2255 movsd 0(%esp), %xmm0 2256 movsd 8(%esp), %xmm1 2257 movsd 16(%esp), %xmm2 2258 movsd 24(%esp), %xmm3 2259 movsd 32(%esp), %xmm4 2260 movsd 40(%esp), %xmm5 2261 movsd 48(%esp), %xmm6 2262 movsd 56(%esp), %xmm7 2263 // Remove floating-point registers and padding. 2264 addl MACRO_LITERAL(8 * 8 + 4), %esp 2265 CFI_ADJUST_CFA_OFFSET(-(8 * 8 + 4)) 2266 // Restore core regs, except `reg`, as it is used to return the 2267 // result of this function (simply remove it from the stack instead). 2268 POP_REG_NE ebx, RAW_VAR(reg) 2269 POP_REG_NE edx, RAW_VAR(reg) 2270 POP_REG_NE ecx, RAW_VAR(reg) 2271 POP_REG_NE eax, RAW_VAR(reg) 2272.Lret_rb_\name: 2273 ret 2274.Lret_forwarding_address\name: 2275 // The overflow cleared the top bits. 2276 sall LITERAL(LOCK_WORD_STATE_FORWARDING_ADDRESS_SHIFT), %eax 2277 mov %eax, REG_VAR(reg) 2278 POP_REG_NE eax, RAW_VAR(reg) 2279 ret 2280 END_FUNCTION VAR(name) 2281END_MACRO 2282 2283READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg00, eax 2284READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg01, ecx 2285READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg02, edx 2286READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg03, ebx 2287READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg05, ebp 2288// Note: There is no art_quick_read_barrier_mark_reg04, as register 4 (ESP) 2289// cannot be used to pass arguments. 2290READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg06, esi 2291READ_BARRIER_MARK_REG art_quick_read_barrier_mark_reg07, edi 2292 2293DEFINE_FUNCTION art_quick_read_barrier_slow 2294 PUSH edx // pass arg3 - offset 2295 PUSH ecx // pass arg2 - obj 2296 PUSH eax // pass arg1 - ref 2297 call SYMBOL(artReadBarrierSlow) // artReadBarrierSlow(ref, obj, offset) 2298 addl LITERAL(12), %esp // pop arguments 2299 CFI_ADJUST_CFA_OFFSET(-12) 2300 ret 2301END_FUNCTION art_quick_read_barrier_slow 2302 2303DEFINE_FUNCTION art_quick_read_barrier_for_root_slow 2304 subl LITERAL(8), %esp // alignment padding 2305 CFI_ADJUST_CFA_OFFSET(8) 2306 PUSH eax // pass arg1 - root 2307 call SYMBOL(artReadBarrierForRootSlow) // artReadBarrierForRootSlow(root) 2308 addl LITERAL(12), %esp // pop argument and remove padding 2309 CFI_ADJUST_CFA_OFFSET(-12) 2310 ret 2311END_FUNCTION art_quick_read_barrier_for_root_slow 2312 2313 /* 2314 * On stack replacement stub. 2315 * On entry: 2316 * [sp] = return address 2317 * [sp + 4] = stack to copy 2318 * [sp + 8] = size of stack 2319 * [sp + 12] = pc to call 2320 * [sp + 16] = JValue* result 2321 * [sp + 20] = shorty 2322 * [sp + 24] = thread 2323 */ 2324DEFINE_FUNCTION art_quick_osr_stub 2325 // Save native callee saves. 2326 PUSH ebp 2327 PUSH ebx 2328 PUSH esi 2329 PUSH edi 2330 SAVE_SIZE=20 // 4 registers and the return address 2331 mov 4+16(%esp), %esi // ESI = argument array 2332 mov 8+16(%esp), %ecx // ECX = size of args 2333 mov 12+16(%esp), %ebx // EBX = pc to call 2334 mov %esp, %ebp // Save stack pointer 2335 CFI_DEF_CFA(ebp, SAVE_SIZE) // CFA = ebp + SAVE_SIZE 2336 CFI_REMEMBER_STATE 2337 andl LITERAL(0xFFFFFFF0), %esp // Align stack 2338 pushl %ebp // Save old stack pointer 2339 subl LITERAL(12), %esp // Align stack 2340 movl LITERAL(0), (%esp) // Store null for ArtMethod* slot 2341 // ebp isn't properly spilled in the osr method, so we need use DWARF expression. 2342 // NB: the CFI must be before the call since this is the address gdb will lookup. 2343 // NB: gdb expects that cfa_expression returns the CFA value (not address to it). 2344 CFI_ESCAPE( /* cfa = [sp + 12] + SAVE_SIZE */ \ 2345 0x0f, 6, /* DW_CFA_def_cfa_expression(len) */ \ 2346 0x92, 4, 12, /* DW_OP_bregx(reg,offset) */ \ 2347 0x06, /* DW_OP_deref */ \ 2348 0x23, SAVE_SIZE) /* DW_OP_plus_uconst(val) */ 2349 call .Losr_entry 2350 mov 12(%esp), %esp // Restore stack pointer. 2351 CFI_DEF_CFA(esp, SAVE_SIZE) // CFA = esp + SAVE_SIZE 2352 2353 // Restore callee saves. 2354 POP edi 2355 POP esi 2356 POP ebx 2357 POP ebp 2358 mov 16(%esp), %ecx // Get JValue result 2359 mov %eax, (%ecx) // Store the result. 2360 mov %edx, 4(%ecx) // Store the other half of the result. 2361 ret 2362.Losr_entry: 2363 CFI_RESTORE_STATE_AND_DEF_CFA(ebp, SAVE_SIZE) // CFA = ebp + SAVE_SIZE 2364 subl LITERAL(4), %ecx // Given stack size contains pushed frame pointer, substract it. 2365 subl %ecx, %esp 2366 mov %esp, %edi // EDI = beginning of stack 2367 rep movsb // while (ecx--) { *edi++ = *esi++ } 2368 jmp *%ebx 2369END_FUNCTION art_quick_osr_stub 2370 2371DEFINE_FUNCTION art_quick_invoke_polymorphic 2372 // On entry: EAX := unused, ECX := receiver 2373 SETUP_SAVE_REFS_AND_ARGS_FRAME ebx, ebx // Save frame. 2374 mov %esp, %edx // Remember SP 2375 sub LITERAL(4), %esp // Alignment padding 2376 CFI_ADJUST_CFA_OFFSET(4) 2377 push %edx // Push SP 2378 CFI_ADJUST_CFA_OFFSET(4) 2379 pushl %fs:THREAD_SELF_OFFSET // Push Thread::Current() 2380 CFI_ADJUST_CFA_OFFSET(4) 2381 push %ecx // Push receiver (method handle) 2382 CFI_ADJUST_CFA_OFFSET(4) 2383 call SYMBOL(artInvokePolymorphic) // invoke with (receiver, thread, SP) 2384 addl LITERAL(16), %esp // Pop arguments. 2385 CFI_ADJUST_CFA_OFFSET(-16) 2386 mov %eax, 4(%esp) // Result is in EAX:EDX. Copy to saved FP state. 2387 mov %edx, 8(%esp) 2388 mov %edx, 40(%esp) // Copy EDX to saved context 2389 RESTORE_SAVE_REFS_AND_ARGS_FRAME 2390 RETURN_OR_DELIVER_PENDING_EXCEPTION 2391END_FUNCTION art_quick_invoke_polymorphic 2392 2393DEFINE_FUNCTION art_quick_invoke_custom 2394 SETUP_SAVE_REFS_AND_ARGS_FRAME ebx, ebx // Save frame. 2395 // EAX := call_site_index 2396 mov %esp, %ecx // Remember SP. 2397 subl LITERAL(4), %esp // Alignment padding. 2398 CFI_ADJUST_CFA_OFFSET(4) 2399 push %ecx // pass SP 2400 CFI_ADJUST_CFA_OFFSET(4) 2401 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 2402 CFI_ADJUST_CFA_OFFSET(4) 2403 push %eax // pass call_site_index 2404 CFI_ADJUST_CFA_OFFSET(4) 2405 call SYMBOL(artInvokeCustom) // artInvokeCustom(call_site_index, Thread*, SP) 2406 addl LITERAL(16), %esp // Pop arguments. 2407 CFI_ADJUST_CFA_OFFSET(-16) 2408 mov %eax, 4(%esp) // Result is in EAX:EDX. Copy to saved FP state. 2409 mov %edx, 8(%esp) 2410 mov %edx, 40(%esp) // Copy EDX to saved context 2411 RESTORE_SAVE_REFS_AND_ARGS_FRAME 2412 RETURN_OR_DELIVER_PENDING_EXCEPTION 2413END_FUNCTION art_quick_invoke_custom 2414 2415// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. 2416// Argument 0: ESP+4: The context pointer for ExecuteSwitchImpl. 2417// Argument 1: ESP+8: Pointer to the templated ExecuteSwitchImpl to call. 2418// Argument 2: ESP+12: The value of DEX PC (memory address of the methods bytecode). 2419DEFINE_FUNCTION ExecuteSwitchImplAsm 2420 PUSH ebx // Spill EBX; Increments ESP, so arg0 is at ESP+8 now. 2421 mov 12(%esp), %eax // EAX = C++ templated interpreter function 2422 mov 16(%esp), %ebx // EBX = DEX PC (callee save register) 2423 mov 8(%esp), %ecx // ECX = Context argument for the function 2424 CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* EAX */, 3 /* EBX */, 0) 2425 2426 sub LITERAL(4), %esp // Alignment padding 2427 CFI_ADJUST_CFA_OFFSET(4) 2428 push %ecx // Push argument 2429 CFI_ADJUST_CFA_OFFSET(4) 2430 call *%eax // Call the wrapped function 2431 addl LITERAL(8), %esp 2432 CFI_ADJUST_CFA_OFFSET(-8) 2433 2434 POP ebx // Restore EBX 2435 ret 2436END_FUNCTION ExecuteSwitchImplAsm 2437 2438// On entry: eax is the class, ebp is the inline cache. 2439DEFINE_FUNCTION art_quick_update_inline_cache 2440#if (INLINE_CACHE_SIZE != 5) 2441#error "INLINE_CACHE_SIZE not as expected." 2442#endif 2443 // Don't update the cache if we are marking. 2444 cmpl LITERAL(0), %fs:THREAD_IS_GC_MARKING_OFFSET 2445 jnz .Lret 2446 PUSH ecx 2447 movl %eax, %ecx // eax will be used for cmpxchg 2448.Lentry1: 2449 movl INLINE_CACHE_CLASSES_OFFSET(%ebp), %eax 2450 cmpl %ecx, %eax 2451 je .Ldone 2452 cmpl LITERAL(0), %eax 2453 jne .Lentry2 2454 lock cmpxchg %ecx, INLINE_CACHE_CLASSES_OFFSET(%ebp) 2455 jz .Ldone 2456 jmp .Lentry1 2457.Lentry2: 2458 movl (INLINE_CACHE_CLASSES_OFFSET+4)(%ebp), %eax 2459 cmpl %ecx, %eax 2460 je .Ldone 2461 cmpl LITERAL(0), %eax 2462 jne .Lentry3 2463 lock cmpxchg %ecx, (INLINE_CACHE_CLASSES_OFFSET+4)(%ebp) 2464 jz .Ldone 2465 jmp .Lentry2 2466.Lentry3: 2467 movl (INLINE_CACHE_CLASSES_OFFSET+8)(%ebp), %eax 2468 cmpl %ecx, %eax 2469 je .Ldone 2470 cmpl LITERAL(0), %eax 2471 jne .Lentry4 2472 lock cmpxchg %ecx, (INLINE_CACHE_CLASSES_OFFSET+8)(%ebp) 2473 jz .Ldone 2474 jmp .Lentry3 2475.Lentry4: 2476 movl (INLINE_CACHE_CLASSES_OFFSET+12)(%ebp), %eax 2477 cmpl %ecx, %eax 2478 je .Ldone 2479 cmpl LITERAL(0), %eax 2480 jne .Lentry5 2481 lock cmpxchg %ecx, (INLINE_CACHE_CLASSES_OFFSET+12)(%ebp) 2482 jz .Ldone 2483 jmp .Lentry4 2484.Lentry5: 2485 // Unconditionally store, the cache is megamorphic. 2486 movl %ecx, (INLINE_CACHE_CLASSES_OFFSET+16)(%ebp) 2487.Ldone: 2488 // Restore registers 2489 movl %ecx, %eax 2490 POP ecx 2491.Lret: 2492 ret 2493END_FUNCTION art_quick_update_inline_cache 2494 2495 // TODO: implement these! 2496UNIMPLEMENTED art_quick_memcmp16 2497 2498// On entry, the method is at the bottom of the stack. 2499DEFINE_FUNCTION art_quick_compile_optimized 2500 SETUP_SAVE_EVERYTHING_FRAME ebx, ebx 2501 mov FRAME_SIZE_SAVE_EVERYTHING(%esp), %eax // Fetch ArtMethod 2502 sub LITERAL(8), %esp // Alignment padding 2503 CFI_ADJUST_CFA_OFFSET(8) 2504 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 2505 CFI_ADJUST_CFA_OFFSET(4) 2506 pushl %eax 2507 CFI_ADJUST_CFA_OFFSET(4) 2508 call SYMBOL(artCompileOptimized) // (ArtMethod*, Thread*) 2509 addl LITERAL(16), %esp // Pop arguments. 2510 CFI_ADJUST_CFA_OFFSET(-16) 2511 RESTORE_SAVE_EVERYTHING_FRAME 2512 ret 2513END_FUNCTION art_quick_compile_optimized 2514