Home | History | Annotate | Download | only in compiler
      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_
    150