blob: f0cd546860237ea24d52721a2c3bc567e9d397c7 [file] [log] [blame]
Ben Murdochc5610432016-08-08 18:44:38 +01001// 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
10namespace v8 {
11namespace internal {
12namespace compiler {
13
14// Forward declarations.
15class CommonOperatorBuilder;
16struct ElementAccess;
17class Graph;
18class JSGraph;
19class MachineOperatorBuilder;
20class Node;
21class 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.
25typedef 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.
31class MemoryOptimizer final {
32 public:
33 MemoryOptimizer(JSGraph* jsgraph, Zone* zone);
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);
46 ~AllocationGroup() {}
47
48 void Add(Node* object);
49 bool Contains(Node* object) const;
50 bool IsNewSpaceAllocation() const { return pretenure() == NOT_TENURED; }
51
52 PretenureFlag pretenure() const { return pretenure_; }
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:
66 static AllocationState const* Empty(Zone* zone) {
67 return new (zone) AllocationState();
68 }
69 static AllocationState const* Closed(AllocationGroup* group, Zone* zone) {
70 return new (zone) AllocationState(group);
71 }
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
79 AllocationGroup* group() const { return group_; }
80 Node* top() const { return top_; }
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
127 AllocationState const* empty_state() const { return empty_state_; }
128 Graph* graph() const;
129 Isolate* isolate() const;
130 JSGraph* jsgraph() const { return jsgraph_; }
131 CommonOperatorBuilder* common() const;
132 MachineOperatorBuilder* machine() const;
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_