1 /**
2  * Copyright (c) 2021-2024 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 #ifndef PANDA_RUNTIME_HOTRELOAD_HOTRELOAD_H_
16 #define PANDA_RUNTIME_HOTRELOAD_HOTRELOAD_H_
17 
18 #include "libpandabase/macros.h"
19 #include "libpandafile/file.h"
20 #include "runtime/include/class.h"
21 #include "runtime/include/managed_thread.h"
22 #include "runtime/include/mem/panda_containers.h"
23 #include "runtime/include/panda_vm.h"
24 #include "runtime/include/runtime.h"
25 #include "runtime/mem/rendezvous.h"
26 
27 namespace ark::hotreload {
28 
29 struct ClassContainment {
30     const panda_file::File *pf;
31     panda_file::File::EntityId classId;
32     const std::string className_;
33     Class *loadedClass;
34     Class *tmpClass;
35     uint32_t fChanges;
36 };
37 
38 enum class Error {
39     NONE,
40     INTERNAL,
41     CLASS_ALREADY_LOADED,
42     CLASS_NOT_FOUND,
43     EXTERNAL_CLASS_READ,
44     INVALID_INPUT_ARG,
45     UNSUPPORTED_CHANGES,
46     NO_DEBUGGER_ATTACHED,
47     CLASS_UNMODIFIABLE,
48     WRONG_CLASS_DESCRIPTOR,
49     INVALID_CLASS_FORMAT,
50     CIRCULAR_CLASS,
51     METHOD_ADDED,
52     METHOD_DELETED,
53     METHOD_SIGN,
54     CLASS_MODIFIERS,
55     HIERARCHY_CHANGED,
56     FIELD_CHANGED
57 };
58 
59 enum ChangesFlags : uint32_t {
60     F_NO_STRUCT_CHANGES = 0x0000U,
61     F_INHERITANCE = 0x0001U,
62     F_METHOD_SIGN = 0x0002U,
63     F_METHOD_DELETED = 0x0004U,
64     F_INTERFACES = 0x0008U,
65     F_FIELDS_TYPE = 0x0010U,
66     F_FIELDS_AMOUNT = 0x0020U,
67     F_ACCESS_FLAGS = 0x0040U,
68     F_METHOD_ADDED = 0x0080U
69 };
70 
71 enum class Type { STRUCTURAL, NORMAL, INVALID };
72 
73 class ArkHotreloadBase {
74 public:
75     /*
76      * There is no API for adding classes for hotreload
77      * 'cause its signature is language-dependent
78      * this API should be declared in superclass
79      */
80     PANDA_PUBLIC_API Error ProcessHotreload();
81 
82     PANDA_PUBLIC_API const panda_file::File *ReadAndOwnPandaFileFromFile(const char *location);
83     PANDA_PUBLIC_API const panda_file::File *ReadAndOwnPandaFileFromMemory(const void *buffer, size_t size);
84 
85     NO_COPY_SEMANTIC(ArkHotreloadBase);
86     NO_MOVE_SEMANTIC(ArkHotreloadBase);
87 
88 protected:
89     explicit ArkHotreloadBase(ManagedThread *mthread, panda_file::SourceLang lang);
90     virtual ~ArkHotreloadBase();
91 
92     virtual Error LangSpecificValidateClasses() = 0;
93     virtual void LangSpecificHotreloadPart() = 0;
94 
95     Error ValidateClassesHotreloadPossibility();
96     Error ValidateClassForHotreload(const ClassContainment &hCls);
97     Type RecognizeHotreloadType(ClassContainment *hCls);
98 
99     Type InheritanceChangesCheck(ClassContainment *hCls);
100     Type FlagsChangesCheck(ClassContainment *hCls);
101     Type FieldChangesCheck(ClassContainment *hCls);
102     Type MethodChangesCheck(ClassContainment *hCls);
103 
104     void ReloadClassNormal(const ClassContainment *hCls);
105     void UpdateVtablesInRuntimeClasses(ClassLinker *classLinker);
106     void AddLoadedPandaFilesToRuntime(ClassLinker *classLinker);
107     void AddObsoleteClassesToRuntime(ClassLinker *classLinker);
108 
109     using FieldIdTable = PandaUnorderedMap<panda_file::File::EntityId, panda_file::File::EntityId>;
110 
111     panda_file::SourceLang lang_;            // NOLINT(misc-non-private-member-variables-in-classes)
112     ManagedThread *thread_;                  // NOLINT(misc-non-private-member-variables-in-classes)
113     PandaVector<ClassContainment> classes_;  // NOLINT(misc-non-private-member-variables-in-classes)
114     PandaVector<std::unique_ptr<const panda_file::File>>
115         pandaFiles_;                                         // NOLINT(misc-non-private-member-variables-in-classes)
116     PandaUnorderedMap<Method *, Method *> methodsTable_;     // NOLINT(misc-non-private-member-variables-in-classes)
117     PandaUnorderedMap<Class *, FieldIdTable> fieldsTables_;  // NOLINT(misc-non-private-member-variables-in-classes)
118     PandaUnorderedSet<Class *> reloadedClasses_;             // NOLINT(misc-non-private-member-variables-in-classes)
119 };
120 
121 }  // namespace ark::hotreload
122 
123 #endif  // PANDA_RUNTIME_HOTRELOAD_HOTRELOAD_H_
124