1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_REFLECTION_INL_H_
18 #define ART_RUNTIME_REFLECTION_INL_H_
19 
20 #include "reflection.h"
21 
22 #include "android-base/stringprintf.h"
23 
24 #include "base/utils.h"
25 #include "common_throws.h"
26 #include "dex/descriptors_names.h"
27 #include "dex/primitive.h"
28 #include "jvalue-inl.h"
29 #include "mirror/object-inl.h"
30 #include "obj_ptr-inl.h"
31 
32 namespace art {
33 
ConvertPrimitiveValueNoThrow(Primitive::Type srcType,Primitive::Type dstType,const JValue & src,JValue * dst)34 inline bool ConvertPrimitiveValueNoThrow(Primitive::Type srcType,
35                                          Primitive::Type dstType,
36                                          const JValue& src,
37                                          JValue* dst) {
38   DCHECK(srcType != Primitive::kPrimNot && dstType != Primitive::kPrimNot);
39   if (LIKELY(srcType == dstType)) {
40     dst->SetJ(src.GetJ());
41     return true;
42   }
43   switch (dstType) {
44   case Primitive::kPrimBoolean:  // Fall-through.
45   case Primitive::kPrimChar:  // Fall-through.
46   case Primitive::kPrimByte:
47     // Only expect assignment with source and destination of identical type.
48     break;
49   case Primitive::kPrimShort:
50     if (srcType == Primitive::kPrimByte) {
51       dst->SetS(src.GetI());
52       return true;
53     }
54     break;
55   case Primitive::kPrimInt:
56     if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
57         srcType == Primitive::kPrimShort) {
58       dst->SetI(src.GetI());
59       return true;
60     }
61     break;
62   case Primitive::kPrimLong:
63     if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
64         srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
65       dst->SetJ(src.GetI());
66       return true;
67     }
68     break;
69   case Primitive::kPrimFloat:
70     if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
71         srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
72       dst->SetF(src.GetI());
73       return true;
74     } else if (srcType == Primitive::kPrimLong) {
75       dst->SetF(src.GetJ());
76       return true;
77     }
78     break;
79   case Primitive::kPrimDouble:
80     if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
81         srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
82       dst->SetD(src.GetI());
83       return true;
84     } else if (srcType == Primitive::kPrimLong) {
85       dst->SetD(src.GetJ());
86       return true;
87     } else if (srcType == Primitive::kPrimFloat) {
88       dst->SetD(src.GetF());
89       return true;
90     }
91     break;
92   default:
93     break;
94   }
95   return false;
96 }
97 
ConvertPrimitiveValue(bool unbox_for_result,Primitive::Type srcType,Primitive::Type dstType,const JValue & src,JValue * dst)98 inline bool ConvertPrimitiveValue(bool unbox_for_result,
99                                   Primitive::Type srcType,
100                                   Primitive::Type dstType,
101                                   const JValue& src,
102                                   JValue* dst) {
103   if (ConvertPrimitiveValueNoThrow(srcType, dstType, src, dst)) {
104     return true;
105   }
106 
107   if (!unbox_for_result) {
108     ThrowIllegalArgumentException(
109         android::base::StringPrintf("Invalid primitive conversion from %s to %s",
110                                     PrettyDescriptor(srcType).c_str(),
111                                     PrettyDescriptor(dstType).c_str()).c_str());
112   } else {
113     ThrowClassCastException(android::base::StringPrintf("Couldn't convert result of type %s to %s",
114                                                         PrettyDescriptor(srcType).c_str(),
115                                                         PrettyDescriptor(dstType).c_str()).c_str());
116   }
117   return false;
118 }
119 
VerifyObjectIsClass(ObjPtr<mirror::Object> o,ObjPtr<mirror::Class> c)120 inline bool VerifyObjectIsClass(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) {
121   if (UNLIKELY(o == nullptr)) {
122     ThrowNullPointerException("null receiver");
123     return false;
124   } else if (UNLIKELY(!o->InstanceOf(c.Ptr()))) {
125     InvalidReceiverError(o, c);
126     return false;
127   }
128   return true;
129 }
130 
131 }  // namespace art
132 
133 #endif  // ART_RUNTIME_REFLECTION_INL_H_
134