Index: src/compiler/memory-optimizer.h |
diff --git a/src/compiler/memory-optimizer.h b/src/compiler/memory-optimizer.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f0cd546860237ea24d52721a2c3bc567e9d397c7 |
--- /dev/null |
+++ b/src/compiler/memory-optimizer.h |
@@ -0,0 +1,149 @@ |
+// Copyright 2016 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef V8_COMPILER_MEMORY_OPTIMIZER_H_ |
+#define V8_COMPILER_MEMORY_OPTIMIZER_H_ |
+ |
+#include "src/zone-containers.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace compiler { |
+ |
+// Forward declarations. |
+class CommonOperatorBuilder; |
+struct ElementAccess; |
+class Graph; |
+class JSGraph; |
+class MachineOperatorBuilder; |
+class Node; |
+class Operator; |
+ |
+// NodeIds are identifying numbers for nodes that can be used to index auxiliary |
+// out-of-line data associated with each node. |
+typedef uint32_t NodeId; |
+ |
+// Lowers all simplified memory access and allocation related nodes (i.e. |
+// Allocate, LoadField, StoreField and friends) to machine operators. |
+// Performs allocation folding and store write barrier elimination |
+// implicitly. |
+class MemoryOptimizer final { |
+ public: |
+ MemoryOptimizer(JSGraph* jsgraph, Zone* zone); |
+ ~MemoryOptimizer() {} |
+ |
+ void Optimize(); |
+ |
+ private: |
+ // An allocation group represents a set of allocations that have been folded |
+ // together. |
+ class AllocationGroup final : public ZoneObject { |
+ public: |
+ AllocationGroup(Node* node, PretenureFlag pretenure, Zone* zone); |
+ AllocationGroup(Node* node, PretenureFlag pretenure, Node* size, |
+ Zone* zone); |
+ ~AllocationGroup() {} |
+ |
+ void Add(Node* object); |
+ bool Contains(Node* object) const; |
+ bool IsNewSpaceAllocation() const { return pretenure() == NOT_TENURED; } |
+ |
+ PretenureFlag pretenure() const { return pretenure_; } |
+ Node* size() const { return size_; } |
+ |
+ private: |
+ ZoneSet<NodeId> node_ids_; |
+ PretenureFlag const pretenure_; |
+ Node* const size_; |
+ |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationGroup); |
+ }; |
+ |
+ // An allocation state is propagated on the effect paths through the graph. |
+ class AllocationState final : public ZoneObject { |
+ public: |
+ static AllocationState const* Empty(Zone* zone) { |
+ return new (zone) AllocationState(); |
+ } |
+ static AllocationState const* Closed(AllocationGroup* group, Zone* zone) { |
+ return new (zone) AllocationState(group); |
+ } |
+ static AllocationState const* Open(AllocationGroup* group, int size, |
+ Node* top, Zone* zone) { |
+ return new (zone) AllocationState(group, size, top); |
+ } |
+ |
+ bool IsNewSpaceAllocation() const; |
+ |
+ AllocationGroup* group() const { return group_; } |
+ Node* top() const { return top_; } |
+ int size() const { return size_; } |
+ |
+ private: |
+ AllocationState(); |
+ explicit AllocationState(AllocationGroup* group); |
+ AllocationState(AllocationGroup* group, int size, Node* top); |
+ |
+ AllocationGroup* const group_; |
+ // The upper bound of the combined allocated object size on the current path |
+ // (max int if allocation folding is impossible on this path). |
+ int const size_; |
+ Node* const top_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AllocationState); |
+ }; |
+ |
+ // An array of allocation states used to collect states on merges. |
+ typedef ZoneVector<AllocationState const*> AllocationStates; |
+ |
+ // We thread through tokens to represent the current state on a given effect |
+ // path through the graph. |
+ struct Token { |
+ Node* node; |
+ AllocationState const* state; |
+ }; |
+ |
+ void VisitNode(Node*, AllocationState const*); |
+ void VisitAllocate(Node*, AllocationState const*); |
+ void VisitCall(Node*, AllocationState const*); |
+ void VisitLoadElement(Node*, AllocationState const*); |
+ void VisitLoadField(Node*, AllocationState const*); |
+ void VisitStoreElement(Node*, AllocationState const*); |
+ void VisitStoreField(Node*, AllocationState const*); |
+ void VisitOtherEffect(Node*, AllocationState const*); |
+ |
+ Node* ComputeIndex(ElementAccess const&, Node*); |
+ WriteBarrierKind ComputeWriteBarrierKind(Node* object, |
+ AllocationState const* state, |
+ WriteBarrierKind); |
+ |
+ AllocationState const* MergeStates(AllocationStates const& states); |
+ |
+ void EnqueueMerge(Node*, int, AllocationState const*); |
+ void EnqueueUses(Node*, AllocationState const*); |
+ void EnqueueUse(Node*, int, AllocationState const*); |
+ |
+ AllocationState const* empty_state() const { return empty_state_; } |
+ Graph* graph() const; |
+ Isolate* isolate() const; |
+ JSGraph* jsgraph() const { return jsgraph_; } |
+ CommonOperatorBuilder* common() const; |
+ MachineOperatorBuilder* machine() const; |
+ Zone* zone() const { return zone_; } |
+ |
+ SetOncePointer<const Operator> allocate_operator_; |
+ JSGraph* const jsgraph_; |
+ AllocationState const* const empty_state_; |
+ ZoneMap<NodeId, AllocationStates> pending_; |
+ ZoneQueue<Token> tokens_; |
+ Zone* const zone_; |
+ |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryOptimizer); |
+}; |
+ |
+} // namespace compiler |
+} // namespace internal |
+} // namespace v8 |
+ |
+#endif // V8_COMPILER_MEMORY_OPTIMIZER_H_ |