1 /*
2  * Copyright (C) 2012 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_VERIFIER_REG_TYPE_CACHE_INL_H_
18 #define ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_INL_H_
19 
20 #include "base/bit_vector-inl.h"
21 #include "class_linker.h"
22 #include "class_root-inl.h"
23 #include "mirror/class-inl.h"
24 #include "mirror/method_handle_impl.h"
25 #include "mirror/method_type.h"
26 #include "mirror/string.h"
27 #include "mirror/throwable.h"
28 #include "reg_type.h"
29 #include "reg_type_cache.h"
30 
31 namespace art HIDDEN {
32 namespace verifier {
33 
GetFromId(uint16_t id)34 inline const art::verifier::RegType& RegTypeCache::GetFromId(uint16_t id) const {
35   DCHECK_LT(id, entries_.size());
36   const RegType* result = entries_[id];
37   DCHECK(result != nullptr);
38   return *result;
39 }
40 
FromCat1Const(int32_t value,bool precise)41 inline const ConstantType& RegTypeCache::FromCat1Const(int32_t value, bool precise) {
42   // We only expect 0 to be a precise constant.
43   DCHECK_IMPLIES(value == 0, precise);
44   if (precise && (value >= kMinSmallConstant) && (value <= kMaxSmallConstant)) {
45     return *down_cast<const ConstantType*>(entries_[value - kMinSmallConstant]);
46   }
47   return FromCat1NonSmallConstant(value, precise);
48 }
49 
Boolean()50 inline const BooleanType& RegTypeCache::Boolean() {
51   return *down_cast<const BooleanType*>(entries_[kBooleanCacheId]);
52 }
Byte()53 inline const ByteType& RegTypeCache::Byte() {
54   return *down_cast<const ByteType*>(entries_[kByteCacheId]);
55 }
Char()56 inline const CharType& RegTypeCache::Char() {
57   return *down_cast<const CharType*>(entries_[kCharCacheId]);
58 }
Short()59 inline const ShortType& RegTypeCache::Short() {
60   return *down_cast<const ShortType*>(entries_[kShortCacheId]);
61 }
Integer()62 inline const IntegerType& RegTypeCache::Integer() {
63   return *down_cast<const IntegerType*>(entries_[kIntCacheId]);
64 }
Float()65 inline const FloatType& RegTypeCache::Float() {
66   return *down_cast<const FloatType*>(entries_[kFloatCacheId]);
67 }
LongLo()68 inline const LongLoType& RegTypeCache::LongLo() {
69   return *down_cast<const LongLoType*>(entries_[kLongLoCacheId]);
70 }
LongHi()71 inline const LongHiType& RegTypeCache::LongHi() {
72   return *down_cast<const LongHiType*>(entries_[kLongHiCacheId]);
73 }
DoubleLo()74 inline const DoubleLoType& RegTypeCache::DoubleLo() {
75   return *down_cast<const DoubleLoType*>(entries_[kDoubleLoCacheId]);
76 }
DoubleHi()77 inline const DoubleHiType& RegTypeCache::DoubleHi() {
78   return *down_cast<const DoubleHiType*>(entries_[kDoubleHiCacheId]);
79 }
Undefined()80 inline const UndefinedType& RegTypeCache::Undefined() {
81   return *down_cast<const UndefinedType*>(entries_[kUndefinedCacheId]);
82 }
Conflict()83 inline const ConflictType& RegTypeCache::Conflict() {
84   return *down_cast<const ConflictType*>(entries_[kConflictCacheId]);
85 }
Null()86 inline const NullType& RegTypeCache::Null() {
87   return *down_cast<const NullType*>(entries_[kNullCacheId]);
88 }
89 
ByteConstant()90 inline const ImpreciseConstType& RegTypeCache::ByteConstant() {
91   const ConstantType& result = FromCat1Const(std::numeric_limits<jbyte>::min(), false);
92   DCHECK(result.IsImpreciseConstant());
93   return *down_cast<const ImpreciseConstType*>(&result);
94 }
95 
CharConstant()96 inline const ImpreciseConstType& RegTypeCache::CharConstant() {
97   int32_t jchar_max = static_cast<int32_t>(std::numeric_limits<jchar>::max());
98   const ConstantType& result =  FromCat1Const(jchar_max, false);
99   DCHECK(result.IsImpreciseConstant());
100   return *down_cast<const ImpreciseConstType*>(&result);
101 }
102 
ShortConstant()103 inline const ImpreciseConstType& RegTypeCache::ShortConstant() {
104   const ConstantType& result =  FromCat1Const(std::numeric_limits<jshort>::min(), false);
105   DCHECK(result.IsImpreciseConstant());
106   return *down_cast<const ImpreciseConstType*>(&result);
107 }
108 
IntConstant()109 inline const ImpreciseConstType& RegTypeCache::IntConstant() {
110   const ConstantType& result = FromCat1Const(std::numeric_limits<jint>::max(), false);
111   DCHECK(result.IsImpreciseConstant());
112   return *down_cast<const ImpreciseConstType*>(&result);
113 }
114 
PosByteConstant()115 inline const ImpreciseConstType& RegTypeCache::PosByteConstant() {
116   const ConstantType& result = FromCat1Const(std::numeric_limits<jbyte>::max(), false);
117   DCHECK(result.IsImpreciseConstant());
118   return *down_cast<const ImpreciseConstType*>(&result);
119 }
120 
PosShortConstant()121 inline const ImpreciseConstType& RegTypeCache::PosShortConstant() {
122   const ConstantType& result =  FromCat1Const(std::numeric_limits<jshort>::max(), false);
123   DCHECK(result.IsImpreciseConstant());
124   return *down_cast<const ImpreciseConstType*>(&result);
125 }
126 
JavaLangClass()127 inline const PreciseReferenceType& RegTypeCache::JavaLangClass() {
128   const RegType* result = &FromClass("Ljava/lang/Class;",
129                                      GetClassRoot<mirror::Class>(),
130                                      /* precise= */ true);
131   DCHECK(result->IsPreciseReference());
132   return *down_cast<const PreciseReferenceType*>(result);
133 }
134 
JavaLangString()135 inline const PreciseReferenceType& RegTypeCache::JavaLangString() {
136   // String is final and therefore always precise.
137   const RegType* result = &FromClass("Ljava/lang/String;",
138                                      GetClassRoot<mirror::String>(),
139                                      /* precise= */ true);
140   DCHECK(result->IsPreciseReference());
141   return *down_cast<const PreciseReferenceType*>(result);
142 }
143 
JavaLangInvokeMethodHandle()144 inline const PreciseReferenceType& RegTypeCache::JavaLangInvokeMethodHandle() {
145   const RegType* result = &FromClass("Ljava/lang/invoke/MethodHandle;",
146                                      GetClassRoot<mirror::MethodHandle>(),
147                                      /* precise= */ true);
148   DCHECK(result->IsPreciseReference());
149   return *down_cast<const PreciseReferenceType*>(result);
150 }
151 
JavaLangInvokeMethodType()152 inline const PreciseReferenceType& RegTypeCache::JavaLangInvokeMethodType() {
153   const RegType* result = &FromClass("Ljava/lang/invoke/MethodType;",
154                                      GetClassRoot<mirror::MethodType>(),
155                                      /* precise= */ true);
156   DCHECK(result->IsPreciseReference());
157   return *down_cast<const PreciseReferenceType*>(result);
158 }
159 
JavaLangThrowable()160 inline const RegType& RegTypeCache::JavaLangThrowable() {
161   const RegType* result = &FromClass("Ljava/lang/Throwable;",
162                                      GetClassRoot<mirror::Throwable>(),
163                                      /* precise= */ false);
164   DCHECK(result->IsReference());
165   DCHECK(!result->IsPreciseReference());
166   return *down_cast<const ReferenceType*>(result);
167 }
168 
JavaLangObject(bool precise)169 inline const RegType& RegTypeCache::JavaLangObject(bool precise) {
170   const RegType* result = &FromClass("Ljava/lang/Object;", GetClassRoot<mirror::Object>(), precise);
171   if (precise) {
172     DCHECK(result->IsPreciseReference());
173     return *down_cast<const PreciseReferenceType*>(result);
174   } else {
175     DCHECK(result->IsReference());
176     return *down_cast<const ReferenceType*>(result);
177   }
178 }
179 
180 template <class RegTypeType>
AddEntry(RegTypeType * new_entry)181 inline RegTypeType& RegTypeCache::AddEntry(RegTypeType* new_entry) {
182   DCHECK(new_entry != nullptr);
183   entries_.push_back(new_entry);
184   if (new_entry->HasClass()) {
185     Handle<mirror::Class> klass = new_entry->GetClassHandle();
186     DCHECK(!klass->IsPrimitive());
187     klass_entries_.push_back(std::make_pair(klass, new_entry));
188   }
189   return *new_entry;
190 }
191 
192 }  // namespace verifier
193 }  // namespace art
194 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_INL_H_
195