1 /*
2  * Copyright (c) 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 ECMASCRIPT_JIT_PROFILER_H
16 #define ECMASCRIPT_JIT_PROFILER_H
17 #include <chrono>
18 #include <memory>
19 #include "ecmascript/common.h"
20 #include "ecmascript/compiler/bytecodes.h"
21 #include "ecmascript/compiler/compilation_env.h"
22 #include "ecmascript/elements.h"
23 #include "ecmascript/ecma_context.h"
24 #include "ecmascript/js_tagged_value.h"
25 #include "ecmascript/jspandafile/method_literal.h"
26 #include "ecmascript/mem/c_containers.h"
27 #include "ecmascript/mem/native_area_allocator.h"
28 #include "ecmascript/mem/region.h"
29 #include "ecmascript/mem/visitor.h"
30 #include "ecmascript/patch/patch_loader.h"
31 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
32 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
33 #include "ecmascript/pgo_profiler/types/pgo_type_generator.h"
34 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
35 #include "ecmascript/platform/mutex.h"
36 #include "ecmascript/taskpool/task.h"
37 #include "ecmascript/pgo_profiler/pgo_utils.h"
38 namespace panda::ecmascript {
39 using namespace pgo;
40 class ProfileTypeInfo;
41 class JSFunction;
42 class PGOProfilerManager;
43 class JITProfiler {
44 public:
45     NO_COPY_SEMANTIC(JITProfiler);
46     NO_MOVE_SEMANTIC(JITProfiler);
47 
48     JITProfiler(EcmaVM *vm);
49 
50     virtual ~JITProfiler();
51     void PUBLIC_API ProfileBytecode(JSThread *thread, const JSHandle<ProfileTypeInfo> &profileTypeInfo,
52                                     ProfileTypeInfo *rawProfileTypeInfo,
53                                     EntityId methodId, ApEntityId abcId, const uint8_t *pcStart,
54                                     uint32_t codeSize, const panda_file::File::Header *header,
55                                     bool useRawProfileTypeInfo = false);
56 
GetOpTypeMap()57     std::unordered_map<int32_t, const PGOSampleType *> GetOpTypeMap()
58     {
59         return bcOffsetPGOOpTypeMap_;
60     }
GetRwTypeMap()61     std::unordered_map<int32_t, const PGORWOpType *> GetRwTypeMap()
62     {
63         return bcOffsetPGORwTypeMap_;
64     }
GetDefOpTypeMap()65     std::unordered_map<int32_t, const PGODefineOpType *> GetDefOpTypeMap()
66     {
67         return bcOffsetPGODefOpTypeMap_;
68     }
InitJITProfiler()69     void InitJITProfiler()
70     {
71         ptManager_ = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager();
72     }
SetCompilationEnv(CompilationEnv *env)73     void SetCompilationEnv(CompilationEnv *env)
74     {
75         compilationEnv_ = env;
76     }
InitChunk(Chunk* chunk)77     void InitChunk(Chunk* chunk)
78     {
79         chunk_ = chunk;
80     }
81 private:
82     enum class BCType : uint8_t {
83         STORE,
84         LOAD,
85     };
86 
87     // SampleType
88     void ConvertOpType(uint32_t slotId, long bcOffset);
89     void ConvertCall(uint32_t slotId, long bcOffset);
90     void ConvertNewObjRange(uint32_t slotId, long bcOffset);
91     void ConvertGetIterator(uint32_t slotId, long bcOffset);
92 
93     // DefineType
94     void ConvertCreateObject(uint32_t slotId, long bcOffset, int32_t traceId);
95 
96     // RwOpType
97     void ConvertICByName(int32_t bcOffset, uint32_t slotId,  BCType type);
98     void ConvertICByNameWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass,
99 		                    JSTaggedValue secondValue, BCType type, uint32_t slotId);
100     void HandleLoadType(ApEntityId &abcId, int32_t &bcOffset,
101                         JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId);
102     void HandleLoadTypeInt(ApEntityId &abcId, int32_t &bcOffset,
103                            JSHClass *hclass, JSTaggedValue &secondValue);
104     void HandleLoadTypePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
105                                         JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId);
106     void HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset,
107                           JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId);
108     void HandleTransitionHandler(ApEntityId &abcId, int32_t &bcOffset,
109                                  JSHClass *hclass, JSTaggedValue &secondValue);
110     void HandleTransWithProtoHandler(ApEntityId &abcId, int32_t &bcOffset,
111                                      JSHClass *hclass, JSTaggedValue &secondValue);
112     void HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
113                                           JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId);
114     void HandleStoreTSHandler(ApEntityId &abcId, int32_t &bcOffset,
115                               JSHClass *hclass, JSTaggedValue &secondValue);
116     void ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type,
117                                  uint32_t slotId);
118     void ConvertICByValue(int32_t bcOffset, uint32_t slotId, BCType type);
119     void ConvertICByValueWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass,
120 		                     JSTaggedValue secondValue, BCType type);
121     void HandleStoreType(ApEntityId &abcId, int32_t &bcOffset,
122                          JSHClass *hclass, JSTaggedValue &secondValue);
123     void HandleTransition(ApEntityId &abcId, int32_t &bcOffset,
124                           JSHClass *hclass, JSTaggedValue &secondValue);
125     void HandleTransWithProto(ApEntityId &abcId, int32_t &bcOffset,
126                               JSHClass *hclass, JSTaggedValue &secondValue);
127     void HandlePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
128                                 JSHClass *hclass, JSTaggedValue &secondValue);
129     void ConvertICByValueWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type);
130     void ConvertInstanceof(int32_t bcOffset, uint32_t slotId);
131 
132     // RwOpType related
133     void AddObjectInfoWithMega(int32_t bcOffset);
134     void AddObjectInfoImplement(int32_t bcOffset, const PGOObjectInfo &info);
135     bool AddTranstionObjectInfo(int32_t bcOffset, JSHClass *receiver,
136 		                JSHClass *hold, JSHClass *holdTra, PGOSampleType accessorMethod);
137     bool AddObjectInfo(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver,
138 		       JSHClass *hold, JSHClass *holdTra, uint32_t accessorMethodId = 0);
139     void AddBuiltinsInfo(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver,
140                          JSHClass *transitionHClass, OnHeapMode onHeap = OnHeapMode::NONE,
141                          bool everOutOfBounds = false);
142     void AddBuiltinsGlobalInfo(ApEntityId abcId, int32_t bcOffset, GlobalIndex globalsId);
143     bool AddBuiltinsInfoByNameInInstance(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver);
144     bool AddBuiltinsInfoByNameInProt(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver, JSHClass *hold);
145 
146     JSTaggedValue TryFindKeyInPrototypeChain(TaggedObject *currObj, JSHClass *currHC, JSTaggedValue key);
147     bool IsJSHClassNotEqual(JSHClass *receiver, JSHClass *hold, JSHClass *exceptRecvHClass,
148 		            JSHClass *exceptRecvHClassOnHeap, JSHClass *exceptHoldHClass,
149 			    JSHClass *exceptPrototypeOfPrototypeHClass);
150     // Other
UpdatePGOType(uint32_t offset, const pgo::PGOType *type)151     void UpdatePGOType(uint32_t offset, const pgo::PGOType *type)
152     {
153         if (type->IsScalarOpType()) {
154             bcOffsetPGOOpTypeMap_[offset] = reinterpret_cast<const PGOSampleType *>(type);
155         } else if (type->IsRwOpType()) {
156             bcOffsetPGORwTypeMap_[offset] = reinterpret_cast<const PGORWOpType *>(type);
157         } else if (type->IsDefineOpType()) {
158             bcOffsetPGODefOpTypeMap_[offset] = reinterpret_cast<const PGODefineOpType *>(type);
159         } else {
160             UNREACHABLE();
161         }
162     }
163 
164     void Clear();
165 
166     EcmaVM *vm_ { nullptr };
167     kungfu::PGOTypeManager *ptManager_ { nullptr };
168     ProfileTypeInfo* profileTypeInfo_ { nullptr };
169     ApEntityId abcId_ { 0 };
170     EntityId methodId_ {};
171     std::unordered_map<int32_t, const PGOSampleType*> bcOffsetPGOOpTypeMap_ {};
172     std::unordered_map<int32_t, const PGORWOpType*> bcOffsetPGORwTypeMap_ {};
173     std::unordered_map<int32_t, const PGODefineOpType*> bcOffsetPGODefOpTypeMap_{};
174     RecursiveMutex mutex_;
175     CompilationEnv *compilationEnv_ {nullptr};
176     Chunk *chunk_ {nullptr};
177 };
178 
179 }
180 #endif //ECMASCRIPT_JIT_PROFILER_H
181