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