• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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 // This file declares the implementation of a new intrinsic %ObserveNode(expr),
6 // which has noop semantics but triggers the invocation of callbacks on a
7 // NodeObserver object. The NodeObserver is set on the OptimizedCompilationInfo
8 // and callbacks are called when the node generated for 'expr' is created or
9 // changed in any phase, until EffectControlLinearization.
10 //
11 // The modifications currently observed are changes to the observed Node
12 // operator and type and its replacement with another Node.
13 //
14 // This provides the infrastructure to write unit tests that check for the
15 // construction of or the lowering to specific nodes in the TurboFan graphs.
16 
17 #ifndef V8_COMPILER_NODE_OBSERVER_H_
18 #define V8_COMPILER_NODE_OBSERVER_H_
19 
20 #include "src/compiler/node.h"
21 #include "src/compiler/operator.h"
22 #include "src/zone/zone.h"
23 
24 namespace v8 {
25 namespace internal {
26 namespace compiler {
27 
28 class Node;
29 class Operator;
30 
31 class ObservableNodeState {
32  public:
33   ObservableNodeState(const Node* node, Zone* zone);
34 
id()35   uint32_t id() const { return id_; }
op()36   const Operator* op() const { return op_; }
opcode()37   int16_t opcode() const { return op_->opcode(); }
type()38   Type type() const { return type_; }
39 
40  private:
41   uint32_t id_;
42   const Operator* op_;
43   Type type_;
44 };
45 
46 inline bool operator==(const ObservableNodeState& lhs,
47                        const ObservableNodeState& rhs) {
48   return lhs.id() == rhs.id() && lhs.op() == rhs.op() &&
49          lhs.type() == rhs.type();
50 }
51 
52 inline bool operator!=(const ObservableNodeState& lhs,
53                        const ObservableNodeState& rhs) {
54   return !operator==(lhs, rhs);
55 }
56 
57 class NodeObserver : public ZoneObject {
58  public:
59   enum class Observation {
60     kContinue,
61     kStop,
62   };
63 
64   NodeObserver() = default;
65   virtual ~NodeObserver() = 0;
66 
67   NodeObserver(const NodeObserver&) = delete;
68   NodeObserver& operator=(const NodeObserver&) = delete;
69 
OnNodeCreated(const Node * node)70   virtual Observation OnNodeCreated(const Node* node) {
71     return Observation::kContinue;
72   }
73 
OnNodeChanged(const char * reducer_name,const Node * node,const ObservableNodeState & old_state)74   virtual Observation OnNodeChanged(const char* reducer_name, const Node* node,
75                                     const ObservableNodeState& old_state) {
76     return Observation::kContinue;
77   }
78 
set_has_observed_changes()79   void set_has_observed_changes() { has_observed_changes_ = true; }
has_observed_changes()80   bool has_observed_changes() const { return has_observed_changes_; }
81 
82  private:
83   std::atomic<bool> has_observed_changes_{false};
84 };
85 inline NodeObserver::~NodeObserver() = default;
86 
87 struct NodeObservation : public ZoneObject {
NodeObservationNodeObservation88   NodeObservation(NodeObserver* node_observer, const Node* node, Zone* zone)
89       : observer(node_observer), state(node, zone) {
90     DCHECK_NOT_NULL(node_observer);
91   }
92 
93   NodeObserver* observer;
94   ObservableNodeState state;
95 };
96 
97 class ObserveNodeManager : public ZoneObject {
98  public:
ObserveNodeManager(Zone * zone)99   explicit ObserveNodeManager(Zone* zone) : zone_(zone), observations_(zone) {}
100 
101   void StartObserving(Node* node, NodeObserver* observer);
102   void OnNodeChanged(const char* reducer_name, const Node* old_node,
103                      const Node* new_node);
104 
105  private:
106   Zone* zone_;
107   ZoneMap<NodeId, NodeObservation*> observations_;
108 };
109 
110 struct ObserveNodeInfo {
ObserveNodeInfoObserveNodeInfo111   ObserveNodeInfo() : observe_node_manager(nullptr), node_observer(nullptr) {}
ObserveNodeInfoObserveNodeInfo112   ObserveNodeInfo(ObserveNodeManager* manager, NodeObserver* observer)
113       : observe_node_manager(manager), node_observer(observer) {}
114 
StartObservingObserveNodeInfo115   void StartObserving(Node* node) const {
116     if (observe_node_manager) {
117       DCHECK_NOT_NULL(node_observer);
118       observe_node_manager->StartObserving(node, node_observer);
119     }
120   }
121 
122   ObserveNodeManager* observe_node_manager;
123   NodeObserver* node_observer;
124 };
125 
126 }  // namespace compiler
127 }  // namespace internal
128 }  // namespace v8
129 
130 #endif  // V8_COMPILER_NODE_OBSERVER_H_
131