| 181 | } |
| 182 | |
| 183 | Status PropagateThroughCallOp( |
| 184 | const Node& n, const absl::optional<std::string>& function_name, |
| 185 | const int call_depth, FunctionLibraryRuntime* lib_runtime, |
| 186 | absl::flat_hash_map<const Edge*, ResourceUsageAnalysis::NodeInfo>* |
| 187 | user_to_source, |
| 188 | absl::flat_hash_map<ResourceUsageAnalysis::NodeInfo, |
| 189 | absl::flat_hash_set<ResourceUsageAnalysis::NodeInfo>>* |
| 190 | source_to_path) { |
| 191 | if (call_depth > kMaxCallDepth) { |
| 192 | return errors::InvalidArgument( |
| 193 | "Function call stack in given graph is too deep, last function ", |
| 194 | "name is: ", function_name.value()); |
| 195 | } |
| 196 | // resource_arg_indices contains all indices of the input |
| 197 | // arguments that carry Stack/TensorArray resource handles. |
| 198 | absl::flat_hash_set<int> resource_arg_indices; |
| 199 | for (const Edge* e : n.in_edges()) { |
| 200 | if (user_to_source->contains(e)) { |
| 201 | resource_arg_indices.emplace(e->dst_input()); |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | // Instantiate associated function to get function body. |
| 206 | FunctionLibraryRuntime::Handle handle; |
| 207 | TF_RETURN_IF_ERROR(InstantiateFunctionCall(n.def(), lib_runtime, &handle)); |
| 208 | auto release_handle_on_return = gtl::MakeCleanup( |
| 209 | [&] { TF_CHECK_OK(lib_runtime->ReleaseHandle(handle)); }); |
| 210 | const FunctionBody* fbody = lib_runtime->GetFunctionBody(handle); |
| 211 | |
| 212 | // Recursively analyze called function for resource sources and users. |
| 213 | absl::flat_hash_map<ResourceUsageAnalysis::NodeInfo, |
| 214 | absl::flat_hash_set<ResourceUsageAnalysis::NodeInfo>> |
| 215 | called_function_source_to_path; |
| 216 | TF_RETURN_IF_ERROR(AnalyzeResourceUsage( |
| 217 | fbody->graph, n.type_string(), call_depth + 1, resource_arg_indices, |
| 218 | lib_runtime, &called_function_source_to_path)); |
| 219 | |
| 220 | TF_RETURN_IF_ERROR(UpdateResourceUsageFromFunctionBodyAnalysis( |
| 221 | n, function_name, *fbody, called_function_source_to_path, user_to_source, |
| 222 | source_to_path)); |
| 223 | return Status::OK(); |
| 224 | } |
| 225 | |
| 226 | // Analyzes pass through values for Identity and IdentityN ops. |
| 227 | Status PropagateThroughIdentityOp( |
no test coverage detected