• 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 #ifndef PANDA_RUNTIME_INCLUDE_CLASS_LINKER_EXTENSION_H_
17 #define PANDA_RUNTIME_INCLUDE_CLASS_LINKER_EXTENSION_H_
18 
19 #include "libpandabase/os/mutex.h"
20 #include "libpandafile/file.h"
21 #include "libpandafile/file_items.h"
22 #include "runtime/class_linker_context.h"
23 #include "runtime/include/class_root.h"
24 #include "runtime/include/class.h"
25 #include "runtime/include/mem/panda_containers.h"
26 
27 namespace panda {
28 
29 class ClassLinker;
30 class ClassLinkerErrorHandler;
31 
32 class ClassLinkerExtension {
33 public:
ClassLinkerExtension(panda_file::SourceLang lang)34     explicit ClassLinkerExtension(panda_file::SourceLang lang) : lang_(lang), boot_context_(this) {}
35 
36     virtual ~ClassLinkerExtension();
37 
38     bool Initialize(ClassLinker *class_linker, bool compressed_string_enabled);
39 
40     bool InitializeFinish();
41 
42     bool InitializeRoots(ManagedThread *thread);
43 
44     virtual void InitializeArrayClass(Class *array_class, Class *component_class) = 0;
45 
46     virtual void InitializePrimitiveClass(Class *primitive_class) = 0;
47 
48     virtual size_t GetClassVTableSize(ClassRoot root) = 0;
49 
50     virtual size_t GetClassIMTSize(ClassRoot root) = 0;
51 
52     virtual size_t GetClassSize(ClassRoot root) = 0;
53 
54     virtual size_t GetArrayClassVTableSize() = 0;
55 
56     virtual size_t GetArrayClassIMTSize() = 0;
57 
58     virtual size_t GetArrayClassSize() = 0;
59 
60     virtual Class *CreateClass(const uint8_t *descriptor, size_t vtable_size, size_t imt_size, size_t size) = 0;
61 
62     virtual void FreeClass(Class *klass) = 0;
63 
64     virtual void InitializeClass(Class *klass) = 0;
65 
66     virtual const void *GetNativeEntryPointFor(Method *method) const = 0;
67 
68     virtual bool CanThrowException(const Method *method) const = 0;
69 
70     virtual ClassLinkerErrorHandler *GetErrorHandler() = 0;
71 
72     virtual ClassLinkerContext *CreateApplicationClassLinkerContext(const PandaVector<PandaString> &path);
73 
GetClassRoot(ClassRoot root)74     Class *GetClassRoot(ClassRoot root) const
75     {
76         return class_roots_[ToIndex(root)];
77     }
78 
GetBootContext()79     ClassLinkerContext *GetBootContext()
80     {
81         return &boot_context_;
82     }
83 
SetClassRoot(ClassRoot root,Class * klass)84     void SetClassRoot(ClassRoot root, Class *klass)
85     {
86         class_roots_[ToIndex(root)] = klass;
87         boot_context_.InsertClass(klass);
88     }
89 
90     Class *FindLoadedClass(const uint8_t *descriptor, ClassLinkerContext *context = nullptr);
91 
92     Class *GetClass(const uint8_t *descriptor, bool need_copy_descriptor = true, ClassLinkerContext *context = nullptr,
93                     ClassLinkerErrorHandler *error_handler = nullptr);
94 
95     Class *GetClass(const panda_file::File &pf, panda_file::File::EntityId id, ClassLinkerContext *context = nullptr,
96                     ClassLinkerErrorHandler *error_handler = nullptr);
97 
GetLanguage()98     panda_file::SourceLang GetLanguage() const
99     {
100         return lang_;
101     }
102 
GetClassLinker()103     ClassLinker *GetClassLinker() const
104     {
105         return class_linker_;
106     }
107 
IsInitialized()108     bool IsInitialized() const
109     {
110         return class_linker_ != nullptr;
111     }
112 
CanInitializeClasses()113     bool CanInitializeClasses()
114     {
115         return can_initialize_classes_;
116     }
117 
118     template <class Callback>
119     bool EnumerateClasses(const Callback &cb, mem::VisitGCRootFlags flags = mem::VisitGCRootFlags::ACCESS_ROOT_ALL)
120     {
121         if (((flags & mem::VisitGCRootFlags::ACCESS_ROOT_ALL) != 0) ||
122             ((flags & mem::VisitGCRootFlags::ACCESS_ROOT_ONLY_NEW) != 0)) {
123             os::memory::LockHolder lock(created_classes_lock_);
124             for (const auto &cls : created_classes_) {
125                 if (!cb(cls)) {
126                     return false;
127                 }
128             }
129         }
130         if (!boot_context_.EnumerateClasses(cb, flags)) {
131             return false;
132         }
133 
134         {
135             os::memory::LockHolder lock(contexts_lock_);
136             for (auto *ctx : contexts_) {
137                 if (!ctx->EnumerateClasses(cb, flags)) {
138                     return false;
139                 }
140             }
141         }
142         return true;
143     }
144 
145     template <class ContextGetterFn>
RegisterContext(const ContextGetterFn & fn)146     void RegisterContext(const ContextGetterFn &fn)
147     {
148         os::memory::LockHolder lock(contexts_lock_);
149         auto *context = fn();
150         if (context != nullptr) {
151             contexts_.push_back(context);
152         }
153     }
154 
155     template <class Callback>
EnumerateContexts(const Callback & cb)156     void EnumerateContexts(const Callback &cb)
157     {
158         if (!cb(&boot_context_)) {
159             return;
160         }
161 
162         os::memory::LockHolder lock(contexts_lock_);
163         for (auto *context : contexts_) {
164             if (!cb(context)) {
165                 return;
166             }
167         }
168     }
169 
170     size_t NumLoadedClasses();
171 
172     void VisitLoadedClasses(size_t flag);
173 
ResolveContext(ClassLinkerContext * context)174     ClassLinkerContext *ResolveContext(ClassLinkerContext *context)
175     {
176         if (context == nullptr) {
177             return &boot_context_;
178         }
179 
180         return context;
181     }
182 
183     void OnClassPrepared(Class *klass);
184 
185     virtual Class *FromClassObject(ObjectHeader *obj);
186 
187     virtual size_t GetClassObjectSizeFromClassSize(uint32_t size);
188 
189     NO_COPY_SEMANTIC(ClassLinkerExtension);
190     NO_MOVE_SEMANTIC(ClassLinkerExtension);
191 
192 protected:
193     void InitializePrimitiveClassRoot(ClassRoot root, panda_file::Type::TypeId type_id, const char *descriptor);
194 
195     void InitializeArrayClassRoot(ClassRoot root, ClassRoot component_root, const char *descriptor);
196 
197     void FreeLoadedClasses();
198 
199     Class *AddClass(Class *klass);
200 
201     // Add the class to the list, when it is just be created and not added to class linker context.
202     void AddCreatedClass(Class *klass);
203 
204     // Remove class in the list, when it has been added to class linker context.
205     void RemoveCreatedClass(Class *klass);
206 
207     using PandaFilePtr = std::unique_ptr<const panda_file::File>;
208     virtual ClassLinkerContext *CreateApplicationClassLinkerContext(PandaVector<PandaFilePtr> &&app_files);
209 
210 private:
211     class BootContext : public ClassLinkerContext {
212     public:
BootContext(ClassLinkerExtension * extension)213         explicit BootContext(ClassLinkerExtension *extension) : extension_(extension)
214         {
215 #ifndef NDEBUG
216             lang_ = extension->GetLanguage();
217 #endif  // NDEBUG
218         }
219         ~BootContext() override = default;
220         NO_COPY_SEMANTIC(BootContext);
221         NO_MOVE_SEMANTIC(BootContext);
222 
IsBootContext()223         bool IsBootContext() const override
224         {
225             return true;
226         }
227 
228         Class *LoadClass(const uint8_t *descriptor, bool need_copy_descriptor,
229                          ClassLinkerErrorHandler *error_handler) override;
230 
231     private:
232         ClassLinkerExtension *extension_;
233     };
234 
235     class AppContext : public ClassLinkerContext {
236     public:
AppContext(ClassLinkerExtension * extension,PandaVector<const panda_file::File * > && pf_list)237         explicit AppContext(ClassLinkerExtension *extension, PandaVector<const panda_file::File *> &&pf_list)
238             : extension_(extension), pfs_(pf_list)
239         {
240 #ifndef NDEBUG
241             lang_ = extension_->GetLanguage();
242 #endif  // NDEBUG
243         }
244         ~AppContext() override = default;
245         NO_COPY_SEMANTIC(AppContext);
246         NO_MOVE_SEMANTIC(AppContext);
247 
248         Class *LoadClass(const uint8_t *descriptor, bool need_copy_descriptor,
249                          ClassLinkerErrorHandler *error_handler) override;
250 
GetPandaFilePaths()251         PandaVector<std::string_view> GetPandaFilePaths() const override
252         {
253             PandaVector<std::string_view> file_paths;
254             for (auto &pf : pfs_) {
255                 if (pf != nullptr) {
256                     file_paths.emplace_back(pf->GetFilename());
257                 }
258             }
259             return file_paths;
260         }
261 
262     private:
263         ClassLinkerExtension *extension_;
264         PandaVector<const panda_file::File *> pfs_;
265     };
266 
267     static constexpr size_t CLASS_ROOT_COUNT = static_cast<size_t>(ClassRoot::LAST_CLASS_ROOT_ENTRY) + 1;
268 
269     virtual bool InitializeImpl(bool compressed_string_enabled) = 0;
270 
ToIndex(ClassRoot root)271     static constexpr size_t ToIndex(ClassRoot root)
272     {
273         return static_cast<size_t>(root);
274     }
ResolveErrorHandler(ClassLinkerErrorHandler * error_handler)275     ClassLinkerErrorHandler *ResolveErrorHandler(ClassLinkerErrorHandler *error_handler)
276     {
277         if (error_handler == nullptr) {
278             return GetErrorHandler();
279         }
280 
281         return error_handler;
282     }
283 
284     panda_file::SourceLang lang_;
285     BootContext boot_context_;
286 
287     std::array<Class *, CLASS_ROOT_COUNT> class_roots_ {};
288     ClassLinker *class_linker_ {nullptr};
289 
290     os::memory::RecursiveMutex contexts_lock_;
291     PandaVector<ClassLinkerContext *> contexts_ GUARDED_BY(contexts_lock_);
292 
293     os::memory::RecursiveMutex created_classes_lock_;
294     PandaVector<Class *> created_classes_ GUARDED_BY(created_classes_lock_);
295 
296     bool can_initialize_classes_ {false};
297 };
298 
299 }  // namespace panda
300 
301 #endif  // PANDA_RUNTIME_INCLUDE_CLASS_LINKER_EXTENSION_H_
302