diff --git a/build/conf/compilers/gnu_compiler.conf b/build/conf/compilers/gnu_compiler.conf index d7b1b3a32e83..a33343866830 100644 --- a/build/conf/compilers/gnu_compiler.conf +++ b/build/conf/compilers/gnu_compiler.conf @@ -101,14 +101,6 @@ when ($OS_EMSCRIPTEN == "yes") { CFLAGS+=-D__EMSCRIPTEN__ } -when ($ARCH_WASM64 == "yes") { - CFLAGS+=-D_LIBCPP_HAS_MUSL_LIBC -} - -when ($ARCH_WASM32 == "yes") { - CFLAGS+=-D_musl_ -} - CFLAGS+=$_C_FLAGS $DEBUG_INFO_FLAGS $_C_FOPTIONS $C_WARNING_OPTS $GCC_PREPROCESSOR_OPTS $USER_CFLAGS $USER_CFLAGS_GLOBAL CXXFLAGS+=$CFLAGS $_STD_CXX $CXX_WARNING_OPTS $USER_CXXFLAGS $USER_CXXFLAGS_GLOBAL CONLYFLAGS+=$USER_CONLYFLAGS $USER_CONLYFLAGS_GLOBAL diff --git a/build/conf/settings.conf b/build/conf/settings.conf index 2094fce5c50d..f645b56620f5 100644 --- a/build/conf/settings.conf +++ b/build/conf/settings.conf @@ -19,6 +19,7 @@ YMAKE_USE_NEW_UIDS=yes PIC_NO_PIE=no FAIL_PY2=no MAIN_OUTPUT_AS_EXTRA=yes +USE_REACHABILITY_TO_REPORT_CONF_ERRORS = yes when ($YMAKE_USE_OLD_UIDS == "yes") { YMAKE_USE_NEW_UIDS=no diff --git a/build/config/tests/cpp_style/config18.clang-format b/build/config/tests/cpp_style/config18.clang-format new file mode 100644 index 000000000000..b2d89e2e756e --- /dev/null +++ b/build/config/tests/cpp_style/config18.clang-format @@ -0,0 +1,97 @@ +Language: Cpp +AccessModifierOffset: -4 +ConstructorInitializerIndentWidth: 4 +AlignEscapedNewlinesLeft: false +AlignEscapedNewlines: Left +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AlwaysBreakTemplateDeclarations: true +AlwaysBreakBeforeMultilineStrings: false +BreakBeforeBinaryOperators: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BinPackParameters: true +ColumnLimit: 0 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +IndentWrappedFunctionNames: false +IndentFunctionDeclarationAfterType: false +MaxEmptyLinesToKeep: 1 +KeepEmptyLinesAtTheStartOfBlocks: false +NamespaceIndentation: All +FixNamespaceComments: true +ShortNamespaceLines: 0 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: Never +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakString: 1000 +PenaltyBreakFirstLessLess: 120 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +SpacesBeforeTrailingComments: 1 +SpacesInSquareBrackets: false +Cpp11BracedListStyle: true +Standard: c++20 +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +BreakBeforeBraces: Attach +InsertBraces: true + +# NB: BraceWrapping has no effect unless BreakBeforeBraces is set to Custom +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: true + +SpacesInParentheses: false +SpacesInAngles: false +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: true +SpaceBeforeAssignmentOperators: true +ContinuationIndentWidth: 4 +CommentPragmas: '^ IWYU pragma:' +ForEachMacros: [ + foreach, + Q_FOREACH, + BOOST_FOREACH, + # Is not a foreach, but correct formatting is achieved + Y_DEFER +] +IfMacros: [ + with_lock # Is not an if, but correct formatting is achieved +] +SpaceBeforeParens: ControlStatements +DisableFormat: false +SortIncludes: false +IndentPPDirectives: BeforeHash + +SpaceBeforeInheritanceColon: false +NamespaceMacros: [Y_UNIT_TEST_SUITE] +AttributeMacros: [Y_PRINTF_FORMAT, Y_NO_SANITIZE, Y_FORCE_INLINE, Y_NO_INLINE, Y_WARN_UNUSED_RESULT, Y_HIDDEN, Y_PUBLIC, Y_PURE_FUNCTION] +IndentExternBlock: Indent +TypenameMacros: [Y_THREAD, Y_STATIC_THREAD, Y_POD_THREAD, Y_POD_STATIC_THREAD] +StatementAttributeLikeMacros: [ythrow] +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: 1 diff --git a/build/config/tests/cpp_style/ya.make b/build/config/tests/cpp_style/ya.make index bb5fccd5ea45..afb406a4fc64 100644 --- a/build/config/tests/cpp_style/ya.make +++ b/build/config/tests/cpp_style/ya.make @@ -2,6 +2,7 @@ LIBRARY() RESOURCE_FILES( config.clang-format + config18.clang-format ) END() diff --git a/build/mapping.conf.json b/build/mapping.conf.json index b40d2cd31557..d3b644ceeb33 100644 --- a/build/mapping.conf.json +++ b/build/mapping.conf.json @@ -482,6 +482,8 @@ "7750425697": "https://devtools-registry.s3.yandex.net/7750425697", "7808687279": "https://devtools-registry.s3.yandex.net/7808687279", "7808709138": "https://devtools-registry.s3.yandex.net/7808709138", + "7827427680": "https://devtools-registry.s3.yandex.net/7827427680", + "7827481464": "https://devtools-registry.s3.yandex.net/7827481464", "5486731632": "https://devtools-registry.s3.yandex.net/5486731632", "5514350352": "https://devtools-registry.s3.yandex.net/5514350352", "5514360398": "https://devtools-registry.s3.yandex.net/5514360398", @@ -1645,6 +1647,8 @@ "7750425697": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", "7808687279": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", "7808709138": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", + "7827427680": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", + "7827481464": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", "5486731632": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", "5514350352": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", "5514360398": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", diff --git a/build/platform/test_tool/host.ya.make.inc b/build/platform/test_tool/host.ya.make.inc index bcdce412a739..d283e213faf7 100644 --- a/build/platform/test_tool/host.ya.make.inc +++ b/build/platform/test_tool/host.ya.make.inc @@ -1,12 +1,12 @@ IF (HOST_OS_DARWIN AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808708280) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827478825) ELSEIF (HOST_OS_DARWIN AND HOST_ARCH_ARM64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808707972) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827476769) ELSEIF (HOST_OS_LINUX AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808709138) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827481464) ELSEIF (HOST_OS_LINUX AND HOST_ARCH_AARCH64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808707633) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827475180) ELSEIF (HOST_OS_WINDOWS AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808708809) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827480238) ENDIF() diff --git a/build/platform/test_tool/host_os.ya.make.inc b/build/platform/test_tool/host_os.ya.make.inc index 3813fb019155..20fd205d7d62 100644 --- a/build/platform/test_tool/host_os.ya.make.inc +++ b/build/platform/test_tool/host_os.ya.make.inc @@ -1,12 +1,12 @@ IF (HOST_OS_DARWIN AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808686430) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827425105) ELSEIF (HOST_OS_DARWIN AND HOST_ARCH_ARM64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808685838) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827423650) ELSEIF (HOST_OS_LINUX AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808687279) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827427680) ELSEIF (HOST_OS_LINUX AND HOST_ARCH_AARCH64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808685532) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827422227) ELSEIF (HOST_OS_WINDOWS AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7808686875) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:7827426459) ENDIF() diff --git a/build/scripts/make_java_srclists.py b/build/scripts/make_java_srclists.py index 02a9da78e015..97c80fb19660 100644 --- a/build/scripts/make_java_srclists.py +++ b/build/scripts/make_java_srclists.py @@ -24,7 +24,6 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument('--moddir') parser.add_argument('--java') - parser.add_argument('--groovy') parser.add_argument('--kotlin') parser.add_argument('--coverage') parser.add_argument('--source-root') @@ -32,7 +31,6 @@ def main(): java = [] kotlin = [] - groovy = [] coverage = [] cur_resources_list_file = None @@ -74,8 +72,6 @@ def main(): kotlin.append(src) if args.coverage and args.source_root: add_rel_src_to_coverage(coverage, src, args.source_root) - elif args.groovy and src.endswith(".groovy"): - groovy.append(src) else: if src == '--resources': if cur_resources_list_file is not None: @@ -118,9 +114,6 @@ def main(): if args.kotlin: with open(args.kotlin, 'w') as f: writelines(f, kotlin) - if args.groovy: - with open(args.groovy, 'w') as f: - writelines(f, groovy) if args.coverage: jcov.write_coverage_sources(args.coverage, args.source_root, coverage) diff --git a/build/sysincl/stl-to-libcxx.yml b/build/sysincl/stl-to-libcxx.yml index 22a93f7ad6fe..dc24ce5aa54b 100644 --- a/build/sysincl/stl-to-libcxx.yml +++ b/build/sysincl/stl-to-libcxx.yml @@ -50,25 +50,34 @@ # Though these are headers provided by libcxx, we do not want to allow them to be included. # We are using non-existent filename to generate error instead, as there is no specific syntax for this case. -- includes: - - ext/hash_map: DO_NOT_INCLUDE_NON_STANDARD_EXT_HASH_MAP - - ext/hash_set: DO_NOT_INCLUDE_NON_STANDARD_EXT_HASH_SET - - experimental/any: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_ANY - - experimental/chrono: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_CHRONO - - experimental/coroutine: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_COROUTINE - - experimental/filesystem: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_FILESYSTEM - - experimental/numeric: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_NUMERIC - - experimental/memory: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_MEMORY - - experimental/optional: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_OPTIONAL - - experimental/ratio: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_RATIO - - experimental/source_location: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_SOURCE_LOCATION - - experimental/string_view: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_STRING_VIEW - - experimental/system_error: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_SYSTEM_ERROR - - experimental/tuple: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_TUPLE - +# GENERATED BY YM2 +- source_filter: "^(?!(contrib/libs/cxxsupp/libcxx)).*" + includes: + - ext/__hash: DO_NOT_INCLUDE_NON_STANDARD_EXT___HASH + - ext/hash_map: DO_NOT_INCLUDE_NON_STANDARD_EXT_HASH_MAP + - ext/hash_set: DO_NOT_INCLUDE_NON_STANDARD_EXT_HASH_SET + - experimental/__config: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___CONFIG + - experimental/__memory: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___MEMORY + - experimental/__simd/abi_tag.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_ABI_TAG_H + - experimental/__simd/aligned_tag.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_ALIGNED_TAG_H + - experimental/__simd/declaration.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_DECLARATION_H + - experimental/__simd/internal_declaration.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_INTERNAL_DECLARATION_H + - experimental/__simd/reference.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_REFERENCE_H + - experimental/__simd/scalar.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_SCALAR_H + - experimental/__simd/simd.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_SIMD_H + - experimental/__simd/simd_mask.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_SIMD_MASK_H + - experimental/__simd/traits.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_TRAITS_H + - experimental/__simd/utility.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_UTILITY_H + - experimental/__simd/vec_ext.h: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL___SIMD_VEC_EXT_H + - experimental/iterator: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_ITERATOR + - experimental/memory: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_MEMORY +#TODO: ban this header too +# - experimental/propagate_const: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_PROPAGATE_CONST + - experimental/simd: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_SIMD + - experimental/type_traits: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_TYPE_TRAITS + - experimental/utility: DO_NOT_INCLUDE_NON_STANDARD_EXPERIMENTAL_UTILITY # This includes all headers needed to resolve includes in c-headers from libcxx listed above -# GENERATED BY YM2 - includes: - algorithm: contrib/libs/cxxsupp/libcxx/include/algorithm - any: contrib/libs/cxxsupp/libcxx/include/any diff --git a/build/ymake.core.conf b/build/ymake.core.conf index b3bd862595bd..0dce97a19222 100644 --- a/build/ymake.core.conf +++ b/build/ymake.core.conf @@ -112,6 +112,7 @@ _TOOL_PROTOC_GEN_GO_GRPC_V2=vendor/google.golang.org/grpc/cmd/protoc-gen-go-grpc _TOOL_RESCOMPILER=tools/rescompiler _TOOL_RESCOMPRESSOR=tools/rescompressor _TOOL_RORESCOMPILER=tools/rorescompiler +TOOL_CPPYNDEXER= when ($DISABLE_SEPARATE_AUX_CPP != "yes") { SEPARATE_AUX_CPP=yes @@ -257,8 +258,15 @@ otherwise { # tag:codenav when ($CODENAVIGATION && $NOCODENAVIGATION != "yes") { + when ($TOOL_CPPYNDEXER == "") { + _TOOL_CPPYNDEXER_REAL=$CPPYNDEXER_RESOURCE_GLOBAL/yndexer + } + otherwise { + _TOOL_CPPYNDEXER_REAL=$TOOL_CPPYNDEXER + } + PY_PROGRAM_LINK_EXE=$LINK_EXE && ${hide;kv:"pyndex $TARGET"} - YNDEXER_ARGS=$YMAKE_PYTHON ${input:"build/scripts/yndexer.py"} $CPPYNDEXER_RESOURCE_GLOBAL/yndexer 1500 $(SOURCE_ROOT) $ARCADIA_BUILD_ROOT ${input:SRC} + YNDEXER_ARGS=$YMAKE_PYTHON ${input:"build/scripts/yndexer.py"} $_TOOL_CPPYNDEXER_REAL 1500 $(SOURCE_ROOT) $ARCADIA_BUILD_ROOT ${input:SRC} YNDEXER_OUTPUT=${noauto;output;suf=${OBJ_CROSS_SUF}${COMPILE_OUT_SUFFIX}.ydx.pb2:SRC} } otherwise { @@ -764,6 +772,9 @@ module _BASE_UNIT: _BARE_UNIT { when ($OS_EMSCRIPTEN == "yes") { when ($NOLIBC != "yes") { PEERDIR+=contrib/restricted/emscripten/include + PEERDIR+=contrib/restricted/emscripten/system/lib/c + PEERDIR+=contrib/restricted/emscripten/system/lib/dlmalloc + PEERDIR+=contrib/restricted/emscripten/system/lib/standalonewasm } } diff --git a/contrib/libs/cxxsupp/libcxx/.yandex_meta/scripts/sysincls.py b/contrib/libs/cxxsupp/libcxx/.yandex_meta/scripts/sysincls.py index a3fb43e6ea56..d1a87cb532b9 100644 --- a/contrib/libs/cxxsupp/libcxx/.yandex_meta/scripts/sysincls.py +++ b/contrib/libs/cxxsupp/libcxx/.yandex_meta/scripts/sysincls.py @@ -14,6 +14,8 @@ assert sysincl.count("# END OF GENERATION") == 1 headers = [] +ext_headers = [] +expr_headers = [] for header in include_dir.glob("**/*"): if not header.is_file(): @@ -23,29 +25,56 @@ if header.parent == include_dir: if header.name.startswith("__") or not '.' in header.name: - headers.append(rel_path) + headers.append(str(rel_path)) else: str_path = str(rel_path) - if str_path.startswith('experimental') or str_path.startswith('ext'): - continue - headers.append(rel_path) + if str_path.startswith('experimental'): + expr_headers.append(str_path) + elif str_path.startswith('ext'): + ext_headers.append(str_path) + else: + headers.append(str_path) -headers = sorted(headers, key = lambda header: (str(header).count('/') != 0, str(header).count('__') != 0, header)) + +headers = sorted(headers, key = lambda header: (header.count('/') != 0, header.count('__') != 0, header)) +ext_headers = sorted(ext_headers) +expr_headers = sorted(expr_headers) manual, generated = sysincl.split(GENERATED_BEG) generated, manual_end = generated.split(GENERATED_END) generated = [] +banned_generated = [] + +for header in ext_headers + expr_headers: + banned_generated.append( + " - {name}:{spaces}DO_NOT_INCLUDE_NON_STANDARD_{banned_name}".format( + name=str(header), + spaces=' ' * max(1, 54 - len(header)), + banned_name=header.replace('/', '_').replace('.', '_').upper(), + ) + ) + if "experimental/propagate_const" == header: + banned_generated[-1] = "#TODO: ban this header too\n#" + banned_generated[-1] for header in headers: generated.append( " - {name}:{spaces}contrib/libs/cxxsupp/libcxx/include/{name}".format( - name=str(header), - spaces=' ' * max(1, 54 - len(str(header))) + name=header, + spaces=' ' * max(1, 54 - len(header)) ) ) -generated = "- includes:\n" + '\n'.join(generated) +generated = """- source_filter: "^(?!(contrib/libs/cxxsupp/libcxx)).*" + includes: +""" \ + + '\n'.join(banned_generated) \ + + """ + +# This includes all headers needed to resolve includes in c-headers from libcxx listed above +- includes: +""" \ + + '\n'.join(generated) with open(sysicncl_path, 'w') as f: f.write(f"{manual}{GENERATED_BEG}{generated}\n{GENERATED_END}{manual_end}") diff --git a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py index 1ba6085ed2d9..c77e96a5b3ea 100644 --- a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py +++ b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py @@ -1,5 +1,7 @@ from devtools.yamaker import fileutil -from devtools.yamaker.project import CMakeNinjaNixProject +from devtools.yamaker import pathutil +from devtools.yamaker.modules import Library +from devtools.yamaker.project import NixSourceProject def post_install(self): @@ -17,25 +19,32 @@ def post_install(self): f"VERSION({self.version})", ) - with self.yamakes["."] as libcxxabi: + self.yamakes["."] = self.module( + Library, + NO_UTIL=True, + NO_RUNTIME=True, + NO_COMPILER_WARNINGS=True, # Files are distributed between libcxxabi and libcxx in a weird manner # but we can not peerdir the latter to avoid loops (see below) # FIXME: sort includes open moving glibcxx-shims into its own dir - libcxxabi.ADDINCL = [ + SRCS=fileutil.files(self.dstdir, rel=True, test=pathutil.is_source), + ADDINCL=[ f"{self.arcdir}/include", "contrib/libs/cxxsupp/libcxx/include", # libcxxabi includes libcxx's private "include/refstring.h" header from src subdirectory "contrib/libs/cxxsupp/libcxx/src", - ] - - # We link libpthread.so automatically depending on the target platform - libcxxabi.CFLAGS.remove("-D_LIBCXXABI_LINK_PTHREAD_LIB") - - libcxxabi.NO_UTIL = True - libcxxabi.NO_RUNTIME = True + ], + PEERDIR=[ + "contrib/libs/libunwind", + ], + CFLAGS=[ + "-D_LIBCPP_BUILDING_LIBRARY", + "-D_LIBCXXABI_BUILDING_LIBRARY", + ], + ) - # As of 1.2.3, musl libc does not provide __cxa_thread_atexit_impl. - libcxxabi.CFLAGS.remove("-DHAVE___CXA_THREAD_ATEXIT_IMPL") + with self.yamakes["."] as libcxxabi: + # As of 1.2.3, musl libc does not provide __cxa_thread_atexit_impl libcxxabi.after( "SRCS", """ @@ -68,13 +77,22 @@ def post_install(self): libcxxabi.PEERDIR.add("library/cpp/sanitizer/include") -llvm_libcxxabi = CMakeNinjaNixProject( +libcxxabi = NixSourceProject( owners=["g:cpp-committee", "g:cpp-contrib"], arcdir="contrib/libs/cxxsupp/libcxxabi", nixattr="llvmPackages_16.libcxxabi", copy_sources=[ "include/__cxxabi_config.h", "include/cxxabi.h", + "src/*.cpp", + "src/*.h", + "src/demangle/*.cpp", + "src/demangle/*.def", + "src/demangle/*.h", + ], + copy_sources_except=[ + # fake exception implementation which just invokes std::terminate + "src/cxa_noexception.cpp", ], disable_includes=[ "aix_state_tab_eh.inc", diff --git a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/devtools.licenses.report b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/devtools.licenses.report index c8b0bda349a9..8c88510b2369 100644 --- a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/devtools.licenses.report +++ b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/devtools.licenses.report @@ -83,8 +83,6 @@ BELONGS ya.make Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 Files with this license: include/__cxxabi_config.h [3:4] - include/c++/v1/__cxxabi_config.h [3:4] - include/c++/v1/cxxabi.h [3:4] include/cxxabi.h [3:4] src/abort_message.cpp [3:4] src/abort_message.h [3:4] @@ -122,8 +120,6 @@ BELONGS ya.make Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception Files with this license: include/__cxxabi_config.h [3:4] - include/c++/v1/__cxxabi_config.h [3:4] - include/c++/v1/cxxabi.h [3:4] include/cxxabi.h [3:4] src/abort_message.cpp [3:4] src/abort_message.h [3:4] @@ -201,8 +197,6 @@ BELONGS ya.make Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 Files with this license: include/__cxxabi_config.h [5:5] - include/c++/v1/__cxxabi_config.h [5:5] - include/c++/v1/cxxabi.h [5:5] include/cxxabi.h [5:5] src/abort_message.cpp [5:5] src/abort_message.h [5:5] @@ -240,8 +234,6 @@ BELONGS ya.make Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception Files with this license: include/__cxxabi_config.h [5:5] - include/c++/v1/__cxxabi_config.h [5:5] - include/c++/v1/cxxabi.h [5:5] include/cxxabi.h [5:5] src/abort_message.cpp [5:5] src/abort_message.h [5:5] diff --git a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix index 6466e5c5e8b9..e0d5f583e07c 100644 --- a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix +++ b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix @@ -8,19 +8,7 @@ pkgs: attrs: with pkgs; with attrs; rec { hash = "sha256-fspqSReX+VD+Nl/Cfq+tDcdPtnQPV1IRopNDfd5VtUs="; }; - patches = [ - # https://reviews.llvm.org/D132298, Allow building libcxxabi alone - (fetchpatch { - url = "https://github.com/llvm/llvm-project/commit/e6a0800532bb409f6d1c62f3698bdd6994a877dc.patch"; - sha256 = "1xyjd56m4pfwq8p3xh6i8lhkk9kq15jaml7qbhxdf87z4jjkk63a"; - stripLen = 1; - }) - ]; - - NIX_CFLAGS_COMPILE = [ - # See DTCC-589 for the details - "-fno-integrated-cc1" - ]; + patches = []; sourceRoot = "source/libcxxabi"; } diff --git a/contrib/libs/cxxsupp/libcxxabi/include/c++/v1/__cxxabi_config.h b/contrib/libs/cxxsupp/libcxxabi/include/c++/v1/__cxxabi_config.h deleted file mode 100644 index c97dd656e165..000000000000 --- a/contrib/libs/cxxsupp/libcxxabi/include/c++/v1/__cxxabi_config.h +++ /dev/null @@ -1,106 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef ____CXXABI_CONFIG_H -#define ____CXXABI_CONFIG_H - -#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ - !defined(__ARM_DWARF_EH__) && !defined(__SEH__) -#define _LIBCXXABI_ARM_EHABI -#endif - -#if !defined(__has_attribute) -#define __has_attribute(_attribute_) 0 -#endif - -#if defined(__clang__) -# define _LIBCXXABI_COMPILER_CLANG -# ifndef __apple_build_version__ -# define _LIBCXXABI_CLANG_VER (__clang_major__ * 100 + __clang_minor__) -# endif -#elif defined(__GNUC__) -# define _LIBCXXABI_COMPILER_GCC -#elif defined(_MSC_VER) -# define _LIBCXXABI_COMPILER_MSVC -#elif defined(__IBMCPP__) -# define _LIBCXXABI_COMPILER_IBM -#endif - -#if defined(_WIN32) - #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) - #define _LIBCXXABI_HIDDEN - #define _LIBCXXABI_DATA_VIS - #define _LIBCXXABI_FUNC_VIS - #define _LIBCXXABI_TYPE_VIS - #elif defined(_LIBCXXABI_BUILDING_LIBRARY) - #define _LIBCXXABI_HIDDEN - #define _LIBCXXABI_DATA_VIS __declspec(dllexport) - #define _LIBCXXABI_FUNC_VIS __declspec(dllexport) - #define _LIBCXXABI_TYPE_VIS __declspec(dllexport) - #else - #define _LIBCXXABI_HIDDEN - #define _LIBCXXABI_DATA_VIS __declspec(dllimport) - #define _LIBCXXABI_FUNC_VIS __declspec(dllimport) - #define _LIBCXXABI_TYPE_VIS __declspec(dllimport) - #endif -#else - #if !defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) - #define _LIBCXXABI_HIDDEN __attribute__((__visibility__("hidden"))) - #define _LIBCXXABI_DATA_VIS __attribute__((__visibility__("default"))) - #define _LIBCXXABI_FUNC_VIS __attribute__((__visibility__("default"))) - #if __has_attribute(__type_visibility__) - #define _LIBCXXABI_TYPE_VIS __attribute__((__type_visibility__("default"))) - #else - #define _LIBCXXABI_TYPE_VIS __attribute__((__visibility__("default"))) - #endif - #else - #define _LIBCXXABI_HIDDEN - #define _LIBCXXABI_DATA_VIS - #define _LIBCXXABI_FUNC_VIS - #define _LIBCXXABI_TYPE_VIS - #endif -#endif - -#if defined(_LIBCXXABI_COMPILER_MSVC) -#define _LIBCXXABI_WEAK -#else -#define _LIBCXXABI_WEAK __attribute__((__weak__)) -#endif - -#if defined(__clang__) -#define _LIBCXXABI_COMPILER_CLANG -#elif defined(__GNUC__) -#define _LIBCXXABI_COMPILER_GCC -#endif - -#if __has_attribute(__no_sanitize__) && defined(_LIBCXXABI_COMPILER_CLANG) -#define _LIBCXXABI_NO_CFI __attribute__((__no_sanitize__("cfi"))) -#else -#define _LIBCXXABI_NO_CFI -#endif - -// wasm32 follows the arm32 ABI convention of using 32-bit guard. -#if defined(__arm__) || defined(__wasm32__) || defined(__ARM64_ARCH_8_32__) -# define _LIBCXXABI_GUARD_ABI_ARM -#endif - -#if defined(_LIBCXXABI_COMPILER_CLANG) -# if !__has_feature(cxx_exceptions) -# define _LIBCXXABI_NO_EXCEPTIONS -# endif -#elif defined(_LIBCXXABI_COMPILER_GCC) && !defined(__EXCEPTIONS) -# define _LIBCXXABI_NO_EXCEPTIONS -#endif - -#if defined(_WIN32) -#define _LIBCXXABI_DTOR_FUNC __thiscall -#else -#define _LIBCXXABI_DTOR_FUNC -#endif - -#endif // ____CXXABI_CONFIG_H diff --git a/contrib/libs/cxxsupp/libcxxabi/include/c++/v1/cxxabi.h b/contrib/libs/cxxsupp/libcxxabi/include/c++/v1/cxxabi.h deleted file mode 100644 index 85cb4b36b811..000000000000 --- a/contrib/libs/cxxsupp/libcxxabi/include/c++/v1/cxxabi.h +++ /dev/null @@ -1,177 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef __CXXABI_H -#define __CXXABI_H - -/* - * This header provides the interface to the C++ ABI as defined at: - * https://itanium-cxx-abi.github.io/cxx-abi/ - */ - -#include -#include - -#include <__cxxabi_config.h> - -#define _LIBCPPABI_VERSION 15000 -#define _LIBCXXABI_NORETURN __attribute__((noreturn)) -#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold)) - -#ifdef __cplusplus - -namespace std { -#if defined(_WIN32) -class _LIBCXXABI_TYPE_VIS type_info; // forward declaration -#else -class type_info; // forward declaration -#endif -} - - -// runtime routines use C calling conventions, but are in __cxxabiv1 namespace -namespace __cxxabiv1 { -extern "C" { - -// 2.4.2 Allocating the Exception Object -extern _LIBCXXABI_FUNC_VIS void * -__cxa_allocate_exception(size_t thrown_size) throw(); -extern _LIBCXXABI_FUNC_VIS void -__cxa_free_exception(void *thrown_exception) throw(); - -// 2.4.3 Throwing the Exception Object -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void -__cxa_throw(void *thrown_exception, std::type_info *tinfo, - void (_LIBCXXABI_DTOR_FUNC *dest)(void *)); - -// 2.5.3 Exception Handlers -extern _LIBCXXABI_FUNC_VIS void * -__cxa_get_exception_ptr(void *exceptionObject) throw(); -extern _LIBCXXABI_FUNC_VIS void * -__cxa_begin_catch(void *exceptionObject) throw(); -extern _LIBCXXABI_FUNC_VIS void __cxa_end_catch(); -#if defined(_LIBCXXABI_ARM_EHABI) -extern _LIBCXXABI_FUNC_VIS bool -__cxa_begin_cleanup(void *exceptionObject) throw(); -extern _LIBCXXABI_FUNC_VIS void __cxa_end_cleanup(); -#endif -extern _LIBCXXABI_FUNC_VIS std::type_info *__cxa_current_exception_type(); - -// 2.5.4 Rethrowing Exceptions -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_rethrow(); - -// 2.6 Auxiliary Runtime APIs -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_bad_cast(void); -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_bad_typeid(void); -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void -__cxa_throw_bad_array_new_length(void); - -// 3.2.6 Pure Virtual Function API -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_pure_virtual(void); - -// 3.2.7 Deleted Virtual Function API -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void); - -// 3.3.2 One-time Construction API -#if defined(_LIBCXXABI_GUARD_ABI_ARM) -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *); -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *); -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *); -#else -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *); -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *); -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *); -#endif - -// 3.3.3 Array Construction and Destruction API -extern _LIBCXXABI_FUNC_VIS void * -__cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size, - void (*constructor)(void *), void (*destructor)(void *)); - -extern _LIBCXXABI_FUNC_VIS void * -__cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size, - void (*constructor)(void *), void (*destructor)(void *), - void *(*alloc)(size_t), void (*dealloc)(void *)); - -extern _LIBCXXABI_FUNC_VIS void * -__cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size, - void (*constructor)(void *), void (*destructor)(void *), - void *(*alloc)(size_t), void (*dealloc)(void *, size_t)); - -extern _LIBCXXABI_FUNC_VIS void -__cxa_vec_ctor(void *array_address, size_t element_count, size_t element_size, - void (*constructor)(void *), void (*destructor)(void *)); - -extern _LIBCXXABI_FUNC_VIS void __cxa_vec_dtor(void *array_address, - size_t element_count, - size_t element_size, - void (*destructor)(void *)); - -extern _LIBCXXABI_FUNC_VIS void __cxa_vec_cleanup(void *array_address, - size_t element_count, - size_t element_size, - void (*destructor)(void *)); - -extern _LIBCXXABI_FUNC_VIS void __cxa_vec_delete(void *array_address, - size_t element_size, - size_t padding_size, - void (*destructor)(void *)); - -extern _LIBCXXABI_FUNC_VIS void -__cxa_vec_delete2(void *array_address, size_t element_size, size_t padding_size, - void (*destructor)(void *), void (*dealloc)(void *)); - -extern _LIBCXXABI_FUNC_VIS void -__cxa_vec_delete3(void *__array_address, size_t element_size, - size_t padding_size, void (*destructor)(void *), - void (*dealloc)(void *, size_t)); - -extern _LIBCXXABI_FUNC_VIS void -__cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count, - size_t element_size, void (*constructor)(void *, void *), - void (*destructor)(void *)); - -// 3.3.5.3 Runtime API -// These functions are part of the C++ ABI, but they are not defined in libc++abi: -// int __cxa_atexit(void (*)(void *), void *, void *); -// void __cxa_finalize(void *); - -// 3.4 Demangler API -extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name, - char *output_buffer, - size_t *length, int *status); - -// Apple additions to support C++ 0x exception_ptr class -// These are primitives to wrap a smart pointer around an exception object -extern _LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() throw(); -extern _LIBCXXABI_FUNC_VIS void -__cxa_rethrow_primary_exception(void *primary_exception); -extern _LIBCXXABI_FUNC_VIS void -__cxa_increment_exception_refcount(void *primary_exception) throw(); -extern _LIBCXXABI_FUNC_VIS void -__cxa_decrement_exception_refcount(void *primary_exception) throw(); - -// Apple extension to support std::uncaught_exception() -extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() throw(); -extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() throw(); - -#if defined(__linux__) || defined(__Fuchsia__) -// Linux and Fuchsia TLS support. Not yet an official part of the Itanium ABI. -// https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables -extern _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*)(void *), void *, - void *) throw(); -#endif - -} // extern "C" -} // namespace __cxxabiv1 - -namespace abi = __cxxabiv1; - -#endif // __cplusplus - -#endif // __CXXABI_H diff --git a/contrib/python/argcomplete/py3/.dist-info/METADATA b/contrib/python/argcomplete/py3/.dist-info/METADATA index 5298d4a927a8..fe74af8ae585 100644 --- a/contrib/python/argcomplete/py3/.dist-info/METADATA +++ b/contrib/python/argcomplete/py3/.dist-info/METADATA @@ -1,17 +1,18 @@ -Metadata-Version: 2.1 +Metadata-Version: 2.4 Name: argcomplete -Version: 3.5.2 +Version: 3.5.3 Summary: Bash tab completion for argparse -Home-page: https://github.com/kislyuk/argcomplete -Author: Andrey Kislyuk -Author-email: kislyuk@gmail.com -License: Apache Software License +Project-URL: Homepage, https://github.com/kislyuk/argcomplete Project-URL: Documentation, https://kislyuk.github.io/argcomplete Project-URL: Source Code, https://github.com/kislyuk/argcomplete Project-URL: Issue Tracker, https://github.com/kislyuk/argcomplete/issues Project-URL: Change Log, https://github.com/kislyuk/argcomplete/blob/develop/Changes.rst -Platform: MacOS X -Platform: Posix +Author: Andrey Kislyuk +Author-email: kislyuk@gmail.com +License: Apache Software License +License-File: LICENSE.rst +License-File: NOTICE +Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License @@ -27,21 +28,18 @@ Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Development Status :: 5 - Production/Stable Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Shells Classifier: Topic :: Terminals Requires-Python: >=3.8 -Description-Content-Type: text/x-rst -License-File: LICENSE.rst -License-File: NOTICE Provides-Extra: test -Requires-Dist: coverage; extra == "test" -Requires-Dist: pexpect; extra == "test" -Requires-Dist: wheel; extra == "test" -Requires-Dist: ruff; extra == "test" -Requires-Dist: mypy; extra == "test" +Requires-Dist: coverage; extra == 'test' +Requires-Dist: mypy; extra == 'test' +Requires-Dist: pexpect; extra == 'test' +Requires-Dist: ruff; extra == 'test' +Requires-Dist: wheel; extra == 'test' +Description-Content-Type: text/x-rst argcomplete - Bash/zsh tab completion for argparse ================================================== @@ -85,6 +83,9 @@ follows: args = parser.parse_args() ... +If using ``pyproject.toml`` ``[project.scripts]`` entry points, the ``PYTHON_ARGCOMPLETE_OK`` marker should appear +at the beginning of the file that contains the entry point. + Register your Python application with your shell's completion framework by running ``register-python-argcomplete``:: eval "$(register-python-argcomplete my-python-app)" @@ -268,9 +269,9 @@ multiple Python versions on the same system, the version being used to run the s ``/etc/shells``, and run ``chsh`` to change your shell). You can check the version of the running copy of bash with ``echo $BASH_VERSION``. -.. note:: If you use setuptools/distribute ``scripts`` or ``entry_points`` directives to package your module, +.. note:: If you use ``project.scripts`` directives to provide command line entry points to your package, argcomplete will follow the wrapper scripts to their destination and look for ``PYTHON_ARGCOMPLETE_OK`` in the - destination code. + first kilobyte of the file containing the destination code. If you choose not to use global completion, or ship a completion module that depends on argcomplete, you must register your script explicitly using ``eval "$(register-python-argcomplete my-python-app)"``. Standard completion module diff --git a/contrib/python/argcomplete/py3/README.rst b/contrib/python/argcomplete/py3/README.rst index c134a566e6b2..13f0fa7ae366 100644 --- a/contrib/python/argcomplete/py3/README.rst +++ b/contrib/python/argcomplete/py3/README.rst @@ -40,6 +40,9 @@ follows: args = parser.parse_args() ... +If using ``pyproject.toml`` ``[project.scripts]`` entry points, the ``PYTHON_ARGCOMPLETE_OK`` marker should appear +at the beginning of the file that contains the entry point. + Register your Python application with your shell's completion framework by running ``register-python-argcomplete``:: eval "$(register-python-argcomplete my-python-app)" @@ -223,9 +226,9 @@ multiple Python versions on the same system, the version being used to run the s ``/etc/shells``, and run ``chsh`` to change your shell). You can check the version of the running copy of bash with ``echo $BASH_VERSION``. -.. note:: If you use setuptools/distribute ``scripts`` or ``entry_points`` directives to package your module, +.. note:: If you use ``project.scripts`` directives to provide command line entry points to your package, argcomplete will follow the wrapper scripts to their destination and look for ``PYTHON_ARGCOMPLETE_OK`` in the - destination code. + first kilobyte of the file containing the destination code. If you choose not to use global completion, or ship a completion module that depends on argcomplete, you must register your script explicitly using ``eval "$(register-python-argcomplete my-python-app)"``. Standard completion module diff --git a/contrib/python/argcomplete/py3/argcomplete/completers.py b/contrib/python/argcomplete/py3/argcomplete/completers.py index b62c593d64f3..610349f65278 100644 --- a/contrib/python/argcomplete/py3/argcomplete/completers.py +++ b/contrib/python/argcomplete/py3/argcomplete/completers.py @@ -59,13 +59,17 @@ def __call__(self, prefix, **kwargs): completion = [] if self.allowednames: if self.directories: - files = _call(["bash", "-c", "compgen -A directory -- '{p}'".format(p=prefix)]) + # Using 'bind' in this and the following commands is a workaround to a bug in bash + # that was fixed in bash 5.3 but affects older versions. Environment variables are not treated + # correctly in older versions and calling bind makes them available. For details, see + # https://savannah.gnu.org/support/index.php?111125 + files = _call(["bash", "-c", "bind; compgen -A directory -- '{p}'".format(p=prefix)], stderr=subprocess.DEVNULL) completion += [f + "/" for f in files] for x in self.allowednames: - completion += _call(["bash", "-c", "compgen -A file -X '!*.{0}' -- '{p}'".format(x, p=prefix)]) + completion += _call(["bash", "-c", "bind; compgen -A file -X '!*.{0}' -- '{p}'".format(x, p=prefix)], stderr=subprocess.DEVNULL) else: - completion += _call(["bash", "-c", "compgen -A file -- '{p}'".format(p=prefix)]) - anticomp = _call(["bash", "-c", "compgen -A directory -- '{p}'".format(p=prefix)]) + completion += _call(["bash", "-c", "bind; compgen -A file -- '{p}'".format(p=prefix)], stderr=subprocess.DEVNULL) + anticomp = _call(["bash", "-c", "bind; compgen -A directory -- '{p}'".format(p=prefix)], stderr=subprocess.DEVNULL) completion = list(set(completion) - set(anticomp)) if self.directories: diff --git a/contrib/python/argcomplete/py3/ya.make b/contrib/python/argcomplete/py3/ya.make index e54ca26a823e..dfa97494a92b 100644 --- a/contrib/python/argcomplete/py3/ya.make +++ b/contrib/python/argcomplete/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(3.5.2) +VERSION(3.5.3) LICENSE(Apache-2.0) diff --git a/contrib/python/pyparsing/py3/.dist-info/METADATA b/contrib/python/pyparsing/py3/.dist-info/METADATA index ff6f9b622795..6b5fbefef606 100644 --- a/contrib/python/pyparsing/py3/.dist-info/METADATA +++ b/contrib/python/pyparsing/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pyparsing -Version: 3.2.0 +Version: 3.2.1 Summary: pyparsing module - Classes and methods to define and execute parsing grammars Author-email: Paul McGuire Requires-Python: >=3.9 diff --git a/contrib/python/pyparsing/py3/pyparsing/__init__.py b/contrib/python/pyparsing/py3/pyparsing/__init__.py index 543ceb62bd53..726c76cb2449 100644 --- a/contrib/python/pyparsing/py3/pyparsing/__init__.py +++ b/contrib/python/pyparsing/py3/pyparsing/__init__.py @@ -120,8 +120,8 @@ def __repr__(self): return f"{__name__}.{type(self).__name__}({', '.join('{}={!r}'.format(*nv) for nv in zip(self._fields, self))})" -__version_info__ = version_info(3, 2, 0, "final", 1) -__version_time__ = "13 Oct 2024 09:46 UTC" +__version_info__ = version_info(3, 2, 1, "final", 1) +__version_time__ = "31 Dec 2024 20:41 UTC" __version__ = __version_info__.__version__ __versionTime__ = __version_time__ __author__ = "Paul McGuire " diff --git a/contrib/python/pyparsing/py3/pyparsing/actions.py b/contrib/python/pyparsing/py3/pyparsing/actions.py index 1d2dce99e199..f491aab986e9 100644 --- a/contrib/python/pyparsing/py3/pyparsing/actions.py +++ b/contrib/python/pyparsing/py3/pyparsing/actions.py @@ -1,21 +1,34 @@ # actions.py +from __future__ import annotations + +from typing import Union, Callable, Any from .exceptions import ParseException from .util import col, replaced_by_pep8 +from .results import ParseResults + + +ParseAction = Union[ + Callable[[], Any], + Callable[[ParseResults], Any], + Callable[[int, ParseResults], Any], + Callable[[str, int, ParseResults], Any], +] class OnlyOnce: """ Wrapper for parse actions, to ensure they are only called once. + Note: parse action signature must include all 3 arguments. """ - def __init__(self, method_call): + def __init__(self, method_call: Callable[[str, int, ParseResults], Any]): from .core import _trim_arity self.callable = _trim_arity(method_call) self.called = False - def __call__(self, s, l, t): + def __call__(self, s: str, l: int, t: ParseResults) -> ParseResults: if not self.called: results = self.callable(s, l, t) self.called = True @@ -30,20 +43,20 @@ def reset(self): self.called = False -def match_only_at_col(n): +def match_only_at_col(n: int) -> ParseAction: """ Helper method for defining parse actions that require matching at a specific column in the input text. """ - def verify_col(strg, locn, toks): + def verify_col(strg: str, locn: int, toks: ParseResults) -> None: if col(locn, strg) != n: raise ParseException(strg, locn, f"matched token not at column {n}") return verify_col -def replace_with(repl_str): +def replace_with(repl_str: str) -> ParseAction: """ Helper method for common parse actions that simply return a literal value. Especially useful when used with @@ -60,7 +73,7 @@ def replace_with(repl_str): return lambda s, l, t: [repl_str] -def remove_quotes(s, l, t): +def remove_quotes(s: str, l: int, t: ParseResults) -> Any: """ Helper parse action for removing quotation marks from parsed quoted strings. @@ -77,7 +90,7 @@ def remove_quotes(s, l, t): return t[0][1:-1] -def with_attribute(*args, **attr_dict): +def with_attribute(*args: tuple[str, str], **attr_dict) -> ParseAction: """ Helper to create a validating parse action to be used with start tags created with :class:`make_xml_tags` or @@ -133,17 +146,17 @@ def with_attribute(*args, **attr_dict): 1 4 0 1 0 1,3 2,3 1,1 """ + attrs_list: list[tuple[str, str]] = [] if args: - attrs = args[:] + attrs_list.extend(args) else: - attrs = attr_dict.items() - attrs = [(k, v) for k, v in attrs] + attrs_list.extend(attr_dict.items()) - def pa(s, l, tokens): - for attrName, attrValue in attrs: + def pa(s: str, l: int, tokens: ParseResults) -> None: + for attrName, attrValue in attrs_list: if attrName not in tokens: raise ParseException(s, l, "no matching attribute " + attrName) - if attrValue != with_attribute.ANY_VALUE and tokens[attrName] != attrValue: + if attrValue != with_attribute.ANY_VALUE and tokens[attrName] != attrValue: # type: ignore [attr-defined] raise ParseException( s, l, @@ -156,7 +169,7 @@ def pa(s, l, tokens): with_attribute.ANY_VALUE = object() # type: ignore [attr-defined] -def with_class(classname, namespace=""): +def with_class(classname: str, namespace: str = "") -> ParseAction: """ Simplified version of :class:`with_attribute` when matching on a div class - made difficult because ``class`` is diff --git a/contrib/python/pyparsing/py3/pyparsing/common.py b/contrib/python/pyparsing/py3/pyparsing/common.py index 649aad009617..e46511086dad 100644 --- a/contrib/python/pyparsing/py3/pyparsing/common.py +++ b/contrib/python/pyparsing/py3/pyparsing/common.py @@ -210,14 +210,14 @@ class pyparsing_common: """any numeric expression, returns the corresponding Python type""" fnumber = ( - Regex(r"[+-]?\d+\.?\d*([eE][+-]?\d+)?") + Regex(r"[+-]?\d+\.?\d*(?:[eE][+-]?\d+)?") .set_name("fnumber") .set_parse_action(convert_to_float) ) """any int or real number, returned as float""" ieee_float = ( - Regex(r"(?i)[+-]?((\d+\.?\d*(e[+-]?\d+)?)|nan|inf(inity)?)") + Regex(r"(?i:[+-]?(?:(?:\d+\.?\d*(?:e[+-]?\d+)?)|nan|inf(?:inity)?))") .set_name("ieee_float") .set_parse_action(convert_to_float) ) diff --git a/contrib/python/pyparsing/py3/pyparsing/core.py b/contrib/python/pyparsing/py3/pyparsing/core.py index 4f43c3bf991c..b884e2d4a40b 100644 --- a/contrib/python/pyparsing/py3/pyparsing/core.py +++ b/contrib/python/pyparsing/py3/pyparsing/core.py @@ -215,12 +215,7 @@ def _should_enable_warnings( _generatorType = types.GeneratorType ParseImplReturnType = tuple[int, Any] PostParseReturnType = Union[ParseResults, Sequence[ParseResults]] -ParseAction = Union[ - Callable[[], Any], - Callable[[ParseResults], Any], - Callable[[int, ParseResults], Any], - Callable[[str, int, ParseResults], Any], -] + ParseCondition = Union[ Callable[[], bool], Callable[[ParseResults], bool], @@ -486,6 +481,7 @@ def __init__(self, savelist: bool = False): self.callPreparse = True self.callDuringTry = False self.suppress_warnings_: list[Diagnostics] = [] + self.show_in_diagram = True def suppress_warning(self, warning_type: Diagnostics) -> ParserElement: """ @@ -5558,7 +5554,8 @@ def __or__(self, other) -> ParserElement: not in self.suppress_warnings_ ): warnings.warn( - "using '<<' operator with '|' is probably an error, use '<<='", + "warn_on_match_first_with_lshift_operator:" + " using '<<' operator with '|' is probably an error, use '<<='", stacklevel=2, ) ret = super().__or__(other) @@ -5572,7 +5569,8 @@ def __del__(self): and Diagnostics.warn_on_assignment_to_Forward not in self.suppress_warnings_ ): warnings.warn_explicit( - "Forward defined here but no expression attached later using '<<=' or '<<'", + "warn_on_assignment_to_Forward:" + " Forward defined here but no expression attached later using '<<=' or '<<'", UserWarning, filename=self.caller_frame.filename, lineno=self.caller_frame.lineno, @@ -5600,7 +5598,8 @@ def parseImpl(self, instring, loc, do_actions=True) -> ParseImplReturnType: else: stacklevel = 2 warnings.warn( - "Forward expression was never assigned a value, will not parse any input", + "warn_on_parse_using_empty_Forward:" + " Forward expression was never assigned a value, will not parse any input", stacklevel=stacklevel, ) if not ParserElement._left_recursion_enabled: @@ -6157,7 +6156,7 @@ def autoname_elements() -> None: Utility to simplify mass-naming of parser elements, for generating railroad diagram with named subdiagrams. """ - calling_frame = sys._getframe().f_back + calling_frame = sys._getframe(1) if calling_frame is None: return calling_frame = typing.cast(types.FrameType, calling_frame) diff --git a/contrib/python/pyparsing/py3/pyparsing/diagram/__init__.py b/contrib/python/pyparsing/py3/pyparsing/diagram/__init__.py index 7926f2c35528..56526b741b87 100644 --- a/contrib/python/pyparsing/py3/pyparsing/diagram/__init__.py +++ b/contrib/python/pyparsing/py3/pyparsing/diagram/__init__.py @@ -1,6 +1,7 @@ # mypy: ignore-errors from __future__ import annotations +import itertools import railroad import pyparsing import dataclasses @@ -40,7 +41,7 @@ {{ body | safe }} {% for diagram in diagrams %}
-

{{ diagram.title }}

+

{{ diagram.title }}

{{ diagram.text }}
{{ diagram.svg }} @@ -56,8 +57,35 @@ template = Template(jinja2_template_source) +_bookmark_lookup = {} +_bookmark_ids = itertools.count(start=1) + +def _make_bookmark(s: str) -> str: + """ + Converts a string into a valid HTML bookmark (ID or anchor name). + """ + if s in _bookmark_lookup: + return _bookmark_lookup[s] + + # Replace invalid characters with hyphens and ensure only valid characters + bookmark = re.sub(r'[^a-zA-Z0-9-]+', '-', s) + + # Ensure it starts with a letter by adding 'z' if necessary + if not bookmark[:1].isalpha(): + bookmark = f"z{bookmark}" + + # Convert to lowercase and strip hyphens + bookmark = bookmark.lower().strip('-') + + _bookmark_lookup[s] = bookmark = f"{bookmark}-{next(_bookmark_ids):04d}" + + return bookmark + + def _collapse_verbose_regex(regex_str: str) -> str: - collapsed = pyparsing.Regex(r"#.*").suppress().transform_string(regex_str) + if "\n" not in regex_str: + return regex_str + collapsed = pyparsing.Regex(r"#.*$").suppress().transform_string(regex_str) collapsed = re.sub(r"\s*\n\s*", "", collapsed) return collapsed @@ -72,6 +100,11 @@ class NamedDiagram: index: int diagram: railroad.DiagramItem = None + @property + def bookmark(self): + bookmark = _make_bookmark(self.name) + return bookmark + T = TypeVar("T") @@ -99,7 +132,7 @@ class AnnotatedItem(railroad.Group): """ def __init__(self, label: str, item): - super().__init__(item=item, label=f"[{label}]") + super().__init__(item=item, label=f"[{label}]" if label else "") class EditablePartial(Generic[T]): @@ -162,7 +195,11 @@ def railroad_to_html(diagrams: list[NamedDiagram], embed=False, **kwargs) -> str title = diagram.name if diagram.index == 0: title += " (root)" - data.append({"title": title, "text": "", "svg": io.getvalue()}) + data.append( + { + "title": title, "text": "", "svg": io.getvalue(), "bookmark": diagram.bookmark + } + ) return template.render(diagrams=data, embed=embed, **kwargs) @@ -336,6 +373,12 @@ def __delitem__(self, key: int): def __contains__(self, key: int): return key in self._element_diagram_states + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + def generate_unnamed(self) -> int: """ Generate a number used in the name of an otherwise unnamed diagram @@ -360,7 +403,8 @@ def extract_into_diagram(self, el_id: int): # Replace the original definition of this element with a regular block if position.parent: - ret = EditablePartial.from_call(railroad.NonTerminal, text=position.name) + href = f"#{_make_bookmark(position.name)}" + ret = EditablePartial.from_call(railroad.NonTerminal, text=position.name, href=href) if "item" in position.parent.kwargs: position.parent.kwargs["item"] = ret elif "items" in position.parent.kwargs: @@ -447,7 +491,7 @@ def _visible_exprs(exprs: Iterable[pyparsing.ParserElement]): return [ e for e in exprs - if not (e.customName or e.resultsName or isinstance(e, non_diagramming_exprs)) + if not isinstance(e, non_diagramming_exprs) ] @@ -461,6 +505,7 @@ def _to_diagram_element( name_hint: str = None, show_results_names: bool = False, show_groups: bool = False, + show_hidden: bool = False, ) -> typing.Optional[EditablePartial]: """ Recursively converts a PyParsing Element to a railroad Element @@ -472,8 +517,9 @@ def _to_diagram_element( do so :param name_hint: If provided, this will override the generated name :param show_results_names: bool flag indicating whether to add annotations for results names - :returns: The converted version of the input element, but as a Partial that hasn't yet been constructed :param show_groups: bool flag indicating whether to show groups using bounding box + :param show_hidden: bool flag indicating whether to show elements that are typically hidden + :returns: The converted version of the input element, but as a Partial that hasn't yet been constructed """ exprs = element.recurse() name = name_hint or element.customName or type(element).__name__ @@ -489,7 +535,7 @@ def _to_diagram_element( element, ( # pyparsing.TokenConverter, - # pyparsing.Forward, + pyparsing.Forward, pyparsing.Located, ), ): @@ -513,25 +559,33 @@ def _to_diagram_element( # If the element isn't worth extracting, we always treat it as the first time we say it if _worth_extracting(element): - if el_id in lookup and lookup[el_id].name is not None: + looked_up = lookup.get(el_id) + if looked_up and looked_up.name is not None: # If we've seen this element exactly once before, we are only just now finding out that it's a duplicate, # so we have to extract it into a new diagram. - looked_up = lookup[el_id] looked_up.mark_for_extraction(el_id, lookup, name=name_hint) - ret = EditablePartial.from_call(railroad.NonTerminal, text=looked_up.name) + href = f"#{_make_bookmark(looked_up.name)}" + ret = EditablePartial.from_call(railroad.NonTerminal, text=looked_up.name, href=href) return ret elif el_id in lookup.diagrams: # If we have seen the element at least twice before, and have already extracted it into a subdiagram, we # just put in a marker element that refers to the sub-diagram + text = lookup.diagrams[el_id].kwargs["name"] ret = EditablePartial.from_call( - railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] + railroad.NonTerminal, text=text, href=f"#{_make_bookmark(text)}" ) return ret # Recursively convert child elements # Here we find the most relevant Railroad element for matching pyparsing Element # We use ``items=[]`` here to hold the place for where the child elements will go once created + + # see if this element is normally hidden, and whether hidden elements are desired + # if not, just return None + if not element.show_in_diagram and not show_hidden: + return None + if isinstance(element, pyparsing.And): # detect And's created with ``expr*N`` notation - for these use a OneOrMore with a repeat # (all will have the same name, and resultsName) @@ -566,7 +620,9 @@ def _to_diagram_element( if show_groups: ret = EditablePartial.from_call(AnnotatedItem, label="", item="") else: - ret = EditablePartial.from_call(railroad.Sequence, items=[]) + ret = EditablePartial.from_call( + railroad.Group, item=None, label=element_results_name + ) elif isinstance(element, pyparsing.TokenConverter): label = type(element).__name__.lower() if label == "tokenconverter": @@ -607,10 +663,6 @@ def _to_diagram_element( *args, ) ret = EditablePartial.from_call(railroad.ZeroOrMore, item="") - elif isinstance(element, pyparsing.Group): - ret = EditablePartial.from_call( - railroad.Group, item=None, label=element_results_name - ) elif isinstance(element, pyparsing.Empty) and not element.customName: # Skip unnamed "Empty" elements ret = None @@ -619,10 +671,8 @@ def _to_diagram_element( elif len(exprs) > 0 and not element_results_name: ret = EditablePartial.from_call(railroad.Group, item="", label=name) elif isinstance(element, pyparsing.Regex): - patt = _collapse_verbose_regex(element.pattern) - element.pattern = patt - element._defaultName = None - ret = EditablePartial.from_call(railroad.Terminal, element.defaultName) + collapsed_patt = _collapse_verbose_regex(element.pattern) + ret = EditablePartial.from_call(railroad.Terminal, collapsed_patt) elif len(exprs) > 0: ret = EditablePartial.from_call(railroad.Sequence, items=[]) else: @@ -685,8 +735,10 @@ def _to_diagram_element( if el_id in lookup and lookup[el_id].extract and lookup[el_id].complete: lookup.extract_into_diagram(el_id) if ret is not None: + text = lookup.diagrams[el_id].kwargs["name"] + href = f"#{_make_bookmark(text)}" ret = EditablePartial.from_call( - railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] + railroad.NonTerminal, text=text, href=href ) return ret diff --git a/contrib/python/pyparsing/py3/pyparsing/helpers.py b/contrib/python/pyparsing/py3/pyparsing/helpers.py index d2bd05f3d39a..f781e8713271 100644 --- a/contrib/python/pyparsing/py3/pyparsing/helpers.py +++ b/contrib/python/pyparsing/py3/pyparsing/helpers.py @@ -199,7 +199,8 @@ def one_of( and __diag__.warn_on_multiple_string_args_to_oneof ): warnings.warn( - "More than one string argument passed to one_of, pass" + "warn_on_multiple_string_args_to_oneof:" + " More than one string argument passed to one_of, pass" " choices as a list or space-delimited string", stacklevel=2, ) @@ -779,25 +780,27 @@ def parseImpl(self, instring, loc, doActions=True): _FB.__name__ = "FollowedBy>" ret = Forward() + ret.set_name(f"{base_expr.name}_expression") if isinstance(lpar, str): lpar = Suppress(lpar) if isinstance(rpar, str): rpar = Suppress(rpar) + nested_expr = (lpar + ret + rpar).set_name(f"nested_{base_expr.name}") + # if lpar and rpar are not suppressed, wrap in group if not (isinstance(lpar, Suppress) and isinstance(rpar, Suppress)): - lastExpr = base_expr | Group(lpar + ret + rpar).set_name( - f"nested_{base_expr.name}" - ) + lastExpr = base_expr | Group(nested_expr) else: - lastExpr = base_expr | (lpar + ret + rpar).set_name(f"nested_{base_expr.name}") - root_expr = lastExpr + lastExpr = base_expr | nested_expr arity: int rightLeftAssoc: opAssoc pa: typing.Optional[ParseAction] opExpr1: ParserElement opExpr2: ParserElement + matchExpr: ParserElement + match_lookahead: ParserElement for operDef in op_list: opExpr, arity, rightLeftAssoc, pa = (operDef + (None,))[:4] # type: ignore[assignment] if isinstance(opExpr, str_type): @@ -809,9 +812,9 @@ def parseImpl(self, instring, loc, doActions=True): "if numterms=3, opExpr must be a tuple or list of two expressions" ) opExpr1, opExpr2 = opExpr - term_name = f"{opExpr1}{opExpr2} term" + term_name = f"{opExpr1}{opExpr2} operations" else: - term_name = f"{opExpr} term" + term_name = f"{opExpr} operations" if not 1 <= arity <= 3: raise ValueError("operator must be unary (1), binary (2), or ternary (3)") @@ -821,48 +824,62 @@ def parseImpl(self, instring, loc, doActions=True): thisExpr: ParserElement = Forward().set_name(term_name) thisExpr = typing.cast(Forward, thisExpr) + match_lookahead = And([]) if rightLeftAssoc is OpAssoc.LEFT: if arity == 1: - matchExpr = _FB(lastExpr + opExpr) + Group(lastExpr + opExpr[1, ...]) + match_lookahead = _FB(lastExpr + opExpr) + matchExpr = Group(lastExpr + opExpr[1, ...]) elif arity == 2: if opExpr is not None: - matchExpr = _FB(lastExpr + opExpr + lastExpr) + Group( - lastExpr + (opExpr + lastExpr)[1, ...] - ) + match_lookahead = _FB(lastExpr + opExpr + lastExpr) + matchExpr = Group(lastExpr + (opExpr + lastExpr)[1, ...]) else: - matchExpr = _FB(lastExpr + lastExpr) + Group(lastExpr[2, ...]) + match_lookahead = _FB(lastExpr + lastExpr) + matchExpr = Group(lastExpr[2, ...]) elif arity == 3: - matchExpr = _FB( + match_lookahead = _FB( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr - ) + Group(lastExpr + OneOrMore(opExpr1 + lastExpr + opExpr2 + lastExpr)) + ) + matchExpr = Group( + lastExpr + (opExpr1 + lastExpr + opExpr2 + lastExpr)[1, ...] + ) elif rightLeftAssoc is OpAssoc.RIGHT: if arity == 1: # try to avoid LR with this extra test if not isinstance(opExpr, Opt): opExpr = Opt(opExpr) - matchExpr = _FB(opExpr.expr + thisExpr) + Group(opExpr + thisExpr) + match_lookahead = _FB(opExpr.expr + thisExpr) + matchExpr = Group(opExpr + thisExpr) elif arity == 2: if opExpr is not None: - matchExpr = _FB(lastExpr + opExpr + thisExpr) + Group( - lastExpr + (opExpr + thisExpr)[1, ...] - ) + match_lookahead = _FB(lastExpr + opExpr + thisExpr) + matchExpr = Group(lastExpr + (opExpr + thisExpr)[1, ...]) else: - matchExpr = _FB(lastExpr + thisExpr) + Group( - lastExpr + thisExpr[1, ...] - ) + match_lookahead = _FB(lastExpr + thisExpr) + matchExpr = Group(lastExpr + thisExpr[1, ...]) elif arity == 3: - matchExpr = _FB( + match_lookahead = _FB( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr - ) + Group(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + ) + matchExpr = Group(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + + # suppress lookahead expr from railroad diagrams + match_lookahead.show_in_diagram = False + + # TODO - determine why this statement can't be included in the following + # if pa block + matchExpr = match_lookahead + matchExpr + if pa: if isinstance(pa, (tuple, list)): matchExpr.set_parse_action(*pa) else: matchExpr.set_parse_action(pa) + thisExpr <<= (matchExpr | lastExpr).setName(term_name) lastExpr = thisExpr + ret <<= lastExpr - root_expr.set_name("base_expr") return ret @@ -1009,10 +1026,9 @@ def checkUnindent(s, l, t): return smExpr.set_name("indented block") -# it's easy to get these comment structures wrong - they're very common, so may as well make them available -c_style_comment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + "*/").set_name( - "C style comment" -) +# it's easy to get these comment structures wrong - they're very common, +# so may as well make them available +c_style_comment = Regex(r"/\*(?:[^*]|\*(?!/))*\*\/").set_name("C style comment") "Comment of the form ``/* ... */``" html_comment = Regex(r"").set_name("HTML comment") @@ -1022,8 +1038,8 @@ def checkUnindent(s, l, t): dbl_slash_comment = Regex(r"//(?:\\\n|[^\n])*").set_name("// comment") "Comment of the form ``// ... (to end of line)``" -cpp_style_comment = Combine( - Regex(r"/\*(?:[^*]|\*(?!/))*") + "*/" | dbl_slash_comment +cpp_style_comment = Regex( + r"(?:/\*(?:[^*]|\*(?!/))*\*\/)|(?://(?:\\\n|[^\n])*)" ).set_name("C++ style comment") "Comment of either form :class:`c_style_comment` or :class:`dbl_slash_comment`" diff --git a/contrib/python/pyparsing/py3/pyparsing/results.py b/contrib/python/pyparsing/py3/pyparsing/results.py index 245847832a8f..be834b7e6077 100644 --- a/contrib/python/pyparsing/py3/pyparsing/results.py +++ b/contrib/python/pyparsing/py3/pyparsing/results.py @@ -523,6 +523,7 @@ def as_list(self, *, flatten: bool = False) -> list: result_list = result.as_list() print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj'] """ + def flattened(pr): to_visit = collections.deque([*self]) while to_visit: diff --git a/contrib/python/pyparsing/py3/pyparsing/util.py b/contrib/python/pyparsing/py3/pyparsing/util.py index 1487019c272d..03a60d4fddc2 100644 --- a/contrib/python/pyparsing/py3/pyparsing/util.py +++ b/contrib/python/pyparsing/py3/pyparsing/util.py @@ -192,6 +192,7 @@ class _GroupConsecutive: (2, iter(['m'])) (3, iter(['p', 'q', 'r', 's'])) """ + def __init__(self): self.prev = 0 self.counter = itertools.count() diff --git a/contrib/python/pyparsing/py3/ya.make b/contrib/python/pyparsing/py3/ya.make index 1b36194fab48..e229986ca672 100644 --- a/contrib/python/pyparsing/py3/ya.make +++ b/contrib/python/pyparsing/py3/ya.make @@ -4,7 +4,7 @@ PY3_LIBRARY() PROVIDES(pyparsing) -VERSION(3.2.0) +VERSION(3.2.1) LICENSE(MIT) diff --git a/ya b/ya index bcacf384295a..a850fec58084 100755 --- a/ya +++ b/ya @@ -39,33 +39,33 @@ REGISTRY_ENDPOINT = os.environ.get("YA_REGISTRY_ENDPOINT", "https://devtools-reg PLATFORM_MAP = { "data": { "darwin": { - "md5": "950e88ffc7c851dfbafafb89ba1b1b77", + "md5": "85c76fbd0d23319cce3ad98cd6926ad7", "urls": [ - f"{REGISTRY_ENDPOINT}/7808696359" + f"{REGISTRY_ENDPOINT}/7827466176" ] }, "darwin-arm64": { - "md5": "9d15442d9bb0a0aa6669cea947fe336b", + "md5": "b29d3df1d6e67afaa304bdc0fc811966", "urls": [ - f"{REGISTRY_ENDPOINT}/7808696176" + f"{REGISTRY_ENDPOINT}/7827465506" ] }, "linux-aarch64": { - "md5": "9250ef732fc3a971ff28a126126b4a76", + "md5": "855754159dd5301a07b58ed0c01dc334", "urls": [ - f"{REGISTRY_ENDPOINT}/7808695917" + f"{REGISTRY_ENDPOINT}/7827464666" ] }, "win32-clang-cl": { - "md5": "00674a6eda2cf970ab4c73937c808050", + "md5": "fba50c68c7a0a106dc7370113172c77c", "urls": [ - f"{REGISTRY_ENDPOINT}/7808696543" + f"{REGISTRY_ENDPOINT}/7827466887" ] }, "linux": { - "md5": "9a6d64ab467535c82de4351766427700", + "md5": "8292d28960e74996f913db75c3a880f6", "urls": [ - f"{REGISTRY_ENDPOINT}/7808696801" + f"{REGISTRY_ENDPOINT}/7827467700" ] } } diff --git a/ydb/ci/rightlib.txt b/ydb/ci/rightlib.txt index ca6d071a3a5a..f575271e186e 100644 --- a/ydb/ci/rightlib.txt +++ b/ydb/ci/rightlib.txt @@ -1 +1 @@ -fc7eb64e6147971fb5da235644f47a1df89e0de5 +96a6bd3bf87c39c8257a86654f45eabf6546a778 diff --git a/yql/essentials/core/peephole_opt/yql_opt_peephole_physical.cpp b/yql/essentials/core/peephole_opt/yql_opt_peephole_physical.cpp index 6131a31b1542..f7ba75c96c1f 100644 --- a/yql/essentials/core/peephole_opt/yql_opt_peephole_physical.cpp +++ b/yql/essentials/core/peephole_opt/yql_opt_peephole_physical.cpp @@ -558,11 +558,15 @@ TExprNode::TPtr ExpandEquiJoinImpl(const TExprNode& node, TExprContext& ctx) { if (joinKind == "Cross") { return ctx.Builder(node.Pos()) .Callable("FlatMap") - .Add(0, std::move(list1)) + .Callable(0, "Collect") + .Add(0, std::move(list1)) + .Seal() .Lambda(1) .Param("left") .Callable("Map") - .Add(0, std::move(list2)) + .Callable(0, "Collect") + .Add(0, std::move(list2)) + .Seal() .Lambda(1) .Param("right") .Callable("AsStruct") diff --git a/yql/essentials/core/yql_expr_type_annotation.cpp b/yql/essentials/core/yql_expr_type_annotation.cpp index 7da6bd439abc..56626afe87ee 100644 --- a/yql/essentials/core/yql_expr_type_annotation.cpp +++ b/yql/essentials/core/yql_expr_type_annotation.cpp @@ -393,6 +393,25 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& .Build(); return IGraphTransformer::TStatus::Repeat; + } else if (IsDataTypeDecimal(from) && IsDataTypeDecimal(to)) { + auto* sourceDecimal = sourceType.Cast(); + auto* expectedDecimal = expectedType.Cast(); + ui8 p1 = FromString(sourceDecimal->GetParamOne()), s1 = FromString(sourceDecimal->GetParamTwo()); + ui8 p2 = FromString(expectedDecimal->GetParamOne()), s2 = FromString(expectedDecimal->GetParamTwo()); + if (s1 > s2) { + TString message = TStringBuilder() << "Implicit decimal cast would lose precision"; + auto issue = TIssue(node->Pos(ctx), message); + ctx.AddError(issue); + return IGraphTransformer::TStatus::Error; + } + if (p1 - s1 > p2 - s2) { + TString message = TStringBuilder() << "Implicit decimal cast would narrow the range"; + auto issue = TIssue(node->Pos(ctx), message); + ctx.AddError(issue); + return IGraphTransformer::TStatus::Error; + } + allow = true; + useCast = true; } if (!allow || !isSafe) { diff --git a/yql/essentials/minikql/aligned_page_pool.cpp b/yql/essentials/minikql/aligned_page_pool.cpp index ec9199bc272c..3e69f83c9945 100644 --- a/yql/essentials/minikql/aligned_page_pool.cpp +++ b/yql/essentials/minikql/aligned_page_pool.cpp @@ -1,7 +1,7 @@ #include "aligned_page_pool.h" -#include "util/string/builder.h" #include +#include #include #include #include @@ -26,6 +26,30 @@ static_assert(MaxMidSize == 64 * 1024 * 1024, "Upper memory block 64 Mb"); namespace { +size_t GetMemoryMapsCount() { + size_t lineCount = 0; + TString line; +#if defined(_unix_) + TFileInput file("/proc/self/maps"); + while (file.ReadLine(line)) ++lineCount; +#endif + return lineCount; +} + +ui64 GetMaxMemoryMaps() { + ui64 maxMapCount = 0; +#if defined(_unix_) + maxMapCount = FromString(TFileInput("/proc/sys/vm/max_map_count").ReadAll()); +#endif + return maxMapCount; +} + +TString GetMemoryMapsString() { + TStringStream ss; + ss << " (maps: " << GetMemoryMapsCount() << " vs " << GetMaxMemoryMaps() << ")"; + return ss.Str(); +} + template class TGlobalPools; @@ -146,9 +170,15 @@ class TGlobalPools { void DoMunmap(void* addr, size_t size) { if (Y_UNLIKELY(0 != T::Munmap(addr, size))) { + TStringStream mmaps; + const auto lastError = LastSystemError(); + if (lastError == ENOMEM) { + mmaps << GetMemoryMapsString(); + } + ythrow yexception() << "Munmap(0x" << IntToString<16>(reinterpret_cast(addr)) - << ", " << size << ") failed: " << LastSystemErrorText(); + << ", " << size << ") failed: " << LastSystemErrorText(lastError) << mmaps.Str(); } i64 prev = TotalMmappedBytes.fetch_sub(size); @@ -493,7 +523,14 @@ void* TAlignedPagePoolImpl::Alloc(size_t size) { auto allocSize = size + ALLOC_AHEAD_PAGES * POOL_PAGE_SIZE; void* mem = globalPool.DoMmap(allocSize); if (Y_UNLIKELY(MAP_FAILED == mem)) { - ythrow yexception() << "Mmap failed to allocate " << (size + POOL_PAGE_SIZE) << " bytes: " << LastSystemErrorText(); + TStringStream mmaps; + const auto lastError = LastSystemError(); + if (lastError == ENOMEM) { + mmaps << GetMemoryMapsString(); + } + + ythrow yexception() << "Mmap failed to allocate " << (size + POOL_PAGE_SIZE) << " bytes: " + << LastSystemErrorText(lastError) << mmaps.Str(); } res = AlignUp(mem, POOL_PAGE_SIZE); @@ -641,7 +678,13 @@ void* GetAlignedPage(ui64 size) { auto allocSize = Max(MaxMidSize, size); void* mem = pool.DoMmap(allocSize); if (Y_UNLIKELY(MAP_FAILED == mem)) { - ythrow yexception() << "Mmap failed to allocate " << allocSize << " bytes: " << LastSystemErrorText(); + TStringStream mmaps; + const auto lastError = LastSystemError(); + if (lastError == ENOMEM) { + mmaps << GetMemoryMapsString(); + } + + ythrow yexception() << "Mmap failed to allocate " << allocSize << " bytes: " << LastSystemErrorText(lastError) << mmaps.Str(); } if (size < MaxMidSize) { diff --git a/yql/essentials/minikql/comp_nodes/mkql_append.cpp b/yql/essentials/minikql/comp_nodes/mkql_append.cpp index 41436b098555..82894c6d108e 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_append.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_append.cpp @@ -53,44 +53,20 @@ class TAppendWrapper : public TMutableCodegeneratorNode> BranchInst::Create(work, done, check, block); block = work; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(left->getType(), {factory->getType(), left->getType(), right->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory, left, right}, "res", block); - result->addIncoming(res, block); - } else { - const auto retPtr = new AllocaInst(left->getType(), 0U, "ret_ptr", block); - const auto itemPtr = new AllocaInst(right->getType(), 0U, "item_ptr", block); - new StoreInst(left, retPtr, block); - new StoreInst(right, itemPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), retPtr->getType(), itemPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, retPtr, itemPtr}, "", block); - const auto res = new LoadInst(left->getType(), retPtr, "res", block); - result->addIncoming(res, block); - } + const auto funType = FunctionType::get(left->getType(), {factory->getType(), left->getType(), right->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory, left, right}, "res", block); + result->addIncoming(res, block); BranchInst::Create(done, block); block = done; return result; } else { - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(left->getType(), {factory->getType(), left->getType(), right->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory, left, right}, "res", block); - return res; - } else { - const auto retPtr = new AllocaInst(left->getType(), 0U, "ret_ptr", block); - const auto itemPtr = new AllocaInst(right->getType(), 0U, "item_ptr", block); - new StoreInst(left, retPtr, block); - new StoreInst(right, itemPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), retPtr->getType(), itemPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, retPtr, itemPtr}, "", block); - const auto res = new LoadInst(left->getType(), retPtr, "res", block); - return res; - } + const auto funType = FunctionType::get(left->getType(), {factory->getType(), left->getType(), right->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory, left, right}, "res", block); + return res; } } #endif diff --git a/yql/essentials/minikql/comp_nodes/mkql_block_compress.cpp b/yql/essentials/minikql/comp_nodes/mkql_block_compress.cpp index 3db1e34a4c8d..74e0dca0d1d4 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_block_compress.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_block_compress.cpp @@ -51,15 +51,12 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode(&GetBitmapScalarValue)); - const auto getBitmapType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(bitmapType, { valueType }, false): - FunctionType::get(bitmapType, { ptrValueType }, false); + const auto getBitmapType = FunctionType::get(bitmapType, { valueType }, false); const auto getBitmap = ctx.Codegen.GetModule().getOrInsertFunction(name, getBitmapType); const auto work = BasicBlock::Create(context, "work", ctx.Func); @@ -83,7 +80,7 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode; auto& context = ctx.Codegen.GetContext(); const auto valueType = Type::getInt128Ty(context); - const auto ptrValueType = PointerType::getUnqual(valueType); const auto statusType = Type::getInt32Ty(context); const auto sizeType = Type::getInt64Ty(context); @@ -167,9 +163,7 @@ using TBaseComputation = TStatelessWideFlowCodegeneratorNode; const auto name = "GetBitmapPopCountCount"; ctx.Codegen.AddGlobalMapping(name, reinterpret_cast(&GetBitmapPopCountCount)); - const auto getPopCountType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(sizeType, { valueType }, false): - FunctionType::get(sizeType, { ptrValueType }, false); + const auto getPopCountType = FunctionType::get(sizeType, { valueType }, false); const auto getPopCount = ctx.Codegen.GetModule().getOrInsertFunction(name, getPopCountType); const auto loop = BasicBlock::Create(context, "loop", ctx.Func); @@ -191,7 +185,7 @@ using TBaseComputation = TStatelessWideFlowCodegeneratorNode; block = work; const auto bitmapValue = getres.second[BitmapIndex_](ctx, block); - const auto pops = CallInst::Create(getPopCount, { WrapArgumentForWindows(bitmapValue, ctx, block) }, "pops", block); + const auto pops = CallInst::Create(getPopCount, { bitmapValue }, "pops", block); ValueCleanup(EValueRepresentation::Any, bitmapValue, ctx, block); @@ -413,7 +407,7 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode; block = good; const auto bitmap = getres.second[BitmapIndex_](ctx, block); - const auto bitmapArg = WrapArgumentForWindows(bitmap, ctx, block); + const auto bitmapArg = bitmap; const auto stepType = Type::getInt8Ty(context); const auto checkFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Check)); diff --git a/yql/essentials/minikql/comp_nodes/mkql_block_skiptake.cpp b/yql/essentials/minikql/comp_nodes/mkql_block_skiptake.cpp index f5671b2635f6..2496b75ca60c 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_block_skiptake.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_block_skiptake.cpp @@ -51,7 +51,6 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNodegetEntryBlock().back(); @@ -64,9 +63,7 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode(&GetBlockCount)); - const auto getCountType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(indexType, { valueType }, false): - FunctionType::get(indexType, { ptrValueType }, false); + const auto getCountType = FunctionType::get(indexType, { valueType }, false); const auto getCount = ctx.Codegen.GetModule().getOrInsertFunction(name, getCountType); const auto init = BasicBlock::Create(context, "init", ctx.Func); @@ -119,7 +116,7 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNodegetEntryBlock().back(); @@ -285,9 +281,7 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode(&GetBlockCount)); - const auto getCountType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(indexType, { valueType }, false): - FunctionType::get(indexType, { ptrValueType }, false); + const auto getCountType = FunctionType::get(indexType, { valueType }, false); const auto getCount = ctx.Codegen.GetModule().getOrInsertFunction(name, getCountType); const auto init = BasicBlock::Create(context, "init", ctx.Func); @@ -332,7 +326,7 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode(&GetBlockCount)); - const auto getCountType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(indexType, { valueType }, false): - FunctionType::get(indexType, { ptrValueType }, false); + const auto getCountType = FunctionType::get(indexType, { valueType }, false); const auto getCount = ctx.Codegen.GetModule().getOrInsertFunction(name, getCountType); const auto make = BasicBlock::Create(context, "make", ctx.Func); @@ -633,7 +630,7 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode; const auto self = CastInst::Create(Instruction::IntToPtr, ConstantInt::get(Type::getInt64Ty(context), uintptr_t(this)), ptrType, "self", block); const auto asScalarFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TAsScalarWrapper::AsScalar)); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto asScalarType = FunctionType::get(Type::getInt128Ty(context), {self->getType(), value->getType(), ctx.Ctx->getType()}, false); - const auto asScalarFuncPtr = CastInst::Create(Instruction::IntToPtr, asScalarFunc, PointerType::getUnqual(asScalarType), "function", block); - return CallInst::Create(asScalarType, asScalarFuncPtr, {self, value, ctx.Ctx}, "scalar", block); - } else { - const auto valuePtr = new AllocaInst(value->getType(), 0U, "value", block); - new StoreInst(value, valuePtr, block); - const auto asScalarType = FunctionType::get(Type::getVoidTy(context), {self->getType(), valuePtr->getType(), valuePtr->getType(), ctx.Ctx->getType()}, false); - const auto asScalarFuncPtr = CastInst::Create(Instruction::IntToPtr, asScalarFunc, PointerType::getUnqual(asScalarType), "function", block); - CallInst::Create(asScalarType, asScalarFuncPtr, {self, valuePtr, valuePtr, ctx.Ctx}, "", block); - return new LoadInst(value->getType(), valuePtr, "result", block); - } + const auto asScalarType = FunctionType::get(Type::getInt128Ty(context), {self->getType(), value->getType(), ctx.Ctx->getType()}, false); + const auto asScalarFuncPtr = CastInst::Create(Instruction::IntToPtr, asScalarFunc, PointerType::getUnqual(asScalarType), "function", block); + return CallInst::Create(asScalarType, asScalarFuncPtr, {self, value, ctx.Ctx}, "scalar", block); } #endif private: @@ -932,20 +920,9 @@ using TBaseComputation = TMutableCodegeneratorNode; const auto self = CastInst::Create(Instruction::IntToPtr, ConstantInt::get(Type::getInt64Ty(context), uintptr_t(this)), ptrType, "self", block); const auto replicateFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TReplicateScalarWrapper::Replicate)); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto replicateType = FunctionType::get(Type::getInt128Ty(context), {self->getType(), value->getType(), count->getType(), ctx.Ctx->getType()}, false); - const auto replicateFuncPtr = CastInst::Create(Instruction::IntToPtr, replicateFunc, PointerType::getUnqual(replicateType), "function", block); - return CallInst::Create(replicateType, replicateFuncPtr, {self, value, count, ctx.Ctx}, "replicate", block); - } else { - const auto valuePtr = new AllocaInst(value->getType(), 0U, "value", block); - const auto countPtr = new AllocaInst(count->getType(), 0U, "count", block); - new StoreInst(value, valuePtr, block); - new StoreInst(count, countPtr, block); - const auto replicateType = FunctionType::get(Type::getVoidTy(context), {self->getType(), valuePtr->getType(), valuePtr->getType(), countPtr->getType(), ctx.Ctx->getType()}, false); - const auto replicateFuncPtr = CastInst::Create(Instruction::IntToPtr, replicateFunc, PointerType::getUnqual(replicateType), "function", block); - CallInst::Create(replicateType, replicateFuncPtr, {self, valuePtr, valuePtr, countPtr, ctx.Ctx}, "", block); - return new LoadInst(value->getType(), valuePtr, "result", block); - } + const auto replicateType = FunctionType::get(Type::getInt128Ty(context), {self->getType(), value->getType(), count->getType(), ctx.Ctx->getType()}, false); + const auto replicateFuncPtr = CastInst::Create(Instruction::IntToPtr, replicateFunc, PointerType::getUnqual(replicateType), "function", block); + return CallInst::Create(replicateType, replicateFuncPtr, {self, value, count, ctx.Ctx}, "replicate", block); } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_callable.cpp b/yql/essentials/minikql/comp_nodes/mkql_callable.cpp index 4f49d4e4fef5..76f703137f0a 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_callable.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_callable.cpp @@ -104,24 +104,16 @@ class TCallableWrapper : public TCustomValueCodegeneratorNode const auto argsType = ArrayType::get(valueType, ArgNodes.size()); const auto contextType = GetCompContextType(context); - const auto funcType = codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows ? - FunctionType::get(valueType, {PointerType::getUnqual(contextType), PointerType::getUnqual(argsType)}, false): - FunctionType::get(Type::getVoidTy(context), {PointerType::getUnqual(valueType), PointerType::getUnqual(contextType), PointerType::getUnqual(argsType)}, false); + const auto funcType = + FunctionType::get(valueType, {PointerType::getUnqual(contextType), PointerType::getUnqual(argsType)}, false); TCodegenContext ctx(codegen); ctx.Func = cast(module.getOrInsertFunction(name.c_str(), funcType).getCallee()); DISubprogramAnnotator annotator(ctx, ctx.Func); - auto args = ctx.Func->arg_begin(); - const auto resultArg = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? &*args++ : nullptr; - if (resultArg) { - resultArg->addAttr(Attribute::StructRet); - resultArg->addAttr(Attribute::NoAlias); - } - ctx.Ctx = &*args; const auto argsPtr = &*++args; @@ -140,12 +132,7 @@ class TCallableWrapper : public TCustomValueCodegeneratorNode const auto result = GetNodeValue(ResultNode, ctx, block); - if (resultArg) { - new StoreInst(result, resultArg, block); - ReturnInst::Create(context, block); - } else { - ReturnInst::Create(context, result, block); - } + ReturnInst::Create(context, result, block); return ctx.Func; } diff --git a/yql/essentials/minikql/comp_nodes/mkql_chain1_map.cpp b/yql/essentials/minikql/comp_nodes/mkql_chain1_map.cpp index c12d9917c594..56c4b8c9acf6 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_chain1_map.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_chain1_map.cpp @@ -238,7 +238,7 @@ class TBaseChain1MapWrapper { return f; const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = IsStream ? Type::getInt32Ty(context) : Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(valueType)}, false); @@ -257,8 +257,7 @@ class TBaseChain1MapWrapper { const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto good = BasicBlock::Create(context, "good", ctx.Func); const auto done = BasicBlock::Create(context, "done", ctx.Func); @@ -473,20 +472,10 @@ class TListChain1MapWrapper : public TBothWaysCodegeneratorNodegetType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); - map->addIncoming(value, block); - } else { - const auto resultPtr = new AllocaInst(list->getType(), 0U, "return", block); - new StoreInst(list, resultPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType(), resultPtr->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx, resultPtr}, "", block); - const auto value = new LoadInst(list->getType(), resultPtr, "value", block); - map->addIncoming(value, block); - } + const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); + map->addIncoming(value, block); BranchInst::Create(done, block); } diff --git a/yql/essentials/minikql/comp_nodes/mkql_chain_map.cpp b/yql/essentials/minikql/comp_nodes/mkql_chain_map.cpp index e0d9ff1f1303..000387838003 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_chain_map.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_chain_map.cpp @@ -230,7 +230,7 @@ class TBaseChainMapWrapper { return f; const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = IsStream ? Type::getInt32Ty(context) : Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(valueType), PointerType::getUnqual(valueType)}, false); @@ -250,8 +250,7 @@ class TBaseChainMapWrapper { const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto init = BasicBlock::Create(context, "init", ctx.Func); const auto work = BasicBlock::Create(context, "work", ctx.Func); @@ -456,22 +455,10 @@ class TListChainMapWrapper : public TBothWaysCodegeneratorNodegetType() , {self->getType(), ctx.Ctx->getType(), list->getType(), init->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list, init}, "value", block); - map->addIncoming(value, block); - } else { - const auto resultPtr = new AllocaInst(list->getType(), 0U, "return", block); - const auto initPtr = new AllocaInst(init->getType(), 0U, "init", block); - new StoreInst(list, resultPtr, block); - new StoreInst(init, initPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType(), resultPtr->getType(), initPtr->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx, resultPtr, initPtr}, "", block); - const auto value = new LoadInst(list->getType(), resultPtr, "value", block); - map->addIncoming(value, block); - } + const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType(), init->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list, init}, "value", block); + map->addIncoming(value, block); BranchInst::Create(done, block); } diff --git a/yql/essentials/minikql/comp_nodes/mkql_chopper.cpp b/yql/essentials/minikql/comp_nodes/mkql_chopper.cpp index f3b5aecf0bc3..eb93380e182e 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_chopper.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_chopper.cpp @@ -554,7 +554,7 @@ class TChopperWrapper : public TCustomValueCodegeneratorNode { MKQL_ENSURE(codegenKeyArg, "Key arg must be codegenerator node."); const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); const auto stateType = Type::getInt8Ty(context); @@ -578,8 +578,7 @@ class TChopperWrapper : public TCustomValueCodegeneratorNode { auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto first = new LoadInst(stateType, stateArg, "first", block); const auto reload = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_EQ, first, ConstantInt::get(stateType, ui8(EState::Next)), "reload", block); @@ -650,7 +649,7 @@ class TChopperWrapper : public TCustomValueCodegeneratorNode { MKQL_ENSURE(codegenInput, "Input arg must be codegenerator node."); const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); const auto stateType = Type::getInt8Ty(context); @@ -680,8 +679,7 @@ class TChopperWrapper : public TCustomValueCodegeneratorNode { auto block = main; - const auto input = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, inputArg, "load_input", false, block) : static_cast(inputArg); + const auto input = static_cast(inputArg); BranchInst::Create(loop, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_collect.cpp b/yql/essentials/minikql/comp_nodes/mkql_collect.cpp index 836bb2726055..ad23aeb44991 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_collect.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_collect.cpp @@ -42,19 +42,10 @@ using TBaseComputation = TMutableCodegeneratorRootNode; const auto list = PHINode::Create(valueType, 2U, "list", work); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(valueType, {factory->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, empty, PointerType::getUnqual(funType), "empty", block); - const auto first = CallInst::Create(funType, funcPtr, {factory}, "init", block); - list->addIncoming(first, block); - } else { - const auto ptr = new AllocaInst(valueType, 0U, "ptr", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), ptr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, empty, PointerType::getUnqual(funType), "empty", block); - CallInst::Create(funType, funcPtr, {factory, ptr}, "", block); - const auto first = new LoadInst(valueType, ptr, "init", block); - list->addIncoming(first, block); - } + const auto funType = FunctionType::get(valueType, {factory->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, empty, PointerType::getUnqual(funType), "empty", block); + const auto first = CallInst::Create(funType, funcPtr, {factory}, "init", block); + list->addIncoming(first, block); BranchInst::Create(work, block); @@ -69,22 +60,10 @@ using TBaseComputation = TMutableCodegeneratorRootNode; { block = good; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(valueType, {factory->getType(), list->getType(), item->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, append, PointerType::getUnqual(funType), "append", block); - const auto next = CallInst::Create(funType, funcPtr, {factory, list, item}, "next", block); - list->addIncoming(next, block); - } else { - const auto retPtr = new AllocaInst(list->getType(), 0U, "ret_ptr", block); - const auto itemPtr = new AllocaInst(item->getType(), 0U, "item_ptr", block); - new StoreInst(list, retPtr, block); - new StoreInst(item, itemPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), retPtr->getType(), itemPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, append, PointerType::getUnqual(funType), "append", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, retPtr, itemPtr}, "", block); - const auto next = new LoadInst(list->getType(), retPtr, "next", block); - list->addIncoming(next, block); - } + const auto funType = FunctionType::get(valueType, {factory->getType(), list->getType(), item->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, append, PointerType::getUnqual(funType), "append", block); + const auto next = CallInst::Create(funType, funcPtr, {factory, list, item}, "next", block); + list->addIncoming(next, block); BranchInst::Create(work, block); } @@ -154,39 +133,19 @@ class TCollectWrapper : public TMutableCodegeneratorNode BranchInst::Create(work, done, null, block); block = work; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(seq->getType(), {factory->getType(), seq->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory, seq}, "res", block); - result->addIncoming(res, block); - } else { - const auto ptr = new AllocaInst(seq->getType(), 0U, "ptr", block); - new StoreInst(seq, ptr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), ptr->getType(), ptr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, ptr, ptr}, "", block); - const auto res = new LoadInst(seq->getType(), ptr, "res", block); - result->addIncoming(res, block); - } + const auto funType = FunctionType::get(seq->getType(), {factory->getType(), seq->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory, seq}, "res", block); + result->addIncoming(res, block); BranchInst::Create(done, block); block = done; return result; } else { - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(seq->getType(), {factory->getType(), seq->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory, seq}, "res", block); - return res; - } else { - const auto ptr = new AllocaInst(seq->getType(), 0U, "ptr", block); - new StoreInst(seq, ptr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), ptr->getType(), ptr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, ptr, ptr}, "", block); - const auto res = new LoadInst(seq->getType(), ptr, "res", block); - return res; - } + const auto funType = FunctionType::get(seq->getType(), {factory->getType(), seq->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory, seq}, "res", block); + return res; } } #endif diff --git a/yql/essentials/minikql/comp_nodes/mkql_combine.cpp b/yql/essentials/minikql/comp_nodes/mkql_combine.cpp index dffe2e1c5aa4..cc618593bcbf 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_combine.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_combine.cpp @@ -354,12 +354,7 @@ class TCombineCoreFlowWrapper: public std::conditional_tCreateSetValue(ctx, block, key); - const auto keyParam = NYql::NCodegen::ETarget::Windows == ctx.Codegen.GetEffectiveTarget() ? - new AllocaInst(key->getType(), 0U, "key_param", &main->back()) : key; - - if (NYql::NCodegen::ETarget::Windows == ctx.Codegen.GetEffectiveTarget()) { - new StoreInst(key, keyParam, block); - } + const auto keyParam = key; const auto atFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::At)); const auto atType = FunctionType::get(ptrValueType, {stateArg->getType(), keyParam->getType()}, false); @@ -722,7 +717,7 @@ class TCombineCoreWrapper: public TCustomValueCodegeneratorNode(ptrValueType) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); @@ -830,8 +825,7 @@ class TCombineCoreWrapper: public TCustomValueCodegeneratorNode(containerArg); + const auto stream = static_cast(containerArg); BranchInst::Create(loop, block); @@ -850,12 +844,7 @@ class TCombineCoreWrapper: public TCustomValueCodegeneratorNodeCreateSetValue(ctx, block, key); - const auto keyParam = NYql::NCodegen::ETarget::Windows == ctx.Codegen.GetEffectiveTarget() ? - new AllocaInst(key->getType(), 0U, "key_param", &main->back()) : key; - - if (NYql::NCodegen::ETarget::Windows == ctx.Codegen.GetEffectiveTarget()) { - new StoreInst(key, keyParam, block); - } + const auto keyParam = key; const auto atFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::At)); const auto atType = FunctionType::get(ptrValueType, {stateArg->getType(), keyParam->getType()}, false); diff --git a/yql/essentials/minikql/comp_nodes/mkql_condense.cpp b/yql/essentials/minikql/comp_nodes/mkql_condense.cpp index f7c262327357..ff729dbbed65 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_condense.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_condense.cpp @@ -352,7 +352,7 @@ class TCondenseWrapper : public TCustomValueCodegeneratorNode(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); const auto stateType = Type::getInt8Ty(context); @@ -373,8 +373,7 @@ class TCondenseWrapper : public TCustomValueCodegeneratorNode(containerArg); + const auto container = static_cast(containerArg); const auto state = new LoadInst(stateType, statePtr, "state", block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_condense1.cpp b/yql/essentials/minikql/comp_nodes/mkql_condense1.cpp index 1cf679ed07fe..a573b480720a 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_condense1.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_condense1.cpp @@ -370,7 +370,7 @@ class TCondense1Wrapper : public TCustomValueCodegeneratorNode(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); const auto stateType = Type::getInt8Ty(context); @@ -391,8 +391,7 @@ class TCondense1Wrapper : public TCustomValueCodegeneratorNode(containerArg); + const auto container = static_cast(containerArg); const auto step = BasicBlock::Create(context, "step", ctx.Func); const auto none = BasicBlock::Create(context, "none", ctx.Func); diff --git a/yql/essentials/minikql/comp_nodes/mkql_decimal_div.cpp b/yql/essentials/minikql/comp_nodes/mkql_decimal_div.cpp index 394ddbc4f515..be561df7e3fa 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_decimal_div.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_decimal_div.cpp @@ -46,13 +46,11 @@ class TDecimalDivWrapper : public TMutableCodegeneratorNode(&DecimalMulAndDivNormalMultiplier)); - const auto fnType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, valType, valType }, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, valTypePtr, valTypePtr }, false); + const auto fnType = + FunctionType::get(valType, { valType, valType, valType }, false); const auto func = ctx.Codegen.GetModule().getOrInsertFunction(name, fnType); const auto left = GetNodeValue(Left, ctx, block); @@ -73,20 +71,7 @@ class TDecimalDivWrapper : public TMutableCodegeneratorNode(&DecimalDiv)); - const auto fnType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, valType }, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, valTypePtr }, false); + const auto fnType = + FunctionType::get(valType, { valType, valType }, false); const auto func = ctx.Codegen.GetModule().getOrInsertFunction(name, fnType); const auto left = GetNodeValue(Left, ctx, block); @@ -199,19 +169,7 @@ class TDecimalDivIntegralWrapper : public TMutableCodegeneratorNode(new SExtInst(GetterFor(right, context, block), valType, "sext", block)): static_cast(new ZExtInst(GetterFor(right, context, block), valType, "zext", block)); - Value* div; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - div = CallInst::Create(func, {GetterForInt128(left, block), cast}, "div", block); - } else { - const auto retPtr = new AllocaInst(valType, 0U, "ret_ptr", block); - const auto arg1Ptr = new AllocaInst(valType, 0U, "arg1", block); - const auto arg2Ptr = new AllocaInst(valType, 0U, "arg2", block); - new StoreInst(GetterForInt128(left, block), arg1Ptr, block); - new StoreInst(cast, arg2Ptr, block); - CallInst::Create(func, { retPtr, arg1Ptr, arg2Ptr }, "", block); - div = new LoadInst(valType, retPtr, "res", block); - } - + const auto div = CallInst::Create(func, {GetterForInt128(left, block), cast}, "div", block); result->addIncoming(SetterForInt128(div, block), block); BranchInst::Create(done, block); @@ -221,18 +179,7 @@ class TDecimalDivIntegralWrapper : public TMutableCodegeneratorNode() ? static_cast(new SExtInst(GetterFor(right, context, block), valType, "sext", block)): static_cast(new ZExtInst(GetterFor(right, context, block), valType, "zext", block)); - Value* div; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - div = CallInst::Create(func, {GetterForInt128(left, block), cast}, "div", block); - } else { - const auto retPtr = new AllocaInst(valType, 0U, "ret_ptr", block); - const auto arg1Ptr = new AllocaInst(valType, 0U, "arg1", block); - const auto arg2Ptr = new AllocaInst(valType, 0U, "arg2", block); - new StoreInst(GetterForInt128(left, block), arg1Ptr, block); - new StoreInst(cast, arg2Ptr, block); - CallInst::Create(func, { retPtr, arg1Ptr, arg2Ptr }, "", block); - div = new LoadInst(valType, retPtr, "res", block); - } + const auto div = CallInst::Create(func, {GetterForInt128(left, block), cast}, "div", block); return SetterForInt128(div, block); } } diff --git a/yql/essentials/minikql/comp_nodes/mkql_decimal_mul.cpp b/yql/essentials/minikql/comp_nodes/mkql_decimal_mul.cpp index a92f8fa87913..80dd95b79e74 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_decimal_mul.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_decimal_mul.cpp @@ -47,17 +47,12 @@ class TDecimalMulWrapper : public TMutableCodegeneratorNode 1; const auto name = useMulAddDiv ? "DecimalMulAndDivNormalDivider" : "DecimalMul"; const auto fnType = useMulAddDiv ? - NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, valType, valType }, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, valTypePtr, valTypePtr }, false): - NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, valType}, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, valTypePtr }, false); + FunctionType::get(valType, { valType, valType, valType }, false): + FunctionType::get(valType, { valType, valType}, false); ctx.Codegen.AddGlobalMapping(name, useMulAddDiv ? reinterpret_cast(&DecimalMulAndDivNormalDivider) : reinterpret_cast(&DecimalMul)); const auto func = ctx.Codegen.GetModule().getOrInsertFunction(name, fnType); @@ -82,31 +77,9 @@ class TDecimalMulWrapper : public TMutableCodegeneratorNode(&DecimalMul)); - const auto fnType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, valType }, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, valTypePtr }, false); + const auto fnType = + FunctionType::get(valType, { valType, valType }, false); const auto func = ctx.Codegen.GetModule().getOrInsertFunction(name, fnType); const auto left = GetNodeValue(Left, ctx, block); @@ -236,18 +185,7 @@ class TDecimalMulIntegralWrapper : public TMutableCodegeneratorNode() ? static_cast(new SExtInst(GetterFor(right, context, block), valType, "sext", block)): static_cast(new ZExtInst(GetterFor(right, context, block), valType, "zext", block)); - Value* mul; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - mul = CallInst::Create(func, {GetterForInt128(left, block), cast}, "div", block); - } else { - const auto retPtr = new AllocaInst(valType, 0U, "ret_ptr", block); - const auto arg1Ptr = new AllocaInst(valType, 0U, "arg1", block); - const auto arg2Ptr = new AllocaInst(valType, 0U, "arg2", block); - new StoreInst(GetterForInt128(left, block), arg1Ptr, block); - new StoreInst(cast, arg2Ptr, block); - CallInst::Create(func, { retPtr, arg1Ptr, arg2Ptr }, "", block); - mul = new LoadInst(valType, retPtr, "res", block); - } + const auto mul = CallInst::Create(func, {GetterForInt128(left, block), cast}, "div", block); const auto ok = NDecimal::GenInBounds(mul, NDecimal::GenConstant(-Bound, context), NDecimal::GenConstant(+Bound, context), block); const auto nan = NDecimal::GenIsNonComparable(mul, context, block); @@ -266,18 +204,7 @@ class TDecimalMulIntegralWrapper : public TMutableCodegeneratorNode() ? static_cast(new SExtInst(GetterFor(right, context, block), valType, "sext", block)): static_cast(new ZExtInst(GetterFor(right, context, block), valType, "zext", block)); - Value* mul; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - mul = CallInst::Create(func, {GetterForInt128(left, block), cast}, "div", block); - } else { - const auto retPtr = new AllocaInst(valType, 0U, "ret_ptr", block); - const auto arg1Ptr = new AllocaInst(valType, 0U, "arg1", block); - const auto arg2Ptr = new AllocaInst(valType, 0U, "arg2", block); - new StoreInst(GetterForInt128(left, block), arg1Ptr, block); - new StoreInst(cast, arg2Ptr, block); - CallInst::Create(func, { retPtr, arg1Ptr, arg2Ptr }, "", block); - mul = new LoadInst(valType, retPtr, "res", block); - } + const auto mul = CallInst::Create(func, {GetterForInt128(left, block), cast}, "div", block); const auto ok = NDecimal::GenInBounds(mul, NDecimal::GenConstant(-Bound, context), NDecimal::GenConstant(+Bound, context), block); const auto nan = NDecimal::GenIsNonComparable(mul, context, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_dictitems.cpp b/yql/essentials/minikql/comp_nodes/mkql_dictitems.cpp index 54d839e9c74c..8790089972df 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_dictitems.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_dictitems.cpp @@ -159,7 +159,7 @@ class TDictItemsWrapper : public TCustomValueCodegeneratorNode(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(valueType)}, false); @@ -178,8 +178,7 @@ class TDictItemsWrapper : public TCustomValueCodegeneratorNode(containerArg); + const auto container = static_cast(containerArg); const auto good = BasicBlock::Create(context, "good", ctx.Func); const auto done = BasicBlock::Create(context, "done", ctx.Func); diff --git a/yql/essentials/minikql/comp_nodes/mkql_discard.cpp b/yql/essentials/minikql/comp_nodes/mkql_discard.cpp index 1fbbf6ac61a3..969f02973127 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_discard.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_discard.cpp @@ -167,7 +167,7 @@ class TDiscardWrapper : public TCustomValueCodegeneratorNode { return f; const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(valueType)}, false); @@ -185,8 +185,7 @@ class TDiscardWrapper : public TCustomValueCodegeneratorNode { const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto loop = BasicBlock::Create(context, "loop", ctx.Func); diff --git a/yql/essentials/minikql/comp_nodes/mkql_enumerate.cpp b/yql/essentials/minikql/comp_nodes/mkql_enumerate.cpp index 9905e97d1ac1..61887fe000e1 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_enumerate.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_enumerate.cpp @@ -133,20 +133,10 @@ class TEnumerateWrapper : public TMutableCodegeneratorNode { const auto ptrType = PointerType::getUnqual(StructType::get(context)); const auto self = CastInst::Create(Instruction::IntToPtr, ConstantInt::get(Type::getInt64Ty(context), uintptr_t(this)), ptrType, "self", block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto signature = FunctionType::get(list->getType(), {self->getType(), ctx.Ctx->getType(), list->getType(), start->getType(), step->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - const auto output = CallInst::Create(signature, creator, {self, ctx.Ctx, list, start, step}, "output", block); - return output; - } else { - const auto place = new AllocaInst(list->getType(), 0U, "place", block); - new StoreInst(list, place, block); - const auto signature = FunctionType::get(Type::getVoidTy(context), {self->getType(), place->getType(), ctx.Ctx->getType(), place->getType(), start->getType(), step->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - CallInst::Create(signature, creator, {self, place, ctx.Ctx, place, start, step}, "", block); - const auto output = new LoadInst(list->getType(), place, "output", block); - return output; - } + const auto signature = FunctionType::get(list->getType(), {self->getType(), ctx.Ctx->getType(), list->getType(), start->getType(), step->getType()}, false); + const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); + const auto output = CallInst::Create(signature, creator, {self, ctx.Ctx, list, start, step}, "output", block); + return output; } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_extend.cpp b/yql/essentials/minikql/comp_nodes/mkql_extend.cpp index 75033de49dd7..1be59576c0ae 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_extend.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_extend.cpp @@ -566,19 +566,10 @@ using TBaseComputation = TMutableCodegeneratorNode)); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(valueType, {factory->getType(), array->getType(), size->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory, array, size}, "res", block); - return res; - } else { - const auto retPtr = new AllocaInst(valueType, 0U, "ret_ptr", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), array->getType(), size->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, array, size}, "", block); - const auto res = new LoadInst(valueType, retPtr, "res", block); - return res; - } + const auto funType = FunctionType::get(valueType, {factory->getType(), array->getType(), size->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory, array, size}, "res", block); + return res; } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_filter.cpp b/yql/essentials/minikql/comp_nodes/mkql_filter.cpp index 5e8993db5781..55edc59f3f1b 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_filter.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_filter.cpp @@ -280,7 +280,7 @@ class TBaseFilterWrapper { return f; const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = IsStream ? Type::getInt32Ty(context) : Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(valueType)}, false); @@ -299,8 +299,7 @@ class TBaseFilterWrapper { const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto loop = BasicBlock::Create(context, "loop", ctx.Func); const auto good = BasicBlock::Create(context, "good", ctx.Func); @@ -488,7 +487,7 @@ class TBaseFilterWithLimitWrapper { const auto valueType = Type::getInt128Ty(context); const auto limitType = Type::getInt64Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = IsStream ? Type::getInt32Ty(context) : Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(limitType), PointerType::getUnqual(valueType)}, false); @@ -523,8 +522,7 @@ class TBaseFilterWithLimitWrapper { ReturnInst::Create(context, IsStream ? ConstantInt::get(statusType, static_cast(NUdf::EFetchStatus::Finish)) : ConstantInt::getFalse(context), block); block = init; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); BranchInst::Create(loop, block); block = loop; @@ -971,20 +969,10 @@ class TListFilterWrapper : public TBothWaysCodegeneratorNode const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TListFilterWrapper::MakeLazyList)); const auto ptrType = PointerType::getUnqual(StructType::get(context)); const auto self = CastInst::Create(Instruction::IntToPtr, ConstantInt::get(Type::getInt64Ty(context), uintptr_t(this)), ptrType, "self", block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); - out->addIncoming(value, block); - } else { - const auto resultPtr = new AllocaInst(list->getType(), 0U, "return", block); - new StoreInst(list, resultPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType(), resultPtr->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx, resultPtr}, "", block); - const auto value = new LoadInst(list->getType(), resultPtr, "value", block); - out->addIncoming(value, block); - } + const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); + out->addIncoming(value, block); BranchInst::Create(done, block); } @@ -1340,20 +1328,10 @@ class TListFilterWithLimitWrapper : public TBothWaysCodegeneratorNodegetType() , {self->getType(), ctx.Ctx->getType(), list->getType(), limit->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list, limit}, "value", block); - out->addIncoming(value, block); - } else { - const auto resultPtr = new AllocaInst(list->getType(), 0U, "return", block); - new StoreInst(list, resultPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType(), resultPtr->getType(), limit->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx, resultPtr, limit}, "", block); - const auto value = new LoadInst(list->getType(), resultPtr, "value", block); - out->addIncoming(value, block); - } + const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType(), limit->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list, limit}, "value", block); + out->addIncoming(value, block); BranchInst::Create(done, block); } diff --git a/yql/essentials/minikql/comp_nodes/mkql_flatmap.cpp b/yql/essentials/minikql/comp_nodes/mkql_flatmap.cpp index dc1d9a7472fe..0e53e650ac6c 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_flatmap.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_flatmap.cpp @@ -1170,7 +1170,7 @@ class TBaseFlatMapWrapper { return f; const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = IsInputStream ? Type::getInt32Ty(context) : Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(valueType)}, false); @@ -1189,8 +1189,7 @@ class TBaseFlatMapWrapper { const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto loop = BasicBlock::Create(context, "loop", ctx.Func); const auto good = BasicBlock::Create(context, "good", ctx.Func); @@ -1242,7 +1241,7 @@ class TBaseFlatMapWrapper { return f; const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = IsInputStream ? Type::getInt32Ty(context) : Type::getInt1Ty(context); const auto stateType = ResultContainerOpt ? Type::getInt32Ty(context) : Type::getInt1Ty(context); @@ -1263,8 +1262,7 @@ class TBaseFlatMapWrapper { const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto zero = ConstantInt::get(valueType, 0); @@ -1578,17 +1576,9 @@ class TListFlatMapWrapper : public TBothWaysCodegeneratorNode)); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(list->getType(), {factory->getType(), vector->getType(), index->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - res = CallInst::Create(funType, funcPtr, {factory, vector, index}, "res", block); - } else { - const auto retPtr = new AllocaInst(list->getType(), 0U, "ret_ptr", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), vector->getType(), index->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, vector, index}, "", block); - res = new LoadInst(list->getType(), retPtr, "res", block); - } + const auto funType = FunctionType::get(list->getType(), {factory->getType(), vector->getType(), index->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + res = CallInst::Create(funType, funcPtr, {factory, vector, index}, "res", block); } map->addIncoming(res, block); BranchInst::Create(free, done, heap, block); @@ -1613,20 +1603,10 @@ class TListFlatMapWrapper : public TBothWaysCodegeneratorNodegetType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); - map->addIncoming(value, block); - } else { - const auto resultPtr = new AllocaInst(list->getType(), 0U, "return", block); - new StoreInst(list, resultPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType(), resultPtr->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx, resultPtr}, "", block); - const auto value = new LoadInst(list->getType(), resultPtr, "value", block); - map->addIncoming(value, block); - } + const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); + map->addIncoming(value, block); BranchInst::Create(done, block); } diff --git a/yql/essentials/minikql/comp_nodes/mkql_fromstring.cpp b/yql/essentials/minikql/comp_nodes/mkql_fromstring.cpp index d208343cc2ab..7b8c0fe0a6f7 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_fromstring.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_fromstring.cpp @@ -78,13 +78,11 @@ class TDecimalFromStringWrapper : public TMutableCodegeneratorNode(&DecimalFromString)); - const auto fnType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, psType, psType }, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, psType, psType }, false); + const auto fnType = + FunctionType::get(valType, { valType, psType, psType }, false); const auto func = ctx.Codegen.GetModule().getOrInsertFunction(name, fnType); const auto zero = ConstantInt::get(valType, 0ULL); @@ -108,15 +106,7 @@ class TDecimalFromStringWrapper : public TMutableCodegeneratorNodeIsTemporaryValue()) ValueCleanup(Data->GetRepresentation(), value, ctx, block); @@ -198,13 +188,11 @@ class TFromStringWrapper : public TMutableCodegeneratorNode(&DataFromString)); - const auto fnType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, slotType }, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, slotType }, false); + const auto fnType = + FunctionType::get(valType, { valType, slotType }, false); const auto func = ctx.Codegen.GetModule().getOrInsertFunction(name, fnType); const auto zero = ConstantInt::get(valType, 0ULL); @@ -224,15 +212,7 @@ class TFromStringWrapper : public TMutableCodegeneratorNodeIsTemporaryValue()) ValueCleanup(Data->GetRepresentation(), value, ctx, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_heap.cpp b/yql/essentials/minikql/comp_nodes/mkql_heap.cpp index 74fa51806a85..260223a0f36c 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_heap.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_heap.cpp @@ -84,18 +84,9 @@ class THeapWrapper : public TMutableCodegeneratorNode const auto idxType = Type::getInt32Ty(context); Value* array = nullptr; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(valueType, {fact->getType(), list->getType(), itemsPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - array = CallInst::Create(funType, funcPtr, {fact, list, itemsPtr}, "array", block); - } else { - const auto arrayPtr = new AllocaInst(valueType, 0U, "array_ptr", block); - new StoreInst(list, arrayPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {fact->getType(), arrayPtr->getType(), arrayPtr->getType(), itemsPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {fact, arrayPtr, arrayPtr, itemsPtr}, "", block); - array = new LoadInst(valueType, arrayPtr, "array", block); - } + const auto funType = FunctionType::get(valueType, {fact->getType(), list->getType(), itemsPtr->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + array = CallInst::Create(funType, funcPtr, {fact, list, itemsPtr}, "array", block); result->addIncoming(array, block); @@ -269,18 +260,9 @@ class TNthWrapper : public TMutableCodegeneratorNode const auto idxType = Type::getInt32Ty(context); Value* array = nullptr; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(valueType, {fact->getType(), list->getType(), itemsPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - array = CallInst::Create(funType, funcPtr, {fact, list, itemsPtr}, "array", block); - } else { - const auto arrayPtr = new AllocaInst(valueType, 0U, "array_ptr", block); - new StoreInst(list, arrayPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {fact->getType(), arrayPtr->getType(), arrayPtr->getType(), itemsPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {fact, arrayPtr, arrayPtr, itemsPtr}, "", block); - array = new LoadInst(valueType, arrayPtr, "array", block); - } + const auto funType = FunctionType::get(valueType, {fact->getType(), list->getType(), itemsPtr->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + array = CallInst::Create(funType, funcPtr, {fact, list, itemsPtr}, "array", block); result->addIncoming(array, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_iterator.cpp b/yql/essentials/minikql/comp_nodes/mkql_iterator.cpp index dcd9d351cfad..b413d1cbca8d 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_iterator.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_iterator.cpp @@ -30,20 +30,10 @@ class TIteratorWrapper : public TMutableCodegeneratorNode { const auto factory = ctx.GetFactory(); const auto func = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&THolderFactory::CreateIteratorOverList)); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto signature = FunctionType::get(value->getType(), {factory->getType(), value->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - const auto output = CallInst::Create(signature, creator, {factory, value}, "output", block); - return output; - } else { - const auto place = new AllocaInst(value->getType(), 0U, "place", block); - new StoreInst(value, place, block); - const auto signature = FunctionType::get(Type::getVoidTy(context), {factory->getType(), place->getType(), place->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - CallInst::Create(signature, creator, {factory, place, place}, "", block); - const auto output = new LoadInst(value->getType(), place, "output", block); - return output; - } + const auto signature = FunctionType::get(value->getType(), {factory->getType(), value->getType()}, false); + const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); + const auto output = CallInst::Create(signature, creator, {factory, value}, "output", block); + return output; } #endif private: @@ -76,20 +66,10 @@ class TForwardListWrapper : public TMutableCodegeneratorNodegetType(), {factory->getType(), value->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - const auto output = CallInst::Create(signature, creator, {factory, value}, "output", block); - return output; - } else { - const auto place = new AllocaInst(value->getType(), 0U, "place", block); - new StoreInst(value, place, block); - const auto signature = FunctionType::get(Type::getVoidTy(context), {factory->getType(), place->getType(), place->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - CallInst::Create(signature, creator, {factory, place, place}, "", block); - const auto output = new LoadInst(value->getType(), place, "output", block); - return output; - } + const auto signature = FunctionType::get(value->getType(), {factory->getType(), value->getType()}, false); + const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); + const auto output = CallInst::Create(signature, creator, {factory, value}, "output", block); + return output; } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_join_dict.cpp b/yql/essentials/minikql/comp_nodes/mkql_join_dict.cpp index b93970b6466a..127e32a0ebff 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_join_dict.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_join_dict.cpp @@ -49,27 +49,12 @@ class TJoinDictWrapper : public TMutableCodegeneratorPtrNodegetType(), ctx.Ctx->getType(), one->getType(), two->getType() }, false); - const auto joinFuncPtr = CastInst::Create(Instruction::IntToPtr, joinFunc, PointerType::getUnqual(joinFuncType), "cast", block); - const auto join = CallInst::Create(joinFuncType, joinFuncPtr, { joinFuncArg, ctx.Ctx, one, two }, "join", block); - AddRefBoxed(join, ctx, block); - new StoreInst(join, pointer, block); - } else { - const auto onePtr = new AllocaInst(one->getType(), 0U, "one_ptr", block); - const auto twoPtr = new AllocaInst(two->getType(), 0U, "two_ptr", block); - new StoreInst(one, onePtr, block); - new StoreInst(two, twoPtr, block); - - const auto joinFuncType = FunctionType::get(Type::getVoidTy(context), - { joinFuncArg->getType(), pointer->getType(), ctx.Ctx->getType(), onePtr->getType(), twoPtr->getType() }, false); - - const auto joinFuncPtr = CastInst::Create(Instruction::IntToPtr, joinFunc, PointerType::getUnqual(joinFuncType), "cast", block); - CallInst::Create(joinFuncType, joinFuncPtr, { joinFuncArg, pointer, ctx.Ctx, onePtr, twoPtr }, "", block); - const auto join = new LoadInst(Type::getInt128Ty(context), pointer, "join", block); - AddRefBoxed(join, ctx, block); - } + const auto joinFuncType = FunctionType::get(Type::getInt128Ty(context), + { joinFuncArg->getType(), ctx.Ctx->getType(), one->getType(), two->getType() }, false); + const auto joinFuncPtr = CastInst::Create(Instruction::IntToPtr, joinFunc, PointerType::getUnqual(joinFuncType), "cast", block); + const auto join = CallInst::Create(joinFuncType, joinFuncPtr, { joinFuncArg, ctx.Ctx, one, two }, "join", block); + AddRefBoxed(join, ctx, block); + new StoreInst(join, pointer, block); } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_lazy_list.cpp b/yql/essentials/minikql/comp_nodes/mkql_lazy_list.cpp index f7d04055582b..f19ac809a422 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_lazy_list.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_lazy_list.cpp @@ -60,20 +60,10 @@ class TLazyListWrapper : public TMutableCodegeneratorNodegetType(), {factory->getType(), list->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory, list}, "res", block); - lazy->addIncoming(res, block); - } else { - const auto retPtr = new AllocaInst(list->getType(), 0U, "ret_ptr", block); - new StoreInst(list, retPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), retPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, retPtr}, "", block); - const auto res = new LoadInst(list->getType(), retPtr, "res", block); - lazy->addIncoming(res, block); - } + const auto funType = FunctionType::get(list->getType(), {factory->getType(), list->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory, list}, "res", block); + lazy->addIncoming(res, block); BranchInst::Create(done, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_listfromrange.cpp b/yql/essentials/minikql/comp_nodes/mkql_listfromrange.cpp index 1e374c4dcca3..fab157dafbfd 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_listfromrange.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_listfromrange.cpp @@ -279,19 +279,10 @@ class TListFromRangeWrapper : public TMutableCodegeneratorNodegetType(), start->getType(), end->getType(), step->getType(), timezone->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - const auto output = CallInst::Create(signature, creator, {ctx.Ctx, start, end, step, timezone}, "output", block); - return output; - } else { - const auto place = new AllocaInst(valueType, 0U, "place", block); - const auto signature = FunctionType::get(Type::getVoidTy(context), {place->getType(), ctx.Ctx->getType(), start->getType(), end->getType(), step->getType(), timezone->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - CallInst::Create(signature, creator, {place, ctx.Ctx, start, end, step, timezone}, "", block); - const auto output = new LoadInst(valueType, place, "output", block); - return output; - } + const auto signature = FunctionType::get(valueType, {ctx.Ctx->getType(), start->getType(), end->getType(), step->getType(), timezone->getType()}, false); + const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); + const auto output = CallInst::Create(signature, creator, {ctx.Ctx, start, end, step, timezone}, "output", block); + return output; } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_map.cpp b/yql/essentials/minikql/comp_nodes/mkql_map.cpp index 690b68228b2b..ff014286e839 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_map.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_map.cpp @@ -197,7 +197,7 @@ class TBaseMapWrapper { return f; const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = IsStream ? Type::getInt32Ty(context) : Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(valueType)}, false); @@ -216,8 +216,7 @@ class TBaseMapWrapper { const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto good = BasicBlock::Create(context, "good", ctx.Func); const auto done = BasicBlock::Create(context, "done", ctx.Func); @@ -392,20 +391,10 @@ class TListMapWrapper : public TBothWaysCodegeneratorNode, priv const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TListMapWrapper::MakeLazyList)); const auto ptrType = PointerType::getUnqual(StructType::get(context)); const auto self = CastInst::Create(Instruction::IntToPtr, ConstantInt::get(Type::getInt64Ty(context), uintptr_t(this)), ptrType, "self", block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); - map->addIncoming(value, block); - } else { - const auto resultPtr = new AllocaInst(list->getType(), 0U, "return", block); - new StoreInst(list, resultPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType(), resultPtr->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx, resultPtr}, "", block); - const auto value = new LoadInst(list->getType(), resultPtr, "value", block); - map->addIncoming(value, block); - } + const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); + map->addIncoming(value, block); BranchInst::Create(done, block); } diff --git a/yql/essentials/minikql/comp_nodes/mkql_map_join.cpp b/yql/essentials/minikql/comp_nodes/mkql_map_join.cpp index 05de9fafc6de..9cdb16e855f9 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_map_join.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_map_join.cpp @@ -1544,7 +1544,7 @@ class TMapJoinCoreWrapper : public TMapJoinCoreWrapperBase, public TCus const auto valueType = Type::getInt128Ty(context); const auto arrayType = ArrayType::get(valueType, this->OutputRepresentations.size()); const auto keysType = IsTuple ? ArrayType::get(valueType, this->LeftKeyColumns.size()) : nullptr; - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, containerType, PointerType::getUnqual(valueType)}, false); @@ -1564,11 +1564,9 @@ class TMapJoinCoreWrapper : public TMapJoinCoreWrapperBase, public TCus const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto stream = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, streamArg, "load_stream", false, block) : static_cast(streamArg); + const auto stream = static_cast(streamArg); - const auto dict = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, dictArg, "load_dict", false, block) : static_cast(dictArg); + const auto dict = static_cast(dictArg); const auto zero = ConstantInt::get(valueType, 0); const auto fsok = ConstantInt::get(statusType, static_cast(NUdf::EFetchStatus::Ok)); @@ -1701,7 +1699,7 @@ class TMapJoinCoreWrapper : public TMapJoinCoreWrapperBase, public TCus const auto valueType = Type::getInt128Ty(context); const auto arrayType = ArrayType::get(valueType, this->OutputRepresentations.size()); const auto keysType = IsTuple ? ArrayType::get(valueType, this->LeftKeyColumns.size()) : nullptr; - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, containerType, PointerType::getUnqual(valueType), PointerType::getUnqual(valueType), PointerType::getUnqual(valueType)}, false); @@ -1723,11 +1721,9 @@ class TMapJoinCoreWrapper : public TMapJoinCoreWrapperBase, public TCus const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto stream = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, streamArg, "load_stream", false, block) : static_cast(streamArg); + const auto stream = static_cast(streamArg); - const auto dict = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, dictArg, "load_dict", false, block) : static_cast(dictArg); + const auto dict = static_cast(dictArg); const auto zero = ConstantInt::get(valueType, 0); const auto fsok = ConstantInt::get(statusType, static_cast(NUdf::EFetchStatus::Ok)); diff --git a/yql/essentials/minikql/comp_nodes/mkql_multimap.cpp b/yql/essentials/minikql/comp_nodes/mkql_multimap.cpp index c9fad3198fdf..3a3f24e37423 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_multimap.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_multimap.cpp @@ -282,20 +282,10 @@ class TListMultiMapWrapper : public TBothWaysCodegeneratorNodegetType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); - map->addIncoming(value, block); - } else { - const auto resultPtr = new AllocaInst(list->getType(), 0U, "return", block); - new StoreInst(list, resultPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType(), resultPtr->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx, resultPtr}, "", block); - const auto value = new LoadInst(list->getType(), resultPtr, "value", block); - map->addIncoming(value, block); - } + const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); + map->addIncoming(value, block); BranchInst::Create(done, block); } @@ -335,7 +325,7 @@ class TListMultiMapWrapper : public TBothWaysCodegeneratorNode(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(positionType), PointerType::getUnqual(valueType)}, false); @@ -355,8 +345,7 @@ class TListMultiMapWrapper : public TBothWaysCodegeneratorNode(containerArg); + const auto container = static_cast(containerArg); const auto position = new LoadInst(positionType, positionArg, "position", false, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_prepend.cpp b/yql/essentials/minikql/comp_nodes/mkql_prepend.cpp index 334197d48896..0b29d724f3b8 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_prepend.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_prepend.cpp @@ -53,44 +53,20 @@ class TPrependWrapper : public TMutableCodegeneratorNode BranchInst::Create(work, done, check, block); block = work; - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(right->getType(), {factory->getType(), left->getType(), right->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory, left, right}, "res", block); - result->addIncoming(res, block); - } else { - const auto retPtr = new AllocaInst(right->getType(), 0U, "ret_ptr", block); - const auto itemPtr = new AllocaInst(left->getType(), 0U, "item_ptr", block); - new StoreInst(right, retPtr, block); - new StoreInst(left, itemPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), itemPtr->getType(), retPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, itemPtr, retPtr}, "", block); - const auto res = new LoadInst(right->getType(), retPtr, "res", block); - result->addIncoming(res, block); - } + const auto funType = FunctionType::get(right->getType(), {factory->getType(), left->getType(), right->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory, left, right}, "res", block); + result->addIncoming(res, block); BranchInst::Create(done, block); block = done; return result; } else { - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(right->getType(), {factory->getType(), left->getType(), right->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory, left, right}, "res", block); - return res; - } else { - const auto retPtr = new AllocaInst(right->getType(), 0U, "ret_ptr", block); - const auto itemPtr = new AllocaInst(left->getType(), 0U, "item_ptr", block); - new StoreInst(right, retPtr, block); - new StoreInst(left, itemPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), itemPtr->getType(), retPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, itemPtr, retPtr}, "", block); - const auto res = new LoadInst(right->getType(), retPtr, "res", block); - return res; - } + const auto funType = FunctionType::get(right->getType(), {factory->getType(), left->getType(), right->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory, left, right}, "res", block); + return res; } } #endif diff --git a/yql/essentials/minikql/comp_nodes/mkql_reverse.cpp b/yql/essentials/minikql/comp_nodes/mkql_reverse.cpp index 6549b03dfd75..692595f3a4e3 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_reverse.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_reverse.cpp @@ -38,20 +38,10 @@ class TReverseWrapper : public TMutableCodegeneratorNode { const auto list = GetNodeValue(List, ctx, block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(list->getType(), {factory->getType(), builder->getType(), list->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto result = CallInst::Create(funType, funcPtr, {factory, builder, list}, "result", block); - return result; - } else { - const auto retPtr = new AllocaInst(list->getType(), 0U, "ret_ptr", block); - new StoreInst(list, retPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), builder->getType(), retPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, builder, retPtr}, "", block); - const auto result = new LoadInst(list->getType(), retPtr, "result", block); - return result; - } + const auto funType = FunctionType::get(list->getType(), {factory->getType(), builder->getType(), list->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto result = CallInst::Create(funType, funcPtr, {factory, builder, list}, "result", block); + return result; } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_skip.cpp b/yql/essentials/minikql/comp_nodes/mkql_skip.cpp index ad9b43ebac63..9f33a1ae1543 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_skip.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_skip.cpp @@ -262,20 +262,10 @@ class TSkipWrapper : public TMutableCodegeneratorNode { const auto cnt = GetNodeValue(Count, ctx, block); const auto count = GetterFor(cnt, context, block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(list->getType(), {factory->getType(), builder->getType(), list->getType(), count->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto result = CallInst::Create(funType, funcPtr, {factory, builder, list, count}, "result", block); - return result; - } else { - const auto retPtr = new AllocaInst(list->getType(), 0U, "ret_ptr", block); - new StoreInst(list, retPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), builder->getType(), retPtr->getType(), count->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, builder, retPtr, count}, "", block); - const auto result = new LoadInst(list->getType(), retPtr, "result", block); - return result; - } + const auto funType = FunctionType::get(list->getType(), {factory->getType(), builder->getType(), list->getType(), count->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto result = CallInst::Create(funType, funcPtr, {factory, builder, list, count}, "result", block); + return result; } #endif diff --git a/yql/essentials/minikql/comp_nodes/mkql_squeeze_to_list.cpp b/yql/essentials/minikql/comp_nodes/mkql_squeeze_to_list.cpp index 9a3e257c2c71..ca5e0cf547c1 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_squeeze_to_list.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_squeeze_to_list.cpp @@ -140,7 +140,7 @@ class TSqueezeToListWrapper: public TStatefulFlowCodegeneratorNodegetType(), arg->getType()}, false); const auto pushPtr = CastInst::Create(Instruction::IntToPtr, push, PointerType::getUnqual(pushType), "push", block); @@ -152,21 +152,11 @@ class TSqueezeToListWrapper: public TStatefulFlowCodegeneratorNodegetType(), ctx.Ctx->getType()}, false); - const auto pullPtr = CastInst::Create(Instruction::IntToPtr, pull, PointerType::getUnqual(pullType), "pull", block); - const auto list = CallInst::Create(pullType, pullPtr, {stateArg, ctx.Ctx}, "list", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(list, block); - } else { - const auto ptr = new AllocaInst(valueType, 0U, "ptr", block); - const auto pullType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), ptr->getType(), ctx.Ctx->getType()}, false); - const auto pullPtr = CastInst::Create(Instruction::IntToPtr, pull, PointerType::getUnqual(pullType), "pull", block); - CallInst::Create(pullType, pullPtr, {stateArg, ptr, ctx.Ctx}, "", block); - const auto list = new LoadInst(valueType, ptr, "list", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(list, block); - } + const auto pullType = FunctionType::get(valueType, {stateArg->getType(), ctx.Ctx->getType()}, false); + const auto pullPtr = CastInst::Create(Instruction::IntToPtr, pull, PointerType::getUnqual(pullType), "pull", block); + const auto list = CallInst::Create(pullType, pullPtr, {stateArg, ctx.Ctx}, "list", block); + UnRefBoxed(state, ctx, block); + result->addIncoming(list, block); new StoreInst(GetFinish(context), statePtr, block); BranchInst::Create(over, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_switch.cpp b/yql/essentials/minikql/comp_nodes/mkql_switch.cpp index 1dab916ca87a..f8c9c2e4602f 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_switch.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_switch.cpp @@ -304,9 +304,6 @@ class TSwitchFlowWrapper : public TStatefulFlowCodegeneratorNode(this)->GetIndex())}, "state_ptr", block); const auto state = new LoadInst(valueType, statePtr, "state", block); const auto half = CastInst::Create(Instruction::Trunc, state, Type::getInt64Ty(context), "half", block); @@ -326,17 +323,9 @@ class TSwitchFlowWrapper : public TStatefulFlowCodegeneratorNodegetType(), pos->getType()}, false); - const auto getPtr = CastInst::Create(Instruction::IntToPtr, getFunc, PointerType::getUnqual(getType), "get", block); - input = CallInst::Create(getType, getPtr, {stateArg, pos}, "input", block); - } else { - const auto getType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), placeholder->getType(), pos->getType()}, false); - const auto getPtr = CastInst::Create(Instruction::IntToPtr, getFunc, PointerType::getUnqual(getType), "get", block); - CallInst::Create(getType, getPtr, {stateArg, placeholder, pos}, "", block); - input = new LoadInst(valueType, placeholder, "input", block); - } + const auto getType = FunctionType::get(valueType, {stateArg->getType(), pos->getType()}, false); + const auto getPtr = CastInst::Create(Instruction::IntToPtr, getFunc, PointerType::getUnqual(getType), "get", block); + const auto input = CallInst::Create(getType, getPtr, {stateArg, pos}, "input", block); const auto special = SwitchInst::Create(input, good, 2U, block); special->addCase(GetYield(context), back); @@ -469,7 +458,7 @@ class TSwitchFlowWrapper : public TStatefulFlowCodegeneratorNodegetType(), addArg->getType()}, false); const auto addPtr = CastInst::Create(Instruction::IntToPtr, addFunc, PointerType::getUnqual(addType), "add", block); CallInst::Create(addType, addPtr, {stateArg, addArg}, "", block); @@ -812,7 +801,7 @@ class TSwitchWrapper : public TCustomValueCodegeneratorNode(ptrValueType) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = Type::getInt32Ty(context); const auto indexType = Type::getInt32Ty(context); @@ -883,8 +872,7 @@ class TSwitchWrapper : public TCustomValueCodegeneratorNode(containerArg); + const auto stream = static_cast(containerArg); BranchInst::Create(loop, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_take.cpp b/yql/essentials/minikql/comp_nodes/mkql_take.cpp index 3e19ee2932d8..f2e9bc7023d8 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_take.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_take.cpp @@ -265,20 +265,10 @@ class TTakeWrapper : public TMutableCodegeneratorNode { const auto cnt = GetNodeValue(Count, ctx, block); const auto count = GetterFor(cnt, context, block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(list->getType(), {factory->getType(), builder->getType(), list->getType(), count->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto result = CallInst::Create(funType, funcPtr, {factory, builder, list, count}, "result", block); - return result; - } else { - const auto retPtr = new AllocaInst(list->getType(), 0U, "ret_ptr", block); - new StoreInst(list, retPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), builder->getType(), retPtr->getType(), count->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, builder, retPtr, count}, "", block); - const auto result = new LoadInst(list->getType(), retPtr, "result", block); - return result; - } + const auto funType = FunctionType::get(list->getType(), {factory->getType(), builder->getType(), list->getType(), count->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto result = CallInst::Create(funType, funcPtr, {factory, builder, list, count}, "result", block); + return result; } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_todict.cpp b/yql/essentials/minikql/comp_nodes/mkql_todict.cpp index 0ac6b83a11e5..10d0b4609c06 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_todict.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_todict.cpp @@ -1065,7 +1065,7 @@ class TSqueezeSetFlowWrapper : public TStatefulFlowCodegeneratorNodegetType(), keyArg->getType()}, false); const auto insPtr = CastInst::Create(Instruction::IntToPtr, insert, PointerType::getUnqual(insType), "insert", block); @@ -1077,21 +1077,11 @@ class TSqueezeSetFlowWrapper : public TStatefulFlowCodegeneratorNodegetType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); - const auto dict = CallInst::Create(funType, funcPtr, {stateArg}, "dict", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(dict, block); - } else { - const auto ptr = new AllocaInst(valueType, 0U, "ptr", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), ptr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); - CallInst::Create(funType, funcPtr, {stateArg, ptr}, "", block); - const auto dict = new LoadInst(valueType, ptr, "dict", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(dict, block); - } + const auto funType = FunctionType::get(valueType, {stateArg->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); + const auto dict = CallInst::Create(funType, funcPtr, {stateArg}, "dict", block); + UnRefBoxed(state, ctx, block); + result->addIncoming(dict, block); new StoreInst(item, statePtr, block); BranchInst::Create(over, block); @@ -1262,7 +1252,7 @@ class TSqueezeSetWideWrapper : public TStatefulFlowCodegeneratorNodegetType(), keyArg->getType()}, false); const auto insPtr = CastInst::Create(Instruction::IntToPtr, insert, PointerType::getUnqual(insType), "insert", block); @@ -1274,21 +1264,11 @@ class TSqueezeSetWideWrapper : public TStatefulFlowCodegeneratorNodegetType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); - const auto dict = CallInst::Create(funType, funcPtr, {stateArg}, "dict", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(dict, block); - } else { - const auto ptr = new AllocaInst(valueType, 0U, "ptr", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), ptr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); - CallInst::Create(funType, funcPtr, {stateArg, ptr}, "", block); - const auto dict = new LoadInst(valueType, ptr, "dict", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(dict, block); - } + const auto funType = FunctionType::get(valueType, {stateArg->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); + const auto dict = CallInst::Create(funType, funcPtr, {stateArg}, "dict", block); + UnRefBoxed(state, ctx, block); + result->addIncoming(dict, block); new StoreInst(GetFinish(context), statePtr, block); BranchInst::Create(over, block); @@ -1580,8 +1560,8 @@ class TSqueezeMapFlowWrapper : public TStatefulFlowCodegeneratorNodegetType(), keyArg->getType(), payloadArg->getType()}, false); const auto insPtr = CastInst::Create(Instruction::IntToPtr, insert, PointerType::getUnqual(insType), "insert", block); @@ -1593,21 +1573,11 @@ class TSqueezeMapFlowWrapper : public TStatefulFlowCodegeneratorNodegetType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); - const auto dict = CallInst::Create(funType, funcPtr, {stateArg}, "dict", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(dict, block); - } else { - const auto ptr = new AllocaInst(valueType, 0U, "ptr", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), ptr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); - CallInst::Create(funType, funcPtr, {stateArg, ptr}, "", block); - const auto dict = new LoadInst(valueType, ptr, "dict", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(dict, block); - } + const auto funType = FunctionType::get(valueType, {stateArg->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); + const auto dict = CallInst::Create(funType, funcPtr, {stateArg}, "dict", block); + UnRefBoxed(state, ctx, block); + result->addIncoming(dict, block); new StoreInst(item, statePtr, block); BranchInst::Create(over, block); @@ -1785,8 +1755,8 @@ class TSqueezeMapWideWrapper : public TStatefulFlowCodegeneratorNodegetType(), keyArg->getType(), payloadArg->getType()}, false); const auto insPtr = CastInst::Create(Instruction::IntToPtr, insert, PointerType::getUnqual(insType), "insert", block); @@ -1798,21 +1768,11 @@ class TSqueezeMapWideWrapper : public TStatefulFlowCodegeneratorNodegetType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); - const auto dict = CallInst::Create(funType, funcPtr, {stateArg}, "dict", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(dict, block); - } else { - const auto ptr = new AllocaInst(valueType, 0U, "ptr", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), ptr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); - CallInst::Create(funType, funcPtr, {stateArg, ptr}, "", block); - const auto dict = new LoadInst(valueType, ptr, "dict", block); - UnRefBoxed(state, ctx, block); - result->addIncoming(dict, block); - } + const auto funType = FunctionType::get(valueType, {stateArg->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, build, PointerType::getUnqual(funType), "build", block); + const auto dict = CallInst::Create(funType, funcPtr, {stateArg}, "dict", block); + UnRefBoxed(state, ctx, block); + result->addIncoming(dict, block); new StoreInst(GetFinish(context), statePtr, block); BranchInst::Create(over, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_toindexdict.cpp b/yql/essentials/minikql/comp_nodes/mkql_toindexdict.cpp index 978446be08d9..2bf6be670532 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_toindexdict.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_toindexdict.cpp @@ -38,20 +38,10 @@ class TToIndexDictWrapper : public TMutableCodegeneratorNodegetType(), {factory->getType(), builder->getType(), list->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto result = CallInst::Create(funType, funcPtr, {factory, builder, list}, "result", block); - return result; - } else { - const auto retPtr = new AllocaInst(list->getType(), 0U, "ret_ptr", block); - new StoreInst(list, retPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType(), builder->getType(), retPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr, builder, retPtr}, "", block); - const auto result = new LoadInst(list->getType(), retPtr, "result", block); - return result; - } + const auto funType = FunctionType::get(list->getType(), {factory->getType(), builder->getType(), list->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto result = CallInst::Create(funType, funcPtr, {factory, builder, list}, "result", block); + return result; } #endif private: diff --git a/yql/essentials/minikql/comp_nodes/mkql_tostring.cpp b/yql/essentials/minikql/comp_nodes/mkql_tostring.cpp index b7155f01ffae..130aaf00c5ea 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_tostring.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_tostring.cpp @@ -64,13 +64,11 @@ class TDecimalToStringWrapper : public TMutableCodegeneratorNode(&DecimalToString)); - const auto fnType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, psType, psType }, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, psType, psType }, false); + const auto fnType = + FunctionType::get(valType, { valType, psType, psType }, false); const auto func = ctx.Codegen.GetModule().getOrInsertFunction(name, fnType); const auto fail = BasicBlock::Create(context, "fail", ctx.Func); @@ -93,29 +91,14 @@ class TDecimalToStringWrapper : public TMutableCodegeneratorNodeaddIncoming(string, block); const auto test = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_EQ, string, zero, "test", block); BranchInst::Create(fail, nice, test, block); } else { - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - result = CallInst::Create(func, { GetterForInt128(value, block), precision, scale }, "to_string", block); - } else { - const auto retPtr = new AllocaInst(valType, 0U, "ret_ptr", block); - new StoreInst(GetterForInt128(value, block), retPtr, block); - CallInst::Create(func, { retPtr, retPtr, precision, scale }, "", block); - result = new LoadInst(valType, retPtr, "res", block); - } + result = CallInst::Create(func, { GetterForInt128(value, block), precision, scale }, "to_string", block); const auto test = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_EQ, result, zero, "test", block); BranchInst::Create(fail, nice, test, block); @@ -170,13 +153,11 @@ class TToStringWrapper : public TMutableCodegeneratorNode(&DataToString)); - const auto fnType = NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget() ? - FunctionType::get(valType, { valType, slotType }, false): - FunctionType::get(Type::getVoidTy(context), { valTypePtr, valTypePtr, slotType }, false); + const auto fnType = + FunctionType::get(valType, { valType, slotType }, false); const auto func = ctx.Codegen.GetModule().getOrInsertFunction(name, fnType); const auto zero = ConstantInt::get(valType, 0ULL); @@ -194,15 +175,7 @@ class TToStringWrapper : public TMutableCodegeneratorNodeIsTemporaryValue()) ValueCleanup(Data->GetRepresentation(), value, ctx, block); @@ -213,15 +186,7 @@ class TToStringWrapper : public TMutableCodegeneratorNodeIsTemporaryValue()) ValueCleanup(Data->GetRepresentation(), value, ctx, block); diff --git a/yql/essentials/minikql/comp_nodes/mkql_while.cpp b/yql/essentials/minikql/comp_nodes/mkql_while.cpp index 907af8f6252c..233abf7e896d 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_while.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_while.cpp @@ -315,7 +315,7 @@ class TBaseWhileWrapper { return f; const auto valueType = Type::getInt128Ty(context); - const auto containerType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? static_cast(PointerType::getUnqual(valueType)) : static_cast(valueType); + const auto containerType = static_cast(valueType); const auto contextType = GetCompContextType(context); const auto statusType = IsStream ? Type::getInt32Ty(context) : Type::getInt1Ty(context); const auto funcType = FunctionType::get(statusType, {PointerType::getUnqual(contextType), containerType, PointerType::getUnqual(valueType), PointerType::getUnqual(valueType)}, false); @@ -335,8 +335,7 @@ class TBaseWhileWrapper { const auto main = BasicBlock::Create(context, "main", ctx.Func); auto block = main; - const auto container = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - new LoadInst(valueType, containerArg, "load_container", false, block) : static_cast(containerArg); + const auto container = static_cast(containerArg); const auto good = BasicBlock::Create(context, "good", ctx.Func); const auto stop = BasicBlock::Create(context, "stop", ctx.Func); @@ -610,20 +609,10 @@ class TListWhileWrapper : public TBothWaysCodegeneratorNodegetType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); - out->addIncoming(value, block); - } else { - const auto resultPtr = new AllocaInst(list->getType(), 0U, "return", block); - new StoreInst(list, resultPtr, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType(), resultPtr->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx, resultPtr}, "", block); - const auto value = new LoadInst(list->getType(), resultPtr, "value", block); - out->addIncoming(value, block); - } + const auto funType = FunctionType::get(list->getType() , {self->getType(), ctx.Ctx->getType(), list->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx, list}, "value", block); + out->addIncoming(value, block); BranchInst::Create(done, block); } diff --git a/yql/essentials/minikql/computation/mkql_computation_node_codegen.cpp b/yql/essentials/minikql/computation/mkql_computation_node_codegen.cpp index 7379efe3f5c6..23be45fa194c 100644 --- a/yql/essentials/minikql/computation/mkql_computation_node_codegen.cpp +++ b/yql/essentials/minikql/computation/mkql_computation_node_codegen.cpp @@ -137,13 +137,11 @@ Function* GenerateCompareFunction(NYql::NCodegen::ICodegen& codegen, const TStri auto& context = codegen.GetContext(); const auto valueType = Type::getInt128Ty(context); - const auto ptrType = PointerType::getUnqual(valueType); const auto returnType = Type::getInt1Ty(context); const auto contextType = GetCompContextType(context); - const auto funcType = codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows ? - FunctionType::get(returnType, {PointerType::getUnqual(contextType), valueType, valueType}, false): - FunctionType::get(returnType, {PointerType::getUnqual(contextType), ptrType, ptrType}, false); + const auto funcType = + FunctionType::get(returnType, {PointerType::getUnqual(contextType), valueType, valueType}, false); TCodegenContext ctx(codegen); ctx.AlwaysInline = true; @@ -602,12 +600,10 @@ Function* GenerateEqualsFunction(NYql::NCodegen::ICodegen& codegen, const TStrin auto& context = codegen.GetContext(); const auto valueType = Type::getInt128Ty(context); - const auto ptrType = PointerType::getUnqual(valueType); const auto returnType = Type::getInt1Ty(context); - const auto funcType = codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows ? - FunctionType::get(returnType, {valueType, valueType}, false): - FunctionType::get(returnType, {ptrType, ptrType}, false); + const auto funcType = + FunctionType::get(returnType, {valueType, valueType}, false); TCodegenContext ctx(codegen); ctx.AlwaysInline = true; @@ -733,12 +729,10 @@ Function* GenerateHashFunction(NYql::NCodegen::ICodegen& codegen, const TString& auto& context = codegen.GetContext(); const auto valueType = Type::getInt128Ty(context); - const auto ptrType = PointerType::getUnqual(valueType); const auto returnType = Type::getInt64Ty(context); - const auto funcType = codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows ? - FunctionType::get(returnType, {valueType}, false): - FunctionType::get(returnType, {ptrType}, false); + const auto funcType = + FunctionType::get(returnType, {valueType}, false); TCodegenContext ctx(codegen); ctx.AlwaysInline = true; @@ -1069,9 +1063,8 @@ Function* TExternalCodegeneratorRootNode::GenerateGetValue(NYql::NCodegen::ICode const auto valueType = Type::getInt128Ty(context); const auto contextType = GetCompContextType(context); - const auto funcType = codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows ? - FunctionType::get(valueType, {PointerType::getUnqual(contextType)}, false): - FunctionType::get(Type::getVoidTy(context), {PointerType::getUnqual(valueType), PointerType::getUnqual(contextType)}, false); + const auto funcType = + FunctionType::get(valueType, {PointerType::getUnqual(contextType)}, false); TCodegenContext ctx(codegen); ctx.Func = cast(module.getOrInsertFunction(name.c_str(), funcType).getCallee()); @@ -1079,25 +1072,13 @@ Function* TExternalCodegeneratorRootNode::GenerateGetValue(NYql::NCodegen::ICode DISubprogramAnnotator annotator(ctx, ctx.Func); auto args = ctx.Func->arg_begin(); - if (codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows) { - auto& firstArg = *args++; - firstArg.addAttr(Attribute::StructRet); - firstArg.addAttr(Attribute::NoAlias); - } - auto main = BasicBlock::Create(context, "main", ctx.Func); ctx.Ctx = &*args; ctx.Ctx->addAttr(Attribute::NonNull); const auto get = CreateGetValue(ctx, main); - if (codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) { - ReturnInst::Create(context, get, main); - } else { - new StoreInst(get, &*--args, main); - ReturnInst::Create(context, main); - } - + ReturnInst::Create(context, get, main); return ctx.Func; } @@ -1110,8 +1091,7 @@ Function* TExternalCodegeneratorRootNode::GenerateSetValue(NYql::NCodegen::ICode const auto intType = Type::getInt128Ty(context); const auto contextType = GetCompContextType(context); - const auto valueType = codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? - (Type*)PointerType::getUnqual(intType) : (Type*)intType; + const auto valueType = (Type*)intType; const auto funcType = FunctionType::get(Type::getVoidTy(context), {PointerType::getUnqual(contextType), valueType}, false); TCodegenContext ctx(codegen); @@ -1127,12 +1107,7 @@ Function* TExternalCodegeneratorRootNode::GenerateSetValue(NYql::NCodegen::ICode const auto valueArg = &*++args; - if (codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows) { - const auto value = new LoadInst(valueArg->getType(), valueArg, "load_value", main); - CreateSetValue(ctx, main, value); - } else { - CreateSetValue(ctx, main, valueArg); - } + CreateSetValue(ctx, main, valueArg); ReturnInst::Create(context, main); return ctx.Func; } @@ -1436,7 +1411,7 @@ template<> Type* GetTypeFor(LLVMContext &context) { return Type::getDoub void AddRefBoxed(Value* value, const TCodegenContext& ctx, BasicBlock*& block) { auto& context = ctx.Codegen.GetContext(); - const auto load = value->getType()->isPointerTy() ? new LoadInst(value->getType(), value, "load", block) : value; + const auto load = value->getType()->isPointerTy() ? new LoadInst(Type::getInt128Ty(context), value, "load", block) : value; const auto half = CastInst::Create(Instruction::Trunc, load, Type::getInt64Ty(context), "half", block); const auto counterType = Type::getInt32Ty(context); const auto type = StructType::get(context, {PointerType::getUnqual(StructType::get(context)), counterType, Type::getInt16Ty(context)}); @@ -1468,7 +1443,7 @@ void AddRefBoxed(Value* value, const TCodegenContext& ctx, BasicBlock*& block) { void UnRefBoxed(Value* value, const TCodegenContext& ctx, BasicBlock*& block) { auto& context = ctx.Codegen.GetContext(); - const auto load = value->getType()->isPointerTy() ? new LoadInst(value->getType(), value, "load", block) : value; + const auto load = value->getType()->isPointerTy() ? new LoadInst(Type::getInt128Ty(context), value, "load", block) : value; const auto half = CastInst::Create(Instruction::Trunc, load, Type::getInt64Ty(context), "half", block); const auto counterType = Type::getInt32Ty(context); const auto type = StructType::get(context, {PointerType::getUnqual(StructType::get(context)), counterType, Type::getInt16Ty(context)}); @@ -1511,7 +1486,7 @@ void UnRefBoxed(Value* value, const TCodegenContext& ctx, BasicBlock*& block) { void CleanupBoxed(Value* value, const TCodegenContext& ctx, BasicBlock*& block) { auto& context = ctx.Codegen.GetContext(); - const auto load = value->getType()->isPointerTy() ? new LoadInst(value->getType(), value, "load", block) : value; + const auto load = value->getType()->isPointerTy() ? new LoadInst(Type::getInt128Ty(context), value, "load", block) : value; const auto half = CastInst::Create(Instruction::Trunc, load, Type::getInt64Ty(context), "half", block); const auto counterType = Type::getInt32Ty(context); const auto type = StructType::get(context, {PointerType::getUnqual(StructType::get(context)), counterType, Type::getInt16Ty(context)}); @@ -1893,20 +1868,10 @@ Value* MakeVariant(Value* item, Value* variant, const TCodegenContext& ctx, Basi const auto factory = ctx.GetFactory(); const auto func = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&THolderFactory::CreateBoxedVariantHolder)); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto signature = FunctionType::get(item->getType(), {factory->getType(), item->getType(), variant->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - const auto output = CallInst::Create(signature, creator, {factory, item, variant}, "output", block); - result->addIncoming(output, block); - } else { - const auto place = new AllocaInst(item->getType(), 0U, "place", block); - new StoreInst(item, place, block); - const auto signature = FunctionType::get(Type::getVoidTy(context), {factory->getType(), place->getType(), place->getType(), variant->getType()}, false); - const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); - CallInst::Create(signature, creator, {factory, place, place, variant}, "", block); - const auto output = new LoadInst(item->getType(), place, "output", block); - result->addIncoming(output, block); - } + const auto signature = FunctionType::get(item->getType(), {factory->getType(), item->getType(), variant->getType()}, false); + const auto creator = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(signature), "creator", block); + const auto output = CallInst::Create(signature, creator, {factory, item, variant}, "output", block); + result->addIncoming(output, block); BranchInst::Create(done, block); } @@ -1926,9 +1891,8 @@ Value* GetNodeValue(IComputationNode* node, const TCodegenContext& ctx, BasicBlo const auto valueType = Type::getInt128Ty(context); const auto retPtr = new AllocaInst(valueType, 0U, "return_ptr", &ctx.Func->getEntryBlock().back()); - const auto funType = ctx.Codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows ? - FunctionType::get(Type::getVoidTy(context), {retPtr->getType(), nodeThis->getType(), ctx.Ctx->getType()}, false): - FunctionType::get(Type::getVoidTy(context), {nodeThis->getType(), retPtr->getType(), ctx.Ctx->getType()}, false); + const auto funType = + FunctionType::get(Type::getVoidTy(context), {retPtr->getType(), nodeThis->getType(), ctx.Ctx->getType()}, false); const auto ptrFunType = PointerType::getUnqual(funType); const auto tableType = PointerType::getUnqual(ptrFunType); const auto nodeVTable = CastInst::Create(Instruction::IntToPtr, ptr, PointerType::getUnqual(tableType), "node_vtable", block); @@ -1937,11 +1901,7 @@ Value* GetNodeValue(IComputationNode* node, const TCodegenContext& ctx, BasicBlo const auto elem = GetElementPtrInst::CreateInBounds(ptrFunType, table, {ConstantInt::get(Type::getInt64Ty(context), GetMethodIndex(&IComputationNode::GetValue))}, "element", block); const auto func = new LoadInst(ptrFunType, elem, "func", false, block); - if (ctx.Codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) { - CallInst::Create(funType, func, {retPtr, nodeThis, ctx.Ctx}, "", block); - } else { - CallInst::Create(funType, func, {nodeThis, retPtr, ctx.Ctx}, "", block); - } + CallInst::Create(funType, func, {retPtr, nodeThis, ctx.Ctx}, "", block); ValueRelease(node->GetRepresentation(), retPtr, ctx, block); const auto result = new LoadInst(valueType, retPtr, "return", false, block); @@ -1961,9 +1921,9 @@ void GetNodeValue(Value* value, IComputationNode* node, const TCodegenContext& c const auto ptrType = PointerType::getUnqual(StructType::get(context)); const auto nodeThis = CastInst::Create(Instruction::IntToPtr, ptr, ptrType, "node_this", block); - const auto funType = ctx.Codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows ? - FunctionType::get(Type::getVoidTy(context), {value->getType(), nodeThis->getType(), ctx.Ctx->getType()}, false): - FunctionType::get(Type::getVoidTy(context), {nodeThis->getType(), value->getType(), ctx.Ctx->getType()}, false); + const auto funType = + FunctionType::get(Type::getVoidTy(context), {value->getType(), nodeThis->getType(), ctx.Ctx->getType()}, false); + const auto ptrFunType = PointerType::getUnqual(funType); const auto tableType = PointerType::getUnqual(ptrFunType); const auto nodeVTable = CastInst::Create(Instruction::IntToPtr, ptr, PointerType::getUnqual(tableType), "node_vtable", block); @@ -1972,11 +1932,7 @@ void GetNodeValue(Value* value, IComputationNode* node, const TCodegenContext& c const auto elem = GetElementPtrInst::CreateInBounds(ptrFunType, table, {ConstantInt::get(Type::getInt64Ty(context), GetMethodIndex(&IComputationNode::GetValue))}, "element", block); const auto func = new LoadInst(ptrFunType, elem, "func", false, block); - if (ctx.Codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) { - CallInst::Create(funType, func, {value, nodeThis, ctx.Ctx}, "", block); - } else { - CallInst::Create(funType, func, {nodeThis, value, ctx.Ctx}, "", block); - } + CallInst::Create(funType, func, {value, nodeThis, ctx.Ctx}, "", block); } ICodegeneratorInlineWideNode::TGenerateResult GetNodeValues(IComputationWideFlowNode* node, const TCodegenContext& ctx, BasicBlock*& block) { @@ -1990,17 +1946,9 @@ Value* GenNewArray(const TCodegenContext& ctx, Value* size, Value* items, BasicB const auto fact = ctx.GetFactory(); const auto func = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&THolderFactory::CreateDirectArrayHolder)); const auto valueType = Type::getInt128Ty(context); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(valueType, {fact->getType(), size->getType(), items->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - return CallInst::Create(funType, funcPtr, {fact, size, items}, "array", block); - } else { - const auto resultPtr = new AllocaInst(valueType, 0U, "return", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {fact->getType(), resultPtr->getType(), size->getType(), items->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {fact, resultPtr, size, items}, "", block); - return new LoadInst(valueType, resultPtr, "array", block); - } + const auto funType = FunctionType::get(valueType, {fact->getType(), size->getType(), items->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + return CallInst::Create(funType, funcPtr, {fact, size, items}, "array", block); } Value* GetMemoryUsed(ui64 limit, const TCodegenContext& ctx, BasicBlock* block) { @@ -2064,16 +2012,6 @@ Value* CheckAdjustedMemLimit(ui64 limit, Value* init, const TCodegenContext& ctx template Value* CheckAdjustedMemLimit(ui64 limit, Value* init, const TCodegenContext& ctx, BasicBlock*& block); template Value* CheckAdjustedMemLimit(ui64 limit, Value* init, const TCodegenContext& ctx, BasicBlock*& block); -Value* WrapArgumentForWindows(Value* arg, const TCodegenContext& ctx, BasicBlock* block) { - if (ctx.Codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) { - return arg; - } - - const auto newArg = new AllocaInst(arg->getType(), 0, "argument", block); - new StoreInst(arg, newArg, block); - return newArg; -} - Value* CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block) { auto& context = codegen.GetContext(); @@ -2101,9 +2039,8 @@ void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* const auto ptrStructType = PointerType::getUnqual(StructType::get(context)); const auto boxed = CastInst::Create(Instruction::IntToPtr, data, ptrStructType, "boxed", block); - const auto funType = (codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) ? - FunctionType::get(Type::getVoidTy(context), {output->getType(), boxed->getType()}, false): - FunctionType::get(Type::getVoidTy(context), {boxed->getType(), output->getType()}, false); + const auto funType = + FunctionType::get(Type::getVoidTy(context), {output->getType(), boxed->getType()}, false); const auto ptrFunType = PointerType::getUnqual(funType); const auto tableType = PointerType::getUnqual(ptrFunType); const auto vTable = CastInst::Create(Instruction::IntToPtr, data, PointerType::getUnqual(tableType), "vtable", block); @@ -2112,11 +2049,7 @@ void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* const auto elem = GetElementPtrInst::CreateInBounds(ptrFunType, table, {ConstantInt::get(Type::getInt64Ty(context), GetMethodPtrIndex(methodPtr))}, "element", block); const auto func = new LoadInst(ptrFunType, elem, "func", false, block); - if (codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) { - CallInst::Create(funType, func, {output, boxed}, "", block); - } else { - CallInst::Create(funType, func, {boxed, output}, "", block); - } + CallInst::Create(funType, func, {output, boxed}, "", block); } void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* argument) { @@ -2126,9 +2059,8 @@ void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* const auto ptrStructType = PointerType::getUnqual(StructType::get(context)); const auto boxed = CastInst::Create(Instruction::IntToPtr, data, ptrStructType, "boxed", block); - const auto funType = (codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) ? - FunctionType::get(Type::getVoidTy(context), {output->getType(), boxed->getType(), argument->getType()}, false): - FunctionType::get(Type::getVoidTy(context), {boxed->getType(), output->getType(), argument->getType()}, false); + const auto funType = + FunctionType::get(Type::getVoidTy(context), {output->getType(), boxed->getType(), argument->getType()}, false); const auto ptrFunType = PointerType::getUnqual(funType); const auto tableType = PointerType::getUnqual(ptrFunType); const auto vTable = CastInst::Create(Instruction::IntToPtr, data, PointerType::getUnqual(tableType), "vtable", block); @@ -2137,11 +2069,7 @@ void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* const auto elem = GetElementPtrInst::CreateInBounds(ptrFunType, table, {ConstantInt::get(Type::getInt64Ty(context), GetMethodPtrIndex(methodPtr))}, "element", block); const auto func = new LoadInst(ptrFunType, elem, "func", false, block); - if (codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) { - CallInst::Create(funType, func, {output, boxed, argument}, "", block); - } else { - CallInst::Create(funType, func, {boxed, output, argument}, "", block); - } + CallInst::Create(funType, func, {output, boxed, argument}, "", block); } Value* CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* argument) { @@ -2171,9 +2099,8 @@ void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* const auto ptrStructType = PointerType::getUnqual(StructType::get(context)); const auto boxed = CastInst::Create(Instruction::IntToPtr, data, ptrStructType, "boxed", block); - const auto funType = (codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) ? - FunctionType::get(Type::getVoidTy(context), {output->getType(), boxed->getType(), arg1->getType(), arg2->getType()}, false): - FunctionType::get(Type::getVoidTy(context), {boxed->getType(), output->getType(), arg1->getType(), arg2->getType()}, false); + const auto funType = + FunctionType::get(Type::getVoidTy(context), {output->getType(), boxed->getType(), arg1->getType(), arg2->getType()}, false); const auto ptrFunType = PointerType::getUnqual(funType); const auto tableType = PointerType::getUnqual(ptrFunType); const auto vTable = CastInst::Create(Instruction::IntToPtr, data, PointerType::getUnqual(tableType), "vtable", block); @@ -2182,11 +2109,7 @@ void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* const auto elem = GetElementPtrInst::CreateInBounds(ptrFunType, table, {ConstantInt::get(Type::getInt64Ty(context), GetMethodPtrIndex(methodPtr))}, "element", block); const auto func = new LoadInst(ptrFunType, elem, "func", false, block); - if (codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) { - CallInst::Create(funType, func, {output, boxed, arg1, arg2}, "", block); - } else { - CallInst::Create(funType, func, {boxed, output, arg1, arg2}, "", block); - } + CallInst::Create(funType, func, {output, boxed, arg1, arg2}, "", block); } Value* CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* arg1, Value* arg2) { @@ -2212,59 +2135,19 @@ Value* CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Type* returnType, Va Value* CallUnaryUnboxedValueFunctionImpl(uintptr_t methodPtr, Type* result, Value* arg, NYql::NCodegen::ICodegen& codegen, BasicBlock* block) { auto& context = codegen.GetContext(); const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), methodPtr); - if (NYql::NCodegen::ETarget::Windows != codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(result, {arg->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "ptr", block); - const auto call = CallInst::Create(funType, funcPtr, {arg}, "call", block); - return call; - } else { - const auto ptrArg = new AllocaInst(arg->getType(), 0U, "arg", block); - new StoreInst(arg, ptrArg, block); - - if (Type::getInt128Ty(context) == result) { - const auto ptrResult = new AllocaInst(result, 0U, "result", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {ptrResult->getType(), ptrArg->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "ptr", block); - CallInst::Create(funType, funcPtr, {ptrResult, ptrArg}, "", block); - const auto res = new LoadInst(result, ptrResult, "res", block); - return res; - } else { - const auto funType = FunctionType::get(result, {ptrArg->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "ptr", block); - const auto call = CallInst::Create(funType, funcPtr, {ptrArg}, "call", block); - return call; - } - } + const auto funType = FunctionType::get(result, {arg->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "ptr", block); + const auto call = CallInst::Create(funType, funcPtr, {arg}, "call", block); + return call; } Value* CallBinaryUnboxedValueFunctionImpl(uintptr_t methodPtr, Type* result, Value* left, Value* right, NYql::NCodegen::ICodegen& codegen, BasicBlock* block) { auto& context = codegen.GetContext(); const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), methodPtr); - if (NYql::NCodegen::ETarget::Windows != codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(result, {left->getType(), right->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "ptr", block); - const auto call = CallInst::Create(funType, funcPtr, {left, right}, "call", block); - return call; - } else { - const auto ptrLeft = new AllocaInst(left->getType(), 0U, "left", block); - const auto ptrRight = new AllocaInst(right->getType(), 0U, "right", block); - new StoreInst(left, ptrLeft, block); - new StoreInst(right, ptrRight, block); - - if (Type::getInt128Ty(context) == result) { - const auto ptrResult = new AllocaInst(result, 0U, "result", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {ptrResult->getType(), ptrLeft->getType(), ptrRight->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "ptr", block); - CallInst::Create(funType, funcPtr, {ptrResult, ptrLeft, ptrRight}, "", block); - const auto res = new LoadInst(result, ptrResult, "res", block); - return res; - } else { - const auto funType = FunctionType::get(result, {ptrLeft->getType(), ptrRight->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "ptr", block); - const auto call = CallInst::Create(funType, funcPtr, {ptrLeft, ptrRight}, "call", block); - return call; - } - } + const auto funType = FunctionType::get(result, {left->getType(), right->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "ptr", block); + const auto call = CallInst::Create(funType, funcPtr, {left, right}, "call", block); + return call; } Y_NO_INLINE Value* TDecoratorCodegeneratorNodeBase::CreateGetValueImpl(IComputationNode* node, @@ -2541,19 +2424,10 @@ Y_NO_INLINE Value* TMutableCodegeneratorFallbackNodeBase::DoGenerateGetValueImpl const auto ptrType = PointerType::getUnqual(StructType::get(context)); const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), methodPtr); const auto self = CastInst::Create(Instruction::IntToPtr, ConstantInt::get(Type::getInt64Ty(context), thisPtr), ptrType, "self", block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(type, {self->getType(), ctx.Ctx->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx}, "value", block); - return value; - } else { - const auto resultPtr = new AllocaInst(type, 0U, "return", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {self->getType(), resultPtr->getType(), ctx.Ctx->getType()}, false); - const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, doFuncPtr, {self, resultPtr, ctx.Ctx}, "", block); - const auto value = new LoadInst(type, resultPtr, "value", block); - return value; - } + const auto funType = FunctionType::get(type, {self->getType(), ctx.Ctx->getType()}, false); + const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "function", block); + const auto value = CallInst::Create(funType, doFuncPtr, {self, ctx.Ctx}, "value", block); + return value; } Y_NO_INLINE Function* TCodegeneratorRootNodeBase::GenerateGetValueImpl( @@ -2567,9 +2441,8 @@ Y_NO_INLINE Function* TCodegeneratorRootNodeBase::GenerateGetValueImpl( const auto valueType = Type::getInt128Ty(context); const auto contextType = GetCompContextType(context); - const auto funcType = codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows ? - FunctionType::get(valueType, {PointerType::getUnqual(contextType)}, false): - FunctionType::get(Type::getVoidTy(context) , {PointerType::getUnqual(valueType), PointerType::getUnqual(contextType)}, false); + const auto funcType = + FunctionType::get(valueType, {PointerType::getUnqual(contextType)}, false); TCodegenContext ctx(codegen); ctx.Func = cast(module.getOrInsertFunction(name.c_str(), funcType).getCallee()); @@ -2577,25 +2450,13 @@ Y_NO_INLINE Function* TCodegeneratorRootNodeBase::GenerateGetValueImpl( DISubprogramAnnotator annotator(ctx, ctx.Func); auto args = ctx.Func->arg_begin(); - if (codegen.GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows) { - auto& firstArg = *args++; - firstArg.addAttr(Attribute::StructRet); - firstArg.addAttr(Attribute::NoAlias); - } - auto main = BasicBlock::Create(context, "main", ctx.Func); ctx.Ctx = &*args; ctx.Ctx->addAttr(Attribute::NonNull); const auto get = gen->CreateGetValue(ctx, main); - if (codegen.GetEffectiveTarget() != NYql::NCodegen::ETarget::Windows) { - ReturnInst::Create(context, get, main); - } else { - new StoreInst(get, &*--args, main); - ReturnInst::Create(context, main); - } - + ReturnInst::Create(context, get, main); return ctx.Func; } diff --git a/yql/essentials/minikql/computation/mkql_computation_node_codegen.h.txt b/yql/essentials/minikql/computation/mkql_computation_node_codegen.h.txt index ebd63455ebbe..8835b3b65183 100644 --- a/yql/essentials/minikql/computation/mkql_computation_node_codegen.h.txt +++ b/yql/essentials/minikql/computation/mkql_computation_node_codegen.h.txt @@ -173,8 +173,6 @@ public: virtual void CreateRun(const TCodegenContext& ctx, BasicBlock*& block, Value* result, Value* args) const = 0; }; -Value* WrapArgumentForWindows(Value* arg, const TCodegenContext& ctx, BasicBlock* block); - Value* CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block); template diff --git a/yql/essentials/minikql/computation/mkql_computation_node_graph.cpp b/yql/essentials/minikql/computation/mkql_computation_node_graph.cpp index f9209ad23971..e1a79dff5b10 100644 --- a/yql/essentials/minikql/computation/mkql_computation_node_graph.cpp +++ b/yql/essentials/minikql/computation/mkql_computation_node_graph.cpp @@ -814,8 +814,8 @@ class TComputationPatternImpl final : public IComputationPattern { : Codegen((NYql::NCodegen::ICodegen::IsCodegenAvailable() && opts.OptLLVM != "OFF") || GetEnv(TString("MKQL_FORCE_USE_LLVM")) ? NYql::NCodegen::ICodegen::MakeShared(NYql::NCodegen::ETarget::Native) : NYql::NCodegen::ICodegen::TPtr()) #endif { - /// TODO: Enable JIT for AARCH64 -#if defined(__aarch64__) + /// TODO: Enable JIT for AARCH64/Win +#if defined(__aarch64__) || defined(_win_) Codegen = {}; #endif diff --git a/yql/essentials/minikql/computation/mkql_computation_node_holders_codegen.cpp b/yql/essentials/minikql/computation/mkql_computation_node_holders_codegen.cpp index 3fe7772ba9d1..cead70dec0a9 100644 --- a/yql/essentials/minikql/computation/mkql_computation_node_holders_codegen.cpp +++ b/yql/essentials/minikql/computation/mkql_computation_node_holders_codegen.cpp @@ -126,21 +126,12 @@ Value* TContainerCacheOnContext::GenNewArray(ui64 sz, Value* items, const TCodeg const auto func = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&THolderFactory::CreateDirectArrayHolder)); const auto size = ConstantInt::get(Type::getInt64Ty(context), sz); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(valueType, {fact->getType(), size->getType(), items->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto array = CallInst::Create(funType, funcPtr, {fact, size, items}, "array", block); - AddRefBoxed(array, ctx, block); - result->addIncoming(array, block); - new StoreInst(array, tpsecond, block); - } else { - const auto funType = FunctionType::get(Type::getVoidTy(context), {fact->getType(), tpsecond->getType(), size->getType(), items->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {fact, tpsecond, size, items}, "", block); - const auto array = new LoadInst(valueType, tpsecond, "array", block); - AddRefBoxed(array, ctx, block); - result->addIncoming(array, block); - } + const auto funType = FunctionType::get(valueType, {fact->getType(), size->getType(), items->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto array = CallInst::Create(funType, funcPtr, {fact, size, items}, "array", block); + AddRefBoxed(array, ctx, block); + result->addIncoming(array, block); + new StoreInst(array, tpsecond, block); BranchInst::Create(exit, block); } @@ -189,19 +180,10 @@ class TEmptyNode : public TMutableCodegeneratorNode { const auto factory = ctx.GetFactory(); const auto func = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&THolderFactory::GetEmptyContainerLazy)); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(valueType, {factory->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - const auto res = CallInst::Create(funType, funcPtr, {factory}, "res", block); - return res; - } else { - const auto retPtr = new AllocaInst(valueType, 0U, "ret_ptr", block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {factory->getType(), retPtr->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); - CallInst::Create(funType, funcPtr, {factory, retPtr}, "", block); - const auto res = new LoadInst(valueType, retPtr, "res", block); - return res; - } + const auto funType = FunctionType::get(valueType, {factory->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, func, PointerType::getUnqual(funType), "function", block); + const auto res = CallInst::Create(funType, funcPtr, {factory}, "res", block); + return res; } #endif private: diff --git a/yql/essentials/minikql/invoke_builtins/mkql_builtins_find.cpp b/yql/essentials/minikql/invoke_builtins/mkql_builtins_find.cpp index 1224ecfc59a5..6a9120c302e1 100644 --- a/yql/essentials/minikql/invoke_builtins/mkql_builtins_find.cpp +++ b/yql/essentials/minikql/invoke_builtins/mkql_builtins_find.cpp @@ -34,23 +34,10 @@ struct TFind { StaticCast(GetterFor(p, context, block), context, block), "pos", block): StaticCast(GetterFor(p, context, block), context, block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(string->getType(), {string->getType(), sub->getType(), pos->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); - const auto result = CallInst::Create(funType, funcPtr, {string, sub, pos}, "find", block); - return result; - } else { - const auto ptrArg = new AllocaInst(string->getType(), 0U, "arg", block); - const auto ptrSub = new AllocaInst(sub->getType(), 0U, "sub", block); - const auto ptrResult = new AllocaInst(string->getType(), 0U, "result", block); - new StoreInst(string, ptrArg, block); - new StoreInst(sub, ptrSub, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {ptrResult->getType(), ptrArg->getType(), ptrSub->getType(), pos->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); - CallInst::Create(funType, funcPtr, {ptrResult, ptrArg, ptrSub, pos}, "", block); - const auto result = new LoadInst(string->getType(), ptrResult, "find", block); - return result; - } + const auto funType = FunctionType::get(string->getType(), {string->getType(), sub->getType(), pos->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); + const auto result = CallInst::Create(funType, funcPtr, {string, sub, pos}, "find", block); + return result; } #endif }; diff --git a/yql/essentials/minikql/invoke_builtins/mkql_builtins_substring.cpp b/yql/essentials/minikql/invoke_builtins/mkql_builtins_substring.cpp index 2b292f6b36cd..8a0c6f6f586e 100644 --- a/yql/essentials/minikql/invoke_builtins/mkql_builtins_substring.cpp +++ b/yql/essentials/minikql/invoke_builtins/mkql_builtins_substring.cpp @@ -35,21 +35,10 @@ struct TSubString { GetterFor(cn, context, block), "count", block ): GetterFor(cn, context, block); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(string->getType(), {string->getType(), start->getType(), count->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); - const auto result = CallInst::Create(funType, funcPtr, {string, start, count}, "substring", block); - return result; - } else { - const auto ptrArg = new AllocaInst(string->getType(), 0U, "arg", block); - const auto ptrResult = new AllocaInst(string->getType(), 0U, "result", block); - new StoreInst(string, ptrArg, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {ptrResult->getType(), ptrArg->getType(), start->getType(), count->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); - CallInst::Create(funType, funcPtr, {ptrResult, ptrArg, start, count}, "", block); - const auto result = new LoadInst(string->getType(), ptrResult, "substring", block); - return result; - } + const auto funType = FunctionType::get(string->getType(), {string->getType(), start->getType(), count->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); + const auto result = CallInst::Create(funType, funcPtr, {string, start, count}, "substring", block); + return result; } #endif }; diff --git a/yql/essentials/minikql/invoke_builtins/mkql_builtins_with.cpp b/yql/essentials/minikql/invoke_builtins/mkql_builtins_with.cpp index 723bff5cab66..60927c0e187e 100644 --- a/yql/essentials/minikql/invoke_builtins/mkql_builtins_with.cpp +++ b/yql/essentials/minikql/invoke_builtins/mkql_builtins_with.cpp @@ -29,23 +29,10 @@ struct TStringWith { { auto& context = ctx.Codegen.GetContext(); const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(StringFunc)); - if (NYql::NCodegen::ETarget::Windows != ctx.Codegen.GetEffectiveTarget()) { - const auto funType = FunctionType::get(string->getType(), {string->getType(), sub->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); - const auto result = CallInst::Create(funType, funcPtr, {string, sub}, "has", block); - return result; - } else { - const auto ptrArg = new AllocaInst(string->getType(), 0U, "arg", block); - const auto ptrSub = new AllocaInst(sub->getType(), 0U, "sub", block); - const auto ptrResult = new AllocaInst(string->getType(), 0U, "result", block); - new StoreInst(string, ptrArg, block); - new StoreInst(sub, ptrSub, block); - const auto funType = FunctionType::get(Type::getVoidTy(context), {ptrResult->getType(), ptrArg->getType(), ptrSub->getType()}, false); - const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); - CallInst::Create(funType, funcPtr, {ptrResult, ptrArg, ptrSub}, "", block); - const auto result = new LoadInst(string->getType(), ptrResult, "has", block); - return result; - } + const auto funType = FunctionType::get(string->getType(), {string->getType(), sub->getType()}, false); + const auto funcPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(funType), "func", block); + const auto result = CallInst::Create(funType, funcPtr, {string, sub}, "has", block); + return result; } #endif }; diff --git a/yql/essentials/minikql/mkql_program_builder.cpp b/yql/essentials/minikql/mkql_program_builder.cpp index f59e3371fb5e..82c1f604ba1b 100644 --- a/yql/essentials/minikql/mkql_program_builder.cpp +++ b/yql/essentials/minikql/mkql_program_builder.cpp @@ -4600,7 +4600,8 @@ TRuntimeNode TProgramBuilder::ToDecimal(TRuntimeNode data, ui8 precision, ui8 sc } else if (params.second < scale) { return Invoke("ScaleUp_" + ::ToString(scale - params.second), decimal, args); } else if (params.second > scale) { - return Invoke("ScaleDown_" + ::ToString(params.second - scale), decimal, args); + TRuntimeNode scaled = Invoke("ScaleDown_" + ::ToString(params.second - scale), decimal, args); + return Invoke("CheckBounds_" + ::ToString(precision), decimal, {{ scaled }}); } else if (precision < params.first) { return Invoke("CheckBounds_" + ::ToString(precision), decimal, args); } else if (precision > params.first) { diff --git a/yql/essentials/tests/sql/minirun/part0/canondata/result.json b/yql/essentials/tests/sql/minirun/part0/canondata/result.json index 8b7d690d779e..948ea2a8737d 100644 --- a/yql/essentials/tests/sql/minirun/part0/canondata/result.json +++ b/yql/essentials/tests/sql/minirun/part0/canondata/result.json @@ -338,6 +338,20 @@ "uri": "https://{canondata_backend}/1942525/ede9d81525f3cde3c09402fe9435fdbba85f47bc/resource.tar.gz#test.test_expr-as_dict_dict_key-default.txt-Results_/results.txt" } ], + "test.test[expr-cast_decimal-default.txt-Debug]": [ + { + "checksum": "91294751a47cfcb87a5a3af5e0db632c", + "size": 1564, + "uri": "https://{canondata_backend}/1773845/486531303c5d3ec35ed8056fbdb4be070aadc061/resource.tar.gz#test.test_expr-cast_decimal-default.txt-Debug_/opt.yql" + } + ], + "test.test[expr-cast_decimal-default.txt-Results]": [ + { + "checksum": "7bede4f19295253e7740f658c336afed", + "size": 14064, + "uri": "https://{canondata_backend}/1773845/486531303c5d3ec35ed8056fbdb4be070aadc061/resource.tar.gz#test.test_expr-cast_decimal-default.txt-Results_/results.txt" + } + ], "test.test[expr-cast_string_implicit-default.txt-Debug]": [ { "checksum": "558f5bb0eaa3ea5ec6716c10389761b5", diff --git a/yql/essentials/tests/sql/minirun/part1/canondata/result.json b/yql/essentials/tests/sql/minirun/part1/canondata/result.json index 9db67a2417d7..88857905bb4c 100644 --- a/yql/essentials/tests/sql/minirun/part1/canondata/result.json +++ b/yql/essentials/tests/sql/minirun/part1/canondata/result.json @@ -601,6 +601,20 @@ "uri": "https://{canondata_backend}/1936273/dc5c7fc322621a2828a94006237d3583f38248e5/resource.tar.gz#test.test_join-inmem_by_uncomparable_tuples-default.txt-Results_/results.txt" } ], + "test.test[join-yql-19192-default.txt-Debug]": [ + { + "checksum": "b9c6aea35bc8b70c987653997335369d", + "size": 746, + "uri": "https://{canondata_backend}/1814674/dfd418faf4299c20acfad523d570f8cfb90f89ea/resource.tar.gz#test.test_join-yql-19192-default.txt-Debug_/opt.yql" + } + ], + "test.test[join-yql-19192-default.txt-Results]": [ + { + "checksum": "6e4f62a8d64ea7bbe1a05464bcb80ba4", + "size": 1233, + "uri": "https://{canondata_backend}/1814674/dfd418faf4299c20acfad523d570f8cfb90f89ea/resource.tar.gz#test.test_join-yql-19192-default.txt-Results_/results.txt" + } + ], "test.test[library-library_yqls--Debug]": [ { "checksum": "b2bab6a1ef79eb44b255b25d32270957", diff --git a/yql/essentials/tests/sql/sql2yql/canondata/result.json b/yql/essentials/tests/sql/sql2yql/canondata/result.json index 3c9da739188d..7cb5c7d39cbb 100644 --- a/yql/essentials/tests/sql/sql2yql/canondata/result.json +++ b/yql/essentials/tests/sql/sql2yql/canondata/result.json @@ -2008,6 +2008,27 @@ "uri": "https://{canondata_backend}/1942173/99e88108149e222741552e7e6cddef041d6a2846/resource.tar.gz#test_sql2yql.test_expr-callable_/sql.yql" } ], + "test_sql2yql.test[expr-cast_decimal]": [ + { + "checksum": "0beea95df85e9ea70b06ffa9d9eac69f", + "size": 4965, + "uri": "https://{canondata_backend}/1937001/ceef5344342e97b0173a7afba261a6905a152791/resource.tar.gz#test_sql2yql.test_expr-cast_decimal_/sql.yql" + } + ], + "test_sql2yql.test[expr-cast_decimal_implicit_fail_1]": [ + { + "checksum": "a14d03775787d74c68ee4999aba0f644", + "size": 1282, + "uri": "https://{canondata_backend}/1937001/ceef5344342e97b0173a7afba261a6905a152791/resource.tar.gz#test_sql2yql.test_expr-cast_decimal_implicit_fail_1_/sql.yql" + } + ], + "test_sql2yql.test[expr-cast_decimal_implicit_fail_2]": [ + { + "checksum": "d5c5926076f244e9fb0a01e213a839d3", + "size": 1288, + "uri": "https://{canondata_backend}/1937001/ceef5344342e97b0173a7afba261a6905a152791/resource.tar.gz#test_sql2yql.test_expr-cast_decimal_implicit_fail_2_/sql.yql" + } + ], "test_sql2yql.test[expr-cast_dynumber]": [ { "checksum": "f8e5ceebd24d7c79be2988ed186d2b90", @@ -3422,6 +3443,13 @@ "uri": "https://{canondata_backend}/1942173/99e88108149e222741552e7e6cddef041d6a2846/resource.tar.gz#test_sql2yql.test_join-left_join_with_self_aggr_/sql.yql" } ], + "test_sql2yql.test[join-yql-19192]": [ + { + "checksum": "fffdf1cbb40643da9daf9bdf3edec121", + "size": 2305, + "uri": "https://{canondata_backend}/1937367/af84d06d0fb3153f82b596e7db07f2186d2ec3a2/resource.tar.gz#test_sql2yql.test_join-yql-19192_/sql.yql" + } + ], "test_sql2yql.test[join-yql-6199]": [ { "checksum": "5421f92ec269e5d76133e1ca54b6d0d0", @@ -8196,6 +8224,21 @@ "uri": "file://test_sql_format.test_expr-callable_/formatted.sql" } ], + "test_sql_format.test[expr-cast_decimal]": [ + { + "uri": "file://test_sql_format.test_expr-cast_decimal_/formatted.sql" + } + ], + "test_sql_format.test[expr-cast_decimal_implicit_fail_1]": [ + { + "uri": "file://test_sql_format.test_expr-cast_decimal_implicit_fail_1_/formatted.sql" + } + ], + "test_sql_format.test[expr-cast_decimal_implicit_fail_2]": [ + { + "uri": "file://test_sql_format.test_expr-cast_decimal_implicit_fail_2_/formatted.sql" + } + ], "test_sql_format.test[expr-cast_dynumber]": [ { "uri": "file://test_sql_format.test_expr-cast_dynumber_/formatted.sql" @@ -9206,6 +9249,11 @@ "uri": "file://test_sql_format.test_join-left_join_with_self_aggr_/formatted.sql" } ], + "test_sql_format.test[join-yql-19192]": [ + { + "uri": "file://test_sql_format.test_join-yql-19192_/formatted.sql" + } + ], "test_sql_format.test[join-yql-6199]": [ { "uri": "file://test_sql_format.test_join-yql-6199_/formatted.sql" diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_/formatted.sql new file mode 100644 index 000000000000..542ccae35641 --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_/formatted.sql @@ -0,0 +1,50 @@ +-------------------- +-- Explicit casts -- +-------------------- +$strs = AsList('-1', '0', '1', '2.4', '99.77', '999.5', '-7777'); + +$data = ListMap( + $strs, ($str) -> { + RETURN AsStruct($str AS str); + } +); + +SELECT + dataset.*, + + -- Changing range + CAST(dec_3_1 AS Decimal (5, 1)) AS upcast_3_1, + CAST(dec_5_2 AS Decimal (4, 2)) AS downcast_5_2, + + -- Changing precision + CAST(dec_5_2 AS Decimal (3, 0)) AS rounded_5_2, + CAST(dec_7_0 AS Decimal (9, 2)) AS extended_7_0, + + -- Combinations + CAST(dec_5_2 AS Decimal (6, 0)) AS upcast_rounded_5_2, + CAST(dec_3_1 AS Decimal (7, 3)) AS upcast_extended_3_1, + CAST(dec_5_2 AS Decimal (3, 1)) AS downcast_rounded_5_2, + CAST(dec_7_0 AS Decimal (5, 2)) AS downcast_extended_7_0 +FROM ( + SELECT + str AS a_str, + CAST(str AS Decimal (3, 1)) AS dec_3_1, + CAST(str AS Decimal (5, 2)) AS dec_5_2, + CAST(str AS Decimal (7, 0)) AS dec_7_0 + FROM + AS_TABLE($data) +) AS dataset; + +-------------------- +-- Implicit cast -- +-------------------- +$lambda = ($big_dec) -> { + RETURN $big_dec; +}; + +$func = CALLABLE (Callable<(Decimal (10, 5)) -> Decimal (10, 5)>, $lambda); +$small_dec = Decimal('3.0', 2, 1); + +SELECT + $func($small_dec) +; diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_implicit_fail_1_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_implicit_fail_1_/formatted.sql new file mode 100644 index 000000000000..80c87b460000 --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_implicit_fail_1_/formatted.sql @@ -0,0 +1,12 @@ +/* postgres can not */ +/* custom error: Error: Implicit decimal cast would lose precision */ +$lambda = ($small_dec) -> { + RETURN $small_dec; +}; + +$func_3_1 = CALLABLE (Callable<(Decimal (3, 1)) -> Decimal (3, 1)>, $lambda); +$dec_4_2 = Decimal('11.1', 4, 2); + +SELECT + $func_3_1($dec_4_2) AS try_round +; diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_implicit_fail_2_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_implicit_fail_2_/formatted.sql new file mode 100644 index 000000000000..4691c1a4fd72 --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_expr-cast_decimal_implicit_fail_2_/formatted.sql @@ -0,0 +1,12 @@ +/* postgres can not */ +/* custom error: Error: Implicit decimal cast would narrow the range */ +$lambda = ($small_dec) -> { + RETURN $small_dec; +}; + +$func_3_1 = CALLABLE (Callable<(Decimal (3, 1)) -> Decimal (3, 1)>, $lambda); +$dec_5_1 = Decimal('22.2', 5, 1); + +SELECT + $func_3_1($dec_5_1) AS try_downcast +; diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_join-yql-19192_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_join-yql-19192_/formatted.sql new file mode 100644 index 000000000000..aa600c52ab09 --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_join-yql-19192_/formatted.sql @@ -0,0 +1,18 @@ +$samples1 = AsList(<|sampl: 1|>, <|sampl: 2|>); +$sampling_cumulative_prob1 = AsList(<|color: 'blue', cum_prob: 3|>); + +$cumulative_bounds = ( + SELECT + LAG(cum_prob) OVER () AS lower_cum_bound + FROM + AS_TABLE($sampling_cumulative_prob1) +); + +SELECT + s.sampl, + cb.lower_cum_bound +FROM + AS_TABLE($samples1) AS s +CROSS JOIN + $cumulative_bounds AS cb +; diff --git a/yql/essentials/tests/sql/suites/expr/cast_decimal.sql b/yql/essentials/tests/sql/suites/expr/cast_decimal.sql new file mode 100644 index 000000000000..ed5635406c64 --- /dev/null +++ b/yql/essentials/tests/sql/suites/expr/cast_decimal.sql @@ -0,0 +1,40 @@ +-------------------- +-- Explicit casts -- +-------------------- +$strs = AsList("-1", "0", "1", "2.4", "99.77", "999.5", "-7777"); +$data = ListMap($strs, ($str) -> { return AsStruct($str as str); }); + +SELECT + dataset.*, + + -- Changing range + CAST(dec_3_1 AS Decimal(5, 1)) AS upcast_3_1, + CAST(dec_5_2 AS Decimal(4, 2)) AS downcast_5_2, + + -- Changing precision + CAST(dec_5_2 AS Decimal(3, 0)) AS rounded_5_2, + CAST(dec_7_0 AS Decimal(9, 2)) AS extended_7_0, + + -- Combinations + CAST(dec_5_2 AS Decimal(6, 0)) AS upcast_rounded_5_2, + CAST(dec_3_1 AS Decimal(7, 3)) AS upcast_extended_3_1, + CAST(dec_5_2 AS Decimal(3, 1)) AS downcast_rounded_5_2, + CAST(dec_7_0 AS Decimal(5, 2)) AS downcast_extended_7_0 +FROM ( + SELECT + str AS a_str, + CAST(str AS Decimal(3, 1)) AS dec_3_1, + CAST(str AS Decimal(5, 2)) AS dec_5_2, + CAST(str AS Decimal(7, 0)) AS dec_7_0 + FROM AS_TABLE($data) +) as dataset; + +-------------------- +-- Implicit cast -- +-------------------- +$lambda = ($big_dec) -> { return $big_dec; }; +$func = Callable(Callable<(Decimal(10, 5))->Decimal(10, 5)>, $lambda); + +$small_dec = Decimal("3.0", 2, 1); + +SELECT $func($small_dec); diff --git a/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_1.cfg b/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_1.cfg new file mode 100644 index 000000000000..5dae597903c3 --- /dev/null +++ b/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_1.cfg @@ -0,0 +1 @@ +xfail diff --git a/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_1.sql b/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_1.sql new file mode 100644 index 000000000000..ab58383d714c --- /dev/null +++ b/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_1.sql @@ -0,0 +1,8 @@ +/* postgres can not */ +/* custom error: Error: Implicit decimal cast would lose precision */ +$lambda = ($small_dec) -> { return $small_dec; }; + +$func_3_1 = Callable(Callable<(Decimal(3, 1))->Decimal(3, 1)>, $lambda); +$dec_4_2 = Decimal("11.1", 4, 2); + +SELECT $func_3_1($dec_4_2) AS try_round; diff --git a/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_2.cfg b/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_2.cfg new file mode 100644 index 000000000000..5dae597903c3 --- /dev/null +++ b/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_2.cfg @@ -0,0 +1 @@ +xfail diff --git a/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_2.sql b/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_2.sql new file mode 100644 index 000000000000..9da5dd8c4e54 --- /dev/null +++ b/yql/essentials/tests/sql/suites/expr/cast_decimal_implicit_fail_2.sql @@ -0,0 +1,8 @@ +/* postgres can not */ +/* custom error: Error: Implicit decimal cast would narrow the range */ +$lambda = ($small_dec) -> { return $small_dec; }; + +$func_3_1 = Callable(Callable<(Decimal(3, 1))->Decimal(3, 1)>, $lambda); +$dec_5_1 = Decimal("22.2", 5, 1); + +SELECT $func_3_1($dec_5_1) AS try_downcast; diff --git a/yql/essentials/tests/sql/suites/join/yql-19192.sql b/yql/essentials/tests/sql/suites/join/yql-19192.sql new file mode 100644 index 000000000000..76cc78833dd0 --- /dev/null +++ b/yql/essentials/tests/sql/suites/join/yql-19192.sql @@ -0,0 +1,12 @@ +$samples1 = AsList(<|sampl: 1|>, <|sampl: 2|>); +$sampling_cumulative_prob1 = AsList(<|color: "blue", cum_prob: 3|>); + +$cumulative_bounds = SELECT + LAG(cum_prob) OVER () AS lower_cum_bound +FROM AS_TABLE($sampling_cumulative_prob1); + +SELECT + s.sampl, + cb.lower_cum_bound +FROM AS_TABLE($samples1) AS s +CROSS JOIN $cumulative_bounds AS cb; \ No newline at end of file diff --git a/yql/essentials/udfs/common/math/math_udf.cpp b/yql/essentials/udfs/common/math/math_udf.cpp index 1c2652320bb3..56e86de6288e 100644 --- a/yql/essentials/udfs/common/math/math_udf.cpp +++ b/yql/essentials/udfs/common/math/math_udf.cpp @@ -60,12 +60,21 @@ using TTaggedRoundingMode = NYql::NUdf::TTagged; #define MATH_UDF_MAP_WITHOUT_IR(XX) \ XX(NearbyInt, TOptional(TAutoMap, TTaggedRoundingMode), 0) +#ifdef DISABLE_IR +#define MATH_STRICT_UDF(name, signature, optionalArgsCount) \ + SIMPLE_STRICT_UDF_WITH_OPTIONAL_ARGS(T##name, signature, optionalArgsCount) { \ + TUnboxedValuePod res; \ + name##IR(this, &res, valueBuilder, args); \ + return res; \ + } +#else #define MATH_STRICT_UDF(name, signature, optionalArgsCount) \ SIMPLE_STRICT_UDF_WITH_IR(T##name, signature, optionalArgsCount, "/llvm_bc/Math", #name "IR") { \ TUnboxedValuePod res; \ name##IR(this, &res, valueBuilder, args); \ return res; \ } +#endif #define MATH_STRICT_UDF_WITHOUT_IR(name, signature, optionalArgsCount) \ SIMPLE_STRICT_UDF_WITH_OPTIONAL_ARGS(T##name, signature, optionalArgsCount) { \ diff --git a/yql/essentials/udfs/common/math/ya.make b/yql/essentials/udfs/common/math/ya.make index 4c0909d2393a..2e91b467d8ee 100644 --- a/yql/essentials/udfs/common/math/ya.make +++ b/yql/essentials/udfs/common/math/ya.make @@ -9,64 +9,70 @@ YQL_UDF_CONTRIB(math_udf) SRCS( math_udf.cpp ) + + IF (BUILD_TYPE != "release" AND BUILD_TYPE != "relwithdebinfo") + CFLAGS(-DDISABLE_IR) + ELSE() + USE_LLVM_BC14() + + LLVM_BC( + math_ir.cpp + lib/erfinv.cpp + NAME Math + SYMBOLS + PiIR + EIR + EpsIR + RoundDownwardIR + RoundToNearestIR + RoundTowardZeroIR + RoundUpwardIR + AbsIR + AcosIR + AsinIR + AsinhIR + AtanIR + CbrtIR + CeilIR + CosIR + CoshIR + ErfIR + ErfInvIR + ErfcInvIR + ExpIR + Exp2IR + FabsIR + FloorIR + LgammaIR + RintIR + SinIR + SinhIR + SqrtIR + TanIR + TanhIR + TgammaIR + TruncIR + IsFiniteIR + IsInfIR + IsNaNIR + Atan2IR + FmodIR + HypotIR + RemainderIR + PowIR + LdexpIR + LogIR + Log2IR + Log10IR + SigmoidIR + FuzzyEqualsIR + RoundIR + ModIR + RemIR + ) + + ENDIF() - USE_LLVM_BC14() - - LLVM_BC( - math_ir.cpp - lib/erfinv.cpp - NAME Math - SYMBOLS - PiIR - EIR - EpsIR - RoundDownwardIR - RoundToNearestIR - RoundTowardZeroIR - RoundUpwardIR - AbsIR - AcosIR - AsinIR - AsinhIR - AtanIR - CbrtIR - CeilIR - CosIR - CoshIR - ErfIR - ErfInvIR - ErfcInvIR - ExpIR - Exp2IR - FabsIR - FloorIR - LgammaIR - RintIR - SinIR - SinhIR - SqrtIR - TanIR - TanhIR - TgammaIR - TruncIR - IsFiniteIR - IsInfIR - IsNaNIR - Atan2IR - FmodIR - HypotIR - RemainderIR - PowIR - LdexpIR - LogIR - Log2IR - Log10IR - SigmoidIR - FuzzyEqualsIR - RoundIR - ModIR - RemIR - ) PEERDIR( yql/essentials/udfs/common/math/lib diff --git a/yt/cpp/mapreduce/client/batch_request_impl.cpp b/yt/cpp/mapreduce/client/batch_request_impl.cpp index f45eee319bf2..e7456b918733 100644 --- a/yt/cpp/mapreduce/client/batch_request_impl.cpp +++ b/yt/cpp/mapreduce/client/batch_request_impl.cpp @@ -36,11 +36,11 @@ using ::NThreading::NewPromise; TBatchRequest::TBatchRequest(const TTransactionId& defaultTransaction, ::TIntrusivePtr client) : DefaultTransaction_(defaultTransaction) - , Impl_(MakeIntrusive(client->GetContext().Config)) + , Impl_(client->GetRawClient()->CreateRawBatchRequest()) , Client_(client) { } -TBatchRequest::TBatchRequest(THttpRawBatchRequest* impl, ::TIntrusivePtr client) +TBatchRequest::TBatchRequest(IRawBatchRequest* impl, ::TIntrusivePtr client) : Impl_(impl) , Client_(std::move(client)) { } @@ -189,7 +189,7 @@ TFuture TBatchRequest::CheckPermission( void TBatchRequest::ExecuteBatch(const TExecuteBatchOptions& options) { - Impl_->ExecuteBatch(Client_->GetRetryPolicy()->CreatePolicyForGenericRequest(), Client_->GetContext(), options); + Impl_->ExecuteBatch(options); } //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/cpp/mapreduce/client/batch_request_impl.h b/yt/cpp/mapreduce/client/batch_request_impl.h index d53eb196dd55..bbd993a925cc 100644 --- a/yt/cpp/mapreduce/client/batch_request_impl.h +++ b/yt/cpp/mapreduce/client/batch_request_impl.h @@ -22,10 +22,6 @@ struct TResponseInfo; class TClient; using TClientPtr = ::TIntrusivePtr; -namespace NRawClient { - class THttpRawBatchRequest; -} - //////////////////////////////////////////////////////////////////////////////// class TBatchRequest @@ -119,11 +115,11 @@ class TBatchRequest virtual void ExecuteBatch(const TExecuteBatchOptions& executeBatch) override; private: - TBatchRequest(NDetail::NRawClient::THttpRawBatchRequest* impl, ::TIntrusivePtr client); + TBatchRequest(IRawBatchRequest* impl, ::TIntrusivePtr client); private: TTransactionId DefaultTransaction_; - ::TIntrusivePtr Impl_; + IRawBatchRequestPtr Impl_; std::unique_ptr TmpWithTransaction_; ::TIntrusivePtr Client_; diff --git a/yt/cpp/mapreduce/client/client.cpp b/yt/cpp/mapreduce/client/client.cpp index 9443ea51fceb..8e3eed7bdc18 100644 --- a/yt/cpp/mapreduce/client/client.cpp +++ b/yt/cpp/mapreduce/client/client.cpp @@ -276,7 +276,7 @@ void TClientBase::Concatenate( TRichYPath TClientBase::CanonizeYPath(const TRichYPath& path) { - return NRawClient::CanonizeYPath(ClientRetryPolicy_->CreatePolicyForGenericRequest(), Context_, path); + return NRawClient::CanonizeYPath(RawClient_, path); } TVector TClientBase::GetTableColumnarStatistics( diff --git a/yt/cpp/mapreduce/client/lock.cpp b/yt/cpp/mapreduce/client/lock.cpp index 46306fa7377c..4eecfdb0d5b2 100644 --- a/yt/cpp/mapreduce/client/lock.cpp +++ b/yt/cpp/mapreduce/client/lock.cpp @@ -26,7 +26,7 @@ class TLockPollerItem , Acquired_(acquired) { } - void PrepareRequest(THttpRawBatchRequest* batchRequest) override + void PrepareRequest(IRawBatchRequest* batchRequest) override { LockState_ = batchRequest->Get(TTransactionId(), LockStateYPath_, TGetOptions()); } diff --git a/yt/cpp/mapreduce/client/operation.cpp b/yt/cpp/mapreduce/client/operation.cpp index 8ace8a44bb59..ef7015a6f1b7 100644 --- a/yt/cpp/mapreduce/client/operation.cpp +++ b/yt/cpp/mapreduce/client/operation.cpp @@ -225,11 +225,10 @@ TStructuredJobTableList ApplyProtobufColumnFilters( } auto isDynamic = NRawClient::BatchTransform( - CreateDefaultRequestRetryPolicy(preparer.GetContext().Config), - preparer.GetContext(), + preparer.GetClient()->GetRawClient(), tableList, - [&] (NRawClient::THttpRawBatchRequest& batch, const auto& table) { - return batch.Get(preparer.GetTransactionId(), table.RichYPath->Path_ + "/@dynamic", TGetOptions()); + [&] (IRawBatchRequestPtr batch, const auto& table) { + return batch->Get(preparer.GetTransactionId(), table.RichYPath->Path_ + "/@dynamic", TGetOptions()); }); auto newTableList = tableList; @@ -281,8 +280,8 @@ TSimpleOperationIo CreateSimpleOperationIo( structuredJob, preparer, options, - CanonizeStructuredTableList(preparer.GetContext(), GetStructuredInputs(spec)), - CanonizeStructuredTableList(preparer.GetContext(), GetStructuredOutputs(spec)), + CanonizeStructuredTableList(preparer.GetClient()->GetRawClient(), GetStructuredInputs(spec)), + CanonizeStructuredTableList(preparer.GetClient()->GetRawClient(), GetStructuredOutputs(spec)), hints, nodeReaderFormat, GetColumnsUsedInOperation(spec)); @@ -304,8 +303,8 @@ TSimpleOperationIo CreateSimpleOperationIo( } }; - auto inputs = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer.GetContext(), spec.GetInputs()); - auto outputs = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer.GetContext(), spec.GetOutputs()); + auto inputs = NRawClient::CanonizeYPaths(preparer.GetClient()->GetRawClient(), spec.GetInputs()); + auto outputs = NRawClient::CanonizeYPaths(preparer.GetClient()->GetRawClient(), spec.GetOutputs()); VerifyHasElements(inputs, "input"); VerifyHasElements(outputs, "output"); @@ -318,7 +317,6 @@ TSimpleOperationIo CreateSimpleOperationIo( inputs, outputs, preparer.GetClient()->GetRawClient(), - preparer.GetContext(), preparer.GetClientRetryPolicy(), preparer.GetTransactionId()), &inputs, @@ -497,7 +495,6 @@ TSimpleOperationIo CreateSimpleOperationIoHelper( structuredInputs, structuredOutputs, preparer.GetClient()->GetRawClient(), - preparer.GetContext(), preparer.GetClientRetryPolicy(), preparer.GetTransactionId()), &structuredInputs, @@ -644,7 +641,7 @@ TNode BuildAutoMergeSpec(const TAutoMergeSpec& options) return result; } -TNode BuildJobProfilerSpec(const TJobProfilerSpec& profilerSpec) +[[maybe_unused]] TNode BuildJobProfilerSpec(const TJobProfilerSpec& profilerSpec) { TNode result; if (profilerSpec.ProfilingBinary_) { @@ -1635,9 +1632,9 @@ void ExecuteMapReduce( TMapReduceOperationSpec spec = spec_; TMapReduceOperationIo operationIo; - auto structuredInputs = CanonizeStructuredTableList(preparer->GetContext(), spec.GetStructuredInputs()); - auto structuredMapOutputs = CanonizeStructuredTableList(preparer->GetContext(), spec.GetStructuredMapOutputs()); - auto structuredOutputs = CanonizeStructuredTableList(preparer->GetContext(), spec.GetStructuredOutputs()); + auto structuredInputs = CanonizeStructuredTableList(preparer->GetClient()->GetRawClient(), spec.GetStructuredInputs()); + auto structuredMapOutputs = CanonizeStructuredTableList(preparer->GetClient()->GetRawClient(), spec.GetStructuredMapOutputs()); + auto structuredOutputs = CanonizeStructuredTableList(preparer->GetClient()->GetRawClient(), spec.GetStructuredOutputs()); const bool inferOutputSchema = options.InferOutputSchema_.GetOrElse(preparer->GetContext().Config->InferTableSchema); @@ -1688,7 +1685,6 @@ void ExecuteMapReduce( structuredInputs, mapperOutput, preparer->GetClient()->GetRawClient(), - preparer->GetContext(), preparer->GetClientRetryPolicy(), preparer->GetTransactionId()), &structuredInputs, @@ -1758,7 +1754,6 @@ void ExecuteMapReduce( inputs, outputs, preparer->GetClient()->GetRawClient(), - preparer->GetContext(), preparer->GetClientRetryPolicy(), preparer->GetTransactionId()), &inputs, @@ -1824,7 +1819,6 @@ void ExecuteMapReduce( structuredInputs, structuredOutputs, preparer->GetClient()->GetRawClient(), - preparer->GetContext(), preparer->GetClientRetryPolicy(), preparer->GetTransactionId()), &structuredInputs, @@ -1904,9 +1898,9 @@ void ExecuteRawMapReduce( YT_LOG_DEBUG("Starting raw map-reduce operation (PreparationId: %v)", preparer->GetPreparationId()); TMapReduceOperationIo operationIo; - operationIo.Inputs = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer->GetContext(), spec.GetInputs()); - operationIo.MapOutputs = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer->GetContext(), spec.GetMapOutputs()); - operationIo.Outputs = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer->GetContext(), spec.GetOutputs()); + operationIo.Inputs = NRawClient::CanonizeYPaths(preparer->GetClient()->GetRawClient(), spec.GetInputs()); + operationIo.MapOutputs = NRawClient::CanonizeYPaths(preparer->GetClient()->GetRawClient(), spec.GetMapOutputs()); + operationIo.Outputs = NRawClient::CanonizeYPaths(preparer->GetClient()->GetRawClient(), spec.GetOutputs()); VerifyHasElements(operationIo.Inputs, "inputs"); VerifyHasElements(operationIo.Outputs, "outputs"); @@ -1953,8 +1947,8 @@ void ExecuteSort( { YT_LOG_DEBUG("Starting sort operation (PreparationId: %v)", preparer->GetPreparationId()); - auto inputs = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer->GetContext(), spec.Inputs_); - auto output = NRawClient::CanonizeYPath(nullptr, preparer->GetContext(), spec.Output_); + auto inputs = NRawClient::CanonizeYPaths(preparer->GetClient()->GetRawClient(), spec.Inputs_); + auto output = NRawClient::CanonizeYPath(preparer->GetClient()->GetRawClient(), spec.Output_); if (options.CreateOutputTables_) { CheckInputTablesExist(*preparer, inputs); @@ -2002,8 +1996,8 @@ void ExecuteMerge( { YT_LOG_DEBUG("Starting merge operation (PreparationId: %v)", preparer->GetPreparationId()); - auto inputs = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer->GetContext(), spec.Inputs_); - auto output = NRawClient::CanonizeYPath(nullptr, preparer->GetContext(), spec.Output_); + auto inputs = NRawClient::CanonizeYPaths(preparer->GetClient()->GetRawClient(), spec.Inputs_); + auto output = NRawClient::CanonizeYPath(preparer->GetClient()->GetRawClient(), spec.Output_); if (options.CreateOutputTables_) { CheckInputTablesExist(*preparer, inputs); @@ -2052,7 +2046,7 @@ void ExecuteErase( { YT_LOG_DEBUG("Starting erase operation (PreparationId: %v)", preparer->GetPreparationId()); - auto tablePath = NRawClient::CanonizeYPath(nullptr, preparer->GetContext(), spec.TablePath_); + auto tablePath = NRawClient::CanonizeYPath(preparer->GetClient()->GetRawClient(), spec.TablePath_); TNode specNode = BuildYsonNodeFluently() .BeginMap() @@ -2088,8 +2082,8 @@ void ExecuteRemoteCopy( { YT_LOG_DEBUG("Starting remote copy operation (PreparationId: %v)", preparer->GetPreparationId()); - auto inputs = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer->GetContext(), spec.Inputs_); - auto output = NRawClient::CanonizeYPath(nullptr, preparer->GetContext(), spec.Output_); + auto inputs = NRawClient::CanonizeYPaths(preparer->GetClient()->GetRawClient(), spec.Inputs_); + auto output = NRawClient::CanonizeYPath(preparer->GetClient()->GetRawClient(), spec.Output_); if (options.CreateOutputTables_) { CreateOutputTable(*preparer, output); @@ -2343,7 +2337,7 @@ class TOperationPollerItem : OperationImpl_(std::move(operationImpl)) { } - void PrepareRequest(NRawClient::THttpRawBatchRequest* batchRequest) override + void PrepareRequest(IRawBatchRequest* batchRequest) override { auto filter = TOperationAttributeFilter() .Add(EOperationAttribute::State) diff --git a/yt/cpp/mapreduce/client/operation_preparer.cpp b/yt/cpp/mapreduce/client/operation_preparer.cpp index ac6ea0f9238b..c1907a703781 100644 --- a/yt/cpp/mapreduce/client/operation_preparer.cpp +++ b/yt/cpp/mapreduce/client/operation_preparer.cpp @@ -42,7 +42,7 @@ class TWaitOperationStartPollerItem , Transaction_(std::move(transaction)) { } - void PrepareRequest(NRawClient::THttpRawBatchRequest* batchRequest) override + void PrepareRequest(IRawBatchRequest* batchRequest) override { Future_ = batchRequest->GetOperation( OperationId_, @@ -213,26 +213,26 @@ void TOperationPreparer::LockFiles(TVector* paths) TVector<::NThreading::TFuture> lockIdFutures; lockIdFutures.reserve(paths->size()); - NRawClient::THttpRawBatchRequest lockRequest(GetContext().Config); + auto lockRequest = Client_->GetRawClient()->CreateRawBatchRequest(); for (const auto& path : *paths) { - lockIdFutures.push_back(lockRequest.Lock( + lockIdFutures.push_back(lockRequest->Lock( FileTransaction_->GetId(), path.Path_, ELockMode::LM_SNAPSHOT, TLockOptions().Waitable(true))); } - lockRequest.ExecuteBatch(ClientRetryPolicy_->CreatePolicyForGenericRequest(), GetContext()); + lockRequest->ExecuteBatch(); TVector<::NThreading::TFuture> nodeIdFutures; nodeIdFutures.reserve(paths->size()); - NRawClient::THttpRawBatchRequest getNodeIdRequest(GetContext().Config); + auto getNodeIdRequest = Client_->GetRawClient()->CreateRawBatchRequest(); for (const auto& lockIdFuture : lockIdFutures) { - nodeIdFutures.push_back(getNodeIdRequest.Get( + nodeIdFutures.push_back(getNodeIdRequest->Get( FileTransaction_->GetId(), ::TStringBuilder() << '#' << GetGuidAsString(lockIdFuture.GetValue()) << "/@node_id", TGetOptions())); } - getNodeIdRequest.ExecuteBatch(ClientRetryPolicy_->CreatePolicyForGenericRequest(), GetContext()); + getNodeIdRequest->ExecuteBatch(); for (size_t i = 0; i != paths->size(); ++i) { auto& richPath = (*paths)[i]; @@ -394,7 +394,7 @@ TJobPreparer::TJobPreparer( { CreateStorage(); - auto cypressFileList = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, OperationPreparer_.GetContext(), spec.Files_); + auto cypressFileList = NRawClient::CanonizeYPaths(RawClient_, spec.Files_); for (const auto& file : cypressFileList) { UseFileInCypress(file); diff --git a/yt/cpp/mapreduce/client/prepare_operation.cpp b/yt/cpp/mapreduce/client/prepare_operation.cpp index 83695ef1e838..31574d7e0e41 100644 --- a/yt/cpp/mapreduce/client/prepare_operation.cpp +++ b/yt/cpp/mapreduce/client/prepare_operation.cpp @@ -20,11 +20,9 @@ TOperationPreparationContext::TOperationPreparationContext( const TStructuredJobTableList& structuredInputs, const TStructuredJobTableList& structuredOutputs, const IRawClientPtr& rawClient, - const TClientContext& context, const IClientRetryPolicyPtr& retryPolicy, TTransactionId transactionId) : RawClient_(rawClient) - , Context_(context) , RetryPolicy_(retryPolicy) , TransactionId_(transactionId) , InputSchemas_(structuredInputs.size()) @@ -44,11 +42,9 @@ TOperationPreparationContext::TOperationPreparationContext( TVector inputs, TVector outputs, const IRawClientPtr& rawClient, - const TClientContext& context, const IClientRetryPolicyPtr& retryPolicy, TTransactionId transactionId) : RawClient_(rawClient) - , Context_(context) , RetryPolicy_(retryPolicy) , TransactionId_(transactionId) , InputSchemas_(inputs.size()) @@ -77,17 +73,17 @@ int TOperationPreparationContext::GetOutputCount() const const TVector& TOperationPreparationContext::GetInputSchemas() const { TVector<::NThreading::TFuture> schemaFutures; - NRawClient::THttpRawBatchRequest batch(Context_.Config); + auto batch = RawClient_->CreateRawBatchRequest(); for (int tableIndex = 0; tableIndex < static_cast(InputSchemas_.size()); ++tableIndex) { if (InputSchemasLoaded_[tableIndex]) { schemaFutures.emplace_back(); continue; } Y_ABORT_UNLESS(Inputs_[tableIndex]); - schemaFutures.push_back(batch.Get(TransactionId_, Inputs_[tableIndex]->Path_ + "/@schema", TGetOptions{})); + schemaFutures.push_back(batch->Get(TransactionId_, Inputs_[tableIndex]->Path_ + "/@schema", TGetOptions{})); } - batch.ExecuteBatch(RetryPolicy_->CreatePolicyForGenericRequest(), Context_); + batch->ExecuteBatch(); for (int tableIndex = 0; tableIndex < static_cast(InputSchemas_.size()); ++tableIndex) { if (schemaFutures[tableIndex].Initialized()) { diff --git a/yt/cpp/mapreduce/client/prepare_operation.h b/yt/cpp/mapreduce/client/prepare_operation.h index 3fde1d1678ee..7b34703e897a 100644 --- a/yt/cpp/mapreduce/client/prepare_operation.h +++ b/yt/cpp/mapreduce/client/prepare_operation.h @@ -16,7 +16,6 @@ class TOperationPreparationContext const TStructuredJobTableList& structuredInputs, const TStructuredJobTableList& structuredOutputs, const IRawClientPtr& rawClient, - const TClientContext& context, const IClientRetryPolicyPtr& retryPolicy, TTransactionId transactionId); @@ -24,7 +23,6 @@ class TOperationPreparationContext TVector inputs, TVector outputs, const IRawClientPtr& rawClient, - const TClientContext& context, const IClientRetryPolicyPtr& retryPolicy, TTransactionId transactionId); @@ -42,7 +40,6 @@ class TOperationPreparationContext TVector> Outputs_; const IRawClientPtr RawClient_; - const TClientContext& Context_; const IClientRetryPolicyPtr RetryPolicy_; TTransactionId TransactionId_; diff --git a/yt/cpp/mapreduce/client/py_helpers.cpp b/yt/cpp/mapreduce/client/py_helpers.cpp index 3072449866ed..79c372daa96c 100644 --- a/yt/cpp/mapreduce/client/py_helpers.cpp +++ b/yt/cpp/mapreduce/client/py_helpers.cpp @@ -51,7 +51,7 @@ TStructuredJobTableList NodeToStructuredTablePaths(const TNode& node, const TOpe paths.emplace_back(inputNode.AsString()); } } - paths = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, preparer.GetContext(), paths); + paths = NRawClient::CanonizeYPaths(preparer.GetClient()->GetRawClient(), paths); TStructuredJobTableList result(intermediateTableCount, TStructuredJobTable::Intermediate(TUnspecifiedTableStructure())); for (const auto& path : paths) { result.emplace_back(TStructuredJobTable{TUnspecifiedTableStructure(), path}); diff --git a/yt/cpp/mapreduce/client/skiff.cpp b/yt/cpp/mapreduce/client/skiff.cpp index 499a1308fd16..113dee0743ab 100644 --- a/yt/cpp/mapreduce/client/skiff.cpp +++ b/yt/cpp/mapreduce/client/skiff.cpp @@ -279,8 +279,7 @@ TFormat CreateSkiffFormat(const NSkiff::TSkiffSchemaPtr& schema) { } NSkiff::TSkiffSchemaPtr CreateSkiffSchemaIfNecessary( - const TClientContext& context, - const IClientRetryPolicyPtr& clientRetryPolicy, + const IRawClientPtr& rawClient, const TTransactionId& transactionId, ENodeReaderFormat nodeReaderFormat, const TVector& tablePaths, @@ -304,10 +303,9 @@ NSkiff::TSkiffSchemaPtr CreateSkiffSchemaIfNecessary( } auto nodes = NRawClient::BatchTransform( - clientRetryPolicy->CreatePolicyForGenericRequest(), - context, - NRawClient::CanonizeYPaths(clientRetryPolicy->CreatePolicyForGenericRequest(), context, tablePaths), - [&] (THttpRawBatchRequest& batch, const TRichYPath& path) { + rawClient, + NRawClient::CanonizeYPaths(rawClient, tablePaths), + [&] (IRawBatchRequestPtr batch, const TRichYPath& path) { auto getOptions = TGetOptions() .AttributeFilter( TAttributeFilter() @@ -315,7 +313,7 @@ NSkiff::TSkiffSchemaPtr CreateSkiffSchemaIfNecessary( .AddAttribute("dynamic") .AddAttribute("type") ); - return batch.Get(transactionId, path.Path_, getOptions); + return batch->Get(transactionId, path.Path_, getOptions); }); TVector schemas; diff --git a/yt/cpp/mapreduce/client/skiff.h b/yt/cpp/mapreduce/client/skiff.h index 82d80a4967a7..5f26dc765630 100644 --- a/yt/cpp/mapreduce/client/skiff.h +++ b/yt/cpp/mapreduce/client/skiff.h @@ -59,8 +59,7 @@ void Deserialize(NSkiff::TSkiffSchemaPtr& schema, const TNode& node); TFormat CreateSkiffFormat(const NSkiff::TSkiffSchemaPtr& schema); NSkiff::TSkiffSchemaPtr CreateSkiffSchemaIfNecessary( - const TClientContext& context, - const IClientRetryPolicyPtr& clientRetryPolicy, + const IRawClientPtr& rawClient, const TTransactionId& transactionId, ENodeReaderFormat nodeReaderFormat, const TVector& tablePaths, diff --git a/yt/cpp/mapreduce/client/structured_table_formats.cpp b/yt/cpp/mapreduce/client/structured_table_formats.cpp index 72b76e6b8054..9da31dcf14e9 100644 --- a/yt/cpp/mapreduce/client/structured_table_formats.cpp +++ b/yt/cpp/mapreduce/client/structured_table_formats.cpp @@ -121,8 +121,7 @@ namespace NDetail { //////////////////////////////////////////////////////////////////////////////// NSkiff::TSkiffSchemaPtr TryCreateSkiffSchema( - const TClientContext& context, - const IClientRetryPolicyPtr& clientRetryPolicy, + const IRawClientPtr& rawClient, const TTransactionId& transactionId, const TVector& tables, const TOperationOptions& options, @@ -135,8 +134,7 @@ NSkiff::TSkiffSchemaPtr TryCreateSkiffSchema( return nullptr; } return CreateSkiffSchemaIfNecessary( - context, - clientRetryPolicy, + rawClient, transactionId, nodeReaderFormat, tables, @@ -212,14 +210,14 @@ TStructuredJobTableList ToStructuredJobTableList(const TVector& tableList) +TStructuredJobTableList CanonizeStructuredTableList(const IRawClientPtr& rawClient, const TVector& tableList) { TVector toCanonize; toCanonize.reserve(tableList.size()); for (const auto& table : tableList) { toCanonize.emplace_back(table.RichYPath); } - const auto canonized = NRawClient::CanonizeYPaths(/* retryPolicy */ nullptr, context, toCanonize); + const auto canonized = NRawClient::CanonizeYPaths(rawClient, toCanonize); Y_ABORT_UNLESS(canonized.size() == tableList.size()); TStructuredJobTableList result; @@ -434,8 +432,7 @@ std::pair> TFormatBuilder::CreateNodeFormat( tableList.emplace_back(*table.RichYPath); } skiffSchema = TryCreateSkiffSchema( - Context_, - ClientRetryPolicy_, + RawClient_, TransactionId_, tableList, OperationOptions_, diff --git a/yt/cpp/mapreduce/client/structured_table_formats.h b/yt/cpp/mapreduce/client/structured_table_formats.h index 162630d41103..64a44c6f4d72 100644 --- a/yt/cpp/mapreduce/client/structured_table_formats.h +++ b/yt/cpp/mapreduce/client/structured_table_formats.h @@ -69,7 +69,7 @@ using TStructuredJobTableList = TVector; TString JobTablePathString(const TStructuredJobTable& jobTable); TStructuredJobTableList ToStructuredJobTableList(const TVector& tableList); -TStructuredJobTableList CanonizeStructuredTableList(const TClientContext& context, const TVector& tableList); +TStructuredJobTableList CanonizeStructuredTableList(const IRawClientPtr& rawClient, const TVector& tableList); TVector GetPathList( const TStructuredJobTableList& tableList, const TMaybe>& schemaInferenceResult, diff --git a/yt/cpp/mapreduce/client/yt_poller.cpp b/yt/cpp/mapreduce/client/yt_poller.cpp index 13670fddb550..4980d287fafb 100644 --- a/yt/cpp/mapreduce/client/yt_poller.cpp +++ b/yt/cpp/mapreduce/client/yt_poller.cpp @@ -92,14 +92,14 @@ void TYtPoller::WatchLoop() Y_ABORT_UNLESS(!InProgress_.empty()); } - THttpRawBatchRequest rawBatchRequest(Context_.Config); + THttpRawBatchRequest rawBatchRequest(Context_, ClientRetryPolicy_->CreatePolicyForGenericRequest()); for (auto& item : InProgress_) { item->PrepareRequest(&rawBatchRequest); } try { - rawBatchRequest.ExecuteBatch(ClientRetryPolicy_->CreatePolicyForGenericRequest(), Context_); + rawBatchRequest.ExecuteBatch(); } catch (const std::exception& ex) { YT_LOG_ERROR("Exception while executing batch request: %v", ex.what()); } diff --git a/yt/cpp/mapreduce/client/yt_poller.h b/yt/cpp/mapreduce/client/yt_poller.h index fe9979a6a91f..c2e680932455 100644 --- a/yt/cpp/mapreduce/client/yt_poller.h +++ b/yt/cpp/mapreduce/client/yt_poller.h @@ -15,10 +15,6 @@ namespace NYT { namespace NDetail { -namespace NRawClient { - class THttpRawBatchRequest; -} - //////////////////////////////////////////////////////////////////////////////// class IYtPollerItem @@ -33,7 +29,7 @@ class IYtPollerItem public: virtual ~IYtPollerItem() = default; - virtual void PrepareRequest(NRawClient::THttpRawBatchRequest* batchRequest) = 0; + virtual void PrepareRequest(IRawBatchRequest* batchRequest) = 0; // Should return PollContinue if poller should continue polling this item. // Should return PollBreak if poller should stop polling this item. diff --git a/yt/cpp/mapreduce/interface/fwd.h b/yt/cpp/mapreduce/interface/fwd.h index 162a6ee3e9e7..9dcdf3789a91 100644 --- a/yt/cpp/mapreduce/interface/fwd.h +++ b/yt/cpp/mapreduce/interface/fwd.h @@ -398,6 +398,13 @@ namespace NYT { class IRetryConfigProvider; using IRetryConfigProviderPtr = ::TIntrusivePtr; + //////////////////////////////////////////////////////////////////////////////// + // raw_batch_request.h + //////////////////////////////////////////////////////////////////////////////// + + class IRawBatchRequest; + using IRawBatchRequestPtr = ::TIntrusivePtr; + //////////////////////////////////////////////////////////////////////////////// // raw_client.h //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/cpp/mapreduce/interface/raw_batch_request.h b/yt/cpp/mapreduce/interface/raw_batch_request.h new file mode 100644 index 000000000000..ec7b2b542c81 --- /dev/null +++ b/yt/cpp/mapreduce/interface/raw_batch_request.h @@ -0,0 +1,134 @@ +#pragma once + +#include "client_method_options.h" +#include "fwd.h" +#include "operation.h" + +#include + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +class IRawBatchRequest + : public virtual TThrRefBase +{ +public: + virtual void ExecuteBatch(const TExecuteBatchOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Create( + const TTransactionId& transaction, + const TYPath& path, + ENodeType type, + const TCreateOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Remove( + const TTransactionId& transaction, + const TYPath& path, + const TRemoveOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Exists( + const TTransactionId& transaction, + const TYPath& path, + const TExistsOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Get( + const TTransactionId& transaction, + const TYPath& path, + const TGetOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Set( + const TTransactionId& transaction, + const TYPath& path, + const TNode& value, + const TSetOptions& options = {}) = 0; + + virtual ::NThreading::TFuture List( + const TTransactionId& transaction, + const TYPath& path, + const TListOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Copy( + const TTransactionId& transaction, + const TYPath& sourcePath, + const TYPath& destinationPath, + const TCopyOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Move( + const TTransactionId& transaction, + const TYPath& sourcePath, + const TYPath& destinationPath, + const TMoveOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Link( + const TTransactionId& transaction, + const TYPath& targetPath, + const TYPath& linkPath, + const TLinkOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Lock( + const TTransactionId& transaction, + const TYPath& path, + ELockMode mode, + const TLockOptions& options = {}) = 0; + + virtual ::NThreading::TFuture Unlock( + const TTransactionId& transaction, + const TYPath& path, + const TUnlockOptions& options = {}) = 0; + + virtual ::NThreading::TFuture> GetFileFromCache( + const TTransactionId& transactionId, + const TString& md5Signature, + const TYPath& cachePath, + const TGetFileFromCacheOptions& options = {}) = 0; + + virtual ::NThreading::TFuture PutFileToCache( + const TTransactionId& transactionId, + const TYPath& filePath, + const TString& md5Signature, + const TYPath& cachePath, + const TPutFileToCacheOptions& options = {}) = 0; + + virtual ::NThreading::TFuture CheckPermission( + const TString& user, + EPermission permission, + const TYPath& path, + const TCheckPermissionOptions& options = {}) = 0; + + virtual ::NThreading::TFuture GetOperation( + const TOperationId& operationId, + const TGetOperationOptions& options = {}) = 0; + + virtual ::NThreading::TFuture AbortOperation(const TOperationId& operationId) = 0; + + virtual ::NThreading::TFuture CompleteOperation(const TOperationId& operationId) = 0; + + virtual ::NThreading::TFuture SuspendOperation( + const TOperationId& operationId, + const TSuspendOperationOptions& options = {}) = 0; + + virtual ::NThreading::TFuture ResumeOperation( + const TOperationId& operationId, + const TResumeOperationOptions& options = {}) = 0; + + virtual ::NThreading::TFuture UpdateOperationParameters( + const TOperationId& operationId, + const TUpdateOperationParametersOptions& options = {}) = 0; + + virtual ::NThreading::TFuture CanonizeYPath(const TRichYPath& path) = 0; + + virtual ::NThreading::TFuture> GetTableColumnarStatistics( + const TTransactionId& transaction, + const TVector& paths, + const TGetTableColumnarStatisticsOptions& options = {}) = 0; + + virtual ::NThreading::TFuture GetTablePartitions( + const TTransactionId& transaction, + const TVector& paths, + const TGetTablePartitionsOptions& options = {}) = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT diff --git a/yt/cpp/mapreduce/interface/raw_client.h b/yt/cpp/mapreduce/interface/raw_client.h index 1c140d1dd98e..441e738287de 100644 --- a/yt/cpp/mapreduce/interface/raw_client.h +++ b/yt/cpp/mapreduce/interface/raw_client.h @@ -327,6 +327,10 @@ class IRawClient const TGetTablePartitionsOptions& options = {}) = 0; virtual ui64 GenerateTimestamp() = 0; + + // Batch + + virtual IRawBatchRequestPtr CreateRawBatchRequest() = 0; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/cpp/mapreduce/raw_client/raw_batch_request.cpp b/yt/cpp/mapreduce/raw_client/raw_batch_request.cpp index 1a340b8c1700..08fee25b799f 100644 --- a/yt/cpp/mapreduce/raw_client/raw_batch_request.cpp +++ b/yt/cpp/mapreduce/raw_client/raw_batch_request.cpp @@ -285,16 +285,14 @@ THttpRawBatchRequest::TBatchItem::TBatchItem(const TBatchItem& batchItem, TInsta //////////////////////////////////////////////////////////////////////////////// -THttpRawBatchRequest::THttpRawBatchRequest(const TConfigPtr& config) - : Config_(config) +THttpRawBatchRequest::THttpRawBatchRequest(const TClientContext& context, IRequestRetryPolicyPtr retryPolicy) + : Context_(context) + , RequestRetryPolicy_(std::move(retryPolicy)) { } THttpRawBatchRequest::~THttpRawBatchRequest() = default; -void THttpRawBatchRequest::ExecuteBatch( - IRequestRetryPolicyPtr retryPolicy, - const TClientContext& context, - const TExecuteBatchOptions& options) +void THttpRawBatchRequest::ExecuteBatch(const TExecuteBatchOptions& options) { if (IsExecuted()) { ythrow yexception() << "Cannot execute batch request since it is already executed"; @@ -306,8 +304,8 @@ void THttpRawBatchRequest::ExecuteBatch( const auto concurrency = options.Concurrency_.GetOrElse(50); const auto batchPartMaxSize = options.BatchPartMaxSize_.GetOrElse(concurrency * 5); - if (!retryPolicy) { - retryPolicy = CreateDefaultRequestRetryPolicy(context.Config); + if (!RequestRetryPolicy_) { + RequestRetryPolicy_ = CreateDefaultRequestRetryPolicy(Context_.Config); } while (BatchSize()) { @@ -324,9 +322,9 @@ void THttpRawBatchRequest::ExecuteBatch( TResponseInfo result; try { result = RequestWithRetry( - retryPolicy, - [&context, &header, &body] (TMutationId& mutationId) { - auto response = RequestWithoutRetry(context, mutationId, header, body); + RequestRetryPolicy_, + [this, &header, &body] (TMutationId& mutationId) { + auto response = RequestWithoutRetry(Context_, mutationId, header, body); return TResponseInfo{ .RequestId = response->GetRequestId(), .Response = response->GetResponse(), @@ -337,7 +335,7 @@ void THttpRawBatchRequest::ExecuteBatch( SetErrorResult(std::current_exception()); throw; } - ParseResponse(std::move(result), retryPolicy.Get()); + ParseResponse(std::move(result), RequestRetryPolicy_.Get()); } } @@ -392,7 +390,7 @@ TFuture THttpRawBatchRequest::Create( { return AddRequest( "create", - SerializeParamsForCreate(transaction, Config_->Prefix, path, type, options), + SerializeParamsForCreate(transaction, Context_.Config->Prefix, path, type, options), Nothing()); } @@ -403,7 +401,7 @@ TFuture THttpRawBatchRequest::Remove( { return AddRequest( "remove", - SerializeParamsForRemove(transaction, Config_->Prefix, path, options), + SerializeParamsForRemove(transaction, Context_.Config->Prefix, path, options), Nothing()); } @@ -414,7 +412,7 @@ TFuture THttpRawBatchRequest::Exists( { return AddRequest( "exists", - SerializeParamsForExists(transaction, Config_->Prefix, path, options), + SerializeParamsForExists(transaction, Context_.Config->Prefix, path, options), Nothing()); } @@ -425,7 +423,7 @@ TFuture THttpRawBatchRequest::Get( { return AddRequest( "get", - SerializeParamsForGet(transaction, Config_->Prefix, path, options), + SerializeParamsForGet(transaction, Context_.Config->Prefix, path, options), Nothing()); } @@ -437,7 +435,7 @@ TFuture THttpRawBatchRequest::Set( { return AddRequest( "set", - SerializeParamsForSet(transaction, Config_->Prefix, path, options), + SerializeParamsForSet(transaction, Context_.Config->Prefix, path, options), node); } @@ -448,7 +446,7 @@ TFuture THttpRawBatchRequest::List( { return AddRequest( "list", - SerializeParamsForList(transaction, Config_->Prefix, path, options), + SerializeParamsForList(transaction, Context_.Config->Prefix, path, options), Nothing()); } @@ -460,7 +458,7 @@ TFuture THttpRawBatchRequest::Copy( { return AddRequest( "copy", - SerializeParamsForCopy(transaction, Config_->Prefix, sourcePath, destinationPath, options), + SerializeParamsForCopy(transaction, Context_.Config->Prefix, sourcePath, destinationPath, options), Nothing()); } @@ -472,7 +470,7 @@ TFuture THttpRawBatchRequest::Move( { return AddRequest( "move", - SerializeParamsForMove(transaction, Config_->Prefix, sourcePath, destinationPath, options), + SerializeParamsForMove(transaction, Context_.Config->Prefix, sourcePath, destinationPath, options), Nothing()); } @@ -484,7 +482,7 @@ TFuture THttpRawBatchRequest::Link( { return AddRequest( "link", - SerializeParamsForLink(transaction, Config_->Prefix, targetPath, linkPath, options), + SerializeParamsForLink(transaction, Context_.Config->Prefix, targetPath, linkPath, options), Nothing()); } @@ -496,7 +494,7 @@ TFuture THttpRawBatchRequest::Lock( { return AddRequest( "lock", - SerializeParamsForLock(transaction, Config_->Prefix, path, mode, options), + SerializeParamsForLock(transaction, Context_.Config->Prefix, path, mode, options), Nothing()); } @@ -507,7 +505,7 @@ TFuture THttpRawBatchRequest::Unlock( { return AddRequest( "unlock", - SerializeParamsForUnlock(transaction, Config_->Prefix, path, options), + SerializeParamsForUnlock(transaction, Context_.Config->Prefix, path, options), Nothing()); } @@ -532,7 +530,7 @@ TFuture THttpRawBatchRequest::PutFileToCache( { return AddRequest( "put_file_to_cache", - SerializeParamsForPutFileToCache(transactionId, Config_->Prefix, filePath, md5Signature, cachePath, options), + SerializeParamsForPutFileToCache(transactionId, Context_.Config->Prefix, filePath, md5Signature, cachePath, options), Nothing()); } @@ -544,7 +542,7 @@ TFuture THttpRawBatchRequest::CheckPermission( { return AddRequest( "check_permission", - SerializeParamsForCheckPermission(user, permission, Config_->Prefix, path, options), + SerializeParamsForCheckPermission(user, permission, Context_.Config->Prefix, path, options), Nothing()); } @@ -607,7 +605,7 @@ TFuture THttpRawBatchRequest::CanonizeYPath(const TRichYPath& path) TRichYPath result = path; // Out of the symbols in the canonization branch below, only '<' can appear in the beggining of a valid rich YPath. if (!result.Path_.StartsWith("<")) { - result.Path_ = AddPathPrefix(result.Path_, Config_->Prefix); + result.Path_ = AddPathPrefix(result.Path_, Context_.Config->Prefix); } if (result.Path_.find_first_of("<>{}[]") != TString::npos) { @@ -615,7 +613,7 @@ TFuture THttpRawBatchRequest::CanonizeYPath(const TRichYPath& path) "parse_ypath", SerializeParamsForParseYPath(result), Nothing(), - MakeIntrusive(Config_->Prefix, result)); + MakeIntrusive(Context_.Config->Prefix, result)); } return NThreading::MakeFuture(result); } diff --git a/yt/cpp/mapreduce/raw_client/raw_batch_request.h b/yt/cpp/mapreduce/raw_client/raw_batch_request.h index 670b97a84378..2af0e31305f2 100644 --- a/yt/cpp/mapreduce/raw_client/raw_batch_request.h +++ b/yt/cpp/mapreduce/raw_client/raw_batch_request.h @@ -2,13 +2,14 @@ #include -#include +#include +#include + #include #include +#include #include -#include - #include #include @@ -25,7 +26,7 @@ namespace NYT::NDetail::NRawClient { //////////////////////////////////////////////////////////////////////////////// class THttpRawBatchRequest - : public TThrRefBase + : public IRawBatchRequest { public: struct IResponseItemParser @@ -38,13 +39,10 @@ class THttpRawBatchRequest }; public: - THttpRawBatchRequest(const TConfigPtr& config); + THttpRawBatchRequest(const TClientContext& context, IRequestRetryPolicyPtr retryPolicy); ~THttpRawBatchRequest(); - void ExecuteBatch( - IRequestRetryPolicyPtr retryPolicy, - const TClientContext& context, - const TExecuteBatchOptions& options = {}); + void ExecuteBatch(const TExecuteBatchOptions& options = {}) override; bool IsExecuted() const; void MarkExecuted(); @@ -68,91 +66,113 @@ class THttpRawBatchRequest const TTransactionId& transaction, const TYPath& path, ENodeType type, - const TCreateOptions& options); + const TCreateOptions& options = {}) override; + ::NThreading::TFuture Remove( const TTransactionId& transaction, const TYPath& path, - const TRemoveOptions& options); + const TRemoveOptions& options = {}) override; + ::NThreading::TFuture Exists( const TTransactionId& transaction, const TYPath& path, - const TExistsOptions& options); + const TExistsOptions& options = {}) override; + ::NThreading::TFuture Get( const TTransactionId& transaction, const TYPath& path, - const TGetOptions& options); + const TGetOptions& options = {}) override; + ::NThreading::TFuture Set( const TTransactionId& transaction, const TYPath& path, const TNode& value, - const TSetOptions& options); + const TSetOptions& options = {}) override; + ::NThreading::TFuture List( const TTransactionId& transaction, const TYPath& path, - const TListOptions& options); + const TListOptions& options = {}) override; + ::NThreading::TFuture Copy( const TTransactionId& transaction, const TYPath& sourcePath, const TYPath& destinationPath, - const TCopyOptions& options); + const TCopyOptions& options = {}) override; + ::NThreading::TFuture Move( const TTransactionId& transaction, const TYPath& sourcePath, const TYPath& destinationPath, - const TMoveOptions& options); + const TMoveOptions& options = {}) override; + ::NThreading::TFuture Link( const TTransactionId& transaction, const TYPath& targetPath, const TYPath& linkPath, - const TLinkOptions& options); + const TLinkOptions& options = {}) override; + ::NThreading::TFuture Lock( const TTransactionId& transaction, const TYPath& path, ELockMode mode, - const TLockOptions& options); + const TLockOptions& options = {}) override; + ::NThreading::TFuture Unlock( const TTransactionId& transaction, const TYPath& path, - const TUnlockOptions& options); + const TUnlockOptions& options = {}) override; + ::NThreading::TFuture> GetFileFromCache( const TTransactionId& transactionId, const TString& md5Signature, const TYPath& cachePath, - const TGetFileFromCacheOptions& options); + const TGetFileFromCacheOptions& options = {}) override; + ::NThreading::TFuture PutFileToCache( const TTransactionId& transactionId, const TYPath& filePath, const TString& md5Signature, const TYPath& cachePath, - const TPutFileToCacheOptions& options); + const TPutFileToCacheOptions& options = {}) override; + ::NThreading::TFuture CheckPermission( const TString& user, EPermission permission, const TYPath& path, - const TCheckPermissionOptions& options); + const TCheckPermissionOptions& options = {}) override; + ::NThreading::TFuture GetOperation( const TOperationId& operationId, - const TGetOperationOptions& options); - ::NThreading::TFuture AbortOperation(const TOperationId& operationId); - ::NThreading::TFuture CompleteOperation(const TOperationId& operationId); + const TGetOperationOptions& options = {}) override; + + ::NThreading::TFuture AbortOperation(const TOperationId& operationId) override; + + ::NThreading::TFuture CompleteOperation(const TOperationId& operationId) override; + ::NThreading::TFuture SuspendOperation( const TOperationId& operationId, - const TSuspendOperationOptions& options); + const TSuspendOperationOptions& options = {}) override; + ::NThreading::TFuture ResumeOperation( const TOperationId& operationId, - const TResumeOperationOptions& options); + const TResumeOperationOptions& options = {}) override; + ::NThreading::TFuture UpdateOperationParameters( const TOperationId& operationId, - const TUpdateOperationParametersOptions& options); - ::NThreading::TFuture CanonizeYPath(const TRichYPath& path); + const TUpdateOperationParametersOptions& options = {}) override; + + ::NThreading::TFuture CanonizeYPath(const TRichYPath& path) override; + ::NThreading::TFuture> GetTableColumnarStatistics( const TTransactionId& transaction, const TVector& paths, - const TGetTableColumnarStatisticsOptions& options); + const TGetTableColumnarStatisticsOptions& options = {}) override; + ::NThreading::TFuture GetTablePartitions( const TTransactionId& transaction, const TVector& paths, - const TGetTablePartitionsOptions& options); + const TGetTablePartitionsOptions& options = {}) override; private: struct TBatchItem { @@ -182,7 +202,9 @@ class THttpRawBatchRequest void AddRequest(TBatchItem batchItem); private: - TConfigPtr Config_; + const TClientContext Context_; + + IRequestRetryPolicyPtr RequestRetryPolicy_; TDeque BatchItemList_; bool Executed_ = false; diff --git a/yt/cpp/mapreduce/raw_client/raw_client.cpp b/yt/cpp/mapreduce/raw_client/raw_client.cpp index 53d2be114aff..f25fe5a4ee7a 100644 --- a/yt/cpp/mapreduce/raw_client/raw_client.cpp +++ b/yt/cpp/mapreduce/raw_client/raw_client.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -925,6 +926,11 @@ ui64 THttpRawClient::GenerateTimestamp() return NodeFromYsonString(responseInfo->GetResponse()).AsUint64(); } +IRawBatchRequestPtr THttpRawClient::CreateRawBatchRequest() +{ + return MakeIntrusive(Context_, /*retryPolicy*/ nullptr); +} + //////////////////////////////////////////////////////////////////////////////// } // namespace NYT::NDetail diff --git a/yt/cpp/mapreduce/raw_client/raw_client.h b/yt/cpp/mapreduce/raw_client/raw_client.h index e18e32a92ef8..f0e8378db357 100644 --- a/yt/cpp/mapreduce/raw_client/raw_client.h +++ b/yt/cpp/mapreduce/raw_client/raw_client.h @@ -335,6 +335,8 @@ class THttpRawClient ui64 GenerateTimestamp() override; + IRawBatchRequestPtr CreateRawBatchRequest() override; + private: const TClientContext Context_; }; diff --git a/yt/cpp/mapreduce/raw_client/raw_requests.cpp b/yt/cpp/mapreduce/raw_client/raw_requests.cpp index fd5c59ec20c7..30b1619b710d 100644 --- a/yt/cpp/mapreduce/raw_client/raw_requests.cpp +++ b/yt/cpp/mapreduce/raw_client/raw_requests.cpp @@ -253,25 +253,26 @@ TCheckPermissionResponse ParseCheckPermissionResponse(const TNode& node) } TRichYPath CanonizeYPath( - const IRequestRetryPolicyPtr& retryPolicy, - const TClientContext& context, + const IRawClientPtr& rawClient, const TRichYPath& path) { - return CanonizeYPaths(retryPolicy, context, {path}).front(); + return CanonizeYPaths(rawClient, {path}).front(); } TVector CanonizeYPaths( - const IRequestRetryPolicyPtr& retryPolicy, - const TClientContext& context, + const IRawClientPtr& rawClient, const TVector& paths) { - THttpRawBatchRequest batch(context.Config); + auto batch = rawClient->CreateRawBatchRequest(); + TVector> futures; futures.reserve(paths.size()); - for (int i = 0; i < static_cast(paths.size()); ++i) { - futures.push_back(batch.CanonizeYPath(paths[i])); + for (const auto& path : paths) { + futures.push_back(batch->CanonizeYPath(path)); } - batch.ExecuteBatch(retryPolicy, context); + + batch->ExecuteBatch(); + TVector result; result.reserve(futures.size()); for (auto& future : futures) { diff --git a/yt/cpp/mapreduce/raw_client/raw_requests.h b/yt/cpp/mapreduce/raw_client/raw_requests.h index 860d4ae939c2..148762417141 100644 --- a/yt/cpp/mapreduce/raw_client/raw_requests.h +++ b/yt/cpp/mapreduce/raw_client/raw_requests.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace NYT { @@ -33,13 +34,11 @@ TCheckPermissionResponse ParseCheckPermissionResponse(const TNode& node); //////////////////////////////////////////////////////////////////////////////// TRichYPath CanonizeYPath( - const IRequestRetryPolicyPtr& retryPolicy, - const TClientContext& context, + const IRawClientPtr& rawClient, const TRichYPath& path); TVector CanonizeYPaths( - const IRequestRetryPolicyPtr& retryPolicy, - const TClientContext& context, + const IRawClientPtr& rawClient, const TVector& paths); NHttpClient::IHttpResponsePtr SkyShareTable( @@ -53,19 +52,18 @@ TAuthorizationInfo WhoAmI(const TClientContext& context); template auto BatchTransform( - const IRequestRetryPolicyPtr& retryPolicy, - const TClientContext& context, + const IRawClientPtr& rawClient, const TSrc& src, TBatchAdder batchAdder, const TExecuteBatchOptions& executeBatchOptions = {}) { - THttpRawBatchRequest batch(context.Config); + auto batch = rawClient->CreateRawBatchRequest(); using TFuture = decltype(batchAdder(batch, *std::begin(src))); TVector futures; for (const auto& el : src) { futures.push_back(batchAdder(batch, el)); } - batch.ExecuteBatch(retryPolicy, context, executeBatchOptions); + batch->ExecuteBatch(executeBatchOptions); using TDst = decltype(futures[0].ExtractValueSync()); TVector result; result.reserve(std::size(src)); diff --git a/yt/cpp/mapreduce/raw_client/ut/raw_batch_request_ut.cpp b/yt/cpp/mapreduce/raw_client/ut/raw_batch_request_ut.cpp index 36a6935e8201..1871ee80fb47 100644 --- a/yt/cpp/mapreduce/raw_client/ut/raw_batch_request_ut.cpp +++ b/yt/cpp/mapreduce/raw_client/ut/raw_batch_request_ut.cpp @@ -73,7 +73,7 @@ TVector GetAllPathsFromRequestList(const TNode& requestList) TEST(TBatchRequestImplTest, ParseResponse) { TClientContext context; - THttpRawBatchRequest batchRequest(context.Config); + THttpRawBatchRequest batchRequest(context, /*retryPolicy*/ nullptr); EXPECT_EQ(batchRequest.BatchSize(), 0u); diff --git a/yt/yql/providers/yt/codec/codegen/yt_codec_cg.cpp b/yt/yql/providers/yt/codec/codegen/yt_codec_cg.cpp index cdf9588f9488..c81dab97cf76 100644 --- a/yt/yql/providers/yt/codec/codegen/yt_codec_cg.cpp +++ b/yt/yql/providers/yt/codec/codegen/yt_codec_cg.cpp @@ -85,7 +85,7 @@ class TYtCodecCgWriter : public IYtCodecCgWriter { auto& module = Codegen_->GetModule(); auto& context = Codegen_->GetContext(); // input - pointer to struct UnboxedValue as int128 and instance of buffer, output - void - const auto funcType = Flat || Codegen_->GetEffectiveTarget() == NYql::NCodegen::ETarget::Windows ? + const auto funcType = Flat ? FunctionType::get(Type::getVoidTy(context), {PointerType::getUnqual(Type::getInt128Ty(context)), PointerType::getUnqual(Type::getInt8Ty(context))}, false): FunctionType::get(Type::getVoidTy(context), {Type::getInt128Ty(context), PointerType::getUnqual(Type::getInt8Ty(context))}, false); Func_ = cast(module.getOrInsertFunction((TStringBuilder() << (Flat ? "YtCodecCgWriterFlat." : "YtCodecCgWriter.") << cookie).data(), funcType).getCallee()); @@ -768,7 +768,7 @@ class TYtCodecCgReader : public IYtCodecCgReader { case NUdf::TDataType::Id: { CallInst::Create(module.getFunction("ReadTzTimestamp64"), { buf, velemPtr }, "", Block_); break; - } + } default: YQL_ENSURE(false, "Unknown data type: " << schemeType); diff --git a/yt/yql/providers/yt/codec/yt_codec_io.cpp b/yt/yql/providers/yt/codec/yt_codec_io.cpp index 0530bba5f725..aa47453ea26e 100644 --- a/yt/yql/providers/yt/codec/yt_codec_io.cpp +++ b/yt/yql/providers/yt/codec/yt_codec_io.cpp @@ -1655,7 +1655,7 @@ void TMkqlReaderImpl::SetSpecs(const TMkqlIOSpecs& specs, const NKikimr::NMiniKQ if (Specs_->UseBlockInput_) { Decoder_.Reset(new TArrowDecoder(Buf_, *Specs_, holderFactory, NUdf::GetYqlMemoryPool())); } else if (Specs_->UseSkiff_) { -#ifndef MKQL_DISABLE_CODEGEN +#if !defined(MKQL_DISABLE_CODEGEN) && !defined(__aarch64__) && !defined(_win_) if (Specs_->OptLLVM_ != "OFF" && NCodegen::ICodegen::IsCodegenAvailable()) { Decoder_.Reset(new TSkiffLLVMDecoder(Buf_, *Specs_, holderFactory)); } diff --git a/yt/yql/providers/yt/comp_nodes/yql_mkql_output.cpp b/yt/yql/providers/yt/comp_nodes/yql_mkql_output.cpp index a093b6f89be1..1448c77e3745 100644 --- a/yt/yql/providers/yt/comp_nodes/yql_mkql_output.cpp +++ b/yt/yql/providers/yt/comp_nodes/yql_mkql_output.cpp @@ -27,7 +27,7 @@ class TYtOutputWrapper : public TDecoratorCodegeneratorNode { if (true /*|| TODO: !Writer.GenAddRow(item, ctx, block)*/) { const auto addFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TYtOutputWrapper::AddRowImpl)); const auto selfArg = ConstantInt::get(Type::getInt64Ty(context), ui64(this)); - const auto arg = WrapArgumentForWindows(item, ctx, block); + const auto arg = item; const auto addType = FunctionType::get(Type::getVoidTy(context), {selfArg->getType(), arg->getType()}, false); const auto addPtr = CastInst::Create(Instruction::IntToPtr, addFunc, PointerType::getUnqual(addType), "write", block); CallInst::Create(addType, addPtr, {selfArg, arg}, "", block); @@ -77,7 +77,7 @@ using TBaseComputation = TStatelessFlowCodegeneratorNode; const auto addFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TYtFlowOutputWrapper::AddRowImpl)); const auto selfArg = ConstantInt::get(Type::getInt64Ty(context), ui64(this)); - const auto arg = WrapArgumentForWindows(item, ctx, block); + const auto arg = item; const auto addType = FunctionType::get(Type::getVoidTy(context), {selfArg->getType(), arg->getType()}, false); const auto addPtr = CastInst::Create(Instruction::IntToPtr, addFunc, PointerType::getUnqual(addType), "write", block); CallInst::Create(addType, addPtr, {selfArg, arg}, "", block); diff --git a/yt/yql/providers/yt/gateway/file/yql_yt_file_mkql_compiler.cpp b/yt/yql/providers/yt/gateway/file/yql_yt_file_mkql_compiler.cpp index 7c76f31ad2a6..db7fdd7430da 100644 --- a/yt/yql/providers/yt/gateway/file/yql_yt_file_mkql_compiler.cpp +++ b/yt/yql/providers/yt/gateway/file/yql_yt_file_mkql_compiler.cpp @@ -832,54 +832,53 @@ void RegisterYtFileMkqlCompilers(NCommon::TMkqlCallableCompilerBase& compiler) { TRuntimeNode mapDirectOutputs; if (hasMap) { const auto& mapper = ytMapReduce.Mapper().Cast(); - if (const auto arg = mapper.Args().Arg(0).Raw(); arg != mapper.Body().Raw()) { - values = arg->GetTypeAnn()->GetKind() == ETypeAnnotationKind::Flow ? - ctx.ProgramBuilder.ToFlow(values) : ctx.ProgramBuilder.Iterator(values, {}); + const auto arg = mapper.Args().Arg(0).Raw(); + values = arg->GetTypeAnn()->GetKind() == ETypeAnnotationKind::Flow ? + ctx.ProgramBuilder.ToFlow(values) : ctx.ProgramBuilder.Iterator(values, {}); - if (ETypeAnnotationKind::Multi == GetSeqItemType(*ytMapReduce.Mapper().Cast().Args().Arg(0).Ref().GetTypeAnn()).GetKind()) - values = ExpandFlow(values, ctx); + if (ETypeAnnotationKind::Multi == GetSeqItemType(*ytMapReduce.Mapper().Cast().Args().Arg(0).Ref().GetTypeAnn()).GetKind()) + values = ExpandFlow(values, ctx); - NCommon::TMkqlBuildContext innerCtx(ctx, {{arg, values}}, ytMapReduce.Mapper().Ref().UniqueId()); + NCommon::TMkqlBuildContext innerCtx(ctx, {{arg, values}}, ytMapReduce.Mapper().Ref().UniqueId()); - const auto& body = ytMapReduce.Mapper().Cast().Body().Ref(); - values = NCommon::MkqlBuildExpr(body, innerCtx); + const auto& body = ytMapReduce.Mapper().Cast().Body().Ref(); + values = NCommon::MkqlBuildExpr(body, innerCtx); - const auto& mapOutItemType = GetSeqItemType(*body.GetTypeAnn()); - if (const auto mapOutputTypeSetting = NYql::GetSetting(ytMapReduce.Settings().Ref(), EYtSettingType::MapOutputType)) { - if (ETypeAnnotationKind::Multi == mapOutItemType.GetKind()) { - values = NarrowFlow(values, *AS_TYPE(TStructType, NCommon::BuildType(body, *mapOutputTypeSetting->Tail().GetTypeAnn()->Cast()->GetType(), ctx.ProgramBuilder)), ctx); - } + const auto& mapOutItemType = GetSeqItemType(*body.GetTypeAnn()); + if (const auto mapOutputTypeSetting = NYql::GetSetting(ytMapReduce.Settings().Ref(), EYtSettingType::MapOutputType)) { + if (ETypeAnnotationKind::Multi == mapOutItemType.GetKind()) { + values = NarrowFlow(values, *AS_TYPE(TStructType, NCommon::BuildType(body, *mapOutputTypeSetting->Tail().GetTypeAnn()->Cast()->GetType(), ctx.ProgramBuilder)), ctx); } + } - values = ToList(values, ctx); + values = ToList(values, ctx); - if (mapOutItemType.GetKind() == ETypeAnnotationKind::Variant) { - auto tupleType = mapOutItemType.Cast()->GetUnderlyingType()->Cast(); - YQL_ENSURE(tupleType->GetSize() > 0); - mapDirectOutputsCount = tupleType->GetSize() - 1; - YQL_ENSURE(mapDirectOutputsCount < outputsCount); + if (mapOutItemType.GetKind() == ETypeAnnotationKind::Variant) { + auto tupleType = mapOutItemType.Cast()->GetUnderlyingType()->Cast(); + YQL_ENSURE(tupleType->GetSize() > 0); + mapDirectOutputsCount = tupleType->GetSize() - 1; + YQL_ENSURE(mapDirectOutputsCount < outputsCount); - values = ctx.ProgramBuilder.Collect(values); + values = ctx.ProgramBuilder.Collect(values); - mapDirectOutputs = ctx.ProgramBuilder.OrderedFlatMap(values, [&](TRuntimeNode mapOut) { - return ctx.ProgramBuilder.VisitAll(mapOut, [&](ui32 index, TRuntimeNode varitem) { - if (index == 0) { - return ctx.ProgramBuilder.NewEmptyOptional(ctx.ProgramBuilder.NewOptionalType(outputItemType)); - } - return ctx.ProgramBuilder.NewOptional(ctx.ProgramBuilder.NewVariant(varitem, index - 1, outputItemType)); - }); + mapDirectOutputs = ctx.ProgramBuilder.OrderedFlatMap(values, [&](TRuntimeNode mapOut) { + return ctx.ProgramBuilder.VisitAll(mapOut, [&](ui32 index, TRuntimeNode varitem) { + if (index == 0) { + return ctx.ProgramBuilder.NewEmptyOptional(ctx.ProgramBuilder.NewOptionalType(outputItemType)); + } + return ctx.ProgramBuilder.NewOptional(ctx.ProgramBuilder.NewVariant(varitem, index - 1, outputItemType)); }); + }); - auto toReduceType = NCommon::BuildType(body, *tupleType->GetItems().front(), ctx.ProgramBuilder); - values = ctx.ProgramBuilder.OrderedFlatMap(values, [&](TRuntimeNode mapOut) { - return ctx.ProgramBuilder.VisitAll(mapOut, [&](ui32 index, TRuntimeNode varitem) { - if (index == 0) { - return ctx.ProgramBuilder.NewOptional(varitem); - } - return ctx.ProgramBuilder.NewEmptyOptional(ctx.ProgramBuilder.NewOptionalType(toReduceType)); - }); + auto toReduceType = NCommon::BuildType(body, *tupleType->GetItems().front(), ctx.ProgramBuilder); + values = ctx.ProgramBuilder.OrderedFlatMap(values, [&](TRuntimeNode mapOut) { + return ctx.ProgramBuilder.VisitAll(mapOut, [&](ui32 index, TRuntimeNode varitem) { + if (index == 0) { + return ctx.ProgramBuilder.NewOptional(varitem); + } + return ctx.ProgramBuilder.NewEmptyOptional(ctx.ProgramBuilder.NewOptionalType(toReduceType)); }); - } + }); } } diff --git a/yt/yt/build/ya.make b/yt/yt/build/ya.make index 3c9ef07a0f4f..5bbd5e3e89a4 100644 --- a/yt/yt/build/ya.make +++ b/yt/yt/build/ya.make @@ -3,7 +3,7 @@ LIBRARY() INCLUDE(${ARCADIA_ROOT}/yt/ya_cpp.make.inc) SET(YT_VERSION_MAJOR 25) -SET(YT_VERSION_MINOR 1) +SET(YT_VERSION_MINOR 2) DEFAULT(YT_VERSION_PATCH 0) DEFAULT(YT_VERSION_BRANCH "local") diff --git a/yt/yt/core/actions/future-inl.h b/yt/yt/core/actions/future-inl.h index 1b5f67d05b1e..090ac8a72749 100644 --- a/yt/yt/core/actions/future-inl.h +++ b/yt/yt/core/actions/future-inl.h @@ -2461,7 +2461,7 @@ class TCancelableBoundedConcurrencyRunner , ConcurrencyLimit_(concurrencyLimit) , Futures_(Callbacks_.size(), VoidFuture) , Results_(Callbacks_.size()) - , CurrentIndex_(std::min(ConcurrencyLimit_, ssize(Callbacks_))) + , CurrentIndex_(std::min(ConcurrencyLimit_, std::ssize(Callbacks_))) , FailOnFirstError_(failOnError) { } @@ -2499,35 +2499,44 @@ class TCancelableBoundedConcurrencyRunner void RunCallback(int index) { - auto future = Callbacks_[index](); + // ORD-2002: Avoid calling OnResult directly to prevent unbounded + // recursive chains like RunCallback -> OnResult -> RunCallback... + while (true) { + auto future = Callbacks_[index](); + if (!future.IsSet()) { + { + auto guard = Guard(SpinLock_); + if (Error_) { + guard.Release(); + future.Cancel(*Error_); + return; + } - if (future.IsSet()) { - OnResult(index, std::move(future.Get())); - return; - } + Futures_[index] = future.template As(); + } - { - auto guard = Guard(SpinLock_); - if (Error_) { - guard.Release(); - future.Cancel(*Error_); - return; + future.Subscribe( + BIND_NO_PROPAGATE(&TCancelableBoundedConcurrencyRunner::OnResult, MakeStrong(this), index) + // NB: Sync invoker protects from unbounded recursion. + .Via(GetSyncInvoker())); + break; } - Futures_[index] = future.template As(); - } + auto suggestedIndex = HandleResultAndSuggestNextIndex(index, std::move(future.Get())); + if (!suggestedIndex) { + break; + } - future.Subscribe( - BIND_NO_PROPAGATE(&TCancelableBoundedConcurrencyRunner::OnResult, MakeStrong(this), index) - // NB: Sync invoker protects from unbounded recursion. - .Via(GetSyncInvoker())); + index = *suggestedIndex; + } } - void OnResult(int index, const NYT::TErrorOr& result) + [[nodiscard]] + std::optional HandleResultAndSuggestNextIndex(int index, const TErrorOr& result) { if (FailOnFirstError_ && !result.IsOK()) { OnError(result); - return; + return std::nullopt; } int newIndex; @@ -2535,7 +2544,7 @@ class TCancelableBoundedConcurrencyRunner { auto guard = Guard(SpinLock_); if (Error_) { - return; + return std::nullopt; } newIndex = CurrentIndex_++; @@ -2543,12 +2552,17 @@ class TCancelableBoundedConcurrencyRunner Results_[index] = result; } - if (finishedCount == ssize(Callbacks_)) { + if (finishedCount == std::ssize(Callbacks_)) { Promise_.TrySet(Results_); } - if (newIndex < ssize(Callbacks_)) { - RunCallback(newIndex); + return newIndex < std::ssize(Callbacks_) ? std::optional(newIndex) : std::nullopt; + } + + void OnResult(int index, const TErrorOr& result) + { + if (auto suggestedIndex = HandleResultAndSuggestNextIndex(index, result)) { + RunCallback(*suggestedIndex); } } @@ -2616,26 +2630,44 @@ class TBoundedConcurrencyRunner void RunCallback(int index) { - auto future = Callbacks_[index](); - if (future.IsSet()) { - OnResult(index, future.Get()); - } else { - future.Subscribe( - BIND_NO_PROPAGATE(&TBoundedConcurrencyRunner::OnResult, MakeStrong(this), index)); + // ORD-2002: Avoid calling OnResult directly to prevent unbounded + // recursive chains like RunCallback -> OnResult -> RunCallback... + while (true) { + auto future = Callbacks_[index](); + if (!future.IsSet()) { + future.Subscribe( + BIND_NO_PROPAGATE(&TBoundedConcurrencyRunner::OnResult, MakeStrong(this), index) + // NB: Sync invoker protects from unbounded recursion. + .Via(GetSyncInvoker())); + break; + } + + auto suggestedIndex = HandleResultAndSuggestNextIndex(index, future.Get()); + if (!suggestedIndex) { + break; + } + + index = *suggestedIndex; } } - void OnResult(int index, const NYT::TErrorOr& result) + [[nodiscard]] + std::optional HandleResultAndSuggestNextIndex(int index, const TErrorOr& result) { Results_[index] = result; int newIndex = CurrentIndex_++; - if (newIndex < static_cast(Callbacks_.size())) { - RunCallback(newIndex); + if (++FinishedCount_ == std::ssize(Callbacks_)) { + Promise_.Set(Results_); } - if (++FinishedCount_ == static_cast(Callbacks_.size())) { - Promise_.Set(Results_); + return newIndex < std::ssize(Callbacks_) ? std::optional(newIndex) : std::nullopt; + } + + void OnResult(int index, const TErrorOr& result) + { + if (auto suggestedIndex = HandleResultAndSuggestNextIndex(index, result)) { + RunCallback(*suggestedIndex); } } }; diff --git a/yt/yt/core/actions/unittests/actions_ut.cpp b/yt/yt/core/actions/unittests/actions_ut.cpp index bb9a415e970c..272bc2d1951c 100644 --- a/yt/yt/core/actions/unittests/actions_ut.cpp +++ b/yt/yt/core/actions/unittests/actions_ut.cpp @@ -94,6 +94,25 @@ TEST(TCancelableRunWithBoundedConcurrencyTest, Cancelation) EXPECT_EQ(canceledCount, 4); } +TEST(TCancelableRunWithBoundedConcurrencyTest, RecurseRunner) +{ + auto threadPool = CreateThreadPool(4, "ThreadPool"); + + std::vector()>> callbacks; + for (int i = 0; i < 50'000; ++i) { + callbacks.push_back(BIND([] { + return VoidFuture; + })); + } + + auto future = CancelableRunWithBoundedConcurrency( + std::move(callbacks), + /*concurrencyLimit*/ 5); + + WaitFor(future) + .ThrowOnError(); +} + TEST(TAllSucceededBoundedConcurrencyTest, CancelOthers) { using TCounter = std::atomic; diff --git a/yt/yt/core/concurrency/new_fair_share_thread_pool.cpp b/yt/yt/core/concurrency/new_fair_share_thread_pool.cpp deleted file mode 100644 index fec716623def..000000000000 --- a/yt/yt/core/concurrency/new_fair_share_thread_pool.cpp +++ /dev/null @@ -1,1425 +0,0 @@ -#include "two_level_fair_share_thread_pool.h" -#include "new_fair_share_thread_pool.h" -#include "private.h" -#include "notify_manager.h" -#include "profiling_helpers.h" -#include "scheduler_thread.h" -#include "thread_pool_detail.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include - -#include - -#include - -namespace NYT::NConcurrency { - -using namespace NProfiling; - -//////////////////////////////////////////////////////////////////////////////// - -namespace { - -YT_DEFINE_GLOBAL(const NLogging::TLogger, Logger, "FairShareThreadPool"); - -DECLARE_REFCOUNTED_CLASS(TBucketMapping) -DECLARE_REFCOUNTED_CLASS(TTwoLevelFairShareQueue) -DECLARE_REFCOUNTED_CLASS(TBucket) - -struct TExecutionPool; - -// High 16 bits is thread index and 48 bits for thread pool ptr. -YT_DEFINE_THREAD_LOCAL(TPackedPtr, ThreadCookie, 0); - -constexpr auto LogDurationThreshold = TDuration::Seconds(1); - -//////////////////////////////////////////////////////////////////////////////// - -template -class THeapItem -{ -public: - THeapItem(const THeapItem&) = delete; - THeapItem& operator=(const THeapItem&) = delete; - - explicit THeapItem(T* ptr) - : Ptr_(std::move(ptr)) - { - AdjustBackReference(); - } - - ~THeapItem() - { - if (Ptr_) { - YT_ASSERT(Ptr_->PositionInHeap_ == this); - Ptr_->PositionInHeap_ = nullptr; - } - } - - T& operator* () - { - return *Ptr_; - } - - const T& operator*() const - { - return *Ptr_; - } - - T* operator->() - { - return Ptr_; - } - - const T* operator->() const - { - return Ptr_; - } - - bool operator < (const THeapItem& other) const - { - return *Ptr_ < *other; - } - - THeapItem(THeapItem&& other) noexcept - : Ptr_(std::move(other.Ptr_)) - { - other.Ptr_ = nullptr; - AdjustBackReference(); - } - - THeapItem& operator=(THeapItem&& other) noexcept - { - Ptr_ = std::move(other.Ptr_); - other.Ptr_ = nullptr; - AdjustBackReference(); - - return *this; - } - -private: - T* Ptr_; - - void AdjustBackReference() - { - if (Ptr_) { - Ptr_->PositionInHeap_ = this; - } - } -}; - -template -class THeapItemBase -{ -public: - friend THeapItem; - - THeapItem* GetPositionInHeap() const - { - return PositionInHeap_; - } - - ~THeapItemBase() - { - YT_ASSERT(!PositionInHeap_); - } - -private: - THeapItem* PositionInHeap_ = nullptr; -}; - -template -class TPriorityQueue -{ -public: - void Insert(T* object) - { - Items_.emplace_back(object); - SiftUp(Items_.begin(), Items_.end(), Items_.end() - 1); - YT_ASSERT(object->GetPositionInHeap()); - } - - void Extract(const T* object) - { - auto* positionInHeap = object->GetPositionInHeap(); - YT_ASSERT(Items_.data() <= positionInHeap && positionInHeap < Items_.data() + Items_.size()); - - std::swap(*positionInHeap, Items_.back()); - SiftDown( - Items_.data(), - Items_.data() + std::ssize(Items_) - 1, - positionInHeap); - - YT_ASSERT(Items_.back()->GetPositionInHeap() == object->GetPositionInHeap()); - Items_.pop_back(); - } - - void AdjustDown(const T* object) - { - auto* positionInHeap = object->GetPositionInHeap(); - YT_ASSERT(Items_.data() <= positionInHeap && positionInHeap < Items_.data() + Items_.size()); - SiftDown( - Items_.data(), - Items_.data() + std::ssize(Items_), - positionInHeap); - } - - T* GetFront() - { - YT_ASSERT(!Empty()); - return &*Items_.front(); - } - - bool Empty() const - { - return Items_.empty(); - } - - size_t GetSize() const - { - return Items_.size(); - } - - T& operator[] (size_t index) - { - return *Items_[index]; - } - - template - void ForEach(F&& functor) - { - for (auto& item : Items_) { - functor(&*item); - } - } - - void Clear() - { - Items_.clear(); - } - -private: - std::vector> Items_; -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct TAction -{ - TCpuInstant EnqueuedAt = 0; - TCpuInstant StartedAt = 0; - - // Callback keeps raw ptr to bucket to minimize bucket ref count. - TClosure Callback; - TBucketPtr BucketHolder; - - TPackedPtr EnqueuedThreadCookie = 0; -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct TEnqueuedTime - : public THeapItemBase -{ - TCpuInstant Value = 0; -}; - -bool operator < (const TEnqueuedTime& lhs, const TEnqueuedTime& rhs) -{ - return lhs.Value < rhs.Value; -} - -//////////////////////////////////////////////////////////////////////////////// - -// Data for scheduling on the first level. -struct TExecutionPool final - : public THeapItemBase -{ - const TString PoolName; - - // Profiling sensors. - const NProfiling::TSummary BucketCounter; - const NProfiling::TSummary SizeCounter; - const NProfiling::TCounter DequeuedCounter; - const TEventTimer WaitTimeCounter; - const TEventTimer ExecTimeCounter; - const TEventTimer TotalTimeCounter; - const NProfiling::TTimeCounter CumulativeTimeCounter; - - // Action count is used to decide whether to reset excess time or not. - size_t ActionCountInQueue = 0; - - TCpuDuration NextUpdateWeightInstant = 0; - double InverseWeight = 1.0; - TCpuDuration ExcessTime = 0; - - TPriorityQueue ActiveBucketsHeap; - TCpuDuration LastBucketExcessTime = 0; - - TIntrusiveLinkedListNode LinkedListNode; - // Execution pool is retained for some after last usage to flush profiling counters. - TCpuInstant LastUsageTime = 0; - - TExecutionPool(TString poolName, const TProfiler& profiler) - : PoolName(std::move(poolName)) - , BucketCounter(profiler.Summary("/buckets")) - , SizeCounter(profiler.Summary("/size")) - , DequeuedCounter(profiler.Counter("/dequeued")) - , WaitTimeCounter(profiler.Timer("/time/wait")) - , ExecTimeCounter(profiler.Timer("/time/exec")) - , TotalTimeCounter(profiler.Timer("/time/total")) - , CumulativeTimeCounter(profiler.TimeCounter("/time/cumulative")) - { } -}; - -bool operator < (const TExecutionPool& lhs, const TExecutionPool& rhs) -{ - return lhs.ExcessTime < rhs.ExcessTime; -} - -using TExecutionPoolPtr = ::NYT::TIntrusivePtr; - -//////////////////////////////////////////////////////////////////////////////// - -// Data for scheduling on the second level. -struct TBucketBase -{ - const TString BucketName; - const TString PoolName; - - TRingQueue ActionQueue; - TExecutionPoolPtr Pool = nullptr; - - TCpuDuration ExcessTime = 0; - - TEnqueuedTime EnqueuedTime; - - TBucketBase(TString bucketName, TString poolName) - : BucketName(std::move(bucketName)) - , PoolName(std::move(poolName)) - { } -}; - -bool operator < (const TBucketBase& lhs, const TBucketBase& rhs) -{ - return std::tie(lhs.ExcessTime, lhs.EnqueuedTime) < std::tie(rhs.ExcessTime, rhs.EnqueuedTime); -} - -//////////////////////////////////////////////////////////////////////////////// - -class TBucket - : public IInvoker - , public THeapItemBase - , public TBucketBase -{ -public: - TBucket(TString bucketName, TString poolName, TBucketMappingPtr parent) - : TBucketBase(std::move(bucketName), std::move(poolName)) - , Parent_(std::move(parent)) - { } - - ~TBucket(); - - void RunCallback(const TClosure& callback, TCpuInstant cpuInstant) - { - YT_LOG_TRACE("Executing callback (EnqueuedAt: %v)", cpuInstant); - TCurrentInvokerGuard currentInvokerGuard(this); - callback.Run(); - } - - bool IsSerialized() const override - { - return false; - } - - void Invoke(TClosure callback) override; - - void Invoke(TMutableRange callbacks) override - { - for (auto& callback : callbacks) { - Invoke(std::move(callback)); - } - } - - NThreading::TThreadId GetThreadId() const override - { - return NThreading::InvalidThreadId; - } - - bool CheckAffinity(const IInvokerPtr& invoker) const override - { - return invoker.Get() == this; - } - - void SubscribeWaitTimeObserved(const TWaitTimeObserver& /*callback*/) override - { } - - void UnsubscribeWaitTimeObserved(const TWaitTimeObserver& /*callback*/) override - { } - -private: - const TBucketMappingPtr Parent_; -}; - -DEFINE_REFCOUNTED_TYPE(TBucket) - -//////////////////////////////////////////////////////////////////////////////// - -class TBucketMapping - : public TRefCounted -{ -public: - struct TExecutionPoolToListNode - { - auto operator() (TExecutionPool* pool) const - { - return &pool->LinkedListNode; - } - }; - - using TPoolQueue = TIntrusiveLinkedList; - - explicit TBucketMapping(TDuration poolRetentionTime) - : PoolRetentionTime_(poolRetentionTime) - { } - - ~TBucketMapping() - { - auto guard = Guard(MappingLock_); - - while (RetainPoolQueue_.GetSize() > 0) { - auto* frontPool = RetainPoolQueue_.GetFront(); - - auto poolIt = PoolMapping_.find(frontPool->PoolName); - YT_ASSERT(poolIt != PoolMapping_.end() && poolIt->second == frontPool); - PoolMapping_.erase(poolIt); - - RetainPoolQueue_.PopFront(); - NYT::DestroyRefCounted(frontPool); - } - } - - virtual TProfiler GetPoolProfiler(const TString& poolName) = 0; - - virtual void Invoke(TClosure callback, TBucket* bucket) = 0; - - // GetInvoker is protected by mapping lock (can be sharded). - IInvokerPtr GetInvoker(const TString& poolName, const TString& bucketName) - { - // TODO(lukyan): Use reader guard and update it to writer if needed. - auto guard = Guard(MappingLock_); - - auto [bucketIt, bucketInserted] = BucketMapping_.emplace(std::pair(poolName, bucketName), nullptr); - - auto bucket = bucketIt->second ? DangerousGetPtr(bucketIt->second) : nullptr; - if (!bucket) { - bucket = New(bucketName, poolName, MakeStrong(this)); - bucketIt->second = bucket.Get(); - bucket->Pool = GetOrRegisterPool(bucket->PoolName); - } - - return bucket; - } - - // GetInvoker is protected by mapping lock (can be sharded). - void RemoveBucket(TBucket* bucket) - { - auto guard = Guard(MappingLock_); - auto bucketIt = BucketMapping_.find(std::pair(bucket->PoolName, bucket->BucketName)); - - if (bucketIt != BucketMapping_.end() && bucketIt->second == bucket) { - BucketMapping_.erase(bucketIt); - } - - // Detach under lock. - auto* rawPool = bucket->Pool.Release(); - - // Do not want use NewWithDeleter and keep pointer to TTwoLevelFairShareQueue in each execution pool. - if (NYT::GetRefCounter(rawPool)->Unref(1)) { - auto poolsToRemove = DetachPool(rawPool); - guard.Release(); - - while (poolsToRemove.GetSize() > 0) { - auto* frontPool = poolsToRemove.GetFront(); - poolsToRemove.PopFront(); - NYT::DestroyRefCounted(frontPool); - } - } - } - - TExecutionPoolPtr GetOrRegisterPool(TString poolName) - { - YT_ASSERT_SPINLOCK_AFFINITY(MappingLock_); - - auto [mappingIt, inserted] = PoolMapping_.emplace(poolName, nullptr); - if (!inserted) { - YT_ASSERT(mappingIt->second->PoolName == poolName); - - auto* rawPool = mappingIt->second; - // If RetainPoolQueue_ contains only one element its LinkedListNode will be null. - // Determine that pool is in RetainPoolQueue_ by checking its ref count. - if (NYT::GetRefCounter(rawPool)->GetRefCount() == 0) { - RetainPoolQueue_.Remove(rawPool); - rawPool->LinkedListNode = {}; - - YT_LOG_TRACE("Restoring pool (PoolName: %v)", rawPool->PoolName); - } - - YT_LOG_TRACE("Reusing pool (PoolName: %v)", rawPool->PoolName); - - // NB: Strong RC could be zero, see above. - NYT::GetRefCounter(rawPool)->DangerousRef(); - return TExecutionPoolPtr(rawPool, /*addReference*/ false); - } else { - YT_LOG_TRACE("Creating pool (PoolName: %v)", poolName); - auto pool = New(poolName, GetPoolProfiler(poolName)); - mappingIt->second = pool.Get(); - - return pool; - } - } - - TPoolQueue DetachPool(TExecutionPool* pool) - { - YT_ASSERT_SPINLOCK_AFFINITY(MappingLock_); - - YT_LOG_TRACE("Removing pool (PoolName: %v)", pool->PoolName); - - auto currentInstant = GetCpuInstant(); - pool->LastUsageTime = currentInstant; - - // Items in RetainPoolQueue_ are ordered by LastUsageTime. - // When pool is used again it is removed from RetainPoolQueue_. - RetainPoolQueue_.PushBack(pool); - return ProceedRetainQueue(currentInstant); - } - - TPoolQueue ProceedRetainQueue(TCpuInstant currentInstant) - { - YT_ASSERT_SPINLOCK_AFFINITY(MappingLock_); - - YT_LOG_TRACE("ProceedRetainQueue (Size: %v)", RetainPoolQueue_.GetSize()); - - TPoolQueue poolsToRemove; - - while (RetainPoolQueue_.GetSize() > 0) { - auto* frontPool = RetainPoolQueue_.GetFront(); - - auto lastUsageTime = frontPool->LastUsageTime; - if (CpuDurationToDuration(currentInstant - lastUsageTime) < PoolRetentionTime_) { - break; - } - - YT_LOG_TRACE("Destroing pool (PoolName: %v)", frontPool->PoolName); - - auto poolIt = PoolMapping_.find(frontPool->PoolName); - YT_ASSERT(poolIt != PoolMapping_.end() && poolIt->second == frontPool); - PoolMapping_.erase(poolIt); - - RetainPoolQueue_.PopFront(); - poolsToRemove.PushBack(frontPool); - } - - return poolsToRemove; - } - - void MaybeProceedRetainQueue(TCpuInstant currentInstant) - { - if (!MappingLock_.TryAcquire()) { - return; - } - - auto finally = Finally([&] { - MappingLock_.Release(); - }); - - auto poolsToRemove = ProceedRetainQueue(currentInstant); - MappingLock_.Release(); - finally.Release(); - - while (poolsToRemove.GetSize() > 0) { - auto* frontPool = poolsToRemove.GetFront(); - poolsToRemove.PopFront(); - NYT::DestroyRefCounted(frontPool); - } - } - -private: - const TDuration PoolRetentionTime_; - - YT_DECLARE_SPIN_LOCK(NThreading::TSpinLock, MappingLock_); - THashMap, TBucket*> BucketMapping_; - THashMap PoolMapping_; - - TPoolQueue RetainPoolQueue_; -}; - -DEFINE_REFCOUNTED_TYPE(TBucketMapping) - -//////////////////////////////////////////////////////////////////////////////// - -void TBucket::Invoke(TClosure callback) -{ - Parent_->Invoke(std::move(callback), this); -} - -TBucket::~TBucket() -{ - Parent_->RemoveBucket(this); -} - -//////////////////////////////////////////////////////////////////////////////// - -DEFINE_ENUM(ERequest, - (None) - (EndExecute) - (FetchNext) -); - -class TTwoLevelFairShareQueue - : protected TNotifyManager - , public TBucketMapping -{ -public: - using TWaitTimeObserver = ITwoLevelFairShareThreadPool::TWaitTimeObserver; - - TTwoLevelFairShareQueue( - TIntrusivePtr callbackEventCount, - const TString& threadNamePrefix, - const TNewTwoLevelFairShareThreadPoolOptions& options) - : TNotifyManager(std::move(callbackEventCount), GetThreadTags(threadNamePrefix), options.PollingPeriod) - , TBucketMapping(options.PoolRetentionTime) - , ThreadNamePrefix_(threadNamePrefix) - , Profiler_(TProfiler{"/fair_share_queue"} - .WithHot()) - , CumulativeSchedulingTimeCounter_(Profiler_ - .WithTags(GetThreadTags(ThreadNamePrefix_)) - .TimeCounter("/time/scheduling_cumulative")) - , PoolWeightProvider_(options.PoolWeightProvider) - , VerboseLogging_(options.VerboseLogging) - { } - - ~TTwoLevelFairShareQueue() - { - Shutdown(); - } - - void Configure(int threadCount) - { - ThreadCount_.store(threadCount); - } - - void Configure(TDuration pollingPeriod) - { - TNotifyManager::SetPollingPeriod(pollingPeriod); - } - - // (arkady-e1ppa): Explanation of memory orders and fences around Stopped_: - /* - We have two concurrent actions: Invoke and Shutdown. - For our logic Invoke method does 2 things: - 1) It pushes callback to the queue (we assume it be release RMW operation) - In reality right now it is seq_cst, but it this can and should be changed in the future. - 2) Now, the second (and third) action is seq_cst fence and then seq_cst read of Stopped_. - Shutdown also does two thigns: - 1) It does a seq_cst rmw in Stopped_ (effectively, just write) - 2) It drains the queue. - In order to prevent losing callbacks in queue - We need to make sure that either Invoke observes |true| in the read - or Shutdown observes placed callback from said Invoke. - We care about this, because if callback is stuck in queue it will - remain there until process is killed. If said callback MUST be - either executed or discarded (e.g. IPollable or Fiber) in order - for program to finish correctly (an not get stuck), then such a leak - can cause hung shutdown (and it used to do exactly that). - - Relevant parts of execution are written below - (letter is the same in the code). - T1(Invoke) T2(Shutdown) - RMW^rel(Queue, 0, 1) (a) RMW^rlx(Stopping, false, true) (d) - Fence^sc (b) Fence^sc (e) - R^rlx(Stopping, false) (c) RMW^acq(Queue, 0, 0) (f) - - We suppose that callback is lost so we haven't - seen 1 in (f) nor true in (c). - Since (c) reads false it reads from ctor which precedes - (d) in modification order. Thus we have (c) -cob-> (d) - (coherence-ordered before, https://eel.is/c++draft/atomics.order#3.3). - Likewise (f) must have read from some previous - dequeue attempt (or ctor) which precedes (a) in modification order. - Again, (f) -cob-> (a). - Now, for fences we have (sb means sequenced-before): - (b) -sb-> (c) -cob-> (d) -sb-> (e) => (b) -S-> (e) - (see https://eel.is/c++draft/atomics.order#4.4). - We also have - (e) -sb-> (f) -cob-> (a) -sb-> (b) => (b) -S-> (e). - Thus loop in S found contradicting the assumption - that (f) doesn't read 1 and (c) doesn't read true. - */ - - // Invoke is lock free on a fast path (a.k.a. no shutdown). - void Invoke(TClosure callback, TBucket* bucket) override - { - // We can't guarantee read of |true| in time anyway - // So relaxed order is enough. - if (Stopped_.load(std::memory_order::relaxed)) { - Drain(); - return; - } - - auto cpuInstant = GetCpuInstant(); - - YT_LOG_TRACE("Invoking action (EnqueuedAt: %v, Invoker: %v)", - cpuInstant, - ThreadNamePrefix_); - - TAction action; - action.EnqueuedAt = cpuInstant; - // Callback keeps raw ptr to bucket to minimize bucket ref count. - action.Callback = BIND(&TBucket::RunCallback, Unretained(bucket), std::move(callback), cpuInstant); - action.BucketHolder = MakeStrong(bucket); - action.EnqueuedThreadCookie = ThreadCookie(); - - InvokeQueue_.Enqueue(std::move(action)); // <- (a) - - std::atomic_thread_fence(std::memory_order::seq_cst); // <- (b) - if (Stopped_.load(std::memory_order::relaxed)) { // <- (c) - // We have encountered stop right after we have enqueued - // callback. There is a possibility that it is now stuck - // in queue forever. We dequeue it ourselves. - Drain(); - } - - NotifyFromInvoke(cpuInstant, ActiveThreads_.load() == 0); - } - - void StopPrologue() - { - GetEventCount()->NotifyAll(); - } - - TClosure OnExecute(int index, bool fetchNext, std::function isStopping) - { - while (true) { - auto cookie = GetEventCount()->PrepareWait(); - - auto& threadState = ThreadStates_[index]; - - auto hasAction = threadState.Action.BucketHolder; - int activeThreadDelta = hasAction ? -1 : 0; - - auto callback = DoOnExecute(index, fetchNext); - - if (callback) { - activeThreadDelta += 1; - } - - YT_VERIFY(activeThreadDelta >= -1 && activeThreadDelta <= 1); - - if (activeThreadDelta != 0) { - auto activeThreads = ActiveThreads_.fetch_add(activeThreadDelta); - auto newActiveThreads = activeThreads + activeThreadDelta; - YT_VERIFY(newActiveThreads >= 0 && newActiveThreads <= TThreadPoolBase::MaxThreadCount); - activeThreadDelta = 0; - } - - if (callback || isStopping()) { - CancelWait(); - return callback; - } - - YT_VERIFY(fetchNext); - MaybeRunMaintenance(&threadState, GetCpuInstant(), /*flush*/ true); - Wait(cookie, isStopping); - } - } - - void Shutdown() - { - if (Stopped_.exchange(true, std::memory_order::relaxed)) { // <- (d) - return; - } - std::atomic_thread_fence(std::memory_order::seq_cst); // <- (e) - - Drain(); // <- (f) - } - - void Drain() - { - auto guard = Guard(MainLock_); - - WaitHeap_.Clear(); - - std::vector buckets; - ActivePoolsHeap_.ForEach([&] (auto* pool) { - pool->ActiveBucketsHeap.ForEach([&] (auto* bucket) { - buckets.push_back(bucket); - }); - pool->ActiveBucketsHeap.Clear(); - }); - ActivePoolsHeap_.Clear(); - - // Actions hold strong references to buckets. - // Buckets' ActionQueue must be cleared before destroying actions. - std::vector actions; - for (auto* bucket : buckets) { - while (!bucket->ActionQueue.empty()) { - actions.push_back(std::move(bucket->ActionQueue.front())); - bucket->ActionQueue.pop(); - } - } - - InvokeQueue_.DequeueAll(); - - guard.Release(); - actions.clear(); - - } - - void SubscribeWaitTimeObserved(const TWaitTimeObserver& callback) - { - WaitTimeObservers_.Subscribe(callback); - } - - void UnsubscribeWaitTimeObserved(const TWaitTimeObserver& callback) - { - WaitTimeObservers_.Unsubscribe(callback); - } - -private: - struct TThreadState - { - std::atomic Request = ERequest::None; - - TCpuInstant AccountedAt = 0; - TAction Action; - - // Used to store bucket ref under lock to destroy it outside. - TBucketPtr BucketToUnref; - int LastActionsInQueue; - TDuration TimeFromStart; - TDuration TimeFromEnqueue; - TCpuInstant LastMaintenanceInstant = {}; - }; - - static_assert(sizeof(TThreadState) >= CacheLineSize); - - const TString ThreadNamePrefix_; - const TProfiler Profiler_; - const NProfiling::TTimeCounter CumulativeSchedulingTimeCounter_; - const IPoolWeightProviderPtr PoolWeightProvider_; - const bool VerboseLogging_; - - std::atomic Stopped_ = false; - TMpscStack InvokeQueue_; - char Padding0_[CacheLineSize - sizeof(TMpscStack)]; - - // Use simple non adaptive spinlock without complex wait strategies. - ::TSpinLock MainLock_; - char Padding1_[CacheLineSize - sizeof(::TSpinLock)]; - - std::array ThreadStates_; - - TPriorityQueue ActivePoolsHeap_; - TCpuDuration LastPoolExcessTime_ = 0; - TPriorityQueue WaitHeap_; - - // Buffer to keep actions during distribution to threads. - std::array OtherActions_; - std::atomic ThreadCount_ = 0; - std::atomic ActiveThreads_ = 0; - - TCallbackList WaitTimeObservers_; - - TProfiler GetPoolProfiler(const TString& poolName) override - { - return Profiler_.WithTags(GetBucketTags(ThreadNamePrefix_, poolName)); - } - - Y_NO_INLINE void ConsumeInvokeQueue() - { - YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - - Y_UNUSED(Padding0_); - Y_UNUSED(Padding1_); - - InvokeQueue_.DequeueAll(true, [&] (auto& action) { - auto* bucket = action.BucketHolder.Get(); - - auto* pool = bucket->Pool.Get(); - - YT_VERIFY(!pool->LinkedListNode.Next && !pool->LinkedListNode.Prev); - - if (!pool->GetPositionInHeap()) { - // ExcessTime can be greater than last pool excess time - // if the pool is "currently executed" and reschedules action. - if (pool->ExcessTime < LastPoolExcessTime_) { - // Use last pool excess time to schedule new pool - // after earlier scheduled pools (and not yet executed) in queue. - - YT_LOG_DEBUG_IF(VerboseLogging_, "Initial pool excess time (Name: %v, ExcessTime: %v -> %v)", - pool->PoolName, - pool->ExcessTime, - LastPoolExcessTime_); - - pool->ExcessTime = LastPoolExcessTime_; - } - - ActivePoolsHeap_.Insert(pool); - } - - ++pool->ActionCountInQueue; - - auto enqueuedAt = action.EnqueuedAt; - - bool wasEmpty = bucket->ActionQueue.empty(); - bucket->ActionQueue.push(std::move(action)); - - if (wasEmpty) { - bucket->EnqueuedTime.Value = enqueuedAt; - } - - YT_ASSERT(wasEmpty == !bucket->GetPositionInHeap()); - - if (!bucket->GetPositionInHeap()) { - // ExcessTime can be greater than last bucket excess time - // if the bucket is "currently executed" and reschedules action. - if (bucket->ExcessTime < pool->LastBucketExcessTime) { - // Use last bucket excess time to schedule new bucket - // after earlier scheduled buckets (and not yet executed) in queue. - - YT_LOG_DEBUG_IF(VerboseLogging_, "Initial bucket excess time (Name: %v, ExcessTime: %v -> %v)", - bucket->BucketName, - bucket->ExcessTime, - pool->LastBucketExcessTime); - - bucket->ExcessTime = pool->LastBucketExcessTime; - } - - pool->ActiveBucketsHeap.Insert(bucket); - pool->BucketCounter.Record(pool->ActiveBucketsHeap.GetSize()); - WaitHeap_.Insert(&bucket->EnqueuedTime); - } - }); - } - - void ServeBeginExecute(TThreadState* threadState, TCpuInstant currentInstant, TAction action) - { - YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - - YT_ASSERT(!threadState->Action.Callback); - YT_ASSERT(!threadState->Action.BucketHolder); - - action.StartedAt = currentInstant; - - threadState->AccountedAt = currentInstant; - threadState->Action = std::move(action); - } - - void ServeEndExecute(TThreadState* threadState, TCpuInstant /*cpuInstant*/) - { - YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - - auto action = std::move(threadState->Action); - YT_ASSERT(!threadState->Action.Callback); - YT_ASSERT(!action.Callback); - - if (!action.BucketHolder) { - // There was no action in begin execute. - return; - } - - // Try not to change bucket ref count under lock. - auto bucket = std::move(action.BucketHolder); - - auto& pool = *bucket->Pool; - YT_ASSERT(pool.PoolName == bucket->PoolName); - - // LastActionsInQueue is used to update SizeCounter outside lock. - threadState->LastActionsInQueue = --pool.ActionCountInQueue; - - // Do not destroy bucket pointer under lock. Move it in thread state in other place and - // destroy in corresponding thread after combiner. - threadState->BucketToUnref = std::move(bucket); - } - - Y_NO_INLINE void UpdateExcessTime(TBucket* bucket, TCpuDuration duration, TCpuInstant currentInstant) - { - YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - - auto* pool = bucket->Pool.Get(); - - if (PoolWeightProvider_ && pool->NextUpdateWeightInstant < currentInstant) { - pool->NextUpdateWeightInstant = currentInstant + DurationToCpuDuration(TDuration::Seconds(1)); - pool->InverseWeight = 1.0 / PoolWeightProvider_->GetWeight(pool->PoolName); - } - - YT_LOG_DEBUG_IF(VerboseLogging_, "Increment excess time (BucketName: %v, PoolName: %v, ExcessTime: %v -> %v)", - bucket->BucketName, - bucket->PoolName, - bucket->ExcessTime, - bucket->ExcessTime + duration); - - pool->ExcessTime += duration * pool->InverseWeight; - bucket->ExcessTime += duration; - - if (auto* positionInHeap = pool->GetPositionInHeap()) { - ActivePoolsHeap_.AdjustDown(pool); - } - - if (auto* positionInHeap = bucket->GetPositionInHeap()) { - pool->ActiveBucketsHeap.AdjustDown(bucket); - } - - // No need to update wait heap. - YT_ASSERT(!bucket->EnqueuedTime.GetPositionInHeap() == !bucket->GetPositionInHeap()); - } - - Y_NO_INLINE bool GetStarvingBucket(TAction* action) - { - YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - - YT_LOG_DEBUG_IF( - VerboseLogging_, - "Buckets: %v", - MakeFormattableView( - xrange(size_t(0), ActivePoolsHeap_.GetSize()), - [&] (auto* builder, auto index) { - auto& pool = ActivePoolsHeap_[index]; - builder->AppendFormat("%v [", CpuDurationToDuration(pool.ExcessTime)); - - for (size_t bucketIndex = 0; bucketIndex < pool.ActiveBucketsHeap.GetSize(); ++bucketIndex) { - const auto& bucket = pool.ActiveBucketsHeap[bucketIndex]; - - builder->AppendFormat("%Qv:%v/%v ", - bucket.BucketName, - CpuDurationToDuration(bucket.ExcessTime), - bucket.ActionQueue.front().EnqueuedAt); - } - builder->AppendFormat("]"); - })); - - if (ActivePoolsHeap_.Empty()) { - return false; - } - - auto* pool = ActivePoolsHeap_.GetFront(); - LastPoolExcessTime_ = pool->ExcessTime; - - auto* bucket = pool->ActiveBucketsHeap.GetFront(); - pool->LastBucketExcessTime = bucket->ExcessTime; - - YT_ASSERT(!bucket->ActionQueue.empty()); - *action = std::move(bucket->ActionQueue.front()); - bucket->ActionQueue.pop(); - - YT_ASSERT(bucket == action->BucketHolder); - - if (bucket->ActionQueue.empty()) { - bucket->EnqueuedTime.Value = std::numeric_limits::max(); - - WaitHeap_.Extract(&bucket->EnqueuedTime); - - pool->ActiveBucketsHeap.Extract(bucket); - pool->BucketCounter.Record(pool->ActiveBucketsHeap.GetSize()); - - if (pool->ActiveBucketsHeap.Empty()) { - ActivePoolsHeap_.Extract(pool); - } - } else { - bucket->EnqueuedTime.Value = bucket->ActionQueue.front().EnqueuedAt; - WaitHeap_.AdjustDown(&bucket->EnqueuedTime); - } - - return true; - } - - Y_NO_INLINE std::tuple ServeCombinedRequests(TCpuInstant currentInstant, int currentThreadIndex) - { - YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - - auto threadCount = ThreadCount_.load(); - // Thread pool size can be reconfigures during serving requests. - threadCount = std::max(threadCount, currentThreadIndex + 1); - - // Saved thread requests. They must be saved before consuming invoke queue. - std::array threadRequests{false}; - std::array threadIds; - int requestCount = 0; - - YT_LOG_TRACE("Updating excess time"); - - // Recalculate excess time for all currently evaluating or evaluated recently (end execute) buckets - for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex) { - auto& threadState = ThreadStates_[threadIndex]; - - // TODO(lukyan): Can skip (for threads without requests) or throttle UpdateExcessTime if it happens frequently. - // For each currently evaluating buckets recalculate excess time. - if (auto* bucket = threadState.Action.BucketHolder.Get()) { - - // TODO(lukyan): Update last excess time for pool without active buckets. - UpdateExcessTime(bucket, currentInstant - threadState.AccountedAt, currentInstant); - threadState.AccountedAt = currentInstant; - } - - auto request = threadState.Request.load(std::memory_order::acquire); - if (request != ERequest::None) { - ServeEndExecute(&threadState, currentInstant); - - if (request == ERequest::FetchNext) { - // Save requests before ConsumeInvokeQueue. Otherwise some thread can schedule action - // but action can not be fetched (schedule and fetch happens after ConsumeInvokeQueue). - threadRequests[threadIndex] = true; - threadIds[requestCount++] = threadIndex; - } else { - threadState.Request.store(ERequest::None, std::memory_order::release); - } - } - } - - YT_LOG_TRACE("Consuming invoke queue"); - - ConsumeInvokeQueue(); - - int fetchedActions = 0; - int otherActionCount = 0; - - // Schedule actions to desired threads. - while (fetchedActions < requestCount) { - TAction action; - - if (!GetStarvingBucket(&action)) { - break; - } - - ++fetchedActions; - - int threadIndex = -1; - - auto unpackedCookie = TTaggedPtr::Unpack(action.EnqueuedThreadCookie); - // TODO(lukyan): Check also wait time. If it is too high, no matter where to schedule. - if (unpackedCookie.Ptr == this) { - threadIndex = unpackedCookie.Tag; - } - - if (threadIndex != -1 && threadRequests[threadIndex]) { - ServeBeginExecute(&ThreadStates_[threadIndex], currentInstant, std::move(action)); - threadRequests[threadIndex] = false; - ThreadStates_[threadIndex].Request.store(ERequest::None, std::memory_order::release); - } else { - OtherActions_[otherActionCount++] = std::move(action); - } - } - - // Schedule other actions. - for (int threadIndex : TRange(threadIds.data(), requestCount)) { - if (threadRequests[threadIndex]) { - if (otherActionCount > 0) { - ServeBeginExecute(&ThreadStates_[threadIndex], currentInstant, std::move(OtherActions_[--otherActionCount])); - } - - ThreadStates_[threadIndex].Request.store(ERequest::None, std::memory_order::release); - } - } - - return {requestCount, fetchedActions}; - } - - TCpuInstant GetMinEnqueuedAt() - { - YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - - return WaitHeap_.Empty() - ? std::numeric_limits::max() - : WaitHeap_.GetFront()->Value; - } - - TClosure DoOnExecute(int index, bool fetchNext) - { - auto cpuInstant = GetCpuInstant(); - auto& threadState = ThreadStates_[index]; - - const auto& oldAction = threadState.Action; - if (oldAction.BucketHolder) { - auto waitTime = CpuDurationToDuration(oldAction.StartedAt - oldAction.EnqueuedAt); - auto timeFromStart = CpuDurationToDuration(cpuInstant - oldAction.StartedAt); - auto timeFromEnqueue = CpuDurationToDuration(cpuInstant - oldAction.EnqueuedAt); - - threadState.TimeFromStart = timeFromStart; - threadState.TimeFromEnqueue = timeFromEnqueue; - - if (timeFromStart > LogDurationThreshold) { - YT_LOG_DEBUG("Callback execution took too long (Wait: %v, Execution: %v, Total: %v)", - waitTime, - timeFromStart, - timeFromEnqueue); - } - - if (waitTime > LogDurationThreshold) { - YT_LOG_DEBUG("Callback wait took too long (Wait: %v, Execution: %v, Total: %v)", - waitTime, - timeFromStart, - timeFromEnqueue); - } - } - - auto finally = Finally([&] { - auto bucketToUndef = std::move(threadState.BucketToUnref); - if (bucketToUndef) { - auto* pool = bucketToUndef->Pool.Get(); - pool->SizeCounter.Record(threadState.LastActionsInQueue); - pool->DequeuedCounter.Increment(1); - pool->ExecTimeCounter.Record(threadState.TimeFromStart); - pool->TotalTimeCounter.Record(threadState.TimeFromEnqueue); - pool->CumulativeTimeCounter.Add(threadState.TimeFromStart); - bucketToUndef.Reset(); - } - - const auto& action = threadState.Action; - if (action.BucketHolder) { - auto waitTime = CpuDurationToDuration(action.StartedAt - action.EnqueuedAt); - action.BucketHolder->Pool->WaitTimeCounter.Record(waitTime); - WaitTimeObservers_.Fire(waitTime); - } - - MaybeRunMaintenance(&threadState, action.StartedAt, /*flush*/ false); - - CumulativeSchedulingTimeCounter_.Add(CpuDurationToDuration(GetCpuInstant() - cpuInstant)); - - if (!fetchNext) { - MaybeProceedRetainQueue(cpuInstant); - } - }); - - auto& request = threadState.Request; - YT_VERIFY(request == ERequest::None); - request.store(fetchNext ? ERequest::FetchNext : ERequest::EndExecute); - - if (MainLock_.IsLocked() || !MainLock_.TryAcquire()) { - // Locked here. - while (true) { - SpinLockPause(); - - if (request.load(std::memory_order::acquire) == ERequest::None) { - return std::move(threadState.Action.Callback); - } else if (!MainLock_.IsLocked() && MainLock_.TryAcquire()) { - break; - } - } - } - - ResetMinEnqueuedAt(); - - YT_LOG_TRACE("Started serving requests"); - auto [requests, fetchedActions] = ServeCombinedRequests(cpuInstant, index); - - // Evaluate notify condition here, but call NotifyAfterFetch outside lock. - auto newMinEnqueuedAt = GetMinEnqueuedAt(); - MainLock_.Release(); - - auto endInstant = GetCpuInstant(); - YT_LOG_TRACE("Finished serving requests (Duration: %v, Requests: %v, FetchCount: %v, MinEnqueuedAt: %v)", - CpuDurationToDuration(endInstant - cpuInstant), - requests, - fetchedActions, - CpuInstantToInstant(newMinEnqueuedAt)); - - NotifyAfterFetch(endInstant, newMinEnqueuedAt); - - return std::move(threadState.Action.Callback); - } - - static void MaybeRunMaintenance(TThreadState* threadState, TCpuInstant now, bool flush) - { - YT_ASSERT(threadState); - - constexpr i64 MaintenancePeriod = 1'000'000'000; - if (flush || now > threadState->LastMaintenanceInstant + MaintenancePeriod) { - ReclaimHazardPointers(false); - threadState->LastMaintenanceInstant = now; - } - } -}; - -DEFINE_REFCOUNTED_TYPE(TTwoLevelFairShareQueue) - -//////////////////////////////////////////////////////////////////////////////// - -class TFairShareThread - : public TSchedulerThread -{ -public: - TFairShareThread( - TTwoLevelFairShareQueuePtr queue, - TIntrusivePtr callbackEventCount, - const TString& threadGroupName, - const TString& threadName, - int index) - : TSchedulerThread( - std::move(callbackEventCount), - threadGroupName, - threadName) - , Queue_(std::move(queue)) - , Index_(index) - { } - -protected: - const TTwoLevelFairShareQueuePtr Queue_; - const int Index_; - - void OnStart() override - { - ThreadCookie() = TTaggedPtr(Queue_.Get(), static_cast(Index_)).Pack(); - } - - void StopPrologue() override - { - Queue_->StopPrologue(); - } - - TClosure OnExecute() override - { - bool fetchNext = !TSchedulerThread::IsStopping() || TSchedulerThread::GracefulStop_; - - return Queue_->OnExecute(Index_, fetchNext, [&] { - return TSchedulerThread::IsStopping(); - }); - } - - TClosure BeginExecute() override - { - Y_UNREACHABLE(); - } - - void EndExecute() override - { - Y_UNREACHABLE(); - } -}; - -DEFINE_REFCOUNTED_TYPE(TFairShareThread) - -//////////////////////////////////////////////////////////////////////////////// - -class TTwoLevelFairShareThreadPool - : public ITwoLevelFairShareThreadPool - , public TThreadPoolBase -{ -public: - TTwoLevelFairShareThreadPool( - int threadCount, - const TString& threadNamePrefix, - const TNewTwoLevelFairShareThreadPoolOptions& options) - : TThreadPoolBase(threadNamePrefix) - , Queue_(New( - CallbackEventCount_, - ThreadNamePrefix_, - options)) - { - SetThreadCount(threadCount); - } - - ~TTwoLevelFairShareThreadPool() - { - Shutdown(); - } - - void SetThreadCount(int threadCount) override - { - TThreadPoolBase::SetThreadCount(threadCount); - } - - void SetPollingPeriod(TDuration pollingPeriod) override - { - Queue_->Configure(pollingPeriod); - } - - IInvokerPtr GetInvoker( - const TString& poolName, - const TFairShareThreadPoolTag& bucketName) override - { - EnsureStarted(); - return Queue_->GetInvoker(poolName, bucketName); - } - - void Shutdown() override - { - TThreadPoolBase::Shutdown(); - } - - int GetThreadCount() override - { - return TThreadPoolBase::GetThreadCount(); - } - - void SubscribeWaitTimeObserved(const TWaitTimeObserver& callback) override - { - Queue_->SubscribeWaitTimeObserved(callback); - } - - void UnsubscribeWaitTimeObserved(const TWaitTimeObserver& callback) override - { - Queue_->UnsubscribeWaitTimeObserved(callback); - } - -private: - const TIntrusivePtr CallbackEventCount_ = New(); - const TTwoLevelFairShareQueuePtr Queue_; - - void DoShutdown() override - { - Queue_->Shutdown(); - TThreadPoolBase::DoShutdown(); - Queue_->Drain(); - } - - void DoSetThreadCount(int threadCount) override - { - Queue_->Configure(threadCount); - TThreadPoolBase::DoSetThreadCount(threadCount); - } - - TSchedulerThreadPtr SpawnThread(int index) override - { - return New( - Queue_, - CallbackEventCount_, - ThreadNamePrefix_, - MakeThreadName(index), - index); - } -}; - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// - -ITwoLevelFairShareThreadPoolPtr CreateNewTwoLevelFairShareThreadPool( - int threadCount, - const TString& threadNamePrefix, - const TNewTwoLevelFairShareThreadPoolOptions& options) -{ - return New( - threadCount, - threadNamePrefix, - options); -} - -//////////////////////////////////////////////////////////////////////////////// - -} // namespace NYT::NConcurrency diff --git a/yt/yt/core/concurrency/new_fair_share_thread_pool.h b/yt/yt/core/concurrency/new_fair_share_thread_pool.h deleted file mode 100644 index 8be740969e8d..000000000000 --- a/yt/yt/core/concurrency/new_fair_share_thread_pool.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "public.h" - -#include - -namespace NYT::NConcurrency { - -//////////////////////////////////////////////////////////////////////////////// - -struct TNewTwoLevelFairShareThreadPoolOptions -{ - IPoolWeightProviderPtr PoolWeightProvider = nullptr; - bool VerboseLogging = false; - TDuration PollingPeriod = TDuration::MilliSeconds(10); - TDuration PoolRetentionTime = TDuration::Seconds(30); -}; - -ITwoLevelFairShareThreadPoolPtr CreateNewTwoLevelFairShareThreadPool( - int threadCount, - const TString& threadNamePrefix, - const TNewTwoLevelFairShareThreadPoolOptions& options = {}); - -//////////////////////////////////////////////////////////////////////////////// - -} // namespace NYT::NConcurrency diff --git a/yt/yt/core/concurrency/thread_pool_poller.cpp b/yt/yt/core/concurrency/thread_pool_poller.cpp index 88a32319cb3c..0158c1d77be3 100644 --- a/yt/yt/core/concurrency/thread_pool_poller.cpp +++ b/yt/yt/core/concurrency/thread_pool_poller.cpp @@ -2,7 +2,6 @@ #include "thread_pool_poller.h" #include "private.h" #include "two_level_fair_share_thread_pool.h" -#include "new_fair_share_thread_pool.h" #include #include @@ -200,7 +199,7 @@ class TThreadPoolPollerImpl // pollables and on shutdown. PollerImpl_.Set(nullptr, WakeupHandle_.GetFD(), CONT_POLL_EDGE_TRIGGERED | CONT_POLL_READ); - FairShareThreadPool_ = CreateNewTwoLevelFairShareThreadPool( + FairShareThreadPool_ = CreateTwoLevelFairShareThreadPool( threadCount, threadNamePrefix + "FS", { diff --git a/yt/yt/core/concurrency/two_level_fair_share_thread_pool.cpp b/yt/yt/core/concurrency/two_level_fair_share_thread_pool.cpp index 07897b4dc87c..d8dd529326f9 100644 --- a/yt/yt/core/concurrency/two_level_fair_share_thread_pool.cpp +++ b/yt/yt/core/concurrency/two_level_fair_share_thread_pool.cpp @@ -1,397 +1,793 @@ #include "two_level_fair_share_thread_pool.h" #include "private.h" -#include "invoker_queue.h" +#include "notify_manager.h" #include "profiling_helpers.h" #include "scheduler_thread.h" #include "thread_pool_detail.h" #include +#include +#include #include #include - -#include +#include +#include #include -#include +#include -#include +#include + +#include + +#include -#include +#include namespace NYT::NConcurrency { using namespace NProfiling; -static constexpr auto& Logger = ConcurrencyLogger; - //////////////////////////////////////////////////////////////////////////////// namespace { -struct THeapItem; -class TTwoLevelFairShareQueue; +YT_DEFINE_GLOBAL(const NLogging::TLogger, Logger, "FairShareThreadPool"); -DECLARE_REFCOUNTED_STRUCT(TBucket) +DECLARE_REFCOUNTED_CLASS(TBucketMapping) +DECLARE_REFCOUNTED_CLASS(TTwoLevelFairShareQueue) +DECLARE_REFCOUNTED_CLASS(TBucket) -struct TBucket - : public IInvoker +struct TExecutionPool; + +// High 16 bits is thread index and 48 bits for thread pool ptr. +YT_DEFINE_THREAD_LOCAL(TPackedPtr, ThreadCookie, 0); + +constexpr auto LogDurationThreshold = TDuration::Seconds(1); + +//////////////////////////////////////////////////////////////////////////////// + +template +class THeapItem { - TBucket(size_t poolId, TFairShareThreadPoolTag tag, TWeakPtr parent) - : PoolId(poolId) - , Tag(std::move(tag)) - , Parent(std::move(parent)) - { } +public: + THeapItem(const THeapItem&) = delete; + THeapItem& operator=(const THeapItem&) = delete; - void RunCallback(const TClosure& callback) + explicit THeapItem(T* ptr) + : Ptr_(std::move(ptr)) { - TCurrentInvokerGuard currentInvokerGuard(this); - callback(); + AdjustBackReference(); } - void Invoke(TClosure callback) override; + ~THeapItem() + { + if (Ptr_) { + YT_ASSERT(Ptr_->PositionInHeap_ == this); + Ptr_->PositionInHeap_ = nullptr; + } + } - void Invoke(TMutableRange callbacks) override; + T& operator* () + { + return *Ptr_; + } - void Drain() + const T& operator*() const { - Queue.clear(); + return *Ptr_; } - NThreading::TThreadId GetThreadId() const override + T* operator->() { - return NThreading::InvalidThreadId; + return Ptr_; } - bool CheckAffinity(const IInvokerPtr& invoker) const override + const T* operator->() const { - return invoker.Get() == this; + return Ptr_; } - bool IsSerialized() const override + bool operator < (const THeapItem& other) const { - return false; + return *Ptr_ < *other; } - void SubscribeWaitTimeObserved(const TWaitTimeObserver& /*callback*/) override - { } + THeapItem(THeapItem&& other) noexcept + : Ptr_(std::move(other.Ptr_)) + { + other.Ptr_ = nullptr; + AdjustBackReference(); + } - void UnsubscribeWaitTimeObserved(const TWaitTimeObserver& /*callback*/) override - { } + THeapItem& operator=(THeapItem&& other) noexcept + { + Ptr_ = std::move(other.Ptr_); + other.Ptr_ = nullptr; + AdjustBackReference(); - ~TBucket(); + return *this; + } - const size_t PoolId; - const TFairShareThreadPoolTag Tag; - TWeakPtr Parent; - TRingQueue Queue; - THeapItem* HeapIterator = nullptr; - NProfiling::TCpuDuration WaitTime = 0; +private: + T* Ptr_; - TCpuDuration ExcessTime = 0; - int CurrentExecutions = 0; + void AdjustBackReference() + { + if (Ptr_) { + Ptr_->PositionInHeap_ = this; + } + } }; -DEFINE_REFCOUNTED_TYPE(TBucket) +template +class THeapItemBase +{ +public: + friend THeapItem; + + THeapItem* GetPositionInHeap() const + { + return PositionInHeap_; + } + + ~THeapItemBase() + { + YT_ASSERT(!PositionInHeap_); + } + +private: + THeapItem* PositionInHeap_ = nullptr; +}; -struct THeapItem +template +class TPriorityQueue { - TBucketPtr Bucket; +public: + void Insert(T* object) + { + Items_.emplace_back(object); + SiftUp(Items_.begin(), Items_.end(), Items_.end() - 1); + YT_ASSERT(object->GetPositionInHeap()); + } - THeapItem(const THeapItem&) = delete; - THeapItem& operator=(const THeapItem&) = delete; + void Extract(const T* object) + { + auto* positionInHeap = object->GetPositionInHeap(); + YT_ASSERT(Items_.data() <= positionInHeap && positionInHeap < Items_.data() + Items_.size()); - explicit THeapItem(TBucketPtr bucket) - : Bucket(std::move(bucket)) + std::swap(*positionInHeap, Items_.back()); + SiftDown( + Items_.data(), + Items_.data() + std::ssize(Items_) - 1, + positionInHeap); + + YT_ASSERT(Items_.back()->GetPositionInHeap() == object->GetPositionInHeap()); + Items_.pop_back(); + } + + void AdjustDown(const T* object) { - AdjustBackReference(this); + auto* positionInHeap = object->GetPositionInHeap(); + YT_ASSERT(Items_.data() <= positionInHeap && positionInHeap < Items_.data() + Items_.size()); + SiftDown( + Items_.data(), + Items_.data() + std::ssize(Items_), + positionInHeap); } - THeapItem(THeapItem&& other) noexcept - : Bucket(std::move(other.Bucket)) + T* GetFront() { - AdjustBackReference(this); + YT_ASSERT(!Empty()); + return &*Items_.front(); } - THeapItem& operator=(THeapItem&& other) noexcept + bool Empty() const { - Bucket = std::move(other.Bucket); - AdjustBackReference(this); + return Items_.empty(); + } - return *this; + size_t GetSize() const + { + return Items_.size(); } - void AdjustBackReference(THeapItem* iterator) + T& operator[] (size_t index) { - if (Bucket) { - Bucket->HeapIterator = iterator; - } + return *Items_[index]; } - ~THeapItem() + template + void ForEach(F&& functor) { - if (Bucket) { - Bucket->HeapIterator = nullptr; + for (auto& item : Items_) { + functor(&*item); } } + + void Clear() + { + Items_.clear(); + } + +private: + std::vector> Items_; +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct TAction +{ + TCpuInstant EnqueuedAt = 0; + TCpuInstant StartedAt = 0; + + // Callback keeps raw ptr to bucket to minimize bucket ref count. + TClosure Callback; + TBucketPtr BucketHolder; + + TPackedPtr EnqueuedThreadCookie = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct TEnqueuedTime + : public THeapItemBase +{ + TCpuInstant Value = 0; }; -bool operator < (const THeapItem& lhs, const THeapItem& rhs) +bool operator < (const TEnqueuedTime& lhs, const TEnqueuedTime& rhs) { - return lhs.Bucket->ExcessTime < rhs.Bucket->ExcessTime; + return lhs.Value < rhs.Value; } //////////////////////////////////////////////////////////////////////////////// -static constexpr auto LogDurationThreshold = TDuration::Seconds(1); +// Data for scheduling on the first level. +struct TExecutionPool final + : public THeapItemBase +{ + const TString PoolName; + + // Profiling sensors. + const NProfiling::TSummary BucketCounter; + const NProfiling::TSummary SizeCounter; + const NProfiling::TCounter DequeuedCounter; + const TEventTimer WaitTimeCounter; + const TEventTimer ExecTimeCounter; + const TEventTimer TotalTimeCounter; + const NProfiling::TTimeCounter CumulativeTimeCounter; + + // Action count is used to decide whether to reset excess time or not. + size_t ActionCountInQueue = 0; + + TCpuDuration NextUpdateWeightInstant = 0; + double InverseWeight = 1.0; + TCpuDuration ExcessTime = 0; -DECLARE_REFCOUNTED_TYPE(TTwoLevelFairShareQueue) + TPriorityQueue ActiveBucketsHeap; + TCpuDuration LastBucketExcessTime = 0; + + TIntrusiveLinkedListNode LinkedListNode; + // Execution pool is retained for some after last usage to flush profiling counters. + TCpuInstant LastUsageTime = 0; + + TExecutionPool(TString poolName, const TProfiler& profiler) + : PoolName(std::move(poolName)) + , BucketCounter(profiler.Summary("/buckets")) + , SizeCounter(profiler.Summary("/size")) + , DequeuedCounter(profiler.Counter("/dequeued")) + , WaitTimeCounter(profiler.Timer("/time/wait")) + , ExecTimeCounter(profiler.Timer("/time/exec")) + , TotalTimeCounter(profiler.Timer("/time/total")) + , CumulativeTimeCounter(profiler.TimeCounter("/time/cumulative")) + { } +}; -class TTwoLevelFairShareQueue - : public TRefCounted +bool operator < (const TExecutionPool& lhs, const TExecutionPool& rhs) { -public: - using TWaitTimeObserver = ITwoLevelFairShareThreadPool::TWaitTimeObserver; + return lhs.ExcessTime < rhs.ExcessTime; +} - TTwoLevelFairShareQueue( - TIntrusivePtr callbackEventCount, - const TString& threadNamePrefix, - IPoolWeightProviderPtr poolWeightProvider) - : CallbackEventCount_(std::move(callbackEventCount)) - , ThreadNamePrefix_(threadNamePrefix) - , Profiler_(TProfiler("/fair_share_queue") - .WithHot()) - , PoolWeightProvider_(std::move(poolWeightProvider)) +using TExecutionPoolPtr = ::NYT::TIntrusivePtr; + +//////////////////////////////////////////////////////////////////////////////// + +// Data for scheduling on the second level. +struct TBucketBase +{ + const TString BucketName; + const TString PoolName; + + TRingQueue ActionQueue; + TExecutionPoolPtr Pool = nullptr; + + TCpuDuration ExcessTime = 0; + + TEnqueuedTime EnqueuedTime; + + TBucketBase(TString bucketName, TString poolName) + : BucketName(std::move(bucketName)) + , PoolName(std::move(poolName)) { } +}; - ~TTwoLevelFairShareQueue() +bool operator < (const TBucketBase& lhs, const TBucketBase& rhs) +{ + return std::tie(lhs.ExcessTime, lhs.EnqueuedTime) < std::tie(rhs.ExcessTime, rhs.EnqueuedTime); +} + +//////////////////////////////////////////////////////////////////////////////// + +class TBucket + : public IInvoker + , public THeapItemBase + , public TBucketBase +{ +public: + TBucket(TString bucketName, TString poolName, TBucketMappingPtr parent) + : TBucketBase(std::move(bucketName), std::move(poolName)) + , Parent_(std::move(parent)) + { } + + ~TBucket(); + + void RunCallback(const TClosure& callback, TCpuInstant cpuInstant) { - Shutdown(); + YT_LOG_TRACE("Executing callback (EnqueuedAt: %v)", cpuInstant); + TCurrentInvokerGuard currentInvokerGuard(this); + callback.Run(); } - void Configure(int threadCount) + bool IsSerialized() const override { - ThreadCount_.store(threadCount); + return false; + } + + void Invoke(TClosure callback) override; + + void Invoke(TMutableRange callbacks) override + { + for (auto& callback : callbacks) { + Invoke(std::move(callback)); + } } - IInvokerPtr GetInvoker(const TString& poolName, const TFairShareThreadPoolTag& tag) + NThreading::TThreadId GetThreadId() const override { - while (true) { - auto guard = Guard(SpinLock_); + return NThreading::InvalidThreadId; + } - auto poolIt = NameToPoolId_.find(poolName); - if (poolIt == NameToPoolId_.end()) { - auto newPoolId = GetLowestEmptyPoolId(); + bool CheckAffinity(const IInvokerPtr& invoker) const override + { + return invoker.Get() == this; + } - auto profiler = Profiler_.WithTags(GetBucketTags(ThreadNamePrefix_, poolName)); - auto newPool = std::make_unique(poolName, profiler); - if (newPoolId >= IdToPool_.size()) { - IdToPool_.emplace_back(); - } - IdToPool_[newPoolId] = std::move(newPool); - poolIt = NameToPoolId_.emplace(poolName, newPoolId).first; - } + void SubscribeWaitTimeObserved(const TWaitTimeObserver& /*callback*/) override + { } - auto poolId = poolIt->second; - const auto& pool = IdToPool_[poolId]; - if (PoolWeightProvider_) { - pool->Weight = PoolWeightProvider_->GetWeight(poolName); - } + void UnsubscribeWaitTimeObserved(const TWaitTimeObserver& /*callback*/) override + { } - TBucketPtr bucket; - auto bucketIt = pool->TagToBucket.find(tag); - if (bucketIt == pool->TagToBucket.end()) { - bucket = New(poolId, tag, MakeWeak(this)); - YT_VERIFY(pool->TagToBucket.emplace(tag, bucket.Get()).second); - pool->BucketCounter.Update(pool->TagToBucket.size()); - } else { - bucket = DangerousGetPtr(bucketIt->second); - if (!bucket) { - // Bucket is already being destroyed; backoff and retry. - guard.Release(); - ThreadYield(); - continue; - } - } +private: + const TBucketMappingPtr Parent_; +}; - return bucket; - } - } +DEFINE_REFCOUNTED_TYPE(TBucket) + +//////////////////////////////////////////////////////////////////////////////// - void Invoke(TClosure callback, TBucket* bucket) +class TBucketMapping + : public TRefCounted +{ +public: + struct TExecutionPoolToListNode { - auto guard = Guard(SpinLock_); - // See Shutdown method. - if (Stopping_) { - return; + auto operator() (TExecutionPool* pool) const + { + return &pool->LinkedListNode; } - const auto& pool = IdToPool_[bucket->PoolId]; + }; - pool->SizeCounter.Record(++pool->Size); + using TPoolQueue = TIntrusiveLinkedList; - if (!bucket->HeapIterator) { - // Otherwise ExcessTime will be recalculated in AccountCurrentlyExecutingBuckets. - if (bucket->CurrentExecutions == 0 && !pool->Heap.empty()) { - bucket->ExcessTime = pool->Heap.front().Bucket->ExcessTime; - } + explicit TBucketMapping(TDuration poolRetentionTime) + : PoolRetentionTime_(poolRetentionTime) + { } + + ~TBucketMapping() + { + auto guard = Guard(MappingLock_); - pool->Heap.emplace_back(bucket); - AdjustHeapBack(pool->Heap.begin(), pool->Heap.end()); - YT_VERIFY(bucket->HeapIterator); + while (RetainPoolQueue_.GetSize() > 0) { + auto* frontPool = RetainPoolQueue_.GetFront(); + + auto poolIt = PoolMapping_.find(frontPool->PoolName); + YT_ASSERT(poolIt != PoolMapping_.end() && poolIt->second == frontPool); + PoolMapping_.erase(poolIt); + + RetainPoolQueue_.PopFront(); + NYT::DestroyRefCounted(frontPool); } + } - YT_ASSERT(callback); + virtual TProfiler GetPoolProfiler(const TString& poolName) = 0; - TEnqueuedAction action; - action.Finished = false; - action.EnqueuedAt = GetCpuInstant(); - action.Callback = BIND(&TBucket::RunCallback, MakeStrong(bucket), std::move(callback)); - bucket->Queue.push(std::move(action)); + virtual void Invoke(TClosure callback, TBucket* bucket) = 0; - guard.Release(); + // GetInvoker is protected by mapping lock (can be sharded). + IInvokerPtr GetInvoker(const TString& poolName, const TString& bucketName) + { + // TODO(lukyan): Use reader guard and update it to writer if needed. + auto guard = Guard(MappingLock_); + + auto [bucketIt, bucketInserted] = BucketMapping_.emplace(std::pair(poolName, bucketName), nullptr); + + auto bucket = bucketIt->second ? DangerousGetPtr(bucketIt->second) : nullptr; + if (!bucket) { + bucket = New(bucketName, poolName, MakeStrong(this)); + bucketIt->second = bucket.Get(); + bucket->Pool = GetOrRegisterPool(bucket->PoolName); + } - CallbackEventCount_->NotifyOne(); + return bucket; } + // GetInvoker is protected by mapping lock (can be sharded). void RemoveBucket(TBucket* bucket) { - auto guard = Guard(SpinLock_); + auto guard = Guard(MappingLock_); + auto bucketIt = BucketMapping_.find(std::pair(bucket->PoolName, bucket->BucketName)); - auto& pool = IdToPool_[bucket->PoolId]; + if (bucketIt != BucketMapping_.end() && bucketIt->second == bucket) { + BucketMapping_.erase(bucketIt); + } + + // Detach under lock. + auto* rawPool = bucket->Pool.Release(); - auto it = pool->TagToBucket.find(bucket->Tag); - YT_VERIFY(it != pool->TagToBucket.end()); - YT_VERIFY(it->second == bucket); - pool->TagToBucket.erase(it); - pool->BucketCounter.Update(pool->TagToBucket.size()); + // Do not want use NewWithDeleter and keep pointer to TTwoLevelFairShareQueue in each execution pool. + if (NYT::GetRefCounter(rawPool)->Unref(1)) { + auto poolsToRemove = DetachPool(rawPool); + guard.Release(); - if (pool->TagToBucket.empty()) { - YT_VERIFY(NameToPoolId_.erase(pool->PoolName) == 1); - pool.reset(); + while (poolsToRemove.GetSize() > 0) { + auto* frontPool = poolsToRemove.GetFront(); + poolsToRemove.PopFront(); + NYT::DestroyRefCounted(frontPool); + } } } - void Shutdown() + TExecutionPoolPtr GetOrRegisterPool(TString poolName) { - auto guard = Guard(SpinLock_); - // NB(arkady-e1ppa): We write/read value under spinlock - // instead of atomic in order to ensure that in Invoke method - // we either observe |false| and enqueue callback - // which will be drained here or we observe |true| - // and not enqueue callback at all. - Stopping_ = true; - - for (const auto& pool : IdToPool_) { - if (pool) { - for (const auto& item : pool->Heap) { - item.Bucket->Drain(); - } + YT_ASSERT_SPINLOCK_AFFINITY(MappingLock_); + + auto [mappingIt, inserted] = PoolMapping_.emplace(poolName, nullptr); + if (!inserted) { + YT_ASSERT(mappingIt->second->PoolName == poolName); + + auto* rawPool = mappingIt->second; + // If RetainPoolQueue_ contains only one element its LinkedListNode will be null. + // Determine that pool is in RetainPoolQueue_ by checking its ref count. + if (NYT::GetRefCounter(rawPool)->GetRefCount() == 0) { + RetainPoolQueue_.Remove(rawPool); + rawPool->LinkedListNode = {}; + + YT_LOG_TRACE("Restoring pool (PoolName: %v)", rawPool->PoolName); } + + YT_LOG_TRACE("Reusing pool (PoolName: %v)", rawPool->PoolName); + + // NB: Strong RC could be zero, see above. + NYT::GetRefCounter(rawPool)->DangerousRef(); + return TExecutionPoolPtr(rawPool, /*addReference*/ false); + } else { + YT_LOG_TRACE("Creating pool (PoolName: %v)", poolName); + auto pool = New(poolName, GetPoolProfiler(poolName)); + mappingIt->second = pool.Get(); + + return pool; } } - bool BeginExecute(TEnqueuedAction* action, int index) + TPoolQueue DetachPool(TExecutionPool* pool) { - auto& threadState = ThreadStates_[index]; + YT_ASSERT_SPINLOCK_AFFINITY(MappingLock_); - YT_ASSERT(!threadState.Bucket); - YT_ASSERT(action && action->Finished); + YT_LOG_TRACE("Removing pool (PoolName: %v)", pool->PoolName); auto currentInstant = GetCpuInstant(); + pool->LastUsageTime = currentInstant; - TBucketPtr bucket; - { - auto guard = Guard(SpinLock_); - bucket = GetStarvingBucket(action); + // Items in RetainPoolQueue_ are ordered by LastUsageTime. + // When pool is used again it is removed from RetainPoolQueue_. + RetainPoolQueue_.PushBack(pool); + return ProceedRetainQueue(currentInstant); + } + + TPoolQueue ProceedRetainQueue(TCpuInstant currentInstant) + { + YT_ASSERT_SPINLOCK_AFFINITY(MappingLock_); + + YT_LOG_TRACE("ProceedRetainQueue (Size: %v)", RetainPoolQueue_.GetSize()); - if (!bucket) { - return false; + TPoolQueue poolsToRemove; + + while (RetainPoolQueue_.GetSize() > 0) { + auto* frontPool = RetainPoolQueue_.GetFront(); + + auto lastUsageTime = frontPool->LastUsageTime; + if (CpuDurationToDuration(currentInstant - lastUsageTime) < PoolRetentionTime_) { + break; } - ++bucket->CurrentExecutions; + YT_LOG_TRACE("Destroing pool (PoolName: %v)", frontPool->PoolName); - threadState.Bucket = bucket; - threadState.AccountedAt = currentInstant; + auto poolIt = PoolMapping_.find(frontPool->PoolName); + YT_ASSERT(poolIt != PoolMapping_.end() && poolIt->second == frontPool); + PoolMapping_.erase(poolIt); - action->StartedAt = currentInstant; - bucket->WaitTime = action->StartedAt - action->EnqueuedAt; + RetainPoolQueue_.PopFront(); + poolsToRemove.PushBack(frontPool); } - // Microoptimization: avoid calling CpuDurationToDuration if no observers are registered. - if (!WaitTimeObservers_.IsEmpty()) { - WaitTimeObservers_.Fire(CpuDurationToDuration(action->StartedAt - action->EnqueuedAt)); + return poolsToRemove; + } + + void MaybeProceedRetainQueue(TCpuInstant currentInstant) + { + if (!MappingLock_.TryAcquire()) { + return; } - YT_ASSERT(action && !action->Finished); + auto finally = Finally([&] { + MappingLock_.Release(); + }); - { - auto guard = Guard(SpinLock_); - auto& pool = IdToPool_[bucket->PoolId]; + auto poolsToRemove = ProceedRetainQueue(currentInstant); + MappingLock_.Release(); + finally.Release(); - pool->WaitTimeCounter.Record(CpuDurationToDuration(bucket->WaitTime)); + while (poolsToRemove.GetSize() > 0) { + auto* frontPool = poolsToRemove.GetFront(); + poolsToRemove.PopFront(); + NYT::DestroyRefCounted(frontPool); } + } - return true; +private: + const TDuration PoolRetentionTime_; + + YT_DECLARE_SPIN_LOCK(NThreading::TSpinLock, MappingLock_); + THashMap, TBucket*> BucketMapping_; + THashMap PoolMapping_; + + TPoolQueue RetainPoolQueue_; +}; + +DEFINE_REFCOUNTED_TYPE(TBucketMapping) + +//////////////////////////////////////////////////////////////////////////////// + +void TBucket::Invoke(TClosure callback) +{ + Parent_->Invoke(std::move(callback), this); +} + +TBucket::~TBucket() +{ + Parent_->RemoveBucket(this); +} + +//////////////////////////////////////////////////////////////////////////////// + +DEFINE_ENUM(ERequest, + (None) + (EndExecute) + (FetchNext) +); + +class TTwoLevelFairShareQueue + : protected TNotifyManager + , public TBucketMapping +{ +public: + using TWaitTimeObserver = ITwoLevelFairShareThreadPool::TWaitTimeObserver; + + TTwoLevelFairShareQueue( + TIntrusivePtr callbackEventCount, + const TString& threadNamePrefix, + const TNewTwoLevelFairShareThreadPoolOptions& options) + : TNotifyManager(std::move(callbackEventCount), GetThreadTags(threadNamePrefix), options.PollingPeriod) + , TBucketMapping(options.PoolRetentionTime) + , ThreadNamePrefix_(threadNamePrefix) + , Profiler_(TProfiler{"/fair_share_queue"} + .WithHot()) + , CumulativeSchedulingTimeCounter_(Profiler_ + .WithTags(GetThreadTags(ThreadNamePrefix_)) + .TimeCounter("/time/scheduling_cumulative")) + , PoolWeightProvider_(options.PoolWeightProvider) + , VerboseLogging_(options.VerboseLogging) + { } + + ~TTwoLevelFairShareQueue() + { + Shutdown(); } - void EndExecute(TEnqueuedAction* action, int index) + void Configure(int threadCount) { - auto& threadState = ThreadStates_[index]; - if (!threadState.Bucket) { + ThreadCount_.store(threadCount); + } + + void Configure(TDuration pollingPeriod) + { + TNotifyManager::SetPollingPeriod(pollingPeriod); + } + + // (arkady-e1ppa): Explanation of memory orders and fences around Stopped_: + /* + We have two concurrent actions: Invoke and Shutdown. + For our logic Invoke method does 2 things: + 1) It pushes callback to the queue (we assume it be release RMW operation) + In reality right now it is seq_cst, but it this can and should be changed in the future. + 2) Now, the second (and third) action is seq_cst fence and then seq_cst read of Stopped_. + Shutdown also does two thigns: + 1) It does a seq_cst rmw in Stopped_ (effectively, just write) + 2) It drains the queue. + In order to prevent losing callbacks in queue + We need to make sure that either Invoke observes |true| in the read + or Shutdown observes placed callback from said Invoke. + We care about this, because if callback is stuck in queue it will + remain there until process is killed. If said callback MUST be + either executed or discarded (e.g. IPollable or Fiber) in order + for program to finish correctly (an not get stuck), then such a leak + can cause hung shutdown (and it used to do exactly that). + + Relevant parts of execution are written below + (letter is the same in the code). + T1(Invoke) T2(Shutdown) + RMW^rel(Queue, 0, 1) (a) RMW^rlx(Stopping, false, true) (d) + Fence^sc (b) Fence^sc (e) + R^rlx(Stopping, false) (c) RMW^acq(Queue, 0, 0) (f) + + We suppose that callback is lost so we haven't + seen 1 in (f) nor true in (c). + Since (c) reads false it reads from ctor which precedes + (d) in modification order. Thus we have (c) -cob-> (d) + (coherence-ordered before, https://eel.is/c++draft/atomics.order#3.3). + Likewise (f) must have read from some previous + dequeue attempt (or ctor) which precedes (a) in modification order. + Again, (f) -cob-> (a). + Now, for fences we have (sb means sequenced-before): + (b) -sb-> (c) -cob-> (d) -sb-> (e) => (b) -S-> (e) + (see https://eel.is/c++draft/atomics.order#4.4). + We also have + (e) -sb-> (f) -cob-> (a) -sb-> (b) => (b) -S-> (e). + Thus loop in S found contradicting the assumption + that (f) doesn't read 1 and (c) doesn't read true. + */ + + // Invoke is lock free on a fast path (a.k.a. no shutdown). + void Invoke(TClosure callback, TBucket* bucket) override + { + // We can't guarantee read of |true| in time anyway + // So relaxed order is enough. + if (Stopped_.load(std::memory_order::relaxed)) { + Drain(); return; } - YT_ASSERT(action); + auto cpuInstant = GetCpuInstant(); - if (action->Finished) { - return; + YT_LOG_TRACE("Invoking action (EnqueuedAt: %v, Invoker: %v)", + cpuInstant, + ThreadNamePrefix_); + + TAction action; + action.EnqueuedAt = cpuInstant; + // Callback keeps raw ptr to bucket to minimize bucket ref count. + action.Callback = BIND(&TBucket::RunCallback, Unretained(bucket), std::move(callback), cpuInstant); + action.BucketHolder = MakeStrong(bucket); + action.EnqueuedThreadCookie = ThreadCookie(); + + InvokeQueue_.Enqueue(std::move(action)); // <- (a) + + std::atomic_thread_fence(std::memory_order::seq_cst); // <- (b) + if (Stopped_.load(std::memory_order::relaxed)) { // <- (c) + // We have encountered stop right after we have enqueued + // callback. There is a possibility that it is now stuck + // in queue forever. We dequeue it ourselves. + Drain(); } - auto currentInstant = GetCpuInstant(); + NotifyFromInvoke(cpuInstant, ActiveThreads_.load() == 0); + } + + void StopPrologue() + { + GetEventCount()->NotifyAll(); + } - action->FinishedAt = currentInstant; + TClosure OnExecute(int index, bool fetchNext, std::function isStopping) + { + while (true) { + auto cookie = GetEventCount()->PrepareWait(); - auto timeFromStart = CpuDurationToDuration(action->FinishedAt - action->StartedAt); - auto timeFromEnqueue = CpuDurationToDuration(action->FinishedAt - action->EnqueuedAt); + auto& threadState = ThreadStates_[index]; - { - auto guard = Guard(SpinLock_); - const auto& pool = IdToPool_[threadState.Bucket->PoolId]; - pool->SizeCounter.Record(--pool->Size); - pool->ExecTimeCounter.Record(timeFromStart); - pool->TotalTimeCounter.Record(timeFromEnqueue); + auto hasAction = threadState.Action.BucketHolder; + int activeThreadDelta = hasAction ? -1 : 0; + + auto callback = DoOnExecute(index, fetchNext); + + if (callback) { + activeThreadDelta += 1; + } + + YT_VERIFY(activeThreadDelta >= -1 && activeThreadDelta <= 1); + + if (activeThreadDelta != 0) { + auto activeThreads = ActiveThreads_.fetch_add(activeThreadDelta); + auto newActiveThreads = activeThreads + activeThreadDelta; + YT_VERIFY(newActiveThreads >= 0 && newActiveThreads <= TThreadPoolBase::MaxThreadCount); + activeThreadDelta = 0; + } + + if (callback || isStopping()) { + CancelWait(); + return callback; + } + + YT_VERIFY(fetchNext); + MaybeRunMaintenance(&threadState, GetCpuInstant(), /*flush*/ true); + Wait(cookie, isStopping); } + } - if (timeFromStart > LogDurationThreshold) { - YT_LOG_DEBUG("Callback execution took too long (Wait: %v, Execution: %v, Total: %v)", - CpuDurationToDuration(action->StartedAt - action->EnqueuedAt), - timeFromStart, - timeFromEnqueue); + void Shutdown() + { + if (Stopped_.exchange(true, std::memory_order::relaxed)) { // <- (d) + return; } + std::atomic_thread_fence(std::memory_order::seq_cst); // <- (e) - auto waitTime = CpuDurationToDuration(action->StartedAt - action->EnqueuedAt); + Drain(); // <- (f) + } - if (waitTime > LogDurationThreshold) { - YT_LOG_DEBUG("Callback wait took too long (Wait: %v, Execution: %v, Total: %v)", - waitTime, - timeFromStart, - timeFromEnqueue); + void Drain() + { + auto guard = Guard(MainLock_); + + WaitHeap_.Clear(); + + std::vector buckets; + ActivePoolsHeap_.ForEach([&] (auto* pool) { + pool->ActiveBucketsHeap.ForEach([&] (auto* bucket) { + buckets.push_back(bucket); + }); + pool->ActiveBucketsHeap.Clear(); + }); + ActivePoolsHeap_.Clear(); + + // Actions hold strong references to buckets. + // Buckets' ActionQueue must be cleared before destroying actions. + std::vector actions; + for (auto* bucket : buckets) { + while (!bucket->ActionQueue.empty()) { + actions.push_back(std::move(bucket->ActionQueue.front())); + bucket->ActionQueue.pop(); + } } - action->Finished = true; + InvokeQueue_.DequeueAll(); - // Remove outside lock because of lock inside RemoveBucket. - TBucketPtr bucket; - { - auto guard = Guard(SpinLock_); - bucket = std::move(threadState.Bucket); - - UpdateExcessTime(bucket.Get(), currentInstant - threadState.AccountedAt); - threadState.AccountedAt = currentInstant; + guard.Release(); + actions.clear(); - YT_VERIFY(bucket->CurrentExecutions-- > 0); - } } void SubscribeWaitTimeObserved(const TWaitTimeObserver& callback) @@ -407,205 +803,459 @@ class TTwoLevelFairShareQueue private: struct TThreadState { + std::atomic Request = ERequest::None; + TCpuInstant AccountedAt = 0; - TBucketPtr Bucket; + TAction Action; + + // Used to store bucket ref under lock to destroy it outside. + TBucketPtr BucketToUnref; + int LastActionsInQueue; + TDuration TimeFromStart; + TDuration TimeFromEnqueue; + TCpuInstant LastMaintenanceInstant = {}; }; - struct TExecutionPool + static_assert(sizeof(TThreadState) >= CacheLineSize); + + const TString ThreadNamePrefix_; + const TProfiler Profiler_; + const NProfiling::TTimeCounter CumulativeSchedulingTimeCounter_; + const IPoolWeightProviderPtr PoolWeightProvider_; + const bool VerboseLogging_; + + std::atomic Stopped_ = false; + TMpscStack InvokeQueue_; + char Padding0_[CacheLineSize - sizeof(TMpscStack)]; + + // Use simple non adaptive spinlock without complex wait strategies. + ::TSpinLock MainLock_; + char Padding1_[CacheLineSize - sizeof(::TSpinLock)]; + + std::array ThreadStates_; + + TPriorityQueue ActivePoolsHeap_; + TCpuDuration LastPoolExcessTime_ = 0; + TPriorityQueue WaitHeap_; + + // Buffer to keep actions during distribution to threads. + std::array OtherActions_; + std::atomic ThreadCount_ = 0; + std::atomic ActiveThreads_ = 0; + + TCallbackList WaitTimeObservers_; + + TProfiler GetPoolProfiler(const TString& poolName) override { - TExecutionPool(const TString& poolName, const TProfiler& profiler) - : PoolName(poolName) - , BucketCounter(profiler.Gauge("/buckets")) - , SizeCounter(profiler.Summary("/size")) - , WaitTimeCounter(profiler.Timer("/time/wait")) - , ExecTimeCounter(profiler.Timer("/time/exec")) - , TotalTimeCounter(profiler.Timer("/time/total")) - { } + return Profiler_.WithTags(GetBucketTags(ThreadNamePrefix_, poolName)); + } - TBucketPtr GetStarvingBucket(TEnqueuedAction* action) - { - if (!Heap.empty()) { - auto bucket = Heap.front().Bucket; - YT_VERIFY(!bucket->Queue.empty()); - *action = std::move(bucket->Queue.front()); - bucket->Queue.pop(); - - if (bucket->Queue.empty()) { - ExtractHeap(Heap.begin(), Heap.end()); - Heap.pop_back(); - } + Y_NO_INLINE void ConsumeInvokeQueue() + { + YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - return bucket; - } + Y_UNUSED(Padding0_); + Y_UNUSED(Padding1_); - return nullptr; - } + InvokeQueue_.DequeueAll(true, [&] (auto& action) { + auto* bucket = action.BucketHolder.Get(); - const TString PoolName; + auto* pool = bucket->Pool.Get(); - TGauge BucketCounter; - std::atomic Size = 0; - NProfiling::TSummary SizeCounter; - TEventTimer WaitTimeCounter; - TEventTimer ExecTimeCounter; - TEventTimer TotalTimeCounter; + YT_VERIFY(!pool->LinkedListNode.Next && !pool->LinkedListNode.Prev); - double Weight = 1.0; + if (!pool->GetPositionInHeap()) { + // ExcessTime can be greater than last pool excess time + // if the pool is "currently executed" and reschedules action. + if (pool->ExcessTime < LastPoolExcessTime_) { + // Use last pool excess time to schedule new pool + // after earlier scheduled pools (and not yet executed) in queue. - TCpuDuration ExcessTime = 0; - std::vector Heap; - THashMap TagToBucket; - }; + YT_LOG_DEBUG_IF(VerboseLogging_, "Initial pool excess time (Name: %v, ExcessTime: %v -> %v)", + pool->PoolName, + pool->ExcessTime, + LastPoolExcessTime_); - const TIntrusivePtr CallbackEventCount_; - const TString ThreadNamePrefix_; - const TProfiler Profiler_; - const IPoolWeightProviderPtr PoolWeightProvider_; + pool->ExcessTime = LastPoolExcessTime_; + } - YT_DECLARE_SPIN_LOCK(NThreading::TSpinLock, SpinLock_); - // NB: We set this flag to true so that whomever may spam tasks to queue - // will stop doing so after the shutdown. - bool Stopping_ = false; - std::vector> IdToPool_; - THashMap NameToPoolId_; + ActivePoolsHeap_.Insert(pool); + } - std::atomic ThreadCount_ = 0; - std::array ThreadStates_; + ++pool->ActionCountInQueue; - TCallbackList WaitTimeObservers_; + auto enqueuedAt = action.EnqueuedAt; + bool wasEmpty = bucket->ActionQueue.empty(); + bucket->ActionQueue.push(std::move(action)); - size_t GetLowestEmptyPoolId() - { - YT_ASSERT_SPINLOCK_AFFINITY(SpinLock_); + if (wasEmpty) { + bucket->EnqueuedTime.Value = enqueuedAt; + } - size_t id = 0; - while (id < IdToPool_.size() && IdToPool_[id]) { - ++id; - } - return id; + YT_ASSERT(wasEmpty == !bucket->GetPositionInHeap()); + + if (!bucket->GetPositionInHeap()) { + // ExcessTime can be greater than last bucket excess time + // if the bucket is "currently executed" and reschedules action. + if (bucket->ExcessTime < pool->LastBucketExcessTime) { + // Use last bucket excess time to schedule new bucket + // after earlier scheduled buckets (and not yet executed) in queue. + + YT_LOG_DEBUG_IF(VerboseLogging_, "Initial bucket excess time (Name: %v, ExcessTime: %v -> %v)", + bucket->BucketName, + bucket->ExcessTime, + pool->LastBucketExcessTime); + + bucket->ExcessTime = pool->LastBucketExcessTime; + } + + pool->ActiveBucketsHeap.Insert(bucket); + pool->BucketCounter.Record(pool->ActiveBucketsHeap.GetSize()); + WaitHeap_.Insert(&bucket->EnqueuedTime); + } + }); } - void AccountCurrentlyExecutingBuckets() + void ServeBeginExecute(TThreadState* threadState, TCpuInstant currentInstant, TAction action) { - YT_ASSERT_SPINLOCK_AFFINITY(SpinLock_); + YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - auto currentInstant = GetCpuInstant(); - auto threadCount = ThreadCount_.load(); - for (int index = 0; index < threadCount; ++index) { - auto& threadState = ThreadStates_[index]; - if (!threadState.Bucket) { - continue; - } + YT_ASSERT(!threadState->Action.Callback); + YT_ASSERT(!threadState->Action.BucketHolder); - auto duration = currentInstant - threadState.AccountedAt; - threadState.AccountedAt = currentInstant; + action.StartedAt = currentInstant; - UpdateExcessTime(threadState.Bucket.Get(), duration); - } + threadState->AccountedAt = currentInstant; + threadState->Action = std::move(action); } - void UpdateExcessTime(TBucket* bucket, TCpuDuration duration) + void ServeEndExecute(TThreadState* threadState, TCpuInstant /*cpuInstant*/) { - YT_ASSERT_SPINLOCK_AFFINITY(SpinLock_); - - const auto& pool = IdToPool_[bucket->PoolId]; + YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - pool->ExcessTime += duration / pool->Weight; - bucket->ExcessTime += duration; + auto action = std::move(threadState->Action); + YT_ASSERT(!threadState->Action.Callback); + YT_ASSERT(!action.Callback); - auto positionInHeap = bucket->HeapIterator; - if (!positionInHeap) { + if (!action.BucketHolder) { + // There was no action in begin execute. return; } - size_t indexInHeap = positionInHeap - pool->Heap.data(); - YT_VERIFY(indexInHeap < pool->Heap.size()); - SiftDown(pool->Heap.begin(), pool->Heap.end(), pool->Heap.begin() + indexInHeap, std::less<>()); + // Try not to change bucket ref count under lock. + auto bucket = std::move(action.BucketHolder); + + auto& pool = *bucket->Pool; + YT_ASSERT(pool.PoolName == bucket->PoolName); + + // LastActionsInQueue is used to update SizeCounter outside lock. + threadState->LastActionsInQueue = --pool.ActionCountInQueue; + + // Do not destroy bucket pointer under lock. Move it in thread state in other place and + // destroy in corresponding thread after combiner. + threadState->BucketToUnref = std::move(bucket); } - TBucketPtr GetStarvingBucket(TEnqueuedAction* action) + Y_NO_INLINE void UpdateExcessTime(TBucket* bucket, TCpuDuration duration, TCpuInstant currentInstant) { - YT_ASSERT_SPINLOCK_AFFINITY(SpinLock_); + YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); - // For each currently evaluating buckets recalculate excess time. - AccountCurrentlyExecutingBuckets(); + auto* pool = bucket->Pool.Get(); - // Compute min excess over non-empty queues. - auto minExcessTime = std::numeric_limits::max(); + if (PoolWeightProvider_ && pool->NextUpdateWeightInstant < currentInstant) { + pool->NextUpdateWeightInstant = currentInstant + DurationToCpuDuration(TDuration::Seconds(1)); + pool->InverseWeight = 1.0 / PoolWeightProvider_->GetWeight(pool->PoolName); + } - int minPoolIndex = -1; - for (int index = 0; index < std::ssize(IdToPool_); ++index) { - const auto& pool = IdToPool_[index]; - if (pool && !pool->Heap.empty() && pool->ExcessTime < minExcessTime) { - minExcessTime = pool->ExcessTime; - minPoolIndex = index; - } + YT_LOG_DEBUG_IF(VerboseLogging_, "Increment excess time (BucketName: %v, PoolName: %v, ExcessTime: %v -> %v)", + bucket->BucketName, + bucket->PoolName, + bucket->ExcessTime, + bucket->ExcessTime + duration); + + pool->ExcessTime += duration * pool->InverseWeight; + bucket->ExcessTime += duration; + + if (auto* positionInHeap = pool->GetPositionInHeap()) { + ActivePoolsHeap_.AdjustDown(pool); + } + + if (auto* positionInHeap = bucket->GetPositionInHeap()) { + pool->ActiveBucketsHeap.AdjustDown(bucket); } - YT_LOG_TRACE( + // No need to update wait heap. + YT_ASSERT(!bucket->EnqueuedTime.GetPositionInHeap() == !bucket->GetPositionInHeap()); + } + + Y_NO_INLINE bool GetStarvingBucket(TAction* action) + { + YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); + + YT_LOG_DEBUG_IF( + VerboseLogging_, "Buckets: %v", MakeFormattableView( - xrange(size_t(0), IdToPool_.size()), + xrange(size_t(0), ActivePoolsHeap_.GetSize()), [&] (auto* builder, auto index) { - const auto& pool = IdToPool_[index]; - if (!pool) { - builder->AppendString(""); - return; - } - builder->AppendFormat("[%v %v ", index, pool->ExcessTime); - for (const auto& [tagId, rawBucket] : pool->TagToBucket) { - if (auto bucket = DangerousGetPtr(rawBucket)) { - auto excess = CpuDurationToDuration(bucket->ExcessTime).MilliSeconds(); - builder->AppendFormat("(%v %v) ", tagId, excess); - } else { - builder->AppendFormat("(%v ?) ", tagId); - } + auto& pool = ActivePoolsHeap_[index]; + builder->AppendFormat("%v [", CpuDurationToDuration(pool.ExcessTime)); + + for (size_t bucketIndex = 0; bucketIndex < pool.ActiveBucketsHeap.GetSize(); ++bucketIndex) { + const auto& bucket = pool.ActiveBucketsHeap[bucketIndex]; + + builder->AppendFormat("%Qv:%v/%v ", + bucket.BucketName, + CpuDurationToDuration(bucket.ExcessTime), + bucket.ActionQueue.front().EnqueuedAt); } builder->AppendFormat("]"); })); - if (minPoolIndex >= 0) { - // Reduce excesses (with truncation). - auto delta = IdToPool_[minPoolIndex]->ExcessTime; - for (const auto& pool : IdToPool_) { - if (pool) { - pool->ExcessTime = std::max(pool->ExcessTime - delta, 0); - } + if (ActivePoolsHeap_.Empty()) { + return false; + } + + auto* pool = ActivePoolsHeap_.GetFront(); + LastPoolExcessTime_ = pool->ExcessTime; + + auto* bucket = pool->ActiveBucketsHeap.GetFront(); + pool->LastBucketExcessTime = bucket->ExcessTime; + + YT_ASSERT(!bucket->ActionQueue.empty()); + *action = std::move(bucket->ActionQueue.front()); + bucket->ActionQueue.pop(); + + YT_ASSERT(bucket == action->BucketHolder); + + if (bucket->ActionQueue.empty()) { + bucket->EnqueuedTime.Value = std::numeric_limits::max(); + + WaitHeap_.Extract(&bucket->EnqueuedTime); + + pool->ActiveBucketsHeap.Extract(bucket); + pool->BucketCounter.Record(pool->ActiveBucketsHeap.GetSize()); + + if (pool->ActiveBucketsHeap.Empty()) { + ActivePoolsHeap_.Extract(pool); } - return IdToPool_[minPoolIndex]->GetStarvingBucket(action); + } else { + bucket->EnqueuedTime.Value = bucket->ActionQueue.front().EnqueuedAt; + WaitHeap_.AdjustDown(&bucket->EnqueuedTime); } - return nullptr; + return true; } -}; -DEFINE_REFCOUNTED_TYPE(TTwoLevelFairShareQueue) + Y_NO_INLINE std::tuple ServeCombinedRequests(TCpuInstant currentInstant, int currentThreadIndex) + { + YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); -//////////////////////////////////////////////////////////////////////////////// + auto threadCount = ThreadCount_.load(); + // Thread pool size can be reconfigures during serving requests. + threadCount = std::max(threadCount, currentThreadIndex + 1); -void TBucket::Invoke(TClosure callback) -{ - if (auto parent = Parent.Lock()) { - parent->Invoke(std::move(callback), this); + // Saved thread requests. They must be saved before consuming invoke queue. + std::array threadRequests{false}; + std::array threadIds; + int requestCount = 0; + + YT_LOG_TRACE("Updating excess time"); + + // Recalculate excess time for all currently evaluating or evaluated recently (end execute) buckets + for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex) { + auto& threadState = ThreadStates_[threadIndex]; + + // TODO(lukyan): Can skip (for threads without requests) or throttle UpdateExcessTime if it happens frequently. + // For each currently evaluating buckets recalculate excess time. + if (auto* bucket = threadState.Action.BucketHolder.Get()) { + + // TODO(lukyan): Update last excess time for pool without active buckets. + UpdateExcessTime(bucket, currentInstant - threadState.AccountedAt, currentInstant); + threadState.AccountedAt = currentInstant; + } + + auto request = threadState.Request.load(std::memory_order::acquire); + if (request != ERequest::None) { + ServeEndExecute(&threadState, currentInstant); + + if (request == ERequest::FetchNext) { + // Save requests before ConsumeInvokeQueue. Otherwise some thread can schedule action + // but action can not be fetched (schedule and fetch happens after ConsumeInvokeQueue). + threadRequests[threadIndex] = true; + threadIds[requestCount++] = threadIndex; + } else { + threadState.Request.store(ERequest::None, std::memory_order::release); + } + } + } + + YT_LOG_TRACE("Consuming invoke queue"); + + ConsumeInvokeQueue(); + + int fetchedActions = 0; + int otherActionCount = 0; + + // Schedule actions to desired threads. + while (fetchedActions < requestCount) { + TAction action; + + if (!GetStarvingBucket(&action)) { + break; + } + + ++fetchedActions; + + int threadIndex = -1; + + auto unpackedCookie = TTaggedPtr::Unpack(action.EnqueuedThreadCookie); + // TODO(lukyan): Check also wait time. If it is too high, no matter where to schedule. + if (unpackedCookie.Ptr == this) { + threadIndex = unpackedCookie.Tag; + } + + if (threadIndex != -1 && threadRequests[threadIndex]) { + ServeBeginExecute(&ThreadStates_[threadIndex], currentInstant, std::move(action)); + threadRequests[threadIndex] = false; + ThreadStates_[threadIndex].Request.store(ERequest::None, std::memory_order::release); + } else { + OtherActions_[otherActionCount++] = std::move(action); + } + } + + // Schedule other actions. + for (int threadIndex : TRange(threadIds.data(), requestCount)) { + if (threadRequests[threadIndex]) { + if (otherActionCount > 0) { + ServeBeginExecute(&ThreadStates_[threadIndex], currentInstant, std::move(OtherActions_[--otherActionCount])); + } + + ThreadStates_[threadIndex].Request.store(ERequest::None, std::memory_order::release); + } + } + + return {requestCount, fetchedActions}; } -} -void TBucket::Invoke(TMutableRange callbacks) -{ - if (auto parent = Parent.Lock()) { - for (auto& callback : callbacks) { - parent->Invoke(std::move(callback), this); + TCpuInstant GetMinEnqueuedAt() + { + YT_ASSERT_SPINLOCK_AFFINITY(MainLock_); + + return WaitHeap_.Empty() + ? std::numeric_limits::max() + : WaitHeap_.GetFront()->Value; + } + + TClosure DoOnExecute(int index, bool fetchNext) + { + auto cpuInstant = GetCpuInstant(); + auto& threadState = ThreadStates_[index]; + + const auto& oldAction = threadState.Action; + if (oldAction.BucketHolder) { + auto waitTime = CpuDurationToDuration(oldAction.StartedAt - oldAction.EnqueuedAt); + auto timeFromStart = CpuDurationToDuration(cpuInstant - oldAction.StartedAt); + auto timeFromEnqueue = CpuDurationToDuration(cpuInstant - oldAction.EnqueuedAt); + + threadState.TimeFromStart = timeFromStart; + threadState.TimeFromEnqueue = timeFromEnqueue; + + if (timeFromStart > LogDurationThreshold) { + YT_LOG_DEBUG("Callback execution took too long (Wait: %v, Execution: %v, Total: %v)", + waitTime, + timeFromStart, + timeFromEnqueue); + } + + if (waitTime > LogDurationThreshold) { + YT_LOG_DEBUG("Callback wait took too long (Wait: %v, Execution: %v, Total: %v)", + waitTime, + timeFromStart, + timeFromEnqueue); + } } + + auto finally = Finally([&] { + auto bucketToUndef = std::move(threadState.BucketToUnref); + if (bucketToUndef) { + auto* pool = bucketToUndef->Pool.Get(); + pool->SizeCounter.Record(threadState.LastActionsInQueue); + pool->DequeuedCounter.Increment(1); + pool->ExecTimeCounter.Record(threadState.TimeFromStart); + pool->TotalTimeCounter.Record(threadState.TimeFromEnqueue); + pool->CumulativeTimeCounter.Add(threadState.TimeFromStart); + bucketToUndef.Reset(); + } + + const auto& action = threadState.Action; + if (action.BucketHolder) { + auto waitTime = CpuDurationToDuration(action.StartedAt - action.EnqueuedAt); + action.BucketHolder->Pool->WaitTimeCounter.Record(waitTime); + WaitTimeObservers_.Fire(waitTime); + } + + MaybeRunMaintenance(&threadState, action.StartedAt, /*flush*/ false); + + CumulativeSchedulingTimeCounter_.Add(CpuDurationToDuration(GetCpuInstant() - cpuInstant)); + + if (!fetchNext) { + MaybeProceedRetainQueue(cpuInstant); + } + }); + + auto& request = threadState.Request; + YT_VERIFY(request == ERequest::None); + request.store(fetchNext ? ERequest::FetchNext : ERequest::EndExecute); + + if (MainLock_.IsLocked() || !MainLock_.TryAcquire()) { + // Locked here. + while (true) { + SpinLockPause(); + + if (request.load(std::memory_order::acquire) == ERequest::None) { + return std::move(threadState.Action.Callback); + } else if (!MainLock_.IsLocked() && MainLock_.TryAcquire()) { + break; + } + } + } + + ResetMinEnqueuedAt(); + + YT_LOG_TRACE("Started serving requests"); + auto [requests, fetchedActions] = ServeCombinedRequests(cpuInstant, index); + + // Evaluate notify condition here, but call NotifyAfterFetch outside lock. + auto newMinEnqueuedAt = GetMinEnqueuedAt(); + MainLock_.Release(); + + auto endInstant = GetCpuInstant(); + YT_LOG_TRACE("Finished serving requests (Duration: %v, Requests: %v, FetchCount: %v, MinEnqueuedAt: %v)", + CpuDurationToDuration(endInstant - cpuInstant), + requests, + fetchedActions, + CpuInstantToInstant(newMinEnqueuedAt)); + + NotifyAfterFetch(endInstant, newMinEnqueuedAt); + + return std::move(threadState.Action.Callback); } -} -TBucket::~TBucket() -{ - if (auto parent = Parent.Lock()) { - parent->RemoveBucket(this); + static void MaybeRunMaintenance(TThreadState* threadState, TCpuInstant now, bool flush) + { + YT_ASSERT(threadState); + + constexpr i64 MaintenancePeriod = 1'000'000'000; + if (flush || now > threadState->LastMaintenanceInstant + MaintenancePeriod) { + ReclaimHazardPointers(false); + threadState->LastMaintenanceInstant = now; + } } -} +}; + +DEFINE_REFCOUNTED_TYPE(TTwoLevelFairShareQueue) //////////////////////////////////////////////////////////////////////////////// @@ -631,16 +1281,33 @@ class TFairShareThread const TTwoLevelFairShareQueuePtr Queue_; const int Index_; - TEnqueuedAction CurrentAction_; + void OnStart() override + { + ThreadCookie() = TTaggedPtr(Queue_.Get(), static_cast(Index_)).Pack(); + } + + void StopPrologue() override + { + Queue_->StopPrologue(); + } + + TClosure OnExecute() override + { + bool fetchNext = !TSchedulerThread::IsStopping() || TSchedulerThread::GracefulStop_; + + return Queue_->OnExecute(Index_, fetchNext, [&] { + return TSchedulerThread::IsStopping(); + }); + } TClosure BeginExecute() override { - return BeginExecuteImpl(Queue_->BeginExecute(&CurrentAction_, Index_), &CurrentAction_); + Y_UNREACHABLE(); } void EndExecute() override { - Queue_->EndExecute(&CurrentAction_, Index_); + Y_UNREACHABLE(); } }; @@ -656,15 +1323,14 @@ class TTwoLevelFairShareThreadPool TTwoLevelFairShareThreadPool( int threadCount, const TString& threadNamePrefix, - IPoolWeightProviderPtr poolWeightProvider) + const TNewTwoLevelFairShareThreadPoolOptions& options) : TThreadPoolBase(threadNamePrefix) , Queue_(New( CallbackEventCount_, ThreadNamePrefix_, - std::move(poolWeightProvider))) + options)) { SetThreadCount(threadCount); - EnsureStarted(); } ~TTwoLevelFairShareThreadPool() @@ -677,20 +1343,17 @@ class TTwoLevelFairShareThreadPool TThreadPoolBase::SetThreadCount(threadCount); } - void SetPollingPeriod(TDuration /*pollingPeriod*/) override - { } - - int GetThreadCount() override + void SetPollingPeriod(TDuration pollingPeriod) override { - return TThreadPoolBase::GetThreadCount(); + Queue_->Configure(pollingPeriod); } IInvokerPtr GetInvoker( const TString& poolName, - const TFairShareThreadPoolTag& tag) override + const TFairShareThreadPoolTag& bucketName) override { EnsureStarted(); - return Queue_->GetInvoker(poolName, tag); + return Queue_->GetInvoker(poolName, bucketName); } void Shutdown() override @@ -698,6 +1361,11 @@ class TTwoLevelFairShareThreadPool TThreadPoolBase::Shutdown(); } + int GetThreadCount() override + { + return TThreadPoolBase::GetThreadCount(); + } + void SubscribeWaitTimeObserved(const TWaitTimeObserver& callback) override { Queue_->SubscribeWaitTimeObserved(callback); @@ -712,11 +1380,11 @@ class TTwoLevelFairShareThreadPool const TIntrusivePtr CallbackEventCount_ = New(); const TTwoLevelFairShareQueuePtr Queue_; - void DoShutdown() override { Queue_->Shutdown(); TThreadPoolBase::DoShutdown(); + Queue_->Drain(); } void DoSetThreadCount(int threadCount) override @@ -743,12 +1411,12 @@ class TTwoLevelFairShareThreadPool ITwoLevelFairShareThreadPoolPtr CreateTwoLevelFairShareThreadPool( int threadCount, const TString& threadNamePrefix, - IPoolWeightProviderPtr poolWeightProvider) + const TNewTwoLevelFairShareThreadPoolOptions& options) { return New( threadCount, threadNamePrefix, - std::move(poolWeightProvider)); + options); } //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/concurrency/two_level_fair_share_thread_pool.h b/yt/yt/core/concurrency/two_level_fair_share_thread_pool.h index 57d616391b58..611b9e7219e6 100644 --- a/yt/yt/core/concurrency/two_level_fair_share_thread_pool.h +++ b/yt/yt/core/concurrency/two_level_fair_share_thread_pool.h @@ -40,11 +40,22 @@ struct ITwoLevelFairShareThreadPool DEFINE_REFCOUNTED_TYPE(ITwoLevelFairShareThreadPool) +//////////////////////////////////////////////////////////////////////////////// + +struct TNewTwoLevelFairShareThreadPoolOptions +{ + IPoolWeightProviderPtr PoolWeightProvider = nullptr; + bool VerboseLogging = false; + TDuration PollingPeriod = TDuration::MilliSeconds(10); + TDuration PoolRetentionTime = TDuration::Seconds(30); +}; + +//////////////////////////////////////////////////////////////////////////////// + ITwoLevelFairShareThreadPoolPtr CreateTwoLevelFairShareThreadPool( int threadCount, const TString& threadNamePrefix, - IPoolWeightProviderPtr poolWeightProvider = nullptr); + const TNewTwoLevelFairShareThreadPoolOptions& options = {}); -//////////////////////////////////////////////////////////////////////////////// } // namespace NYT::NConcurrency diff --git a/yt/yt/core/concurrency/unittests/scheduler_ut.cpp b/yt/yt/core/concurrency/unittests/scheduler_ut.cpp index 445b98543a83..22ca6eb90fac 100644 --- a/yt/yt/core/concurrency/unittests/scheduler_ut.cpp +++ b/yt/yt/core/concurrency/unittests/scheduler_ut.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include @@ -1268,7 +1267,7 @@ TEST_P(TFairShareSchedulerTest, TwoLevelFairness) YT_VERIFY(numWorkers > numPools); YT_VERIFY(numThreads <= numWorkers); - auto threadPool = CreateNewTwoLevelFairShareThreadPool( + auto threadPool = CreateTwoLevelFairShareThreadPool( numThreads, "MyFairSharePool", { diff --git a/yt/yt/core/concurrency/unittests/two_level_fair_share_thread_pool_ut.cpp b/yt/yt/core/concurrency/unittests/two_level_fair_share_thread_pool_ut.cpp index c155f00fb893..97a0dbbe83a9 100644 --- a/yt/yt/core/concurrency/unittests/two_level_fair_share_thread_pool_ut.cpp +++ b/yt/yt/core/concurrency/unittests/two_level_fair_share_thread_pool_ut.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include @@ -15,7 +14,7 @@ namespace { TEST(TTwoLevelFairShareThreadPoolTest, Configure) { - auto threadPool = CreateNewTwoLevelFairShareThreadPool(1, "Test"); + auto threadPool = CreateTwoLevelFairShareThreadPool(1, "Test"); auto counter = std::make_shared>(); auto callback = BIND([=] { ++*counter; }); std::vector> futures; diff --git a/yt/yt/core/misc/ref_counted_tracker.h b/yt/yt/core/misc/ref_counted_tracker.h index 0a3a0de8a443..6cd482da9b7f 100644 --- a/yt/yt/core/misc/ref_counted_tracker.h +++ b/yt/yt/core/misc/ref_counted_tracker.h @@ -13,7 +13,7 @@ namespace NYT { //////////////////////////////////////////////////////////////////////////////// -struct TRefCountedTrackerStatistics +struct TRefCountedTrackerStatistics final { struct TStatistics { diff --git a/yt/yt/core/misc/ref_counted_tracker_statistics_producer.cpp b/yt/yt/core/misc/ref_counted_tracker_statistics_producer.cpp index e6b32125065a..8330e63c5f79 100644 --- a/yt/yt/core/misc/ref_counted_tracker_statistics_producer.cpp +++ b/yt/yt/core/misc/ref_counted_tracker_statistics_producer.cpp @@ -2,6 +2,10 @@ #include +#include + +#include + namespace NYT { using namespace NYson; @@ -9,34 +13,101 @@ using namespace NYTree; //////////////////////////////////////////////////////////////////////////////// +namespace { + +void Produce(IYsonConsumer* consumer, const TRefCountedTrackerStatistics& statistics) +{ + BuildYsonFluently(consumer) + .BeginMap() + .Item("statistics") + .DoListFor(statistics.NamedStatistics, [] (TFluentList fluent, const auto& namedSlotStatistics) { + fluent + .Item().BeginMap() + .Item("name").Value(namedSlotStatistics.FullName) + .Item("objects_alive").Value(namedSlotStatistics.ObjectsAlive) + .Item("objects_allocated").Value(namedSlotStatistics.ObjectsAllocated) + .Item("bytes_alive").Value(namedSlotStatistics.BytesAlive) + .Item("bytes_allocated").Value(namedSlotStatistics.BytesAllocated) + .EndMap(); + }) + .Item("total").BeginMap() + .Item("objects_alive").Value(statistics.TotalStatistics.ObjectsAlive) + .Item("objects_allocated").Value(statistics.TotalStatistics.ObjectsAllocated) + .Item("bytes_alive").Value(statistics.TotalStatistics.BytesAlive) + .Item("bytes_allocated").Value(statistics.TotalStatistics.BytesAllocated) + .EndMap() + .EndMap(); +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// + TYsonProducer CreateRefCountedTrackerStatisticsProducer() { return BIND([] (IYsonConsumer* consumer) { - auto statistics = TRefCountedTracker::Get()->GetStatistics(); - - BuildYsonFluently(consumer) - .BeginMap() - .Item("statistics") - .DoListFor(statistics.NamedStatistics, [] (TFluentList fluent, const auto& namedSlotStatistics) { - fluent - .Item().BeginMap() - .Item("name").Value(namedSlotStatistics.FullName) - .Item("objects_alive").Value(namedSlotStatistics.ObjectsAlive) - .Item("objects_allocated").Value(namedSlotStatistics.ObjectsAllocated) - .Item("bytes_alive").Value(namedSlotStatistics.BytesAlive) - .Item("bytes_allocated").Value(namedSlotStatistics.BytesAllocated) - .EndMap(); - }) - .Item("total").BeginMap() - .Item("objects_alive").Value(statistics.TotalStatistics.ObjectsAlive) - .Item("objects_allocated").Value(statistics.TotalStatistics.ObjectsAllocated) - .Item("bytes_alive").Value(statistics.TotalStatistics.BytesAlive) - .Item("bytes_allocated").Value(statistics.TotalStatistics.BytesAllocated) - .EndMap() - .EndMap(); + Produce(consumer, TRefCountedTracker::Get()->GetStatistics()); }); } //////////////////////////////////////////////////////////////////////////////// +class TCachingRefCountedTrackerStatisticsManager +{ +public: + TYsonProducer GetProducer() + { + return Producer_; + } + +private: + TCachingRefCountedTrackerStatisticsManager() + : Producer_(BIND([this] (IYsonConsumer* consumer) { + Produce(consumer, *GetCachedStatistics()); + })) + { } + + DECLARE_LEAKY_SINGLETON_FRIEND() + + const TYsonProducer Producer_; + + static constexpr auto CachedStatisticsTtl = TDuration::Seconds(10); + + NThreading::TSpinLock CachedStatisticsLock_; + TIntrusivePtr CachedStatistics_; + TInstant CachedStatisticsUpdateTime_; + + TIntrusivePtr GetCachedStatistics() + { + auto now = TInstant::Now(); + + // Fast path. + { + auto guard = Guard(CachedStatisticsLock_); + if (CachedStatistics_ && now < CachedStatisticsUpdateTime_ + CachedStatisticsTtl) { + return CachedStatistics_; + } + } + + // Slow path. + auto statistics = New(TRefCountedTracker::Get()->GetStatistics()); + { + auto guard = Guard(CachedStatisticsLock_); + if (!CachedStatistics_ || now > CachedStatisticsUpdateTime_ + CachedStatisticsTtl) { + CachedStatistics_ = std::move(statistics); + } + return CachedStatistics_; + } + } +}; + +//////////////////////////////////////////////////////////////////////////////// + +TYsonProducer GetCachingRefCountedTrackerStatisticsProducer() +{ + return LeakySingleton()->GetProducer(); +} + +//////////////////////////////////////////////////////////////////////////////// + } // namespace NYT diff --git a/yt/yt/core/misc/ref_counted_tracker_statistics_producer.h b/yt/yt/core/misc/ref_counted_tracker_statistics_producer.h index 92b2a8b62c2e..cfe7b7ebc9d3 100644 --- a/yt/yt/core/misc/ref_counted_tracker_statistics_producer.h +++ b/yt/yt/core/misc/ref_counted_tracker_statistics_producer.h @@ -8,8 +8,12 @@ namespace NYT { //////////////////////////////////////////////////////////////////////////////// +//! Creates a producer for constructing the most up-to-date state of RCT. NYson::TYsonProducer CreateRefCountedTrackerStatisticsProducer(); +//! Returns a producer that applies a (reasonable) caching to RCT data. +NYson::TYsonProducer GetCachingRefCountedTrackerStatisticsProducer(); + //////////////////////////////////////////////////////////////////////////////// } // namespace NYT diff --git a/yt/yt/core/ya.make b/yt/yt/core/ya.make index 41e2da5dfa3d..a47b5ddfbf3e 100644 --- a/yt/yt/core/ya.make +++ b/yt/yt/core/ya.make @@ -71,7 +71,6 @@ SRCS( concurrency/invoker_alarm.cpp concurrency/invoker_queue.cpp concurrency/lease_manager.cpp - concurrency/new_fair_share_thread_pool.cpp concurrency/nonblocking_batcher.cpp concurrency/notify_manager.cpp concurrency/periodic_executor.cpp diff --git a/yt/yt/core/yson/protobuf_interop.cpp b/yt/yt/core/yson/protobuf_interop.cpp index 1c09fbe86f8b..d552719d78db 100644 --- a/yt/yt/core/yson/protobuf_interop.cpp +++ b/yt/yt/core/yson/protobuf_interop.cpp @@ -808,7 +808,7 @@ TProtobufElement TProtobufField::GetElement(bool insideRepeated) const }); } else { return std::make_unique(TProtobufScalarElement{ - static_cast(GetType()), + static_cast(GetType()), GetEnumYsonStorageType() }); } diff --git a/yt/yt/core/yson/protobuf_interop.h b/yt/yt/core/yson/protobuf_interop.h index 6327336075e1..c82f5c293b9c 100644 --- a/yt/yt/core/yson/protobuf_interop.h +++ b/yt/yt/core/yson/protobuf_interop.h @@ -66,8 +66,7 @@ struct TProtobufMessageElement struct TProtobufScalarElement { - YT_DEFINE_STRONG_TYPEDEF(TType, int); - TType Type; + TProtobufElementType Type; // Meaningful only when TYPE == TYPE_ENUM. EEnumYsonStorageType EnumStorageType; diff --git a/yt/yt/core/yson/public.h b/yt/yt/core/yson/public.h index dae0c0b29888..1e757e187429 100644 --- a/yt/yt/core/yson/public.h +++ b/yt/yt/core/yson/public.h @@ -96,6 +96,9 @@ DECLARE_REFCOUNTED_CLASS(TProtobufInteropDynamicConfig); */ class TProtobufMessageType; +//! A reflected counterpart of ::google::protobuf::FieldDescriptor::Type. +YT_DEFINE_STRONG_TYPEDEF(TProtobufElementType, int); + //! An opaque reflected counterpart of ::google::protobuf::EnumDescriptor. class TProtobufEnumType; diff --git a/yt/yt/core/yson/unittests/protobuf_yson_ut.cpp b/yt/yt/core/yson/unittests/protobuf_yson_ut.cpp index 214d748ace78..a369a85275e5 100644 --- a/yt/yt/core/yson/unittests/protobuf_yson_ut.cpp +++ b/yt/yt/core/yson/unittests/protobuf_yson_ut.cpp @@ -2113,7 +2113,7 @@ void TestScalarByYPath(const TYPath& path, FieldDescriptor::Type type) EXPECT_EQ(path, result.HeadPath); EXPECT_EQ("", result.TailPath); EXPECT_EQ( - static_cast(type), + static_cast(type), std::get>(result.Element)->Type); } diff --git a/yt/yt/library/tcmalloc/config.cpp b/yt/yt/library/tcmalloc/config.cpp index b1e7cdf3c099..3219ffcf22d6 100644 --- a/yt/yt/library/tcmalloc/config.cpp +++ b/yt/yt/library/tcmalloc/config.cpp @@ -6,6 +6,25 @@ using namespace NYTree; //////////////////////////////////////////////////////////////////////////////// +void THeapSizeLimitConfig::ApplyDynamicInplace(const TDynamicHeapSizeLimitConfigPtr& dynamicConfig) +{ + UpdateYsonStructField(ContainerMemoryRatio, dynamicConfig->ContainerMemoryRatio); + UpdateYsonStructField(ContainerMemoryMargin, dynamicConfig->ContainerMemoryMargin); + UpdateYsonStructField(Hard, dynamicConfig->Hard); + UpdateYsonStructField(DumpMemoryProfileOnViolation, dynamicConfig->DumpMemoryProfileOnViolation); + UpdateYsonStructField(MemoryProfileDumpTimeout, dynamicConfig->MemoryProfileDumpTimeout); + UpdateYsonStructField(MemoryProfileDumpPath, dynamicConfig->MemoryProfileDumpPath); + UpdateYsonStructField(MemoryProfileDumpFilenameSuffix, dynamicConfig->MemoryProfileDumpFilenameSuffix); +} + +THeapSizeLimitConfigPtr THeapSizeLimitConfig::ApplyDynamic(const TDynamicHeapSizeLimitConfigPtr& dynamicConfig) const +{ + auto mergedConfig = CloneYsonStruct(MakeStrong(this)); + mergedConfig->ApplyDynamicInplace(dynamicConfig); + mergedConfig->Postprocess(); + return mergedConfig; +} + void THeapSizeLimitConfig::Register(TRegistrar registrar) { registrar.Parameter("container_memory_ratio", &TThis::ContainerMemoryRatio) @@ -20,7 +39,7 @@ void THeapSizeLimitConfig::Register(TRegistrar registrar) .Default(TDuration::Minutes(10)); registrar.Parameter("memory_profile_dump_path", &TThis::MemoryProfileDumpPath) .Default(); - registrar.Parameter("emory_profile_dump_filename_suffix", &TThis::MemoryProfileDumpFilenameSuffix) + registrar.Parameter("memory_profile_dump_filename_suffix", &TThis::MemoryProfileDumpFilenameSuffix) .Default(); registrar.Postprocessor([] (THeapSizeLimitConfig* config) { @@ -30,17 +49,45 @@ void THeapSizeLimitConfig::Register(TRegistrar registrar) }); } -TTCMallocConfigPtr TTCMallocConfig::ApplyDynamic(const TTCMallocConfigPtr& dynamicConfig) const +//////////////////////////////////////////////////////////////////////////////// + +void TDynamicHeapSizeLimitConfig::Register(TRegistrar registrar) { - // TODO(babenko): fix this mess - auto mergedConfig = CloneYsonStruct(dynamicConfig); - mergedConfig->HeapSizeLimit->MemoryProfileDumpPath = HeapSizeLimit->MemoryProfileDumpPath; - mergedConfig->Postprocess(); - return mergedConfig; + registrar.Parameter("container_memory_ratio", &TThis::ContainerMemoryRatio) + .Default(); + registrar.Parameter("container_memory_margin", &TThis::ContainerMemoryMargin) + .Default(); + registrar.Parameter("hard", &TThis::Hard) + .Default(); + registrar.Parameter("dump_memory_profile_on_violation", &TThis::DumpMemoryProfileOnViolation) + .Default(); + registrar.Parameter("memory_profile_dump_timeout", &TThis::MemoryProfileDumpTimeout) + .Default(); + registrar.Parameter("memory_profile_dump_path", &TThis::MemoryProfileDumpPath) + .Default(); + registrar.Parameter("memory_profile_dump_filename_suffix", &TThis::MemoryProfileDumpFilenameSuffix) + .Default(); } //////////////////////////////////////////////////////////////////////////////// +TTCMallocConfigPtr TTCMallocConfig::ApplyDynamic(const TDynamicTCMallocConfigPtr& dynamicConfig) const +{ + auto mergedConfig = CloneYsonStruct(MakeStrong(this)); + UpdateYsonStructField(mergedConfig->AggressiveReleaseThreshold, dynamicConfig->AggressiveReleaseThreshold); + UpdateYsonStructField(mergedConfig->AggressiveReleaseThresholdRatio, dynamicConfig->AggressiveReleaseThresholdRatio); + UpdateYsonStructField(mergedConfig->AggressiveReleaseSize, dynamicConfig->AggressiveReleaseSize); + UpdateYsonStructField(mergedConfig->AggressiveReleasePeriod, dynamicConfig->AggressiveReleasePeriod); + UpdateYsonStructField(mergedConfig->GuardedSamplingRate, dynamicConfig->GuardedSamplingRate); + UpdateYsonStructField(mergedConfig->ProfileSamplingRate, dynamicConfig->ProfileSamplingRate); + UpdateYsonStructField(mergedConfig->MaxPerCpuCacheSize, dynamicConfig->MaxPerCpuCacheSize); + UpdateYsonStructField(mergedConfig->MaxTotalThreadCacheBytes, dynamicConfig->MaxTotalThreadCacheBytes); + UpdateYsonStructField(mergedConfig->BackgroundReleaseRate, dynamicConfig->BackgroundReleaseRate); + mergedConfig->HeapSizeLimit->ApplyDynamicInplace(dynamicConfig->HeapSizeLimit); + mergedConfig->Postprocess(); + return mergedConfig; +} + void TTCMallocConfig::Register(TRegistrar registrar) { registrar.Parameter("aggressive_release_threshold", &TThis::AggressiveReleaseThreshold) @@ -69,5 +116,33 @@ void TTCMallocConfig::Register(TRegistrar registrar) //////////////////////////////////////////////////////////////////////////////// +void TDynamicTCMallocConfig::Register(TRegistrar registrar) +{ + registrar.Parameter("aggressive_release_threshold", &TThis::AggressiveReleaseThreshold) + .Default(); + registrar.Parameter("aggressive_release_threshold_ratio", &TThis::AggressiveReleaseThresholdRatio) + .Optional(); + + registrar.Parameter("aggressive_release_size", &TThis::AggressiveReleaseSize) + .Default(); + registrar.Parameter("aggressive_release_period", &TThis::AggressiveReleasePeriod) + .Default(); + registrar.Parameter("guarded_sampling_rate", &TThis::GuardedSamplingRate) + .Default(); + registrar.Parameter("profile_sampling_rate", &TThis::ProfileSamplingRate) + .Default(); + registrar.Parameter("max_per_cpu_cache_size", &TThis::MaxPerCpuCacheSize) + .Default(); + registrar.Parameter("max_total_thread_cache_bytes", &TThis::MaxTotalThreadCacheBytes) + .Default(); + registrar.Parameter("background_release_rate", &TThis::BackgroundReleaseRate) + .Default(); + + registrar.Parameter("heap_size_limit", &TThis::HeapSizeLimit) + .DefaultNew(); +} + +//////////////////////////////////////////////////////////////////////////////// + } // namespace NYT::NTCMalloc diff --git a/yt/yt/library/tcmalloc/config.h b/yt/yt/library/tcmalloc/config.h index 1783b1a65cfb..3c140b44308c 100644 --- a/yt/yt/library/tcmalloc/config.h +++ b/yt/yt/library/tcmalloc/config.h @@ -34,6 +34,9 @@ struct THeapSizeLimitConfig std::optional MemoryProfileDumpPath; std::optional MemoryProfileDumpFilenameSuffix; + void ApplyDynamicInplace(const TDynamicHeapSizeLimitConfigPtr& dynamicConfig); + THeapSizeLimitConfigPtr ApplyDynamic(const TDynamicHeapSizeLimitConfigPtr& dynamicConfig) const; + REGISTER_YSON_STRUCT(THeapSizeLimitConfig); static void Register(TRegistrar registrar); @@ -43,6 +46,30 @@ DEFINE_REFCOUNTED_TYPE(THeapSizeLimitConfig) //////////////////////////////////////////////////////////////////////////////// +struct TDynamicHeapSizeLimitConfig + : public NYTree::TYsonStruct +{ + std::optional ContainerMemoryRatio; + std::optional ContainerMemoryMargin; + + std::optional Hard; + + std::optional DumpMemoryProfileOnViolation; + + std::optional MemoryProfileDumpTimeout; + + std::optional MemoryProfileDumpPath; + std::optional MemoryProfileDumpFilenameSuffix; + + REGISTER_YSON_STRUCT(TDynamicHeapSizeLimitConfig); + + static void Register(TRegistrar registrar); +}; + +DEFINE_REFCOUNTED_TYPE(TDynamicHeapSizeLimitConfig) + +//////////////////////////////////////////////////////////////////////////////// + struct TTCMallocConfig : public NYTree::TYsonStruct { @@ -66,7 +93,7 @@ struct TTCMallocConfig THeapSizeLimitConfigPtr HeapSizeLimit; - TTCMallocConfigPtr ApplyDynamic(const TTCMallocConfigPtr& dynamicConfig) const; + TTCMallocConfigPtr ApplyDynamic(const TDynamicTCMallocConfigPtr& dynamicConfig) const; REGISTER_YSON_STRUCT(TTCMallocConfig); @@ -77,4 +104,32 @@ DEFINE_REFCOUNTED_TYPE(TTCMallocConfig) //////////////////////////////////////////////////////////////////////////////// +struct TDynamicTCMallocConfig + : public NYTree::TYsonStruct +{ + std::optional AggressiveReleaseThreshold; + + std::optional AggressiveReleaseThresholdRatio; + + std::optional AggressiveReleaseSize; + std::optional AggressiveReleasePeriod; + + std::optional GuardedSamplingRate; + + std::optional ProfileSamplingRate; + std::optional MaxPerCpuCacheSize; + std::optional MaxTotalThreadCacheBytes; + std::optional BackgroundReleaseRate; + + TDynamicHeapSizeLimitConfigPtr HeapSizeLimit; + + REGISTER_YSON_STRUCT(TDynamicTCMallocConfig); + + static void Register(TRegistrar registrar); +}; + +DEFINE_REFCOUNTED_TYPE(TDynamicTCMallocConfig) + +//////////////////////////////////////////////////////////////////////////////// + } // namespace NYT::NTCMalloc diff --git a/yt/yt/library/tcmalloc/configure_tcmalloc_manager.cpp b/yt/yt/library/tcmalloc/configure_tcmalloc_manager.cpp index d5947bf185da..49829b935778 100644 --- a/yt/yt/library/tcmalloc/configure_tcmalloc_manager.cpp +++ b/yt/yt/library/tcmalloc/configure_tcmalloc_manager.cpp @@ -14,6 +14,11 @@ void SetupSingletonConfigParameter(TYsonStructParameter& par parameter.DefaultNew(); } +void SetupSingletonConfigParameter(TYsonStructParameter& parameter) +{ + parameter.DefaultNew(); +} + void ConfigureSingleton(const TTCMallocConfigPtr& config) { TTCMallocManager::Configure(config); @@ -21,7 +26,7 @@ void ConfigureSingleton(const TTCMallocConfigPtr& config) void ReconfigureSingleton( const TTCMallocConfigPtr& config, - const TTCMallocConfigPtr& dynamicConfig) + const TDynamicTCMallocConfigPtr& dynamicConfig) { TTCMallocManager::Configure(config->ApplyDynamic(dynamicConfig)); } @@ -29,7 +34,7 @@ void ReconfigureSingleton( YT_DEFINE_RECONFIGURABLE_SINGLETON( "tcmalloc", TTCMallocConfig, - TTCMallocConfig); + TDynamicTCMallocConfig); //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/library/tcmalloc/public.h b/yt/yt/library/tcmalloc/public.h index f6703f918c38..c9600da99a9d 100644 --- a/yt/yt/library/tcmalloc/public.h +++ b/yt/yt/library/tcmalloc/public.h @@ -10,6 +10,8 @@ namespace NYT::NTCMalloc { DECLARE_REFCOUNTED_STRUCT(TTCMallocConfig) DECLARE_REFCOUNTED_STRUCT(THeapSizeLimitConfig) +DECLARE_REFCOUNTED_STRUCT(TDynamicTCMallocConfig) +DECLARE_REFCOUNTED_STRUCT(TDynamicHeapSizeLimitConfig) YT_DECLARE_RECONFIGURABLE_SINGLETON(TTCMallocConfig, TTCMallocConfig);