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