• 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 #ifndef PANDA_RUNTIME_RUNTIME_H_
17 #define PANDA_RUNTIME_RUNTIME_H_
18 
19 #include <atomic>
20 #include <csignal>
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 #include "libpandabase/mem/arena_allocator.h"
26 #include "libpandabase/os/mutex.h"
27 #include "libpandabase/taskmanager/task_scheduler.h"
28 #include "libpandabase/utils/expected.h"
29 #include "libpandabase/utils/dfx.h"
30 #include "libpandafile/file_items.h"
31 #include "libpandafile/literal_data_accessor.h"
32 #include "runtime/include/class_linker.h"
33 #include "runtime/include/mem/panda_containers.h"
34 #include "runtime/include/mem/panda_smart_pointers.h"
35 #include "runtime/include/mem/panda_string.h"
36 #include "runtime/include/method.h"
37 #include "runtime/include/runtime_options.h"
38 #include "runtime/include/gc_task.h"
39 #ifndef PANDA_TARGET_WINDOWS
40 #include "runtime/signal_handler.h"
41 #endif
42 #include "runtime/mem/allocator_adapter.h"
43 #include "runtime/mem/gc/gc.h"
44 #include "runtime/mem/gc/gc_trigger.h"
45 #include "runtime/mem/memory_manager.h"
46 #include "runtime/monitor_pool.h"
47 #include "runtime/string_table.h"
48 #include "runtime/thread_manager.h"
49 #include "verification/public.h"
50 #include "libpandabase/os/native_stack.h"
51 #include "libpandabase/os/library_loader.h"
52 #include "runtime/include/loadable_agent.h"
53 #include "runtime/tooling/tools.h"
54 
55 namespace ark {
56 
57 class DProfiler;
58 class CompilerInterface;
59 class ClassHierarchyAnalysis;
60 class RuntimeController;
61 class PandaVM;
62 class RuntimeNotificationManager;
63 class Trace;
64 
65 namespace tooling {
66 class DebugInterface;
67 class MemoryAllocationDumper;
68 }  // namespace tooling
69 
70 using UnwindStackFn = os::native_stack::FuncUnwindstack;
71 
72 class PANDA_PUBLIC_API Runtime {
73 public:
74     using ExitHook = void (*)(int32_t status);
75     using AbortHook = void (*)();
76 
77     enum class Error {
78         PANDA_FILE_LOAD_ERROR,
79         INVALID_ENTRY_POINT,
80         CLASS_NOT_FOUND,
81         CLASS_NOT_INITIALIZED,
82         METHOD_NOT_FOUND,
83         CLASS_LINKER_EXTENSION_NOT_FOUND
84     };
85 
86     class DebugSession final {
87     public:
88         explicit DebugSession(Runtime &runtime);
89         ~DebugSession();
90 
91         tooling::DebugInterface &GetDebugger();
92 
93     private:
94         Runtime &runtime_;
95         bool isJitEnabled_;
96         os::memory::LockHolder<os::memory::Mutex> lock_;
97         PandaUniquePtr<tooling::DebugInterface> debugger_;
98 
99         NO_COPY_SEMANTIC(DebugSession);
100         NO_MOVE_SEMANTIC(DebugSession);
101     };
102 
103     using DebugSessionHandle = std::shared_ptr<DebugSession>;
104 
105     LanguageContext GetLanguageContext(const std::string &runtimeType);
106     LanguageContext GetLanguageContext(const Method &method);
107     LanguageContext GetLanguageContext(const Class &cls);
108     LanguageContext GetLanguageContext(const BaseClass &cls);
109     LanguageContext GetLanguageContext(panda_file::ClassDataAccessor *cda);
110     LanguageContext GetLanguageContext(panda_file::SourceLang lang);
111 
112     static bool CreateInstance(const RuntimeOptions &options, mem::InternalAllocatorPtr internalAllocator);
113 
114     static bool Create(const RuntimeOptions &options);
115 
116     // Deprecated. Only for capability with js_runtime.
117     static bool Create(const RuntimeOptions &options, const std::vector<LanguageContextBase *> &ctxs);
118 
119     static bool DestroyUnderLockHolder();
120 
121     static bool Destroy();
122 
123     static Runtime *GetCurrent();
124 
125     template <typename Handler>
GetCurrentSync(Handler && handler)126     static auto GetCurrentSync(Handler &&handler)
127     {
128         os::memory::LockHolder lock(mutex_);
129         return handler(*GetCurrent());
130     }
131 
GetRuntimeLock()132     static os::memory::Mutex *GetRuntimeLock()
133     {
134         return &mutex_;
135     }
136 
GetClassLinker()137     ClassLinker *GetClassLinker() const
138     {
139         return classLinker_;
140     }
141 
GetNotificationManager()142     RuntimeNotificationManager *GetNotificationManager() const
143     {
144         return notificationManager_;
145     }
146 
GetOptions()147     static const RuntimeOptions &GetOptions()
148     {
149         return options_;
150     }
151 
SetZygoteNoThreadSection(bool val)152     void SetZygoteNoThreadSection(bool val)
153     {
154         zygoteNoThreads_ = val;
155     }
156 
IsTaskManagerUsed()157     static bool IsTaskManagerUsed()
158     {
159         return isTaskManagerUsed_;
160     }
161 
SetTaskManagerUsed(bool value)162     static void SetTaskManagerUsed(bool value)
163     {
164         isTaskManagerUsed_ = value;
165     }
166 
167     coretypes::String *ResolveString(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
168 
169     coretypes::String *ResolveStringFromCompiledCode(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
170 
171     coretypes::String *ResolveString(PandaVM *vm, const panda_file::File &pf, panda_file::File::EntityId id,
172                                      const LanguageContext &ctx);
173 
174     coretypes::String *ResolveString(PandaVM *vm, const uint8_t *mutf8, uint32_t length, const LanguageContext &ctx);
175 
176     Class *GetClassRootForLiteralTag(const ClassLinkerExtension &ext, panda_file::LiteralTag tag) const;
177 
178     static bool GetLiteralTagAndValue(const panda_file::File &pf, uint32_t id, panda_file::LiteralTag *tag,
179                                       panda_file::LiteralDataAccessor::LiteralValue *value);
180 
181     uintptr_t GetPointerToConstArrayData(const panda_file::File &pf, uint32_t id) const;
182 
183     coretypes::Array *ResolveLiteralArray(PandaVM *vm, const Method &caller, uint32_t id);
184     coretypes::Array *ResolveLiteralArray(PandaVM *vm, const panda_file::File &pf, uint32_t id,
185                                           const LanguageContext &ctx);
186 
187     void PreZygoteFork();
188 
189     void PostZygoteFork();
190 
191     Expected<int, Error> ExecutePandaFile(std::string_view filename, std::string_view entryPoint,
192                                           const std::vector<std::string> &args);
193 
194     int StartDProfiler(std::string_view appName);
195 
196     int StartMemAllocDumper(const PandaString &dumpFile);
197 
198     Expected<int, Error> Execute(std::string_view entryPoint, const std::vector<std::string> &args);
199 
200     int StartDProfiler(const PandaString &appName);
201 
IsDebugMode()202     bool IsDebugMode() const
203     {
204         return isDebugMode_;
205     }
206 
SetDebugMode(bool isDebugMode)207     void SetDebugMode(bool isDebugMode)
208     {
209         isDebugMode_ = isDebugMode;
210     }
211 
IsDebuggerConnected()212     bool IsDebuggerConnected() const
213     {
214         return isDebuggerConnected_;
215     }
216 
SetDebuggerConnected(bool dbgConnectedState)217     void SetDebuggerConnected(bool dbgConnectedState)
218     {
219         isDebuggerConnected_ = dbgConnectedState;
220     }
221 
IsProfileableFromShell()222     bool IsProfileableFromShell() const
223     {
224         return isProfileableFromShell_;
225     }
226 
SetProfileableFromShell(bool profileableFromShell)227     void SetProfileableFromShell(bool profileableFromShell)
228     {
229         isProfileableFromShell_ = profileableFromShell;
230     }
231 
232     PandaVector<PandaString> GetBootPandaFiles();
233 
234     PandaVector<PandaString> GetPandaFiles();
235 
236     // Returns true if profile saving is enabled.
237     bool SaveProfileInfo() const;
238 
GetProcessPackageName()239     const std::string &GetProcessPackageName() const
240     {
241         return processPackageName_;
242     }
243 
SetProcessPackageName(const char * packageName)244     void SetProcessPackageName(const char *packageName)
245     {
246         if (packageName == nullptr) {
247             processPackageName_.clear();
248         } else {
249             processPackageName_ = packageName;
250         }
251     }
252 
GetProcessDataDirectory()253     const std::string &GetProcessDataDirectory() const
254     {
255         return processDataDirectory_;
256     }
257 
SetProcessDataDirectory(const char * dataDir)258     void SetProcessDataDirectory(const char *dataDir)
259     {
260         if (dataDir == nullptr) {
261             processDataDirectory_.clear();
262         } else {
263             processDataDirectory_ = dataDir;
264         }
265     }
266 
GetPandaPath()267     std::string GetPandaPath()
268     {
269         return pandaPathString_;
270     }
271 
GetRuntimeType()272     static const std::string &GetRuntimeType()
273     {
274         return runtimeType_;
275     }
276 
277     void UpdateProcessState(int state);
278 
IsZygote()279     bool IsZygote() const
280     {
281         return isZygote_;
282     }
283 
IsInitialized()284     bool IsInitialized() const
285     {
286         return isInitialized_;
287     }
288 
289     // NOTE(00510180): lack NativeBridgeAction action
290     void InitNonZygoteOrPostFork(bool isSystemServer, const char *isa, const std::function<void()> &initHook = {},
291                                  bool profileSystemServer = false);
292 
GetVersion()293     static const char *GetVersion()
294     {
295         // NOTE(chenmudan): change to the correct version when we have one;
296         return "1.0.0";
297     }
298 
GetFingerprint()299     PandaString GetFingerprint()
300     {
301         return fingerPrint_;
302     }
303 
304     [[noreturn]] static void Halt(int32_t status);
305 
SetExitHook(ExitHook exitHook)306     void SetExitHook(ExitHook exitHook)
307     {
308         ASSERT(exit_ == nullptr);
309         exit_ = exitHook;
310     }
311 
SetAbortHook(AbortHook abortHook)312     void SetAbortHook(AbortHook abortHook)
313     {
314         ASSERT(abort_ == nullptr);
315         abort_ = abortHook;
316     }
317 
318     [[noreturn]] static void Abort(const char *message = nullptr);
319 
320     Expected<Method *, Error> ResolveEntryPoint(std::string_view entryPoint);
321 
322     void RegisterSensitiveThread() const;
323 
324     // Deprecated.
325     // Get VM instance from the thread. In multi-vm runtime this method returns
326     // the first VM. It is undeterminated which VM will be first.
GetPandaVM()327     PandaVM *GetPandaVM() const
328     {
329         return pandaVm_;
330     }
331 
GetCha()332     ClassHierarchyAnalysis *GetCha() const
333     {
334         return cha_;
335     }
336 
GetVerificationConfig()337     ark::verifier::Config const *GetVerificationConfig() const
338     {
339         return verifierConfig_;
340     }
341 
GetVerificationConfig()342     ark::verifier::Config *GetVerificationConfig()
343     {
344         return verifierConfig_;
345     }
346 
GetVerifierService()347     ark::verifier::Service *GetVerifierService()
348     {
349         return verifierService_;
350     }
351 
IsDebuggerAttached()352     bool IsDebuggerAttached()
353     {
354         return debugSession_.use_count() > 0;
355     }
356 
357     void DumpForSigQuit(std::ostream &os);
358 
IsDumpNativeCrash()359     bool IsDumpNativeCrash()
360     {
361         return isDumpNativeCrash_;
362     }
363 
IsChecksSuspend()364     bool IsChecksSuspend() const
365     {
366         return checksSuspend_;
367     }
368 
IsChecksStack()369     bool IsChecksStack() const
370     {
371         return checksStack_;
372     }
373 
IsChecksNullptr()374     bool IsChecksNullptr() const
375     {
376         return checksNullptr_;
377     }
378 
IsStacktrace()379     bool IsStacktrace() const
380     {
381         return isStacktrace_;
382     }
383 
IsJitEnabled()384     bool IsJitEnabled() const
385     {
386         return isJitEnabled_;
387     }
388 
IsProfilerEnabled()389     bool IsProfilerEnabled() const
390     {
391         return isProfilerEnabled_ || isJitEnabled_;
392     }
393 
ForceEnableJit()394     void ForceEnableJit()
395     {
396         isJitEnabled_ = true;
397     }
398 
ForceDisableJit()399     void ForceDisableJit()
400     {
401         isJitEnabled_ = false;
402     }
403 
404 #ifndef PANDA_TARGET_WINDOWS
GetSignalManager()405     SignalManager *GetSignalManager()
406     {
407         return signalManager_;
408     }
409 #endif
410 
411     static mem::GCType GetGCType(const RuntimeOptions &options, panda_file::SourceLang lang);
412 
413     static void SetDaemonMemoryLeakThreshold(uint32_t daemonMemoryLeakThreshold);
414 
415     static void SetDaemonThreadsCount(uint32_t daemonThreadsCnt);
416 
417     DebugSessionHandle StartDebugSession();
418 
GetInternalAllocator()419     mem::InternalAllocatorPtr GetInternalAllocator() const
420     {
421         return internalAllocator_;
422     }
423 
424     PandaString GetMemoryStatistics();
425     PandaString GetFinalStatistics();
426 
427     Expected<LanguageContext, Error> ExtractLanguageContext(const panda_file::File *pf, std::string_view entryPoint);
428 
GetUnwindStackFn()429     UnwindStackFn GetUnwindStackFn() const
430     {
431         return unwindStackFn_;
432     }
433 
SetUnwindStackFn(UnwindStackFn unwindStackFn)434     void SetUnwindStackFn(UnwindStackFn unwindStackFn)
435     {
436         unwindStackFn_ = unwindStackFn;
437     }
438 
GetTools()439     inline tooling::Tools &GetTools()
440     {
441         return tools_;
442     }
443 
444 private:
445     void NotifyAboutLoadedModules();
446 
447     std::optional<Error> CreateApplicationClassLinkerContext(std::string_view filename, std::string_view entryPoint);
448 
449     bool LoadVerificationConfig();
450 
451     bool CreatePandaVM(std::string_view runtimeType);
452 
453     bool InitializePandaVM();
454 
455     bool HandleAotOptions();
456 
457     void HandleJitOptions();
458 
459     bool CheckOptionsConsistency();
460 
461     void CheckOptionsFromOs() const;
462 
463     void SetPandaPath();
464 
465     void SetThreadClassPointers();
466 
467     bool Initialize();
468 
469     bool Shutdown();
470 
471     bool LoadBootPandaFiles(panda_file::File::OpenMode openMode);
472 
473     void CheckBootPandaFiles();
474 
475     bool IsEnableMemoryHooks() const;
476 
477     /**
478      * @brief Unload debugger library and destroy debug session.
479      * As side effect, `Debugger` instance will be destroyed. Hence the method must be called
480      * during runtime destruction after sending `VmDeath` event and before uninitializing threads.
481      */
482     void UnloadDebugger();
483 
484     static void CreateDfxController(const RuntimeOptions &options);
485 
486     static void BlockSignals();
487 
488     inline void InitializeVerifierRuntime();
489 
490     Runtime(const RuntimeOptions &options, mem::InternalAllocatorPtr internalAllocator);
491 
492     ~Runtime();
493 
494     static Runtime *instance_;
495     static RuntimeOptions options_;
496     static std::string runtimeType_;
497     static os::memory::Mutex mutex_;
498     static bool isTaskManagerUsed_;
499 
500     // NOTE(dtrubenk): put all of it in the permanent space
501     mem::InternalAllocatorPtr internalAllocator_;
502     RuntimeNotificationManager *notificationManager_;
503     ClassLinker *classLinker_;
504     ClassHierarchyAnalysis *cha_;
505     DProfiler *dprofiler_ = nullptr;
506     tooling::MemoryAllocationDumper *memAllocDumper_ = nullptr;
507 
508     PandaVM *pandaVm_ = nullptr;
509 
510 #ifndef PANDA_TARGET_WINDOWS
511     SignalManager *signalManager_ {nullptr};
512 #endif
513 
514     // For IDE is real connected.
515     bool isDebugMode_ {false};
516     bool isDebuggerConnected_ {false};
517     bool isProfileableFromShell_ {false};
518     os::memory::Mutex debugSessionCreationMutex_ {};
519     os::memory::Mutex debugSessionUniquenessMutex_ {};
520     DebugSessionHandle debugSession_ {};
521 
522     // Additional VMInfo
523     std::string processPackageName_;
524     std::string processDataDirectory_;
525 
526     // For saving class path.
527     std::string pandaPathString_;
528 
529     AbortHook abort_ = nullptr;
530     ExitHook exit_ = nullptr;
531 
532     bool zygoteNoThreads_ {false};
533     bool isZygote_;
534     bool isInitialized_ {false};
535 
536     bool saveProfilingInfo_;
537 
538     bool checksSuspend_ {false};
539     bool checksStack_ {true};
540     bool checksNullptr_ {true};
541     bool isStacktrace_ {false};
542     bool isJitEnabled_ {false};
543     bool isProfilerEnabled_ {false};
544 
545     bool isDumpNativeCrash_ {true};
546 
547     PandaString fingerPrint_ = "unknown";
548 
549     // Verification
550     ark::verifier::Config *verifierConfig_ = nullptr;
551     ark::verifier::Service *verifierService_ = nullptr;
552 
553     struct AppContext {
554         ClassLinkerContext *ctx {nullptr};
555         std::optional<panda_file::SourceLang> lang;
556     };
557     AppContext appContext_ {};
558 
559     RuntimeController *runtimeController_ {nullptr};
560     UnwindStackFn unwindStackFn_ {nullptr};
561 
562     tooling::Tools tools_;
563 
564     NO_COPY_SEMANTIC(Runtime);
565     NO_MOVE_SEMANTIC(Runtime);
566 };
567 
GetInternalAllocatorAdapter(const Runtime * runtime)568 inline mem::AllocatorAdapter<void> GetInternalAllocatorAdapter(const Runtime *runtime)
569 {
570     return runtime->GetInternalAllocator()->Adapter();
571 }
572 
573 void InitSignals();
574 
575 }  // namespace ark
576 
577 #endif  // PANDA_RUNTIME_RUNTIME_H_
578