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