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 : using NodeId = uint32_t;
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 1062868 : ~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, AllocationType allocation, Zone* zone);
49 : AllocationGroup(Node* node, AllocationType allocation, Node* size,
50 : Zone* zone);
51 : ~AllocationGroup() = default;
52 :
53 : void Add(Node* object);
54 : bool Contains(Node* object) const;
55 : bool IsYoungGenerationAllocation() const {
56 : return allocation() == AllocationType::kYoung;
57 : }
58 :
59 : AllocationType allocation() const { return allocation_; }
60 : Node* size() const { return size_; }
61 :
62 : private:
63 : ZoneSet<NodeId> node_ids_;
64 : AllocationType const allocation_;
65 : Node* const size_;
66 :
67 : DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationGroup);
68 : };
69 :
70 : // An allocation state is propagated on the effect paths through the graph.
71 : class AllocationState final : public ZoneObject {
72 : public:
73 : static AllocationState const* Empty(Zone* zone) {
74 : return new (zone) AllocationState();
75 : }
76 : static AllocationState const* Closed(AllocationGroup* group, Zone* zone) {
77 : return new (zone) AllocationState(group);
78 : }
79 : static AllocationState const* Open(AllocationGroup* group, intptr_t size,
80 : Node* top, Zone* zone) {
81 : return new (zone) AllocationState(group, size, top);
82 : }
83 :
84 : bool IsYoungGenerationAllocation() const;
85 :
86 : AllocationGroup* group() const { return group_; }
87 : Node* top() const { return top_; }
88 : intptr_t size() const { return size_; }
89 :
90 : private:
91 : AllocationState();
92 : explicit AllocationState(AllocationGroup* group);
93 : AllocationState(AllocationGroup* group, intptr_t size, Node* top);
94 :
95 : AllocationGroup* const group_;
96 : // The upper bound of the combined allocated object size on the current path
97 : // (max int if allocation folding is impossible on this path).
98 : intptr_t const size_;
99 : Node* const top_;
100 :
101 : DISALLOW_COPY_AND_ASSIGN(AllocationState);
102 : };
103 :
104 : // An array of allocation states used to collect states on merges.
105 : using AllocationStates = ZoneVector<AllocationState const*>;
106 :
107 : // We thread through tokens to represent the current state on a given effect
108 : // path through the graph.
109 : struct Token {
110 : Node* node;
111 : AllocationState const* state;
112 : };
113 :
114 : void VisitNode(Node*, AllocationState const*);
115 : void VisitAllocateRaw(Node*, AllocationState const*);
116 : void VisitCall(Node*, AllocationState const*);
117 : void VisitCallWithCallerSavedRegisters(Node*, AllocationState const*);
118 : void VisitLoadElement(Node*, AllocationState const*);
119 : void VisitLoadField(Node*, AllocationState const*);
120 : void VisitStoreElement(Node*, AllocationState const*);
121 : void VisitStoreField(Node*, AllocationState const*);
122 : void VisitStore(Node*, AllocationState const*);
123 : void VisitOtherEffect(Node*, AllocationState const*);
124 :
125 : Node* ComputeIndex(ElementAccess const&, Node*);
126 : WriteBarrierKind ComputeWriteBarrierKind(Node* object,
127 : AllocationState const* state,
128 : WriteBarrierKind);
129 :
130 : AllocationState const* MergeStates(AllocationStates const& states);
131 :
132 : void EnqueueMerge(Node*, int, AllocationState const*);
133 : void EnqueueUses(Node*, AllocationState const*);
134 : void EnqueueUse(Node*, int, AllocationState const*);
135 :
136 : bool NeedsPoisoning(LoadSensitivity load_sensitivity) const;
137 :
138 : AllocationState const* empty_state() const { return empty_state_; }
139 : Graph* graph() const;
140 : Isolate* isolate() const;
141 : JSGraph* jsgraph() const { return jsgraph_; }
142 : CommonOperatorBuilder* common() const;
143 : MachineOperatorBuilder* machine() const;
144 : Zone* zone() const { return zone_; }
145 235504 : GraphAssembler* gasm() { return &graph_assembler_; }
146 :
147 : SetOncePointer<const Operator> allocate_operator_;
148 : JSGraph* const jsgraph_;
149 : AllocationState const* const empty_state_;
150 : ZoneMap<NodeId, AllocationStates> pending_;
151 : ZoneQueue<Token> tokens_;
152 : Zone* const zone_;
153 : GraphAssembler graph_assembler_;
154 : PoisoningMitigationLevel poisoning_level_;
155 : AllocationFolding allocation_folding_;
156 :
157 : DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryOptimizer);
158 : };
159 :
160 : } // namespace compiler
161 : } // namespace internal
162 : } // namespace v8
163 :
164 : #endif // V8_COMPILER_MEMORY_OPTIMIZER_H_
|