/* * Find the return type in the signature, and convert it to a class * object. For primitive types we use a boxed class, for reference types * we do a name lookup. * * On failure, we return NULL with an exception raised. */ ClassObject* dvmGetBoxedReturnType(const Method* meth) { const char* sig = dexProtoGetReturnType(&meth->prototype); switch (*sig) { case 'Z': case 'C': case 'F': case 'D': case 'B': case 'S': case 'I': case 'J': case 'V': return dvmFindPrimitiveClass(*sig); case '[': case 'L': return dvmFindClass(sig, meth->clazz->classLoader); default: { /* should not have passed verification */ char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); ALOGE("Bad return type in signature '%s'", desc); free(desc); dvmThrowInternalError(NULL); return NULL; } } }
GOTO_TARGET(filledNewArray, bool methodCallRange, bool) { ClassObject* arrayClass; ArrayObject* newArray; u4* contents; char typeCh; int i; u4 arg5; EXPORT_PC(); ref = FETCH(1); /* class ref */ vdst = FETCH(2); /* first 4 regs -or- range base */ if (methodCallRange) { vsrc1 = INST_AA(inst); /* #of elements */ arg5 = -1; /* silence compiler warning */ ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}", vsrc1, ref, vdst, vdst+vsrc1-1); } else { arg5 = INST_A(inst); vsrc1 = INST_B(inst); /* #of elements */ ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}", vsrc1, ref, vdst, arg5); } /* * Resolve the array class. */ arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); if (arrayClass == NULL) { arrayClass = dvmResolveClass(curMethod->clazz, ref, false); if (arrayClass == NULL) GOTO_exceptionThrown(); } /* if (!dvmIsArrayClass(arrayClass)) { dvmThrowRuntimeException( "filled-new-array needs array class"); GOTO_exceptionThrown(); } */ /* verifier guarantees this is an array class */ assert(dvmIsArrayClass(arrayClass)); assert(dvmIsClassInitialized(arrayClass)); /* * Create an array of the specified type. */ LOGVV("+++ filled-new-array type is '%s'", arrayClass->descriptor); typeCh = arrayClass->descriptor[1]; if (typeCh == 'D' || typeCh == 'J') { /* category 2 primitives not allowed */ dvmThrowRuntimeException("bad filled array req"); GOTO_exceptionThrown(); } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') { /* TODO: requires multiple "fill in" loops with different widths */ ALOGE("non-int primitives not implemented"); dvmThrowInternalError( "filled-new-array not implemented for anything but 'int'"); GOTO_exceptionThrown(); } newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK); if (newArray == NULL) GOTO_exceptionThrown(); /* * Fill in the elements. It's legal for vsrc1 to be zero. */ contents = (u4*)(void*)newArray->contents; if (methodCallRange) { for (i = 0; i < vsrc1; i++) contents[i] = GET_REGISTER(vdst+i); } else { assert(vsrc1 <= 5); if (vsrc1 == 5) { contents[4] = GET_REGISTER(arg5); vsrc1--; } for (i = 0; i < vsrc1; i++) { contents[i] = GET_REGISTER(vdst & 0x0f); vdst >>= 4; } } if (typeCh == 'L' || typeCh == '[') { dvmWriteBarrierArray(newArray, 0, newArray->length); } retval.l = (Object*)newArray; }