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