1 /* Copyright 2020 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 #ifndef TENSORFLOW_PYTHON_UTIL_FUNCTION_PARAMETER_CANONICALIZER_H_ 17 #define TENSORFLOW_PYTHON_UTIL_FUNCTION_PARAMETER_CANONICALIZER_H_ 18 19 #include <Python.h> 20 21 #include <vector> 22 23 #include "absl/types/span.h" 24 #include "tensorflow/core/platform/logging.h" 25 #include "tensorflow/python/lib/core/safe_pyobject_ptr.h" 26 27 namespace tensorflow { 28 29 // A class that Canonicalizes Python arg & kwargs parameters. 30 class FunctionParameterCanonicalizer { 31 public: 32 // `arg_names` is a list of argument names, and `defaults` is default PyObject 33 // instances for arguments. `default` is aligned to the end. 34 FunctionParameterCanonicalizer(absl::Span<const char*> arg_names, 35 absl::Span<PyObject*> defaults); 36 37 // Returns the total number of arguments. 38 ABSL_MUST_USE_RESULT GetArgSize()39 int GetArgSize() const { return interned_arg_names_.size(); } 40 41 // Canonicalizes `args` and `kwargs` by the spec specified at construction. 42 // It's written to `result`. Returns `true` if Canonicalization was 43 // successful, and `false` otherwise. When it fails, it also sets CPython 44 // error status. 45 // This function does not update reference counter of any Python objects. 46 // `PyObject*`s in `result` are borrowed references from `args`, `kwargs`, and 47 // possibly `defaults_`, and will be only valid if `args` and `kwargs` are 48 // still alive. 49 ABSL_MUST_USE_RESULT 50 ABSL_ATTRIBUTE_HOT 51 bool Canonicalize(PyObject* args, PyObject* kwargs, 52 absl::Span<PyObject*> result); 53 54 private: 55 // Simple linear search of `name` in `interned_arg_names`. If found, returns 56 // the index. If not found, returns `interned_arg_names.size()`. 57 ABSL_MUST_USE_RESULT 58 ABSL_ATTRIBUTE_HOT 59 std::size_t InternedArgNameLinearSearch(PyObject* name); 60 61 // Check if `interned_arg_names_` is unique. 62 bool AreInternedArgNamesUnique(); 63 64 // TODO(kkb): Use one `std::vector` and two `absl:Span`s instead to improve 65 // cache locality. 66 std::vector<Safe_PyObjectPtr> interned_arg_names_; 67 std::vector<Safe_PyObjectPtr> defaults_; 68 const int positional_args_size_; 69 }; 70 71 } // namespace tensorflow 72 73 #endif // TENSORFLOW_PYTHON_UTIL_FUNCTION_PARAMETER_CANONICALIZER_H_ 74