1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_
6 #define V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_
7 
8 #include "src/base/compiler-specific.h"
9 #include "src/common/globals.h"
10 #include "src/compiler/access-builder.h"
11 #include "src/compiler/escape-analysis.h"
12 #include "src/compiler/graph-reducer.h"
13 
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17 
18 class Deduplicator;
19 class JSGraph;
20 
21 // Perform hash-consing when creating or mutating nodes. Used to avoid duplicate
22 // nodes when creating ObjectState, StateValues and FrameState nodes
23 class NodeHashCache {
24  public:
NodeHashCache(Graph * graph,Zone * zone)25   NodeHashCache(Graph* graph, Zone* zone)
26       : graph_(graph), cache_(zone), temp_nodes_(zone) {}
27 
28   // Handle to a conceptually new mutable node. Tries to re-use existing nodes
29   // and to recycle memory if possible.
30   class Constructor {
31    public:
32     // Construct a new node as a clone of [from].
Constructor(NodeHashCache * cache,Node * from)33     Constructor(NodeHashCache* cache, Node* from)
34         : node_cache_(cache), from_(from), tmp_(nullptr) {}
35     // Construct a new node from scratch.
36     Constructor(NodeHashCache* cache, const Operator* op, int input_count,
37                 Node** inputs, Type type);
38 
39     // Modify the new node.
ReplaceValueInput(Node * input,int i)40     void ReplaceValueInput(Node* input, int i) {
41       if (!tmp_ && input == NodeProperties::GetValueInput(from_, i)) return;
42       Node* node = MutableNode();
43       NodeProperties::ReplaceValueInput(node, input, i);
44     }
ReplaceInput(Node * input,int i)45     void ReplaceInput(Node* input, int i) {
46       if (!tmp_ && input == from_->InputAt(i)) return;
47       Node* node = MutableNode();
48       node->ReplaceInput(i, input);
49     }
50 
51     // Obtain the mutated node or a cached copy. Invalidates the [Constructor].
52     Node* Get();
53 
54    private:
55     Node* MutableNode();
56 
57     NodeHashCache* node_cache_;
58     // Original node, copied on write.
59     Node* from_;
60     // Temporary node used for mutations, can be recycled if cache is hit.
61     Node* tmp_;
62   };
63 
64  private:
65   Node* Query(Node* node);
Insert(Node * node)66   void Insert(Node* node) { cache_.insert(node); }
67 
68   Graph* graph_;
69   struct NodeEquals {
operatorNodeEquals70     bool operator()(Node* a, Node* b) const {
71       return NodeProperties::Equals(a, b);
72     }
73   };
74   struct NodeHashCode {
operatorNodeHashCode75     size_t operator()(Node* n) const { return NodeProperties::HashCode(n); }
76   };
77   ZoneUnorderedSet<Node*, NodeHashCode, NodeEquals> cache_;
78   // Unused nodes whose memory can be recycled.
79   ZoneVector<Node*> temp_nodes_;
80 };
81 
82 // Modify the graph according to the information computed in the previous phase.
83 class V8_EXPORT_PRIVATE EscapeAnalysisReducer final
NON_EXPORTED_BASE(AdvancedReducer)84     : public NON_EXPORTED_BASE(AdvancedReducer) {
85  public:
86   EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph,
87                         EscapeAnalysisResult analysis_result, Zone* zone);
88   EscapeAnalysisReducer(const EscapeAnalysisReducer&) = delete;
89   EscapeAnalysisReducer& operator=(const EscapeAnalysisReducer&) = delete;
90 
91   Reduction Reduce(Node* node) override;
92   const char* reducer_name() const override { return "EscapeAnalysisReducer"; }
93   void Finalize() override;
94 
95   // Verifies that all virtual allocation nodes have been dealt with. Run it
96   // after this reducer has been applied.
97   void VerifyReplacement() const;
98 
99  private:
100   void ReduceFrameStateInputs(Node* node);
101   Node* ReduceDeoptState(Node* node, Node* effect, Deduplicator* deduplicator);
102   Node* ObjectIdNode(const VirtualObject* vobject);
103   Reduction ReplaceNode(Node* original, Node* replacement);
104 
105   JSGraph* jsgraph() const { return jsgraph_; }
106   Isolate* isolate() const { return jsgraph_->isolate(); }
107   EscapeAnalysisResult analysis_result() const { return analysis_result_; }
108   Zone* zone() const { return zone_; }
109 
110   JSGraph* const jsgraph_;
111   EscapeAnalysisResult analysis_result_;
112   ZoneVector<Node*> object_id_cache_;
113   NodeHashCache node_cache_;
114   ZoneSet<Node*> arguments_elements_;
115   Zone* const zone_;
116 };
117 
118 }  // namespace compiler
119 }  // namespace internal
120 }  // namespace v8
121 
122 #endif  // V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_
123