• 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 <memory>
21 #include <string>
22 #include <csignal>
23 #include <vector>
24 
25 #include "libpandabase/mem/arena_allocator.h"
26 #include "libpandabase/os/mutex.h"
27 #include "libpandabase/utils/expected.h"
28 #include "libpandafile/file_items.h"
29 #include "libpandafile/literal_data_accessor.h"
30 #include "runtime/include/class_linker.h"
31 #include "runtime/include/mem/panda_containers.h"
32 #include "runtime/include/mem/panda_smart_pointers.h"
33 #include "runtime/include/mem/panda_string.h"
34 #include "runtime/include/method.h"
35 #include "runtime/include/relayout_profiler.h"
36 #include "runtime/include/runtime_options.h"
37 #include "runtime/include/gc_task.h"
38 #include "runtime/include/tooling/debug_interface.h"
39 #include "runtime/mem/allocator_adapter.h"
40 #include "runtime/mem/gc/gc.h"
41 #include "runtime/mem/gc/gc_trigger.h"
42 #include "runtime/mem/memory_manager.h"
43 #include "runtime/monitor_pool.h"
44 #include "runtime/string_table.h"
45 #include "runtime/thread_manager.h"
46 #include "verification/verification_options.h"
47 #include "libpandabase/os/native_stack.h"
48 #include "libpandabase/os/library_loader.h"
49 #include "runtime/include/loadable_agent.h"
50 
51 namespace panda {
52 
53 class DProfiler;
54 class CompilerInterface;
55 class ClassHierarchyAnalysis;
56 class RuntimeController;
57 class PandaVM;
58 class RuntimeNotificationManager;
59 class Trace;
60 
61 namespace tooling {
62 class Debugger;
63 }  // namespace tooling
64 
65 using UnwindStackFn = os::unix::native_stack::FUNC_UNWINDSTACK;
66 
67 class Runtime {
68 public:
69     using ExitHook = void (*)(int32_t status);
70     using AbortHook = void (*)();
71 
72     enum class Error {
73         PANDA_FILE_LOAD_ERROR,
74         INVALID_ENTRY_POINT,
75         CLASS_NOT_FOUND,
76         CLASS_NOT_INITIALIZED,
77         METHOD_NOT_FOUND,
78         CLASS_LINKER_EXTENSION_NOT_FOUND
79     };
80 
81     class DebugSession final {
82     public:
83         explicit DebugSession(Runtime &runtime);
84         ~DebugSession();
85 
86         tooling::DebugInterface &GetDebugger();
87 
88     private:
89         Runtime &runtime_;
90         bool is_jit_enabled_;
91         os::memory::LockHolder<os::memory::Mutex> lock_;
92         PandaUniquePtr<tooling::DebugInterface> debugger_;
93 
94         NO_COPY_SEMANTIC(DebugSession);
95         NO_MOVE_SEMANTIC(DebugSession);
96     };
97 
98     using DebugSessionHandle = std::shared_ptr<DebugSession>;
99 
100     LanguageContext GetLanguageContext(const std::string &runtime_type);
101     LanguageContext GetLanguageContext(const Method &method);
102     LanguageContext GetLanguageContext(const Class &cls);
103     LanguageContext GetLanguageContext(const BaseClass &cls);
104     LanguageContext GetLanguageContext(panda_file::ClassDataAccessor *cda);
105     LanguageContext GetLanguageContext(panda_file::SourceLang lang);
106 
107     static bool CreateInstance(const RuntimeOptions &options, mem::InternalAllocatorPtr internal_allocator);
108 
109     PANDA_PUBLIC_API static bool Create(const RuntimeOptions &options);
110 
111     // Deprecated. Only for capability with ets_runtime.
112     PANDA_PUBLIC_API static bool Create(const RuntimeOptions &options, const std::vector<LanguageContextBase *> &ctxs);
113 
114     static bool DestroyUnderLockHolder();
115 
116     PANDA_PUBLIC_API static bool Destroy();
117 
118     PANDA_PUBLIC_API static Runtime *GetCurrent();
119 
120     template <typename Handler>
GetCurrentSync(Handler && handler)121     static auto GetCurrentSync(Handler &&handler)
122     {
123         os::memory::LockHolder<os::memory::Mutex> lock(mutex);
124         return handler(*GetCurrent());
125     }
126 
GetClassLinker()127     ClassLinker *GetClassLinker() const
128     {
129         return class_linker_;
130     }
131 
GetNotificationManager()132     RuntimeNotificationManager *GetNotificationManager() const
133     {
134         return notification_manager_;
135     }
136 
GetOptions()137     static const RuntimeOptions &GetOptions()
138     {
139         return options_;
140     }
141 
SetZygoteNoThreadSection(bool val)142     void SetZygoteNoThreadSection(bool val)
143     {
144         zygote_no_threads_ = val;
145     }
146 
147     coretypes::String *ResolveString(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
148 
149     coretypes::String *ResolveStringFromCompiledCode(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
150 
151     coretypes::String *ResolveString(PandaVM *vm, const panda_file::File &pf, panda_file::File::EntityId id,
152                                      const LanguageContext &ctx);
153 
154     coretypes::String *ResolveString(PandaVM *vm, const uint8_t *mutf8, uint32_t length, const LanguageContext &ctx);
155 
156     Class *GetClassRootForLiteralTag(const ClassLinkerExtension &ext, panda_file::LiteralTag tag) const;
157 
158     static bool GetLiteralTagAndValue(const panda_file::File &pf, uint32_t id, panda_file::LiteralTag *tag,
159                                       panda_file::LiteralDataAccessor::LiteralValue *value);
160 
161     uintptr_t GetPointerToConstArrayData(const panda_file::File &pf, uint32_t id) const;
162 
163     coretypes::Array *ResolveLiteralArray(PandaVM *vm, const Method &caller, uint32_t id);
164     coretypes::Array *ResolveLiteralArray(PandaVM *vm, const panda_file::File &pf, uint32_t id,
165                                           const LanguageContext &ctx);
166 
167     void PreZygoteFork();
168 
169     void PostZygoteFork();
170 
171     Expected<int, Error> ExecutePandaFile(std::string_view filename, std::string_view entry_point,
172                                           const std::vector<std::string> &args);
173 
174     int StartDProfiler(std::string_view app_name);
175 
176     Expected<int, Error> Execute(std::string_view entry_point, const std::vector<std::string> &args);
177 
178     int StartDProfiler(const PandaString &app_name);
179 
IsDebugMode()180     bool IsDebugMode() const
181     {
182         return is_debug_mode_;
183     }
184 
SetDebugMode(bool is_debug_mode)185     void SetDebugMode(bool is_debug_mode)
186     {
187         is_debug_mode_ = is_debug_mode;
188     }
189 
IsDebuggerConnected()190     bool IsDebuggerConnected() const
191     {
192         return is_debugger_connected_;
193     }
194 
SetDebuggerConnected(bool dbg_connected_state)195     void SetDebuggerConnected(bool dbg_connected_state)
196     {
197         is_debugger_connected_ = dbg_connected_state;
198     }
199 
IsProfileableFromShell()200     bool IsProfileableFromShell() const
201     {
202         return is_profileable_from_shell_;
203     }
204 
SetProfileableFromShell(bool profileable_from_shell)205     void SetProfileableFromShell(bool profileable_from_shell)
206     {
207         is_profileable_from_shell_ = profileable_from_shell;
208     }
209 
210     PandaVector<PandaString> GetBootPandaFiles();
211 
212     PandaVector<PandaString> GetPandaFiles();
213 
214     // Returns true if profile saving is enabled.
215     bool SaveProfileInfo() const;
216 
GetPandaPath()217     std::string GetPandaPath()
218     {
219         return panda_path_string_;
220     }
221 
GetRuntimeType()222     static const std::string &GetRuntimeType()
223     {
224         return runtime_type_;
225     }
226 
227     void UpdateProcessState(int state);
228 
IsZygote()229     bool IsZygote() const
230     {
231         return is_zygote_;
232     }
233 
IsInitialized()234     bool IsInitialized() const
235     {
236         return is_initialized_;
237     }
238 
239     // TODO: lack NativeBridgeAction action
240     void InitNonZygoteOrPostFork(bool is_system_server, const char *isa, bool profile_system_server = false);
241 
GetVersion()242     static const char *GetVersion()
243     {
244         // TODO(chenmudan): change to the correct version when we have one;
245         return "1.0.0";
246     }
247 
GetFingerprint()248     PandaString GetFingerprint()
249     {
250         return fingerPrint_;
251     }
252 
253     [[noreturn]] static void Halt(int32_t status);
254 
SetExitHook(ExitHook exit_hook)255     void SetExitHook(ExitHook exit_hook)
256     {
257         ASSERT(exit_ == nullptr);
258         exit_ = exit_hook;
259     }
260 
SetAbortHook(AbortHook abort_hook)261     void SetAbortHook(AbortHook abort_hook)
262     {
263         ASSERT(abort_ == nullptr);
264         abort_ = abort_hook;
265     }
266 
267     [[noreturn]] static void Abort(const char *message = nullptr);
268 
269     Expected<Method *, Error> ResolveEntryPoint(std::string_view entry_point);
270 
271     void RegisterSensitiveThread() const;
272 
273     // Deprecated.
274     // Get VM instance from the thread. In multi-vm runtime this method returns
275     // the first VM. It is undeterminated which VM will be first.
GetPandaVM()276     PandaVM *GetPandaVM() const
277     {
278         return panda_vm_;
279     }
280 
GetCha()281     ClassHierarchyAnalysis *GetCha() const
282     {
283         return cha_;
284     }
285 
GetVerificationOptions()286     const panda::verifier::VerificationOptions &GetVerificationOptions() const
287     {
288         return VerificationOptions_;
289     }
290 
GetVerificationOptions()291     panda::verifier::VerificationOptions &GetVerificationOptions()
292     {
293         return VerificationOptions_;
294     }
295 
IsDebuggerAttached()296     bool IsDebuggerAttached()
297     {
298         return debug_session_.use_count() > 0;
299     }
300 
301     void DumpForSigQuit(std::ostream &os);
302 
IsDumpNativeCrash()303     bool IsDumpNativeCrash()
304     {
305         return is_dump_native_crash_;
306     }
307 
IsChecksSuspend()308     bool IsChecksSuspend() const
309     {
310         return checks_suspend_;
311     }
312 
IsChecksStack()313     bool IsChecksStack() const
314     {
315         return checks_stack_;
316     }
317 
IsChecksNullptr()318     bool IsChecksNullptr() const
319     {
320         return checks_nullptr_;
321     }
322 
IsStacktrace()323     bool IsStacktrace() const
324     {
325         return is_stacktrace_;
326     }
327 
IsJitEnabled()328     bool IsJitEnabled() const
329     {
330         return is_jit_enabled_;
331     }
332 
ForceEnableJit()333     void ForceEnableJit()
334     {
335         is_jit_enabled_ = true;
336     }
337 
ForceDisableJit()338     void ForceDisableJit()
339     {
340         is_jit_enabled_ = false;
341     }
342 
343     static mem::GCType GetGCType(const RuntimeOptions &options, panda_file::SourceLang lang);
344 
345     static void SetDaemonMemoryLeakThreshold(uint32_t daemon_memory_leak_threshold);
346 
347     DebugSessionHandle StartDebugSession();
348 
GetInternalAllocator()349     mem::InternalAllocatorPtr GetInternalAllocator() const
350     {
351         return internal_allocator_;
352     }
353 
354     PandaString GetMemoryStatistics();
355     PandaString GetFinalStatistics();
356 
357     Expected<LanguageContext, Error> ExtractLanguageContext(const panda_file::File *pf, std::string_view entry_point);
358 
GetUnwindStackFn()359     UnwindStackFn GetUnwindStackFn() const
360     {
361         return unwind_stack_fn_;
362     }
363 
SetUnwindStackFn(UnwindStackFn unwind_stack_fn)364     void SetUnwindStackFn(UnwindStackFn unwind_stack_fn)
365     {
366         unwind_stack_fn_ = unwind_stack_fn;
367     }
368 
GetRelayoutProfiler()369     RelayoutProfiler *GetRelayoutProfiler()
370     {
371         return relayout_profiler_;
372     }
373 
374 private:
375     void NotifyAboutLoadedModules();
376 
377     std::optional<Error> CreateApplicationClassLinkerContext(std::string_view filename, std::string_view entry_point);
378 
379     bool LoadVerificationConfig();
380 
381     bool CreatePandaVM(std::string_view runtime_type);
382 
383     bool InitializePandaVM();
384 
385     bool HandleAotOptions();
386 
387     void HandleJitOptions();
388 
389     bool CheckOptionsConsistency();
390 
391     void SetPandaPath();
392 
393     bool Initialize();
394 
395     bool Shutdown();
396 
397     bool LoadBootPandaFiles(panda_file::File::OpenMode open_mode);
398 
399     static void BlockSignals();
400 
401     inline void InitializeVerificationResultCache();
402 
403     Runtime(const RuntimeOptions &options, mem::InternalAllocatorPtr internal_allocator);
404 
405     ~Runtime();
406 
407     static Runtime *instance;
408     static RuntimeOptions options_;
409     static std::string runtime_type_;
410     static os::memory::Mutex mutex;
411 
412     // TODO(dtrubenk): put all of it in the permanent space
413     mem::InternalAllocatorPtr internal_allocator_;
414     RuntimeNotificationManager *notification_manager_;
415     ClassLinker *class_linker_;
416     ClassHierarchyAnalysis *cha_;
417     DProfiler *dprofiler_ = nullptr;
418 
419     PandaVM *panda_vm_ = nullptr;
420 
421     // For IDE is real connected.
422     bool is_debug_mode_ {false};
423     bool is_debugger_connected_ {false};
424     bool is_profileable_from_shell_ {false};
425     os::memory::Mutex debug_session_creation_mutex_ {};
426     os::memory::Mutex debug_session_uniqueness_mutex_ {};
427     DebugSessionHandle debug_session_ {};
428 
429     // For saving class path.
430     std::string panda_path_string_;
431 
432     AbortHook abort_ = nullptr;
433     ExitHook exit_ = nullptr;
434 
435     bool zygote_no_threads_;
436     bool is_zygote_;
437     bool is_initialized_ {false};
438 
439     bool save_profiling_info_;
440 
441     bool checks_suspend_ {false};
442     bool checks_stack_ {true};
443     bool checks_nullptr_ {true};
444     bool is_stacktrace_ {false};
445     bool is_jit_enabled_ {false};
446 
447     bool is_dump_native_crash_ {true};
448 
449     PandaString fingerPrint_ = "unknown";
450 
451     // Verification
452     panda::verifier::VerificationOptions VerificationOptions_;
453 
454     struct AppContext {
455         ClassLinkerContext *ctx {nullptr};
456         std::optional<panda_file::SourceLang> lang;
457     };
458     AppContext app_context_ {};
459 
460     RuntimeController *runtime_controller_ {nullptr};
461     UnwindStackFn unwind_stack_fn_ {nullptr};
462 
463     RelayoutProfiler *relayout_profiler_ {nullptr};
464 
465     NO_COPY_SEMANTIC(Runtime);
466     NO_MOVE_SEMANTIC(Runtime);
467 };
468 
GetInternalAllocatorAdapter(const Runtime * runtime)469 inline mem::AllocatorAdapter<void> GetInternalAllocatorAdapter(const Runtime *runtime)
470 {
471     return runtime->GetInternalAllocator()->Adapter();
472 }
473 
474 void InitSignals();
475 
476 }  // namespace panda
477 
478 #endif  // PANDA_RUNTIME_RUNTIME_H_
479