OLD | NEW |
(Empty) | |
| 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); |
| 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_ |
OLD | NEW |