• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 "runtime/core/core_class_linker_extension.h"
17 
18 #include "runtime/include/coretypes/class.h"
19 #include "runtime/include/exceptions.h"
20 #include "runtime/include/panda_vm.h"
21 
22 namespace panda {
23 
24 using SourceLang = panda_file::SourceLang;
25 using Type = panda_file::Type;
26 
OnError(ClassLinker::Error error,const PandaString & message)27 void CoreClassLinkerExtension::ErrorHandler::OnError(ClassLinker::Error error, const PandaString &message)
28 {
29     auto *thread = ManagedThread::GetCurrent();
30     LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::PANDA_ASSEMBLY);
31 
32     switch (error) {
33         case ClassLinker::Error::CLASS_NOT_FOUND: {
34             ThrowException(ctx, thread, ctx.GetClassNotFoundExceptionDescriptor(),
35                            utf::CStringAsMutf8(message.c_str()));
36             break;
37         }
38         case ClassLinker::Error::FIELD_NOT_FOUND: {
39             ThrowException(ctx, thread, ctx.GetNoSuchFieldErrorDescriptor(), utf::CStringAsMutf8(message.c_str()));
40             break;
41         }
42         case ClassLinker::Error::METHOD_NOT_FOUND: {
43             ThrowException(ctx, thread, ctx.GetNoSuchMethodErrorDescriptor(), utf::CStringAsMutf8(message.c_str()));
44             break;
45         }
46         case ClassLinker::Error::NO_CLASS_DEF: {
47             ThrowException(ctx, thread, ctx.GetNoClassDefFoundErrorDescriptor(), utf::CStringAsMutf8(message.c_str()));
48             break;
49         }
50         case ClassLinker::Error::CLASS_CIRCULARITY: {
51             ThrowException(ctx, thread, ctx.GetClassCircularityErrorDescriptor(), utf::CStringAsMutf8(message.c_str()));
52             break;
53         }
54         default:
55             LOG(FATAL, CLASS_LINKER) << "Unhandled error (" << static_cast<size_t>(error) << "): " << message;
56             break;
57     }
58 }
59 
InitializeImpl(bool compressed_string_enabled)60 bool CoreClassLinkerExtension::InitializeImpl(bool compressed_string_enabled)
61 {
62     LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(GetLanguage());
63 
64     auto *class_class = CreateClass(ctx.GetClassClassDescriptor(), GetClassVTableSize(ClassRoot::CLASS),
65                                     GetClassIMTSize(ClassRoot::CLASS), GetClassSize(ClassRoot::CLASS));
66     coretypes::Class::FromRuntimeClass(class_class)->SetClass(class_class);
67     class_class->SetState(Class::State::LOADED);
68     class_class->SetLoadContext(GetBootContext());
69     GetClassLinker()->AddClassRoot(ClassRoot::CLASS, class_class);
70 
71     auto *obj_class = CreateClass(ctx.GetObjectClassDescriptor(), GetClassVTableSize(ClassRoot::OBJECT),
72                                   GetClassIMTSize(ClassRoot::OBJECT), GetClassSize(ClassRoot::OBJECT));
73     obj_class->SetObjectSize(ObjectHeader::ObjectHeaderSize());
74     class_class->SetBase(obj_class);
75     obj_class->SetState(Class::State::LOADED);
76     obj_class->SetLoadContext(GetBootContext());
77     GetClassLinker()->AddClassRoot(ClassRoot::OBJECT, obj_class);
78 
79     auto *string_class = CreateClass(ctx.GetStringClassDescriptor(), GetClassVTableSize(ClassRoot::STRING),
80                                      GetClassIMTSize(ClassRoot::STRING), GetClassSize(ClassRoot::STRING));
81     string_class->SetBase(obj_class);
82     string_class->SetStringClass();
83     coretypes::String::SetCompressedStringsEnabled(compressed_string_enabled);
84     string_class->SetState(Class::State::LOADED);
85     string_class->SetLoadContext(GetBootContext());
86     GetClassLinker()->AddClassRoot(ClassRoot::STRING, string_class);
87 
88     InitializeArrayClassRoot(ClassRoot::ARRAY_CLASS, ClassRoot::CLASS,
89                              utf::Mutf8AsCString(ctx.GetClassArrayClassDescriptor()));
90 
91     InitializePrimitiveClassRoot(ClassRoot::U1, Type::TypeId::U1, "Z");
92     InitializePrimitiveClassRoot(ClassRoot::I8, Type::TypeId::I8, "B");
93     InitializePrimitiveClassRoot(ClassRoot::U8, Type::TypeId::U8, "H");
94     InitializePrimitiveClassRoot(ClassRoot::I16, Type::TypeId::I16, "S");
95     InitializePrimitiveClassRoot(ClassRoot::U16, Type::TypeId::U16, "C");
96     InitializePrimitiveClassRoot(ClassRoot::I32, Type::TypeId::I32, "I");
97     InitializePrimitiveClassRoot(ClassRoot::U32, Type::TypeId::U32, "U");
98     InitializePrimitiveClassRoot(ClassRoot::I64, Type::TypeId::I64, "J");
99     InitializePrimitiveClassRoot(ClassRoot::U64, Type::TypeId::U64, "Q");
100     InitializePrimitiveClassRoot(ClassRoot::F32, Type::TypeId::F32, "F");
101     InitializePrimitiveClassRoot(ClassRoot::F64, Type::TypeId::F64, "D");
102     InitializePrimitiveClassRoot(ClassRoot::TAGGED, Type::TypeId::TAGGED, "A");
103 
104     InitializeArrayClassRoot(ClassRoot::ARRAY_U1, ClassRoot::U1, "[Z");
105     InitializeArrayClassRoot(ClassRoot::ARRAY_I8, ClassRoot::I8, "[B");
106     InitializeArrayClassRoot(ClassRoot::ARRAY_U8, ClassRoot::U8, "[H");
107     InitializeArrayClassRoot(ClassRoot::ARRAY_I16, ClassRoot::I16, "[S");
108     InitializeArrayClassRoot(ClassRoot::ARRAY_U16, ClassRoot::U16, "[C");
109     InitializeArrayClassRoot(ClassRoot::ARRAY_I32, ClassRoot::I32, "[I");
110     InitializeArrayClassRoot(ClassRoot::ARRAY_U32, ClassRoot::U32, "[U");
111     InitializeArrayClassRoot(ClassRoot::ARRAY_I64, ClassRoot::I64, "[J");
112     InitializeArrayClassRoot(ClassRoot::ARRAY_U64, ClassRoot::U64, "[Q");
113     InitializeArrayClassRoot(ClassRoot::ARRAY_F32, ClassRoot::F32, "[F");
114     InitializeArrayClassRoot(ClassRoot::ARRAY_F64, ClassRoot::F64, "[D");
115     InitializeArrayClassRoot(ClassRoot::ARRAY_TAGGED, ClassRoot::TAGGED, "[A");
116     InitializeArrayClassRoot(ClassRoot::ARRAY_STRING, ClassRoot::STRING,
117                              utf::Mutf8AsCString(ctx.GetStringArrayClassDescriptor()));
118 
119     return true;
120 }
121 
InitializeArrayClass(Class * array_class,Class * component_class)122 void CoreClassLinkerExtension::InitializeArrayClass(Class *array_class, Class *component_class)
123 {
124     ASSERT(IsInitialized());
125 
126     auto *object_class = GetClassRoot(ClassRoot::OBJECT);
127     array_class->SetBase(object_class);
128     array_class->SetComponentType(component_class);
129     uint32_t access_flags = component_class->GetAccessFlags() & ACC_FILE_MASK;
130     access_flags &= ~ACC_INTERFACE;
131     access_flags |= ACC_FINAL | ACC_ABSTRACT;
132     array_class->SetAccessFlags(access_flags);
133     array_class->SetState(Class::State::INITIALIZED);
134 }
135 
InitializePrimitiveClass(Class * primitive_class)136 void CoreClassLinkerExtension::InitializePrimitiveClass(Class *primitive_class)
137 {
138     ASSERT(IsInitialized());
139 
140     primitive_class->SetAccessFlags(ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT);
141     primitive_class->SetState(Class::State::INITIALIZED);
142 }
143 
GetClassVTableSize(ClassRoot root)144 size_t CoreClassLinkerExtension::GetClassVTableSize(ClassRoot root)
145 {
146     ASSERT(IsInitialized());
147 
148     switch (root) {
149         case ClassRoot::U1:
150         case ClassRoot::I8:
151         case ClassRoot::U8:
152         case ClassRoot::I16:
153         case ClassRoot::U16:
154         case ClassRoot::I32:
155         case ClassRoot::U32:
156         case ClassRoot::I64:
157         case ClassRoot::U64:
158         case ClassRoot::F32:
159         case ClassRoot::F64:
160         case ClassRoot::TAGGED:
161             return 0;
162         case ClassRoot::ARRAY_U1:
163         case ClassRoot::ARRAY_I8:
164         case ClassRoot::ARRAY_U8:
165         case ClassRoot::ARRAY_I16:
166         case ClassRoot::ARRAY_U16:
167         case ClassRoot::ARRAY_I32:
168         case ClassRoot::ARRAY_U32:
169         case ClassRoot::ARRAY_I64:
170         case ClassRoot::ARRAY_U64:
171         case ClassRoot::ARRAY_F32:
172         case ClassRoot::ARRAY_F64:
173         case ClassRoot::ARRAY_TAGGED:
174         case ClassRoot::ARRAY_CLASS:
175         case ClassRoot::ARRAY_STRING:
176             return GetArrayClassVTableSize();
177         case ClassRoot::OBJECT:
178         case ClassRoot::CLASS:
179         case ClassRoot::STRING:
180             return 0;
181         default: {
182             break;
183         }
184     }
185 
186     UNREACHABLE();
187 }
188 
GetClassIMTSize(ClassRoot root)189 size_t CoreClassLinkerExtension::GetClassIMTSize(ClassRoot root)
190 {
191     ASSERT(IsInitialized());
192 
193     switch (root) {
194         case ClassRoot::U1:
195         case ClassRoot::I8:
196         case ClassRoot::U8:
197         case ClassRoot::I16:
198         case ClassRoot::U16:
199         case ClassRoot::I32:
200         case ClassRoot::U32:
201         case ClassRoot::I64:
202         case ClassRoot::U64:
203         case ClassRoot::F32:
204         case ClassRoot::F64:
205         case ClassRoot::TAGGED:
206             return 0;
207         case ClassRoot::ARRAY_U1:
208         case ClassRoot::ARRAY_I8:
209         case ClassRoot::ARRAY_U8:
210         case ClassRoot::ARRAY_I16:
211         case ClassRoot::ARRAY_U16:
212         case ClassRoot::ARRAY_I32:
213         case ClassRoot::ARRAY_U32:
214         case ClassRoot::ARRAY_I64:
215         case ClassRoot::ARRAY_U64:
216         case ClassRoot::ARRAY_F32:
217         case ClassRoot::ARRAY_F64:
218         case ClassRoot::ARRAY_TAGGED:
219         case ClassRoot::ARRAY_CLASS:
220         case ClassRoot::ARRAY_STRING:
221             return GetArrayClassIMTSize();
222         case ClassRoot::OBJECT:
223         case ClassRoot::CLASS:
224         case ClassRoot::STRING:
225             return 0;
226         default: {
227             break;
228         }
229     }
230 
231     UNREACHABLE();
232 }
233 
GetClassSize(ClassRoot root)234 size_t CoreClassLinkerExtension::GetClassSize(ClassRoot root)
235 {
236     ASSERT(IsInitialized());
237 
238     switch (root) {
239         case ClassRoot::U1:
240         case ClassRoot::I8:
241         case ClassRoot::U8:
242         case ClassRoot::I16:
243         case ClassRoot::U16:
244         case ClassRoot::I32:
245         case ClassRoot::U32:
246         case ClassRoot::I64:
247         case ClassRoot::U64:
248         case ClassRoot::F32:
249         case ClassRoot::F64:
250         case ClassRoot::TAGGED:
251             return Class::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0);
252         case ClassRoot::ARRAY_U1:
253         case ClassRoot::ARRAY_I8:
254         case ClassRoot::ARRAY_U8:
255         case ClassRoot::ARRAY_I16:
256         case ClassRoot::ARRAY_U16:
257         case ClassRoot::ARRAY_I32:
258         case ClassRoot::ARRAY_U32:
259         case ClassRoot::ARRAY_I64:
260         case ClassRoot::ARRAY_U64:
261         case ClassRoot::ARRAY_F32:
262         case ClassRoot::ARRAY_F64:
263         case ClassRoot::ARRAY_TAGGED:
264         case ClassRoot::ARRAY_CLASS:
265         case ClassRoot::ARRAY_STRING:
266             return GetArrayClassSize();
267         case ClassRoot::OBJECT:
268         case ClassRoot::CLASS:
269         case ClassRoot::STRING:
270             return Class::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0);
271         default: {
272             break;
273         }
274     }
275 
276     UNREACHABLE();
277 }
278 
GetArrayClassVTableSize()279 size_t CoreClassLinkerExtension::GetArrayClassVTableSize()
280 {
281     ASSERT(IsInitialized());
282 
283     return GetClassVTableSize(ClassRoot::OBJECT);
284 }
285 
GetArrayClassIMTSize()286 size_t CoreClassLinkerExtension::GetArrayClassIMTSize()
287 {
288     ASSERT(IsInitialized());
289 
290     return GetClassIMTSize(ClassRoot::OBJECT);
291 }
292 
GetArrayClassSize()293 size_t CoreClassLinkerExtension::GetArrayClassSize()
294 {
295     ASSERT(IsInitialized());
296 
297     return GetClassSize(ClassRoot::OBJECT);
298 }
299 
CreateClass(const uint8_t * descriptor,size_t vtable_size,size_t imt_size,size_t size)300 Class *CoreClassLinkerExtension::CreateClass(const uint8_t *descriptor, size_t vtable_size, size_t imt_size,
301                                              size_t size)
302 {
303     ASSERT(IsInitialized());
304 
305     auto vm = Thread::GetCurrent()->GetVM();
306     auto *heap_manager = vm->GetHeapManager();
307 
308     auto *class_root = GetClassRoot(ClassRoot::CLASS);
309     ObjectHeader *object_header;
310     if (class_root == nullptr) {
311         object_header = heap_manager->AllocateNonMovableObject<true>(class_root, coretypes::Class::GetSize(size));
312     } else {
313         object_header = heap_manager->AllocateNonMovableObject<false>(class_root, coretypes::Class::GetSize(size));
314     }
315 
316     if (UNLIKELY(object_header == nullptr)) {
317         return nullptr;
318     }
319 
320     auto *res = reinterpret_cast<coretypes::Class *>(object_header);
321     res->InitClass(descriptor, vtable_size, imt_size, size);
322     auto *klass = res->GetRuntimeClass();
323     klass->SetManagedObject(res);
324     AddCreatedClass(klass);
325     return klass;
326 }
327 
FreeClass(Class * klass)328 void CoreClassLinkerExtension::FreeClass(Class *klass)
329 {
330     ASSERT(IsInitialized());
331 
332     RemoveCreatedClass(klass);
333 }
334 
~CoreClassLinkerExtension()335 CoreClassLinkerExtension::~CoreClassLinkerExtension()
336 {
337     if (!IsInitialized()) {
338         return;
339     }
340 
341     FreeLoadedClasses();
342 }
343 
344 }  // namespace panda
345