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