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