quick_entrypoints_x86.S revision 88474b416eb257078e590bf9bc7957cee604a186
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 /* 20 * Macro that sets up the callee save frame to conform with 21 * Runtime::CreateCalleeSaveMethod(kSaveAll) 22 */ 23MACRO0(SETUP_SAVE_ALL_CALLEE_SAVE_FRAME) 24 PUSH edi // Save callee saves (ebx is saved/restored by the upcall) 25 PUSH esi 26 PUSH ebp 27 subl MACRO_LITERAL(16), %esp // Grow stack by 4 words, bottom word will hold Method* 28 .cfi_adjust_cfa_offset 16 29END_MACRO 30 31 /* 32 * Macro that sets up the callee save frame to conform with 33 * Runtime::CreateCalleeSaveMethod(kRefsOnly) 34 */ 35MACRO0(SETUP_REF_ONLY_CALLEE_SAVE_FRAME) 36 PUSH edi // Save callee saves (ebx is saved/restored by the upcall) 37 PUSH esi 38 PUSH ebp 39 subl MACRO_LITERAL(16), %esp // Grow stack by 4 words, bottom word will hold Method* 40 .cfi_adjust_cfa_offset 16 41END_MACRO 42 43MACRO0(RESTORE_REF_ONLY_CALLEE_SAVE_FRAME) 44 addl MACRO_LITERAL(16), %esp // Unwind stack up to return address 45 POP ebp // Restore callee saves (ebx is saved/restored by the upcall) 46 POP esi 47 POP edi 48 .cfi_adjust_cfa_offset -28 49END_MACRO 50 51 /* 52 * Macro that sets up the callee save frame to conform with 53 * Runtime::CreateCalleeSaveMethod(kRefsAndArgs) 54 */ 55MACRO0(SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME) 56 PUSH edi // Save callee saves 57 PUSH esi 58 PUSH ebp 59 PUSH ebx // Save args 60 PUSH edx 61 PUSH ecx 62 PUSH eax // Align stack, eax will be clobbered by Method* 63END_MACRO 64 65MACRO0(RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME) 66 addl MACRO_LITERAL(4), %esp // Remove padding 67 .cfi_adjust_cfa_offset -4 68 POP ecx // Restore args except eax 69 POP edx 70 POP ebx 71 POP ebp // Restore callee saves 72 POP esi 73 POP edi 74END_MACRO 75 76 /* 77 * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending 78 * exception is Thread::Current()->exception_. 79 */ 80MACRO0(DELIVER_PENDING_EXCEPTION) 81 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save callee saves for throw 82 mov %esp, %ecx 83 // Outgoing argument set up 84 subl MACRO_LITERAL(8), %esp // Alignment padding 85 .cfi_adjust_cfa_offset 8 86 PUSH ecx // pass SP 87 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 88 .cfi_adjust_cfa_offset 4 89 call SYMBOL(artDeliverPendingExceptionFromCode) // artDeliverPendingExceptionFromCode(Thread*, SP) 90 int3 // unreached 91END_MACRO 92 93MACRO2(NO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 94 DEFINE_FUNCTION VAR(c_name, 0) 95 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 96 mov %esp, %ecx 97 // Outgoing argument set up 98 subl MACRO_LITERAL(8), %esp // alignment padding 99 .cfi_adjust_cfa_offset 8 100 PUSH ecx // pass SP 101 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 102 .cfi_adjust_cfa_offset 4 103 call VAR(cxx_name, 1) // cxx_name(Thread*, SP) 104 int3 // unreached 105 END_FUNCTION VAR(c_name, 0) 106END_MACRO 107 108MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 109 DEFINE_FUNCTION VAR(c_name, 0) 110 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 111 mov %esp, %ecx 112 // Outgoing argument set up 113 PUSH eax // alignment padding 114 PUSH ecx // pass SP 115 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 116 .cfi_adjust_cfa_offset 4 117 PUSH eax // pass arg1 118 call VAR(cxx_name, 1) // cxx_name(arg1, Thread*, SP) 119 int3 // unreached 120 END_FUNCTION VAR(c_name, 0) 121END_MACRO 122 123MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name) 124 DEFINE_FUNCTION VAR(c_name, 0) 125 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 126 mov %esp, %edx 127 // Outgoing argument set up 128 PUSH edx // pass SP 129 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 130 .cfi_adjust_cfa_offset 4 131 PUSH ecx // pass arg2 132 PUSH eax // pass arg1 133 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*, SP) 134 int3 // unreached 135 END_FUNCTION VAR(c_name, 0) 136END_MACRO 137 138 /* 139 * Called by managed code to create and deliver a NullPointerException. 140 */ 141NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode 142 143 /* 144 * Called by managed code to create and deliver an ArithmeticException. 145 */ 146NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode 147 148 /* 149 * Called by managed code to create and deliver a StackOverflowError. 150 */ 151NO_ARG_RUNTIME_EXCEPTION art_quick_throw_stack_overflow, artThrowStackOverflowFromCode 152 153 /* 154 * Called by managed code, saves callee saves and then calls artThrowException 155 * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception. 156 */ 157ONE_ARG_RUNTIME_EXCEPTION art_quick_deliver_exception, artDeliverExceptionFromCode 158 159 /* 160 * Called by managed code to create and deliver a NoSuchMethodError. 161 */ 162ONE_ARG_RUNTIME_EXCEPTION art_quick_throw_no_such_method, artThrowNoSuchMethodFromCode 163 164 /* 165 * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds 166 * index, arg2 holds limit. 167 */ 168TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode 169 170 /* 171 * All generated callsites for interface invokes and invocation slow paths will load arguments 172 * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain 173 * the method_idx. This wrapper will save arg1-arg3, load the caller's Method*, align the 174 * stack and call the appropriate C helper. 175 * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1. 176 * 177 * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting 178 * of the target Method* in r0 and method->code_ in r1. 179 * 180 * If unsuccessful, the helper will return NULL/NULL. There will bea pending exception in the 181 * thread and we branch to another stub to deliver it. 182 * 183 * On success this wrapper will restore arguments and *jump* to the target, leaving the lr 184 * pointing back to the original caller. 185 */ 186MACRO2(INVOKE_TRAMPOLINE, c_name, cxx_name) 187 DEFINE_FUNCTION VAR(c_name, 0) 188 // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs) 189 // return address 190 PUSH edi 191 PUSH esi 192 PUSH ebp 193 PUSH ebx 194 PUSH edx 195 PUSH ecx 196 PUSH eax // <-- callee save Method* to go here 197 movl %esp, %edx // remember SP 198 // Outgoing argument set up 199 subl MACRO_LITERAL(12), %esp // alignment padding 200 .cfi_adjust_cfa_offset 12 201 PUSH edx // pass SP 202 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 203 .cfi_adjust_cfa_offset 4 204 pushl 32(%edx) // pass caller Method* 205 .cfi_adjust_cfa_offset 4 206 PUSH ecx // pass arg2 207 PUSH eax // pass arg1 208 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, Thread*, SP) 209 movl %edx, %edi // save code pointer in EDI 210 addl MACRO_LITERAL(36), %esp // Pop arguments skip eax 211 .cfi_adjust_cfa_offset -36 212 POP ecx // Restore args 213 POP edx 214 POP ebx 215 POP ebp // Restore callee saves. 216 POP esi 217 // Swap EDI callee save with code pointer. 218 xchgl %edi, (%esp) 219 testl %eax, %eax // Branch forward if exception pending. 220 jz 1f 221 // Tail call to intended method. 222 ret 2231: 224 addl MACRO_LITERAL(4), %esp // Pop code pointer off stack 225 .cfi_adjust_cfa_offset -4 226 DELIVER_PENDING_EXCEPTION 227 END_FUNCTION VAR(c_name, 0) 228END_MACRO 229 230INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline, artInvokeInterfaceTrampoline 231INVOKE_TRAMPOLINE art_quick_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck 232 233INVOKE_TRAMPOLINE art_quick_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck 234INVOKE_TRAMPOLINE art_quick_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck 235INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck 236INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck 237 238 /* 239 * Quick invocation stub. 240 * On entry: 241 * [sp] = return address 242 * [sp + 4] = method pointer 243 * [sp + 8] = argument array or NULL for no argument methods 244 * [sp + 12] = size of argument array in bytes 245 * [sp + 16] = (managed) thread pointer 246 * [sp + 20] = JValue* result 247 * [sp + 24] = result type char 248 */ 249DEFINE_FUNCTION art_quick_invoke_stub 250 PUSH ebp // save ebp 251 PUSH ebx // save ebx 252 mov %esp, %ebp // copy value of stack pointer into base pointer 253 .cfi_def_cfa_register ebp 254 mov 20(%ebp), %ebx // get arg array size 255 addl LITERAL(28), %ebx // reserve space for return addr, method*, ebx, and ebp in frame 256 andl LITERAL(0xFFFFFFF0), %ebx // align frame size to 16 bytes 257 subl LITERAL(12), %ebx // remove space for return address, ebx, and ebp 258 subl %ebx, %esp // reserve stack space for argument array 259 lea 4(%esp), %eax // use stack pointer + method ptr as dest for memcpy 260 pushl 20(%ebp) // push size of region to memcpy 261 pushl 16(%ebp) // push arg array as source of memcpy 262 pushl %eax // push stack pointer as destination of memcpy 263 call SYMBOL(memcpy) // (void*, const void*, size_t) 264 addl LITERAL(12), %esp // pop arguments to memcpy 265 movl LITERAL(0), (%esp) // store NULL for method* 266 mov 12(%ebp), %eax // move method pointer into eax 267 mov 4(%esp), %ecx // copy arg1 into ecx 268 mov 8(%esp), %edx // copy arg2 into edx 269 mov 12(%esp), %ebx // copy arg3 into ebx 270 call *METHOD_CODE_OFFSET(%eax) // call the method 271 mov %ebp, %esp // restore stack pointer 272 POP ebx // pop ebx 273 POP ebp // pop ebp 274 mov 20(%esp), %ecx // get result pointer 275 cmpl LITERAL(68), 24(%esp) // test if result type char == 'D' 276 je return_double_quick 277 cmpl LITERAL(70), 24(%esp) // test if result type char == 'F' 278 je return_float_quick 279 mov %eax, (%ecx) // store the result 280 mov %edx, 4(%ecx) // store the other half of the result 281 ret 282return_double_quick: 283return_float_quick: 284 movsd %xmm0, (%ecx) // store the floating point result 285 ret 286END_FUNCTION art_quick_invoke_stub 287 288MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 289 DEFINE_FUNCTION VAR(c_name, 0) 290 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 291 mov %esp, %edx // remember SP 292 // Outgoing argument set up 293 subl MACRO_LITERAL(8), %esp // push padding 294 .cfi_adjust_cfa_offset 8 295 PUSH edx // pass SP 296 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 297 .cfi_adjust_cfa_offset 4 298 call VAR(cxx_name, 1) // cxx_name(Thread*, SP) 299 addl MACRO_LITERAL(16), %esp // pop arguments 300 .cfi_adjust_cfa_offset -16 301 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 302 CALL_MACRO(return_macro, 2) // return or deliver exception 303 END_FUNCTION VAR(c_name, 0) 304END_MACRO 305 306MACRO3(ONE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 307 DEFINE_FUNCTION VAR(c_name, 0) 308 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 309 mov %esp, %edx // remember SP 310 // Outgoing argument set up 311 PUSH eax // push padding 312 PUSH edx // pass SP 313 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 314 .cfi_adjust_cfa_offset 4 315 PUSH eax // pass arg1 316 call VAR(cxx_name, 1) // cxx_name(arg1, Thread*, SP) 317 addl MACRO_LITERAL(16), %esp // pop arguments 318 .cfi_adjust_cfa_offset -16 319 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 320 CALL_MACRO(return_macro, 2) // return or deliver exception 321 END_FUNCTION VAR(c_name, 0) 322END_MACRO 323 324MACRO3(TWO_ARG_DOWNCALL, c_name, cxx_name, return_macro) 325 DEFINE_FUNCTION VAR(c_name, 0) 326 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 327 mov %esp, %edx // remember SP 328 // Outgoing argument set up 329 PUSH edx // pass SP 330 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 331 .cfi_adjust_cfa_offset 4 332 PUSH ecx // pass arg2 333 PUSH eax // pass arg1 334 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, Thread*, SP) 335 addl MACRO_LITERAL(16), %esp // pop arguments 336 .cfi_adjust_cfa_offset -16 337 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 338 CALL_MACRO(return_macro, 2) // return or deliver exception 339 END_FUNCTION VAR(c_name, 0) 340END_MACRO 341 342MACRO3(THREE_ARG_DOWNCALL, c_name, cxx_name, return_macro) 343 DEFINE_FUNCTION VAR(c_name, 0) 344 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 345 mov %esp, %ebx // remember SP 346 // Outgoing argument set up 347 subl MACRO_LITERAL(12), %esp // alignment padding 348 .cfi_adjust_cfa_offset 12 349 PUSH ebx // pass SP 350 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 351 .cfi_adjust_cfa_offset 4 352 PUSH edx // pass arg3 353 PUSH ecx // pass arg2 354 PUSH eax // pass arg1 355 call VAR(cxx_name, 1) // cxx_name(arg1, arg2, arg3, Thread*, SP) 356 addl MACRO_LITERAL(32), %esp // pop arguments 357 .cfi_adjust_cfa_offset -32 358 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 359 CALL_MACRO(return_macro, 2) // return or deliver exception 360 END_FUNCTION VAR(c_name, 0) 361END_MACRO 362 363MACRO0(RETURN_IF_EAX_NOT_ZERO) 364 testl %eax, %eax // eax == 0 ? 365 jz 1f // if eax == 0 goto 1 366 ret // return 3671: // deliver exception on current thread 368 DELIVER_PENDING_EXCEPTION 369END_MACRO 370 371MACRO0(RETURN_IF_EAX_ZERO) 372 testl %eax, %eax // eax == 0 ? 373 jnz 1f // if eax != 0 goto 1 374 ret // return 3751: // deliver exception on current thread 376 DELIVER_PENDING_EXCEPTION 377END_MACRO 378 379MACRO0(RETURN_OR_DELIVER_PENDING_EXCEPTION) 380 mov %fs:THREAD_EXCEPTION_OFFSET, %ebx // get exception field 381 testl %ebx, %ebx // ebx == 0 ? 382 jnz 1f // if ebx != 0 goto 1 383 ret // return 3841: // deliver exception on current thread 385 DELIVER_PENDING_EXCEPTION 386END_MACRO 387 388TWO_ARG_DOWNCALL art_quick_alloc_object, artAllocObjectFromCode, RETURN_IF_EAX_NOT_ZERO 389TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check, artAllocObjectFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO 390THREE_ARG_DOWNCALL art_quick_alloc_array, artAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO 391THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check, artAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO 392THREE_ARG_DOWNCALL art_quick_check_and_alloc_array, artCheckAndAllocArrayFromCode, RETURN_IF_EAX_NOT_ZERO 393THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check, artCheckAndAllocArrayFromCodeWithAccessCheck, RETURN_IF_EAX_NOT_ZERO 394 395TWO_ARG_DOWNCALL art_quick_alloc_object_instrumented, artAllocObjectFromCodeInstrumented, RETURN_IF_EAX_NOT_ZERO 396TWO_ARG_DOWNCALL art_quick_alloc_object_with_access_check_instrumented, artAllocObjectFromCodeWithAccessCheckInstrumented, RETURN_IF_EAX_NOT_ZERO 397THREE_ARG_DOWNCALL art_quick_alloc_array_instrumented, artAllocArrayFromCodeInstrumented, RETURN_IF_EAX_NOT_ZERO 398THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check_instrumented, artAllocArrayFromCodeWithAccessCheckInstrumented, RETURN_IF_EAX_NOT_ZERO 399THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_instrumented, artCheckAndAllocArrayFromCodeInstrumented, RETURN_IF_EAX_NOT_ZERO 400THREE_ARG_DOWNCALL art_quick_check_and_alloc_array_with_access_check_instrumented, artCheckAndAllocArrayFromCodeWithAccessCheckInstrumented, RETURN_IF_EAX_NOT_ZERO 401 402TWO_ARG_DOWNCALL art_quick_resolve_string, artResolveStringFromCode, RETURN_IF_EAX_NOT_ZERO 403TWO_ARG_DOWNCALL art_quick_initialize_static_storage, artInitializeStaticStorageFromCode, RETURN_IF_EAX_NOT_ZERO 404TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_EAX_NOT_ZERO 405TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_EAX_NOT_ZERO 406 407TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO 408 409DEFINE_FUNCTION art_quick_lock_object 410 testl %eax, %eax // null check object/eax 411 jz slow_lock 412retry_lock: 413 movl LOCK_WORD_OFFSET(%eax), %ecx // ecx := lock word 414 movl %fs:THREAD_ID_OFFSET, %edx // edx := thread id 415 test %ecx, %ecx 416 jb slow_lock // lock word contains a monitor 417 jnz already_thin // lock word contains a thin lock 418 // unlocked case - %edx holds thread id with count of 0 419 movl %eax, %ecx // remember object in case of retry 420 xor %eax, %eax // eax == 0 for comparison with lock word in cmpxchg 421 lock cmpxchg %edx, LOCK_WORD_OFFSET(%ecx) 422 jnz cmpxchg_fail // cmpxchg failed retry 423 ret 424cmpxchg_fail: 425 movl %ecx, %eax // restore eax 426 jmp retry_lock 427already_thin: 428 cmpw %ax, %dx // do we hold the lock already? 429 jne slow_lock 430 addl LITERAL(65536), %eax // increment recursion count 431 jb slow_lock // count overflowed so go slow 432 movl %eax, LOCK_WORD_OFFSET(%ecx) // update lockword, cmpxchg not necessary as we hold lock 433 ret 434slow_lock: 435 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 436 mov %esp, %edx // remember SP 437 // Outgoing argument set up 438 PUSH eax // push padding 439 PUSH edx // pass SP 440 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 441 .cfi_adjust_cfa_offset 4 442 PUSH eax // pass object 443 call artLockObjectFromCode // artLockObjectFromCode(object, Thread*, SP) 444 addl MACRO_LITERAL(16), %esp // pop arguments 445 .cfi_adjust_cfa_offset -16 446 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 447 RETURN_IF_EAX_ZERO 448END_FUNCTION art_quick_lock_object 449 450DEFINE_FUNCTION art_quick_unlock_object 451 testl %eax, %eax // null check object/eax 452 jz slow_unlock 453 movl LOCK_WORD_OFFSET(%eax), %ecx // ecx := lock word 454 movl %fs:THREAD_ID_OFFSET, %edx // edx := thread id 455 test %ecx, %ecx 456 jb slow_unlock // lock word contains a monitor 457 cmpw %cx, %dx // does the thread id match? 458 jne slow_unlock 459 cmpl LITERAL(65536), %ecx 460 jae recursive_thin_unlock 461 movl LITERAL(0), LOCK_WORD_OFFSET(%eax) 462 ret 463recursive_thin_unlock: 464 subl LITERAL(65536), %ecx 465 mov %ecx, LOCK_WORD_OFFSET(%eax) 466 ret 467slow_unlock: 468 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 469 mov %esp, %edx // remember SP 470 // Outgoing argument set up 471 PUSH eax // push padding 472 PUSH edx // pass SP 473 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 474 .cfi_adjust_cfa_offset 4 475 PUSH eax // pass object 476 call artUnlockObjectFromCode // artUnlockObjectFromCode(object, Thread*, SP) 477 addl MACRO_LITERAL(16), %esp // pop arguments 478 .cfi_adjust_cfa_offset -16 479 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 480 RETURN_IF_EAX_ZERO 481END_FUNCTION art_quick_unlock_object 482 483DEFINE_FUNCTION art_quick_is_assignable 484 PUSH eax // alignment padding 485 PUSH ecx // pass arg2 - obj->klass 486 PUSH eax // pass arg1 - checked class 487 call SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass) 488 addl LITERAL(12), %esp // pop arguments 489 .cfi_adjust_cfa_offset -12 490 ret 491END_FUNCTION art_quick_is_assignable 492 493DEFINE_FUNCTION art_quick_check_cast 494 PUSH eax // alignment padding 495 PUSH ecx // pass arg2 - obj->klass 496 PUSH eax // pass arg1 - checked class 497 call SYMBOL(artIsAssignableFromCode) // (Class* klass, Class* ref_klass) 498 testl %eax, %eax 499 jz 1f // jump forward if not assignable 500 addl LITERAL(12), %esp // pop arguments 501 .cfi_adjust_cfa_offset -12 502 ret 5031: 504 POP eax // pop arguments 505 POP ecx 506 addl LITERAL(4), %esp 507 .cfi_adjust_cfa_offset -12 508 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 509 mov %esp, %edx 510 // Outgoing argument set up 511 PUSH edx // pass SP 512 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 513 .cfi_adjust_cfa_offset 4 514 PUSH ecx // pass arg2 515 PUSH eax // pass arg1 516 call SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*, SP) 517 int3 // unreached 518END_FUNCTION art_quick_check_cast 519 520 /* 521 * Entry from managed code for array put operations of objects where the value being stored 522 * needs to be checked for compatibility. 523 * eax = array, ecx = index, edx = value 524 */ 525DEFINE_FUNCTION art_quick_aput_obj_with_null_and_bound_check 526 testl %eax, %eax 527 jnz art_quick_aput_obj_with_bound_check 528 jmp art_quick_throw_null_pointer_exception 529END_FUNCTION art_quick_aput_obj_with_null_and_bound_check 530 531DEFINE_FUNCTION art_quick_aput_obj_with_bound_check 532 movl ARRAY_LENGTH_OFFSET(%eax), %ebx 533 cmpl %ebx, %ecx 534 jb art_quick_aput_obj 535 mov %ecx, %eax 536 mov %ebx, %ecx 537 jmp art_quick_throw_array_bounds 538END_FUNCTION art_quick_aput_obj_with_bound_check 539 540DEFINE_FUNCTION art_quick_aput_obj 541 test %edx, %edx // store of null 542 jz do_aput_null 543 movl CLASS_OFFSET(%eax), %ebx 544 movl CLASS_COMPONENT_TYPE_OFFSET(%ebx), %ebx 545 cmpl CLASS_OFFSET(%edx), %ebx // value's type == array's component type - trivial assignability 546 jne check_assignability 547do_aput: 548 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) 549 movl %fs:THREAD_CARD_TABLE_OFFSET, %edx 550 shrl LITERAL(7), %eax 551 movb %dl, (%edx, %eax) 552 ret 553do_aput_null: 554 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) 555 ret 556check_assignability: 557 PUSH eax // save arguments 558 PUSH ecx 559 PUSH edx 560 subl LITERAL(8), %esp // alignment padding 561 .cfi_adjust_cfa_offset 8 562 pushl CLASS_OFFSET(%edx) // pass arg2 - type of the value to be stored 563 .cfi_adjust_cfa_offset 4 564 PUSH ebx // pass arg1 - component type of the array 565 call SYMBOL(artIsAssignableFromCode) // (Class* a, Class* b) 566 addl LITERAL(16), %esp // pop arguments 567 .cfi_adjust_cfa_offset -16 568 testl %eax, %eax 569 jz throw_array_store_exception 570 POP edx 571 POP ecx 572 POP eax 573 movl %edx, OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4) // do the aput 574 movl %fs:THREAD_CARD_TABLE_OFFSET, %edx 575 shrl LITERAL(7), %eax 576 movb %dl, (%edx, %eax) 577 ret 578throw_array_store_exception: 579 POP edx 580 POP ecx 581 POP eax 582 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context 583 mov %esp, %ecx 584 // Outgoing argument set up 585 PUSH ecx // pass SP 586 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 587 .cfi_adjust_cfa_offset 4 588 PUSH edx // pass arg2 - value 589 PUSH eax // pass arg1 - array 590 call SYMBOL(artThrowArrayStoreException) // (array, value, Thread*, SP) 591 int3 // unreached 592END_FUNCTION art_quick_aput_obj 593 594DEFINE_FUNCTION art_quick_memcpy 595 PUSH edx // pass arg3 596 PUSH ecx // pass arg2 597 PUSH eax // pass arg1 598 call SYMBOL(memcpy) // (void*, const void*, size_t) 599 addl LITERAL(12), %esp // pop arguments 600 .cfi_adjust_cfa_offset -12 601 ret 602END_FUNCTION art_quick_memcpy 603 604NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret 605 606DEFINE_FUNCTION art_quick_fmod 607 subl LITERAL(12), %esp // alignment padding 608 .cfi_adjust_cfa_offset 12 609 PUSH ebx // pass arg4 b.hi 610 PUSH edx // pass arg3 b.lo 611 PUSH ecx // pass arg2 a.hi 612 PUSH eax // pass arg1 a.lo 613 call SYMBOL(fmod) // (jdouble a, jdouble b) 614 fstpl (%esp) // pop return value off fp stack 615 movsd (%esp), %xmm0 // place into %xmm0 616 addl LITERAL(28), %esp // pop arguments 617 .cfi_adjust_cfa_offset -28 618 ret 619END_FUNCTION art_quick_fmod 620 621DEFINE_FUNCTION art_quick_fmodf 622 PUSH eax // alignment padding 623 PUSH ecx // pass arg2 b 624 PUSH eax // pass arg1 a 625 call SYMBOL(fmodf) // (jfloat a, jfloat b) 626 fstps (%esp) // pop return value off fp stack 627 movss (%esp), %xmm0 // place into %xmm0 628 addl LITERAL(12), %esp // pop arguments 629 .cfi_adjust_cfa_offset -12 630 ret 631END_FUNCTION art_quick_fmodf 632 633DEFINE_FUNCTION art_quick_l2d 634 PUSH ecx // push arg2 a.hi 635 PUSH eax // push arg1 a.lo 636 fildll (%esp) // load as integer and push into st0 637 fstpl (%esp) // pop value off fp stack as double 638 movsd (%esp), %xmm0 // place into %xmm0 639 addl LITERAL(8), %esp // pop arguments 640 .cfi_adjust_cfa_offset -8 641 ret 642END_FUNCTION art_quick_l2d 643 644DEFINE_FUNCTION art_quick_l2f 645 PUSH ecx // push arg2 a.hi 646 PUSH eax // push arg1 a.lo 647 fildll (%esp) // load as integer and push into st0 648 fstps (%esp) // pop value off fp stack as a single 649 movss (%esp), %xmm0 // place into %xmm0 650 addl LITERAL(8), %esp // pop argument 651 .cfi_adjust_cfa_offset -8 652 ret 653END_FUNCTION art_quick_l2f 654 655DEFINE_FUNCTION art_quick_d2l 656 PUSH eax // alignment padding 657 PUSH ecx // pass arg2 a.hi 658 PUSH eax // pass arg1 a.lo 659 call SYMBOL(art_d2l) // (jdouble a) 660 addl LITERAL(12), %esp // pop arguments 661 .cfi_adjust_cfa_offset -12 662 ret 663END_FUNCTION art_quick_d2l 664 665DEFINE_FUNCTION art_quick_f2l 666 subl LITERAL(8), %esp // alignment padding 667 .cfi_adjust_cfa_offset 8 668 PUSH eax // pass arg1 a 669 call SYMBOL(art_f2l) // (jfloat a) 670 addl LITERAL(12), %esp // pop arguments 671 .cfi_adjust_cfa_offset -12 672 ret 673END_FUNCTION art_quick_f2l 674 675DEFINE_FUNCTION art_quick_idivmod 676 cmpl LITERAL(0x80000000), %eax 677 je check_arg2 // special case 678args_ok: 679 cdq // edx:eax = sign extend eax 680 idiv %ecx // (edx,eax) = (edx:eax % ecx, edx:eax / ecx) 681 ret 682check_arg2: 683 cmpl LITERAL(-1), %ecx 684 jne args_ok 685 xorl %edx, %edx 686 ret // eax already holds min int 687END_FUNCTION art_quick_idivmod 688 689DEFINE_FUNCTION art_quick_ldiv 690 subl LITERAL(12), %esp // alignment padding 691 .cfi_adjust_cfa_offset 12 692 PUSH ebx // pass arg4 b.hi 693 PUSH edx // pass arg3 b.lo 694 PUSH ecx // pass arg2 a.hi 695 PUSH eax // pass arg1 a.lo 696 call SYMBOL(artLdiv) // (jlong a, jlong b) 697 addl LITERAL(28), %esp // pop arguments 698 .cfi_adjust_cfa_offset -28 699 ret 700END_FUNCTION art_quick_ldiv 701 702DEFINE_FUNCTION art_quick_lmod 703 subl LITERAL(12), %esp // alignment padding 704 .cfi_adjust_cfa_offset 12 705 PUSH ebx // pass arg4 b.hi 706 PUSH edx // pass arg3 b.lo 707 PUSH ecx // pass arg2 a.hi 708 PUSH eax // pass arg1 a.lo 709 call SYMBOL(artLmod) // (jlong a, jlong b) 710 addl LITERAL(28), %esp // pop arguments 711 .cfi_adjust_cfa_offset -28 712 ret 713END_FUNCTION art_quick_lmod 714 715DEFINE_FUNCTION art_quick_lmul 716 imul %eax, %ebx // ebx = a.lo(eax) * b.hi(ebx) 717 imul %edx, %ecx // ecx = b.lo(edx) * a.hi(ecx) 718 mul %edx // edx:eax = a.lo(eax) * b.lo(edx) 719 add %ebx, %ecx 720 add %ecx, %edx // edx += (a.lo * b.hi) + (b.lo * a.hi) 721 ret 722END_FUNCTION art_quick_lmul 723 724DEFINE_FUNCTION art_quick_lshl 725 // ecx:eax << edx 726 xchg %edx, %ecx 727 shld %cl,%eax,%edx 728 shl %cl,%eax 729 test LITERAL(32), %cl 730 jz 1f 731 mov %eax, %edx 732 xor %eax, %eax 7331: 734 ret 735END_FUNCTION art_quick_lshl 736 737DEFINE_FUNCTION art_quick_lshr 738 // ecx:eax >> edx 739 xchg %edx, %ecx 740 shrd %cl,%edx,%eax 741 sar %cl,%edx 742 test LITERAL(32),%cl 743 jz 1f 744 mov %edx, %eax 745 sar LITERAL(31), %edx 7461: 747 ret 748END_FUNCTION art_quick_lshr 749 750DEFINE_FUNCTION art_quick_lushr 751 // ecx:eax >>> edx 752 xchg %edx, %ecx 753 shrd %cl,%edx,%eax 754 shr %cl,%edx 755 test LITERAL(32),%cl 756 jz 1f 757 mov %edx, %eax 758 xor %edx, %edx 7591: 760 ret 761END_FUNCTION art_quick_lushr 762 763DEFINE_FUNCTION art_quick_set32_instance 764 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 765 mov %esp, %ebx // remember SP 766 subl LITERAL(8), %esp // alignment padding 767 .cfi_adjust_cfa_offset 8 768 PUSH ebx // pass SP 769 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 770 .cfi_adjust_cfa_offset 4 771 mov 32(%ebx), %ebx // get referrer 772 PUSH ebx // pass referrer 773 PUSH edx // pass new_val 774 PUSH ecx // pass object 775 PUSH eax // pass field_idx 776 call SYMBOL(artSet32InstanceFromCode) // (field_idx, Object*, new_val, referrer, Thread*, SP) 777 addl LITERAL(32), %esp // pop arguments 778 .cfi_adjust_cfa_offset -32 779 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 780 RETURN_IF_EAX_ZERO // return or deliver exception 781END_FUNCTION art_quick_set32_instance 782 783DEFINE_FUNCTION art_quick_set64_instance 784 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 785 subl LITERAL(8), %esp // alignment padding 786 .cfi_adjust_cfa_offset 8 787 PUSH esp // pass SP-8 788 addl LITERAL(8), (%esp) // fix SP on stack by adding 8 789 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 790 .cfi_adjust_cfa_offset 4 791 PUSH ebx // pass high half of new_val 792 PUSH edx // pass low half of new_val 793 PUSH ecx // pass object 794 PUSH eax // pass field_idx 795 call SYMBOL(artSet64InstanceFromCode) // (field_idx, Object*, new_val, Thread*, SP) 796 addl LITERAL(32), %esp // pop arguments 797 .cfi_adjust_cfa_offset -32 798 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 799 RETURN_IF_EAX_ZERO // return or deliver exception 800END_FUNCTION art_quick_set64_instance 801 802DEFINE_FUNCTION art_quick_set_obj_instance 803 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 804 mov %esp, %ebx // remember SP 805 subl LITERAL(8), %esp // alignment padding 806 .cfi_adjust_cfa_offset 8 807 PUSH ebx // pass SP 808 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 809 .cfi_adjust_cfa_offset 4 810 mov 32(%ebx), %ebx // get referrer 811 PUSH ebx // pass referrer 812 PUSH edx // pass new_val 813 PUSH ecx // pass object 814 PUSH eax // pass field_idx 815 call SYMBOL(artSetObjInstanceFromCode) // (field_idx, Object*, new_val, referrer, Thread*, SP) 816 addl LITERAL(32), %esp // pop arguments 817 .cfi_adjust_cfa_offset -32 818 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 819 RETURN_IF_EAX_ZERO // return or deliver exception 820END_FUNCTION art_quick_set_obj_instance 821 822DEFINE_FUNCTION art_quick_get32_instance 823 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 824 mov %esp, %ebx // remember SP 825 mov 32(%esp), %edx // get referrer 826 subl LITERAL(12), %esp // alignment padding 827 .cfi_adjust_cfa_offset 12 828 PUSH ebx // pass SP 829 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 830 .cfi_adjust_cfa_offset 4 831 PUSH edx // pass referrer 832 PUSH ecx // pass object 833 PUSH eax // pass field_idx 834 call SYMBOL(artGet32InstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 835 addl LITERAL(32), %esp // pop arguments 836 .cfi_adjust_cfa_offset -32 837 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 838 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 839END_FUNCTION art_quick_get32_instance 840 841DEFINE_FUNCTION art_quick_get64_instance 842 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 843 mov %esp, %ebx // remember SP 844 mov 32(%esp), %edx // get referrer 845 subl LITERAL(12), %esp // alignment padding 846 .cfi_adjust_cfa_offset 12 847 PUSH ebx // pass SP 848 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 849 .cfi_adjust_cfa_offset 4 850 PUSH edx // pass referrer 851 PUSH ecx // pass object 852 PUSH eax // pass field_idx 853 call SYMBOL(artGet64InstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 854 addl LITERAL(32), %esp // pop arguments 855 .cfi_adjust_cfa_offset -32 856 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 857 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 858END_FUNCTION art_quick_get64_instance 859 860DEFINE_FUNCTION art_quick_get_obj_instance 861 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 862 mov %esp, %ebx // remember SP 863 mov 32(%esp), %edx // get referrer 864 subl LITERAL(12), %esp // alignment padding 865 .cfi_adjust_cfa_offset 12 866 PUSH ebx // pass SP 867 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 868 .cfi_adjust_cfa_offset 4 869 PUSH edx // pass referrer 870 PUSH ecx // pass object 871 PUSH eax // pass field_idx 872 call SYMBOL(artGetObjInstanceFromCode) // (field_idx, Object*, referrer, Thread*, SP) 873 addl LITERAL(32), %esp // pop arguments 874 .cfi_adjust_cfa_offset -32 875 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 876 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 877END_FUNCTION art_quick_get_obj_instance 878 879DEFINE_FUNCTION art_quick_set32_static 880 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 881 mov %esp, %ebx // remember SP 882 mov 32(%esp), %edx // get referrer 883 subl LITERAL(12), %esp // alignment padding 884 .cfi_adjust_cfa_offset 12 885 PUSH ebx // pass SP 886 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 887 .cfi_adjust_cfa_offset 4 888 PUSH edx // pass referrer 889 PUSH ecx // pass new_val 890 PUSH eax // pass field_idx 891 call SYMBOL(artSet32StaticFromCode) // (field_idx, new_val, referrer, Thread*, SP) 892 addl LITERAL(32), %esp // pop arguments 893 .cfi_adjust_cfa_offset -32 894 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 895 RETURN_IF_EAX_ZERO // return or deliver exception 896END_FUNCTION art_quick_set32_static 897 898DEFINE_FUNCTION art_quick_set64_static 899 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 900 mov %esp, %ebx // remember SP 901 subl LITERAL(8), %esp // alignment padding 902 .cfi_adjust_cfa_offset 8 903 PUSH ebx // pass SP 904 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 905 .cfi_adjust_cfa_offset 4 906 mov 32(%ebx), %ebx // get referrer 907 PUSH edx // pass high half of new_val 908 PUSH ecx // pass low half of new_val 909 PUSH ebx // pass referrer 910 PUSH eax // pass field_idx 911 call SYMBOL(artSet64StaticFromCode) // (field_idx, referrer, new_val, Thread*, SP) 912 addl LITERAL(32), %esp // pop arguments 913 .cfi_adjust_cfa_offset -32 914 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 915 RETURN_IF_EAX_ZERO // return or deliver exception 916END_FUNCTION art_quick_set64_static 917 918DEFINE_FUNCTION art_quick_set_obj_static 919 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 920 mov %esp, %ebx // remember SP 921 mov 32(%esp), %edx // get referrer 922 subl LITERAL(12), %esp // alignment padding 923 .cfi_adjust_cfa_offset 12 924 PUSH ebx // pass SP 925 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 926 .cfi_adjust_cfa_offset 4 927 PUSH edx // pass referrer 928 PUSH ecx // pass new_val 929 PUSH eax // pass field_idx 930 call SYMBOL(artSetObjStaticFromCode) // (field_idx, new_val, referrer, Thread*, SP) 931 addl LITERAL(32), %esp // pop arguments 932 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 933 RETURN_IF_EAX_ZERO // return or deliver exception 934END_FUNCTION art_quick_set_obj_static 935 936DEFINE_FUNCTION art_quick_get32_static 937 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 938 mov %esp, %edx // remember SP 939 mov 32(%esp), %ecx // get referrer 940 PUSH edx // pass SP 941 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 942 .cfi_adjust_cfa_offset 4 943 PUSH ecx // pass referrer 944 PUSH eax // pass field_idx 945 call SYMBOL(artGet32StaticFromCode) // (field_idx, referrer, Thread*, SP) 946 addl LITERAL(16), %esp // pop arguments 947 .cfi_adjust_cfa_offset -16 948 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 949 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 950END_FUNCTION art_quick_get32_static 951 952DEFINE_FUNCTION art_quick_get64_static 953 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 954 mov %esp, %edx // remember SP 955 mov 32(%esp), %ecx // get referrer 956 PUSH edx // pass SP 957 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 958 .cfi_adjust_cfa_offset 4 959 PUSH ecx // pass referrer 960 PUSH eax // pass field_idx 961 call SYMBOL(artGet64StaticFromCode) // (field_idx, referrer, Thread*, SP) 962 addl LITERAL(16), %esp // pop arguments 963 .cfi_adjust_cfa_offset -16 964 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 965 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 966END_FUNCTION art_quick_get64_static 967 968DEFINE_FUNCTION art_quick_get_obj_static 969 SETUP_REF_ONLY_CALLEE_SAVE_FRAME // save ref containing registers for GC 970 mov %esp, %edx // remember SP 971 mov 32(%esp), %ecx // get referrer 972 PUSH edx // pass SP 973 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 974 .cfi_adjust_cfa_offset 4 975 PUSH ecx // pass referrer 976 PUSH eax // pass field_idx 977 call SYMBOL(artGetObjStaticFromCode) // (field_idx, referrer, Thread*, SP) 978 addl LITERAL(16), %esp // pop arguments 979 .cfi_adjust_cfa_offset -16 980 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address 981 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 982END_FUNCTION art_quick_get_obj_static 983 984DEFINE_FUNCTION art_quick_proxy_invoke_handler 985 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame and Method* 986 PUSH esp // pass SP 987 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 988 .cfi_adjust_cfa_offset 4 989 PUSH ecx // pass receiver 990 PUSH eax // pass proxy method 991 call SYMBOL(artQuickProxyInvokeHandler) // (proxy method, receiver, Thread*, SP) 992 movd %eax, %xmm0 // place return value also into floating point return value 993 movd %edx, %xmm1 994 punpckldq %xmm1, %xmm0 995 addl LITERAL(44), %esp // pop arguments 996 .cfi_adjust_cfa_offset -44 997 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 998END_FUNCTION art_quick_proxy_invoke_handler 999 1000 /* 1001 * Called to resolve an imt conflict. xmm0 is a hidden argument that holds the target method's 1002 * dex method index. 1003 */ 1004DEFINE_FUNCTION art_quick_imt_conflict_trampoline 1005 PUSH ecx 1006 movl 8(%esp), %eax // load caller Method* 1007 movl METHOD_DEX_CACHE_METHODS_OFFSET(%eax), %eax // load dex_cache_resolved_methods 1008 movd %xmm0, %ecx // get target method index stored in xmm0 1009 movl OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4), %eax // load the target method 1010 POP ecx 1011 jmp art_quick_invoke_interface_trampoline 1012END_FUNCTION art_quick_imt_conflict_trampoline 1013 1014DEFINE_FUNCTION art_quick_resolution_trampoline 1015 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1016 PUSH esp // pass SP 1017 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1018 .cfi_adjust_cfa_offset 4 1019 PUSH ecx // pass receiver 1020 PUSH eax // pass method 1021 call SYMBOL(artQuickResolutionTrampoline) // (Method* called, receiver, Thread*, SP) 1022 movl %eax, %edi // remember code pointer in EDI 1023 addl LITERAL(16), %esp // pop arguments 1024 test %eax, %eax // if code pointer is NULL goto deliver pending exception 1025 jz 1f 1026 POP eax // called method 1027 POP ecx // restore args 1028 POP edx 1029 POP ebx 1030 POP ebp // restore callee saves except EDI 1031 POP esi 1032 xchgl 0(%esp),%edi // restore EDI and place code pointer as only value on stack 1033 ret // tail call into method 10341: 1035 RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME 1036 DELIVER_PENDING_EXCEPTION 1037END_FUNCTION art_quick_resolution_trampoline 1038 1039DEFINE_FUNCTION art_quick_to_interpreter_bridge 1040 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME // save frame 1041 mov %esp, %edx // remember SP 1042 PUSH eax // alignment padding 1043 PUSH edx // pass SP 1044 pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current() 1045 .cfi_adjust_cfa_offset 4 1046 PUSH eax // pass method 1047 call SYMBOL(artQuickToInterpreterBridge) // (method, Thread*, SP) 1048 movd %eax, %xmm0 // place return value also into floating point return value 1049 movd %edx, %xmm1 1050 punpckldq %xmm1, %xmm0 1051 addl LITERAL(16), %esp // pop arguments 1052 .cfi_adjust_cfa_offset -16 1053 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 1054 RETURN_OR_DELIVER_PENDING_EXCEPTION // return or deliver exception 1055END_FUNCTION art_quick_to_interpreter_bridge 1056 1057 /* 1058 * Routine that intercepts method calls and returns. 1059 */ 1060DEFINE_FUNCTION art_quick_instrumentation_entry 1061 SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME 1062 movl %esp, %edx // Save SP. 1063 PUSH eax // Save eax which will be clobbered by the callee-save method. 1064 subl LITERAL(8), %esp // Align stack. 1065 .cfi_adjust_cfa_offset 8 1066 pushl 40(%esp) // Pass LR. 1067 .cfi_adjust_cfa_offset 4 1068 PUSH edx // Pass SP. 1069 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1070 .cfi_adjust_cfa_offset 4 1071 PUSH ecx // Pass receiver. 1072 PUSH eax // Pass Method*. 1073 call SYMBOL(artInstrumentationMethodEntryFromCode) // (Method*, Object*, Thread*, SP, LR) 1074 addl LITERAL(28), %esp // Pop arguments upto saved Method*. 1075 movl 28(%esp), %edi // Restore edi. 1076 movl %eax, 28(%esp) // Place code* over edi, just under return pc. 1077 movl LITERAL(SYMBOL(art_quick_instrumentation_exit)), 32(%esp) 1078 // Place instrumentation exit as return pc. 1079 movl (%esp), %eax // Restore eax. 1080 movl 8(%esp), %ecx // Restore ecx. 1081 movl 12(%esp), %edx // Restore edx. 1082 movl 16(%esp), %ebx // Restore ebx. 1083 movl 20(%esp), %ebp // Restore ebp. 1084 movl 24(%esp), %esi // Restore esi. 1085 addl LITERAL(28), %esp // Wind stack back upto code*. 1086 ret // Call method (and pop). 1087END_FUNCTION art_quick_instrumentation_entry 1088 1089DEFINE_FUNCTION art_quick_instrumentation_exit 1090 pushl LITERAL(0) // Push a fake return PC as there will be none on the stack. 1091 SETUP_REF_ONLY_CALLEE_SAVE_FRAME 1092 mov %esp, %ecx // Remember SP 1093 subl LITERAL(8), %esp // Save float return value. 1094 .cfi_adjust_cfa_offset 8 1095 movd %xmm0, (%esp) 1096 PUSH edx // Save gpr return value. 1097 PUSH eax 1098 subl LITERAL(8), %esp // Align stack 1099 movd %xmm0, (%esp) 1100 subl LITERAL(8), %esp // Pass float return value. 1101 .cfi_adjust_cfa_offset 8 1102 movd %xmm0, (%esp) 1103 PUSH edx // Pass gpr return value. 1104 PUSH eax 1105 PUSH ecx // Pass SP. 1106 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current. 1107 .cfi_adjust_cfa_offset 4 1108 call SYMBOL(artInstrumentationMethodExitFromCode) // (Thread*, SP, gpr_result, fpr_result) 1109 mov %eax, %ecx // Move returned link register. 1110 addl LITERAL(32), %esp // Pop arguments. 1111 .cfi_adjust_cfa_offset -32 1112 movl %edx, %ebx // Move returned link register for deopt 1113 // (ebx is pretending to be our LR). 1114 POP eax // Restore gpr return value. 1115 POP edx 1116 movd (%esp), %xmm0 // Restore fpr return value. 1117 addl LITERAL(8), %esp 1118 .cfi_adjust_cfa_offset -8 1119 RESTORE_REF_ONLY_CALLEE_SAVE_FRAME 1120 addl LITERAL(4), %esp // Remove fake return pc. 1121 jmp *%ecx // Return. 1122END_FUNCTION art_quick_instrumentation_exit 1123 1124 /* 1125 * Instrumentation has requested that we deoptimize into the interpreter. The deoptimization 1126 * will long jump to the upcall with a special exception of -1. 1127 */ 1128DEFINE_FUNCTION art_quick_deoptimize 1129 pushl %ebx // Fake that we were called. 1130 SETUP_SAVE_ALL_CALLEE_SAVE_FRAME 1131 mov %esp, %ecx // Remember SP. 1132 subl LITERAL(8), %esp // Align stack. 1133 .cfi_adjust_cfa_offset 8 1134 PUSH ecx // Pass SP. 1135 pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). 1136 .cfi_adjust_cfa_offset 4 1137 call SYMBOL(artDeoptimize) // artDeoptimize(Thread*, SP) 1138 int3 // Unreachable. 1139END_FUNCTION art_quick_deoptimize 1140 1141 /* 1142 * String's indexOf. 1143 * 1144 * On entry: 1145 * eax: string object (known non-null) 1146 * ecx: char to match (known <= 0xFFFF) 1147 * edx: Starting offset in string data 1148 */ 1149DEFINE_FUNCTION art_quick_indexof 1150 PUSH edi // push callee save reg 1151 mov STRING_COUNT_OFFSET(%eax), %ebx 1152 mov STRING_VALUE_OFFSET(%eax), %edi 1153 mov STRING_OFFSET_OFFSET(%eax), %eax 1154 testl %edx, %edx // check if start < 0 1155 jl clamp_min 1156clamp_done: 1157 cmpl %ebx, %edx // check if start >= count 1158 jge not_found 1159 lea STRING_DATA_OFFSET(%edi, %eax, 2), %edi // build a pointer to the start of string data 1160 mov %edi, %eax // save a copy in eax to later compute result 1161 lea (%edi, %edx, 2), %edi // build pointer to start of data to compare 1162 subl %edx, %ebx // compute iteration count 1163 /* 1164 * At this point we have: 1165 * eax: original start of string data 1166 * ecx: char to compare 1167 * ebx: length to compare 1168 * edi: start of data to test 1169 */ 1170 mov %eax, %edx 1171 mov %ecx, %eax // put char to match in %eax 1172 mov %ebx, %ecx // put length to compare in %ecx 1173 repne scasw // find %ax, starting at [%edi], up to length %ecx 1174 jne not_found 1175 subl %edx, %edi 1176 sar LITERAL(1), %edi 1177 decl %edi // index = ((curr_ptr - orig_ptr) / 2) - 1 1178 mov %edi, %eax 1179 POP edi // pop callee save reg 1180 ret 1181 .balign 16 1182not_found: 1183 mov LITERAL(-1), %eax // return -1 (not found) 1184 POP edi // pop callee save reg 1185 ret 1186clamp_min: 1187 xor %edx, %edx // clamp start to 0 1188 jmp clamp_done 1189END_FUNCTION art_quick_indexof 1190 1191 /* 1192 * String's compareTo. 1193 * 1194 * On entry: 1195 * eax: this string object (known non-null) 1196 * ecx: comp string object (known non-null) 1197 */ 1198DEFINE_FUNCTION art_quick_string_compareto 1199 PUSH esi // push callee save reg 1200 PUSH edi // push callee save reg 1201 mov STRING_COUNT_OFFSET(%eax), %edx 1202 mov STRING_COUNT_OFFSET(%ecx), %ebx 1203 mov STRING_VALUE_OFFSET(%eax), %esi 1204 mov STRING_VALUE_OFFSET(%ecx), %edi 1205 mov STRING_OFFSET_OFFSET(%eax), %eax 1206 mov STRING_OFFSET_OFFSET(%ecx), %ecx 1207 /* Build pointers to the start of string data */ 1208 lea STRING_DATA_OFFSET(%esi, %eax, 2), %esi 1209 lea STRING_DATA_OFFSET(%edi, %ecx, 2), %edi 1210 /* Calculate min length and count diff */ 1211 mov %edx, %ecx 1212 mov %edx, %eax 1213 subl %ebx, %eax 1214 cmovg %ebx, %ecx 1215 /* 1216 * At this point we have: 1217 * eax: value to return if first part of strings are equal 1218 * ecx: minimum among the lengths of the two strings 1219 * esi: pointer to this string data 1220 * edi: pointer to comp string data 1221 */ 1222 repe cmpsw // find nonmatching chars in [%esi] and [%edi], up to length %ecx 1223 jne not_equal 1224 POP edi // pop callee save reg 1225 POP esi // pop callee save reg 1226 ret 1227 .balign 16 1228not_equal: 1229 movzwl -2(%esi), %eax // get last compared char from this string 1230 movzwl -2(%edi), %ecx // get last compared char from comp string 1231 subl %ecx, %eax // return the difference 1232 POP edi // pop callee save reg 1233 POP esi // pop callee save reg 1234 ret 1235END_FUNCTION art_quick_string_compareto 1236 1237 // TODO: implement these! 1238UNIMPLEMENTED art_quick_memcmp16 1239