state-values-utils.h 4.34 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2015 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_STATE_VALUES_UTILS_H_
#define V8_COMPILER_STATE_VALUES_UTILS_H_

8
#include <array>
9

10
#include "src/common/globals.h"
11
#include "src/compiler/common-operator.h"
12
#include "src/compiler/js-graph.h"
13
#include "src/zone/zone-hashmap.h"
14 15 16 17

namespace v8 {
namespace internal {

18 19
class BitVector;

20 21 22 23
namespace compiler {

class Graph;

24
class V8_EXPORT_PRIVATE StateValuesCache {
25 26 27
 public:
  explicit StateValuesCache(JSGraph* js_graph);

28
  Node* GetNodeForValues(Node** values, size_t count,
29 30
                         const BitVector* liveness = nullptr,
                         int liveness_offset = 0);
31 32 33

 private:
  static const size_t kMaxInputCount = 8;
34
  using WorkingBuffer = std::array<Node*, kMaxInputCount>;
35 36 37 38 39 40 41 42 43 44

  struct NodeKey {
    Node* node;

    explicit NodeKey(Node* node) : node(node) {}
  };

  struct StateValuesKey : public NodeKey {
    // ValueArray - array of nodes ({node} has to be nullptr).
    size_t count;
45
    SparseInputMask mask;
46 47
    Node** values;

48 49
    StateValuesKey(size_t count, SparseInputMask mask, Node** values)
        : NodeKey(nullptr), count(count), mask(mask), values(values) {}
50 51 52 53 54 55
  };

  static bool AreKeysEqual(void* key1, void* key2);
  static bool IsKeysEqualToNode(StateValuesKey* key, Node* node);
  static bool AreValueKeysEqual(StateValuesKey* key1, StateValuesKey* key2);

56 57 58 59 60 61 62 63
  // Fills {node_buffer}, starting from {node_count}, with {values}, starting
  // at {values_idx}, sparsely encoding according to {liveness}. {node_count} is
  // updated with the new number of inputs in {node_buffer}, and a bitmask of
  // the sparse encoding is returned.
  SparseInputMask::BitMaskType FillBufferWithValues(WorkingBuffer* node_buffer,
                                                    size_t* node_count,
                                                    size_t* values_idx,
                                                    Node** values, size_t count,
64 65
                                                    const BitVector* liveness,
                                                    int liveness_offset);
66 67

  Node* BuildTree(size_t* values_idx, Node** values, size_t count,
68
                  const BitVector* liveness, int liveness_offset, size_t level);
69 70

  WorkingBuffer* GetWorkingSpace(size_t level);
71
  Node* GetEmptyStateValues();
72 73
  Node* GetValuesNodeFromCache(Node** nodes, size_t count,
                               SparseInputMask mask);
74 75 76 77 78 79 80

  Graph* graph() { return js_graph_->graph(); }
  CommonOperatorBuilder* common() { return js_graph_->common(); }

  Zone* zone() { return graph()->zone(); }

  JSGraph* js_graph_;
81
  CustomMatcherZoneHashMap hash_map_;
82
  ZoneVector<WorkingBuffer> working_space_;  // One working space per level.
83 84 85
  Node* empty_state_values_;
};

86
class V8_EXPORT_PRIVATE StateValuesAccess {
87
 public:
88 89 90 91 92 93
  struct TypedNode {
    Node* node;
    MachineType type;
    TypedNode(Node* node, MachineType type) : node(node), type(type) {}
  };

94
  class V8_EXPORT_PRIVATE iterator {
95
   public:
96
    bool operator!=(iterator const& other) const;
97 98
    iterator& operator++();
    TypedNode operator*();
99

100 101 102 103 104 105
    Node* node();
    bool done() const { return current_depth_ < 0; }

    // Returns the number of empty nodes that were skipped over.
    size_t AdvanceTillNotEmpty();

106 107 108 109
   private:
    friend class StateValuesAccess;

    iterator() : current_depth_(-1) {}
110 111 112 113 114 115 116 117 118
    explicit iterator(Node* node);

    MachineType type();
    void Advance();
    void EnsureValid();

    SparseInputMask::InputIterator* Top();
    void Push(Node* node);
    void Pop();
119 120

    static const int kMaxInlineDepth = 8;
121
    SparseInputMask::InputIterator stack_[kMaxInlineDepth];
122 123 124 125 126
    int current_depth_;
  };

  explicit StateValuesAccess(Node* node) : node_(node) {}

127 128
  size_t size() const;
  iterator begin() const { return iterator(node_); }
129 130 131 132 133 134 135 136 137 138 139
  iterator begin_without_receiver() const {
    return ++begin();  // Skip the receiver.
  }
  iterator begin_without_receiver_and_skip(int n_skips) {
    iterator it = begin_without_receiver();
    while (n_skips > 0 && !it.done()) {
      ++it;
      --n_skips;
    }
    return it;
  }
140
  iterator end() const { return iterator(); }
141 142 143 144 145 146 147 148 149 150

 private:
  Node* node_;
};

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_STATE_VALUES_UTILS_H_