• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_CIRCUIT_H
17 #define ECMASCRIPT_COMPILER_CIRCUIT_H
18 
19 #include <algorithm>
20 #include <iostream>
21 #include <map>
22 #include <unordered_map>
23 #include <vector>
24 
25 #include "ecmascript/compiler/gate.h"
26 #include "ecmascript/compiler/share_gate_meta_data.h"
27 #include "ecmascript/compiler/lcr_gate_meta_data.h"
28 #include "ecmascript/compiler/mcr_gate_meta_data.h"
29 #include "ecmascript/compiler/hcr_gate_meta_data.h"
30 #include "ecmascript/compiler/gate_meta_data_builder.h"
31 #include "ecmascript/frames.h"
32 
33 #include "libpandabase/macros.h"
34 #include "securec.h"
35 
36 namespace panda::ecmascript::kungfu {
37 class DebugInfo;
38 enum class VisitState : uint8_t {
39     UNVISITED,
40     PENDING,
41     VISITED,
42 };
43 
44 class Circuit {  // note: calling NewGate could make all saved Gate* invalid
45 public:
46     explicit Circuit(NativeAreaAllocator* allocator, DebugInfo* dInfo = nullptr, const char* funcName = nullptr,
47                      bool isArch64 = true, FrameType type = FrameType::OPTIMIZED_FRAME);
48     ~Circuit();
49     NO_COPY_SEMANTIC(Circuit);
50     NO_MOVE_SEMANTIC(Circuit);
51 
52     GateRef NewGate(const GateMetaData *meta, const std::vector<GateRef> &inList, const char* comment = nullptr);
53     GateRef NewGate(const GateMetaData *meta, MachineType machineType, GateType type, const char* comment = nullptr);
54     GateRef NewGate(const GateMetaData *meta, MachineType machineType,
55         const std::initializer_list<GateRef>& args, GateType type, const char* comment = nullptr);
56     GateRef NewGate(const GateMetaData *meta, MachineType machineType, size_t numIns,
57                     const GateRef inList[], GateType type, const char* comment = nullptr);
58     GateRef NewGate(const GateMetaData *meta, MachineType machineType,
59                     const std::vector<GateRef>& inList, GateType type, const char* comment = nullptr);
60     void PrintAllGates() const;
61     void PrintAllGatesWithBytecode() const;
62     void GetAllGates(std::vector<GateRef>& gates) const;
63     static GateRef NullGate();
64     void Verify(GateRef gate) const;
65     panda::ecmascript::FrameType GetFrameType() const;
66     void SetFrameType(panda::ecmascript::FrameType type);
67     GateRef GetConstantGate(MachineType machineType, uint64_t value, GateType type);
68     void ClearConstantCache(MachineType machineType, uint64_t value, GateType type);
69     GateRef GetConstantStringGate(MachineType machineType, std::string_view str, GateType type);
70     GateRef NewArg(MachineType machineType, size_t index, GateType type, GateRef argRoot);
71     GateRef GetInitialEnvGate(GateRef jsFunc);
72     size_t GetGateCount() const;
73     TimeStamp GetTime() const;
74     void AdvanceTime() const;
SetArch(bool isArch64)75     void SetArch(bool isArch64)
76     {
77         isArch64_ = isArch64;
78     }
IsArch64()79     bool IsArch64() const
80     {
81         return isArch64_;
82     }
83     void InitRoot();
GetRoot()84     GateRef GetRoot() const
85     {
86         return root_;
87     }
SetRoot(GateRef root)88     void SetRoot(GateRef root)
89     {
90         root_ = root;
91     }
92 
chunk()93     Chunk* chunk()
94     {
95         return &chunk_;
96     }
97 
GetMetaBuilder()98     GateMetaBuilder *GetMetaBuilder()
99     {
100         return &metaBuilder_;
101     }
102 
103     GateRef GetStateRoot() const;
104     GateRef GetDependRoot() const;
105     GateRef GetArgRoot() const;
106     GateRef GetReturnRoot() const;
107 
108 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
109     const GateMetaData* NAME()                  \
110     {                                           \
111         return metaBuilder_.NAME();             \
112     }
113     IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_META)
114 #undef DECLARE_GATE_META
115 
116 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
117     const GateMetaData* NAME(size_t value)      \
118     {                                           \
119         return metaBuilder_.NAME(value);        \
120     }
GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)121     GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)
122 #undef DECLARE_GATE_META
123 
124 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
125     const GateMetaData* NAME(uint64_t value)    \
126     {                                           \
127         return metaBuilder_.NAME(value);        \
128     }
129     GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_META)
130 #undef DECLARE_GATE_META
131 
132 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
133     const GateMetaData* NAME(bool value)        \
134     {                                           \
135         return metaBuilder_.NAME(value);        \
136     }
137     GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_META)
138 #undef DECLARE_GATE_META
139 
140 #define DECLARE_GATE_META_WITH_BOOL_VALUE_IN(NAME, OP, R, S, D, V)          \
141     const GateMetaData* NAME(size_t value, bool flag)                       \
142     {                                                                       \
143         return metaBuilder_.NAME(value, flag);                              \
144     }
145     GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_GATE_META_WITH_BOOL_VALUE_IN)
146 #undef DECLARE_GATE_META_WITH_BOOL_VALUE_IN
147 
148 #define DECLARE_GATE_META(NAME, OP, R, S, D, V)                    \
149     const GateMetaData* NAME(uint64_t value, uint64_t pcOffset)    \
150     {                                                              \
151         return metaBuilder_.NAME(value, pcOffset);                 \
152     }
153     GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META)
154 #undef DECLARE_GATE_META
155 
156 #define DECLARE_GATE_META_FOR_CALL(NAME, OP, R, S, D, V)                        \
157     const GateMetaData* NAME(uint64_t value, uint64_t pcOffset, bool noGC)      \
158     {                                                                           \
159         return metaBuilder_.NAME(value, pcOffset, noGC);                        \
160     }
161     GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_META_FOR_CALL)
162 #undef DECLARE_GATE_META_FOR_CALL
163 
164 #define DECLARE_GATE_META(NAME, OP, R, S, D, V)                    \
165     const GateMetaData* NAME(uint64_t pcOffset) const              \
166     {                                                              \
167         return metaBuilder_.NAME(pcOffset);                        \
168     }
169     GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META)
170 #undef DECLARE_GATE_META
171 
172     const GateMetaData* Nop()
173     {
174         return metaBuilder_.Nop();
175     }
176 
JSBytecode(size_t valuesIn,uint32_t methodId,EcmaOpcode opcode,uint32_t pcOffset,uint32_t bcIndex,bool writable,bool hasFrameState)177     const GateMetaData* JSBytecode(size_t valuesIn, uint32_t methodId, EcmaOpcode opcode,
178         uint32_t pcOffset, uint32_t bcIndex, bool writable, bool hasFrameState)
179     {
180         GateFlags writableFlags = writable ? GateFlags::NONE_FLAG : GateFlags::NO_WRITE;
181         GateFlags frameStateFlags = hasFrameState ? GateFlags::HAS_FRAME_STATE : GateFlags::NONE_FLAG;
182         GateFlags flags = static_cast<GateFlags>(writableFlags | frameStateFlags);
183         return metaBuilder_.JSBytecode(valuesIn, methodId, opcode, pcOffset, bcIndex, flags);
184     }
185 
TypedBinaryOp(uint64_t value,TypedBinOp binOp,PGOTypeRef type)186     const GateMetaData* TypedBinaryOp(uint64_t value, TypedBinOp binOp, PGOTypeRef type)
187     {
188         return metaBuilder_.TypedBinaryOp(value, binOp, type);
189     }
190 
TypedCallTargetCheckOp(uint32_t numIns,uint64_t value,TypedCallTargetCheckOp checkOp)191     const GateMetaData* TypedCallTargetCheckOp(uint32_t numIns, uint64_t value, TypedCallTargetCheckOp checkOp)
192     {
193         return metaBuilder_.TypedCallTargetCheckOp(numIns, value, checkOp);
194     }
195 
DeadGate()196     GateRef DeadGate()
197     {
198         if (dead_ == NullGate()) {
199             dead_ = NewGate(Dead(), MachineType::NOVALUE, GateType::Empty());
200         }
201         return dead_;
202     }
203 
GetMaxGateId()204     size_t GetMaxGateId() const
205     {
206         ASSERT(gateCount_ != 0);
207         return static_cast<size_t>(gateCount_ - 1);
208     }
209 
IsOptimizedJSFunctionFrame()210     bool IsOptimizedJSFunctionFrame() const
211     {
212         return frameType_ == FrameType::OPTIMIZED_JS_FUNCTION_FRAME
213             || frameType_ == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
214     }
215 
216     bool GetDebugInfo(GateRef g, size_t &index) const;
217 
218 private:
219     static const size_t CIRCUIT_SPACE = 1U << 30U;  // 1GB
220 
221     void Print(GateRef gate) const;
222     GateType GetGateType(GateRef gate) const;
223     GateRef GetGateRef(const Gate *gate) const;
224     MachineType GetMachineType(GateRef gate) const;
225     void SetMark(GateRef gate, MarkCode mark) const;
226     OpCode GetOpCode(GateRef gate) const;
227     void SetMachineType(GateRef gate, MachineType machineType);
228     void SetGateType(GateRef gate, GateType type);
229     GateId GetId(GateRef gate) const;
230     void DeleteGate(GateRef gate);
231     void DecreaseIn(GateRef gate, size_t idx);
232 
233     MarkCode GetMark(GateRef gate) const;
234     void DeleteIn(GateRef gate, size_t idx);
235     void ModifyIn(GateRef gate, size_t idx, GateRef in);
236     void NewIn(GateRef gate, size_t idx, GateRef in);
237     std::vector<GateRef> GetOutVector(GateRef gate) const;
238     bool IsFirstOutNull(GateRef gate) const;
239     bool IsInGateNull(GateRef gate, size_t idx) const;
240     GateRef GetIn(GateRef gate, size_t idx) const;
241     bool IsValueSelector(GateRef gate) const;
242     bool IsSelector(GateRef gate) const;
243     bool IsControlCase(GateRef gate) const;
244     bool IsLoopHead(GateRef gate) const;
245     void ResetAllGateTimeStamps() const;
246     uint8_t *AllocateSpace(size_t gateSize);
247     Gate *AllocateGateSpace(size_t numIns);
248     size_t GetCircuitDataSize() const;
249     const void *GetSpaceDataStartPtrConst() const;
250     const void *GetSpaceDataEndPtrConst() const;
251     const uint8_t *GetDataPtrConst(size_t offset) const;
252     uint8_t *GetDataPtr(size_t offset);
253     Gate *LoadGatePtr(GateRef shift);
254     const Gate *LoadGatePtrConst(GateRef shift) const;
255     bool AddComment(GateRef g, const char* str);
GetMetaData(GateRef gate)256     const GateMetaData *GetMetaData(GateRef gate) const
257     {
258         return LoadGatePtrConst(gate)->GetMetaData();
259     }
260 #ifndef NDEBUG
GetGateRefById(size_t id)261     GateRef GetGateRefById(size_t id) const
262     {
263         if (id > allGates_.size()) {
264             return NullGate();
265         }
266         return allGates_[id];
267     }
268 #endif
269 
270 private:
271     void* space_ {nullptr};
272     size_t circuitSize_ {0};
273     size_t gateCount_ {0};
274     TimeStamp time_;
275     std::map<std::tuple<MachineType, BitField, GateType>, GateRef> constantCache_ {};
276     std::map<std::pair<BitField, GateRef>, GateRef> constantDataCache_ {};
277     std::map<GateRef, GateRef> initialEnvCache_ {};
278     panda::ecmascript::FrameType frameType_ {FrameType::OPTIMIZED_FRAME};
279     bool isArch64_ { false };
280 
281     Chunk chunk_;
282     GateRef root_ { NullGate() };
283     GateRef dead_ { NullGate() };
284     GateRef replaceable_ { NullGate() };
285     GateMetaBuilder metaBuilder_;
286     ChunkMap<GateRef, size_t> gateToDInfo_;
287     DebugInfo* debugInfo_ {nullptr};
288 #ifndef NDEBUG
289     ChunkVector<GateRef> allGates_;
290 #endif
291 
292     friend class GateAccessor;
293     friend class ConstGateAccessor;
294     friend class Verifier;
295 };
296 }  // namespace panda::ecmascript::kungfu
297 
298 #endif  // ECMASCRIPT_COMPILER_CIRCUIT_H
299