• 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 #ifndef PANDA_RUNTIME_CLASS_LINKER_CONTEXT_H_
16 #define PANDA_RUNTIME_CLASS_LINKER_CONTEXT_H_
17 
18 #include "libpandabase/macros.h"
19 #include "libpandabase/mem/object_pointer.h"
20 #include "libpandabase/os/mutex.h"
21 #include "libpandabase/utils/bit_utils.h"
22 #include "runtime/include/class.h"
23 #include "runtime/include/mem/panda_containers.h"
24 #include "runtime/mem/gc/gc.h"
25 #include "runtime/mem/gc/gc_root.h"
26 #include "runtime/mem/object_helpers.h"
27 
28 namespace panda {
29 
30 class ClassLinker;
31 class ClassLinkerErrorHandler;
32 
33 class ClassLinkerContext {
34 public:
ClassLinkerContext(panda_file::SourceLang lang)35     explicit ClassLinkerContext(panda_file::SourceLang lang) : lang_(lang) {}
FindClass(const uint8_t * descriptor)36     Class *FindClass(const uint8_t *descriptor)
37     {
38         os::memory::LockHolder lock(classes_lock_);
39         auto it = loaded_classes_.find(descriptor);
40         if (it != loaded_classes_.cend()) {
41             return it->second;
42         }
43 
44         return nullptr;
45     }
46 
IsBootContext()47     virtual bool IsBootContext() const
48     {
49         return false;
50     }
51 
GetSourceLang()52     panda_file::SourceLang GetSourceLang()
53     {
54         return lang_;
55     }
56 
LoadClass(const uint8_t * descriptor,bool need_copy_descriptor,ClassLinkerErrorHandler * error_handler)57     virtual Class *LoadClass([[maybe_unused]] const uint8_t *descriptor, [[maybe_unused]] bool need_copy_descriptor,
58                              [[maybe_unused]] ClassLinkerErrorHandler *error_handler)
59     {
60         return nullptr;
61     }
62 
InsertClass(Class * klass)63     Class *InsertClass(Class *klass)
64     {
65         os::memory::LockHolder lock(classes_lock_);
66         auto *other_klass = FindClass(klass->GetDescriptor());
67         if (other_klass != nullptr) {
68             return other_klass;
69         }
70 
71         ASSERT(klass->GetSourceLang() == lang_);
72         loaded_classes_.insert({klass->GetDescriptor(), klass});
73         return nullptr;
74     }
75 
RemoveClass(Class * klass)76     void RemoveClass(Class *klass)
77     {
78         os::memory::LockHolder lock(classes_lock_);
79         loaded_classes_.erase(klass->GetDescriptor());
80     }
81 
82     template <class Callback>
EnumerateClasses(const Callback & cb)83     bool EnumerateClasses(const Callback &cb)
84     {
85         os::memory::LockHolder lock(classes_lock_);
86         for (const auto &v : loaded_classes_) {
87             if (!cb(v.second)) {
88                 return false;
89             }
90         }
91         return true;
92     }
93 
EnumeratePandaFiles(const std::function<bool (const panda_file::File &)> &)94     virtual void EnumeratePandaFiles(const std::function<bool(const panda_file::File &)> & /* cb */) const {}
95 
NumLoadedClasses()96     size_t NumLoadedClasses()
97     {
98         os::memory::LockHolder lock(classes_lock_);
99         return loaded_classes_.size();
100     }
101 
VisitLoadedClasses(size_t flag)102     void VisitLoadedClasses(size_t flag)
103     {
104         os::memory::LockHolder lock(classes_lock_);
105         for (auto &loaded_class : loaded_classes_) {
106             auto class_ptr = loaded_class.second;
107             class_ptr->DumpClass(GET_LOG_STREAM(ERROR, RUNTIME), flag);
108         }
109     }
110 
VisitGCRoots(const ObjectVisitor & cb)111     void VisitGCRoots(const ObjectVisitor &cb)
112     {
113         for (auto root : roots_) {
114             cb(root);
115         }
116     }
117 
AddGCRoot(ObjectHeader * obj)118     bool AddGCRoot(ObjectHeader *obj)
119     {
120         os::memory::LockHolder lock(classes_lock_);
121         for (auto root : roots_) {
122             if (root == obj) {
123                 return false;
124             }
125         }
126 
127         roots_.emplace_back(obj);
128         return true;
129     }
130 
UpdateGCRoots()131     void UpdateGCRoots()
132     {
133         for (auto &root : roots_) {
134             if (root->IsForwarded()) {
135                 root = ::panda::mem::GetForwardAddress(root);
136             }
137         }
138     }
139 
GetPandaFilePaths()140     virtual PandaVector<std::string_view> GetPandaFilePaths() const
141     {
142         return PandaVector<std::string_view>();
143     }
144 
Dump(std::ostream & os)145     virtual void Dump(std::ostream &os)
146     {
147         os << "|Class loader :\"" << this << "\" "
148            << "|Loaded Classes:" << NumLoadedClasses() << "\n";
149     }
150 
FindClassLoaderParent(ClassLinkerContext * parent)151     virtual bool FindClassLoaderParent([[maybe_unused]] ClassLinkerContext *parent)
152     {
153         parent = nullptr;
154         return false;
155     }
156 
157     ClassLinkerContext() = default;
158     virtual ~ClassLinkerContext() = default;
159 
160     NO_COPY_SEMANTIC(ClassLinkerContext);
161     NO_MOVE_SEMANTIC(ClassLinkerContext);
162 
163 private:
164     // Dummy fix of concurrency issues to evaluate degradation
165     os::memory::RecursiveMutex classes_lock_;
166     PandaUnorderedMap<const uint8_t *, Class *, utf::Mutf8Hash, utf::Mutf8Equal> loaded_classes_
167         GUARDED_BY(classes_lock_);
168     PandaVector<ObjectPointer<ObjectHeader>> roots_;
169     panda_file::SourceLang lang_ {panda_file::SourceLang::PANDA_ASSEMBLY};
170 };
171 
172 }  // namespace panda
173 
174 #endif  // PANDA_RUNTIME_CLASS_LINKER_CONTEXT_H_
175