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