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