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