| %verify "executed" |
| %verify "exception handled" |
| /* |
| * Execute a "native inline" instruction. |
| * |
| * We will be calling through a function table: |
| * |
| * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult) |
| * |
| * Ignores argument count - always loads 4. |
| * |
| */ |
| /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ |
| movl rSELF,%ecx |
| EXPORT_PC |
| movzwl 2(rPC),%eax # eax<- BBBB |
| SPILL(rIBASE) # preserve rIBASE |
| movl offThread_subMode(%ecx), %edx # edx<- submode flags |
| andl $$kSubModeDebugProfile, %edx # debug or profile mode active? |
| jnz .L${opcode}_debugprofile # yes, take slow path |
| .L${opcode}_resume: |
| leal offThread_retval(%ecx),%ecx # ecx<- &self->retval |
| movl %ecx,OUT_ARG4(%esp) |
| call .L${opcode}_continue # make call; will return after |
| UNSPILL(rIBASE) # restore rIBASE |
| testl %eax,%eax # successful? |
| jz common_exceptionThrown # no, handle exception |
| FETCH_INST_OPCODE 3 %ecx |
| ADVANCE_PC 3 |
| GOTO_NEXT_R %ecx |
| |
| .L${opcode}_continue: |
| /* |
| * Extract args, call function. |
| * ecx = #of args (0-4) |
| * eax = call index |
| * @esp = return addr |
| * esp is -4 from normal |
| * |
| * Go ahead and load all 4 args, even if not used. |
| */ |
| movzwl 4(rPC),rIBASE |
| |
| movl $$0xf,%ecx |
| andl rIBASE,%ecx |
| GET_VREG_R %ecx %ecx |
| sarl $$4,rIBASE |
| movl %ecx,4+OUT_ARG0(%esp) |
| |
| movl $$0xf,%ecx |
| andl rIBASE,%ecx |
| GET_VREG_R %ecx %ecx |
| sarl $$4,rIBASE |
| movl %ecx,4+OUT_ARG1(%esp) |
| |
| movl $$0xf,%ecx |
| andl rIBASE,%ecx |
| GET_VREG_R %ecx %ecx |
| sarl $$4,rIBASE |
| movl %ecx,4+OUT_ARG2(%esp) |
| |
| movl $$0xf,%ecx |
| andl rIBASE,%ecx |
| GET_VREG_R %ecx %ecx |
| sarl $$4,rIBASE |
| movl %ecx,4+OUT_ARG3(%esp) |
| |
| sall $$4,%eax # index *= sizeof(table entry) |
| jmp *gDvmInlineOpsTable(%eax) |
| # will return to caller of .L${opcode}_continue |
| |
| /* |
| * We're debugging or profiling. |
| * eax: opIndex |
| */ |
| .L${opcode}_debugprofile: |
| movl %eax,OUT_ARG0(%esp) # arg0<- BBBB |
| SPILL_TMP1(%eax) # save opIndex |
| call dvmResolveInlineNative # dvmResolveInlineNative(opIndex) |
| movl rSELF,%ecx # restore self |
| testl %eax,%eax # method resolved? |
| movl %eax,%edx # save possibly resolved method in edx |
| UNSPILL_TMP1(%eax) # in case not resolved, restore opIndex |
| jz .L${opcode}_resume # not resolved, just move on |
| SPILL_TMP2(%edx) # save method |
| movl %edx,OUT_ARG0(%esp) # arg0<- method |
| movl %ecx,OUT_ARG1(%esp) # arg1<- self |
| call dvmFastMethodTraceEnter # dvmFastMethodTraceEnter(method,self) |
| movl rSELF,%ecx # restore self |
| UNSPILL_TMP1(%eax) # restore opIndex |
| leal offThread_retval(%ecx),%ecx # ecx<- &self->retval |
| movl %ecx,OUT_ARG4(%esp) # needed for pResult of inline operation handler |
| call .L${opcode}_continue # make call; will return after |
| SPILL_TMP1(%eax) # save result of inline |
| UNSPILL_TMP2(%eax) # restore method |
| movl rSELF,%ecx # restore self |
| movl %eax,OUT_ARG0(%esp) # arg0<- method |
| movl %ecx,OUT_ARG1(%esp) # arg1<- self |
| call dvmFastNativeMethodTraceExit # dvmFastNativeMethodTraceExit(method,self) |
| UNSPILL(rIBASE) # restore rIBASE |
| UNSPILL_TMP1(%eax) # restore result of inline |
| testl %eax,%eax # successful? |
| jz common_exceptionThrown # no, handle exception |
| FETCH_INST_OPCODE 3 %ecx |
| ADVANCE_PC 3 |
| GOTO_NEXT_R %ecx |