1418d20fc407052d4152157f61e7453359f902383Elliott Hughes/* 2418d20fc407052d4152157f61e7453359f902383Elliott Hughes * Copyright (C) 2011 The Android Open Source Project 3418d20fc407052d4152157f61e7453359f902383Elliott Hughes * 4418d20fc407052d4152157f61e7453359f902383Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5418d20fc407052d4152157f61e7453359f902383Elliott Hughes * you may not use this file except in compliance with the License. 6418d20fc407052d4152157f61e7453359f902383Elliott Hughes * You may obtain a copy of the License at 7418d20fc407052d4152157f61e7453359f902383Elliott Hughes * 8418d20fc407052d4152157f61e7453359f902383Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9418d20fc407052d4152157f61e7453359f902383Elliott Hughes * 10418d20fc407052d4152157f61e7453359f902383Elliott Hughes * Unless required by applicable law or agreed to in writing, software 11418d20fc407052d4152157f61e7453359f902383Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12418d20fc407052d4152157f61e7453359f902383Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13418d20fc407052d4152157f61e7453359f902383Elliott Hughes * See the License for the specific language governing permissions and 14418d20fc407052d4152157f61e7453359f902383Elliott Hughes * limitations under the License. 15418d20fc407052d4152157f61e7453359f902383Elliott Hughes */ 16418d20fc407052d4152157f61e7453359f902383Elliott Hughes 17418d20fc407052d4152157f61e7453359f902383Elliott Hughes#include "reflection.h" 18418d20fc407052d4152157f61e7453359f902383Elliott Hughes 19418d20fc407052d4152157f61e7453359f902383Elliott Hughes#include "class_linker.h" 2062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h" 214f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 225d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao#include "invoke_arg_array_builder.h" 23418d20fc407052d4152157f61e7453359f902383Elliott Hughes#include "jni_internal.h" 24ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h" 25ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h" 272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array.h" 292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 306d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h" 3100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 3200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "well_known_classes.h" 33418d20fc407052d4152157f61e7453359f902383Elliott Hughes 34418d20fc407052d4152157f61e7453359f902383Elliott Hughesnamespace art { 35418d20fc407052d4152157f61e7453359f902383Elliott Hughes 3600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersjobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, jobject javaReceiver, 37365c10235438607541fa2259a5fec48061b90bd8Ian Rogers jobject javaArgs) { 3800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers jmethodID mid = soa.Env()->FromReflectedMethod(javaMethod); 39ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = soa.DecodeMethod(mid); 402a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 412dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* declaring_class = m->GetDeclaringClass(); 420045a290e6b79a274250e3112880c04bde437d4aIan Rogers if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaring_class, true, true)) { 432a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes return NULL; 442a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes } 452a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* receiver = NULL; 472a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes if (!m->IsStatic()) { 482a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes // Check that the receiver is non-null and an instance of the field's declaring class. 492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers receiver = soa.Decode<mirror::Object*>(javaReceiver); 50eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes if (!VerifyObjectInClass(receiver, declaring_class)) { 512a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes return NULL; 522a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes } 532a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 542a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes // Find the actual implementation of the virtual method. 552a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m); 5600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mid = soa.EncodeMethod(m); 572a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes } 582a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 592a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes // Get our arrays of arguments and their types, and check they're the same size. 602dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::ObjectArray<mirror::Object>* objects = 612dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs); 626d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers MethodHelper mh(m); 636d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers const DexFile::TypeList* classes = mh.GetParameterTypeList(); 646d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers uint32_t classes_size = classes == NULL ? 0 : classes->Size(); 656d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers uint32_t arg_count = (objects != NULL) ? objects->GetLength() : 0; 666d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (arg_count != classes_size) { 6762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowIllegalArgumentException(NULL, 6862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("Wrong number of arguments; expected %d, got %d", 6962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers classes_size, arg_count).c_str()); 702a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes return NULL; 712a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes } 722a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 732a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes // Translate javaArgs to a jvalue[]. 742a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes UniquePtr<jvalue[]> args(new jvalue[arg_count]); 752a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes JValue* decoded_args = reinterpret_cast<JValue*>(args.get()); 766d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers for (uint32_t i = 0; i < arg_count; ++i) { 772dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* arg = objects->Get(i); 782dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* dst_class = mh.GetClassFromTypeIdx(classes->GetTypeItem(i).type_idx_); 7937f7775b92398d87e48bc306f9d10a1b563dcdd5Elliott Hughes if (!UnboxPrimitiveForArgument(arg, dst_class, decoded_args[i], m, i)) { 8037f7775b92398d87e48bc306f9d10a1b563dcdd5Elliott Hughes return NULL; 8137f7775b92398d87e48bc306f9d10a1b563dcdd5Elliott Hughes } 8237f7775b92398d87e48bc306f9d10a1b563dcdd5Elliott Hughes if (!dst_class->IsPrimitive()) { 8300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers args[i].l = soa.AddLocalReference<jobject>(arg); 842a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes } 852a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes } 862a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 872a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes // Invoke the method. 8800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JValue value(InvokeWithJValues(soa, javaReceiver, mid, args.get())); 892a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 902a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early. 9100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (soa.Self()->IsExceptionPending()) { 9200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers jthrowable th = soa.Env()->ExceptionOccurred(); 9300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers soa.Env()->ExceptionClear(); 9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers jclass exception_class = soa.Env()->FindClass("java/lang/reflect/InvocationTargetException"); 9500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V"); 9600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th); 9700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance)); 982a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes return NULL; 992a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes } 1002a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 1012a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes // Box if necessary and return. 102af6e67a4816d2593586115b89faa659225363246Ian Rogers return soa.AddLocalReference<jobject>(BoxPrimitive(mh.GetReturnType()->GetPrimitiveType(), value)); 1032a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes} 1042a20cfd0b7fc81099f5de0da782ebcc1cb262792Elliott Hughes 1052dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersbool VerifyObjectInClass(mirror::Object* o, mirror::Class* c) { 106418d20fc407052d4152157f61e7453359f902383Elliott Hughes if (o == NULL) { 10762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowNullPointerException(NULL, "null receiver"); 10862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return false; 109b600b3f8360f535913fedc91aef7c8e5abaca48aElliott Hughes } else if (!o->InstanceOf(c)) { 110b600b3f8360f535913fedc91aef7c8e5abaca48aElliott Hughes std::string expected_class_name(PrettyDescriptor(c)); 111b600b3f8360f535913fedc91aef7c8e5abaca48aElliott Hughes std::string actual_class_name(PrettyTypeOf(o)); 11262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowIllegalArgumentException(NULL, 11362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("Expected receiver of type %s, but got %s", 11462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers expected_class_name.c_str(), 11562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers actual_class_name.c_str()).c_str()); 116418d20fc407052d4152157f61e7453359f902383Elliott Hughes return false; 117418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 118418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 119418d20fc407052d4152157f61e7453359f902383Elliott Hughes} 120418d20fc407052d4152157f61e7453359f902383Elliott Hughes 12162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersbool ConvertPrimitiveValue(const ThrowLocation* throw_location, bool unbox_for_result, 12262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Primitive::Type srcType, Primitive::Type dstType, 1236b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom const JValue& src, JValue& dst) { 124c129a6b44193ac3a872f852a69d336e0e7ed8640Jesse Wilson CHECK(srcType != Primitive::kPrimNot && dstType != Primitive::kPrimNot); 125418d20fc407052d4152157f61e7453359f902383Elliott Hughes switch (dstType) { 1266b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimBoolean: 127f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes if (srcType == Primitive::kPrimBoolean) { 128f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetZ(src.GetZ()); 129f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes return true; 130f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes } 131f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes break; 1326b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimChar: 133f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes if (srcType == Primitive::kPrimChar) { 134f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetC(src.GetC()); 135f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes return true; 136f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes } 137f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes break; 1386b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimByte: 139f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes if (srcType == Primitive::kPrimByte) { 140f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetB(src.GetB()); 141418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 142418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 143418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 1446b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimShort: 1456b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimShort) { 146f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetS(src.GetI()); 147418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 148418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 149418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 1506b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimInt: 1516b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || 1526b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { 153f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetI(src.GetI()); 154418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 155418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 156418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 1576b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimLong: 1586b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || 1596b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { 160f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetJ(src.GetI()); 161418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 1626b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom } else if (srcType == Primitive::kPrimLong) { 163f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetJ(src.GetJ()); 164418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 165418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 166418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 1676b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimFloat: 1686b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || 1696b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { 170f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetF(src.GetI()); 171418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 1726b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom } else if (srcType == Primitive::kPrimLong) { 173f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetF(src.GetJ()); 174418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 1756b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom } else if (srcType == Primitive::kPrimFloat) { 176f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetF(src.GetF()); 177418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 178418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 179418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 1806b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimDouble: 1816b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || 1826b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { 183f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetD(src.GetI()); 184418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 1856b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom } else if (srcType == Primitive::kPrimLong) { 186f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetD(src.GetJ()); 187418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 1886b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom } else if (srcType == Primitive::kPrimFloat) { 189f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetD(src.GetF()); 190418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 1916b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom } else if (srcType == Primitive::kPrimDouble) { 192f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes dst.SetJ(src.GetJ()); 193418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 194418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 195418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 196418d20fc407052d4152157f61e7453359f902383Elliott Hughes default: 197418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 198418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 19962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (!unbox_for_result) { 20062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowIllegalArgumentException(throw_location, 20162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("Invalid primitive conversion from %s to %s", 20262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(srcType).c_str(), 20362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(dstType).c_str()).c_str()); 20462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 20562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowClassCastException(throw_location, 20662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("Couldn't convert result of type %s to %s", 20762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(srcType).c_str(), 208df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom PrettyDescriptor(dstType).c_str()).c_str()); 20962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 210418d20fc407052d4152157f61e7453359f902383Elliott Hughes return false; 211418d20fc407052d4152157f61e7453359f902383Elliott Hughes} 212418d20fc407052d4152157f61e7453359f902383Elliott Hughes 2132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersmirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) { 2146b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom if (src_class == Primitive::kPrimNot) { 215af6e67a4816d2593586115b89faa659225363246Ian Rogers return value.GetL(); 216418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 217418d20fc407052d4152157f61e7453359f902383Elliott Hughes 21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers jmethodID m = NULL; 2196b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom switch (src_class) { 2206b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimBoolean: 22100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers m = WellKnownClasses::java_lang_Boolean_valueOf; 222418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 2236b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimByte: 22400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers m = WellKnownClasses::java_lang_Byte_valueOf; 225418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 2266b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimChar: 22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers m = WellKnownClasses::java_lang_Character_valueOf; 228418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 2296b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimDouble: 23000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers m = WellKnownClasses::java_lang_Double_valueOf; 231418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 2326b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimFloat: 23300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers m = WellKnownClasses::java_lang_Float_valueOf; 234418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 2356b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimInt: 23600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers m = WellKnownClasses::java_lang_Integer_valueOf; 237418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 2386b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimLong: 23900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers m = WellKnownClasses::java_lang_Long_valueOf; 240418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 2416b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimShort: 24200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers m = WellKnownClasses::java_lang_Short_valueOf; 243418d20fc407052d4152157f61e7453359f902383Elliott Hughes break; 2446b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom case Primitive::kPrimVoid: 245418d20fc407052d4152157f61e7453359f902383Elliott Hughes // There's no such thing as a void field, and void methods invoked via reflection return null. 246af6e67a4816d2593586115b89faa659225363246Ian Rogers return NULL; 247418d20fc407052d4152157f61e7453359f902383Elliott Hughes default: 2486b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom LOG(FATAL) << static_cast<int>(src_class); 249418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 250418d20fc407052d4152157f61e7453359f902383Elliott Hughes 25150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 25200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (kIsDebugBuild) { 25350b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers CHECK_EQ(soa.Self()->GetState(), kRunnable); 25400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 2555d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao 2565d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao ArgArray arg_array(NULL, 0); 257af6e67a4816d2593586115b89faa659225363246Ian Rogers JValue result; 2585d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao if (src_class == Primitive::kPrimDouble || src_class == Primitive::kPrimLong) { 2595d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao arg_array.AppendWide(value.GetJ()); 2605d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao } else { 2615d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao arg_array.Append(value.GetI()); 2625d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao } 2635d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao 2645d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao soa.DecodeMethod(m)->Invoke(soa.Self(), arg_array.GetArray(), arg_array.GetNumBytes(), 2656474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao &result, 'L'); 266af6e67a4816d2593586115b89faa659225363246Ian Rogers return result.GetL(); 267418d20fc407052d4152157f61e7453359f902383Elliott Hughes} 268418d20fc407052d4152157f61e7453359f902383Elliott Hughes 269ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic std::string UnboxingFailureKind(mirror::ArtMethod* m, int index, mirror::ArtField* f) 270b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 27184a5bb4556d8974d3aa1c436af36e48d622b4045Elliott Hughes if (m != NULL && index != -1) { 2727934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom ++index; // Humans count from 1. 27384a5bb4556d8974d3aa1c436af36e48d622b4045Elliott Hughes return StringPrintf("method %s argument %d", PrettyMethod(m, false).c_str(), index); 274aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes } 275aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes if (f != NULL) { 276aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes return "field " + PrettyField(f, false); 277aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes } 278aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes return "result"; 279aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes} 280aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes 28162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic bool UnboxPrimitive(const ThrowLocation* throw_location, mirror::Object* o, 28262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Class* dst_class, JValue& unboxed_value, 283ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m, int index, mirror::ArtField* f) 284b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 28562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers bool unbox_for_result = (f == NULL) && (index == -1); 2866b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom if (!dst_class->IsPrimitive()) { 28762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (UNLIKELY(o != NULL && !o->InstanceOf(dst_class))) { 28862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (!unbox_for_result) { 28962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowIllegalArgumentException(throw_location, 29062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("%s has type %s, got %s", 29162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers UnboxingFailureKind(m, index, f).c_str(), 29262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(dst_class).c_str(), 29362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyTypeOf(o).c_str()).c_str()); 29462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 29562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowClassCastException(throw_location, 29662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("Couldn't convert result of type %s to %s", 29762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyTypeOf(o).c_str(), 298df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom PrettyDescriptor(dst_class).c_str()).c_str()); 29962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 300418d20fc407052d4152157f61e7453359f902383Elliott Hughes return false; 301418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 302f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes unboxed_value.SetL(o); 303418d20fc407052d4152157f61e7453359f902383Elliott Hughes return true; 30462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 30562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (UNLIKELY(dst_class->GetPrimitiveType() == Primitive::kPrimVoid)) { 30662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowIllegalArgumentException(throw_location, 30762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("Can't unbox %s to void", 30862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers UnboxingFailureKind(m, index, f).c_str()).c_str()); 309418d20fc407052d4152157f61e7453359f902383Elliott Hughes return false; 310418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 31162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (UNLIKELY(o == NULL)) { 31262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (!unbox_for_result) { 31362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowIllegalArgumentException(throw_location, 31462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("%s has type %s, got null", 31562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers UnboxingFailureKind(m, index, f).c_str(), 31662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(dst_class).c_str()).c_str()); 31762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 31862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowNullPointerException(throw_location, 31962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("Expected to unbox a '%s' primitive type but was returned null", 32062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(dst_class).c_str()).c_str()); 32162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 322418d20fc407052d4152157f61e7453359f902383Elliott Hughes return false; 323418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 324418d20fc407052d4152157f61e7453359f902383Elliott Hughes 3251d878f3e1c39162496d7c061f7f6710e414d182bElliott Hughes JValue boxed_value; 326955724179c6c739524f610023287f56b24dc31deElliott Hughes std::string src_descriptor(ClassHelper(o->GetClass()).GetDescriptor()); 3272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* src_class = NULL; 328418d20fc407052d4152157f61e7453359f902383Elliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 329ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0); 3306d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (src_descriptor == "Ljava/lang/Boolean;") { 331418d20fc407052d4152157f61e7453359f902383Elliott Hughes src_class = class_linker->FindPrimitiveClass('Z'); 332f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes boxed_value.SetZ(primitive_field->GetBoolean(o)); 3336d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers } else if (src_descriptor == "Ljava/lang/Byte;") { 334418d20fc407052d4152157f61e7453359f902383Elliott Hughes src_class = class_linker->FindPrimitiveClass('B'); 335f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes boxed_value.SetB(primitive_field->GetByte(o)); 3366d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers } else if (src_descriptor == "Ljava/lang/Character;") { 337418d20fc407052d4152157f61e7453359f902383Elliott Hughes src_class = class_linker->FindPrimitiveClass('C'); 338f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes boxed_value.SetC(primitive_field->GetChar(o)); 3396d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers } else if (src_descriptor == "Ljava/lang/Float;") { 340418d20fc407052d4152157f61e7453359f902383Elliott Hughes src_class = class_linker->FindPrimitiveClass('F'); 341f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes boxed_value.SetF(primitive_field->GetFloat(o)); 3426d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers } else if (src_descriptor == "Ljava/lang/Double;") { 343418d20fc407052d4152157f61e7453359f902383Elliott Hughes src_class = class_linker->FindPrimitiveClass('D'); 344f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes boxed_value.SetD(primitive_field->GetDouble(o)); 3456d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers } else if (src_descriptor == "Ljava/lang/Integer;") { 346418d20fc407052d4152157f61e7453359f902383Elliott Hughes src_class = class_linker->FindPrimitiveClass('I'); 347f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes boxed_value.SetI(primitive_field->GetInt(o)); 3486d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers } else if (src_descriptor == "Ljava/lang/Long;") { 349418d20fc407052d4152157f61e7453359f902383Elliott Hughes src_class = class_linker->FindPrimitiveClass('J'); 350f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes boxed_value.SetJ(primitive_field->GetLong(o)); 3516d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers } else if (src_descriptor == "Ljava/lang/Short;") { 352418d20fc407052d4152157f61e7453359f902383Elliott Hughes src_class = class_linker->FindPrimitiveClass('S'); 353f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes boxed_value.SetS(primitive_field->GetShort(o)); 354418d20fc407052d4152157f61e7453359f902383Elliott Hughes } else { 35562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowIllegalArgumentException(throw_location, 35662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers StringPrintf("%s has type %s, got %s", 35762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers UnboxingFailureKind(m, index, f).c_str(), 35862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(dst_class).c_str(), 359df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom PrettyDescriptor(src_descriptor.c_str()).c_str()).c_str()); 360418d20fc407052d4152157f61e7453359f902383Elliott Hughes return false; 361418d20fc407052d4152157f61e7453359f902383Elliott Hughes } 362418d20fc407052d4152157f61e7453359f902383Elliott Hughes 36362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return ConvertPrimitiveValue(throw_location, unbox_for_result, 36462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers src_class->GetPrimitiveType(), dst_class->GetPrimitiveType(), 3656b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom boxed_value, unboxed_value); 366418d20fc407052d4152157f61e7453359f902383Elliott Hughes} 367418d20fc407052d4152157f61e7453359f902383Elliott Hughes 3682dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersbool UnboxPrimitiveForArgument(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value, 369ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m, size_t index) { 37084a5bb4556d8974d3aa1c436af36e48d622b4045Elliott Hughes CHECK(m != NULL); 37162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return UnboxPrimitive(NULL, o, dst_class, unboxed_value, m, index, NULL); 372aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes} 373aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes 3742dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersbool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, JValue& unboxed_value, 375ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f) { 376aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes CHECK(f != NULL); 37762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return UnboxPrimitive(NULL, o, dst_class, unboxed_value, NULL, -1, f); 378aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes} 379aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes 38062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersbool UnboxPrimitiveForResult(const ThrowLocation& throw_location, mirror::Object* o, 38162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Class* dst_class, JValue& unboxed_value) { 38262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return UnboxPrimitive(&throw_location, o, dst_class, unboxed_value, NULL, -1, NULL); 383aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes} 384aaa5edcf2deb1bddcbf5fb27820ad2240ac5b4f2Elliott Hughes 385418d20fc407052d4152157f61e7453359f902383Elliott Hughes} // namespace art 386