Bug Summary

File:.cache/bazel/_bazel_alan/39be661231df2a680c9b74265384c13c/execroot/org_tensorflow/tensorflow/python/eager/pywrap_tensor.cc
Warning:line 1050, column 21
PyObject ownership leak with reference count of 1

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pywrap_tensor.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-output=html -analyzer-checker=python -analyzer-disable-checker=deadcode -analyzer-config prune-paths=true,suppress-c++-stdlib=true,suppress-null-return-paths=false,crosscheck-with-z3=true,model-path=/opt/pyrefcon/lib/pyrefcon/models/models -analyzer-config experimental-enable-naive-ctu-analysis=true,ctu-dir=/tmp/pyrefcon/tensorflow/csa-scan,ctu-index-name=/tmp/pyrefcon/tensorflow/csa-scan/externalDefMap.txt,ctu-invocation-list=/tmp/pyrefcon/tensorflow/csa-scan/invocations.yaml,display-ctu-progress=false -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/pyrefcon/.cache/bazel/_bazel_alan/39be661231df2a680c9b74265384c13c/execroot/org_tensorflow -resource-dir /opt/pyrefcon/lib/clang/13.0.0 -iquote . -iquote bazel-out/k8-opt/bin -iquote external/com_google_absl -iquote bazel-out/k8-opt/bin/external/com_google_absl -iquote external/nsync -iquote bazel-out/k8-opt/bin/external/nsync -iquote external/eigen_archive -iquote bazel-out/k8-opt/bin/external/eigen_archive -iquote external/gif -iquote bazel-out/k8-opt/bin/external/gif -iquote external/libjpeg_turbo -iquote bazel-out/k8-opt/bin/external/libjpeg_turbo -iquote external/com_google_protobuf -iquote bazel-out/k8-opt/bin/external/com_google_protobuf -iquote external/com_googlesource_code_re2 -iquote bazel-out/k8-opt/bin/external/com_googlesource_code_re2 -iquote external/farmhash_archive -iquote bazel-out/k8-opt/bin/external/farmhash_archive -iquote external/fft2d -iquote bazel-out/k8-opt/bin/external/fft2d -iquote external/highwayhash -iquote bazel-out/k8-opt/bin/external/highwayhash -iquote external/zlib -iquote bazel-out/k8-opt/bin/external/zlib -iquote external/double_conversion -iquote bazel-out/k8-opt/bin/external/double_conversion -iquote external/snappy -iquote bazel-out/k8-opt/bin/external/snappy -iquote external/llvm-project -iquote bazel-out/k8-opt/bin/external/llvm-project -iquote external/llvm_terminfo -iquote bazel-out/k8-opt/bin/external/llvm_terminfo -iquote external/llvm_zlib -iquote bazel-out/k8-opt/bin/external/llvm_zlib -iquote external/curl -iquote bazel-out/k8-opt/bin/external/curl -iquote external/boringssl -iquote bazel-out/k8-opt/bin/external/boringssl -iquote external/jsoncpp_git -iquote bazel-out/k8-opt/bin/external/jsoncpp_git -iquote external/local_config_cuda -iquote bazel-out/k8-opt/bin/external/local_config_cuda -iquote external/local_config_rocm -iquote bazel-out/k8-opt/bin/external/local_config_rocm -iquote external/local_config_tensorrt -iquote bazel-out/k8-opt/bin/external/local_config_tensorrt -iquote external/mkl_dnn_v1 -iquote bazel-out/k8-opt/bin/external/mkl_dnn_v1 -iquote external/com_github_grpc_grpc -iquote bazel-out/k8-opt/bin/external/com_github_grpc_grpc -iquote external/upb -iquote bazel-out/k8-opt/bin/external/upb -iquote external/lmdb -iquote bazel-out/k8-opt/bin/external/lmdb -iquote external/png -iquote bazel-out/k8-opt/bin/external/png -iquote external/gemmlowp -iquote bazel-out/k8-opt/bin/external/gemmlowp -iquote external/icu -iquote bazel-out/k8-opt/bin/external/icu -iquote external/org_sqlite -iquote bazel-out/k8-opt/bin/external/org_sqlite -iquote external/dlpack -iquote bazel-out/k8-opt/bin/external/dlpack -iquote external/local_config_python -iquote bazel-out/k8-opt/bin/external/local_config_python -iquote external/pybind11 -iquote bazel-out/k8-opt/bin/external/pybind11 -isystem external/nsync/public -isystem bazel-out/k8-opt/bin/external/nsync/public -isystem third_party/eigen3/mkl_include -isystem bazel-out/k8-opt/bin/third_party/eigen3/mkl_include -isystem external/eigen_archive -isystem bazel-out/k8-opt/bin/external/eigen_archive -isystem external/gif -isystem bazel-out/k8-opt/bin/external/gif -isystem external/com_google_protobuf/src -isystem bazel-out/k8-opt/bin/external/com_google_protobuf/src -isystem external/farmhash_archive/src -isystem bazel-out/k8-opt/bin/external/farmhash_archive/src -isystem external/zlib -isystem bazel-out/k8-opt/bin/external/zlib -isystem external/double_conversion -isystem bazel-out/k8-opt/bin/external/double_conversion -isystem external/llvm-project/llvm/include -isystem bazel-out/k8-opt/bin/external/llvm-project/llvm/include -isystem external/llvm-project/mlir/include -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/include -isystem external/curl/include -isystem bazel-out/k8-opt/bin/external/curl/include -isystem external/boringssl/src/include -isystem bazel-out/k8-opt/bin/external/boringssl/src/include -isystem external/jsoncpp_git/include -isystem bazel-out/k8-opt/bin/external/jsoncpp_git/include -isystem external/local_config_cuda/cuda -isystem bazel-out/k8-opt/bin/external/local_config_cuda/cuda -isystem external/local_config_cuda/cuda/cuda/include -isystem bazel-out/k8-opt/bin/external/local_config_cuda/cuda/cuda/include -isystem external/local_config_rocm/rocm -isystem bazel-out/k8-opt/bin/external/local_config_rocm/rocm -isystem external/local_config_rocm/rocm/rocm/include -isystem bazel-out/k8-opt/bin/external/local_config_rocm/rocm/rocm/include -isystem external/local_config_rocm/rocm/rocm/include/rocrand -isystem bazel-out/k8-opt/bin/external/local_config_rocm/rocm/rocm/include/rocrand -isystem external/local_config_rocm/rocm/rocm/include/roctracer -isystem bazel-out/k8-opt/bin/external/local_config_rocm/rocm/rocm/include/roctracer -isystem tensorflow/compiler/mlir/tensorflow/include -isystem bazel-out/k8-opt/bin/tensorflow/compiler/mlir/tensorflow/include -isystem tensorflow/compiler/mlir/hlo/include -isystem bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/include -isystem tensorflow/compiler/mlir/xla/include -isystem bazel-out/k8-opt/bin/tensorflow/compiler/mlir/xla/include -isystem external/mkl_dnn_v1/include -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/include -isystem external/mkl_dnn_v1/src -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src -isystem external/mkl_dnn_v1/src/common -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/common -isystem external/mkl_dnn_v1/src/common/ittnotify -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/common/ittnotify -isystem external/mkl_dnn_v1/src/cpu -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/cpu -isystem external/mkl_dnn_v1/src/cpu/gemm -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/cpu/gemm -isystem external/mkl_dnn_v1/src/cpu/x64/xbyak -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/cpu/x64/xbyak -isystem external/com_github_grpc_grpc/include -isystem bazel-out/k8-opt/bin/external/com_github_grpc_grpc/include -isystem external/com_github_grpc_grpc/src/core/ext/upb-generated -isystem bazel-out/k8-opt/bin/external/com_github_grpc_grpc/src/core/ext/upb-generated -isystem external/com_github_grpc_grpc/third_party/address_sorting/include -isystem bazel-out/k8-opt/bin/external/com_github_grpc_grpc/third_party/address_sorting/include -isystem external/png -isystem bazel-out/k8-opt/bin/external/png -isystem external/icu/icu4c/source/common -isystem bazel-out/k8-opt/bin/external/icu/icu4c/source/common -isystem external/llvm-project/mlir/lib/Conversions/GPUToSPIRV -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/lib/Conversions/GPUToSPIRV -isystem external/llvm-project/mlir/lib/Conversion/MemRefToSPIRV -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/lib/Conversion/MemRefToSPIRV -isystem external/llvm-project/mlir/lib/Conversion/StandardToSPIRV -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/lib/Conversion/StandardToSPIRV -isystem external/llvm-project/mlir/lib/Conversion/MathToSPIRV -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/lib/Conversion/MathToSPIRV -isystem external/llvm-project/mlir/lib/Conversion/TosaToLinalg -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/lib/Conversion/TosaToLinalg -isystem external/llvm-project/mlir/lib/Conversion/TosaToSCF -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/lib/Conversion/TosaToSCF -isystem external/llvm-project/mlir/lib/Conversion/TosaToStandard -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/lib/Conversion/TosaToStandard -isystem external/llvm-project/llvm/lib/Target/X86 -isystem bazel-out/k8-opt/bin/external/llvm-project/llvm/lib/Target/X86 -isystem external/local_config_python/numpy_include -isystem bazel-out/k8-opt/bin/external/local_config_python/numpy_include -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -isystem external/pybind11/include -isystem bazel-out/k8-opt/bin/external/pybind11/include -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=1 -D NDEBUG -D SQLITE_OMIT_DEPRECATED -D EIGEN_ALTIVEC_USE_CUSTOM_PACK=0 -D GRPC_ARES=0 -D TENSORFLOW_USE_CUSTOM_CONTRACTION_KERNEL -D TENSORFLOW_USE_MKLDNN_CONTRACTION_KERNEL -D HAVE_SYS_UIO_H -D TF_USE_SNAPPY -D CURL_STATICLIB -D EIGEN_MPL2_ONLY -D EIGEN_MAX_ALIGN_BYTES=64 -D LLVM_ON_UNIX=1 -D HAVE_BACKTRACE=1 -D BACKTRACE_HEADER=<execinfo.h> -D LTDL_SHLIB_EXT=".so" -D LLVM_PLUGIN_EXT=".so" -D LLVM_ENABLE_THREADS=1 -D HAVE_SYSEXITS_H=1 -D HAVE_UNISTD_H=1 -D HAVE_STRERROR_R=1 -D HAVE_LIBPTHREAD=1 -D HAVE_PTHREAD_GETNAME_NP=1 -D HAVE_PTHREAD_SETNAME_NP=1 -D HAVE_PTHREAD_GETSPECIFIC=1 -D HAVE_REGISTER_FRAME=1 -D HAVE_DEREGISTER_FRAME=1 -D _GNU_SOURCE -D HAVE_LINK_H=1 -D HAVE_LSEEK64=1 -D HAVE_MALLINFO=1 -D HAVE_POSIX_FALLOCATE=1 -D HAVE_SBRK=1 -D HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC=1 -D LLVM_NATIVE_ARCH="X86" -D LLVM_NATIVE_ASMPARSER=LLVMInitializeX86AsmParser -D LLVM_NATIVE_ASMPRINTER=LLVMInitializeX86AsmPrinter -D LLVM_NATIVE_DISASSEMBLER=LLVMInitializeX86Disassembler -D LLVM_NATIVE_TARGET=LLVMInitializeX86Target -D LLVM_NATIVE_TARGETINFO=LLVMInitializeX86TargetInfo -D LLVM_NATIVE_TARGETMC=LLVMInitializeX86TargetMC -D LLVM_NATIVE_TARGETMCA=LLVMInitializeX86TargetMCA -D LLVM_HOST_TRIPLE="x86_64-unknown-linux-gnu" -D LLVM_DEFAULT_TARGET_TRIPLE="x86_64-unknown-linux-gnu" -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinAttributesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinDialectIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinLocationAttributesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinTypeInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinTypesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/CallOpInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/CastOpInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/InferTypeOpInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/OpAsmInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/RegionKindInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SideEffectInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SubElementInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SymbolInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TensorEncodingIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ControlFlowInterfacesIncGen -I bazel-out/k8-opt/bin/external/local_config_cuda/cuda/_virtual_includes/cuda_headers_virtual -I bazel-out/k8-opt/bin/external/local_config_tensorrt/_virtual_includes/tensorrt_headers -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ParserTokenKinds -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/DerivedAttributeOpInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LoopLikeInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/StandardOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/VectorInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/AffineMemoryOpInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/AffineOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/CopyOpInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MemRefBaseIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MemRefOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TensorOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ViewLikeInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LinalgInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LinalgStructuredOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LinalgOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MathBaseIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MathOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SCFIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SCFPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TilingInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ComplexBaseIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ComplexOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/PDLOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/PDLTypesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/PDLInterpOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ConversionPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TransformsPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/QuantOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/QuantPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MLIRShapeCanonicalizationIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ShapeOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LLVMDialectAttributesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LLVMDialectInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LLVMOpsIncGen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/canonicalize_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/chlo_ops_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/hlo_ops_base_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/hlo_ops_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/hlo_ops_pattern_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/lhlo_ops_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/lhlo_ops_structs_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/chlo_legalize_to_hlo_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/disc_ral_ops_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/lhlo_gpu_ops_enums_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/lhlo_gpu_ops_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/lhlo_gpu_ops_structs_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/DiscRalPassIncGen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/LmhloPassIncGen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/MhloPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/llvm/_virtual_includes/InstCombineTableGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/VectorOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LinalgPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/StandardOpsTransformsPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LLVMConversionIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LLVMPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/OpenMPOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/AMXIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ArmNeonIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ArmSVEIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/X86VectorIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/AffinePassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/AsyncOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/AsyncPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/OpenACCOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/DLTIBaseIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/GPUBaseIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/GPUOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/GPUPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ParallelLoopMapperAttrGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/NVVMConversionIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/NVVMOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/GPUToNVVMGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/GPUToROCDLTGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ROCDLOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SPIRVAttrUtilsGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SPIRVAvailabilityIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SPIRVCanonicalizationIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SPIRVOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SPIRVSerializationGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ShapeToStandardGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TosaDialectIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TosaInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TosaPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/EmitCAttributesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/EmitCOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MemRefPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SPIRVPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ShapeTransformsPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SparseTensorAttrDefsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SparseTensorOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SparseTensorPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TensorPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/llvm/_virtual_includes/X86CodeGen -I bazel-out/k8-opt/bin/external/llvm-project/llvm/_virtual_includes/X86CommonTableGen -I bazel-out/k8-opt/bin/external/llvm-project/llvm/_virtual_includes/X86Info -I bazel-out/k8-opt/bin/external/llvm-project/llvm/_virtual_includes/X86UtilsAndDesc -I bazel-out/k8-opt/bin/external/pybind11/_virtual_includes/pybind11 -D AUTOLOAD_DYNAMIC_KERNELS -D __DATE__="redacted" -D __TIMESTAMP__="redacted" -D __TIME__="redacted" -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /opt/pyrefcon/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -Wno-builtin-macro-redefined -w -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/home/pyrefcon/.cache/bazel/_bazel_alan/39be661231df2a680c9b74265384c13c/execroot/org_tensorflow -ferror-limit 19 -stack-protector 1 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/pyrefcon/tensorflow/csa-scan/reports -x c++ tensorflow/python/eager/pywrap_tensor.cc

tensorflow/python/eager/pywrap_tensor.cc

1/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#include "tensorflow/python/eager/pywrap_tensor.h"
17
18#include <stdlib.h>
19#include <string.h>
20
21#include <cmath>
22
23#include "structmember.h" // NOLINT // For PyMemberDef
24#include "pybind11/pybind11.h"
25#include "tensorflow/c/c_api.h"
26#include "tensorflow/c/eager/c_api.h"
27#include "tensorflow/c/eager/c_api_internal.h"
28#include "tensorflow/c/eager/tfe_context_internal.h"
29#include "tensorflow/c/eager/tfe_tensorhandle_internal.h"
30#include "tensorflow/c/tf_status.h"
31#include "tensorflow/core/framework/types.h"
32#include "tensorflow/core/framework/types.pb.h"
33#include "tensorflow/core/lib/strings/strcat.h"
34#include "tensorflow/python/eager/pywrap_tensor_conversion.h"
35#include "tensorflow/python/eager/pywrap_tfe.h"
36#include "tensorflow/python/lib/core/ndarray_tensor.h"
37#include "tensorflow/python/lib/core/ndarray_tensor_bridge.h"
38#include "tensorflow/python/lib/core/numpy.h"
39#include "tensorflow/python/lib/core/py_exception_registry.h"
40#include "tensorflow/python/lib/core/py_seq_tensor.h"
41#include "tensorflow/python/lib/core/pybind11_status.h"
42#include "tensorflow/python/lib/core/safe_ptr.h"
43
44// forward declare
45struct EagerTensor;
46namespace tensorflow {
47
48// Convert a TFE_TensorHandle to a Python numpy.ndarray object.
49// The two may share underlying storage so changes to one may reflect in the
50// other.
51PyObject* TFE_TensorHandleToNumpy(TFE_TensorHandle* handle, TF_Status* status) {
52 if (TFE_TensorHandleDataType(handle) == TF_RESOURCE) {
53 TF_SetStatus(status, TF_INVALID_ARGUMENT,
54 "Cannot convert a Tensor of dtype resource to a NumPy array.");
55 return nullptr;
56 }
57
58 if (TFE_TensorHandleDataType(handle) == TF_VARIANT) {
59 TF_SetStatus(status, TF_INVALID_ARGUMENT,
60 "Cannot convert a Tensor of dtype variant to a NumPy array.");
61 return nullptr;
62 }
63 tensorflow::Safe_TF_TensorPtr tensor = nullptr;
64 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();;
65 tensor = tensorflow::make_safe(TFE_TensorHandleResolve(handle, status));
66 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); };
67 if (!status->status.ok()) {
68 return nullptr;
69 }
70
71 PyObject* ret = nullptr;
72 auto cppstatus =
73 tensorflow::TF_TensorToMaybeAliasedPyArray(std::move(tensor), &ret);
74 tensorflow::Set_TF_Status_from_Status(status, cppstatus);
75 if (!status->status.ok()) {
76 Py_XDECREF(ret)_Py_XDECREF(((PyObject*)(ret)));
77 return nullptr;
78 }
79 CHECK_NE(ret, nullptr)while (::tensorflow::internal::CheckOpString _result{ ::tensorflow
::internal::Check_NEImpl( ::tensorflow::internal::GetReferenceableValue
(ret), ::tensorflow::internal::GetReferenceableValue(nullptr)
, "ret" " " "!=" " " "nullptr")}) ::tensorflow::internal::LogMessageFatal
("tensorflow/python/eager/pywrap_tensor.cc", 79) << *(_result
.str_)
;
80 return ret;
81}
82} // namespace tensorflow
83namespace {
84
85using tensorflow::TFE_TensorHandleToNumpy;
86
87// An instance of _EagerTensorProfiler that will receive callbacks about
88// events on eager tensors. This is set by TFE_Py_InitEagerTensor, if at all.
89PyObject* eager_tensor_profiler = nullptr;
90
91// Read-only dict. Please don't use this in any setting where the dict might
92// actually get mutated. This is only used to pass empty kwargs when creating a
93// new EagerTensor.
94PyObject* EmptyDict() {
95 static PyObject* empty_dict = PyDict_New();
96 return empty_dict;
97}
98
99PyObject* EmptyTuple() {
100 static PyObject* empty_tuple = PyTuple_New(0);
101 return empty_tuple;
102}
103
104TFE_Context* GetContextHandle(PyObject* py_context) {
105 tensorflow::Safe_PyObjectPtr py_context_handle(
106 PyObject_GetAttrString(py_context, "_handle"));
107 if (py_context_handle == nullptr) {
108 // Current Python code makes sure this never happens. If it does, or
109 // becomes hard to maintain, we can call the ensure_initialized() method
110 // here.
111 PyErr_SetString(
112 PyExc_TypeError,
113 "Expected `context` argument in EagerTensor constructor to have a "
114 "`_handle` attribute but it did not. Was eager Context initialized?");
115 return nullptr;
116 }
117
118 auto* ctx = reinterpret_cast<TFE_Context*>(
119 PyCapsule_GetPointer(py_context_handle.get(), nullptr));
120 if (ctx == nullptr) {
121 PyErr_SetString(PyExc_TypeError,
122 tensorflow::strings::StrCat(
123 "Expected context._handle to contain a PyCapsule "
124 "encoded pointer to TFE_Context. Got ",
125 Py_TYPE(py_context_handle.get())(((PyObject*)(py_context_handle.get()))->ob_type)->tp_name)
126 .c_str());
127 }
128 return ctx;
129}
130
131
132// Helper function to convert `v` to a tensorflow::DataType and store it in
133// `*out`. Returns true on success, false otherwise.
134// Note that we assume that v is a python int (not long) representing a
135// TF_DataType/tensorflow::DataType value.
136bool PyIntToDataType(PyObject* v, tensorflow::DataType* out) {
137#if PY_MAJOR_VERSION3 < 3
138 if (PyInt_Check(v)) {
139 *out = static_cast<tensorflow::DataType>(PyInt_AS_LONG(v));
140 return true;
141 }
142#else
143 if (PyLong_Check(v)((((((PyObject*)(v))->ob_type))->tp_flags & ((1UL <<
24))) != 0)
) {
144 *out = static_cast<tensorflow::DataType>(PyLong_AsLong(v));
145 return true;
146 }
147#endif
148 return false;
149}
150
151// Helper function to create a python integer from TF_DataType.
152PyObject* PyIntFromDataType(TF_DataType l) {
153#if PY_MAJOR_VERSION3 < 3
154 return PyInt_FromLong(l);
155#else
156 return PyLong_FromLong(l);
157#endif
158}
159
160// PyObject->tensorflow::DataType conversion function to be used with
161// PyArg_Parse* APIs.
162int ConvertDataType(PyObject* obj, tensorflow::DataType* dst) {
163 if (obj == Py_None(&_Py_NoneStruct)) {
164 *dst = tensorflow::DataType::DT_INVALID;
165 } else if (!PyIntToDataType(obj, dst)) {
166 PyErr_SetString(
167 PyExc_TypeError,
168 tensorflow::strings::StrCat(
169 "Expecting a DataType value for dtype. Got ", Py_TYPE(obj)(((PyObject*)(obj))->ob_type)->tp_name)
170 .c_str());
171 return 0;
172 }
173
174 return 1;
175}
176
177// Conversion function extracting a const char** device name from a PyObject.
178// The function should be used with PyArg_Parse* APIs.
179int ConvertDeviceName(PyObject* obj, const char** dst) {
180 if (obj == Py_None(&_Py_NoneStruct)) {
181 *dst = nullptr;
182 } else {
183 auto device_name = TFE_GetPythonString(obj);
184 if (device_name == nullptr) {
185 PyErr_Clear();
186 PyErr_SetString(PyExc_TypeError, "Error parsing device argument.");
187 return 0;
188 }
189 *dst = device_name;
190 }
191
192 return 1;
193}
194
195void RaiseExceptionTypeFromTFStatus(TF_Status* tf_status) {
196 auto status = tensorflow::StatusFromTF_Status(tf_status);
197 SetRegisteredErrFromStatus(status);
198}
199
200} // namespace
201
202namespace tensorflow {
203// This function checks whether the desired type is "compatible" with the
204// inferred type. At a high level, compatibility means that all integral types
205// are compatible with each other, and all floating types are compatible with
206// each other.
207//
208// Type compatibility doesn't consider overflows (i.e. int64 is *always*
209// compatible with int32). This is intended to match graph behavior.
210bool IsCompatible(DataType desired, DataType returned) {
211 if (desired == returned) return true;
212
213 if (DataTypeIsInteger(desired) && DataTypeIsInteger(returned)) {
214 return true;
215 } else if (DataTypeIsFloating(desired) &&
216 (DataTypeIsFloating(returned) || DataTypeIsInteger(returned))) {
217 return true;
218 } else if (DataTypeIsComplex(desired) &&
219 (DataTypeIsComplex(returned) || DataTypeIsInteger(returned) ||
220 DataTypeIsFloating(returned))) {
221 return true;
222 } else if (DataTypeIsQuantized(desired) && DataTypeIsInteger(returned)) {
223 return true;
224 }
225 return false;
226}
227
228// TODO(nareshmodi): Move EagerCast and ReadVariableOp (which use the C API to
229// execute TFE Ops) to a separate common library.
230// Casts data referred to by `handle` from type `src_type_enum` to type
231// `dst_type_enum`.
232TFE_TensorHandle* EagerCast(TFE_Context* ctx, TFE_TensorHandle* handle,
233 TF_DataType src_type_enum,
234 TF_DataType dst_type_enum, TF_Status* out_status) {
235 if (ctx == nullptr) return nullptr;
236 const char* op_name = "Cast";
237 const char* device_name = "/device:CPU:0";
238 TFE_Op* op = TFE_NewOp(ctx, op_name, out_status);
239#define RETURN_ERROR \
240 { \
241 TFE_DeleteOp(op); \
242 return nullptr; \
243 }
244 if (!out_status->status.ok()) RETURN_ERROR
245 TFE_OpSetDevice(op, device_name, out_status);
246 if (!out_status->status.ok()) RETURN_ERROR
247 TFE_OpAddInput(op, handle, out_status);
248 if (!out_status->status.ok()) RETURN_ERROR
249 TFE_OpSetAttrType(op, "SrcT", src_type_enum);
250 TFE_OpSetAttrType(op, "DstT", dst_type_enum);
251 TFE_OpSetAttrBool(op, "Truncate", false);
252 TFE_TensorHandle* output = nullptr;
253 int num_outputs = 1;
254 TFE_Execute(op, &output, &num_outputs, out_status);
255 if (!out_status->status.ok() || num_outputs != 1 || output == nullptr) {
256 if (output != nullptr) {
257 TFE_DeleteTensorHandle(output);
258 }
259 RETURN_ERROR
260 }
261 TFE_DeleteOp(op);
262 return output;
263#undef RETURN_ERROR
264}
265
266Safe_TFE_TensorHandlePtr EagerConst(TFE_Context* ctx, TFE_TensorHandle* handle,
267 const char* device_name,
268 TF_Status* out_status) {
269 const char* op_name = "_EagerConst";
270 std::unique_ptr<TFE_Op, decltype(&TFE_DeleteOp)> op(
271 TFE_NewOp(ctx, op_name, out_status), TFE_DeleteOp);
272 if (!out_status->status.ok()) return nullptr;
273 TFE_OpSetDevice(op.get(), device_name, out_status);
274 if (!out_status->status.ok()) return nullptr;
275 TFE_OpAddInput(op.get(), handle, out_status);
276 if (!out_status->status.ok()) return nullptr;
277 TFE_OpSetAttrType(op.get(), "T", TFE_TensorHandleDataType(handle));
278 TFE_TensorHandle* output = nullptr;
279 int num_outputs = 1;
280 TFE_Execute(op.get(), &output, &num_outputs, out_status);
281 Safe_TFE_TensorHandlePtr result(output);
282 if (!out_status->status.ok() || num_outputs != 1) {
283 return nullptr;
284 }
285 return result;
286}
287
288TFE_TensorHandle* ConvertToEagerTensorUncached(TFE_Context* ctx,
289 PyObject* value,
290 tensorflow::DataType dtype,
291 const char* device_name) {
292 tensorflow::Safe_PyObjectPtr value_decrefer;
293 if (PyArray_IsScalar(value, Generic)(((((PyObject*)(value))->ob_type) == (&(*(PyTypeObject
*)_tensorflow_numpy_api[10])) || PyType_IsSubtype((((PyObject
*)(value))->ob_type), (&(*(PyTypeObject *)_tensorflow_numpy_api
[10])))))
) {
294 // Convert numpy scalars to numpy arrays.
295 value = PyArray_FromScalar(*(PyObject * (*)(PyObject *, PyArray_Descr *)) _tensorflow_numpy_api
[61])
(value, nullptr);
296 // The returned value needs to be DECREF'd, but the original value was
297 // created in python code, and doesn't need to be DECREF'd.
298 value_decrefer.reset(value);
299 }
300
301 Safe_TFE_TensorHandlePtr handle =
302 make_safe(PySeqToTFE_TensorHandle(ctx, value, dtype));
303
304 if (handle == nullptr) return nullptr;
305
306 Safe_TF_StatusPtr status = make_safe(TF_NewStatus());
307 TF_DataType handle_dtype = TFE_TensorHandleDataType(handle.get());
308 if (dtype != tensorflow::DT_INVALID &&
309 dtype != static_cast<DataType>(handle_dtype)) {
310 if (tensorflow::IsCompatible(dtype, static_cast<DataType>(handle_dtype))) {
311 handle = tensorflow::make_safe(
312 tensorflow::EagerCast(ctx, handle.get(), handle_dtype,
313 static_cast<TF_DataType>(dtype), status.get()));
314 if (!status->status.ok()) {
315 PyErr_SetString(PyExc_TypeError,
316 absl::StrCat("Error while casting from dtype ",
317 tensorflow::DataTypeString(
318 static_cast<DataType>(handle_dtype)),
319 " to ", tensorflow::DataTypeString(dtype),
320 ". ", TF_Message(status.get()))
321 .c_str());
322 return nullptr;
323 }
324 } else {
325 tensorflow::Safe_PyObjectPtr value_str(PyObject_Repr(value));
326 PyErr_SetString(
327 PyExc_TypeError,
328 absl::StrCat("Cannot convert ", TFE_GetPythonString(value_str.get()),
329 " to EagerTensor of dtype ",
330 tensorflow::DataTypeString(dtype))
331 .c_str());
332 return nullptr;
333 }
334 }
335
336 // We always initially generate CPU:0 tensors. Copy to the current device.
337 if (device_name != nullptr) {
338 if (strstr(device_name, "/device:CPU:0") != nullptr) {
339 // We always generate CPU:0 tensors, but we may need to change the device
340 // slightly, as for example from /job:localhost/... to /job:worker/...
341 //
342 // Note that this is a shallow copy and will share the underlying buffer,
343 // because we are copying to the same device.
344 handle = make_safe(TFE_TensorHandleCopyToDevice(
345 handle.get(), ctx, device_name, status.get()));
346 const TF_Code code = TF_GetCode(status.get());
347 if (code != TF_OK) {
348 RaiseExceptionTypeFromTFStatus(status.get());
349 return nullptr;
350 }
351 } else {
352 /*Copy the constant to the current device. Identity is sometimes
353 overloaded to allow copies like this, but using a different op allows
354 devices to support constant creation without allowing copies via
355 identity ops.
356
357 Note that running this _EagerConst op limits mirroring of cached Python
358 literals somewhat. Mirroring of constants themselves works:
359
360 with tf.device("GPU:0"):
361 tf.constant(1.) # Cached on CPU:0, mirrored to GPU:0
362 with tf.device("GPU:1"):
363 tf.constant(1.) # Cache hit for the CPU version, new mirror to GPU:1.
364 with tf.device("GPU:1"):
365 tf.constant(1.) # Cache hit for the CPU version, cached mirror
366
367 But mirrors for the output of `tf.constant` are not shared just because
368 there was a cache hit for the input literal, because of _EagerConst:
369
370 x = tf.constant(2.) # Cached on CPU:0
371 with tf.device("GPU:1"):
372 tf.identity(x) # `x` now mirrored to GPU:1
373 y = tf.constant(2.) # Cache hit for CPU version
374 with tf.device("GPU:1"):
375 tf.identity(y) # `y` now mirrored on GPU:1 (new copy!)*/
376 handle =
377 tensorflow::EagerConst(ctx, handle.get(), device_name, status.get());
378 const TF_Code code = TF_GetCode(status.get());
379 if (code != TF_OK) {
380 RaiseExceptionTypeFromTFStatus(status.get());
381 return nullptr;
382 }
383 }
384 }
385
386 return handle.release();
387}
388
389TFE_TensorHandle* ConvertToEagerTensor(TFE_Context* ctx, PyObject* value,
390 DataType dtype,
391 const char* device_name) {
392 // Reduce the overhead of allocation/transfer-to-device for scalars by
393 // caching the corresponding handles. Note that currently only Python
394 // scalars are cached.
395 // TODO(slebedev): also cache singleton NumPy arrays and scalars?
396 if (PyArray_IsPythonNumber(value)(((((PyObject*)(value))->ob_type) == (&PyFloat_Type) ||
PyType_IsSubtype((((PyObject*)(value))->ob_type), (&PyFloat_Type
))) || ((((PyObject*)(value))->ob_type) == (&PyComplex_Type
) || PyType_IsSubtype((((PyObject*)(value))->ob_type), (&
PyComplex_Type))) || ((((((PyObject*)(value))->ob_type))->
tp_flags & ((1UL << 24))) != 0) || ((((PyObject*)(value
))->ob_type) == &PyBool_Type))
) {
397 auto* cache = TFE_TensorHandleCache::Get();
398 TFE_TensorHandle* handle = cache->Lookup(value, dtype, ctx, device_name);
399 if (handle != nullptr) return handle;
400 handle = ConvertToEagerTensorUncached(ctx, value, dtype, device_name);
401 if (handle == nullptr) return nullptr;
402 if (!PyFloat_Check(value)((((PyObject*)(value))->ob_type) == (&PyFloat_Type) ||
PyType_IsSubtype((((PyObject*)(value))->ob_type), (&PyFloat_Type
)))
|| std::isfinite(PyFloat_AS_DOUBLE(value)(((PyFloatObject *)(value))->ob_fval))) {
403 cache->Insert(value, dtype, ctx, device_name, handle);
404 }
405 return handle;
406 } else {
407 return ConvertToEagerTensorUncached(ctx, value, dtype, device_name);
408 }
409}
410
411} // namespace tensorflow
412
413extern "C" {
414
415static const int kMaxEagerTensorParentSize = 64;
416
417// TODO(agarwal): store context handle in EagerTensor.
418typedef struct EagerTensor {
419 PyObject_HEADPyObject ob_base;;
420 // Note that we leave kMaxEagerTensorParentSize bytes here for use by the
421 // parent class. The parent class is set at runtime, so we don't know the
422 // exact size at compile time.
423 char unused[kMaxEagerTensorParentSize];
424 TFE_TensorHandle* handle;
425 int64_t id;
426 // Indicates whether it's a packed tensor or not.
427 bool is_packed;
428 // This mirrors tensorflow.core.framework.ops.Tensor._handle_data Which will
429 // be None for tensors of type other than DT_RESOURCE. For DT_RESOURCE
430 // tensors, this will contain a serialized HandleData proto with shape
431 // inference metadata about shapes and dtypes of resources accessible from
432 // this handle.
433 // Note that we assume that handle_data cannot participate in reference
434 // cycles, and hence don't provide GC support for it.
435 PyObject* handle_data;
436
437 // This stores `_tensor_shape`, a cached `TensorShape` object, and is set the
438 // first time that `_EagerTensorBase`'s `shape` property is called.
439 PyObject* tensor_shape;
440
441 // We store a status object here as an optimization to avoid allocating a new
442 // Status objects on different functions that operate on EagerTensor and need
443 // to use a TF_Status object. However note that accesses to `status` are not
444 // thread-safe.
445 TF_Status status;
446
447 // The eager Context (from eager/context.py) used by this Tensor.
448 // This is currently used only to make sure context outlives TensorHandles.
449 PyObject* context;
450
451 PyObject* weakreflist; /* List of weak references */
452
453 // Per-instance attribute dictionary, to support monkey patching
454 // (e.g. EagerTensor.assign when slicing variables). This dictionary is
455 // created by CPython the first time an attribute is assigned, pointed to by
456 // tp_dictoffset. Note that garbage collection is not enabled for
457 // EagerTensors, so assigning objects to EagerTensor attributes which require
458 // garbage collection is likely to cause issues.
459 PyObject* dict;
460} EagerTensor;
461
462namespace {
463
464// Returns true on success - successfully invoked or no profiler registered.
465// Returns false if some error occurred.
466bool MaybeInvokeCreatedOnEagerTensorProfiler(EagerTensor* created_tensor) {
467 if (eager_tensor_profiler != nullptr) {
468#if PY_MAJOR_VERSION3 < 3
469 PyObject* created_method_name = PyString_InternFromString("created");
470#else
471 PyObject* created_method_name = PyUnicode_InternFromString("created");
472#endif
473 if (created_method_name == nullptr) {
474 return false;
475 }
476 PyObject* result = PyObject_CallMethodObjArgs(
477 eager_tensor_profiler, created_method_name, created_tensor, NULL__null);
478 if (result == nullptr) {
479 LOG(ERROR)::tensorflow::internal::LogMessage("tensorflow/python/eager/pywrap_tensor.cc"
, 479, ::tensorflow::ERROR)
<< "Invoking created() on EagerTensor profiler failed";
480 // While we can potentially continue because the error is related to
481 // profiling, we choose to return an error because:
482 // - If profiling is used, the user likely wants to stop execution on
483 // profiling errors.
484 // - Error in profiling code might have left some state in an invalid
485 // form that can lead to an error later on. Better to fail fast.
486 Py_DECREF(created_method_name)_Py_DECREF(((PyObject*)(created_method_name)));
487 return false;
488 }
489 Py_DECREF(created_method_name)_Py_DECREF(((PyObject*)(created_method_name)));
490 Py_DECREF(result)_Py_DECREF(((PyObject*)(result)));
491 }
492 return true;
493}
494
495} // namespace
496
497// tp_init for EagerTensor.
498int EagerTensor_init(EagerTensor* self, PyObject* args, PyObject* kwds) {
499 self->id = get_uid();
500 self->handle = nullptr;
501 self->is_packed = false;
502 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
503 self->handle_data = Py_None(&_Py_NoneStruct);
504 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
505 self->tensor_shape = Py_None(&_Py_NoneStruct);
506 self->status.status = tensorflow::Status::OK();
507 self->dict = nullptr;
508 self->weakreflist = nullptr;
509 self->context = nullptr;
510 PyObject* value;
511 const char* device_name = nullptr;
512 tensorflow::DataType dtype = tensorflow::DataType::DT_INVALID;
513 const char* kwlist[] = {"value", "device", "dtype", nullptr};
514 if (!PyArg_ParseTupleAndKeywords(
515 args, kwds, "OO&|O&", const_cast<char**>(kwlist), &value,
516 ConvertDeviceName, &device_name, ConvertDataType, &dtype)) {
517 return -1;
518 }
519
520 PyObject* py_context = GetPyEagerContext();
521 if (py_context == nullptr) return -1;
522 self->context = py_context;
523
524 auto* handle = tensorflow::ConvertToEagerTensor(GetContextHandle(py_context),
525 value, dtype, device_name);
526 if (handle == nullptr) return -1;
527 self->handle = handle;
528
529 if (!MaybeInvokeCreatedOnEagerTensorProfiler(self)) {
530 return -1;
531 }
532
533 return 0;
534}
535
536// tp_dealloc for EagerTensor.
537void EagerTensor_dealloc(EagerTensor* self) {
538 // Unhook the object from python's GC so that the weakref deleter doesn't
539 // try to re-delete this.
540 PyObject_GC_UnTrack((PyObject*)self);
541
542 // Clear weak references to self.
543 // Needs to happen before any actual destruction.
544 PyObject_ClearWeakRefs((PyObject*)self);
545
546 Py_DECREF(self->handle_data)_Py_DECREF(((PyObject*)(self->handle_data)));
547 Py_DECREF(self->tensor_shape)_Py_DECREF(((PyObject*)(self->tensor_shape)));
548 // If an attribute dictionary has been created, release it. Note that this
549 // is only ever created by CPython's attribute setting methods; we don't
550 // create it ourselves.
551 Py_CLEAR(self->dict)do { PyObject *_py_tmp = ((PyObject*)(self->dict)); if (_py_tmp
!= __null) { (self->dict) = __null; _Py_DECREF(((PyObject
*)(_py_tmp))); } } while (0)
;
552 if (self->handle != nullptr) {
553 // Destructor may call arbitrary functions that end up calling into
554 // Python from another thread.
555 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();;
556 TFE_DeleteTensorHandle(self->handle);
557 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); };
558 self->handle = nullptr;
559 }
560
561 // Decref context after deleting the tensor handle.
562 Py_XDECREF(self->context)_Py_XDECREF(((PyObject*)(self->context)));
563
564 // We have the global interpreter lock, so use this chance to perform delayed
565 // refcount decrements.
566 tensorflow::ClearDecrefCache();
567 auto id = self->id;
568 Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free(self);
569 TFE_Py_TapeSetDeleteTrace(id);
570}
571
572// Getter for `_id`.
573static PyObject* EagerTensor_getid(EagerTensor* self, void* closure) {
574 return PyLong_FromLongLong(self->id);
575}
576
577// Getter for `_datatype_enum`.
578static PyObject* EagerTensor_datatype_enum(EagerTensor* self) {
579 return PyIntFromDataType(TFE_TensorHandleDataType(self->handle));
580}
581
582// Getter for `_shape_tuple`.
583static PyObject* EagerTensor_shape_tuple(EagerTensor* self) {
584 auto handle = self->handle;
585 int n = TFE_TensorHandleNumDims(handle, &self->status);
586 TF_Code code = TF_GetCode(&self->status);
587 if (code != TF_OK) {
588 RaiseExceptionTypeFromTFStatus(&self->status);
589 // Cleanup self->status before returning.
590 self->status.status = tensorflow::Status::OK();
591 return nullptr;
592 }
593 PyObject* shape = PyTuple_New(n);
594 if (PyErr_Occurred()) return nullptr;
595 for (int i = 0; i < n; ++i) {
596 int64_t dim_c_value = TFE_TensorHandleDim(handle, i, &self->status);
597 PyObject* dim;
598 // The C++ convention is -1 for unknown/variable axis lengths. Translate
599 // that to the Python "None" convention. Unknown axis lengths are unusual
600 // for eager tensors.
601 if (dim_c_value < 0) {
602 Py_IncRef(Py_None(&_Py_NoneStruct));
603 dim = Py_None(&_Py_NoneStruct);
604 } else {
605 dim = PyLong_FromLongLong(dim_c_value);
606 }
607 code = TF_GetCode(&self->status);
608 if (code != TF_OK || dim == nullptr ||
609 PyTuple_SetItem(shape, i, dim) != 0) {
610 if (code != TF_OK) {
611 RaiseExceptionTypeFromTFStatus(&self->status);
612 } else {
613 PyErr_SetString(PyExc_RuntimeError, "Error while creating shape");
614 }
615 // Cleanup self->status before returning.
616 self->status.status = tensorflow::Status::OK();
617 Py_DECREF(shape)_Py_DECREF(((PyObject*)(shape)));
618 if (dim != nullptr) Py_DECREF(dim)_Py_DECREF(((PyObject*)(dim)));
619 return nullptr;
620 }
621 }
622 return shape;
623}
624
625// Getter for `_rank`.
626static PyObject* EagerTensor_rank(EagerTensor* self) {
627 int num_dims = TFE_TensorHandleNumDims(self->handle, &self->status);
628 if (MaybeRaiseExceptionFromTFStatus(&self->status, nullptr)) {
629 // Cleanup self->status before returning.
630 self->status.status = tensorflow::Status::OK();
631 return nullptr;
632 }
633#if PY_MAJOR_VERSION3 < 3
634 return PyInt_FromLong(num_dims);
635#else
636 return PyLong_FromLong(num_dims);
637#endif
638}
639
640// Getter for `_num_elements`.
641static PyObject* EagerTensor_num_elements(EagerTensor* self) {
642 auto handle = self->handle;
643 int n = TFE_TensorHandleNumElements(handle, &self->status);
644 if (MaybeRaiseExceptionFromTFStatus(&self->status, nullptr)) {
645 // Cleanup self->status before returning.
646 self->status.status = tensorflow::Status::OK();
647 return nullptr;
648 }
649 return PyLong_FromLongLong(n);
650}
651
652static PyObject* EagerTensor_handle_data(EagerTensor* self, void* unused) {
653 Py_INCREF(self->handle_data)_Py_INCREF(((PyObject*)(self->handle_data)));
654 return self->handle_data;
655}
656
657static int EagerTensor_sethandle_data(EagerTensor* self, PyObject* value,
658 void* unused) {
659 Py_DECREF(self->handle_data)_Py_DECREF(((PyObject*)(self->handle_data)));
660 Py_INCREF(value)_Py_INCREF(((PyObject*)(value)));
661 self->handle_data = value;
662 return 0;
663}
664
665static PyObject* EagerTensor_tensor_shape(EagerTensor* self, void* unused) {
666 Py_INCREF(self->tensor_shape)_Py_INCREF(((PyObject*)(self->tensor_shape)));
667 return self->tensor_shape;
668}
669
670static int EagerTensor_settensor_shape(EagerTensor* self, PyObject* value,
671 void* unused) {
672 Py_DECREF(self->tensor_shape)_Py_DECREF(((PyObject*)(self->tensor_shape)));
673 Py_INCREF(value)_Py_INCREF(((PyObject*)(value)));
674 self->tensor_shape = value;
675 return 0;
676}
677
678// Function `_copy_to_device`.
679static PyObject* EagerTensor_copy_to_device(EagerTensor* self, PyObject* args,
680 PyObject* kwds) {
681 if (!_PyArg_NoKeywords("copy_to_device", kwds)((kwds) == __null || _PyArg_NoKeywords(("copy_to_device"), (kwds
)))
) return nullptr;
682
683 const char* device_name = nullptr;
684 if (!PyArg_ParseTuple(args, "O&:copy_to_device", ConvertDeviceName,
685 &device_name)) {
686 return nullptr;
687 }
688
689 // Note that this is a shallow copy and will share the underlying buffer
690 // if copying to the same device.
691 TFE_TensorHandle* handle = TFE_TensorHandleCopyToDevice(
692 self->handle, GetContextHandle(self->context), device_name,
693 &self->status);
694 if (MaybeRaiseExceptionFromTFStatus(&self->status, PyExc_RuntimeError)) {
695 // Cleanup self->status before returning.
696 self->status.status = tensorflow::Status::OK();
697 return nullptr;
698 }
699
700 return EagerTensorFromHandle(handle);
701}
702
703// Function `_numpy_internal`.
704// Convert an EagerTensor to a Python numpy.ndarray object.
705// The two may share underlying storage so changes to one may reflect in the
706// other.
707// Note that if `self` is not on CPU, we raise an Exception.
708static PyObject* EagerTensor_numpy_internal(EagerTensor* self) {
709 auto* py_array = TFE_TensorHandleToNumpy(self->handle, &self->status);
710 if (MaybeRaiseExceptionFromTFStatus(&self->status, nullptr)) {
711 Py_XDECREF(py_array)_Py_XDECREF(((PyObject*)(py_array)));
712 // Cleanup self->status before returning.
713 self->status.status = tensorflow::Status::OK();
714 return nullptr;
715 } else {
716 return PyArray_Return(*(PyObject * (*)(PyArrayObject *)) _tensorflow_numpy_api[76]
)
(reinterpret_cast<PyArrayObject*>(py_array));
717 }
718}
719
720// Function `_prefer_custom_summarizer`.
721//
722// A hint that callers should prefer `SummarizeValue` to resolving this handle
723// and formatting the tensor.
724static PyObject* EagerTensor_prefer_custom_summarizer(EagerTensor* self) {
725 if (tensorflow::unwrap(self->handle)->PreferCustomSummarizer()) {
726 Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct
)))), ((PyObject *) &_Py_TrueStruct)
;
727 } else {
728 Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct
)))), ((PyObject *) &_Py_FalseStruct)
;
729 }
730}
731
732// Function `_summarize_value`.
733//
734// Returns a string PyObject which summarizes the value of this tensor. It does
735// not include a shape or dtype.
736static PyObject* EagerTensor_summarize_value(EagerTensor* self) {
737 std::string summary;
738 tensorflow::Status status =
739 tensorflow::unwrap(self->handle)->SummarizeValue(summary);
740 if (MaybeRaiseExceptionFromStatus(status, nullptr)) {
741 return nullptr;
742 }
743 return PyUnicode_FromString(summary.c_str());
744}
745
746// Getter `device`.
747static PyObject* EagerTensor_device(EagerTensor* self) {
748 const char* device = TFE_TensorHandleDeviceName(self->handle, &self->status);
749 if (MaybeRaiseExceptionFromTFStatus(&self->status, PyExc_ValueError)) {
750 // Cleanup self->status before returning.
751 self->status.status = tensorflow::Status::OK();
752 return nullptr;
753 }
754#if PY_MAJOR_VERSION3 >= 3
755 return PyUnicode_FromString(device);
756#else
757 return PyBytes_FromString(device);
758#endif
759}
760
761// Getter `backing_device`.
762static PyObject* EagerTensor_backing_device(EagerTensor* self) {
763 const char* device =
764 TFE_TensorHandleBackingDeviceName(self->handle, &self->status);
765 if (MaybeRaiseExceptionFromTFStatus(&self->status, PyExc_ValueError)) {
766 // Cleanup self->status before returning.
767 self->status.status = tensorflow::Status::OK();
768 return nullptr;
769 }
770#if PY_MAJOR_VERSION3 >= 3
771 return PyUnicode_FromString(device);
772#else
773 return PyBytes_FromString(device);
774#endif
775}
776
777// Getter `is_packed`.
778static PyObject* EagerTensor_is_packed(EagerTensor* self) {
779 return PyBool_FromLong(self->is_packed);
780}
781
782static PyGetSetDef EagerTensor_getsetters[] = {
783 {const_cast<char*>("_id"), (getter)EagerTensor_getid, nullptr,
784 const_cast<char*>("Tensor ID."), nullptr},
785 {const_cast<char*>("device"), (getter)EagerTensor_device, nullptr,
786 const_cast<char*>("Device of op that produced the tensor."), nullptr},
787 {const_cast<char*>("backing_device"), (getter)EagerTensor_backing_device,
788 nullptr, const_cast<char*>("Device on which tensor's memory is resident."),
789 nullptr},
790 {const_cast<char*>("is_packed"), (getter)EagerTensor_is_packed, nullptr,
791 const_cast<char*>("Whether the EagerTensor is a packed tensor or not."),
792 nullptr},
793 {const_cast<char*>("_handle_data"), (getter)EagerTensor_handle_data,
794 (setter)EagerTensor_sethandle_data,
795 const_cast<char*>("Shape/DType data if the EagerTensor is a DT_RESOURCE"),
796 nullptr},
797 {const_cast<char*>("_tensor_shape"), (getter)EagerTensor_tensor_shape,
798 (setter)EagerTensor_settensor_shape,
799 const_cast<char*>("Shape of the tensor."), nullptr},
800 {nullptr} /* Sentinel */
801};
802
803#if PY_MAJOR_VERSION3 < 3
804// Only used for Python2 since Python3 seems to set the __dict__ correctly.
805static PyMemberDef EagerTensor_members[] = {
806 {const_cast<char*>("__dict__"), T_OBJECT6, offsetof(EagerTensor, dict)__builtin_offsetof(EagerTensor, dict),
807 READONLY1},
808 {nullptr},
809};
810#endif
811
812static PyMethodDef EagerTensor_methods[] = {
813 {"_numpy_internal", (PyCFunction)EagerTensor_numpy_internal, METH_NOARGS0x0004,
814 PyDoc_STR("Internal method to get a NumPy array for the tensor.")"Internal method to get a NumPy array for the tensor."},
815 {"_datatype_enum", (PyCFunction)EagerTensor_datatype_enum, METH_NOARGS0x0004,
816 PyDoc_STR("The DType of the tensor as an enum.")"The DType of the tensor as an enum."},
817 {"_shape_tuple", (PyCFunction)EagerTensor_shape_tuple, METH_NOARGS0x0004,
818 PyDoc_STR("The shape of the tensor as a python tuple.")"The shape of the tensor as a python tuple."},
819 {"_rank", (PyCFunction)EagerTensor_rank, METH_NOARGS0x0004,
820 PyDoc_STR("The rank of the tensor.")"The rank of the tensor."},
821 {"_copy_to_device", (PyCFunction)EagerTensor_copy_to_device,
822 METH_VARARGS0x0001 | METH_KEYWORDS0x0002,
823 PyDoc_STR("Copies the tensor to the desired device.")"Copies the tensor to the desired device."},
824 {"_num_elements", (PyCFunction)EagerTensor_num_elements, METH_NOARGS0x0004,
825 PyDoc_STR("Number of elements in the tensor.")"Number of elements in the tensor."},
826 {"_prefer_custom_summarizer",
827 (PyCFunction)EagerTensor_prefer_custom_summarizer, METH_NOARGS0x0004,
828 PyDoc_STR("Indicates whether _numpy_internal loses information.")"Indicates whether _numpy_internal loses information."},
829 {"_summarize_value", (PyCFunction)EagerTensor_summarize_value, METH_NOARGS0x0004,
830 PyDoc_STR("A string which summarizes the value of this tensor.")"A string which summarizes the value of this tensor."},
831 {nullptr, nullptr},
832};
833
834static int EagerTensor_getbuffer(EagerTensor* self, Py_buffer* view,
835 int flags) {
836 if ((flags & PyBUF_WRITABLE0x0001) == PyBUF_WRITABLE0x0001) {
837 PyErr_SetString(PyExc_BufferError, "EagerTensor is not writable.");
838 return -1;
839 }
840
841 // TensorHandleToNumpy is zero-copy for everything but DT_RESOURCE and
842 // DT_STRING so the following is only slightly slower than a NumPy-free
843 // implementation.
844 auto py_array = tensorflow::make_safe(
845 TFE_TensorHandleToNumpy(self->handle, &self->status));
846 if (MaybeRaiseExceptionFromTFStatus(&self->status, PyExc_BufferError)) {
847 // Cleanup self->status before returning.
848 self->status.status = tensorflow::Status::OK();
849 return -1;
850 }
851 if (PyObject_GetBuffer(py_array.get(), view, flags) < 0) {
852 return -1;
853 }
854 view->readonly = 1;
855 return 0;
856}
857
858static PyBufferProcs EagerTensor_as_buffer = {
859#if PY_MAJOR_VERSION3 < 3
860 nullptr, nullptr, nullptr, nullptr,
861#endif
862 (getbufferproc)EagerTensor_getbuffer,
863 // Never called because getbufferproc delegates to NumPy.
864 (releasebufferproc) nullptr};
865
866// Note that here we are trying to dynamically create a new class as a subclass
867// of a "HEAPTYPE" class that is itself created in python code and passed in at
868// runtime. This is fairly atypical and undocumented.
869//
870// We use the following strategy for this. Unfortunately, we have to use
871// different approaches for python2.x vs python3.x
872// For python2.x, we create the class as a static type and set its tp_base to
873// the passed in type. Unfortunately setting tp_flags to include
874// Py_TPFLAGS_HEAPTYPE does not work by itself since it needs some more
875// initialization of the underlying PyHeapTypeObject and not doing that leads to
876// some random crashes especially during garbage collection.
877// python3.x explicitly disables a static subclass of a HEAPTYPE base class.
878// However it provides a new function, PyType_FromSpecWithBases, to create
879// types dynamically.
880
881// Type object for EagerTensor. This is set by TFE_Py_InitEagerTensor.
882PyTypeObject* EagerTensorType = nullptr;
883
884#if PY_MAJOR_VERSION3 >= 3
885static PyType_Slot EagerTensor_Type_slots[] = {
886 {Py_tp_dealloc52, reinterpret_cast<void*>(EagerTensor_dealloc)},
887 {Py_tp_methods64, reinterpret_cast<void*>(EagerTensor_methods)},
888 {Py_tp_getset73, reinterpret_cast<void*>(EagerTensor_getsetters)},
889 {Py_tp_init60, reinterpret_cast<void*>(EagerTensor_init)},
890 {0, nullptr},
891};
892#else
893
894#define EAGER_TENSOR_TPFLAGS (Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0) | Py_TPFLAGS_HAVE_NEWBUFFER)
895
896// TODO(agarwal): support active_trace.
897static PyTypeObject _EagerTensorType = {
898 // clang-format off
899 PyVarObject_HEAD_INIT(nullptr, 0){ { 1, nullptr }, 0 },
900 // clang-format on
901 "EagerTensor", /* tp_name */
902 sizeof(EagerTensor), /* tp_basicsize */
903 0, /* tp_itemsize */
904 (destructor)EagerTensor_dealloc, /* tp_dealloc */
905#if PY_VERSION_HEX((3 << 24) | (8 << 16) | (5 << 8) | (0xF <<
4) | (0 << 0))
< 0x03080000
906 nullptr, /* tp_print */
907#else
908 0, /* tp_vectorcall_offset */
909#endif
910 nullptr, /* tp_getattr */
911 nullptr, /* tp_setattr */
912 nullptr, /* tp_compare */
913 nullptr, /* tp_repr */
914 nullptr, /* tp_as_number */
915 nullptr, /* tp_as_sequence */
916 nullptr, /* tp_as_mapping */
917 nullptr, /* tp_hash */
918 nullptr, /* tp_call */
919 nullptr, /* tp_str */
920 nullptr, /* tp_getattro */
921 nullptr, /* tp_setattro */
922 &EagerTensor_as_buffer, /* tp_as_buffer */
923 EAGER_TENSOR_TPFLAGS, /* tp_flags */
924 nullptr, /* tp_doc */
925 nullptr, /* tp_traverse */
926 nullptr, /* tp_clear */
927 nullptr, /* tp_richcompare */
928 offsetof(EagerTensor, weakreflist)__builtin_offsetof(EagerTensor, weakreflist), /* tp_weaklistoffset */
929 nullptr, /* tp_iter */
930 nullptr, /* tp_iternext */
931 EagerTensor_methods, /* tp_methods */
932 EagerTensor_members, /* tp_members */
933 EagerTensor_getsetters, /* tp_getset */
934 nullptr, /* tp_base */
935 nullptr, /* tp_dict */
936 nullptr, /* tp_descr_get */
937 nullptr, /* tp_descr_set */
938 offsetof(EagerTensor, dict)__builtin_offsetof(EagerTensor, dict), /* tp_dictoffset */
939 (initproc)EagerTensor_init, /* tp_init */
940 nullptr, /* tp_alloc */
941 nullptr, /* tp_new */
942};
943
944#endif
945
946} // extern "C"
947
948bool EagerTensor_CheckExact(const PyObject* o) {
949 return Py_TYPE(o)(((PyObject*)(o))->ob_type) == EagerTensorType;
950}
951
952TFE_TensorHandle* EagerTensor_Handle(const PyObject* o) {
953 return reinterpret_cast<const EagerTensor*>(o)->handle;
954}
955
956PyObject* EagerTensorFromHandle(TFE_TensorHandle* handle,
957 const bool is_packed) {
958 if (handle == nullptr) {
959 return nullptr;
960 }
961 EagerTensor* t = reinterpret_cast<EagerTensor*>(
962 EagerTensorType->tp_new(EagerTensorType, EmptyTuple(), EmptyDict()));
963 if (t != nullptr) {
964 t->id = get_uid();
965 t->is_packed = is_packed;
966 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
967 t->handle_data = Py_None(&_Py_NoneStruct);
968 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
969 t->tensor_shape = Py_None(&_Py_NoneStruct);
970 t->handle = handle;
971 t->status.status = tensorflow::Status::OK();
972 t->weakreflist = nullptr;
973 PyObject* py_context = GetPyEagerContext();
974 if (py_context == nullptr) {
975 LOG(ERROR)::tensorflow::internal::LogMessage("tensorflow/python/eager/pywrap_tensor.cc"
, 975, ::tensorflow::ERROR)
<< "Cannot create an eager tensor before eager context has "
976 "been set or after it has been deleted";
977 return nullptr;
978 }
979 t->context = py_context;
980
981 if (!MaybeInvokeCreatedOnEagerTensorProfiler(t)) {
982 return nullptr;
983 }
984 }
985 return reinterpret_cast<PyObject*>(t);
986}
987
988int64_t PyEagerTensor_ID(const PyObject* tensor) {
989 DCHECK(EagerTensor_CheckExact(tensor))while (false && (EagerTensor_CheckExact(tensor))) ::tensorflow
::internal::LogMessageFatal("tensorflow/python/eager/pywrap_tensor.cc"
, 989)
;
990 return reinterpret_cast<const EagerTensor*>(tensor)->id;
991}
992
993tensorflow::DataType PyEagerTensor_Dtype(const PyObject* tensor) {
994 DCHECK(EagerTensor_CheckExact(tensor))while (false && (EagerTensor_CheckExact(tensor))) ::tensorflow
::internal::LogMessageFatal("tensorflow/python/eager/pywrap_tensor.cc"
, 994)
;
995 return static_cast<tensorflow::DataType>(TFE_TensorHandleDataType(
996 reinterpret_cast<const EagerTensor*>(tensor)->handle));
997}
998
999int64_t PyEagerTensor_NumElements(PyObject* tensor) {
1000 DCHECK(EagerTensor_CheckExact(tensor))while (false && (EagerTensor_CheckExact(tensor))) ::tensorflow
::internal::LogMessageFatal("tensorflow/python/eager/pywrap_tensor.cc"
, 1000)
;
1001 EagerTensor* as_c_eager_tensor = reinterpret_cast<EagerTensor*>(tensor);
1002 int64_t result = TFE_TensorHandleNumElements(as_c_eager_tensor->handle,
1003 &as_c_eager_tensor->status);
1004
1005 if (MaybeRaiseExceptionFromTFStatus(&as_c_eager_tensor->status,
1006 PyExc_ValueError)) {
1007 // Cleanup status before returning.
1008 as_c_eager_tensor->status.status = tensorflow::Status::OK();
1009 return -1;
1010 }
1011
1012 return result;
1013}
1014
1015PyObject* TFE_Py_InitEagerTensor(PyObject* base_class) {
1016 if (!PyType_Check(base_class)((((((PyObject*)(base_class))->ob_type))->tp_flags &
((1UL << 31))) != 0)
) {
1
Assuming the condition is true
2
Taking false branch
1017 PyErr_SetString(
1018 PyExc_TypeError,
1019 tensorflow::strings::StrCat(
1020 "Expecting a class definition for `base_class` passed to ",
1021 "TFE_InitEagerTensor. Got ", Py_TYPE(base_class)(((PyObject*)(base_class))->ob_type)->tp_name)
1022 .c_str());
1023 return nullptr;
1024 }
1025 // Note that we allocated kMaxEagerTensorParentSize bytes of unused space in
1026 // EagerTensor to allow for the space usage of the base class.
1027 PyTypeObject* base_class_type = reinterpret_cast<PyTypeObject*>(base_class);
1028 if (base_class_type->tp_basicsize > kMaxEagerTensorParentSize) {
3
Assuming 'kMaxEagerTensorParentSize' is >= field 'tp_basicsize'
4
Taking false branch
1029 PyErr_SetString(
1030 PyExc_TypeError,
1031 tensorflow::strings::StrCat(
1032 "Unable to create subclass EagerTensor from base class ",
1033 Py_TYPE(base_class)(((PyObject*)(base_class))->ob_type)->tp_name,
1034 ". Need its size to be <= ", kMaxEagerTensorParentSize)
1035 .c_str());
1036 return nullptr;
1037 }
1038 if (base_class_type->tp_itemsize != 0) {
5
Assuming field 'tp_itemsize' is equal to 0
6
Taking false branch
1039 PyErr_SetString(
1040 PyExc_TypeError,
1041 tensorflow::strings::StrCat(
1042 "Unable to create subclass EagerTensor from base class ",
1043 Py_TYPE(base_class)(((PyObject*)(base_class))->ob_type)->tp_name,
1044 " which supports variable length instances.")
1045 .c_str());
1046 return nullptr;
1047 }
1048 Py_INCREF(base_class)_Py_INCREF(((PyObject*)(base_class)));
1049#if PY_MAJOR_VERSION3 >= 3
1050 PyObject* bases = PyTuple_New(1);
7
Calling 'PyTuple_New'
9
Returning from 'PyTuple_New'
12
PyObject ownership leak with reference count of 1
1051 PyTuple_SET_ITEM(bases, 0, base_class)PyTuple_SetItem(bases, 0, base_class);
1052
1053 tensorflow::Safe_PyObjectPtr base_class_module(
1054 PyObject_GetAttrString(base_class, "__module__"));
1055 const char* module = nullptr;
1056 if (PyErr_Occurred()) {
10
Assuming the condition is true
11
Taking true branch
1057 PyErr_Clear();
1058 module = "__builtin__";
1059 } else {
1060 module = PyBytes_AsString(base_class_module.get());
1061 if (module == nullptr) {
1062 PyErr_Clear();
1063 module = PyUnicode_AsUTF8(base_class_module.get());
1064 if (module == nullptr) {
1065 PyErr_Clear();
1066 module = "__builtin__";
1067 }
1068 }
1069 }
1070
1071 // NOTE: The c_str from this string needs to outlast the function, hence is
1072 // static.
1073 static tensorflow::string fully_qualified_name =
1074 tensorflow::strings::StrCat(module, ".EagerTensor");
1075
1076 static PyType_Spec EagerTensor_Type_spec = {
1077 fully_qualified_name.c_str(), sizeof(EagerTensor), 0,
1078 Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0) | Py_TPFLAGS_HEAPTYPE(1UL << 9), EagerTensor_Type_slots};
1079
1080 EagerTensorType = reinterpret_cast<PyTypeObject*>(
1081 PyType_FromSpecWithBases(&EagerTensor_Type_spec, bases));
1082 if (PyErr_Occurred()) {
1083 return nullptr;
1084 }
1085 if (EagerTensorType == nullptr) {
1086 PyErr_SetString(PyExc_RuntimeError, "Error while creating EagerTensorType");
1087 return nullptr;
1088 }
1089 EagerTensorType->tp_dictoffset = offsetof(EagerTensor, dict)__builtin_offsetof(EagerTensor, dict);
1090 EagerTensorType->tp_as_buffer = &EagerTensor_as_buffer;
1091#else
1092 _EagerTensorType.tp_base = base_class_type;
1093
1094 if (PyType_Ready(&_EagerTensorType) < 0) {
1095 if (PyErr_Occurred()) return nullptr;
1096 PyErr_SetString(PyExc_RuntimeError,
1097 "Error while creating EagerTensor type.");
1098 return nullptr;
1099 }
1100 EagerTensorType = &_EagerTensorType;
1101 Py_INCREF(EagerTensorType)_Py_INCREF(((PyObject*)(EagerTensorType)));
1102#endif
1103 return reinterpret_cast<PyObject*>(EagerTensorType);
1104}
1105
1106PyObject* TFE_Py_SetEagerTensorProfiler(PyObject* profiler) {
1107 Py_XDECREF(eager_tensor_profiler)_Py_XDECREF(((PyObject*)(eager_tensor_profiler)));
1108
1109 if (profiler == Py_None(&_Py_NoneStruct)) {
1110 eager_tensor_profiler = nullptr;
1111 } else {
1112 eager_tensor_profiler = profiler;
1113 Py_INCREF(eager_tensor_profiler)_Py_INCREF(((PyObject*)(eager_tensor_profiler)));
1114 }
1115 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
1116}
1117
1118PyObject* TFE_Py_TensorShapeSlice(PyObject* tensors, int slice_dim) {
1119 if (!PyList_Check(tensors)((((((PyObject*)(tensors))->ob_type))->tp_flags & (
(1UL << 25))) != 0)
&& !PyTuple_Check(tensors)((((((PyObject*)(tensors))->ob_type))->tp_flags & (
(1UL << 26))) != 0)
) {
1120 PyErr_SetString(PyExc_TypeError,
1121 tensorflow::strings::StrCat(
1122 "tensors argument must be a list or a tuple. Got \"",
1123 Py_TYPE(tensors)(((PyObject*)(tensors))->ob_type)->tp_name, "\"")
1124 .c_str());
1125 return nullptr;
1126 }
1127 if (slice_dim < 0) {
1128 PyErr_SetString(
1129 PyExc_ValueError,
1130 tensorflow::strings::StrCat("Slice dimension must be non-negative. "
1131 "Got ",
1132 slice_dim)
1133 .c_str());
1134 return nullptr;
1135 }
1136
1137 PyObject* py_context = GetPyEagerContext();
1138 if (py_context == nullptr) {
1139 PyErr_SetString(PyExc_RuntimeError, tensorflow::strings::StrCat(
1140 "Cannot create EagerTensor when "
1141 "EagerContext is not valid")
1142 .c_str());
1143 return nullptr;
1144 }
1145
1146 TFE_Context* ctx = GetContextHandle(py_context);
1147
1148 Py_ssize_t num_tensors = PySequence_Fast_GET_SIZE(tensors)(((((((PyObject*)(tensors))->ob_type))->tp_flags & (
(1UL << 25))) != 0) ? ((static_cast<void> (0)), (
((PyVarObject*)(tensors))->ob_size)) : (((PyVarObject*)(((
static_cast<void> (0)), (PyTupleObject *)(tensors))))->
ob_size))
;
1149 PyObject** tensors_array = PySequence_Fast_ITEMS(tensors)(((((((PyObject*)(tensors))->ob_type))->tp_flags & (
(1UL << 25))) != 0) ? ((PyListObject *)(tensors))->ob_item
: ((PyTupleObject *)(tensors))->ob_item)
;
1150 int64_t num_tensors_int = static_cast<int64_t>(num_tensors);
1151
1152 auto status = tensorflow::make_safe(TF_NewStatus());
1153
1154 // Create an empty tensor.
1155 auto* tensor = tensorflow::unwrap(ctx)->CreateTensor(
1156 tensorflow::DT_INT32, /*dim_sizes=*/{num_tensors_int});
1157
1158 if (num_tensors_int > 0) {
1159 int32_t* data = reinterpret_cast<int32_t*>(tensor->Data());
1160
1161 // Fill the tensor with dims.
1162 for (Py_ssize_t i = 0; i < num_tensors; ++i) {
1163 PyObject* tensor_obj = tensors_array[i];
1164 if (!EagerTensor_CheckExact(tensor_obj)) {
1165 PyErr_SetString(
1166 PyExc_TypeError,
1167 tensorflow::strings::StrCat("Expected a list of EagerTensors but "
1168 "element ",
1169 i, " has type \"",
1170 Py_TYPE(tensor_obj)(((PyObject*)(tensor_obj))->ob_type)->tp_name, "\"")
1171 .c_str());
1172 return nullptr;
1173 }
1174
1175 EagerTensor* t = reinterpret_cast<EagerTensor*>(tensor_obj);
1176 TFE_TensorHandle* handle = t->handle;
1177 int num_dims = TFE_TensorHandleNumDims(handle, status.get());
1178 if (MaybeRaiseExceptionFromTFStatus(status.get(), PyExc_ValueError)) {
1179 return nullptr;
1180 }
1181 if (slice_dim >= num_dims) {
1182 PyErr_SetString(
1183 PyExc_IndexError,
1184 tensorflow::strings::StrCat("Slice dimension (", slice_dim,
1185 ") must be smaller than rank of all "
1186 "tensors, but tensor at index ",
1187 i, " has rank ", num_dims)
1188 .c_str());
1189 return nullptr;
1190 }
1191 int64_t dim = TFE_TensorHandleDim(handle, slice_dim, status.get());
1192 if (MaybeRaiseExceptionFromTFStatus(status.get(), PyExc_ValueError)) {
1193 return nullptr;
1194 }
1195 data[i] = dim;
1196 }
1197 }
1198
1199 TFE_TensorHandle* handle =
1200 tensorflow::wrap(tensorflow::unwrap(ctx)->CreateLocalHandle(tensor));
1201
1202 if (!status->status.ok()) {
1203 PyErr_SetString(
1204 PyExc_RuntimeError,
1205 tensorflow::strings::StrCat("Failed to construct new tensor handle: ",
1206 TF_Message(status.get()))
1207 .c_str());
1208 return nullptr;
1209 }
1210
1211 return EagerTensorFromHandle(handle);
1212}
1213
1214PyObject* TFE_Py_TensorShapeOnDevice(PyObject* tensor) {
1215 if (!EagerTensor_CheckExact(tensor)) {
1216 PyErr_SetString(
1217 PyExc_TypeError,
1218 tensorflow::strings::StrCat("Expected an EagerTensors but got type \"",
1219 Py_TYPE(tensor)(((PyObject*)(tensor))->ob_type)->tp_name, "\"")
1220 .c_str());
1221 return nullptr;
1222 }
1223 TFE_TensorHandle* handle = EagerTensor_Handle(tensor);
1224
1225 auto status = tensorflow::make_safe(TF_NewStatus());
1226 TFE_TensorDebugInfo* debug_info =
1227 TFE_TensorHandleTensorDebugInfo(handle, status.get());
1228 if (!status->status.ok()) {
1229 PyErr_SetString(
1230 PyExc_RuntimeError,
1231 tensorflow::strings::StrCat("Error retrieving tensor's device shape: ",
1232 TF_Message(status.get()))
1233 .c_str());
1234 return nullptr;
1235 }
1236
1237 int rank = TFE_TensorDebugInfoOnDeviceNumDims(debug_info);
1238 PyObject* shape = PyTuple_New(rank);
1239 for (int i = 0; i < rank; ++i) {
1240 int64_t dim_size = TFE_TensorDebugInfoOnDeviceDim(debug_info, i);
1241 PyTuple_SET_ITEM(shape, i, PyLong_FromLongLong(dim_size))PyTuple_SetItem(shape, i, PyLong_FromLongLong(dim_size));
1242 }
1243 TFE_DeleteTensorDebugInfo(debug_info);
1244
1245 return shape;
1246}

/opt/pyrefcon/lib/pyrefcon/models/models/PyTuple_New.model

1#ifndef PyTuple_New
2struct _object;
3typedef struct _object PyObject;
4PyObject* clang_analyzer_PyObject_New_Reference();
5PyObject* PyTuple_New(Py_ssize_t len) {
6 return clang_analyzer_PyObject_New_Reference();
8
Setting reference count to 1
7}
8#else
9#warning "API PyTuple_New is defined as a macro."
10#endif