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