1 /* 2 * Copyright (c) 2024 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_ESCAPE_ANALYSIS_H 17 #define ECMASCRIPT_COMPILER_ESCAPE_ANALYSIS_H 18 19 #include "ecmascript/compiler/combined_pass_visitor.h" 20 #include "ecmascript/compiler/gate_accessor.h" 21 #include "ecmascript/mem/chunk_containers.h" 22 23 namespace panda::ecmascript::kungfu { 24 25 class EscapeAnalysis; 26 class FieldLocation; 27 28 class VirtualObject { 29 public: 30 VirtualObject(size_t numIn, Chunk* chunk); 31 void SetEscaped(); 32 bool IsEscaped() const; 33 ChunkVector<GateRef>& GetUsers(); 34 void ClearUsers(); 35 void AddUser(GateRef gate); 36 FieldLocation GetField(size_t offset); 37 private: 38 ChunkVector<FieldLocation> fields_; 39 // Gates which use this virtual object 40 ChunkVector<GateRef> users_; 41 bool escaped_ {false}; 42 }; 43 44 class FieldLocation { 45 public: FieldLocation()46 FieldLocation() : id_(maxid++) {} FieldLocation(size_t id)47 FieldLocation(size_t id) : id_(id) {} operator ==(const FieldLocation &v) const48 bool operator == (const FieldLocation &v) const 49 { 50 return id_ == v.id_; 51 } operator !=(const FieldLocation &v) const52 bool operator != (const FieldLocation &v) const 53 { 54 return id_ != v.id_; 55 } operator <(const FieldLocation &v) const56 bool operator < (const FieldLocation &v) const 57 { 58 return id_ < v.id_; 59 } 60 static constexpr size_t invalid = -1; Invalid()61 static FieldLocation Invalid() 62 { 63 return FieldLocation(invalid); 64 } 65 private: 66 static size_t maxid; 67 size_t id_; 68 }; 69 70 class State { 71 public: State(Chunk* chunk)72 explicit State(Chunk* chunk) : map_(chunk) {} 73 void SetFieldValue(FieldLocation field, GateRef gate); 74 GateRef GetFieldValue(FieldLocation field) const; 75 bool IsMapEqual(const State &state) const; begin() const76 auto begin() const { return map_.begin(); } end() const77 auto end() const { return map_.end(); } 78 private: 79 ChunkMap<FieldLocation, GateRef> map_; 80 }; 81 82 // When we visit a gate, we first create a GateInfo which maintains results and all information 83 // that may be used in this visit. After finishing this visit, virtual object and replacement 84 // of this gate must be reset. 85 class GateInfo { 86 public: 87 GateInfo(Circuit* circuit, GateRef curGate, EscapeAnalysis* escapeAnalysis, Chunk* chunk); 88 ~GateInfo(); 89 GateRef GetCurrentGate() const; 90 GateRef GetFieldValue(FieldLocation field) const; 91 void SetFieldValue(FieldLocation field, GateRef value); 92 void SetEliminated(); 93 void SetVirtualObject(VirtualObject* object); 94 State MergeState(GateRef gate); 95 void SetReplacement(GateRef replacement); 96 private: 97 Circuit* circuit_; 98 GateAccessor acc_; 99 GateRef curGate_; 100 EscapeAnalysis* escapeAnalysis_; 101 State state_; 102 VirtualObject* object_ {nullptr}; 103 GateRef replacement_ {Circuit::NullGate()}; 104 }; 105 106 class EscapeAnalysis : public PassVisitor { 107 public: EscapeAnalysis(Circuit* circuit, RPOVisitor* visitor, Chunk* chunk, bool isTraced)108 EscapeAnalysis(Circuit* circuit, RPOVisitor* visitor, Chunk* chunk, bool isTraced) 109 : PassVisitor(circuit, chunk, visitor), circuit_(circuit), replacements_(chunk), gateToVirtualObject_(chunk), 110 gateToState_(chunk), chunk_(chunk), isTraced_(isTraced) {} 111 112 GateRef VisitGate(GateRef gate) override; 113 void SetEscaped(GateRef gate); 114 GateRef GetCurrentGate(GateRef gate) const; 115 void RevisitUser(VirtualObject* vObj); 116 GateRef TryGetReplacement(GateRef gate) const; 117 void SetReplacement(GateRef gate, GateRef replacement); 118 VirtualObject* TryGetVirtualObject(GateRef gate) const; 119 VirtualObject* TryGetVirtualObjectAndAddUser(GateRef gate, GateRef currentGate); 120 void SetVirtualObject(GateRef gate, VirtualObject* object); 121 VirtualObject* GetOrCreateVirtualObject(size_t numIn, GateInfo* info); 122 State& GetOrCreateState(GateRef gate); 123 void SetState(GateRef gate, State state); 124 void RevisitGate(GateRef gate); 125 void SetReplaceGate(GateRef gate); 126 private: 127 GateRef VisitCreateObjectWithBuffer(GateRef gate, GateInfo* info); 128 GateRef VisitLoadProperty(GateRef gate, GateInfo* info); 129 GateRef VisitLoadConstOffset(GateRef gate, GateInfo* info); 130 GateRef VisitStoreProperty(GateRef gate, GateInfo* info); 131 GateRef VisitObjectTypeCheck(GateRef gate, GateInfo* info); 132 133 Circuit *circuit_ {nullptr}; 134 ChunkMap<GateRef, GateRef> replacements_; 135 ChunkMap<GateRef, VirtualObject*> gateToVirtualObject_; 136 ChunkMap<GateRef, State> gateToState_; 137 GateRef replaceGate_ {Circuit::NullGate()}; 138 Chunk* chunk_; 139 bool isTraced_; 140 }; 141 142 }; 143 144 #endif