| 120 | } |
| 121 | |
| 122 | char* GraphView::InitializeNode(char* ptr, const Node* n) { |
| 123 | const int id = n->id(); |
| 124 | CHECK(node_offsets_[id] == kuint32max); // Initial value in constructor |
| 125 | |
| 126 | const size_t bytes = NodeItemBytes(n); |
| 127 | constexpr size_t kItemAlignment = sizeof(NodeItem*); |
| 128 | CHECK_EQ(reinterpret_cast<uintptr_t>(ptr) % kItemAlignment, 0); |
| 129 | NodeItem* item = reinterpret_cast<NodeItem*>(ptr); |
| 130 | |
| 131 | // We store a 32-bit offset relative to the beginning of space_, so that we |
| 132 | // only need an array of 32-bit values to map from node id to the NodeItem*, |
| 133 | // (versus 64 bits on most machines if we just stored an array of NodeItem* |
| 134 | // pointers). Casting to int64 is needed on 32bit CPU to avoid comparing |
| 135 | // values as "int" vs "size_t" in CHECK_LE. |
| 136 | CHECK_LE(static_cast<int64_t>(ptr - space_), kuint32max); |
| 137 | const uint32 offset = static_cast<uint32>(ptr - space_); |
| 138 | node_offsets_[id] = offset; |
| 139 | ptr += bytes; |
| 140 | |
| 141 | int32_t num_output_edges; |
| 142 | int32_t num_output_control_edges; |
| 143 | std::tie(num_output_edges, num_output_control_edges) = CountOutputEdges(n); |
| 144 | const int num_inputs = n->num_inputs(); |
| 145 | const int num_outputs = n->num_outputs(); |
| 146 | |
| 147 | new (item) NodeItem(); |
| 148 | item->num_inputs = num_inputs; |
| 149 | item->num_outputs = num_outputs; |
| 150 | item->num_output_edges = num_output_edges; |
| 151 | item->num_output_control_edges = num_output_control_edges; |
| 152 | |
| 153 | // Fill output edges. |
| 154 | // Keep track of the last EdgeInfo in the EdgeInfo array that references |
| 155 | // a given output slot. For all but the last, we need to do a copy of the |
| 156 | // Tensor when propagating results downstream in the graph, but for the |
| 157 | // last one, we can just do a move of the Tensor object to propagate it. |
| 158 | gtl::InlinedVector<EdgeInfo*, 4> last_indices(num_outputs, nullptr); |
| 159 | EdgeInfo* dst_edge = item->output_edge_base(); |
| 160 | for (auto e : n->out_edges()) { |
| 161 | if (e->IsControlEdge()) continue; |
| 162 | dst_edge->dst_id = e->dst()->id(); |
| 163 | CHECK_LE(e->src_output(), 0x3FFFFFFF); // Must fit in 31 bits |
| 164 | dst_edge->output_slot = e->src_output(); |
| 165 | dst_edge->is_last = false; |
| 166 | const int output_slot = dst_edge->output_slot; |
| 167 | if (output_slot >= 0) { |
| 168 | last_indices[output_slot] = dst_edge; |
| 169 | } |
| 170 | // NOTE: The `input_slot` will be rewritten to the frame-wide offset later |
| 171 | // in `ExecutorImpl::Initialize()`. |
| 172 | dst_edge->input_slot = e->dst_input(); |
| 173 | dst_edge++; |
| 174 | } |
| 175 | for (EdgeInfo* edge_info : last_indices) { |
| 176 | if (edge_info != nullptr) { |
| 177 | edge_info->is_last = true; |
| 178 | } |
| 179 | } |
nothing calls this directly
no test coverage detected