| OLD | NEW | 
|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #ifndef V8_COMPILER_ESCAPE_ANALYSIS_H_ | 5 #ifndef V8_COMPILER_ESCAPE_ANALYSIS_H_ | 
| 6 #define V8_COMPILER_ESCAPE_ANALYSIS_H_ | 6 #define V8_COMPILER_ESCAPE_ANALYSIS_H_ | 
| 7 | 7 | 
| 8 #include "src/base/flags.h" | 8 #include "src/base/flags.h" | 
| 9 #include "src/compiler/graph.h" | 9 #include "src/compiler/graph.h" | 
| 10 | 10 | 
| 11 namespace v8 { | 11 namespace v8 { | 
| 12 namespace internal { | 12 namespace internal { | 
| 13 namespace compiler { | 13 namespace compiler { | 
| 14 | 14 | 
| 15 // Forward declarations. | 15 // Forward declarations. | 
| 16 class CommonOperatorBuilder; | 16 class CommonOperatorBuilder; | 
| 17 class EscapeAnalysis; | 17 class EscapeAnalysis; | 
| 18 class VirtualState; | 18 class VirtualState; | 
| 19 class VirtualObject; | 19 class VirtualObject; | 
| 20 | 20 | 
| 21 | 21 | 
| 22 // EscapeStatusAnalysis determines for each allocation whether it escapes. | 22 // EscapeStatusAnalysis determines for each allocation whether it escapes. | 
| 23 class EscapeStatusAnalysis { | 23 class EscapeStatusAnalysis { | 
| 24  public: | 24  public: | 
|  | 25   typedef NodeId Alias; | 
| 25   ~EscapeStatusAnalysis(); | 26   ~EscapeStatusAnalysis(); | 
| 26 | 27 | 
| 27   enum EscapeStatusFlag { | 28   enum Status { | 
| 28     kUnknown = 0u, | 29     kUnknown = 0u, | 
| 29     kTracked = 1u << 0, | 30     kTracked = 1u << 0, | 
| 30     kEscaped = 1u << 1, | 31     kEscaped = 1u << 1, | 
| 31     kOnStack = 1u << 2, | 32     kOnStack = 1u << 2, | 
| 32     kVisited = 1u << 3, | 33     kVisited = 1u << 3, | 
|  | 34     // A node is dangling, if it is a load of some kind, and does not have | 
|  | 35     // an effect successor. | 
|  | 36     kDanglingComputed = 1u << 4, | 
|  | 37     kDangling = 1u << 5, | 
|  | 38     // A node is is an effect branch point, if it has more than 2 non-dangling | 
|  | 39     // effect successors. | 
|  | 40     kBranchPointComputed = 1u << 6, | 
|  | 41     kBranchPoint = 1u << 7, | 
| 33   }; | 42   }; | 
| 34   typedef base::Flags<EscapeStatusFlag, unsigned char> EscapeStatusFlags; | 43   typedef base::Flags<Status, unsigned char> StatusFlags; | 
| 35 | 44 | 
| 36   void Run(); | 45   void RunStatusAnalysis(); | 
| 37 | 46 | 
| 38   bool IsVirtual(Node* node); | 47   bool IsVirtual(Node* node); | 
| 39   bool IsEscaped(Node* node); | 48   bool IsEscaped(Node* node); | 
| 40   bool IsAllocation(Node* node); | 49   bool IsAllocation(Node* node); | 
| 41 |  | 
| 42   void DebugPrint(); | 50   void DebugPrint(); | 
| 43 | 51 | 
| 44   friend class EscapeAnalysis; | 52   EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph, | 
|  | 53                        Zone* zone); | 
|  | 54   void EnqueueForStatusAnalysis(Node* node); | 
|  | 55   bool SetEscaped(Node* node); | 
|  | 56   bool IsEffectBranchPoint(Node* node); | 
|  | 57   bool IsDanglingEffectNode(Node* node); | 
|  | 58   void ResizeStatusVector(); | 
|  | 59   size_t GetStatusVectorSize(); | 
|  | 60   bool IsVirtual(NodeId id); | 
|  | 61 | 
|  | 62   Graph* graph() const { return graph_; } | 
|  | 63   Zone* zone() const { return zone_; } | 
|  | 64   void AssignAliases(); | 
|  | 65   Alias GetAlias(NodeId id) const { return aliases_[id]; } | 
|  | 66   const ZoneVector<Alias>& GetAliasMap() const { return aliases_; } | 
|  | 67   Alias AliasCount() const { return next_free_alias_; } | 
|  | 68   static const Alias kNotReachable; | 
|  | 69   static const Alias kUntrackable; | 
|  | 70 | 
|  | 71   bool IsNotReachable(Node* node); | 
|  | 72   ZoneVector<Node*>& stack() { return stack_; } | 
| 45 | 73 | 
| 46  private: | 74  private: | 
| 47   EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph, |  | 
| 48                        Zone* zone); |  | 
| 49   void Process(Node* node); | 75   void Process(Node* node); | 
| 50   void ProcessAllocate(Node* node); | 76   void ProcessAllocate(Node* node); | 
| 51   void ProcessFinishRegion(Node* node); | 77   void ProcessFinishRegion(Node* node); | 
| 52   void ProcessStoreField(Node* node); | 78   void ProcessStoreField(Node* node); | 
| 53   void ProcessStoreElement(Node* node); | 79   void ProcessStoreElement(Node* node); | 
| 54   bool CheckUsesForEscape(Node* node, bool phi_escaping = false) { | 80   bool CheckUsesForEscape(Node* node, bool phi_escaping = false) { | 
| 55     return CheckUsesForEscape(node, node, phi_escaping); | 81     return CheckUsesForEscape(node, node, phi_escaping); | 
| 56   } | 82   } | 
| 57   bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false); | 83   bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false); | 
| 58   void RevisitUses(Node* node); | 84   void RevisitUses(Node* node); | 
| 59   void RevisitInputs(Node* node); | 85   void RevisitInputs(Node* node); | 
| 60   bool SetEscaped(Node* node); | 86 | 
| 61   bool IsVirtual(NodeId id); | 87   Alias NextAlias() { return next_free_alias_++; } | 
|  | 88 | 
| 62   bool HasEntry(Node* node); | 89   bool HasEntry(Node* node); | 
| 63   void Resize(); | 90 | 
| 64   size_t size(); |  | 
| 65   bool IsAllocationPhi(Node* node); | 91   bool IsAllocationPhi(Node* node); | 
| 66 | 92 | 
| 67   Graph* graph() const { return graph_; } | 93   ZoneVector<Node*> stack_; | 
| 68   Zone* zone() const { return zone_; } |  | 
| 69 |  | 
| 70   EscapeAnalysis* object_analysis_; | 94   EscapeAnalysis* object_analysis_; | 
| 71   Graph* const graph_; | 95   Graph* const graph_; | 
| 72   Zone* const zone_; | 96   Zone* const zone_; | 
| 73   ZoneVector<EscapeStatusFlags> status_; | 97   ZoneVector<StatusFlags> status_; | 
| 74   ZoneDeque<Node*> queue_; | 98   Alias next_free_alias_; | 
|  | 99   ZoneVector<Node*> status_stack_; | 
|  | 100   ZoneVector<Alias> aliases_; | 
| 75 | 101 | 
| 76   DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis); | 102   DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis); | 
| 77 }; | 103 }; | 
| 78 | 104 | 
| 79 | 105 | 
| 80 DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::EscapeStatusFlags) | 106 DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::StatusFlags) | 
| 81 | 107 | 
| 82 | 108 | 
| 83 // Forward Declaration. | 109 // Forward Declaration. | 
| 84 class MergeCache; | 110 class MergeCache; | 
| 85 | 111 | 
| 86 | 112 | 
| 87 // EscapeObjectAnalysis simulates stores to determine values of loads if | 113 // EscapeObjectAnalysis simulates stores to determine values of loads if | 
| 88 // an object is virtual and eliminated. | 114 // an object is virtual and eliminated. | 
| 89 class EscapeAnalysis { | 115 class EscapeAnalysis { | 
| 90  public: | 116  public: | 
| 91   typedef NodeId Alias; | 117   using Alias = EscapeStatusAnalysis::Alias; | 
| 92 |  | 
| 93   EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone); | 118   EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone); | 
| 94   ~EscapeAnalysis(); | 119   ~EscapeAnalysis(); | 
| 95 | 120 | 
| 96   void Run(); | 121   void Run(); | 
| 97 | 122 | 
| 98   Node* GetReplacement(Node* node); | 123   Node* GetReplacement(Node* node); | 
| 99   bool IsVirtual(Node* node); | 124   bool IsVirtual(Node* node); | 
| 100   bool IsEscaped(Node* node); | 125   bool IsEscaped(Node* node); | 
| 101   bool CompareVirtualObjects(Node* left, Node* right); | 126   bool CompareVirtualObjects(Node* left, Node* right); | 
| 102   Node* GetOrCreateObjectState(Node* effect, Node* node); | 127   Node* GetOrCreateObjectState(Node* effect, Node* node); | 
| 103   bool ExistsVirtualAllocate(); | 128   bool ExistsVirtualAllocate(); | 
| 104 | 129 | 
| 105  private: | 130  private: | 
| 106   void RunObjectAnalysis(); | 131   void RunObjectAnalysis(); | 
| 107   void AssignAliases(); |  | 
| 108   bool Process(Node* node); | 132   bool Process(Node* node); | 
| 109   void ProcessLoadField(Node* node); | 133   void ProcessLoadField(Node* node); | 
| 110   void ProcessStoreField(Node* node); | 134   void ProcessStoreField(Node* node); | 
| 111   void ProcessLoadElement(Node* node); | 135   void ProcessLoadElement(Node* node); | 
| 112   void ProcessStoreElement(Node* node); | 136   void ProcessStoreElement(Node* node); | 
| 113   void ProcessAllocationUsers(Node* node); | 137   void ProcessAllocationUsers(Node* node); | 
| 114   void ProcessAllocation(Node* node); | 138   void ProcessAllocation(Node* node); | 
| 115   void ProcessFinishRegion(Node* node); | 139   void ProcessFinishRegion(Node* node); | 
| 116   void ProcessCall(Node* node); | 140   void ProcessCall(Node* node); | 
| 117   void ProcessStart(Node* node); | 141   void ProcessStart(Node* node); | 
| 118   bool ProcessEffectPhi(Node* node); | 142   bool ProcessEffectPhi(Node* node); | 
| 119   void ProcessLoadFromPhi(int offset, Node* from, Node* node, | 143   void ProcessLoadFromPhi(int offset, Node* from, Node* node, | 
| 120                           VirtualState* states); | 144                           VirtualState* states); | 
| 121 | 145 | 
| 122   void ForwardVirtualState(Node* node); | 146   void ForwardVirtualState(Node* node); | 
| 123   bool IsEffectBranchPoint(Node* node); |  | 
| 124   bool IsDanglingEffectNode(Node* node); |  | 
| 125   int OffsetFromAccess(Node* node); | 147   int OffsetFromAccess(Node* node); | 
| 126 | 148   VirtualState* CopyForModificationAt(VirtualState* state, Node* node); | 
|  | 149   VirtualObject* CopyForModificationAt(VirtualObject* obj, VirtualState* state, | 
|  | 150                                        Node* node); | 
| 127   VirtualObject* GetVirtualObject(Node* at, NodeId id); | 151   VirtualObject* GetVirtualObject(Node* at, NodeId id); | 
| 128   VirtualObject* ResolveVirtualObject(VirtualState* state, Node* node); | 152   VirtualObject* ResolveVirtualObject(VirtualState* state, Node* node); | 
| 129   Node* GetReplacementIfSame(ZoneVector<VirtualObject*>& objs); | 153   Node* GetReplacementIfSame(ZoneVector<VirtualObject*>& objs); | 
| 130 | 154 | 
| 131   bool SetEscaped(Node* node); | 155   bool SetEscaped(Node* node); | 
| 132   Node* replacement(NodeId id); | 156   Node* replacement(NodeId id); | 
| 133   Node* replacement(Node* node); | 157   Node* replacement(Node* node); | 
| 134   Node* ResolveReplacement(Node* node); | 158   Node* ResolveReplacement(Node* node); | 
| 135   Node* GetReplacement(NodeId id); | 159   Node* GetReplacement(NodeId id); | 
| 136   bool SetReplacement(Node* node, Node* rep); | 160   bool SetReplacement(Node* node, Node* rep); | 
| 137   bool UpdateReplacement(VirtualState* state, Node* node, Node* rep); | 161   bool UpdateReplacement(VirtualState* state, Node* node, Node* rep); | 
| 138 | 162 | 
| 139   VirtualObject* GetVirtualObject(VirtualState* state, Node* node); | 163   VirtualObject* GetVirtualObject(VirtualState* state, Node* node); | 
| 140 | 164 | 
| 141   void DebugPrint(); | 165   void DebugPrint(); | 
| 142   void DebugPrintState(VirtualState* state); | 166   void DebugPrintState(VirtualState* state); | 
| 143   void DebugPrintObject(VirtualObject* state, Alias id); | 167   void DebugPrintObject(VirtualObject* state, Alias id); | 
| 144 | 168 | 
| 145   Alias NextAlias() { return next_free_alias_++; } | 169   Graph* graph() const { return status_analysis_.graph(); } | 
| 146   Alias AliasCount() const { return next_free_alias_; } | 170   Zone* zone() const { return status_analysis_.zone(); } | 
|  | 171   CommonOperatorBuilder* common() const { return common_; } | 
|  | 172   ZoneVector<Node*>& stack() { return status_analysis_.stack(); } | 
|  | 173   bool IsEffectBranchPoint(Node* node) { | 
|  | 174     return status_analysis_.IsEffectBranchPoint(node); | 
|  | 175   } | 
|  | 176   bool IsDanglingEffectNode(Node* node) { | 
|  | 177     return status_analysis_.IsDanglingEffectNode(node); | 
|  | 178   } | 
|  | 179   bool IsNotReachable(Node* node) { | 
|  | 180     return status_analysis_.IsNotReachable(node); | 
|  | 181   } | 
|  | 182   Alias GetAlias(NodeId id) const { return status_analysis_.GetAlias(id); } | 
|  | 183   Alias AliasCount() const { return status_analysis_.AliasCount(); } | 
| 147 | 184 | 
| 148   Graph* graph() const { return graph_; } | 185   EscapeStatusAnalysis status_analysis_; | 
| 149   CommonOperatorBuilder* common() const { return common_; } |  | 
| 150   Zone* zone() const { return zone_; } |  | 
| 151 |  | 
| 152   static const Alias kNotReachable; |  | 
| 153   static const Alias kUntrackable; |  | 
| 154   Graph* const graph_; |  | 
| 155   CommonOperatorBuilder* const common_; | 186   CommonOperatorBuilder* const common_; | 
| 156   Zone* const zone_; |  | 
| 157   ZoneVector<VirtualState*> virtual_states_; | 187   ZoneVector<VirtualState*> virtual_states_; | 
| 158   ZoneVector<Node*> replacements_; | 188   ZoneVector<Node*> replacements_; | 
| 159   EscapeStatusAnalysis escape_status_; |  | 
| 160   MergeCache* cache_; | 189   MergeCache* cache_; | 
| 161   ZoneVector<Alias> aliases_; |  | 
| 162   Alias next_free_alias_; |  | 
| 163 | 190 | 
| 164   DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); | 191   DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); | 
| 165 }; | 192 }; | 
| 166 | 193 | 
| 167 }  // namespace compiler | 194 }  // namespace compiler | 
| 168 }  // namespace internal | 195 }  // namespace internal | 
| 169 }  // namespace v8 | 196 }  // namespace v8 | 
| 170 | 197 | 
| 171 #endif  // V8_COMPILER_ESCAPE_ANALYSIS_H_ | 198 #endif  // V8_COMPILER_ESCAPE_ANALYSIS_H_ | 
| OLD | NEW | 
|---|