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