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