• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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_MEMORY_OPTIMIZER_H_
6 #define V8_COMPILER_MEMORY_OPTIMIZER_H_
7 
8 #include "src/zone-containers.h"
9 
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13 
14 // Forward declarations.
15 class CommonOperatorBuilder;
16 struct ElementAccess;
17 class Graph;
18 class JSGraph;
19 class MachineOperatorBuilder;
20 class Node;
21 class Operator;
22 
23 // NodeIds are identifying numbers for nodes that can be used to index auxiliary
24 // out-of-line data associated with each node.
25 typedef uint32_t NodeId;
26 
27 // Lowers all simplified memory access and allocation related nodes (i.e.
28 // Allocate, LoadField, StoreField and friends) to machine operators.
29 // Performs allocation folding and store write barrier elimination
30 // implicitly.
31 class MemoryOptimizer final {
32  public:
33   MemoryOptimizer(JSGraph* jsgraph, Zone* zone);
~MemoryOptimizer()34   ~MemoryOptimizer() {}
35 
36   void Optimize();
37 
38  private:
39   // An allocation group represents a set of allocations that have been folded
40   // together.
41   class AllocationGroup final : public ZoneObject {
42    public:
43     AllocationGroup(Node* node, PretenureFlag pretenure, Zone* zone);
44     AllocationGroup(Node* node, PretenureFlag pretenure, Node* size,
45                     Zone* zone);
~AllocationGroup()46     ~AllocationGroup() {}
47 
48     void Add(Node* object);
49     bool Contains(Node* object) const;
IsNewSpaceAllocation()50     bool IsNewSpaceAllocation() const { return pretenure() == NOT_TENURED; }
51 
pretenure()52     PretenureFlag pretenure() const { return pretenure_; }
size()53     Node* size() const { return size_; }
54 
55    private:
56     ZoneSet<NodeId> node_ids_;
57     PretenureFlag const pretenure_;
58     Node* const size_;
59 
60     DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationGroup);
61   };
62 
63   // An allocation state is propagated on the effect paths through the graph.
64   class AllocationState final : public ZoneObject {
65    public:
Empty(Zone * zone)66     static AllocationState const* Empty(Zone* zone) {
67       return new (zone) AllocationState();
68     }
Closed(AllocationGroup * group,Zone * zone)69     static AllocationState const* Closed(AllocationGroup* group, Zone* zone) {
70       return new (zone) AllocationState(group);
71     }
Open(AllocationGroup * group,int size,Node * top,Zone * zone)72     static AllocationState const* Open(AllocationGroup* group, int size,
73                                        Node* top, Zone* zone) {
74       return new (zone) AllocationState(group, size, top);
75     }
76 
77     bool IsNewSpaceAllocation() const;
78 
group()79     AllocationGroup* group() const { return group_; }
top()80     Node* top() const { return top_; }
size()81     int size() const { return size_; }
82 
83    private:
84     AllocationState();
85     explicit AllocationState(AllocationGroup* group);
86     AllocationState(AllocationGroup* group, int size, Node* top);
87 
88     AllocationGroup* const group_;
89     // The upper bound of the combined allocated object size on the current path
90     // (max int if allocation folding is impossible on this path).
91     int const size_;
92     Node* const top_;
93 
94     DISALLOW_COPY_AND_ASSIGN(AllocationState);
95   };
96 
97   // An array of allocation states used to collect states on merges.
98   typedef ZoneVector<AllocationState const*> AllocationStates;
99 
100   // We thread through tokens to represent the current state on a given effect
101   // path through the graph.
102   struct Token {
103     Node* node;
104     AllocationState const* state;
105   };
106 
107   void VisitNode(Node*, AllocationState const*);
108   void VisitAllocate(Node*, AllocationState const*);
109   void VisitCall(Node*, AllocationState const*);
110   void VisitLoadElement(Node*, AllocationState const*);
111   void VisitLoadField(Node*, AllocationState const*);
112   void VisitStoreElement(Node*, AllocationState const*);
113   void VisitStoreField(Node*, AllocationState const*);
114   void VisitOtherEffect(Node*, AllocationState const*);
115 
116   Node* ComputeIndex(ElementAccess const&, Node*);
117   WriteBarrierKind ComputeWriteBarrierKind(Node* object,
118                                            AllocationState const* state,
119                                            WriteBarrierKind);
120 
121   AllocationState const* MergeStates(AllocationStates const& states);
122 
123   void EnqueueMerge(Node*, int, AllocationState const*);
124   void EnqueueUses(Node*, AllocationState const*);
125   void EnqueueUse(Node*, int, AllocationState const*);
126 
empty_state()127   AllocationState const* empty_state() const { return empty_state_; }
128   Graph* graph() const;
129   Isolate* isolate() const;
jsgraph()130   JSGraph* jsgraph() const { return jsgraph_; }
131   CommonOperatorBuilder* common() const;
132   MachineOperatorBuilder* machine() const;
zone()133   Zone* zone() const { return zone_; }
134 
135   SetOncePointer<const Operator> allocate_operator_;
136   JSGraph* const jsgraph_;
137   AllocationState const* const empty_state_;
138   ZoneMap<NodeId, AllocationStates> pending_;
139   ZoneQueue<Token> tokens_;
140   Zone* const zone_;
141 
142   DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryOptimizer);
143 };
144 
145 }  // namespace compiler
146 }  // namespace internal
147 }  // namespace v8
148 
149 #endif  // V8_COMPILER_MEMORY_OPTIMIZER_H_
150