• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "panda_types.h"
17 
18 #include "runtime/include/class_linker.h"
19 #include "runtime/include/method.h"
20 #include "runtime/include/method-inl.h"
21 #include "runtime/include/class.h"
22 #include "runtime/include/runtime.h"
23 
24 #include "utils/span.h"
25 #include "verification/type/type_system.h"
26 #include "verification/type/type_sort.h"
27 #include "verification/type/type_image.h"
28 #include "verification/job_queue/cache.h"
29 
30 #include "verification/type/type_params_inl.h"
31 
32 #include "verifier_messages.h"
33 
34 #include "utils/logger.h"
35 
36 #include "runtime/include/mem/panda_containers.h"
37 #include "runtime/include/mem/panda_string.h"
38 
39 #include "libpandabase/os/mutex.h"
40 
41 namespace panda::verifier {
42 
NormalizedTypeOf(Type type)43 Type PandaTypes::NormalizedTypeOf(Type type)
44 {
45     ASSERT(type.IsValid());
46     if (type.IsBot() || type.IsTop()) {
47         return type;
48     }
49     auto t = NormalizedTypeOf_.find(type);
50     if (t != NormalizedTypeOf_.cend()) {
51         return t->second;
52     }
53     Type result = type;
54     if (type <= Integral32Type()) {
55         result = Normalize()(~Integral32Type());
56         NormalizedTypeOf_[type] = result;
57     } else if (type <= Integral64Type()) {
58         result = Normalize()(~Integral64Type());
59         NormalizedTypeOf_[type] = result;
60         // NOLINTNEXTLINE(bugprone-branch-clone)
61     } else if (type <= F32()) {
62         result = Normalize()(~F64());
63         NormalizedTypeOf_[type] = result;
64     } else if (type <= F64()) {
65         result = Normalize()(~F64());
66         NormalizedTypeOf_[type] = result;
67     } else if (type <= MethodType()) {
68         result = NormalizedMethod()(NormalizeMethodSignature(type.Params()));
69     }
70     NormalizedTypeOf_[type] = result;
71     return result;
72 }
73 
NormalizeMethodSignature(const TypeParams & sig)74 TypeParams PandaTypes::NormalizeMethodSignature(const TypeParams &sig)
75 {
76     TypeParams result {kind_};
77     sig.ForEach([&result, this](const auto &param) {
78         const Type &type = param;
79         result >> (NormalizedTypeOf(type) * param.Variance());
80     });
81     return result;
82 }
83 
NormalizedMethodSignature(const PandaTypes::CachedMethod & method)84 const TypeParams &PandaTypes::NormalizedMethodSignature(const PandaTypes::CachedMethod &method)
85 {
86     auto &&method_id = method.id;
87     auto it = NormalizedSigOfMethod_.find(method_id);
88     if (it != NormalizedSigOfMethod_.end()) {
89         return it->second;
90     }
91     auto &&sig = MethodSignature(method);
92     auto &&normalized_sig = NormalizeMethodSignature(sig);
93     NormalizedSigOfMethod_[method_id] = normalized_sig;
94     return NormalizedSigOfMethod_[method_id];
95 }
96 
MethodSignature(const PandaTypes::CachedMethod & method)97 const TypeParams &PandaTypes::MethodSignature(const PandaTypes::CachedMethod &method)
98 {
99     auto &&method_id = method.id;
100     auto it = SigOfMethod_.find(method_id);
101     if (it != SigOfMethod_.end()) {
102         return it->second;
103     }
104     TypeParams params {kind_};
105     Type return_type;
106     bool return_is_processed = false;
107     for (const auto &arg : method.signature) {
108         Type t;
109         if (CacheOfRuntimeThings::IsRef(arg)) {
110             const auto &cached_class = CacheOfRuntimeThings::GetRef(arg);
111             if (cached_class.type_id == TypeId::VOID) {
112                 t = Top();
113             } else {
114                 t = TypeOf(cached_class);
115             }
116         } else if (CacheOfRuntimeThings::IsDescriptor(arg)) {
117             LOG_VERIFIER_JAVA_TYPES_METHOD_ARG_WAS_NOT_RESOLVED(method.GetName());
118             t = Top();
119         } else {
120             LOG_VERIFIER_JAVA_TYPES_METHOD_ARG_CANNOT_BE_PROCESSED(method.GetName());
121             t = Top();
122         }
123         if (!t.IsValid()) {
124             LOG_VERIFIER_JAVA_TYPES_METHOD_ARG_CANNOT_BE_CONVERTED_TO_TYPE(method.GetName());
125         }
126         if (return_is_processed) {
127             params >> -t;
128         } else {
129             return_type = t;
130             return_is_processed = true;
131         }
132     }
133     params >> +return_type;
134     SigOfMethod_[method_id] = params;
135     return SigOfMethod_[method_id];
136 }
137 
TypeIdOf(const Type & type) const138 PandaTypes::TypeId PandaTypes::TypeIdOf(const Type &type) const
139 {
140     std::vector<std::pair<Type, PandaTypes::TypeId>> types_table = {
141         {U1_, TypeId::U1},   {U8_, TypeId::U8},   {U16_, TypeId::U16}, {U32_, TypeId::U32},
142         {U64_, TypeId::U64}, {I8_, TypeId::I8},   {I16_, TypeId::I16}, {I32_, TypeId::I32},
143         {I64_, TypeId::I64}, {F32_, TypeId::F32}, {F64_, TypeId::F64}, {RefType_, TypeId::REFERENCE}};
144 
145     for (const auto &val : types_table) {
146         if (val.first == type) {
147             return val.second;
148         }
149     }
150 
151     if (type.IsTop()) {
152         return TypeId::VOID;
153     }
154 
155     return TypeId::INVALID;
156 }
157 
TypeOf(const PandaTypes::CachedMethod & method)158 Type PandaTypes::TypeOf(const PandaTypes::CachedMethod &method)
159 {
160     auto id = method.id;
161     auto k = TypeOfMethod_.find(id);
162     if (k != TypeOfMethod_.end()) {
163         return k->second;
164     }
165     ASSERT(!DoNotCalculateMethodType_);
166     auto &&sig = MethodSignature(method);
167     auto &&norm_sig = NormalizedMethodSignature(method);
168     Type type;
169     type = Method()(sig);
170     type << MethodType();
171     TypeOfMethod_[id] = type;
172     // Normalize(Method) <: NormalizedMethod(NormalizedMethodSig)
173     auto norm_type = Normalize()(~type);
174     auto norm_method = NormalizedMethod()(norm_sig);
175     norm_type << norm_method;
176     NormalizedTypeOf_[type] = norm_method;
177     MethodNameOfId_[id] = method.GetName();
178     return type;
179 }
180 
SetArraySubtyping(const Type & t)181 void PandaTypes::SetArraySubtyping(const Type &t)
182 {
183     PandaVector<Type> to_process;
184     PandaVector<Type> just_subtype;
185     t.ForAllSupertypes([&]([[maybe_unused]] const Type &st) {
186         if (!Array()[+st]) {
187             to_process.emplace_back(st);
188         } else {
189             just_subtype.emplace_back(st);
190         }
191         return true;
192     });
193     auto array_type = Array()(+t);
194     for (const auto &st : just_subtype) {
195         array_type << Array()(+st);
196     }
197     for (const auto &st : to_process) {
198         array_type << Array()(+st);
199         SetArraySubtyping(st);
200     }
201 }
202 
TypeOfArray(const PandaTypes::CachedClass & klass)203 Type PandaTypes::TypeOfArray(const PandaTypes::CachedClass &klass)
204 {
205     ASSERT(klass.flags[CachedClass::Flag::ARRAY_CLASS]);
206 
207     Type type;
208     const auto &component = klass.GetArrayComponent();
209     if (!Valid(component)) {
210         type = Array()(+Top());
211         LOG_VERIFIER_JAVA_TYPES_ARRAY_COMPONENT_TYPE_IS_UNDEFINED();
212     } else {
213         auto component_type = TypeOf(component);
214         type = Array()(+component_type);
215         SetArraySubtyping(component_type);
216     }
217     type << ArrayType();
218     if (klass.flags[CachedClass::Flag::OBJECT_ARRAY_CLASS]) {
219         type << ObjectArrayType();
220     }
221 
222     return type;
223 }
224 
TypeOf(const PandaTypes::CachedClass & klass)225 Type PandaTypes::TypeOf(const PandaTypes::CachedClass &klass)
226 {
227     auto id = klass.id;
228     auto k = TypeOfClass_.find(id);
229     if (k != TypeOfClass_.end()) {
230         return k->second;
231     }
232 
233     PandaVector<Type> supertypes;
234     for (const auto &ancestor : klass.ancestors) {
235         // ancestor here cannot be unresolved descriptor
236         ASSERT(CacheOfRuntimeThings::IsRef(ancestor));
237         supertypes.emplace_back(TypeOf(CacheOfRuntimeThings::GetRef(ancestor)));
238     }
239 
240     Type type;
241     bool is_primitive = klass.flags[CachedClass::Flag::PRIMITIVE];
242     bool is_string = klass.flags[CachedClass::Flag::STRING_CLASS];
243 
244     auto class_name = klass.GetName();
245 
246     if (klass.flags[CachedClass::Flag::ARRAY_CLASS]) {
247         type = TypeOfArray(klass);
248     } else if (!is_primitive) {
249         type = TypeSystem_.Parametric(GetSort(class_name))();
250     } else {
251         type = TypeOf(klass.type_id);
252     }
253 
254     if (!is_primitive) {
255         if (!is_string) {
256             type << ObjectType();
257         } else {
258             type << StringType();
259         }
260         NullRefType() << type << RefType();
261         TypeClass()(~type) << TypeClassType() << RefType();
262     }
263     if (klass.flags[CachedClass::Flag::ABSTRACT]) {
264         Abstract()(~type) << AbstractType();
265     }
266     for (auto &super : supertypes) {
267         type << super;
268     }
269     ClassNameOfId_[id] = class_name;
270     TypeOfClass_[id] = type;
271     NormalizedTypeOf(type);
272     return type;
273 }
274 
TypeOf(PandaTypes::TypeId id) const275 Type PandaTypes::TypeOf(PandaTypes::TypeId id) const
276 {
277     if (id == TypeId::VOID) {
278         return Top();
279     }
280 
281     std::vector<std::pair<Type, PandaTypes::TypeId>> types_table = {
282         {U1_, TypeId::U1},   {U8_, TypeId::U8},   {U16_, TypeId::U16}, {U32_, TypeId::U32},
283         {U64_, TypeId::U64}, {I8_, TypeId::I8},   {I16_, TypeId::I16}, {I32_, TypeId::I32},
284         {I64_, TypeId::I64}, {F32_, TypeId::F32}, {F64_, TypeId::F64}, {RefType_, TypeId::REFERENCE}};
285 
286     for (const auto &val : types_table) {
287         if (val.second == id) {
288             return val.first;
289         }
290     }
291 
292     LOG_VERIFIER_JAVA_TYPES_CANNOT_CONVERT_TYPE_ID_TO_TYPE(id);
293     return Top();
294 }
295 
Init()296 void PandaTypes::Init()
297 {
298     TypeSystem_.SetIncrementalRelationClosureMode(false);
299 
300     // base subtyping of primitive types
301     I8() << I16() << I32();
302     U1() << U8() << U16() << U32();
303     F32() << F64();
304     // integral
305     (U1() | I8() | U8()) << Integral8Type();
306     (Integral8Type() | I16() | U16()) << Integral16Type();
307     (Integral16Type() | I32() | U32()) << Integral32Type();
308     (I64() | U64()) << Integral64Type();
309     // sizes
310     F32() << (Float32Type() | F64()) << Float64Type();
311     (Integral32Type() | Float32Type()) << Bits32Type();
312     (Integral64Type() | Float64Type()) << Bits64Type();
313     (Bits32Type() | Bits64Type()) << PrimitiveType();
314 
315     TypeClassType() << RefType();
316     NullRefType() << (PandaClass() | PandaObject() | JavaObject() | JavaClass() | JavaThrowable())
317                   << (ObjectType() | RefType());
318     NullRefType() << (ArrayType() | ObjectArrayType()) << RefType();
319     TypeClass()(~PandaObject()) << TypeClassType();
320     TypeClass()(~JavaObject()) << TypeClassType();
321 
322     TypeSystem_.CloseSubtypingRelation();
323 
324     TypeSystem_.SetIncrementalRelationClosureMode(false);
325     TypeSystem_.SetDeferIncrementalRelationClosure(false);
326 }
327 
328 }  // namespace panda::verifier
329