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 "common_components/taskpool/task.h" 20 #include "ecmascript/common.h" 21 #include "ecmascript/compiler/bytecodes.h" 22 #include "ecmascript/compiler/compilation_env.h" 23 #include "ecmascript/elements.h" 24 #include "ecmascript/js_primitive_ref.h" 25 #include "ecmascript/js_tagged_value.h" 26 #include "ecmascript/jspandafile/method_literal.h" 27 #include "ecmascript/mem/c_containers.h" 28 #include "ecmascript/mem/native_area_allocator.h" 29 #include "ecmascript/mem/region.h" 30 #include "ecmascript/mem/visitor.h" 31 #include "ecmascript/patch/patch_loader.h" 32 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h" 33 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h" 34 #include "ecmascript/pgo_profiler/types/pgo_type_generator.h" 35 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h" 36 #include "ecmascript/platform/mutex.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 JSHandle<JSFunction> jsFunction, JSHandle<GlobalEnv> env, 56 bool useRawProfileTypeInfo = false); 57 GetOpTypeMap()58 std::unordered_map<int32_t, const PGOSampleType *> GetOpTypeMap() 59 { 60 return bcOffsetPGOOpTypeMap_; 61 } GetRwTypeMap()62 std::unordered_map<int32_t, const PGORWOpType *> GetRwTypeMap() 63 { 64 return bcOffsetPGORwTypeMap_; 65 } GetDefOpTypeMap()66 std::unordered_map<int32_t, const PGODefineOpType *> GetDefOpTypeMap() 67 { 68 return bcOffsetPGODefOpTypeMap_; 69 } GetBoolMap()70 std::unordered_map<int32_t, bool> GetBoolMap() 71 { 72 return bcOffsetBoolMap_; 73 } InitJITProfiler()74 void InitJITProfiler() 75 { 76 mainThread_ = vm_->GetJSThread(); 77 ptManager_ = vm_->GetPTManager(); 78 } SetCompilationEnv(CompilationEnv * env)79 void SetCompilationEnv(CompilationEnv *env) 80 { 81 compilationEnv_ = env; 82 } InitChunk(Chunk * chunk)83 void InitChunk(Chunk* chunk) 84 { 85 chunk_ = chunk; 86 } 87 private: 88 static const int INVALID_METHOD_INDEX = 0; 89 enum class BCType : uint8_t { 90 STORE, 91 LOAD, 92 }; 93 94 // SampleType 95 void ConvertOpType(uint32_t slotId, long bcOffset); 96 void ConvertCall(uint32_t slotId, long bcOffset); 97 void ConvertNewObjRange(uint32_t slotId, long bcOffset); 98 void ConvertGetIterator(uint32_t slotId, long bcOffset); 99 100 // DefineType 101 void ConvertCreateObject(uint32_t slotId, long bcOffset, int32_t traceId); 102 103 // RwOpType 104 void ConvertICByName(int32_t bcOffset, uint32_t slotId, BCType type); 105 void ConvertICByNameWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass, 106 JSTaggedValue secondValue, BCType type, uint32_t slotId); 107 void HandleLoadType(ApEntityId &abcId, int32_t &bcOffset, 108 JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId); 109 void HandleLoadTypeInt(ApEntityId &abcId, int32_t &bcOffset, 110 JSHClass *hclass, JSTaggedValue &secondValue); 111 void HandleLoadTypePrototypeHandler( 112 ApEntityId &abcId, int32_t &bcOffset, JSHClass *hclass, 113 JSTaggedValue &secondValue, uint32_t slotId, 114 JSTaggedValue = JSTaggedValue::Undefined()); 115 void HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset, 116 JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId); 117 void HandleTransitionHandler(ApEntityId &abcId, int32_t &bcOffset, 118 JSHClass *hclass, JSTaggedValue &secondValue); 119 void HandleTransWithProtoHandler(ApEntityId &abcId, int32_t &bcOffset, 120 JSHClass *hclass, JSTaggedValue &secondValue); 121 void HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, 122 JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId); 123 void HandleStoreAOTHandler(ApEntityId &abcId, int32_t &bcOffset, 124 JSHClass *hclass, JSTaggedValue &secondValue); 125 void ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type, 126 uint32_t slotId); 127 void ConvertICByValue(int32_t bcOffset, uint32_t slotId, BCType type); 128 void ConvertICByValueWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass, JSTaggedValue secondValue, 129 BCType type, uint32_t slotId, JSTaggedValue name = JSTaggedValue::Undefined()); 130 void HandleStoreType(ApEntityId &abcId, int32_t &bcOffset, 131 JSHClass *hclass, JSTaggedValue &secondValue); 132 void HandleTransition(ApEntityId &abcId, int32_t &bcOffset, 133 JSHClass *hclass, JSTaggedValue &secondValue); 134 void HandleTransWithProto(ApEntityId &abcId, int32_t &bcOffset, 135 JSHClass *hclass, JSTaggedValue &secondValue); 136 void HandlePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset, 137 JSHClass *hclass, JSTaggedValue &secondValue); 138 void ConvertICByValueWithPoly(ApEntityId abcId, int32_t bcOffset, 139 JSTaggedValue name, JSTaggedValue cacheValue, 140 BCType type, uint32_t slotId); 141 void ConvertInstanceof(int32_t bcOffset, uint32_t slotId); 142 void ConvertTryldGlobalByName(uint32_t bcOffset, uint32_t slotId); 143 144 void ConvertExternalModuleVar(uint32_t index, uint32_t bcOffset); 145 146 // RwOpType related 147 void AddObjectInfoWithMega(int32_t bcOffset); 148 void AddObjectInfoImplement(int32_t bcOffset, const PGOObjectInfo &info, 149 JSTaggedValue name = JSTaggedValue::Undefined()); 150 bool AddTranstionObjectInfo(int32_t bcOffset, JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, 151 PGOSampleType accessorMethod, PrimitiveType primitiveType = PRIMITIVE_TYPE_INVALID, 152 JSTaggedValue name = JSTaggedValue::Undefined()); 153 bool AddObjectInfo(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver, 154 JSHClass *hold, JSHClass *holdTra, uint32_t accessorMethodId = INVALID_METHOD_INDEX, 155 PrimitiveType primitiveType = PRIMITIVE_TYPE_INVALID, 156 JSTaggedValue name = JSTaggedValue::Undefined()); 157 void AddBuiltinsInfo(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver, 158 JSHClass *transitionHClass, OnHeapMode onHeap = OnHeapMode::NONE, 159 bool everOutOfBounds = false); 160 bool IsTypedArrayRootHClass(JSType jsType, OnHeapMode mode, JSHClass *receiver); 161 void AddBuiltinsGlobalInfo(ApEntityId abcId, int32_t bcOffset, GlobalIndex globalId); 162 bool AddBuiltinsInfoByNameInInstance(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver); 163 bool AddBuiltinsInfoByNameInProt(ApEntityId abcId, int32_t bcOffset, 164 JSHClass *receiver, JSHClass *hold, bool isNonExist); 165 JSTaggedValue TryFindKeyInPrototypeChain(TaggedObject *currObj, JSHClass *currHC, JSTaggedValue key); 166 bool IsJSHClassNotEqual(JSHClass *receiver, JSHClass *hold, JSHClass *exceptRecvHClass, 167 JSHClass *exceptRecvHClassOnHeap, JSHClass *exceptHoldHClass, 168 JSHClass *exceptPrototypeOfPrototypeHClass); 169 // Other UpdatePGOType(uint32_t offset,const pgo::PGOType * type)170 void UpdatePGOType(uint32_t offset, const pgo::PGOType *type) 171 { 172 if (type->IsScalarOpType()) { 173 bcOffsetPGOOpTypeMap_[offset] = reinterpret_cast<const PGOSampleType *>(type); 174 } else if (type->IsRwOpType()) { 175 bcOffsetPGORwTypeMap_[offset] = reinterpret_cast<const PGORWOpType *>(type); 176 } else if (type->IsDefineOpType()) { 177 bcOffsetPGODefOpTypeMap_[offset] = reinterpret_cast<const PGODefineOpType *>(type); 178 } else { 179 UNREACHABLE(); 180 } 181 } 182 183 inline void SetBcOffsetBool(uint32_t offset, bool isInsufficientProfile = false) 184 { 185 bcOffsetBoolMap_[offset] = isInsufficientProfile; 186 } 187 188 inline bool IsIncompleteProfileTypeInfo(); 189 inline bool SlotValueIsUndefined(uint32_t slotId); 190 inline void UpdateBcOffsetBool(uint32_t offset, uint32_t slotId); 191 inline void UpdateBcOffsetBoolWithNearSlotId(uint32_t offset, uint32_t slotId); 192 193 void Clear(); 194 SetCurrentGlobalEnv(JSHandle<GlobalEnv> env)195 inline void SetCurrentGlobalEnv(JSHandle<GlobalEnv> env) 196 { 197 env_ = env; 198 } 199 GetCurrentGlobalEnv()200 inline const JSHandle<GlobalEnv> GetCurrentGlobalEnv() 201 { 202 return env_; 203 } 204 205 EcmaVM *vm_ { nullptr }; 206 JSThread *mainThread_ {nullptr}; 207 kungfu::PGOTypeManager *ptManager_ { nullptr }; 208 JSHandle<ProfileTypeInfo> profileTypeInfo_; 209 ApEntityId abcId_ { 0 }; 210 EntityId methodId_ {}; 211 std::unordered_map<int32_t, const PGOSampleType*> bcOffsetPGOOpTypeMap_ {}; 212 std::unordered_map<int32_t, const PGORWOpType*> bcOffsetPGORwTypeMap_ {}; 213 std::unordered_map<int32_t, const PGODefineOpType*> bcOffsetPGODefOpTypeMap_{}; 214 std::unordered_map<int32_t, bool> bcOffsetBoolMap_ {}; 215 RecursiveMutex mutex_; 216 CompilationEnv *compilationEnv_ {nullptr}; 217 Chunk *chunk_ {nullptr}; 218 JSHandle<JSFunction> jsFunction_; 219 JSHandle<GlobalEnv> env_; 220 }; 221 222 } 223 #endif //ECMASCRIPT_JIT_PROFILER_H 224