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 "runtime/dyn_class_linker_extension.h"
17 #include "runtime/include/class_linker-inl.h"
18 #include "runtime/include/class_linker.h"
19 #include "runtime/include/coretypes/array.h"
20 #include "runtime/include/coretypes/class.h"
21 #include "runtime/include/coretypes/dyn_objects.h"
22 #include "runtime/include/coretypes/native_pointer.h"
23 #include "runtime/include/panda_vm.h"
24
25 namespace panda {
26 using Array = coretypes::Array;
27 using NativePointer = coretypes::NativePointer;
28
29 using Type = panda_file::Type;
30 using SourceLang = panda_file::SourceLang;
31
~DynamicClassLinkerExtension()32 DynamicClassLinkerExtension::~DynamicClassLinkerExtension()
33 {
34 if (!IsInitialized()) {
35 return;
36 }
37
38 FreeLoadedClasses();
39 }
40
InitializeImpl(bool cmpStrEnabled)41 bool DynamicClassLinkerExtension::InitializeImpl([[maybe_unused]] bool cmpStrEnabled)
42 {
43 LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(GetLanguage());
44
45 auto *classClass = CreateClass(ctx.GetClassClassDescriptor(), GetClassVTableSize(ClassRoot::CLASS),
46 GetClassIMTSize(ClassRoot::CLASS), GetClassSize(ClassRoot::CLASS));
47 coretypes::Class::FromRuntimeClass(classClass)->SetClass(classClass);
48 classClass->SetSourceLang(SourceLang::ECMASCRIPT);
49 classClass->SetState(Class::State::LOADED);
50 classClass->SetLoadContext(GetBootContext());
51 GetClassLinker()->AddClassRoot(ClassRoot::CLASS, classClass);
52
53 auto *objClass = CreateClass(ctx.GetObjectClassDescriptor(), GetClassVTableSize(ClassRoot::OBJECT),
54 GetClassIMTSize(ClassRoot::OBJECT), GetClassSize(ClassRoot::OBJECT));
55 objClass->SetObjectSize(ObjectHeader::ObjectHeaderSize());
56 objClass->SetSourceLang(SourceLang::ECMASCRIPT);
57 classClass->SetBase(objClass);
58 objClass->SetState(Class::State::LOADED);
59 objClass->SetLoadContext(GetBootContext());
60 GetClassLinker()->AddClassRoot(ClassRoot::OBJECT, objClass);
61 return true;
62 }
63
InitializeArrayClass(Class * arrayClass,Class * componentClass)64 void DynamicClassLinkerExtension::InitializeArrayClass(Class *arrayClass, Class *componentClass)
65 {
66 ASSERT(IsInitialized());
67
68 auto *objectClass = GetClassRoot(ClassRoot::OBJECT);
69 arrayClass->SetBase(objectClass);
70 arrayClass->SetComponentType(componentClass);
71 uint32_t access_flags = componentClass->GetAccessFlags() & ACC_FILE_MASK;
72 access_flags &= ~ACC_INTERFACE;
73 access_flags |= ACC_FINAL | ACC_ABSTRACT;
74 arrayClass->SetAccessFlags(access_flags);
75 arrayClass->SetState(Class::State::INITIALIZED);
76 }
77
InitializePrimitiveClass(Class * primitiveClass)78 void DynamicClassLinkerExtension::InitializePrimitiveClass(Class *primitiveClass)
79 {
80 ASSERT(IsInitialized());
81
82 primitiveClass->SetAccessFlags(ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT);
83 primitiveClass->SetState(Class::State::INITIALIZED);
84 }
85
GetClassVTableSize(ClassRoot root)86 size_t DynamicClassLinkerExtension::GetClassVTableSize([[maybe_unused]] ClassRoot root)
87 {
88 ASSERT(IsInitialized());
89 return 0;
90 }
91
GetClassIMTSize(ClassRoot root)92 size_t DynamicClassLinkerExtension::GetClassIMTSize([[maybe_unused]] ClassRoot root)
93 {
94 ASSERT(IsInitialized());
95 return 0;
96 }
97
GetClassSize(ClassRoot root)98 size_t DynamicClassLinkerExtension::GetClassSize(ClassRoot root)
99 {
100 ASSERT(IsInitialized());
101
102 switch (root) {
103 case ClassRoot::U1:
104 case ClassRoot::I8:
105 case ClassRoot::U8:
106 case ClassRoot::I16:
107 case ClassRoot::U16:
108 case ClassRoot::I32:
109 case ClassRoot::U32:
110 case ClassRoot::I64:
111 case ClassRoot::U64:
112 case ClassRoot::F32:
113 case ClassRoot::F64:
114 case ClassRoot::TAGGED:
115 return ClassHelper::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0);
116 case ClassRoot::ARRAY_U1:
117 case ClassRoot::ARRAY_I8:
118 case ClassRoot::ARRAY_U8:
119 case ClassRoot::ARRAY_I16:
120 case ClassRoot::ARRAY_U16:
121 case ClassRoot::ARRAY_I32:
122 case ClassRoot::ARRAY_U32:
123 case ClassRoot::ARRAY_I64:
124 case ClassRoot::ARRAY_U64:
125 case ClassRoot::ARRAY_F32:
126 case ClassRoot::ARRAY_F64:
127 case ClassRoot::ARRAY_TAGGED:
128 case ClassRoot::ARRAY_CLASS:
129 case ClassRoot::ARRAY_STRING:
130 return GetArrayClassSize();
131 case ClassRoot::OBJECT:
132 case ClassRoot::CLASS:
133 case ClassRoot::STRING:
134 return ClassHelper::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0);
135 default: {
136 UNREACHABLE();
137 break;
138 }
139 }
140
141 return 0;
142 }
143
GetArrayClassVTableSize()144 size_t DynamicClassLinkerExtension::GetArrayClassVTableSize()
145 {
146 ASSERT(IsInitialized());
147
148 return GetClassVTableSize(ClassRoot::OBJECT);
149 }
150
GetArrayClassSize()151 size_t DynamicClassLinkerExtension::GetArrayClassSize()
152 {
153 ASSERT(IsInitialized());
154
155 return GetClassSize(ClassRoot::OBJECT);
156 }
157
CreateClass(const uint8_t * descriptor,size_t vtableSize,size_t imt_size,size_t size)158 Class *DynamicClassLinkerExtension::CreateClass(const uint8_t *descriptor, size_t vtableSize, size_t imt_size,
159 size_t size)
160 {
161 ASSERT(IsInitialized());
162
163 auto vm = Thread::GetCurrent()->GetVM();
164 auto *heap_manager = vm->GetHeapManager();
165 auto object_header =
166 heap_manager->AllocateNonMovableObject(GetClassRoot(ClassRoot::CLASS), coretypes::Class::GetSize(size));
167 // CODECHECK-NOLINTNEXTLINE(CPP_RULE_ID_SMARTPOINTER_INSTEADOF_ORIGINPOINTER)
168 auto *res = reinterpret_cast<coretypes::Class *>(object_header);
169 res->InitClass(descriptor, vtableSize, imt_size, size);
170 auto *klass = res->GetRuntimeClass();
171 klass->SetManagedObject(res);
172 klass->SetSourceLang(GetLanguage());
173 return klass;
174 }
175
FreeClass(Class * klass)176 void DynamicClassLinkerExtension::FreeClass(Class *klass)
177 {
178 ASSERT(IsInitialized());
179
180 auto *cls = coretypes::Class::FromRuntimeClass(klass);
181 auto allocator = GetClassLinker()->GetAllocator();
182 allocator->Free(cls);
183 }
184
OnError(ClassLinker::Error error,const PandaString & message)185 void DynamicClassLinkerExtension::ErrorHandler::OnError([[maybe_unused]] ClassLinker::Error error,
186 [[maybe_unused]] const PandaString &message)
187 {
188 }
189 } // namespace panda
190