123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130 |
- #include "mkql_todict.h"
- #include <yql/essentials/minikql/computation/mkql_computation_list_adapter.h>
- #include <yql/essentials/minikql/computation/mkql_computation_node_codegen.h> // Y_IGNORE
- #include <yql/essentials/minikql/computation/mkql_computation_node_holders.h>
- #include <yql/essentials/minikql/computation/mkql_computation_node_pack.h>
- #include <yql/essentials/minikql/computation/mkql_llvm_base.h> // Y_IGNORE
- #include <yql/essentials/minikql/computation/presort.h>
- #include <yql/essentials/minikql/mkql_node_cast.h>
- #include <yql/essentials/minikql/mkql_string_util.h>
- #include <yql/essentials/public/udf/udf_types.h>
- #include <yql/essentials/utils/cast.h>
- #include <yql/essentials/utils/hash.h>
- #include <algorithm>
- #include <unordered_map>
- #include <optional>
- #include <vector>
- namespace NKikimr {
- namespace NMiniKQL {
- using NYql::EnsureDynamicCast;
- namespace {
- class ISetAccumulator {
- public:
- virtual ~ISetAccumulator() = default;
- virtual void Add(NUdf::TUnboxedValue&& key) = 0;
- virtual NUdf::TUnboxedValue Build() = 0;
- };
- class ISetAccumulatorFactory {
- public:
- virtual ~ISetAccumulatorFactory() = default;
- virtual bool IsSorted() const = 0;
- virtual std::unique_ptr<ISetAccumulator> Create(TType* keyType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx,
- ui64 itemsCountHint) const = 0;
- };
- class IMapAccumulator {
- public:
- virtual ~IMapAccumulator() = default;
- virtual void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) = 0;
- virtual NUdf::TUnboxedValue Build() = 0;
- };
- class IMapAccumulatorFactory {
- public:
- virtual ~IMapAccumulatorFactory() = default;
- virtual bool IsSorted() const = 0;
- virtual std::unique_ptr<IMapAccumulator> Create(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint) const = 0;
- };
- template <typename T>
- class TSetAccumulatorFactory : public ISetAccumulatorFactory {
- public:
- bool IsSorted() const final {
- return T::IsSorted;
- }
- std::unique_ptr<ISetAccumulator> Create(TType* keyType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx,
- ui64 itemsCountHint) const {
- return std::make_unique<T>(keyType, keyTypes, isTuple, encoded, compare, equate, hash, ctx, itemsCountHint);
- }
- };
- template <typename T>
- class TMapAccumulatorFactory : public IMapAccumulatorFactory {
- public:
- bool IsSorted() const final {
- return T::IsSorted;
- }
- std::unique_ptr<IMapAccumulator> Create(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx,
- ui64 itemsCountHint) const {
- return std::make_unique<T>(keyType, payloadType, keyTypes, isTuple, encoded, compare, equate, hash, ctx, itemsCountHint);
- }
- };
- class THashedMultiMapAccumulator : public IMapAccumulator {
- using TMapType = TValuesDictHashMap;
- TComputationContext& Ctx;
- TType* KeyType;
- const TKeyTypes& KeyTypes;
- bool IsTuple;
- std::shared_ptr<TValuePacker> Packer;
- const NUdf::IHash* Hash;
- const NUdf::IEquate* Equate;
- TMapType Map;
- public:
- static constexpr bool IsSorted = false;
- THashedMultiMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), KeyType(keyType), KeyTypes(keyTypes), IsTuple(isTuple), Hash(hash), Equate(equate)
- , Map(0, TValueHasher(KeyTypes, isTuple, hash), TValueEqual(KeyTypes, isTuple, equate))
- {
- Y_UNUSED(compare);
- if (encoded) {
- Packer = std::make_shared<TValuePacker>(true, keyType);
- }
- Y_UNUSED(payloadType);
- Map.reserve(itemsCountHint);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- if (Packer) {
- key = MakeString(Packer->Pack(key));
- }
- auto it = Map.find(key);
- if (it == Map.end()) {
- it = Map.emplace(std::move(key), Ctx.HolderFactory.NewVectorHolder()).first;
- }
- it->second.Push(std::move(payload));
- }
- NUdf::TUnboxedValue Build() final
- {
- const auto filler = [this](TValuesDictHashMap& targetMap) {
- targetMap = std::move(Map);
- };
- return Ctx.HolderFactory.CreateDirectHashedDictHolder(filler, KeyTypes, IsTuple, true, Packer ? KeyType : nullptr, Hash, Equate);
- }
- };
- class THashedMapAccumulator : public IMapAccumulator {
- using TMapType = TValuesDictHashMap;
- TComputationContext& Ctx;
- TType* KeyType;
- const TKeyTypes& KeyTypes;
- const bool IsTuple;
- std::shared_ptr<TValuePacker> Packer;
- const NUdf::IHash* Hash;
- const NUdf::IEquate* Equate;
- TMapType Map;
- public:
- static constexpr bool IsSorted = false;
- THashedMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), KeyType(keyType), KeyTypes(keyTypes), IsTuple(isTuple), Hash(hash), Equate(equate)
- , Map(0, TValueHasher(KeyTypes, isTuple, hash), TValueEqual(KeyTypes, isTuple, equate))
- {
- Y_UNUSED(compare);
- if (encoded) {
- Packer = std::make_shared<TValuePacker>(true, keyType);
- }
- Y_UNUSED(payloadType);
- Map.reserve(itemsCountHint);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- if (Packer) {
- key = MakeString(Packer->Pack(key));
- }
- Map.emplace(std::move(key), std::move(payload));
- }
- NUdf::TUnboxedValue Build() final
- {
- const auto filler = [this](TMapType& targetMap) {
- targetMap = std::move(Map);
- };
- return Ctx.HolderFactory.CreateDirectHashedDictHolder(filler, KeyTypes, IsTuple, true, Packer ? KeyType : nullptr, Hash, Equate);
- }
- };
- template<typename T, bool OptionalKey>
- class THashedSingleFixedMultiMapAccumulator : public IMapAccumulator {
- using TMapType = TValuesDictHashSingleFixedMap<T>;
- TComputationContext& Ctx;
- const TKeyTypes& KeyTypes;
- TMapType Map;
- TUnboxedValueVector NullPayloads;
- NUdf::TUnboxedValue CurrentEmptyVectorForInsert;
- public:
- static constexpr bool IsSorted = false;
- THashedSingleFixedMultiMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), KeyTypes(keyTypes), Map(0, TMyHash<T>(), TMyEquals<T>()) {
- Y_UNUSED(keyType);
- Y_UNUSED(payloadType);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Map.reserve(itemsCountHint);
- CurrentEmptyVectorForInsert = Ctx.HolderFactory.NewVectorHolder();
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final {
- if constexpr (OptionalKey) {
- if (!key) {
- NullPayloads.emplace_back(std::move(payload));
- return;
- }
- }
- auto insertInfo = Map.emplace(key.Get<T>(), CurrentEmptyVectorForInsert);
- if (insertInfo.second) {
- CurrentEmptyVectorForInsert = Ctx.HolderFactory.NewVectorHolder();
- }
- insertInfo.first->second.Push(payload.Release());
- }
- NUdf::TUnboxedValue Build() final {
- std::optional<NUdf::TUnboxedValue> nullPayload;
- if (NullPayloads.size()) {
- nullPayload = Ctx.HolderFactory.VectorAsVectorHolder(std::move(NullPayloads));
- }
- return Ctx.HolderFactory.CreateDirectHashedSingleFixedMapHolder<T, OptionalKey>(std::move(Map), std::move(nullPayload));
- }
- };
- template<typename T, bool OptionalKey>
- class THashedSingleFixedMapAccumulator : public IMapAccumulator {
- using TMapType = TValuesDictHashSingleFixedMap<T>;
- TComputationContext& Ctx;
- TMapType Map;
- std::optional<NUdf::TUnboxedValue> NullPayload;
- public:
- static constexpr bool IsSorted = false;
- THashedSingleFixedMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), Map(0, TMyHash<T>(), TMyEquals<T>())
- {
- Y_UNUSED(keyType);
- Y_UNUSED(payloadType);
- Y_UNUSED(keyTypes);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Map.reserve(itemsCountHint);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- if constexpr (OptionalKey) {
- if (!key) {
- NullPayload.emplace(std::move(payload));
- return;
- }
- }
- Map.emplace(key.Get<T>(), std::move(payload));
- }
- NUdf::TUnboxedValue Build() final
- {
- return Ctx.HolderFactory.CreateDirectHashedSingleFixedMapHolder<T, OptionalKey>(std::move(Map), std::move(NullPayload));
- }
- };
- class THashedSetAccumulator : public ISetAccumulator {
- using TSetType = TValuesDictHashSet;
- TComputationContext& Ctx;
- TType* KeyType;
- const TKeyTypes& KeyTypes;
- bool IsTuple;
- std::shared_ptr<TValuePacker> Packer;
- TSetType Set;
- const NUdf::IHash* Hash;
- const NUdf::IEquate* Equate;
- public:
- static constexpr bool IsSorted = false;
- THashedSetAccumulator(TType* keyType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), KeyType(keyType), KeyTypes(keyTypes), IsTuple(isTuple), Set(0, TValueHasher(KeyTypes, isTuple, hash),
- TValueEqual(KeyTypes, isTuple, equate)), Hash(hash), Equate(equate)
- {
- Y_UNUSED(compare);
- if (encoded) {
- Packer = std::make_shared<TValuePacker>(true, keyType);
- }
- Set.reserve(itemsCountHint);
- }
- void Add(NUdf::TUnboxedValue&& key) final
- {
- if (Packer) {
- key = MakeString(Packer->Pack(key));
- }
- Set.emplace(std::move(key));
- }
- NUdf::TUnboxedValue Build() final
- {
- const auto filler = [this](TSetType& targetSet) {
- targetSet = std::move(Set);
- };
- return Ctx.HolderFactory.CreateDirectHashedSetHolder(filler, KeyTypes, IsTuple, true, Packer ? KeyType : nullptr, Hash, Equate);
- }
- };
- template <typename T, bool OptionalKey>
- class THashedSingleFixedSetAccumulator : public ISetAccumulator{
- using TSetType = TValuesDictHashSingleFixedSet<T>;
- TComputationContext& Ctx;
- TSetType Set;
- bool HasNull = false;
- public:
- static constexpr bool IsSorted = false;
- THashedSingleFixedSetAccumulator(TType* keyType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), Set(0, TMyHash<T>(), TMyEquals<T>())
- {
- Y_UNUSED(keyType);
- Y_UNUSED(keyTypes);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Set.reserve(itemsCountHint);
- }
- void Add(NUdf::TUnboxedValue&& key) final
- {
- if constexpr (OptionalKey) {
- if (!key) {
- HasNull = true;
- return;
- }
- }
- Set.emplace(key.Get<T>());
- }
- NUdf::TUnboxedValue Build() final
- {
- return Ctx.HolderFactory.CreateDirectHashedSingleFixedSetHolder<T, OptionalKey>(std::move(Set), HasNull);
- }
- };
- template <typename T, bool OptionalKey>
- class THashedSingleFixedCompactSetAccumulator : public ISetAccumulator {
- using TSetType = TValuesDictHashSingleFixedCompactSet<T>;
- TComputationContext& Ctx;
- TPagedArena Pool;
- TSetType Set;
- bool HasNull = false;
- public:
- static constexpr bool IsSorted = false;
- THashedSingleFixedCompactSetAccumulator(TType* keyType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), Pool(&Ctx.HolderFactory.GetPagePool()), Set(Ctx.HolderFactory.GetPagePool(), itemsCountHint / COMPACT_HASH_MAX_LOAD_FACTOR)
- {
- Y_UNUSED(keyType);
- Y_UNUSED(keyTypes);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Set.SetMaxLoadFactor(COMPACT_HASH_MAX_LOAD_FACTOR);
- }
- void Add(NUdf::TUnboxedValue&& key) final
- {
- if constexpr (OptionalKey) {
- if (!key) {
- HasNull = true;
- return;
- }
- }
- Set.Insert(key.Get<T>());
- }
- NUdf::TUnboxedValue Build() final
- {
- return Ctx.HolderFactory.CreateDirectHashedSingleFixedCompactSetHolder<T, OptionalKey>(std::move(Set), HasNull);
- }
- };
- class THashedCompactSetAccumulator : public ISetAccumulator {
- using TSetType = TValuesDictHashCompactSet;
- TComputationContext& Ctx;
- TPagedArena Pool;
- TSetType Set;
- TType *KeyType;
- std::shared_ptr<TValuePacker> KeyPacker;
- public:
- static constexpr bool IsSorted = false;
- THashedCompactSetAccumulator(TType* keyType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), Pool(&Ctx.HolderFactory.GetPagePool()), Set(Ctx.HolderFactory.GetPagePool(), itemsCountHint / COMPACT_HASH_MAX_LOAD_FACTOR, TSmallValueHash(), TSmallValueEqual())
- , KeyType(keyType), KeyPacker(std::make_shared<TValuePacker>(true, keyType))
- {
- Y_UNUSED(keyTypes);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Set.SetMaxLoadFactor(COMPACT_HASH_MAX_LOAD_FACTOR);
- }
- void Add(NUdf::TUnboxedValue&& key) final
- {
- Set.Insert(AddSmallValue(Pool, KeyPacker->Pack(key)));
- }
- NUdf::TUnboxedValue Build() final
- {
- return Ctx.HolderFactory.CreateDirectHashedCompactSetHolder(std::move(Set), std::move(Pool), KeyType, &Ctx);
- }
- };
- template <bool Multi>
- class THashedCompactMapAccumulator;
- template <>
- class THashedCompactMapAccumulator<false> : public IMapAccumulator {
- using TMapType = TValuesDictHashCompactMap;
- TComputationContext& Ctx;
- TPagedArena Pool;
- TMapType Map;
- TType *KeyType, *PayloadType;
- std::shared_ptr<TValuePacker> KeyPacker, PayloadPacker;
- public:
- static constexpr bool IsSorted = false;
- THashedCompactMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), Pool(&Ctx.HolderFactory.GetPagePool()), Map(Ctx.HolderFactory.GetPagePool(), itemsCountHint / COMPACT_HASH_MAX_LOAD_FACTOR)
- , KeyType(keyType), PayloadType(payloadType)
- , KeyPacker(std::make_shared<TValuePacker>(true, keyType))
- , PayloadPacker(std::make_shared<TValuePacker>(false, payloadType))
- {
- Y_UNUSED(keyTypes);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Map.SetMaxLoadFactor(COMPACT_HASH_MAX_LOAD_FACTOR);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- Map.InsertNew(AddSmallValue(Pool, KeyPacker->Pack(key)), AddSmallValue(Pool, PayloadPacker->Pack(payload)));
- }
- NUdf::TUnboxedValue Build() final
- {
- return Ctx.HolderFactory.CreateDirectHashedCompactMapHolder(std::move(Map), std::move(Pool), KeyType, PayloadType, &Ctx);
- }
- };
- template <>
- class THashedCompactMapAccumulator<true> : public IMapAccumulator {
- using TMapType = TValuesDictHashCompactMultiMap;
- TComputationContext& Ctx;
- TPagedArena Pool;
- TMapType Map;
- TType *KeyType, *PayloadType;
- std::shared_ptr<TValuePacker> KeyPacker, PayloadPacker;
- public:
- static constexpr bool IsSorted = false;
- THashedCompactMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), Pool(&Ctx.HolderFactory.GetPagePool()), Map(Ctx.HolderFactory.GetPagePool(), itemsCountHint / COMPACT_HASH_MAX_LOAD_FACTOR)
- , KeyType(keyType), PayloadType(payloadType)
- , KeyPacker(std::make_shared<TValuePacker>(true, keyType))
- , PayloadPacker(std::make_shared<TValuePacker>(false, payloadType))
- {
- Y_UNUSED(keyTypes);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Map.SetMaxLoadFactor(COMPACT_HASH_MAX_LOAD_FACTOR);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- Map.Insert(AddSmallValue(Pool, KeyPacker->Pack(key)), AddSmallValue(Pool, PayloadPacker->Pack(payload)));
- }
- NUdf::TUnboxedValue Build() final
- {
- return Ctx.HolderFactory.CreateDirectHashedCompactMultiMapHolder(std::move(Map), std::move(Pool), KeyType, PayloadType, &Ctx);
- }
- };
- template <typename T, bool OptionalKey, bool Multi>
- class THashedSingleFixedCompactMapAccumulator;
- template <typename T, bool OptionalKey>
- class THashedSingleFixedCompactMapAccumulator<T, OptionalKey, false> : public IMapAccumulator {
- using TMapType = TValuesDictHashSingleFixedCompactMap<T>;
- TComputationContext& Ctx;
- TPagedArena Pool;
- TMapType Map;
- std::optional<ui64> NullPayload;
- TType* PayloadType;
- std::shared_ptr<TValuePacker> PayloadPacker;
- public:
- static constexpr bool IsSorted = false;
- THashedSingleFixedCompactMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), Pool(&Ctx.HolderFactory.GetPagePool()), Map(Ctx.HolderFactory.GetPagePool(), itemsCountHint / COMPACT_HASH_MAX_LOAD_FACTOR)
- , PayloadType(payloadType), PayloadPacker(std::make_shared<TValuePacker>(false, payloadType))
- {
- Y_UNUSED(keyType);
- Y_UNUSED(keyTypes);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Map.SetMaxLoadFactor(COMPACT_HASH_MAX_LOAD_FACTOR);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- if constexpr (OptionalKey) {
- if (!key) {
- NullPayload = AddSmallValue(Pool, PayloadPacker->Pack(payload));
- return;
- }
- }
- Map.InsertNew(key.Get<T>(), AddSmallValue(Pool, PayloadPacker->Pack(payload)));
- }
- NUdf::TUnboxedValue Build() final
- {
- return Ctx.HolderFactory.CreateDirectHashedSingleFixedCompactMapHolder<T, OptionalKey>(std::move(Map), std::move(NullPayload), std::move(Pool), PayloadType, &Ctx);
- }
- };
- template <typename T, bool OptionalKey>
- class THashedSingleFixedCompactMapAccumulator<T, OptionalKey, true> : public IMapAccumulator {
- using TMapType = TValuesDictHashSingleFixedCompactMultiMap<T>;
- TComputationContext& Ctx;
- TPagedArena Pool;
- TMapType Map;
- std::vector<ui64> NullPayloads;
- TType* PayloadType;
- std::shared_ptr<TValuePacker> PayloadPacker;
- public:
- static constexpr bool IsSorted = false;
- THashedSingleFixedCompactMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), Pool(&Ctx.HolderFactory.GetPagePool()), Map(Ctx.HolderFactory.GetPagePool(), itemsCountHint / COMPACT_HASH_MAX_LOAD_FACTOR)
- , PayloadType(payloadType), PayloadPacker(std::make_shared<TValuePacker>(false, payloadType))
- {
- Y_UNUSED(keyTypes);
- Y_UNUSED(keyType);
- Y_UNUSED(isTuple);
- Y_UNUSED(encoded);
- Y_UNUSED(compare);
- Y_UNUSED(equate);
- Y_UNUSED(hash);
- Map.SetMaxLoadFactor(COMPACT_HASH_MAX_LOAD_FACTOR);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- if constexpr (OptionalKey) {
- if (!key) {
- NullPayloads.push_back(AddSmallValue(Pool, PayloadPacker->Pack(payload)));
- return;
- }
- }
- Map.Insert(key.Get<T>(), AddSmallValue(Pool, PayloadPacker->Pack(payload)));
- }
- NUdf::TUnboxedValue Build() final
- {
- return Ctx.HolderFactory.CreateDirectHashedSingleFixedCompactMultiMapHolder<T, OptionalKey>(std::move(Map), std::move(NullPayloads), std::move(Pool), PayloadType, &Ctx);
- }
- };
- class TSortedSetAccumulator : public ISetAccumulator {
- TComputationContext& Ctx;
- TType* KeyType;
- const TKeyTypes& KeyTypes;
- bool IsTuple;
- const NUdf::ICompare* Compare;
- const NUdf::IEquate* Equate;
- std::optional<TGenericPresortEncoder> Packer;
- TUnboxedValueVector Items;
- public:
- static constexpr bool IsSorted = true;
- TSortedSetAccumulator(TType* keyType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), KeyType(keyType), KeyTypes(keyTypes), IsTuple(isTuple), Compare(compare), Equate(equate)
- {
- Y_UNUSED(hash);
- if (encoded) {
- Packer.emplace(KeyType);
- }
- Items.reserve(itemsCountHint);
- }
- void Add(NUdf::TUnboxedValue&& key) final
- {
- if (Packer) {
- key = MakeString(Packer->Encode(key, false));
- }
- Items.emplace_back(std::move(key));
- }
- NUdf::TUnboxedValue Build() final
- {
- const TSortedSetFiller filler = [this](TUnboxedValueVector& values) {
- std::stable_sort(Items.begin(), Items.end(), TValueLess(KeyTypes, IsTuple, Compare));
- Items.erase(std::unique(Items.begin(), Items.end(), TValueEqual(KeyTypes, IsTuple, Equate)), Items.end());
- values = std::move(Items);
- };
- return Ctx.HolderFactory.CreateDirectSortedSetHolder(filler, KeyTypes, IsTuple,
- EDictSortMode::SortedUniqueAscending, true, Packer ? KeyType : nullptr, Compare, Equate);
- }
- };
- template<bool IsMulti>
- class TSortedMapAccumulator;
- template<>
- class TSortedMapAccumulator<false> : public IMapAccumulator {
- TComputationContext& Ctx;
- TType* KeyType;
- const TKeyTypes& KeyTypes;
- bool IsTuple;
- const NUdf::ICompare* Compare;
- const NUdf::IEquate* Equate;
- std::optional<TGenericPresortEncoder> Packer;
- TKeyPayloadPairVector Items;
- public:
- static constexpr bool IsSorted = true;
- TSortedMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx)
- , KeyType(keyType)
- , KeyTypes(keyTypes)
- , IsTuple(isTuple)
- , Compare(compare)
- , Equate(equate)
- {
- Y_UNUSED(hash);
- if (encoded) {
- Packer.emplace(KeyType);
- }
- Y_UNUSED(payloadType);
- Items.reserve(itemsCountHint);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- if (Packer) {
- key = MakeString(Packer->Encode(key, false));
- }
- Items.emplace_back(std::move(key), std::move(payload));
- }
- NUdf::TUnboxedValue Build() final
- {
- const TSortedDictFiller filler = [this](TKeyPayloadPairVector& values) {
- values = std::move(Items);
- };
- return Ctx.HolderFactory.CreateDirectSortedDictHolder(filler, KeyTypes, IsTuple, EDictSortMode::RequiresSorting,
- true, Packer ? KeyType : nullptr, Compare, Equate);
- }
- };
- template<>
- class TSortedMapAccumulator<true> : public IMapAccumulator {
- TComputationContext& Ctx;
- TType* KeyType;
- const TKeyTypes& KeyTypes;
- bool IsTuple;
- const NUdf::ICompare* Compare;
- const NUdf::IEquate* Equate;
- std::optional<TGenericPresortEncoder> Packer;
- TKeyPayloadPairVector Items;
- public:
- static constexpr bool IsSorted = true;
- TSortedMapAccumulator(TType* keyType, TType* payloadType, const TKeyTypes& keyTypes, bool isTuple, bool encoded,
- const NUdf::ICompare* compare, const NUdf::IEquate* equate, const NUdf::IHash* hash, TComputationContext& ctx, ui64 itemsCountHint)
- : Ctx(ctx), KeyType(keyType), KeyTypes(keyTypes), IsTuple(isTuple), Compare(compare), Equate(equate)
- {
- Y_UNUSED(hash);
- if (encoded) {
- Packer.emplace(KeyType);
- }
- Y_UNUSED(payloadType);
- Items.reserve(itemsCountHint);
- }
- void Add(NUdf::TUnboxedValue&& key, NUdf::TUnboxedValue&& payload) final
- {
- if (Packer) {
- key = MakeString(Packer->Encode(key, false));
- }
- Items.emplace_back(std::move(key), std::move(payload));
- }
- NUdf::TUnboxedValue Build() final
- {
- const TSortedDictFiller filler = [this](TKeyPayloadPairVector& values) {
- std::stable_sort(Items.begin(), Items.end(), TKeyPayloadPairLess(KeyTypes, IsTuple, Compare));
- TKeyPayloadPairVector groups;
- groups.reserve(Items.size());
- if (!Items.empty()) {
- TDefaultListRepresentation currentList(std::move(Items.begin()->second));
- auto lastKey = std::move(Items.begin()->first);
- TValueEqual eqPredicate(KeyTypes, IsTuple, Equate);
- for (auto it = Items.begin() + 1; it != Items.end(); ++it) {
- if (eqPredicate(lastKey, it->first)) {
- currentList = currentList.Append(std::move(it->second));
- }
- else {
- auto payload = Ctx.HolderFactory.CreateDirectListHolder(std::move(currentList));
- groups.emplace_back(std::move(lastKey), std::move(payload));
- currentList = TDefaultListRepresentation(std::move(it->second));
- lastKey = std::move(it->first);
- }
- }
- auto payload = Ctx.HolderFactory.CreateDirectListHolder(std::move(currentList));
- groups.emplace_back(std::move(lastKey), std::move(payload));
- }
- values = std::move(groups);
- };
- return Ctx.HolderFactory.CreateDirectSortedDictHolder(filler, KeyTypes, IsTuple,
- EDictSortMode::SortedUniqueAscending, true, Packer ? KeyType : nullptr, Compare, Equate);
- }
- };
- class TSetWrapper : public TMutableComputationNode<TSetWrapper> {
- typedef TMutableComputationNode<TSetWrapper> TBaseComputation;
- public:
- class TStreamValue : public TComputationValue<TStreamValue> {
- public:
- TStreamValue(TMemoryUsageInfo* memInfo, NUdf::TUnboxedValue&& input, IComputationExternalNode* const item,
- IComputationNode* const key, std::unique_ptr<ISetAccumulator>&& setAccum, TComputationContext& ctx)
- : TComputationValue<TStreamValue>(memInfo)
- , Input(std::move(input))
- , Item(item)
- , Key(key)
- , SetAccum(std::move(setAccum))
- , Ctx(ctx) {}
- private:
- NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& result) override {
- if (Finished) {
- return NUdf::EFetchStatus::Finish;
- }
- for (;;) {
- NUdf::TUnboxedValue item;
- switch (auto status = Input.Fetch(item)) {
- case NUdf::EFetchStatus::Ok: {
- Item->SetValue(Ctx, std::move(item));
- SetAccum->Add(Key->GetValue(Ctx));
- break; // and continue
- }
- case NUdf::EFetchStatus::Finish: {
- result = SetAccum->Build();
- Finished = true;
- return NUdf::EFetchStatus::Ok;
- }
- case NUdf::EFetchStatus::Yield: {
- return NUdf::EFetchStatus::Yield;
- }
- }
- }
- }
- NUdf::TUnboxedValue Input;
- IComputationExternalNode* const Item;
- IComputationNode* const Key;
- const std::unique_ptr<ISetAccumulator> SetAccum;
- TComputationContext& Ctx;
- bool Finished = false;
- };
- TSetWrapper(TComputationMutables& mutables, TType* keyType, IComputationNode* list, IComputationExternalNode* item,
- IComputationNode* key, ui64 itemsCountHint, bool isStream, std::unique_ptr<ISetAccumulatorFactory> factory)
- : TBaseComputation(mutables, EValueRepresentation::Boxed)
- , KeyType(keyType)
- , List(list)
- , Item(item)
- , Key(key)
- , ItemsCountHint(itemsCountHint)
- , IsStream(isStream)
- , Factory(std::move(factory))
- {
- GetDictionaryKeyTypes(KeyType, KeyTypes, IsTuple, Encoded, UseIHash);
- Compare = UseIHash && Factory->IsSorted() ? MakeCompareImpl(KeyType) : nullptr;
- Equate = UseIHash ? MakeEquateImpl(KeyType) : nullptr;
- Hash = UseIHash && !Factory->IsSorted() ? MakeHashImpl(KeyType) : nullptr;
- }
- NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const {
- if (IsStream) {
- return ctx.HolderFactory.Create<TStreamValue>(List->GetValue(ctx), Item, Key,
- Factory->Create(KeyType, KeyTypes, IsTuple, Encoded, Compare.Get(), Equate.Get(), Hash.Get(),
- ctx, ItemsCountHint), ctx);
- }
- const auto& list = List->GetValue(ctx);
- auto itemsCountHint = ItemsCountHint;
- if (list.HasFastListLength()) {
- if (const auto size = list.GetListLength())
- itemsCountHint = size;
- else
- return ctx.HolderFactory.GetEmptyContainerLazy();
- }
- auto acc = Factory->Create(KeyType, KeyTypes, IsTuple, Encoded, Compare.Get(), Equate.Get(), Hash.Get(),
- ctx, itemsCountHint);
- TThresher<false>::DoForEachItem(list,
- [this, &acc, &ctx] (NUdf::TUnboxedValue&& item) {
- Item->SetValue(ctx, std::move(item));
- acc->Add(Key->GetValue(ctx));
- }
- );
- return acc->Build().Release();
- }
- private:
- void RegisterDependencies() const final {
- this->DependsOn(List);
- this->Own(Item);
- this->DependsOn(Key);
- }
- TType* const KeyType;
- IComputationNode* const List;
- IComputationExternalNode* const Item;
- IComputationNode* const Key;
- const ui64 ItemsCountHint;
- const bool IsStream;
- const std::unique_ptr<ISetAccumulatorFactory> Factory;
- TKeyTypes KeyTypes;
- bool IsTuple;
- bool Encoded;
- bool UseIHash;
- NUdf::ICompare::TPtr Compare;
- NUdf::IEquate::TPtr Equate;
- NUdf::IHash::TPtr Hash;
- };
- #ifndef MKQL_DISABLE_CODEGEN
- template <class TLLVMBase>
- class TLLVMFieldsStructureStateWithAccum: public TLLVMBase {
- private:
- using TBase = TLLVMBase;
- llvm::PointerType* StructPtrType;
- protected:
- using TBase::Context;
- public:
- std::vector<llvm::Type*> GetFieldsArray() {
- std::vector<llvm::Type*> result = TBase::GetFields();
- result.emplace_back(StructPtrType); //accumulator
- return result;
- }
- llvm::Constant* GetAccumulator() {
- return ConstantInt::get(Type::getInt32Ty(Context), TBase::GetFieldsCount() + 0);
- }
- TLLVMFieldsStructureStateWithAccum(llvm::LLVMContext& context)
- : TBase(context)
- , StructPtrType(PointerType::getUnqual(StructType::get(context))) {
- }
- };
- #endif
- class TSqueezeSetFlowWrapper : public TStatefulFlowCodegeneratorNode<TSqueezeSetFlowWrapper> {
- using TBase = TStatefulFlowCodegeneratorNode<TSqueezeSetFlowWrapper>;
- public:
- class TState : public TComputationValue<TState> {
- using TBase = TComputationValue<TState>;
- public:
- TState(TMemoryUsageInfo* memInfo, std::unique_ptr<ISetAccumulator>&& setAccum)
- : TBase(memInfo), SetAccum(std::move(setAccum)) {}
- NUdf::TUnboxedValuePod Build() {
- return SetAccum->Build().Release();
- }
- void Insert(NUdf::TUnboxedValuePod value) {
- SetAccum->Add(value);
- }
- private:
- const std::unique_ptr<ISetAccumulator> SetAccum;
- };
- TSqueezeSetFlowWrapper(TComputationMutables& mutables, TType* keyType,
- IComputationNode* flow, IComputationExternalNode* item, IComputationNode* key, ui64 itemsCountHint,
- std::unique_ptr<ISetAccumulatorFactory> factory)
- : TBase(mutables, flow, EValueRepresentation::Boxed, EValueRepresentation::Any)
- , KeyType(keyType)
- , Flow(flow)
- , Item(item)
- , Key(key)
- , ItemsCountHint(itemsCountHint)
- , Factory(std::move(factory))
- {
- GetDictionaryKeyTypes(KeyType, KeyTypes, IsTuple, Encoded, UseIHash);
- Compare = UseIHash && Factory->IsSorted() ? MakeCompareImpl(KeyType) : nullptr;
- Equate = UseIHash ? MakeEquateImpl(KeyType) : nullptr;
- Hash = UseIHash && !Factory->IsSorted() ? MakeHashImpl(KeyType) : nullptr;
- }
- NUdf::TUnboxedValuePod DoCalculate(NUdf::TUnboxedValue& state, TComputationContext& ctx) const {
- if (state.IsFinish()) {
- return state.Release();
- } else if (state.IsInvalid()) {
- MakeState(ctx, state);
- }
- while (const auto statePtr = static_cast<TState*>(state.AsBoxed().Get())) {
- if (auto item = Flow->GetValue(ctx); item.IsYield()) {
- return item.Release();
- } else if (item.IsFinish()) {
- const auto dict = statePtr->Build();
- state = std::move(item);
- return dict;
- } else {
- Item->SetValue(ctx, std::move(item));
- statePtr->Insert(Key->GetValue(ctx).Release());
- }
- }
- Y_UNREACHABLE();
- }
- #ifndef MKQL_DISABLE_CODEGEN
- Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* statePtr, BasicBlock*& block) const {
- auto& context = ctx.Codegen.GetContext();
- const auto codegenItemArg = dynamic_cast<ICodegeneratorExternalNode*>(Item);
- MKQL_ENSURE(codegenItemArg, "Item must be codegenerator node.");
- const auto valueType = Type::getInt128Ty(context);
- TLLVMFieldsStructureStateWithAccum<TLLVMFieldsStructure<TComputationValue<TState>>> fieldsStruct(context);
- const auto stateType = StructType::get(context, fieldsStruct.GetFieldsArray());
- const auto statePtrType = PointerType::getUnqual(stateType);
- const auto make = BasicBlock::Create(context, "make", ctx.Func);
- const auto main = BasicBlock::Create(context, "main", ctx.Func);
- BranchInst::Create(make, main, IsInvalid(statePtr, block, context), block);
- block = make;
- 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);
- const auto makeFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TSqueezeSetFlowWrapper::MakeState));
- const auto makeType = FunctionType::get(Type::getVoidTy(context), {self->getType(), ctx.Ctx->getType(), statePtr->getType()}, false);
- const auto makeFuncPtr = CastInst::Create(Instruction::IntToPtr, makeFunc, PointerType::getUnqual(makeType), "function", block);
- CallInst::Create(makeType, makeFuncPtr, {self, ctx.Ctx, statePtr}, "", block);
- BranchInst::Create(main, block);
- block = main;
- const auto more = BasicBlock::Create(context, "more", ctx.Func);
- const auto done = BasicBlock::Create(context, "done", ctx.Func);
- const auto plus = BasicBlock::Create(context, "plus", ctx.Func);
- const auto over = BasicBlock::Create(context, "over", ctx.Func);
- const auto result = PHINode::Create(valueType, 3U, "result", over);
- const auto state = new LoadInst(valueType, statePtr, "state", block);
- const auto half = CastInst::Create(Instruction::Trunc, state, Type::getInt64Ty(context), "half", block);
- const auto stateArg = CastInst::Create(Instruction::IntToPtr, half, statePtrType, "state_arg", block);
- result->addIncoming(GetFinish(context), block);
- BranchInst::Create(over, more, IsFinish(state, block, context), block);
- block = more;
- const auto item = GetNodeValue(Flow, ctx, block);
- result->addIncoming(GetYield(context), block);
- const auto choise = SwitchInst::Create(item, plus, 2U, block);
- choise->addCase(GetFinish(context), done);
- choise->addCase(GetYield(context), over);
- block = plus;
- codegenItemArg->CreateSetValue(ctx, block, item);
- const auto key = GetNodeValue(Key, ctx, block);
- const auto insert = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Insert));
- const auto keyArg = key;
- const auto insType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), keyArg->getType()}, false);
- const auto insPtr = CastInst::Create(Instruction::IntToPtr, insert, PointerType::getUnqual(insType), "insert", block);
- CallInst::Create(insType, insPtr, {stateArg, keyArg}, "", block);
- BranchInst::Create(more, block);
- block = done;
- const auto build = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Build));
- 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);
- block = over;
- return result;
- }
- #endif
- private:
- void MakeState(TComputationContext& ctx, NUdf::TUnboxedValue& state) const {
- state = ctx.HolderFactory.Create<TState>(Factory->Create(KeyType, KeyTypes, IsTuple, Encoded,
- Compare.Get(), Equate.Get(), Hash.Get(), ctx, ItemsCountHint));
- }
- void RegisterDependencies() const final {
- if (const auto flow = this->FlowDependsOn(Flow)) {
- this->Own(flow, Item);
- this->DependsOn(flow, Key);
- }
- }
- TType* const KeyType;
- IComputationNode* const Flow;
- IComputationExternalNode* const Item;
- IComputationNode* const Key;
- const ui64 ItemsCountHint;
- const std::unique_ptr<ISetAccumulatorFactory> Factory;
- TKeyTypes KeyTypes;
- bool IsTuple;
- bool Encoded;
- bool UseIHash;
- NUdf::ICompare::TPtr Compare;
- NUdf::IEquate::TPtr Equate;
- NUdf::IHash::TPtr Hash;
- };
- class TSqueezeSetWideWrapper : public TStatefulFlowCodegeneratorNode<TSqueezeSetWideWrapper> {
- using TBase = TStatefulFlowCodegeneratorNode<TSqueezeSetWideWrapper>;
- public:
- class TState : public TComputationValue<TState> {
- using TBase = TComputationValue<TState>;
- public:
- TState(TMemoryUsageInfo* memInfo, std::unique_ptr<ISetAccumulator>&& setAccum)
- : TBase(memInfo), SetAccum(std::move(setAccum)) {}
- NUdf::TUnboxedValuePod Build() {
- return SetAccum->Build().Release();
- }
- void Insert(NUdf::TUnboxedValuePod value) {
- SetAccum->Add(value);
- }
- private:
- const std::unique_ptr<ISetAccumulator> SetAccum;
- };
- TSqueezeSetWideWrapper(TComputationMutables& mutables, TType* keyType,
- IComputationWideFlowNode* flow, TComputationExternalNodePtrVector&& items, IComputationNode* key,
- ui64 itemsCountHint, std::unique_ptr<ISetAccumulatorFactory> factory)
- : TBase(mutables, flow, EValueRepresentation::Boxed, EValueRepresentation::Any)
- , KeyType(keyType)
- , Flow(flow)
- , Items(std::move(items))
- , Key(key)
- , ItemsCountHint(itemsCountHint)
- , Factory(std::move(factory))
- , PasstroughKey(GetPasstroughtMap(TComputationNodePtrVector{Key}, Items).front())
- , WideFieldsIndex(mutables.IncrementWideFieldsIndex(Items.size()))
- {
- GetDictionaryKeyTypes(KeyType, KeyTypes, IsTuple, Encoded, UseIHash);
- Compare = UseIHash && Factory->IsSorted() ? MakeCompareImpl(KeyType) : nullptr;
- Equate = UseIHash ? MakeEquateImpl(KeyType) : nullptr;
- Hash = UseIHash && !Factory->IsSorted() ? MakeHashImpl(KeyType) : nullptr;
- }
- NUdf::TUnboxedValuePod DoCalculate(NUdf::TUnboxedValue& state, TComputationContext& ctx) const {
- if (state.IsFinish()) {
- return state.Release();
- } else if (state.IsInvalid()) {
- MakeState(ctx, state);
- }
- auto** fields = ctx.WideFields.data() + WideFieldsIndex;
- while (const auto statePtr = static_cast<TState*>(state.AsBoxed().Get())) {
- for (auto i = 0U; i < Items.size(); ++i)
- if (Key == Items[i] || Items[i]->GetDependencesCount() > 0U)
- fields[i] = &Items[i]->RefValue(ctx);
- switch (const auto result = Flow->FetchValues(ctx, fields)) {
- case EFetchResult::One:
- statePtr->Insert(Key->GetValue(ctx).Release());
- continue;
- case EFetchResult::Yield:
- return NUdf::TUnboxedValuePod::MakeYield();
- case EFetchResult::Finish: {
- const auto dict = statePtr->Build();
- state = NUdf::TUnboxedValuePod::MakeFinish();
- return dict;
- }
- }
- }
- Y_UNREACHABLE();
- }
- #ifndef MKQL_DISABLE_CODEGEN
- Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* statePtr, BasicBlock*& block) const {
- auto& context = ctx.Codegen.GetContext();
- const auto valueType = Type::getInt128Ty(context);
- TLLVMFieldsStructureStateWithAccum<TLLVMFieldsStructure<TComputationValue<TState>>> fieldsStruct(context);
- const auto stateType = StructType::get(context, fieldsStruct.GetFieldsArray());
- const auto statePtrType = PointerType::getUnqual(stateType);
- const auto make = BasicBlock::Create(context, "make", ctx.Func);
- const auto main = BasicBlock::Create(context, "main", ctx.Func);
- BranchInst::Create(make, main, IsInvalid(statePtr, block, context), block);
- block = make;
- 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);
- const auto makeFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TSqueezeSetWideWrapper::MakeState));
- const auto makeType = FunctionType::get(Type::getVoidTy(context), {self->getType(), ctx.Ctx->getType(), statePtr->getType()}, false);
- const auto makeFuncPtr = CastInst::Create(Instruction::IntToPtr, makeFunc, PointerType::getUnqual(makeType), "function", block);
- CallInst::Create(makeType, makeFuncPtr, {self, ctx.Ctx, statePtr}, "", block);
- BranchInst::Create(main, block);
- block = main;
- const auto more = BasicBlock::Create(context, "more", ctx.Func);
- const auto done = BasicBlock::Create(context, "done", ctx.Func);
- const auto plus = BasicBlock::Create(context, "plus", ctx.Func);
- const auto over = BasicBlock::Create(context, "over", ctx.Func);
- const auto result = PHINode::Create(valueType, 3U, "result", over);
- const auto state = new LoadInst(valueType, statePtr, "state", block);
- const auto half = CastInst::Create(Instruction::Trunc, state, Type::getInt64Ty(context), "half", block);
- const auto stateArg = CastInst::Create(Instruction::IntToPtr, half, statePtrType, "state_arg", block);
- result->addIncoming(GetFinish(context), block);
- BranchInst::Create(over, more, IsFinish(state, block, context), block);
- block = more;
- const auto getres = GetNodeValues(Flow, ctx, block);
- result->addIncoming(GetYield(context), block);
- const auto action = SwitchInst::Create(getres.first, plus, 2U, block);
- action->addCase(ConstantInt::get(Type::getInt32Ty(context), i32(EFetchResult::Finish)), done);
- action->addCase(ConstantInt::get(Type::getInt32Ty(context), i32(EFetchResult::Yield)), over);
- block = plus;
- if (!PasstroughKey) {
- for (auto i = 0U; i < Items.size(); ++i)
- if (Items[i]->GetDependencesCount() > 0U)
- EnsureDynamicCast<ICodegeneratorExternalNode*>(Items[i])->CreateSetValue(ctx, block, getres.second[i](ctx, block));
- }
- const auto key = PasstroughKey ? getres.second[*PasstroughKey](ctx, block) : GetNodeValue(Key, ctx, block);
- const auto insert = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Insert));
- const auto keyArg = key;
- const auto insType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), keyArg->getType()}, false);
- const auto insPtr = CastInst::Create(Instruction::IntToPtr, insert, PointerType::getUnqual(insType), "insert", block);
- CallInst::Create(insType, insPtr, {stateArg, keyArg}, "", block);
- BranchInst::Create(more, block);
- block = done;
- const auto build = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Build));
- 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);
- block = over;
- return result;
- }
- #endif
- private:
- void MakeState(TComputationContext& ctx, NUdf::TUnboxedValue& state) const {
- state = ctx.HolderFactory.Create<TState>(Factory->Create(KeyType, KeyTypes, IsTuple, Encoded,
- Compare.Get(), Equate.Get(), Hash.Get(), ctx, ItemsCountHint));
- }
- void RegisterDependencies() const final {
- if (const auto flow = this->FlowDependsOn(Flow)) {
- std::for_each(Items.cbegin(), Items.cend(), std::bind(&TSqueezeSetWideWrapper::Own, flow, std::placeholders::_1));
- this->DependsOn(flow, Key);
- }
- }
- TType* const KeyType;
- IComputationWideFlowNode* const Flow;
- const TComputationExternalNodePtrVector Items;
- IComputationNode* const Key;
- const ui64 ItemsCountHint;
- const std::unique_ptr<ISetAccumulatorFactory> Factory;
- TKeyTypes KeyTypes;
- bool IsTuple;
- bool Encoded;
- bool UseIHash;
- const std::optional<size_t> PasstroughKey;
- const ui32 WideFieldsIndex;
- NUdf::ICompare::TPtr Compare;
- NUdf::IEquate::TPtr Equate;
- NUdf::IHash::TPtr Hash;
- };
- class TMapWrapper : public TMutableComputationNode<TMapWrapper> {
- typedef TMutableComputationNode<TMapWrapper> TBaseComputation;
- public:
- class TStreamValue : public TComputationValue<TStreamValue> {
- public:
- TStreamValue(TMemoryUsageInfo* memInfo, NUdf::TUnboxedValue&& input, IComputationExternalNode* const item,
- IComputationNode* const key, IComputationNode* const payload, std::unique_ptr<IMapAccumulator>&& mapAccum, TComputationContext& ctx)
- : TComputationValue<TStreamValue>(memInfo)
- , Input(std::move(input))
- , Item(item)
- , Key(key)
- , Payload(payload)
- , MapAccum(std::move(mapAccum))
- , Ctx(ctx) {}
- private:
- NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& result) override {
- if (Finished) {
- return NUdf::EFetchStatus::Finish;
- }
- for (;;) {
- NUdf::TUnboxedValue item;
- switch (auto status = Input.Fetch(item)) {
- case NUdf::EFetchStatus::Ok: {
- Item->SetValue(Ctx, std::move(item));
- MapAccum->Add(Key->GetValue(Ctx), Payload->GetValue(Ctx));
- break; // and continue
- }
- case NUdf::EFetchStatus::Finish: {
- result = MapAccum->Build();
- Finished = true;
- return NUdf::EFetchStatus::Ok;
- }
- case NUdf::EFetchStatus::Yield: {
- return NUdf::EFetchStatus::Yield;
- }
- }
- }
- }
- NUdf::TUnboxedValue Input;
- IComputationExternalNode* const Item;
- IComputationNode* const Key;
- IComputationNode* const Payload;
- const std::unique_ptr<IMapAccumulator> MapAccum;
- TComputationContext& Ctx;
- bool Finished = false;
- };
- TMapWrapper(TComputationMutables& mutables, TType* keyType, TType* payloadType, IComputationNode* list, IComputationExternalNode* item,
- IComputationNode* key, IComputationNode* payload, ui64 itemsCountHint, bool isStream, std::unique_ptr<IMapAccumulatorFactory> factory)
- : TBaseComputation(mutables, EValueRepresentation::Boxed)
- , KeyType(keyType)
- , PayloadType(payloadType)
- , List(list)
- , Item(item)
- , Key(key)
- , Payload(payload)
- , ItemsCountHint(itemsCountHint)
- , IsStream(isStream)
- , Factory(std::move(factory))
- {
- GetDictionaryKeyTypes(KeyType, KeyTypes, IsTuple, Encoded, UseIHash);
- Compare = UseIHash && Factory->IsSorted() ? MakeCompareImpl(KeyType) : nullptr;
- Equate = UseIHash ? MakeEquateImpl(KeyType) : nullptr;
- Hash = UseIHash && !Factory->IsSorted() ? MakeHashImpl(KeyType) : nullptr;
- }
- NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const {
- if (IsStream) {
- return ctx.HolderFactory.Create<TStreamValue>(List->GetValue(ctx), Item, Key, Payload,
- Factory->Create(KeyType, PayloadType, KeyTypes, IsTuple, Encoded, Compare.Get(), Equate.Get(), Hash.Get(),
- ctx, ItemsCountHint), ctx);
- }
- const auto& list = List->GetValue(ctx);
- auto itemsCountHint = ItemsCountHint;
- if (list.HasFastListLength()) {
- if (const auto size = list.GetListLength())
- itemsCountHint = size;
- else
- return ctx.HolderFactory.GetEmptyContainerLazy();
- }
- auto acc = Factory->Create(KeyType, PayloadType, KeyTypes, IsTuple, Encoded,
- Compare.Get(), Equate.Get(), Hash.Get(), ctx, itemsCountHint);
- TThresher<false>::DoForEachItem(list,
- [this, &acc, &ctx] (NUdf::TUnboxedValue&& item) {
- Item->SetValue(ctx, std::move(item));
- acc->Add(Key->GetValue(ctx), Payload->GetValue(ctx));
- }
- );
- return acc->Build().Release();
- }
- private:
- void RegisterDependencies() const final {
- this->DependsOn(List);
- this->Own(Item);
- this->DependsOn(Key);
- this->DependsOn(Payload);
- }
- TType* const KeyType;
- TType* PayloadType;
- IComputationNode* const List;
- IComputationExternalNode* const Item;
- IComputationNode* const Key;
- IComputationNode* const Payload;
- const ui64 ItemsCountHint;
- const bool IsStream;
- const std::unique_ptr<IMapAccumulatorFactory> Factory;
- TKeyTypes KeyTypes;
- bool IsTuple;
- bool Encoded;
- bool UseIHash;
- NUdf::ICompare::TPtr Compare;
- NUdf::IEquate::TPtr Equate;
- NUdf::IHash::TPtr Hash;
- };
- class TSqueezeMapFlowWrapper : public TStatefulFlowCodegeneratorNode<TSqueezeMapFlowWrapper> {
- using TBase = TStatefulFlowCodegeneratorNode<TSqueezeMapFlowWrapper>;
- public:
- class TState : public TComputationValue<TState> {
- using TBase = TComputationValue<TState>;
- public:
- TState(TMemoryUsageInfo* memInfo, std::unique_ptr<IMapAccumulator>&& mapAccum)
- : TBase(memInfo), MapAccum(std::move(mapAccum)) {}
- NUdf::TUnboxedValuePod Build() {
- return MapAccum->Build().Release();
- }
- void Insert(NUdf::TUnboxedValuePod key, NUdf::TUnboxedValuePod value) {
- MapAccum->Add(key, value);
- }
- private:
- const std::unique_ptr<IMapAccumulator> MapAccum;
- };
- TSqueezeMapFlowWrapper(TComputationMutables& mutables, TType* keyType, TType* payloadType,
- IComputationNode* flow, IComputationExternalNode* item, IComputationNode* key, IComputationNode* payload,
- ui64 itemsCountHint, std::unique_ptr<IMapAccumulatorFactory> factory)
- : TBase(mutables, flow, EValueRepresentation::Boxed, EValueRepresentation::Any)
- , KeyType(keyType)
- , PayloadType(payloadType)
- , Flow(flow)
- , Item(item)
- , Key(key)
- , Payload(payload)
- , ItemsCountHint(itemsCountHint)
- , Factory(std::move(factory))
- {
- GetDictionaryKeyTypes(KeyType, KeyTypes, IsTuple, Encoded, UseIHash);
- Compare = UseIHash && Factory->IsSorted() ? MakeCompareImpl(KeyType) : nullptr;
- Equate = UseIHash ? MakeEquateImpl(KeyType) : nullptr;
- Hash = UseIHash && !Factory->IsSorted() ? MakeHashImpl(KeyType) : nullptr;
- }
- NUdf::TUnboxedValuePod DoCalculate(NUdf::TUnboxedValue& state, TComputationContext& ctx) const {
- if (state.IsFinish()) {
- return state;
- } else if (state.IsInvalid()) {
- MakeState(ctx, state);
- }
- while (const auto statePtr = static_cast<TState*>(state.AsBoxed().Get())) {
- if (auto item = Flow->GetValue(ctx); item.IsYield()) {
- return item.Release();
- } else if (item.IsFinish()) {
- const auto dict = statePtr->Build();
- state = std::move(item);
- return dict;
- } else {
- Item->SetValue(ctx, std::move(item));
- statePtr->Insert(Key->GetValue(ctx).Release(), Payload->GetValue(ctx).Release());
- }
- }
- Y_UNREACHABLE();
- }
- #ifndef MKQL_DISABLE_CODEGEN
- Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* statePtr, BasicBlock*& block) const {
- auto& context = ctx.Codegen.GetContext();
- const auto codegenItemArg = dynamic_cast<ICodegeneratorExternalNode*>(Item);
- MKQL_ENSURE(codegenItemArg, "Item must be codegenerator node.");
- const auto valueType = Type::getInt128Ty(context);
- TLLVMFieldsStructureStateWithAccum<TLLVMFieldsStructure<TComputationValue<TState>>> fieldsStruct(context);
- const auto stateType = StructType::get(context, fieldsStruct.GetFieldsArray());
- const auto statePtrType = PointerType::getUnqual(stateType);
- const auto make = BasicBlock::Create(context, "make", ctx.Func);
- const auto main = BasicBlock::Create(context, "main", ctx.Func);
- BranchInst::Create(make, main, IsInvalid(statePtr, block, context), block);
- block = make;
- 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);
- const auto makeFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TSqueezeMapFlowWrapper::MakeState));
- const auto makeType = FunctionType::get(Type::getVoidTy(context), {self->getType(), ctx.Ctx->getType(), statePtr->getType()}, false);
- const auto makeFuncPtr = CastInst::Create(Instruction::IntToPtr, makeFunc, PointerType::getUnqual(makeType), "function", block);
- CallInst::Create(makeType, makeFuncPtr, {self, ctx.Ctx, statePtr}, "", block);
- BranchInst::Create(main, block);
- block = main;
- const auto more = BasicBlock::Create(context, "more", ctx.Func);
- const auto done = BasicBlock::Create(context, "done", ctx.Func);
- const auto plus = BasicBlock::Create(context, "plus", ctx.Func);
- const auto over = BasicBlock::Create(context, "over", ctx.Func);
- const auto result = PHINode::Create(valueType, 3U, "result", over);
- const auto state = new LoadInst(valueType, statePtr, "state", block);
- const auto half = CastInst::Create(Instruction::Trunc, state, Type::getInt64Ty(context), "half", block);
- const auto stateArg = CastInst::Create(Instruction::IntToPtr, half, statePtrType, "state_arg", block);
- result->addIncoming(GetFinish(context), block);
- BranchInst::Create(over, more, IsFinish(state, block, context), block);
- block = more;
- const auto item = GetNodeValue(Flow, ctx, block);
- result->addIncoming(GetYield(context), block);
- const auto choise = SwitchInst::Create(item, plus, 2U, block);
- choise->addCase(GetFinish(context), done);
- choise->addCase(GetYield(context), over);
- block = plus;
- codegenItemArg->CreateSetValue(ctx, block, item);
- const auto key = GetNodeValue(Key, ctx, block);
- const auto payload = GetNodeValue(Payload, ctx, block);
- const auto insert = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Insert));
- const auto keyArg = key;
- const auto payloadArg = payload;
- const auto insType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), keyArg->getType(), payloadArg->getType()}, false);
- const auto insPtr = CastInst::Create(Instruction::IntToPtr, insert, PointerType::getUnqual(insType), "insert", block);
- CallInst::Create(insType, insPtr, {stateArg, keyArg, payloadArg}, "", block);
- BranchInst::Create(more, block);
- block = done;
- const auto build = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Build));
- 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);
- block = over;
- return result;
- }
- #endif
- private:
- void MakeState(TComputationContext& ctx, NUdf::TUnboxedValue& state) const {
- state = ctx.HolderFactory.Create<TState>(Factory->Create(KeyType, PayloadType, KeyTypes, IsTuple, Encoded,
- Compare.Get(), Equate.Get(), Hash.Get(), ctx, ItemsCountHint));
- }
- void RegisterDependencies() const final {
- if (const auto flow = this->FlowDependsOn(Flow)) {
- this->Own(flow, Item);
- this->DependsOn(flow, Key);
- this->DependsOn(flow, Payload);
- }
- }
- TType* const KeyType;
- TType* PayloadType;
- IComputationNode* const Flow;
- IComputationExternalNode* const Item;
- IComputationNode* const Key;
- IComputationNode* const Payload;
- const ui64 ItemsCountHint;
- const std::unique_ptr<IMapAccumulatorFactory> Factory;
- TKeyTypes KeyTypes;
- bool IsTuple;
- bool Encoded;
- bool UseIHash;
- NUdf::ICompare::TPtr Compare;
- NUdf::IEquate::TPtr Equate;
- NUdf::IHash::TPtr Hash;
- };
- class TSqueezeMapWideWrapper : public TStatefulFlowCodegeneratorNode<TSqueezeMapWideWrapper> {
- using TBase = TStatefulFlowCodegeneratorNode<TSqueezeMapWideWrapper>;
- public:
- class TState : public TComputationValue<TState> {
- using TBase = TComputationValue<TState>;
- public:
- TState(TMemoryUsageInfo* memInfo, std::unique_ptr<IMapAccumulator>&& mapAccum)
- : TBase(memInfo), MapAccum(std::move(mapAccum)) {}
- NUdf::TUnboxedValuePod Build() {
- return MapAccum->Build().Release();
- }
- void Insert(NUdf::TUnboxedValuePod key, NUdf::TUnboxedValuePod value) {
- MapAccum->Add(key, value);
- }
- private:
- const std::unique_ptr<IMapAccumulator> MapAccum;
- };
- TSqueezeMapWideWrapper(TComputationMutables& mutables, TType* keyType, TType* payloadType,
- IComputationWideFlowNode* flow, TComputationExternalNodePtrVector&& items, IComputationNode* key, IComputationNode* payload,
- ui64 itemsCountHint, std::unique_ptr<IMapAccumulatorFactory> factory)
- : TBase(mutables, flow, EValueRepresentation::Boxed, EValueRepresentation::Any)
- , KeyType(keyType)
- , PayloadType(payloadType)
- , Flow(flow)
- , Items(std::move(items))
- , Key(key)
- , Payload(payload)
- , ItemsCountHint(itemsCountHint)
- , Factory(std::move(factory))
- , PasstroughKey(GetPasstroughtMap(TComputationNodePtrVector{Key}, Items).front())
- , PasstroughPayload(GetPasstroughtMap(TComputationNodePtrVector{Payload}, Items).front())
- , WideFieldsIndex(mutables.IncrementWideFieldsIndex(Items.size()))
- {
- GetDictionaryKeyTypes(KeyType, KeyTypes, IsTuple, Encoded, UseIHash);
- Compare = UseIHash && Factory->IsSorted() ? MakeCompareImpl(KeyType) : nullptr;
- Equate = UseIHash ? MakeEquateImpl(KeyType) : nullptr;
- Hash = UseIHash && !Factory->IsSorted() ? MakeHashImpl(KeyType) : nullptr;
- }
- NUdf::TUnboxedValuePod DoCalculate(NUdf::TUnboxedValue& state, TComputationContext& ctx) const {
- if (state.IsFinish()) {
- return state;
- } else if (state.IsInvalid()) {
- MakeState(ctx, state);
- }
- auto** fields = ctx.WideFields.data() + WideFieldsIndex;
- while (const auto statePtr = static_cast<TState*>(state.AsBoxed().Get())) {
- for (auto i = 0U; i < Items.size(); ++i)
- if (Key == Items[i] || Payload == Items[i] || Items[i]->GetDependencesCount() > 0U)
- fields[i] = &Items[i]->RefValue(ctx);
- switch (const auto result = Flow->FetchValues(ctx, fields)) {
- case EFetchResult::One:
- statePtr->Insert(Key->GetValue(ctx).Release(), Payload->GetValue(ctx).Release());
- continue;
- case EFetchResult::Yield:
- return NUdf::TUnboxedValuePod::MakeYield();
- case EFetchResult::Finish: {
- const auto dict = statePtr->Build();
- state = NUdf::TUnboxedValuePod::MakeFinish();
- return dict;
- }
- }
- }
- Y_UNREACHABLE();
- }
- #ifndef MKQL_DISABLE_CODEGEN
- Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* statePtr, BasicBlock*& block) const {
- auto& context = ctx.Codegen.GetContext();
- const auto valueType = Type::getInt128Ty(context);
- TLLVMFieldsStructureStateWithAccum<TLLVMFieldsStructure<TComputationValue<TState>>> fieldsStruct(context);
- const auto stateType = StructType::get(context, fieldsStruct.GetFieldsArray());
- const auto statePtrType = PointerType::getUnqual(stateType);
- const auto make = BasicBlock::Create(context, "make", ctx.Func);
- const auto main = BasicBlock::Create(context, "main", ctx.Func);
- BranchInst::Create(make, main, IsInvalid(statePtr, block, context), block);
- block = make;
- 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);
- const auto makeFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TSqueezeMapWideWrapper::MakeState));
- const auto makeType = FunctionType::get(Type::getVoidTy(context), {self->getType(), ctx.Ctx->getType(), statePtr->getType()}, false);
- const auto makeFuncPtr = CastInst::Create(Instruction::IntToPtr, makeFunc, PointerType::getUnqual(makeType), "function", block);
- CallInst::Create(makeType, makeFuncPtr, {self, ctx.Ctx, statePtr}, "", block);
- BranchInst::Create(main, block);
- block = main;
- const auto more = BasicBlock::Create(context, "more", ctx.Func);
- const auto done = BasicBlock::Create(context, "done", ctx.Func);
- const auto plus = BasicBlock::Create(context, "plus", ctx.Func);
- const auto over = BasicBlock::Create(context, "over", ctx.Func);
- const auto result = PHINode::Create(valueType, 3U, "result", over);
- const auto state = new LoadInst(valueType, statePtr, "state", block);
- const auto half = CastInst::Create(Instruction::Trunc, state, Type::getInt64Ty(context), "half", block);
- const auto stateArg = CastInst::Create(Instruction::IntToPtr, half, statePtrType, "state_arg", block);
- result->addIncoming(GetFinish(context), block);
- BranchInst::Create(over, more, IsFinish(state, block, context), block);
- block = more;
- const auto getres = GetNodeValues(Flow, ctx, block);
- result->addIncoming(GetYield(context), block);
- const auto action = SwitchInst::Create(getres.first, plus, 2U, block);
- action->addCase(ConstantInt::get(Type::getInt32Ty(context), i32(EFetchResult::Finish)), done);
- action->addCase(ConstantInt::get(Type::getInt32Ty(context), i32(EFetchResult::Yield)), over);
- block = plus;
- if (!(PasstroughKey && PasstroughPayload)) {
- for (auto i = 0U; i < Items.size(); ++i)
- if (Items[i]->GetDependencesCount() > 0U)
- EnsureDynamicCast<ICodegeneratorExternalNode*>(Items[i])->CreateSetValue(ctx, block, getres.second[i](ctx, block));
- }
- const auto key = PasstroughKey ? getres.second[*PasstroughKey](ctx, block) : GetNodeValue(Key, ctx, block);
- const auto payload = PasstroughPayload ? getres.second[*PasstroughPayload](ctx, block) : GetNodeValue(Payload, ctx, block);
- const auto insert = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Insert));
- const auto keyArg = key;
- const auto payloadArg = payload;
- const auto insType = FunctionType::get(Type::getVoidTy(context), {stateArg->getType(), keyArg->getType(), payloadArg->getType()}, false);
- const auto insPtr = CastInst::Create(Instruction::IntToPtr, insert, PointerType::getUnqual(insType), "insert", block);
- CallInst::Create(insType, insPtr, {stateArg, keyArg, payloadArg}, "", block);
- BranchInst::Create(more, block);
- block = done;
- const auto build = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TState::Build));
- 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);
- block = over;
- return result;
- }
- #endif
- private:
- void MakeState(TComputationContext& ctx, NUdf::TUnboxedValue& state) const {
- state = ctx.HolderFactory.Create<TState>(Factory->Create(KeyType, PayloadType, KeyTypes, IsTuple, Encoded,
- Compare.Get(), Equate.Get(), Hash.Get(), ctx, ItemsCountHint));
- }
- void RegisterDependencies() const final {
- if (const auto flow = this->FlowDependsOn(Flow)) {
- std::for_each(Items.cbegin(), Items.cend(), std::bind(&TSqueezeMapWideWrapper::Own, flow, std::placeholders::_1));
- this->DependsOn(flow, Key);
- this->DependsOn(flow, Payload);
- }
- }
- TType* const KeyType;
- TType* PayloadType;
- IComputationWideFlowNode* const Flow;
- const TComputationExternalNodePtrVector Items;
- IComputationNode* const Key;
- IComputationNode* const Payload;
- const ui64 ItemsCountHint;
- const std::unique_ptr<IMapAccumulatorFactory> Factory;
- TKeyTypes KeyTypes;
- bool IsTuple;
- bool Encoded;
- bool UseIHash;
- const std::optional<size_t> PasstroughKey;
- const std::optional<size_t> PasstroughPayload;
- mutable std::vector<NUdf::TUnboxedValue*> Fields;
- const ui32 WideFieldsIndex;
- NUdf::ICompare::TPtr Compare;
- NUdf::IEquate::TPtr Equate;
- NUdf::IHash::TPtr Hash;
- };
- template <typename TAccumulator>
- IComputationNode* WrapToSet(TCallable& callable, const TNodeLocator& nodeLocator, TComputationMutables& mutables) {
- const auto keyType = callable.GetInput(callable.GetInputsCount() - 5U).GetStaticType();
- const auto itemsCountHint = AS_VALUE(TDataLiteral, callable.GetInput(callable.GetInputsCount() - 1U))->AsValue().Get<ui64>();
- const auto flow = LocateNode(nodeLocator, callable, 0U);
- const auto keySelector = LocateNode(nodeLocator, callable, callable.GetInputsCount() - 5U);
- auto factory = std::make_unique<TSetAccumulatorFactory<TAccumulator>>();
- if (const auto wide = dynamic_cast<IComputationWideFlowNode*>(flow)) {
- const auto width = callable.GetInputsCount() - 6U;
- TComputationExternalNodePtrVector args(width, nullptr);
- auto index = 0U;
- std::generate_n(args.begin(), width, [&](){ return LocateExternalNode(nodeLocator, callable, ++index); });
- return new TSqueezeSetWideWrapper(mutables, keyType, wide, std::move(args), keySelector, itemsCountHint, std::move(factory));
- }
- const auto itemArg = LocateExternalNode(nodeLocator, callable, 1U);
- const auto type = callable.GetInput(0U).GetStaticType();
- if (type->IsList()) {
- return new TSetWrapper(mutables, keyType, flow, itemArg, keySelector, itemsCountHint, false, std::move(factory));
- }
- if (type->IsFlow()) {
- return new TSqueezeSetFlowWrapper(mutables, keyType, flow, itemArg, keySelector, itemsCountHint, std::move(factory));
- }
- if (type->IsStream()) {
- return new TSetWrapper(mutables, keyType, flow, itemArg, keySelector, itemsCountHint, true, std::move(factory));
- }
- THROW yexception() << "Expected list, flow or stream.";
- }
- template <typename TAccumulator>
- IComputationNode* WrapToMap(TCallable& callable, const TNodeLocator& nodeLocator, TComputationMutables& mutables) {
- const auto keyType = callable.GetInput(callable.GetInputsCount() - 5U).GetStaticType();
- const auto payloadType = callable.GetInput(callable.GetInputsCount() - 4U).GetStaticType();
- const auto itemsCountHint = AS_VALUE(TDataLiteral, callable.GetInput(callable.GetInputsCount() - 1U))->AsValue().Get<ui64>();
- const auto flow = LocateNode(nodeLocator, callable, 0U);
- const auto keySelector = LocateNode(nodeLocator, callable, callable.GetInputsCount() - 5U);
- const auto payloadSelector = LocateNode(nodeLocator, callable, callable.GetInputsCount() - 4U);
- auto factory = std::make_unique<TMapAccumulatorFactory<TAccumulator>>();
- if (const auto wide = dynamic_cast<IComputationWideFlowNode*>(flow)) {
- const auto width = callable.GetInputsCount() - 6U;
- TComputationExternalNodePtrVector args(width, nullptr);
- auto index = 0U;
- std::generate(args.begin(), args.end(), [&](){ return LocateExternalNode(nodeLocator, callable, ++index); });
- return new TSqueezeMapWideWrapper(mutables, keyType, payloadType, wide, std::move(args), keySelector, payloadSelector, itemsCountHint, std::move(factory));
- }
- const auto itemArg = LocateExternalNode(nodeLocator, callable, 1U);
- const auto type = callable.GetInput(0U).GetStaticType();
- if (type->IsList()) {
- return new TMapWrapper(mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector, itemsCountHint, false, std::move(factory));
- }
- if (type->IsFlow()) {
- return new TSqueezeMapFlowWrapper(mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector, itemsCountHint, std::move(factory));
- }
- if (type->IsStream()) {
- return new TMapWrapper(mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector, itemsCountHint, true, std::move(factory));
- }
- THROW yexception() << "Expected list, flow or stream.";
- }
- IComputationNode* WrapToSortedDictInternal(TCallable& callable, const TComputationNodeFactoryContext& ctx, bool isList) {
- MKQL_ENSURE(callable.GetInputsCount() >= 6U, "Expected six or more args.");
- const auto type = callable.GetInput(0U).GetStaticType();
- if (isList) {
- MKQL_ENSURE(type->IsList(), "Expected list.");
- } else {
- MKQL_ENSURE(type->IsFlow() || type->IsStream(), "Expected flow or stream.");
- }
- const auto keyType = callable.GetInput(callable.GetInputsCount() - 5U).GetStaticType();
- const auto payloadType = callable.GetInput(callable.GetInputsCount() - 4U).GetStaticType();
- const auto multiData = AS_VALUE(TDataLiteral, callable.GetInput(callable.GetInputsCount() - 3U));
- const bool isMulti = multiData->AsValue().Get<bool>();
- const auto itemsCountHint = AS_VALUE(TDataLiteral, callable.GetInput(callable.GetInputsCount() - 1U))->AsValue().Get<ui64>();
- const auto flow = LocateNode(ctx.NodeLocator, callable, 0U);
- const auto keySelector = LocateNode(ctx.NodeLocator, callable, callable.GetInputsCount() -5U);
- const auto payloadSelector = LocateNode(ctx.NodeLocator, callable, callable.GetInputsCount() -4U);
- if (const auto wide = dynamic_cast<IComputationWideFlowNode*>(flow)) {
- const auto width = callable.GetInputsCount() - 6U;
- TComputationExternalNodePtrVector args(width, nullptr);
- auto index = 0U;
- std::generate(args.begin(), args.end(), [&](){ return LocateExternalNode(ctx.NodeLocator, callable, ++index); });
- if (!isMulti && payloadType->IsVoid()) {
- return new TSqueezeSetWideWrapper(ctx.Mutables, keyType, wide, std::move(args), keySelector, itemsCountHint,
- std::make_unique<TSetAccumulatorFactory<TSortedSetAccumulator>>());
- } else if (isMulti) {
- return new TSqueezeMapWideWrapper(ctx.Mutables, keyType, payloadType, wide, std::move(args), keySelector, payloadSelector, itemsCountHint,
- std::make_unique<TMapAccumulatorFactory<TSortedMapAccumulator<true>>>());
- } else {
- return new TSqueezeMapWideWrapper(ctx.Mutables, keyType, payloadType, wide, std::move(args), keySelector, payloadSelector, itemsCountHint,
- std::make_unique<TMapAccumulatorFactory<TSortedMapAccumulator<false>>>());
- }
- }
- const auto itemArg = LocateExternalNode(ctx.NodeLocator, callable, 1U);
- if (!isMulti && payloadType->IsVoid()) {
- auto factory = std::make_unique<TSetAccumulatorFactory<TSortedSetAccumulator>>();
- if (type->IsList()) {
- return new TSetWrapper(ctx.Mutables, keyType, flow, itemArg, keySelector, itemsCountHint,
- false, std::move(factory));
- }
- if (type->IsFlow()) {
- return new TSqueezeSetFlowWrapper(ctx.Mutables, keyType, flow, itemArg, keySelector,
- itemsCountHint, std::move(factory));
- }
- if (type->IsStream()) {
- return new TSetWrapper(ctx.Mutables, keyType, flow, itemArg, keySelector, itemsCountHint,
- true, std::move(factory));
- }
- } else if (isMulti) {
- auto factory = std::make_unique<TMapAccumulatorFactory<TSortedMapAccumulator<true>>>();
- if (type->IsList()) {
- return new TMapWrapper(ctx.Mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector, itemsCountHint,
- false, std::move(factory));
- }
- if (type->IsFlow()) {
- return new TSqueezeMapFlowWrapper(ctx.Mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector,
- itemsCountHint, std::move(factory));
- }
- if (type->IsStream()) {
- return new TMapWrapper(ctx.Mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector, itemsCountHint,
- true, std::move(factory));
- }
- } else {
- auto factory = std::make_unique<TMapAccumulatorFactory<TSortedMapAccumulator<false>>>();
- if (type->IsList()) {
- return new TMapWrapper(ctx.Mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector, itemsCountHint,
- false, std::move(factory));
- }
- if (type->IsFlow()) {
- return new TSqueezeMapFlowWrapper(ctx.Mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector,
- itemsCountHint, std::move(factory));
- }
- if (type->IsStream()) {
- return new TMapWrapper(ctx.Mutables, keyType, payloadType, flow, itemArg, keySelector, payloadSelector, itemsCountHint,
- true, std::move(factory));
- }
- }
- THROW yexception() << "Expected list, flow or stream.";
- }
- IComputationNode* WrapToHashedDictInternal(TCallable& callable, const TComputationNodeFactoryContext& ctx, bool isList) {
- MKQL_ENSURE(callable.GetInputsCount() >= 6U, "Expected six or more args.");
- const auto type = callable.GetInput(0U).GetStaticType();
- if (isList) {
- MKQL_ENSURE(type->IsList(), "Expected list.");
- } else {
- MKQL_ENSURE(type->IsFlow() || type->IsStream(), "Expected flow or stream.");
- }
- const auto keyType = callable.GetInput(callable.GetInputsCount() - 5U).GetStaticType();
- const auto payloadType = callable.GetInput(callable.GetInputsCount() - 4U).GetStaticType();
- const bool multi = AS_VALUE(TDataLiteral, callable.GetInput(callable.GetInputsCount() - 3U))->AsValue().Get<bool>();
- const bool isCompact = AS_VALUE(TDataLiteral, callable.GetInput(callable.GetInputsCount() - 2U))->AsValue().Get<bool>();
- const auto payloadSelectorNode = callable.GetInput(callable.GetInputsCount() - 4U);
- const bool isOptional = keyType->IsOptional();
- const auto unwrappedKeyType = isOptional ? AS_TYPE(TOptionalType, keyType)->GetItemType() : keyType;
- if (!multi && payloadType->IsVoid()) {
- if (isCompact) {
- if (unwrappedKeyType->IsData()) {
- #define USE_HASHED_SINGLE_FIXED_COMPACT_SET(xType, xLayoutType) \
- case NUdf::TDataType<xType>::Id: \
- if (isOptional) { \
- return WrapToSet< \
- THashedSingleFixedCompactSetAccumulator<xLayoutType, true>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } else { \
- return WrapToSet< \
- THashedSingleFixedCompactSetAccumulator<xLayoutType, false>>(callable, ctx.NodeLocator, ctx.Mutables); \
- }
- switch (AS_TYPE(TDataType, unwrappedKeyType)->GetSchemeType()) {
- KNOWN_FIXED_VALUE_TYPES(USE_HASHED_SINGLE_FIXED_COMPACT_SET)
- }
- #undef USE_HASHED_SINGLE_FIXED_COMPACT_SET
- }
- return WrapToSet<THashedCompactSetAccumulator>(callable, ctx.NodeLocator, ctx.Mutables);
- }
- if (unwrappedKeyType->IsData()) {
- #define USE_HASHED_SINGLE_FIXED_SET(xType, xLayoutType) \
- case NUdf::TDataType<xType>::Id: \
- if (isOptional) { \
- return WrapToSet< \
- THashedSingleFixedSetAccumulator<xLayoutType, true>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } else { \
- return WrapToSet< \
- THashedSingleFixedSetAccumulator<xLayoutType, false>>(callable, ctx.NodeLocator, ctx.Mutables); \
- }
- switch (AS_TYPE(TDataType, unwrappedKeyType)->GetSchemeType()) {
- KNOWN_FIXED_VALUE_TYPES(USE_HASHED_SINGLE_FIXED_SET)
- }
- #undef USE_HASHED_SINGLE_FIXED_SET
- }
- return WrapToSet<THashedSetAccumulator>(callable, ctx.NodeLocator, ctx.Mutables);
- }
- if (isCompact) {
- if (unwrappedKeyType->IsData()) {
- #define USE_HASHED_SINGLE_FIXED_COMPACT_MAP(xType, xLayoutType) \
- case NUdf::TDataType<xType>::Id: \
- if (multi) { \
- if (isOptional) { \
- return WrapToMap< \
- THashedSingleFixedCompactMapAccumulator<xLayoutType, true, true>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } else { \
- return WrapToMap< \
- THashedSingleFixedCompactMapAccumulator<xLayoutType, false, true>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } \
- } else { \
- if (isOptional) { \
- return WrapToMap< \
- THashedSingleFixedCompactMapAccumulator<xLayoutType, true, false>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } else { \
- return WrapToMap< \
- THashedSingleFixedCompactMapAccumulator<xLayoutType, false, false>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } \
- }
- switch (AS_TYPE(TDataType, unwrappedKeyType)->GetSchemeType()) {
- KNOWN_FIXED_VALUE_TYPES(USE_HASHED_SINGLE_FIXED_COMPACT_MAP)
- }
- #undef USE_HASHED_SINGLE_FIXED_COMPACT_MAP
- }
- if (multi) {
- return WrapToMap<THashedCompactMapAccumulator<true>>(callable, ctx.NodeLocator, ctx.Mutables);
- } else {
- return WrapToMap<THashedCompactMapAccumulator<false>>(callable, ctx.NodeLocator, ctx.Mutables);
- }
- }
- if (unwrappedKeyType->IsData()) {
- #define USE_HASHED_SINGLE_FIXED_MAP(xType, xLayoutType) \
- case NUdf::TDataType<xType>::Id: \
- if (multi) { \
- if (isOptional) { \
- return WrapToMap< \
- THashedSingleFixedMultiMapAccumulator<xLayoutType, true>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } else { \
- return WrapToMap< \
- THashedSingleFixedMultiMapAccumulator<xLayoutType, false>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } \
- } else { \
- if (isOptional) { \
- return WrapToMap< \
- THashedSingleFixedMapAccumulator<xLayoutType, true>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } else { \
- return WrapToMap< \
- THashedSingleFixedMapAccumulator<xLayoutType, false>>(callable, ctx.NodeLocator, ctx.Mutables); \
- } \
- }
- switch (AS_TYPE(TDataType, unwrappedKeyType)->GetSchemeType()) {
- KNOWN_FIXED_VALUE_TYPES(USE_HASHED_SINGLE_FIXED_MAP)
- }
- #undef USE_HASHED_SINGLE_FIXED_MAP
- }
- if (multi) {
- return WrapToMap<THashedMultiMapAccumulator>(callable, ctx.NodeLocator, ctx.Mutables);
- } else {
- return WrapToMap<THashedMapAccumulator>(callable, ctx.NodeLocator, ctx.Mutables);
- }
- }
- }
- IComputationNode* WrapToSortedDict(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
- return WrapToSortedDictInternal(callable, ctx, true);
- }
- IComputationNode* WrapToHashedDict(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
- return WrapToHashedDictInternal(callable, ctx, true);
- }
- IComputationNode* WrapSqueezeToSortedDict(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
- return WrapToSortedDictInternal(callable, ctx, false);
- }
- IComputationNode* WrapSqueezeToHashedDict(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
- return WrapToHashedDictInternal(callable, ctx, false);
- }
- }
- }
|