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