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"
38namespace panda::ecmascript {
39using namespace pgo;
40class ProfileTypeInfo;
41class JSFunction;
42class PGOProfilerManager;
43class JITProfiler {
44public:
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
57    std::unordered_map<int32_t, const PGOSampleType *> GetOpTypeMap()
58    {
59        return bcOffsetPGOOpTypeMap_;
60    }
61    std::unordered_map<int32_t, const PGORWOpType *> GetRwTypeMap()
62    {
63        return bcOffsetPGORwTypeMap_;
64    }
65    std::unordered_map<int32_t, const PGODefineOpType *> GetDefOpTypeMap()
66    {
67        return bcOffsetPGODefOpTypeMap_;
68    }
69    void InitJITProfiler()
70    {
71        ptManager_ = vm_->GetJSThread()->GetCurrentEcmaContext()->GetPTManager();
72    }
73    void SetCompilationEnv(CompilationEnv *env)
74    {
75        compilationEnv_ = env;
76    }
77    void InitChunk(Chunk* chunk)
78    {
79        chunk_ = chunk;
80    }
81private:
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
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