1 /* Copyright (C) 2008 The Android Open Source Project 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 /* 17 * File: footer.S 18 */ 19 20 .text 21 .align 2 22 23 /* 24 * Check to see if the thread needs to be suspended or debugger/profiler 25 * activity has begun. 26 * 27 * On entry: 28 * %ecx is reentry type, e.g. kInterpEntryInstr 29 * %edx is PC adjustment in bytes 30 */ 31 32common_periodicChecks: 33 movl %edx, -8(%esp) # save pc adjustments 34 movl rGLUE, %edx # %edx<- pMterpGlue 35 movl %ebx, -4(%esp) # save %ebx to the stack 36 movl offGlue_pSelfSuspendCount(%edx), %ebx # %ebx<- pSuspendCount (int) 37#if defined(WITH_DEBUGGER) 38 movl offGlue_pDebuggerActive(%edx), %eax # %eax<- pDebuggerActive 39 movl (%eax), %eax # %eax<- get debuggerActive (boolean) 40 and $$7, %eax # %eax<- mask for boolean (just how many bits does it take?) 41#endif 42 cmp $$0, (%ebx) # check if suspend is pending 43 jne 2f # handle suspend 44#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 45#if defined(WITH_PROFILER) 46 movl offGlue_pActiveProfilers(%edx), %ebx # %ebx<- activeProfilers (int) 47 or (%ebx), %eax # %eax<- merge activeProfilers and debuggerActive 48#else 49 cmp $$0, %eax # check for debuggerActive 50#endif 51 jne 3f # debugger or profiler active; switch interp 52#endif 53 movl -8(%esp), %edx # %edx<- restore %edx 54 movl -4(%esp), %ebx # %ebx<- restore %ebx 55 ret # return 562: # check suspended 57 movl offGlue_self(%edx), %eax # %eax<- glue->self 58 movl %eax, -12(%esp) # push parameter boolean 59 lea -12(%esp), %esp 60 call dvmCheckSuspendPending # call: (Thread* self) 61 # return: bool 62 movl 4(%esp), %edx # %edx<- restore %edx 63 movl 8(%esp), %ebx # %ebx<- restore %ebx 64 lea 12(%esp), %esp 65 ret # return 663: # debugger/profiler enabled, bail out 67 add -8(%esp), rPC # rPC<- pc adjustments 68 movl %ecx, offGlue_entryPoint(%edx) # glue->entryPoint<- reentry type 69 movl $$1, %edx # switch to interp == true 70 jmp common_gotoBail # bail 71 72 /* 73 * Check to see if the thread needs to be suspended or debugger/profiler 74 * activity has begun. With this variant, the reentry type is hard coded 75 * as kInterpEntryInstr. 76 * 77 * On entry: 78 * %edx is PC adjustment in bytes 79 */ 80 81common_periodicChecks2: 82 movl rGLUE, %ecx # %ecx<- pMterpGlue 83 movl offGlue_pSelfSuspendCount(%ecx), rINST # %ebx<- pSuspendCount (int) 84#if defined(WITH_DEBUGGER) 85 movl offGlue_pDebuggerActive(%ecx), %eax # %eax<- pDebuggerActive 86 movl (%eax), %eax # %eax<- get debuggerActive (boolean) 87 and $$7, %eax # %eax<- mask for boolean (just how many bits does it take?) 88#endif 89 cmp $$0, (rINST) # check if suspend is pending 90 jne 2f # handle suspend 91#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 92#if defined(WITH_PROFILER) 93 movl offGlue_pActiveProfilers(%ecx), rINST # %edx<- activeProfilers (int) 94 or (rINST), %eax # %eax<- merge activeProfilers and debuggerActive 95#else 96 cmp $$0, %eax # check for debuggerActive 97#endif 98 jne 3f # debugger or profiler active; switch interp 99#endif 100 FINISH_RB %edx, %ecx # jump to next instruction 1012: # check suspended 102 movl offGlue_self(%ecx), %eax# %eax<- glue->self 103 movl %edx, rINST 104 movl %eax, -12(%esp) # push parameter boolean 105 lea -12(%esp), %esp 106 call dvmCheckSuspendPending # call: (Thread* self) 107 # return: bool 108 movl rINST, %edx # %edx<- restore %edx 109 lea 12(%esp), %esp 110 FINISH_RB %edx, %ecx # jump to next instruction 111 1123: # debugger/profiler enabled, bail out 113 add -8(%esp), rPC # rPC<- pc adjustments 114 movl $$kInterpEntryInstr, offGlue_entryPoint(%ecx) # glue->entryPoint<- reentry type 115 movl $$1, %edx # switch to interp<- true 116 jmp common_gotoBail # bail 117 118 119 /* 120 * The equivalent of "goto bail", this calls through the "bail handler". 121 * State registers will be saved to the "glue" area before bailing. 122 * 123 * On entry: 124 * %edx is "bool changeInterp", indicating if we want to switch to the 125 * other interpreter or just bail all the way out 126 */ 127 128common_gotoBail: 129 SAVE_PC_FP_TO_GLUE %ecx # save program counter and frame pointer 130 131 /* 132 * Inlined dvmMterpStdBail 133 */ 134 135 lea 40(%ebp), %esp 136 movl %edx, %eax 137 movl 24(%ebp), %edi 138 movl 28(%ebp), %esi 139 movl 32(%ebp), %ebx 140 movl 36(%ebp), %ebp 141 ret 142 143 /* 144 * Common code for method invocation with range. 145 * 146 * On entry: 147 * %ecx is "Method* methodToCall", the method we're trying to call 148 */ 149 150common_invokeMethodRange: 151.LinvokeNewRange: 152 153 /* 154 * prepare to copy args to "outs" area of current frame 155 */ 156 157 SAVEAREA_FROM_FP %eax # %eax<- &outs; &StackSaveArea 158 test rINST, rINST # test for no args 159 movl rINST, sReg0 # sReg0<- AA 160 jz .LinvokeArgsDone # no args; jump to args done 161 FETCH 2, %edx # %edx<- CCCC 162 163 /* 164 * %ecx=methodToCall, %edx=CCCC, sReg0=count, %eax=&outs (&stackSaveArea) 165 * (very few methods have > 10 args; could unroll for common cases) 166 */ 167 168 movl %ebx, sReg1 # sReg1<- save %ebx 169 lea (rFP, %edx, 4), %edx # %edx<- &vCCCC 170 shll $$2, sReg0 # sReg0<- offset 171 subl sReg0, %eax # %eax<- update &outs 172 shrl $$2, sReg0 # sReg0<- offset 1731: 174 movl (%edx), %ebx # %ebx<- vCCCC 175 lea 4(%edx), %edx # %edx<- &vCCCC++ 176 subl $$1, sReg0 # sReg<- sReg-- 177 movl %ebx, (%eax) # *outs<- vCCCC 178 lea 4(%eax), %eax # outs++ 179 jne 1b # loop if count (sReg0) not zero 180 movl sReg1, %ebx # %ebx<- restore %ebx 181 jmp .LinvokeArgsDone # continue 182 183 /* 184 * %ecx is "Method* methodToCall", the method we're trying to call 185 * prepare to copy args to "outs" area of current frame 186 */ 187 188common_invokeMethodNoRange: 189.LinvokeNewNoRange: 190 movl rINST, sReg0 # sReg0<- BA 191 shrl $$4, sReg0 # sReg0<- B 192 je .LinvokeArgsDone # no args; jump to args done 193 SAVEAREA_FROM_FP %eax # %eax<- &outs; &StackSaveArea 194 FETCH 2, %edx # %edx<- GFED 195 196 /* 197 * %ecx=methodToCall, %edx=GFED, sReg0=count, %eax=outs 198 */ 199 200.LinvokeNonRange: 201 cmp $$2, sReg0 # compare sReg0 to 2 202 movl %edx, sReg1 # sReg1<- GFED 203 jl 1f # handle 1 arg 204 je 2f # handle 2 args 205 cmp $$4, sReg0 # compare sReg0 to 4 206 jl 3f # handle 3 args 207 je 4f # handle 4 args 2085: 209 andl $$15, rINST # rINST<- A 210 lea -4(%eax), %eax # %eax<- update &outs; &outs-- 211 movl (rFP, rINST, 4), %edx # %edx<- vA 212 movl %edx, (%eax) # *outs<- vA 213 movl sReg1, %edx # %edx<- GFED 2144: 215 shr $$12, %edx # %edx<- G 216 lea -4(%eax), %eax # %eax<- update &outs; &outs-- 217 movl (rFP, %edx, 4), %edx # %edx<- vG 218 movl %edx, (%eax) # *outs<- vG 219 movl sReg1, %edx # %edx<- GFED 2203: 221 and $$0x0f00, %edx # %edx<- 0F00 222 shr $$6, %edx # %edx<- F at correct offset 223 lea -4(%eax), %eax # %eax<- update &outs; &outs-- 224 movl (rFP, %edx), %edx # %edx<- vF 225 movl %edx, (%eax) # *outs<- vF 226 movl sReg1, %edx # %edx<- GFED 2272: 228 and $$0x00f0, %edx # %edx<- 00E0 229 shr $$2, %edx # %edx<- E at correct offset 230 lea -4(%eax), %eax # %eax<- update &outs; &outs-- 231 movl (rFP, %edx), %edx # %edx<- vE 232 movl %edx, (%eax) # *outs<- vE 233 movl sReg1, %edx # %edx<- GFED 2341: 235 and $$0x000f, %edx # %edx<- 000D 236 movl (rFP, %edx, 4), %edx # %edx<- vD 237 movl %edx, -4(%eax) # *--outs<- vD 2380: 239 240 /* 241 * %ecx is "Method* methodToCall", the method we're trying to call 242 * find space for the new stack frame, check for overflow 243 */ 244 245.LinvokeArgsDone: 246 movzwl offMethod_registersSize(%ecx), %eax # %eax<- methodToCall->regsSize 247 movzwl offMethod_outsSize(%ecx), %edx # %edx<- methodToCall->outsSize 248 movl %ecx, sReg0 # sReg<- methodToCall 249 shl $$2, %eax # %eax<- update offset 250 SAVEAREA_FROM_FP %ecx # %ecx<- &outs; &StackSaveArea 251 subl %eax, %ecx # %ecx<- newFP; (old savearea - regsSize) 252 movl rGLUE, %eax # %eax<- pMterpGlue 253 movl %ecx, sReg1 # sReg1<- &outs 254 subl $$sizeofStackSaveArea, %ecx # %ecx<- newSaveArea (stack save area using newFP) 255 movl offGlue_interpStackEnd(%eax), %eax # %eax<- glue->interpStackEnd 256 movl %eax, sReg2 # sReg2<- glue->interpStackEnd 257 shl $$2, %edx # %edx<- update offset for outsSize 258 movl %ecx, %eax # %eax<- newSaveArea 259 sub %edx, %ecx # %ecx<- bottom; (newSaveArea - outsSize) 260 cmp sReg2, %ecx # compare interpStackEnd and bottom 261 movl sReg0, %ecx # %ecx<- restore methodToCall 262 jl .LstackOverflow # handle frame overflow 263 264 /* 265 * set up newSaveArea 266 */ 267 268#ifdef EASY_GDB 269 SAVEAREA_FROM_FP %edx # %edx<- &outs; &StackSaveArea 270 movl %edx, offStackSaveArea_prevSave(%eax) # newSaveArea->prevSave<- &outs 271#endif 272 movl rFP, offStackSaveArea_prevFrame(%eax) # newSaveArea->prevFrame<- rFP 273 movl rPC, offStackSaveArea_savedPc(%eax) # newSaveArea->savedPc<- rPC 274 testl $$ACC_NATIVE, offMethod_accessFlags(%ecx) # check for native call 275 movl %ecx, offStackSaveArea_method(%eax) # newSaveArea->method<- method to call 276 jne .LinvokeNative # handle native call 277 278 /* 279 * Update "glue" values for the new method 280 * %ecx=methodToCall, sReg1=newFp 281 */ 282 283 movl offMethod_clazz(%ecx), %edx # %edx<- method->clazz 284 movl rGLUE, %eax # %eax<- pMterpGlue 285 movl %ecx, offGlue_method(%eax) # glue->method<- methodToCall 286 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 287 movl offMethod_insns(%ecx), rPC # rPC<- methodToCall->insns 288 movl %edx, offGlue_methodClassDex(%eax) # glue->methodClassDex<- method->clazz->pDvmDex 289 movl offGlue_self(%eax), %ecx # %ecx<- glue->self 290 movl sReg1, rFP # rFP<- newFP 291 movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 292 FINISH_A # jump to methodToCall->insns 293 294 /* 295 * Prep for the native call 296 * %ecx=methodToCall, sReg1=newFP, %eax=newSaveArea 297 */ 298 299.LinvokeNative: 300 movl rGLUE, %edx # %edx<- pMterpGlue 301 movl %ecx, -20(%esp) # push parameter methodToCall 302 movl offGlue_self(%edx), %edx # %edx<- glue->self 303 movl offThread_jniLocal_topCookie(%edx), %ecx # %ecx<- glue->self->thread->refNext 304 movl %ecx, offStackSaveArea_localRefCookie(%eax) # newSaveArea->localRefCookie<- refNext 305 movl %eax, -4(%esp) # save newSaveArea 306 movl sReg1, %eax # %eax<- newFP 307 movl %eax, offThread_curFrame(%edx) # glue->self->curFrame<- newFP 308 movl %edx, -8(%esp) # save glue->self 309 movl %edx, -16(%esp) # push parameter glue->self 310 movl rGLUE, %edx # %edx<- pMterpGlue 311 movl -20(%esp), %ecx # %ecx<- methodToCall 312 lea offGlue_retval(%edx), %edx # %edx<- &retval 313 movl %edx, -24(%esp) # push parameter pMterpGlue 314 movl %eax, -28(%esp) # push parameter newFP 315 lea -28(%esp), %esp 316 317#ifdef ASSIST_DEBUGGER 318 jmp .Lskip 319 .type dalvik_mterp, %function 320dalvik_mterp: 321 MTERP_ENTRY 322.Lskip: 323#endif 324 call *offMethod_nativeFunc(%ecx) # call methodToCall->nativeFunc 325 lea 28(%esp), %esp 326 movl -4(%esp), %edx # %edx<- newSaveArea 327 movl -8(%esp), %ecx # %ecx<- glue->self 328 movl offStackSaveArea_localRefCookie(%edx), %eax # %eax<- newSaveArea->localRefCookie 329 FFETCH_ADV 3, %edx # %edx<- next instruction hi; fetch, advance 330 cmp $$0, offThread_exception(%ecx) # check for exception 331 movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- rFP 332 movl %eax, offThread_jniLocal_topCookie(%ecx) # glue->self<- newSaveArea->localRefCookie 333 jne common_exceptionThrown # handle exception 334 FGETOP_JMP 3, %edx # jump to next instruction; getop, jmp 335 336.LstackOverflow: 337 movl rGLUE, %ecx # %ecx<- pMterpGlue 338 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 339 movl %ecx, -4(%esp) # push parameter self 340 lea -4(%esp), %esp 341 call dvmHandleStackOverflow # call: (Thread* self) 342 # return: void 343 lea 4(%esp), %esp 344 jmp common_exceptionThrown # handle exception 345#ifdef ASSIST_DEBUGGER 346#endif 347 348 /* 349 * Common code for handling a return instruction. 350 * 351 * This does not return. 352 */ 353 354common_returnFromMethod: 355.LreturnNew: 356 357 /* 358 * Inline common periodic checks 359 */ 360 361 movl rGLUE, rINST # %ecx<- pMterpGlue 362 movl offGlue_pSelfSuspendCount(rINST), %edx # %ebx<- pSuspendCount (int) 363#if defined(WITH_DEBUGGER) 364 movl offGlue_pDebuggerActive(rINST), %eax # %eax<- pDebuggerActive 365 movl (%eax), %eax # %eax<- get debuggerActive (boolean) 366 and $$7, %eax # %eax<- mask for boolean (just how many bits does it take?) 367#endif 368 cmp $$0, (%edx) # check if suspend is pending 369 jne 2f # handle suspend 370#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 371#if defined(WITH_PROFILER) 372 movl offGlue_pActiveProfilers(rINST), %edx # %edx<- activeProfilers (int) 373 or (%edx), %eax # %eax<- merge activeProfilers and debuggerActive 374#else 375 cmp $$0, %eax # check for debuggerActive 376#endif 377 jne 3f # debugger or profiler active; switch interp 378#endif 379 jmp 4f 3802: # check suspended 381 movl offGlue_self(rINST), %eax# %eax<- glue->self 382 movl %eax, -12(%esp) # push parameter boolean 383 lea -12(%esp), %esp 384 call dvmCheckSuspendPending # call: (Thread* self) 385 # return: bool 386 lea 12(%esp), %esp 387 jmp 4f 3883: # debugger/profiler enabled, bail out 389 movl $$kInterpEntryInstr, offGlue_entryPoint(rINST) # glue->entryPoint<- reentry type 390 movl $$1, %edx # switch to interp<- true 391 jmp common_gotoBail # bail 392 393 394 /* 395 * Get save area; rGLUE is %ebx, rFP is %eax 396 */ 3974: 398 SAVEAREA_FROM_FP %ecx # %ecx<- saveArea(old) 399 movl offStackSaveArea_prevFrame(%ecx), rFP # rFP<- saveArea->PrevFrame 400 movl (offStackSaveArea_method - sizeofStackSaveArea)(rFP), %edx # %edx<- method we are returning to 401 cmpl $$0, %edx # check for break frame 402 je common_gotoBail # bail if break frame 403 movl offStackSaveArea_savedPc(%ecx), rPC # rPC<- saveAreaOld->savedPc 404 movl offGlue_self(rINST), %ecx # %eax<- glue->self 405 movl %edx, offGlue_method(rINST) # glue->method<- newSave->method 406 movl offMethod_clazz(%edx), %edx # %edx<- method->clazz 407 FFETCH_ADV 3, %eax # %ecx<- next instruction hi; fetch, advance 408 movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- rFP 409 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 410 movl %edx, offGlue_methodClassDex(rINST) # glue->pDvmDex<- method->clazz->pDvmDex 411 FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp 412 413 /* 414 * Handle thrown an exception. If the exception processing code 415 * returns to us (instead of falling out of the interpreter), 416 * continue with whatever the next instruction now happens to be. 417 * This does not return. 418 */ 419 420common_exceptionThrown: 421.LexceptionNew: 422 movl $$kInterpEntryThrow, %ecx # %ecx<- reentry type 423 movl $$0, %edx # %edx<- pc adjustment 424 call common_periodicChecks 425 movl rGLUE, %eax # %eax<- pMterpGlue 426 movl offGlue_self(%eax), %edx # %edx<- glue->self 427 movl offThread_exception(%edx), %ecx # %ecx<- pMterpGlue->self->exception 428 movl %edx, -4(%esp) # push parameter self 429 movl %ecx, -8(%esp) # push parameter obj 430 lea -8(%esp), %esp 431 call dvmAddTrackedAlloc # don't allow the exception to be GC'd 432 # call: (Object* obj, Thread* self) 433 # return: void 434 movl 4(%esp), %edx # %edx<- glue->self 435 movl $$0, offThread_exception(%edx) # glue->self->exception<- NULL 436 437 /* 438 * set up args and a local for &fp 439 */ 440 441 movl rFP, -4(%esp) # move fp to stack 442 lea -4(%esp), %esp # update %esp 443 movl %esp, -4(%esp) # push parameter 4<- &fp 444 movl $$0, -8(%esp) # push parameter 3<- false 445 movl 4(%esp), %edx 446 movl %edx, -12(%esp) # push parameter 2<- glue->self->exception 447 movl rGLUE, %eax # %eax<- pMterpGlue 448 movl offGlue_method(%eax), %edx # %edx<- glue->method 449 movl offMethod_insns(%edx), %edx # %edx<- glue->method->insns 450 movl rPC, %ecx # %ecx<- rPC 451 subl %edx, %ecx # %ecx<- pc - glue->method->insns 452 sar $$1, %ecx # %ecx<- adjust %ecx for offset 453 movl %ecx, -16(%esp) # push parameter 1<- glue->method->insns 454 movl 8(%esp), %edx 455 movl %edx, -20(%esp) # push parameter 0<- glue->self 456 lea -20(%esp), %esp 457 458 /* 459 * call dvmFindCatchBlock, %eax gets catchRelPc (a code-unit offset) 460 */ 461 462 call dvmFindCatchBlock # call: (Thread* self, int relPc, Object* exception, 463 # bool doUnroll, void** newFrame) 464 # return: int 465 lea 32(%esp), %esp 466 movl -12(%esp), rFP # rFP<- updated rFP 467 cmp $$0, %eax # check for catchRelPc < 0 468 jl .LnotCaughtLocally # handle not caught locally 469 470 /* 471 * fix stack overflow if necessary 472 */ 473 474 movl -4(%esp), %ecx # %ecx<- glue->self 475 cmp $$0, offThread_stackOverflowed(%ecx) 476 je 1f 477 movl %eax, -4(%esp) # save %eax for later 478 movl %ecx, -12(%esp) # push parameter 2 glue->self 479 lea -12(%esp), %esp 480 call dvmCleanupStackOverflow # call: (Thread* self) 481 # return: void 482 lea 12(%esp), %esp 483 movl -4(%esp), %eax # %eax<- restore %eax 484 jmp 2f 4851: 486 movl %ecx, -12(%esp) # push parameter 2 glue->self 4872: 488 489 /* 490 * adjust locals to match self->curFrame and updated PC 491 * 492 */ 493 494 SAVEAREA_FROM_FP %edx # %edx<- get newSaveArea 495 movl rGLUE, %ecx # %ecx<- pMterpGlue 496 movl offStackSaveArea_method(%edx), rPC # rPC<- newMethod 497 movl rPC, offGlue_method(%ecx) # glue->method<- newMethod 498 movl offMethod_clazz(rPC), %edx # %edx<- method->clazz 499 movl offMethod_insns(rPC), rPC # rPC<- method->insns 500 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 501 lea (rPC, %eax, 2), rPC # rPC<- method->insns + catchRelPc 502 movl %edx, offGlue_methodClassDex(%ecx) # glue->pDvmDex<- method->clazz->pDvmDex 503 movl -8(%esp), %eax 504 movl %eax, -16(%esp) # push parameter 1 obj 505 lea -16(%esp), %esp 506 call dvmReleaseTrackedAlloc # call: (Object* obj, Thread* self) 507 # return: void 508 lea 16(%esp), %esp 509 FINISH_FETCH %eax 510 cmp $$OP_MOVE_EXCEPTION, %eax # is it a move exception 511 jne 1f 512 movl -12(%esp), %edx # %edx<- glue->self 513 movl -8(%esp), %ecx # %ecx<- exception 514 movl %ecx, offThread_exception(%edx) # restore the exception 5151: 516 FINISH_JMP %eax 517 518 /* 519 * -8(%esp) = exception, -4(%esp) = self 520 */ 521 522.LnotCaughtLocally: 523 movl -4(%esp), %edx # %edx<- glue->self 524 movzb offThread_stackOverflowed(%edx), %eax # %eax<- self->stackOverflowed 525 cmp $$0, %eax # check for stack overflow; 526 # maybe should use cmpb 527 je 1f # 528 movl %edx, -12(%esp) # push parameter 1 glue->self 529 lea -12(%esp), %esp 530 call dvmCleanupStackOverflow # call: (Thread* self) 531 # return: void 532 lea 12(%esp), %esp 533 534 /* 535 * Release the exception 536 * -8(%esp) = exception, -4(%esp) = self 537 */ 5381: 539 movl -8(%esp), %ecx # %ecx<- exception 540 movl -4(%esp), %edx # %edx<- glue->self 541 movl %ecx, offThread_exception(%edx) # glue->self<- exception 542 lea -8(%esp), %esp 543 call dvmReleaseTrackedAlloc # call: (Object* obj, Thread* self) 544 # return: void 545 lea 8(%esp), %esp 546 movl $$0, %edx # switch to interp<- false 547 jmp common_gotoBail # bail 548 549 /* 550 * After returning from a "glued" function, pull out the updated 551 * values and start executing at the next instruction. 552 */ 553 554common_resumeAfterGlueCall: 555 LOAD_PC_FP_FROM_GLUE # pull rPC and rFP out of glue 556 FINISH_A # jump to next instruction 557 558 /* 559 * For debugging, cause an immediate fault. 560 */ 561 562common_abort: 563 jmp .LdeadFood 564 565.LdeadFood: 566.word 0xdeadf00d 567 568 /* 569 * Invalid array index. 570 */ 571 572common_errArrayIndex: 573 EXPORT_PC 574 movl $$.LstrArrayIndexException, -8(%esp) # push parameter description 575 movl $$0, -4(%esp) # push parameter msg paramter 576 lea -8(%esp), %esp 577 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 578 # return: void 579 lea 8(%esp), %esp 580 jmp common_exceptionThrown # handle exception 581 582 /* 583 * Invalid array value. 584 */ 585 586common_errArrayStore: 587 EXPORT_PC 588 movl $$.LstrArrayStoreException, -8(%esp) # push parameter description 589 movl $$0, -4(%esp) # push parameter msg paramter 590 lea -8(%esp), %esp 591 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 592 # return: void 593 lea 8(%esp), %esp 594 jmp common_exceptionThrown # handle exception 595 596 /* 597 * Integer divide or mod by zero. 598 */ 599 600common_errDivideByZero: 601 EXPORT_PC 602 movl $$.LstrArithmeticException, -8(%esp) # push parameter description 603 movl $$.LstrDivideByZero, -4(%esp) # push parameter msg paramter 604 lea -8(%esp), %esp 605 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 606 # return: void 607 lea 8(%esp), %esp 608 jmp common_exceptionThrown # handle exception 609 610 /* 611 * Attempt to allocate an array with a negative size. 612 */ 613 614common_errNegativeArraySize: 615 EXPORT_PC 616 movl $$.LstrNegativeArraySizeException, -8(%esp) # push parameter description 617 movl $$0, -4(%esp) # push parameter msg paramter 618 lea -8(%esp), %esp 619 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 620 # return: void 621 lea 8(%esp), %esp 622 jmp common_exceptionThrown # handle exception 623 624 /* 625 * Invocation of a non-existent method. 626 */ 627 628common_errNoSuchMethod: 629 EXPORT_PC 630 movl $$.LstrNoSuchMethodError, -8(%esp) # push parameter description 631 movl $$0, -4(%esp) # push parameter msg paramter 632 lea -8(%esp), %esp 633 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 634 # return: void 635 lea 8(%esp), %esp 636 jmp common_exceptionThrown # handle exception 637 638 /* 639 * Unexpected null object. 640 */ 641 642common_errNullObject: 643 EXPORT_PC 644 movl $$.LstrNullPointerException, -8(%esp) # push parameter description 645 movl $$0, -4(%esp) # push parameter msg paramter 646 lea -8(%esp), %esp 647 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 648 # return: void 649 lea 8(%esp), %esp 650 jmp common_exceptionThrown # handle exception 651 652 /* 653 * String references 654 */ 655 656 .align 4 657 .section .rodata 658.LstrArithmeticException: 659 .asciz "Ljava/lang/ArithmeticException;" 660.LstrArrayIndexException: 661 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 662.LstrArrayStoreException: 663 .asciz "Ljava/lang/ArrayStoreException;" 664.LstrClassCastException: 665 .asciz "Ljava/lang/ClassCastException;" 666.LstrDivideByZero: 667 .asciz "divide by zero" 668.LstrInstantiationError: 669 .asciz "Ljava/lang/InstantiationError;" 670.LstrNegativeArraySizeException: 671 .asciz "Ljava/lang/NegativeArraySizeException;" 672.LstrNoSuchMethodError: 673 .asciz "Ljava/lang/NoSuchMethodError;" 674.LstrNullPointerException: 675 .asciz "Ljava/lang/NullPointerException;" 676.LstrExceptionNotCaughtLocally: 677 .asciz "Exception %s from %s:%d not caught locally\n" 678