• 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 class ArgumentAccessor;
39 enum class VisitState : uint8_t {
40     UNVISITED,
41     PENDING,
42     VISITED,
43 };
44 
45 class Circuit {  // note: calling NewGate could make all saved Gate* invalid
46 public:
47     explicit Circuit(NativeAreaAllocator* allocator, DebugInfo* dInfo = nullptr, const char* funcName = nullptr,
48                      bool isArch64 = true, FrameType type = FrameType::OPTIMIZED_FRAME);
49     ~Circuit();
50     NO_COPY_SEMANTIC(Circuit);
51     NO_MOVE_SEMANTIC(Circuit);
52 
53     ArgumentAccessor *GetArgumentAccessor();
54     GateRef NewGate(const GateMetaData *meta, const std::vector<GateRef> &inList, const char* comment = nullptr);
55     GateRef NewGate(const GateMetaData *meta, MachineType machineType, GateType type, const char* comment = nullptr);
56     GateRef NewGate(const GateMetaData *meta, MachineType machineType,
57         const std::initializer_list<GateRef>& args, GateType type, const char* comment = nullptr);
58     GateRef NewGate(const GateMetaData *meta, MachineType machineType, size_t numIns,
59                     const GateRef inList[], GateType type, const char* comment = nullptr);
60     GateRef NewGate(const GateMetaData *meta, MachineType machineType,
61                     const std::vector<GateRef>& inList, GateType type, const char* comment = nullptr);
62     void PrintAllGates() const;
63     void PrintAllGatesWithBytecode() const;
64     void GetAllGates(std::vector<GateRef>& gates) const;
65     static GateRef NullGate();
66     void Verify(GateRef gate, const std::string& methodName = "") const;
67     panda::ecmascript::FrameType GetFrameType() const;
68     void SetFrameType(panda::ecmascript::FrameType type);
69     GateRef GetConstantGate(MachineType machineType, uint64_t value, GateType type);
70     GateRef GetHeapConstantGate(uint32_t heapConstantIndex);
71     GateRef GetConstantGateWithoutCache(MachineType machineType, uint64_t value, GateType type);
72     void ClearConstantCache(MachineType machineType, uint64_t value, GateType type);
73     GateRef GetConstantStringGate(MachineType machineType, std::string_view str, GateType type);
74     GateRef NewArg(MachineType machineType, size_t index, GateType type, GateRef argRoot);
75     GateRef GetInitialEnvGate(GateRef depend, GateRef jsFunc);
76     size_t GetGateCount() const;
77     TimeStamp GetTime() const;
78     void AdvanceTime() const;
SetArch(bool isArch64)79     void SetArch(bool isArch64)
80     {
81         isArch64_ = isArch64;
82     }
IsArch64()83     bool IsArch64() const
84     {
85         return isArch64_;
86     }
87     void InitRoot();
GetRoot()88     GateRef GetRoot() const
89     {
90         return root_;
91     }
SetRoot(GateRef root)92     void SetRoot(GateRef root)
93     {
94         root_ = root;
95     }
96 
GetGlobalEnvCache()97     GateRef GetGlobalEnvCache() const
98     {
99         return globalEnv_;
100     }
SetGlobalEnvCache(GateRef globalEnv)101     void SetGlobalEnvCache(GateRef globalEnv)
102     {
103         globalEnv_ = globalEnv;
104     }
105 
chunk()106     Chunk* chunk()
107     {
108         return &chunk_;
109     }
110 
GetMetaBuilder()111     GateMetaBuilder *GetMetaBuilder()
112     {
113         return &metaBuilder_;
114     }
115 
116     GateRef GetStateRoot() const;
117     GateRef GetDependRoot() const;
118     GateRef GetArgRoot() const;
119     GateRef GetReturnRoot() const;
120     enum class ArgAccCond: uint8_t {
121         UNSTART, // argAcc_ not initialized
122         START, // argAcc_ initialized
123         CHANGED, // circuit changed after argAcc_ initialized
124     };
125     // Check circuit is not changed while using argAcc_
126     ArgAccCond checkArgAcc_ = ArgAccCond::UNSTART;
127 
128 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
129     const GateMetaData* NAME()                  \
130     {                                           \
131         return metaBuilder_.NAME();             \
132     }
133     IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_META)
134 #undef DECLARE_GATE_META
135 
136 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
137     const GateMetaData* NAME(size_t value)      \
138     {                                           \
139         return metaBuilder_.NAME(value);        \
140     }
GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)141     GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_META)
142 #undef DECLARE_GATE_META
143 
144 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
145     const GateMetaData* NAME(uint64_t value)    \
146     {                                           \
147         return metaBuilder_.NAME(value);        \
148     }
149     GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_META)
150 #undef DECLARE_GATE_META
151 
152 #define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
153     const GateMetaData* NAME(bool value)        \
154     {                                           \
155         return metaBuilder_.NAME(value);        \
156     }
157     GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_META)
158 #undef DECLARE_GATE_META
159 
160 #define DECLARE_GATE_META_WITH_BOOL_VALUE_IN(NAME, OP, R, S, D, V)          \
161     const GateMetaData* NAME(size_t value, bool flag)                       \
162     {                                                                       \
163         return metaBuilder_.NAME(value, flag);                              \
164     }
165     GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_GATE_META_WITH_BOOL_VALUE_IN)
166 #undef DECLARE_GATE_META_WITH_BOOL_VALUE_IN
167 
168 #define DECLARE_GATE_META(NAME, OP, R, S, D, V)                    \
169     const GateMetaData* NAME(uint64_t value, uint64_t pcOffset)    \
170     {                                                              \
171         return metaBuilder_.NAME(value, pcOffset);                 \
172     }
173     GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META)
174 #undef DECLARE_GATE_META
175 
176 #define DECLARE_GATE_META_FOR_CALL(NAME, OP, R, S, D, V)                        \
177     const GateMetaData* NAME(uint64_t value, uint64_t pcOffset, bool noGC)      \
178     {                                                                           \
179         return metaBuilder_.NAME(value, pcOffset, noGC);                        \
180     }
181     GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_META_FOR_CALL)
182 #undef DECLARE_GATE_META_FOR_CALL
183 
184 #define DECLARE_GATE_META_FOR_NEW(NAME, OP, R, S, D, V)                        \
185     const GateMetaData* NAME(uint64_t value, uint64_t pcOffset,                \
186                              bool needPushArgv, bool isFastCall)               \
187     {                                                                          \
188         return metaBuilder_.NAME(value, pcOffset, needPushArgv, isFastCall);   \
189     }
190     GATE_META_DATA_LIST_FOR_NEW(DECLARE_GATE_META_FOR_NEW)
191 #undef DECLARE_GATE_META_FOR_NEW
192 
193 #define DECLARE_GATE_META(NAME, OP, R, S, D, V)                    \
194     const GateMetaData* NAME(uint64_t pcOffset) const              \
195     {                                                              \
196         return metaBuilder_.NAME(pcOffset);                        \
197     }
198     GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META)
199 #undef DECLARE_GATE_META
200 
201     const GateMetaData* Nop()
202     {
203         return metaBuilder_.Nop();
204     }
205 
JSBytecode(size_t valuesIn,uint32_t methodId,EcmaOpcode opcode,uint32_t pcOffset,uint32_t bcIndex,bool writable,bool hasFrameState)206     const GateMetaData* JSBytecode(size_t valuesIn, uint32_t methodId, EcmaOpcode opcode,
207         uint32_t pcOffset, uint32_t bcIndex, bool writable, bool hasFrameState)
208     {
209         GateFlags writableFlags = writable ? GateFlags::NONE_FLAG : GateFlags::NO_WRITE;
210         GateFlags frameStateFlags = hasFrameState ? GateFlags::HAS_FRAME_STATE : GateFlags::NONE_FLAG;
211         GateFlags flags = static_cast<GateFlags>(writableFlags | frameStateFlags);
212         return metaBuilder_.JSBytecode(valuesIn, methodId, opcode, pcOffset, bcIndex, flags);
213     }
214 
DeadGate()215     GateRef DeadGate()
216     {
217         if (dead_ == NullGate()) {
218             dead_ = NewGate(Dead(), MachineType::NOVALUE, GateType::Empty());
219         }
220         return dead_;
221     }
222 
GetMaxGateId()223     size_t GetMaxGateId() const
224     {
225         ASSERT(gateCount_ != 0);
226         return static_cast<size_t>(gateCount_ - 1);
227     }
228 
IsOptimizedOrFastJit()229     bool IsOptimizedOrFastJit() const
230     {
231         return  IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame();
232     }
233 
IsOptimizedJSFunctionFrame()234     bool IsOptimizedJSFunctionFrame() const
235     {
236         return frameType_ == FrameType::OPTIMIZED_JS_FUNCTION_FRAME
237             || frameType_ == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
238     }
239 
IsFastJitFunctionFrame()240     bool IsFastJitFunctionFrame() const
241     {
242         return frameType_ == FrameType::FASTJIT_FUNCTION_FRAME
243             || frameType_ == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME;
244     }
245 
246     bool GetDebugInfo(GateRef g, size_t &index) const;
247 
IsOsr()248     bool IsOsr() const
249     {
250         return isOsr_;
251     }
252 
SetIsOsr()253     void SetIsOsr()
254     {
255         isOsr_ = true;
256     }
257 
258 #ifndef NDEBUG
259     class ScopedComment {
260     public:
261         explicit ScopedComment(std::string &&str, std::string_view *comment);
262 
~ScopedComment()263         ~ScopedComment()
264         {
265             *comment_ = old_;
266         }
267     private:
268         std::string_view old_;
269         std::string str_;
270         std::string_view *comment_;
271     };
272 
273     ScopedComment VisitGateBegin(GateRef visitedGate);
274     ScopedComment CommentBegin(std::string &&str);
275 #else
VisitGateBegin(GateRef visitedGate)276     size_t VisitGateBegin([[maybe_unused]] GateRef visitedGate)
277     {
278         return 0;
279     }
CommentBegin(GateRef visitedGate)280     size_t CommentBegin([[maybe_unused]] GateRef visitedGate)
281     {
282         return 0;
283     }
284 #endif
285 
286 private:
287     static const size_t CIRCUIT_SPACE = 1U << 30U;  // 1GB
288 public:
289     void Print(GateRef gate) const;
290     bool AddComment(GateRef g, std::string &&str);
291     std::string_view GetComment(GateRef gate) const;
292 
293 private:
294     GateType GetGateType(GateRef gate) const;
295     GateRef GetGateRef(const Gate *gate) const;
296     MachineType GetMachineType(GateRef gate) const;
297     void SetMark(GateRef gate, MarkCode mark) const;
298     OpCode GetOpCode(GateRef gate) const;
299     void SetMachineType(GateRef gate, MachineType machineType);
300     void SetGateType(GateRef gate, GateType type);
301     GateId GetId(GateRef gate) const;
302     void DeleteGate(GateRef gate);
303     void DecreaseIn(GateRef gate, size_t idx);
304 
305     MarkCode GetMark(GateRef gate) const;
306     void DeleteIn(GateRef gate, size_t idx);
307     void ModifyIn(GateRef gate, size_t idx, GateRef in);
308     void NewIn(GateRef gate, size_t idx, GateRef in);
309     std::vector<GateRef> GetOutVector(GateRef gate) const;
310     bool IsFirstOutNull(GateRef gate) const;
311     bool IsInGateNull(GateRef gate, size_t idx) const;
312     GateRef GetIn(GateRef gate, size_t idx) const;
313     bool IsValueSelector(GateRef gate) const;
314     bool IsSelector(GateRef gate) const;
315     bool IsControlCase(GateRef gate) const;
316     bool IsLoopHead(GateRef gate) const;
317     void ResetAllGateTimeStamps() const;
318     uint8_t *AllocateSpace(size_t gateSize);
319     Gate *AllocateGateSpace(size_t numIns);
320     size_t GetCircuitDataSize() const;
321     const void *GetSpaceDataStartPtrConst() const;
322     const void *GetSpaceDataEndPtrConst() const;
323     const uint8_t *GetDataPtrConst(size_t offset) const;
324     uint8_t *GetDataPtr(size_t offset);
325     Gate *LoadGatePtr(GateRef shift);
326     const Gate *LoadGatePtrConst(GateRef shift) const;
GetMetaData(GateRef gate)327     const GateMetaData *GetMetaData(GateRef gate) const
328     {
329         return LoadGatePtrConst(gate)->GetMetaData();
330     }
331 #ifndef NDEBUG
GetGateRefById(size_t id)332     GateRef GetGateRefById(size_t id) const
333     {
334         if (id > allGates_.size()) {
335             return NullGate();
336         }
337         return allGates_[id];
338     }
339 #endif
340 
341 private:
342     void* space_ {nullptr};
343     size_t circuitSize_ {0};
344     size_t gateCount_ {0};
345     TimeStamp time_;
346     std::map<std::tuple<MachineType, BitField, GateType>, GateRef> constantCache_ {};
347     std::unordered_map<std::uint32_t, GateRef> heapConstantCache_;
348     std::map<std::pair<BitField, GateRef>, GateRef> constantDataCache_ {};
349     std::map<GateRef, GateRef> initialEnvCache_ {};
350     panda::ecmascript::FrameType frameType_ {FrameType::OPTIMIZED_FRAME};
351     bool isArch64_ { false };
352     bool isOsr_ { false };
353 
354     Chunk chunk_;
355     GateRef root_ { NullGate() };
356     GateRef dead_ { NullGate() };
357     GateRef globalEnv_ {NullGate()};
358     GateRef replaceable_ {NullGate()};
359     GateMetaBuilder metaBuilder_;
360     ChunkMap<GateRef, size_t> gateToDInfo_;
361     DebugInfo* debugInfo_ {nullptr};
362     std::unique_ptr<ArgumentAccessor> argAcc_;
363 #ifndef NDEBUG
364     ChunkVector<GateRef> allGates_;
365     std::string_view currentComment_ {};
366 #endif
367 
368     friend class GateAccessor;
369     friend class ConstGateAccessor;
370     friend class Verifier;
371 };
372 }  // namespace panda::ecmascript::kungfu
373 
374 #endif  // ECMASCRIPT_COMPILER_CIRCUIT_H
375