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 
16 #ifndef ECMASCRIPT_COMPILER_BASELINE_BASELINE_COMPILER_H
17 #define ECMASCRIPT_COMPILER_BASELINE_BASELINE_COMPILER_H
18 
19 #include <unordered_map>
20 #include "ecmascript/ecma_vm.h"
21 #include "ecmascript/mem/machine_code.h"
22 #include "ecmascript/compiler/baseline/baseline_assembler.h"
23 #include "ecmascript/compiler/ecma_opcode_des.h"
24 #include "ecmascript/compiler/jit_compilation_env.h"
25 
26 namespace panda::ecmascript::kungfu {
27 
28 class BytecodeNativePcOffsetTable {
29 public:
30     BytecodeNativePcOffsetTable() = default;
31     ~BytecodeNativePcOffsetTable() = default;
32 
AddPosition(uint64_t nativePc)33     void AddPosition(uint64_t nativePc)
34     {
35         ASSERT(nativePc - prevNativePc < 256); // 256: the max number can be presented by uint8_t
36         auto nativePcDiff = static_cast<uint8_t>(nativePc - prevNativePc);
37         nativePcDiffInfo.emplace_back(static_cast<uint8_t>(nativePcDiff));
38         prevNativePc = nativePc;
39     }
40 
GetData()41     uint8_t *GetData()
42     {
43         return nativePcDiffInfo.data();
44     }
45 
GetSize() const46     size_t GetSize() const
47     {
48         return nativePcDiffInfo.size();
49     }
50 
GetPrevNativePc() const51     uint64_t GetPrevNativePc() const
52     {
53         return prevNativePc;
54     }
55 
56 private:
57     uint64_t prevNativePc = 0;
58     std::vector<uint8_t> nativePcDiffInfo;
59 };
60 
61 class BaselineCompiler {
62 public:
BaselineCompiler(EcmaVM *inputVM, CompilationEnv *inputEnv)63     explicit BaselineCompiler(EcmaVM *inputVM, CompilationEnv *inputEnv)
64         : vm(inputVM), compilationEnv(inputEnv), baselineAssembler(vm->GetJSOptions().GetTargetTriple()) {}
65 
~BaselineCompiler()66     ~BaselineCompiler()
67     {
68         for (auto elem : jumpMap) {
69             if (elem.second != nullptr) {
70                 delete elem.second;
71                 elem.second = nullptr;
72             }
73         }
74         jumpMap.clear();
75     }
76 
77     void Compile(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral);
78 
GetBaselineAssembler()79     BaselineAssembler &GetBaselineAssembler()
80     {
81         return baselineAssembler;
82     }
83 
84     bool CollectMemoryCodeInfos(MachineCodeDesc &codeDesc);
85 
86     void SetPfHeaderAddr(const JSPandaFile *jsPandaFile);
87 
88     void GetJumpToOffsets(const uint8_t *start, const uint8_t *end, std::unordered_set<size_t> &jumpToOffsets) const;
89 private:
90     EcmaVM *vm = nullptr;
91     CompilationEnv *compilationEnv = nullptr;
92     BaselineAssembler baselineAssembler;
93     size_t bytecodeOffset = 0;
94     std::unordered_map<size_t, JumpLabel*> jumpMap;
95 
96 #define BYTECODE_BASELINE_HANDLER(name) void Handle##name(const uint8_t *bytecodeArray);
97     ECMA_OPCODE_LIST(BYTECODE_BASELINE_HANDLER)
98 #undef BYTECODE_BASELINE_HANDLER
99     const uint8_t *pfHeaderAddr = nullptr;
100     const uint8_t *firstPC = nullptr;
101     static constexpr uint32_t ONE_BYTE_SIZE = 8;
102     static constexpr uint32_t TWO_BYTE_SIZE = 16;
103     static constexpr uint32_t THREE_BYTE_SIZE = 24;
104     BytecodeNativePcOffsetTable nativePcOffsetTable;
105 };
106 }  // namespace panda::ecmascript::kungfu
107 #endif  // ECMASCRIPT_COMPILER_BASELINE_BASELINE_COMPILER_H
108