• 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 std::string& methodName = "") 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     GateRef GetConstantGateWithoutCache(MachineType machineType, uint64_t value, GateType type);
69     void ClearConstantCache(MachineType machineType, uint64_t value, GateType type);
70     GateRef GetConstantStringGate(MachineType machineType, std::string_view str, GateType type);
71     GateRef NewArg(MachineType machineType, size_t index, GateType type, GateRef argRoot);
72     GateRef GetInitialEnvGate(GateRef depend, GateRef jsFunc);
73     size_t GetGateCount() const;
74     TimeStamp GetTime() const;
75     void AdvanceTime() const;
SetArch(bool isArch64)76     void SetArch(bool isArch64)
77     {
78         isArch64_ = isArch64;
79     }
IsArch64()80     bool IsArch64() const
81     {
82         return isArch64_;
83     }
84     void InitRoot();
GetRoot()85     GateRef GetRoot() const
86     {
87         return root_;
88     }
SetRoot(GateRef root)89     void SetRoot(GateRef root)
90     {
91         root_ = root;
92     }
93 
chunk()94     Chunk* chunk()
95     {
96         return &chunk_;
97     }
98 
GetMetaBuilder()99     GateMetaBuilder *GetMetaBuilder()
100     {
101         return &metaBuilder_;
102     }
103 
104     GateRef GetStateRoot() const;
105     GateRef GetDependRoot() const;
106     GateRef GetArgRoot() const;
107     GateRef GetReturnRoot() const;
108 
109 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
110     const GateMetaData* NAME()                  \
111     {                                           \
112         return metaBuilder_.NAME();             \
113     }
114     IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_META)
115 #undef DECLARE_GATE_META
116 
117 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
118     const GateMetaData* NAME(size_t value)      \
119     {                                           \
120         return metaBuilder_.NAME(value);        \
121     }
GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)122     GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)
123 #undef DECLARE_GATE_META
124 
125 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
126     const GateMetaData* NAME(uint64_t value)    \
127     {                                           \
128         return metaBuilder_.NAME(value);        \
129     }
130     GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_META)
131 #undef DECLARE_GATE_META
132 
133 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
134     const GateMetaData* NAME(bool value)        \
135     {                                           \
136         return metaBuilder_.NAME(value);        \
137     }
138     GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_META)
139 #undef DECLARE_GATE_META
140 
141 #define DECLARE_GATE_META_WITH_BOOL_VALUE_IN(NAME, OP, R, S, D, V)          \
142     const GateMetaData* NAME(size_t value, bool flag)                       \
143     {                                                                       \
144         return metaBuilder_.NAME(value, flag);                              \
145     }
146     GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_GATE_META_WITH_BOOL_VALUE_IN)
147 #undef DECLARE_GATE_META_WITH_BOOL_VALUE_IN
148 
149 #define DECLARE_GATE_META(NAME, OP, R, S, D, V)                    \
150     const GateMetaData* NAME(uint64_t value, uint64_t pcOffset)    \
151     {                                                              \
152         return metaBuilder_.NAME(value, pcOffset);                 \
153     }
154     GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META)
155 #undef DECLARE_GATE_META
156 
157 #define DECLARE_GATE_META_FOR_CALL(NAME, OP, R, S, D, V)                        \
158     const GateMetaData* NAME(uint64_t value, uint64_t pcOffset, bool noGC)      \
159     {                                                                           \
160         return metaBuilder_.NAME(value, pcOffset, noGC);                        \
161     }
162     GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_META_FOR_CALL)
163 #undef DECLARE_GATE_META_FOR_CALL
164 
165 #define DECLARE_GATE_META_FOR_NEW(NAME, OP, R, S, D, V)                        \
166     const GateMetaData* NAME(uint64_t value, uint64_t pcOffset,                \
167                              bool needPushArgv)                                \
168     {                                                                          \
169         return metaBuilder_.NAME(value, pcOffset, needPushArgv);               \
170     }
171     GATE_META_DATA_LIST_FOR_NEW(DECLARE_GATE_META_FOR_NEW)
172 #undef DECLARE_GATE_META_FOR_NEW
173 
174 #define DECLARE_GATE_META(NAME, OP, R, S, D, V)                    \
175     const GateMetaData* NAME(uint64_t pcOffset) const              \
176     {                                                              \
177         return metaBuilder_.NAME(pcOffset);                        \
178     }
179     GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META)
180 #undef DECLARE_GATE_META
181 
182     const GateMetaData* Nop()
183     {
184         return metaBuilder_.Nop();
185     }
186 
JSBytecode(size_t valuesIn,uint32_t methodId,EcmaOpcode opcode,uint32_t pcOffset,uint32_t bcIndex,bool writable,bool hasFrameState)187     const GateMetaData* JSBytecode(size_t valuesIn, uint32_t methodId, EcmaOpcode opcode,
188         uint32_t pcOffset, uint32_t bcIndex, bool writable, bool hasFrameState)
189     {
190         GateFlags writableFlags = writable ? GateFlags::NONE_FLAG : GateFlags::NO_WRITE;
191         GateFlags frameStateFlags = hasFrameState ? GateFlags::HAS_FRAME_STATE : GateFlags::NONE_FLAG;
192         GateFlags flags = static_cast<GateFlags>(writableFlags | frameStateFlags);
193         return metaBuilder_.JSBytecode(valuesIn, methodId, opcode, pcOffset, bcIndex, flags);
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 
IsOptimizedOrFastJit()210     bool IsOptimizedOrFastJit() const
211     {
212         return  IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame();
213     }
214 
IsOptimizedJSFunctionFrame()215     bool IsOptimizedJSFunctionFrame() const
216     {
217         return frameType_ == FrameType::OPTIMIZED_JS_FUNCTION_FRAME
218             || frameType_ == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
219     }
220 
IsFastJitFunctionFrame()221     bool IsFastJitFunctionFrame() const
222     {
223         return frameType_ == FrameType::FASTJIT_FUNCTION_FRAME
224             || frameType_ == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME;
225     }
226 
227     bool GetDebugInfo(GateRef g, size_t &index) const;
228 
IsOsr()229     bool IsOsr() const
230     {
231         return isOsr_;
232     }
233 
SetIsOsr()234     void SetIsOsr()
235     {
236         isOsr_ = true;
237     }
238 
239 #ifndef NDEBUG
240     class ScopedComment {
241     public:
242         explicit ScopedComment(std::string &&str, std::string_view *comment);
243 
~ScopedComment()244         ~ScopedComment()
245         {
246             *comment_ = old_;
247         }
248     private:
249         std::string_view old_;
250         std::string str_;
251         std::string_view *comment_;
252     };
253 
254     ScopedComment VisitGateBegin(GateRef visitedGate);
255     ScopedComment CommentBegin(std::string &&str);
256 #else
VisitGateBegin(GateRef visitedGate)257     size_t VisitGateBegin([[maybe_unused]] GateRef visitedGate)
258     {
259         return 0;
260     }
CommentBegin(GateRef visitedGate)261     size_t CommentBegin([[maybe_unused]] GateRef visitedGate)
262     {
263         return 0;
264     }
265 #endif
266 
267 private:
268     static const size_t CIRCUIT_SPACE = 1U << 30U;  // 1GB
269 public:
270     void Print(GateRef gate) const;
271     bool AddComment(GateRef g, std::string &&str);
272     std::string_view GetComment(GateRef gate) const;
273 
274 private:
275     GateType GetGateType(GateRef gate) const;
276     GateRef GetGateRef(const Gate *gate) const;
277     MachineType GetMachineType(GateRef gate) const;
278     void SetMark(GateRef gate, MarkCode mark) const;
279     OpCode GetOpCode(GateRef gate) const;
280     void SetMachineType(GateRef gate, MachineType machineType);
281     void SetGateType(GateRef gate, GateType type);
282     GateId GetId(GateRef gate) const;
283     void DeleteGate(GateRef gate);
284     void DecreaseIn(GateRef gate, size_t idx);
285 
286     MarkCode GetMark(GateRef gate) const;
287     void DeleteIn(GateRef gate, size_t idx);
288     void ModifyIn(GateRef gate, size_t idx, GateRef in);
289     void NewIn(GateRef gate, size_t idx, GateRef in);
290     std::vector<GateRef> GetOutVector(GateRef gate) const;
291     bool IsFirstOutNull(GateRef gate) const;
292     bool IsInGateNull(GateRef gate, size_t idx) const;
293     GateRef GetIn(GateRef gate, size_t idx) const;
294     bool IsValueSelector(GateRef gate) const;
295     bool IsSelector(GateRef gate) const;
296     bool IsControlCase(GateRef gate) const;
297     bool IsLoopHead(GateRef gate) const;
298     void ResetAllGateTimeStamps() const;
299     uint8_t *AllocateSpace(size_t gateSize);
300     Gate *AllocateGateSpace(size_t numIns);
301     size_t GetCircuitDataSize() const;
302     const void *GetSpaceDataStartPtrConst() const;
303     const void *GetSpaceDataEndPtrConst() const;
304     const uint8_t *GetDataPtrConst(size_t offset) const;
305     uint8_t *GetDataPtr(size_t offset);
306     Gate *LoadGatePtr(GateRef shift);
307     const Gate *LoadGatePtrConst(GateRef shift) const;
GetMetaData(GateRef gate)308     const GateMetaData *GetMetaData(GateRef gate) const
309     {
310         return LoadGatePtrConst(gate)->GetMetaData();
311     }
312 #ifndef NDEBUG
GetGateRefById(size_t id)313     GateRef GetGateRefById(size_t id) const
314     {
315         if (id > allGates_.size()) {
316             return NullGate();
317         }
318         return allGates_[id];
319     }
320 #endif
321 
322 private:
323     void* space_ {nullptr};
324     size_t circuitSize_ {0};
325     size_t gateCount_ {0};
326     TimeStamp time_;
327     std::map<std::tuple<MachineType, BitField, GateType>, GateRef> constantCache_ {};
328     std::map<std::pair<BitField, GateRef>, GateRef> constantDataCache_ {};
329     std::map<GateRef, GateRef> initialEnvCache_ {};
330     panda::ecmascript::FrameType frameType_ {FrameType::OPTIMIZED_FRAME};
331     bool isArch64_ { false };
332     bool isOsr_ { false };
333 
334     Chunk chunk_;
335     GateRef root_ { NullGate() };
336     GateRef dead_ { NullGate() };
337     GateRef replaceable_ { NullGate() };
338     GateMetaBuilder metaBuilder_;
339     ChunkMap<GateRef, size_t> gateToDInfo_;
340     DebugInfo* debugInfo_ {nullptr};
341 #ifndef NDEBUG
342     ChunkVector<GateRef> allGates_;
343     std::string_view currentComment_ {};
344 #endif
345 
346     friend class GateAccessor;
347     friend class ConstGateAccessor;
348     friend class Verifier;
349 };
350 }  // namespace panda::ecmascript::kungfu
351 
352 #endif  // ECMASCRIPT_COMPILER_CIRCUIT_H
353