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