| %verify "executed" |
| %verify "negative array length" |
| %verify "allocation fails" |
| /* |
| * Allocate an array of objects, specified with the array class |
| * and a count. |
| * |
| * The verifier guarantees that this is an array class, so we don't |
| * check for it here. |
| */ |
| /* new-array vA, vB, class@CCCC */ |
| GET_GLUE(%ecx) |
| EXPORT_PC() |
| movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex |
| movzwl 2(rPC),%eax # eax<- CCCC |
| movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses |
| movl (%ecx,%eax,4),%ecx # ecx<- resolved class |
| movzbl rINST_HI,%eax |
| sarl $$4,%eax # eax<- B |
| GET_VREG(%eax,%eax) # eax<- vB (array length) |
| movzbl rINST_HI,rINST_FULL |
| andb $$0xf,rINST_LO # rINST_FULL<- A |
| testl %eax,%eax |
| js common_errNegativeArraySize # bail |
| testl %ecx,%ecx # already resolved? |
| jne .L${opcode}_finish # yes, fast path |
| jmp .L${opcode}_resolve # resolve now |
| %break |
| |
| /* |
| * Resolve class. (This is an uncommon case.) |
| * ecx holds class (null here) |
| * eax holds array length (vB) |
| */ |
| .L${opcode}_resolve: |
| GET_GLUE(%ecx) |
| SPILL_TMP(%eax) # save array length |
| movl offGlue_method(%ecx),%ecx # ecx<- glue->method |
| movzwl 2(rPC),%eax # eax<- CCCC |
| movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz |
| movl %eax,OUT_ARG1(%esp) |
| movl $$0,OUT_ARG2(%esp) |
| movl %ecx,OUT_ARG0(%esp) |
| SPILL(rPC) |
| call dvmResolveClass # eax<- call(clazz,ref,flag) |
| UNSPILL(rPC) |
| movl %eax,%ecx |
| UNSPILL_TMP(%eax) |
| testl %ecx,%ecx # successful resolution? |
| je common_exceptionThrown # no, bail. |
| # fall through to ${opcode}_finish |
| |
| /* |
| * Finish allocation |
| * |
| * ecx holds class |
| * eax holds array length (vB) |
| */ |
| .L${opcode}_finish: |
| movl %ecx,OUT_ARG0(%esp) |
| movl %eax,OUT_ARG1(%esp) |
| movl $$ALLOC_DONT_TRACK,OUT_ARG2(%esp) |
| SPILL(rPC) |
| call dvmAllocArrayByClass # eax<- call(clazz,length,flags) |
| UNSPILL(rPC) |
| testl %eax,%eax # failed? |
| je common_exceptionThrown # yup - go handle |
| movl rINST_FULL,%ecx |
| FETCH_INST_WORD(2) |
| SET_VREG(%eax,%ecx) |
| ADVANCE_PC(2) |
| GOTO_NEXT |
| |