• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 <cstdlib>
17 
18 #include "mem/lock_config_helper.h"
19 #include "runtime/default_debugger_agent.h"
20 #include "runtime/include/runtime.h"
21 #include "runtime/include/runtime_options.h"
22 #include "runtime/include/runtime_notification.h"
23 #include "runtime/include/panda_vm.h"
24 #include "runtime/include/thread_scopes.h"
25 #include "runtime/mem/gc/reference-processor/reference_processor.h"
26 
27 #include "libpandafile/file.h"
28 
29 namespace ark {
30 /* static */
Create(Runtime * runtime,const RuntimeOptions & options,std::string_view runtimeType)31 PandaVM *PandaVM::Create(Runtime *runtime, const RuntimeOptions &options, std::string_view runtimeType)
32 {
33     LanguageContext ctx = runtime->GetLanguageContext(std::string(runtimeType));
34     return ctx.CreateVM(runtime, options);
35 }
36 
VisitVmRoots(const GCRootVisitor & visitor)37 void PandaVM::VisitVmRoots(const GCRootVisitor &visitor)
38 {
39     os::memory::LockHolder lock(markQueueLock_);
40     for (ObjectHeader *obj : markQueue_) {
41         visitor(mem::GCRoot(mem::RootType::ROOT_VM, obj));
42     }
43 }
44 
UpdateVmRefs(const GCRootUpdater & gcRootUpdater)45 void PandaVM::UpdateVmRefs(const GCRootUpdater &gcRootUpdater)
46 {
47     os::memory::LockHolder lock(markQueueLock_);
48     // NOLINTNEXTLINE(modernize-loop-convert)
49     for (auto it = markQueue_.begin(); it != markQueue_.end(); ++it) {
50         gcRootUpdater(&(*it));
51     }
52 }
53 
InvokeEntrypoint(Method * entrypoint,const std::vector<std::string> & args)54 Expected<int, Runtime::Error> PandaVM::InvokeEntrypoint(Method *entrypoint, const std::vector<std::string> &args)
55 {
56     if (!CheckEntrypointSignature(entrypoint)) {
57         LOG(ERROR, RUNTIME) << "Method '" << entrypoint->GetFullName(true) << "' has invalid signature";
58         return Unexpected(Runtime::Error::INVALID_ENTRY_POINT);
59     }
60     Expected<int, Runtime::Error> ret = InvokeEntrypointImpl(entrypoint, args);
61     ManagedThread *thread = ManagedThread::GetCurrent();
62     ASSERT(thread != nullptr);
63     bool hasException = false;
64     {
65         ScopedManagedCodeThread s(thread);
66         hasException = thread->HasPendingException();
67     }
68     if (hasException) {
69         HandleUncaughtException();
70         ret = EXIT_FAILURE;
71     }
72 
73     return ret;
74 }
75 
HandleLdaStr(Frame * frame,BytecodeId stringId)76 void PandaVM::HandleLdaStr(Frame *frame, BytecodeId stringId)
77 {
78     coretypes::String *str = ark::Runtime::GetCurrent()->ResolveString(this, *frame->GetMethod(), stringId.AsFileId());
79     frame->GetAccAsVReg().SetReference(str);
80 }
81 
OpenPandaFile(std::string_view location)82 std::unique_ptr<const panda_file::File> PandaVM::OpenPandaFile(std::string_view location)
83 {
84     return panda_file::OpenPandaFile(location);
85 }
86 
GetNonMovableString(const panda_file::File & pf,panda_file::File::EntityId id) const87 coretypes::String *PandaVM::GetNonMovableString(const panda_file::File &pf, panda_file::File::EntityId id) const
88 {
89     auto cachedString = GetStringTable()->GetInternalStringFast(pf, id);
90     if (cachedString == nullptr) {
91         return nullptr;
92     }
93 
94     if (!GetHeapManager()->IsObjectInNonMovableSpace(cachedString)) {
95         return nullptr;
96     }
97 
98     return cachedString;
99 }
100 
ShouldEnableDebug()101 bool PandaVM::ShouldEnableDebug()
102 {
103     return !Runtime::GetOptions().GetDebuggerLibraryPath().empty() || Runtime::GetOptions().IsDebuggerEnable();
104 }
105 
106 // Intrusive GC test API
MarkObject(ObjectHeader * obj)107 void PandaVM::MarkObject(ObjectHeader *obj)
108 {
109     os::memory::LockHolder lock(markQueueLock_);
110     markQueue_.push_back(obj);
111 }
112 
IterateOverMarkQueue(const std::function<void (ObjectHeader *)> & visitor)113 void PandaVM::IterateOverMarkQueue(const std::function<void(ObjectHeader *)> &visitor)
114 {
115     os::memory::LockHolder lock(markQueueLock_);
116     for (ObjectHeader *obj : markQueue_) {
117         visitor(obj);
118     }
119 }
120 
ClearMarkQueue()121 void PandaVM::ClearMarkQueue()
122 {
123     os::memory::LockHolder lock(markQueueLock_);
124     markQueue_.clear();
125 }
126 
FreeInternalResources()127 void PandaVM::FreeInternalResources()
128 {
129     // Run monitor deflation first
130     GetMonitorPool()->DeflateMonitors();
131 }
132 
CreateDebuggerAgent()133 LoadableAgentHandle PandaVM::CreateDebuggerAgent()
134 {
135     if (!Runtime::GetOptions().GetDebuggerLibraryPath().empty()) {
136         return DefaultDebuggerAgent::LoadInstance();
137     }
138 
139     return {};
140 }
141 
GetClassesFootprint() const142 PandaString PandaVM::GetClassesFootprint() const
143 {
144     ASSERT(GetLanguageContext().GetLanguageType() == LangTypeT::LANG_TYPE_STATIC);
145     PandaVector<Class *> classes;
146     auto classLinker = Runtime::GetCurrent()->GetClassLinker();
147     classLinker->EnumerateClasses([&classes](Class *cls) {
148         classes.push_back(cls);
149         return true;
150     });
151 
152     PandaVector<uint64_t> footprintOfClasses(classes.size(), 0U);
153     GetHeapManager()->CountInstances(classes, true, footprintOfClasses.data());
154 
155     PandaMultiMap<uint64_t, Class *> footprintToClass;
156     for (size_t index = 0; index < classes.size(); ++index) {
157         footprintToClass.insert({footprintOfClasses[index], classes[index]});
158     }
159 
160     PandaStringStream statistic;
161     PandaMultiMap<uint64_t, Class *>::reverse_iterator rit;
162     for (rit = footprintToClass.rbegin(); rit != footprintToClass.rend(); ++rit) {
163         if (rit->first == 0U) {
164             break;
165         }
166         auto clazz = rit->second;
167         statistic << "class: " << clazz->GetName() << ", footprint - " << rit->first << std::endl;
168     }
169     return statistic.str();
170 }
171 
ProcessReferenceFinalizers()172 void PandaVM::ProcessReferenceFinalizers()
173 {
174     GetReferenceProcessor()->ProcessFinalizers();
175 }
176 
177 }  // namespace ark
178