summaryrefslogtreecommitdiff
path: root/chromium/v8/src/compiler/node-observer.h
blob: a6c4619262d0bb331240dae98b7e86d4b005b888 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2021 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.

// This file declares the implementation of a new intrinsic %ObserveNode(expr),
// which has noop semantics but triggers the invocation of callbacks on a
// NodeObserver object. The NodeObserver is set on the OptimizedCompilationInfo
// and callbacks are called when the node generated for 'expr' is created or
// changed in any phase, until EffectControlLinearization.
//
// The modifications currently observed are changes to the observed Node
// operator and type and its replacement with another Node.
//
// This provides the infrastructure to write unit tests that check for the
// construction of or the lowering to specific nodes in the TurboFan graphs.

#ifndef V8_COMPILER_NODE_OBSERVER_H_
#define V8_COMPILER_NODE_OBSERVER_H_

#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "src/zone/zone.h"

namespace v8 {
namespace internal {
namespace compiler {

class Node;
class Operator;

class ObservableNodeState {
 public:
  ObservableNodeState(const Node* node, Zone* zone);

  uint32_t id() const { return id_; }
  const Operator* op() const { return op_; }
  int16_t opcode() const { return op_->opcode(); }
  Type type() const { return type_; }

 private:
  uint32_t id_;
  const Operator* op_;
  Type type_;
};

inline bool operator==(const ObservableNodeState& lhs,
                       const ObservableNodeState& rhs) {
  return lhs.id() == rhs.id() && lhs.op() == rhs.op() &&
         lhs.type() == rhs.type();
}

inline bool operator!=(const ObservableNodeState& lhs,
                       const ObservableNodeState& rhs) {
  return !operator==(lhs, rhs);
}

class NodeObserver : public ZoneObject {
 public:
  enum class Observation {
    kContinue,
    kStop,
  };

  NodeObserver() = default;
  virtual ~NodeObserver() = 0;

  NodeObserver(const NodeObserver&) = delete;
  NodeObserver& operator=(const NodeObserver&) = delete;

  virtual Observation OnNodeCreated(const Node* node) {
    return Observation::kContinue;
  }

  virtual Observation OnNodeChanged(const char* reducer_name, const Node* node,
                                    const ObservableNodeState& old_state) {
    return Observation::kContinue;
  }

  void set_has_observed_changes() { has_observed_changes_ = true; }
  bool has_observed_changes() const { return has_observed_changes_; }

 private:
  std::atomic<bool> has_observed_changes_{false};
};
inline NodeObserver::~NodeObserver() = default;

struct NodeObservation : public ZoneObject {
  NodeObservation(NodeObserver* node_observer, const Node* node, Zone* zone)
      : observer(node_observer), state(node, zone) {
    DCHECK_NOT_NULL(node_observer);
  }

  NodeObserver* observer;
  ObservableNodeState state;
};

class ObserveNodeManager : public ZoneObject {
 public:
  explicit ObserveNodeManager(Zone* zone) : zone_(zone), observations_(zone) {}

  void StartObserving(Node* node, NodeObserver* observer);
  void OnNodeChanged(const char* reducer_name, const Node* old_node,
                     const Node* new_node);

 private:
  Zone* zone_;
  ZoneMap<NodeId, NodeObservation*> observations_;
};

struct ObserveNodeInfo {
  ObserveNodeInfo() : observe_node_manager(nullptr), node_observer(nullptr) {}
  ObserveNodeInfo(ObserveNodeManager* manager, NodeObserver* observer)
      : observe_node_manager(manager), node_observer(observer) {}

  void StartObserving(Node* node) const {
    if (observe_node_manager) {
      DCHECK_NOT_NULL(node_observer);
      observe_node_manager->StartObserving(node, node_observer);
    }
  }

  ObserveNodeManager* observe_node_manager;
  NodeObserver* node_observer;
};

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

#endif  // V8_COMPILER_NODE_OBSERVER_H_