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