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