diff --git a/3rdparty/tvm b/3rdparty/tvm index 7c8a0f4c57..e0aadc73ce 160000 --- a/3rdparty/tvm +++ b/3rdparty/tvm @@ -1 +1 @@ -Subproject commit 7c8a0f4c579f4293108343594a7c8834c63d9127 +Subproject commit e0aadc73ce9b3a2a205a30b7681c553ccfc1afbf diff --git a/cpp/serve/config.cc b/cpp/serve/config.cc index 84e3cfbb7c..467948590a 100644 --- a/cpp/serve/config.cc +++ b/cpp/serve/config.cc @@ -20,6 +20,11 @@ namespace mlc { namespace llm { namespace serve { +TVM_FFI_STATIC_INIT_BLOCK() { + GenerationConfigNode::RegisterReflection(); + EngineConfigNode::RegisterReflection(); +} + uint64_t TotalDetectGlobalMemory(DLDevice device) { // Get single-card GPU size. tvm::ffi::Any rv; diff --git a/cpp/serve/config.h b/cpp/serve/config.h index 27badee344..914d26cefa 100644 --- a/cpp/serve/config.h +++ b/cpp/serve/config.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -135,6 +136,11 @@ class GenerationConfigNode : public Object { picojson::object AsJSON() const; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; TVM_FFI_DECLARE_OBJECT_INFO("mlc.serve.GenerationConfig", GenerationConfigNode, Object); @@ -302,6 +308,11 @@ class EngineConfigNode : public Object { String AsJSONString() const; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/data.cc b/cpp/serve/data.cc index 90426184f8..1f224774f0 100644 --- a/cpp/serve/data.cc +++ b/cpp/serve/data.cc @@ -13,6 +13,14 @@ namespace mlc { namespace llm { namespace serve { +TVM_FFI_STATIC_INIT_BLOCK() { + DataNode::RegisterReflection(); + TextDataNode::RegisterReflection(); + TokenDataNode::RegisterReflection(); + ImageDataNode::RegisterReflection(); + RequestStreamOutputObj::RegisterReflection(); +} + /****************** Data ******************/ std::pair, Array> SplitData(const Array& original_data, int total_length, diff --git a/cpp/serve/data.h b/cpp/serve/data.h index 102f2313e5..9394e9149b 100644 --- a/cpp/serve/data.h +++ b/cpp/serve/data.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -50,8 +51,14 @@ class DataNode : public Object { */ virtual ObjectRef GetEmbedding(Model model, ObjectRef* dst = nullptr, int offset = 0) const = 0; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; + static constexpr const uint32_t _type_child_slots = 3; TVM_FFI_DECLARE_OBJECT_INFO("mlc.serve.Data", DataNode, Object); }; @@ -75,7 +82,12 @@ class TextDataNode : public DataNode { int GetLength() const final; ObjectRef GetEmbedding(Model model, ObjectRef* dst = nullptr, int offset = 0) const final; - TVM_FFI_DECLARE_OBJECT_INFO("mlc.serve.TextData", TextDataNode, DataNode); + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + + TVM_FFI_DECLARE_OBJECT_INFO_FINAL("mlc.serve.TextData", TextDataNode, DataNode); }; class TextData : public Data { @@ -96,7 +108,12 @@ class TokenDataNode : public DataNode { int GetLength() const final; ObjectRef GetEmbedding(Model model, ObjectRef* dst = nullptr, int offset = 0) const final; - TVM_FFI_DECLARE_OBJECT_INFO("mlc.serve.TokenData", TokenDataNode, DataNode); + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + + TVM_FFI_DECLARE_OBJECT_INFO_FINAL("mlc.serve.TokenData", TokenDataNode, DataNode); }; class TokenData : public Data { @@ -120,7 +137,12 @@ class ImageDataNode : public DataNode { int GetLength() const final; ObjectRef GetEmbedding(Model model, ObjectRef* dst = nullptr, int offset = 0) const final; - TVM_FFI_DECLARE_OBJECT_INFO("mlc.serve.ImageData", ImageDataNode, DataNode); + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + + TVM_FFI_DECLARE_OBJECT_INFO_FINAL("mlc.serve.ImageData", ImageDataNode, DataNode); }; class ImageData : public Data { @@ -197,6 +219,11 @@ class RequestStreamOutputObj : public Object { std::atomic unpacked = false; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/draft_token_workspace_manager.cc b/cpp/serve/draft_token_workspace_manager.cc index d7492f041c..3188737c52 100644 --- a/cpp/serve/draft_token_workspace_manager.cc +++ b/cpp/serve/draft_token_workspace_manager.cc @@ -11,6 +11,8 @@ namespace mlc { namespace llm { namespace serve { +TVM_FFI_STATIC_INIT_BLOCK() { DraftTokenWorkspaceManagerObj::RegisterReflection(); } + DraftTokenWorkspaceManagerObj::DraftTokenWorkspaceManagerObj(int max_num_tokens, int vocab_size, int hidden_size, DLDataType hidden_states_dtype, diff --git a/cpp/serve/draft_token_workspace_manager.h b/cpp/serve/draft_token_workspace_manager.h index dba4ab78ed..914723f8e5 100644 --- a/cpp/serve/draft_token_workspace_manager.h +++ b/cpp/serve/draft_token_workspace_manager.h @@ -5,6 +5,7 @@ #ifndef MLC_LLM_SERVE_DRAFT_TOKEN_WORKSPACE_MANAGER_H_ #define MLC_LLM_SERVE_DRAFT_TOKEN_WORKSPACE_MANAGER_H_ +#include #include #include @@ -73,6 +74,11 @@ class DraftTokenWorkspaceManagerObj : public Object { */ void FreeSlots(const std::vector& slots); + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/engine_actions/action.cc b/cpp/serve/engine_actions/action.cc index 5d04fa949c..a74463f7f1 100644 --- a/cpp/serve/engine_actions/action.cc +++ b/cpp/serve/engine_actions/action.cc @@ -7,6 +7,10 @@ namespace mlc { namespace llm { -namespace serve {} // namespace serve +namespace serve { + +TVM_FFI_STATIC_INIT_BLOCK() { EngineActionObj::RegisterReflection(); } + +} // namespace serve } // namespace llm } // namespace mlc diff --git a/cpp/serve/engine_actions/action.h b/cpp/serve/engine_actions/action.h index 4a5e2d0f9d..69cc5d534d 100644 --- a/cpp/serve/engine_actions/action.h +++ b/cpp/serve/engine_actions/action.h @@ -38,6 +38,11 @@ class EngineActionObj : public Object { */ virtual Array Step(EngineState estate) = 0; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/engine_state.cc b/cpp/serve/engine_state.cc index 742ab9b7f6..110880bae6 100644 --- a/cpp/serve/engine_state.cc +++ b/cpp/serve/engine_state.cc @@ -8,6 +8,8 @@ namespace mlc { namespace llm { namespace serve { +TVM_FFI_STATIC_INIT_BLOCK() { EngineStateObj::RegisterReflection(); } + EngineState::EngineState() { data_ = tvm::ffi::make_object(); } void EngineStateObj::Reset() { diff --git a/cpp/serve/engine_state.h b/cpp/serve/engine_state.h index 0b36b8b72e..78585e0409 100644 --- a/cpp/serve/engine_state.h +++ b/cpp/serve/engine_state.h @@ -98,6 +98,11 @@ class EngineStateObj : public Object { /*! \brief Return the running request state entries*/ const std::vector& GetRunningRequestStateEntries(); + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/event_trace_recorder.cc b/cpp/serve/event_trace_recorder.cc index 2978bd0e84..15c692c653 100644 --- a/cpp/serve/event_trace_recorder.cc +++ b/cpp/serve/event_trace_recorder.cc @@ -149,6 +149,7 @@ EventTraceRecorder EventTraceRecorder::Create() { TVM_FFI_STATIC_INIT_BLOCK() { namespace refl = tvm::ffi::reflection; + EventTraceRecorderImpl::RegisterReflection(); refl::GlobalDef() .def("mlc.serve.EventTraceRecorder", []() { return EventTraceRecorder::Create(); }) .def("mlc.serve.EventTraceRecorderAddEvent", diff --git a/cpp/serve/event_trace_recorder.h b/cpp/serve/event_trace_recorder.h index 64277a07c5..0dadb130cd 100644 --- a/cpp/serve/event_trace_recorder.h +++ b/cpp/serve/event_trace_recorder.h @@ -7,6 +7,7 @@ #define MLC_LLM_SERVE_EVENT_TRACE_RECORDER_H_ #include +#include #include #include @@ -41,6 +42,11 @@ class EventTraceRecorderObj : public Object { /*! \brief Dump the logged events in Chrome Trace Event Format in JSON string. */ virtual std::string DumpJSON() = 0; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/logit_processor.cc b/cpp/serve/logit_processor.cc index 5b4373c8bb..b3ca4ef615 100644 --- a/cpp/serve/logit_processor.cc +++ b/cpp/serve/logit_processor.cc @@ -32,6 +32,8 @@ inline void SyncCopyStream(Device device, TVMStreamHandle compute_stream, /***************** LogitProcessor Implementation *****************/ +TVM_FFI_STATIC_INIT_BLOCK() { LogitProcessorObj::RegisterReflection(); } + class LogitProcessorImpl : public LogitProcessorObj { public: /*! * \brief Constructor of LogitProcessorImpl. */ diff --git a/cpp/serve/logit_processor.h b/cpp/serve/logit_processor.h index 48e4eb191a..0d15c0cd5a 100644 --- a/cpp/serve/logit_processor.h +++ b/cpp/serve/logit_processor.h @@ -68,6 +68,11 @@ class LogitProcessorObj : public Object { const Array& request_ids, const std::vector* cum_num_token = nullptr) = 0; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/model.cc b/cpp/serve/model.cc index 568501dd7e..958d36b7ca 100644 --- a/cpp/serve/model.cc +++ b/cpp/serve/model.cc @@ -23,6 +23,8 @@ namespace serve { /*********************** Model Implementation ***********************/ +TVM_FFI_STATIC_INIT_BLOCK() { ModelObj::RegisterReflection(); } + class ModelImpl; Model Model::Create(String reload_lib_path, String model_path, const picojson::object& model_config, diff --git a/cpp/serve/model.h b/cpp/serve/model.h index d5567a0411..68a5a5ba14 100644 --- a/cpp/serve/model.h +++ b/cpp/serve/model.h @@ -364,6 +364,11 @@ class ModelObj : public Object { /*! \brief Call the given global function on all workers. Only for debug purpose. */ virtual void DebugCallFuncOnAllAllWorker(const String& func_name, Optional func_args) = 0; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/prefix_cache.cc b/cpp/serve/prefix_cache.cc index c1b082629a..f88c3ad55d 100644 --- a/cpp/serve/prefix_cache.cc +++ b/cpp/serve/prefix_cache.cc @@ -13,6 +13,8 @@ namespace serve { using namespace tvm::runtime; +TVM_FFI_STATIC_INIT_BLOCK() { PrefixCacheObj::RegisterReflection(); } + /*! * \brief The implementation of prefix cache. */ diff --git a/cpp/serve/prefix_cache.h b/cpp/serve/prefix_cache.h index fdd1265662..78f5c9e90f 100644 --- a/cpp/serve/prefix_cache.h +++ b/cpp/serve/prefix_cache.h @@ -5,6 +5,7 @@ #ifndef MLC_LLM_SERVE_PREFIX_CACHE_H_ #define MLC_LLM_SERVE_PREFIX_CACHE_H_ #include +#include #include #include @@ -122,6 +123,11 @@ class PrefixCacheObj : public Object { /*! \brief Return the prefix cache mode. */ virtual PrefixCacheMode Mode() = 0; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_mutable = true; TVM_FFI_DECLARE_OBJECT_INFO("mlc.serve.PrefixCache", PrefixCacheObj, Object); }; diff --git a/cpp/serve/radix_tree.cc b/cpp/serve/radix_tree.cc index 3f2e6782e4..07570f1b42 100644 --- a/cpp/serve/radix_tree.cc +++ b/cpp/serve/radix_tree.cc @@ -14,6 +14,8 @@ namespace serve { using namespace tvm::runtime; +TVM_FFI_STATIC_INIT_BLOCK() { PagedRadixTreeObj::RegisterReflection(); } + /*! * \brief The sequence ID linked list structure in paged radix tree node. */ diff --git a/cpp/serve/radix_tree.h b/cpp/serve/radix_tree.h index 847b993ba2..e966721687 100644 --- a/cpp/serve/radix_tree.h +++ b/cpp/serve/radix_tree.h @@ -5,6 +5,7 @@ #ifndef MLC_LLM_SERVE_RADIX_TREE_H_ #define MLC_LLM_SERVE_RADIX_TREE_H_ #include +#include #include #include @@ -107,6 +108,11 @@ class PagedRadixTreeObj : public Object { */ virtual void Reset() = 0; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_mutable = true; TVM_FFI_DECLARE_OBJECT_INFO("mlc.serve.PagedRadixTree", PagedRadixTreeObj, Object); }; diff --git a/cpp/serve/request.cc b/cpp/serve/request.cc index a3344228ee..3f37a792da 100644 --- a/cpp/serve/request.cc +++ b/cpp/serve/request.cc @@ -16,6 +16,8 @@ namespace serve { /****************** Request ******************/ +TVM_FFI_STATIC_INIT_BLOCK() { RequestNode::RegisterReflection(); } + Request::Request(String id, Array inputs, GenerationConfig generation_cfg) { if (generation_cfg->debug_config.special_request == SpecialRequestKind::kNone) { CHECK(!inputs.empty()) << "No input data is given."; diff --git a/cpp/serve/request.h b/cpp/serve/request.h index 3e9fdcae7e..573325f9e7 100644 --- a/cpp/serve/request.h +++ b/cpp/serve/request.h @@ -7,6 +7,7 @@ #define MLC_LLM_SERVE_REQUEST_H_ #include +#include #include #include @@ -55,6 +56,11 @@ class RequestNode : public Object { /*! \brief Backward reference to the request state. */ Object* rstate = nullptr; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/request_state.cc b/cpp/serve/request_state.cc index d4507fbfcf..db26828da7 100644 --- a/cpp/serve/request_state.cc +++ b/cpp/serve/request_state.cc @@ -9,6 +9,12 @@ namespace mlc { namespace llm { namespace serve { +TVM_FFI_STATIC_INIT_BLOCK() { + RequestModelStateNode::RegisterReflection(); + RequestStateEntryNode::RegisterReflection(); + RequestStateNode::RegisterReflection(); +} + /****************** RequestModelState ******************/ RequestModelState::RequestModelState( diff --git a/cpp/serve/request_state.h b/cpp/serve/request_state.h index 079867c7ba..8a7bf56ba3 100644 --- a/cpp/serve/request_state.h +++ b/cpp/serve/request_state.h @@ -115,6 +115,11 @@ class RequestModelStateNode : public Object { /*! \brief Remove all draft tokens from draft_output_tokens. Update appeared_token_ids. */ void RemoveAllDraftTokens(std::vector* removed_draft_token_slots = nullptr); + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; @@ -246,6 +251,11 @@ class RequestStateEntryNode : public Object { void GetDeltaRequestReturn(const Tokenizer& tokenizer, int64_t max_single_sequence_length, RequestStreamOutput* delta_stream_output, int idx); + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; @@ -275,6 +285,11 @@ class RequestStateNode : public Object { */ RequestActionPostProcWorkspace postproc_states; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/serve/sampler/cpu_sampler.cc b/cpp/serve/sampler/cpu_sampler.cc index ad49572319..f68ea4a3fa 100644 --- a/cpp/serve/sampler/cpu_sampler.cc +++ b/cpp/serve/sampler/cpu_sampler.cc @@ -17,6 +17,8 @@ namespace mlc { namespace llm { namespace serve { +TVM_FFI_STATIC_INIT_BLOCK() { SamplerObj::RegisterReflection(); } + /*! * \brief Sample a value from the input probability distribution with top-p. * The input is a batch of distributions, and we use `unit_offset` to specify diff --git a/cpp/serve/sampler/sampler.h b/cpp/serve/sampler/sampler.h index 94a6100004..4c54a39936 100644 --- a/cpp/serve/sampler/sampler.h +++ b/cpp/serve/sampler/sampler.h @@ -120,6 +120,11 @@ class SamplerObj : public Object { const std::vector>& draft_output_tokens, const std::vector& token_tree_parent_ptr, Tensor draft_probs_on_device) = 0; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/tokenizers/streamer.cc b/cpp/tokenizers/streamer.cc index ab583b3f46..524fd795bf 100644 --- a/cpp/tokenizers/streamer.cc +++ b/cpp/tokenizers/streamer.cc @@ -17,6 +17,11 @@ namespace mlc { namespace llm { +TVM_FFI_STATIC_INIT_BLOCK() { + TextStreamerObj::RegisterReflection(); + StopStrHandlerObj::RegisterReflection(); +} + /****************** TextStreamer ******************/ TextStreamerObj::TextStreamerObj(Tokenizer tokenizer) : tokenizer_(std::move(tokenizer)) {} diff --git a/cpp/tokenizers/streamer.h b/cpp/tokenizers/streamer.h index f79d2435af..e6c88e8549 100644 --- a/cpp/tokenizers/streamer.h +++ b/cpp/tokenizers/streamer.h @@ -8,6 +8,7 @@ #define MLC_LLM_STREAMER_H_ #include +#include #include #include @@ -44,6 +45,11 @@ class TextStreamerObj : public Object { // REPLACEMENT CHARACTER (U+FFFD) in UTF-8. static constexpr const char* kReplacementCharacter = "\xef\xbf\xbd"; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; @@ -100,6 +106,11 @@ class StopStrHandlerObj : public Object { /*! \brief Check if the generation has stopped due to stop string. */ bool StopTriggered() const { return stop_triggered_; } + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; diff --git a/cpp/tokenizers/tokenizers.cc b/cpp/tokenizers/tokenizers.cc index 4d7169d8b8..0baec94c6c 100644 --- a/cpp/tokenizers/tokenizers.cc +++ b/cpp/tokenizers/tokenizers.cc @@ -24,6 +24,11 @@ namespace mlc { namespace llm { +TVM_FFI_STATIC_INIT_BLOCK() { + TokenizerInfoNode::RegisterReflection(); + TokenizerObj::RegisterReflection(); +} + #ifndef COMPILE_MLC_WASM_RUNTIME String TokenizerInfoNode::AsJSONString() const { diff --git a/cpp/tokenizers/tokenizers.h b/cpp/tokenizers/tokenizers.h index caf19e00e9..2f918dbb94 100644 --- a/cpp/tokenizers/tokenizers.h +++ b/cpp/tokenizers/tokenizers.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -48,6 +49,11 @@ class TokenizerInfoNode : public Object { String AsJSONString() const; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false; static constexpr const bool _type_mutable = true; @@ -106,6 +112,11 @@ class TokenizerObj : public Object { */ int32_t TokenToId(const std::string& token) const; + static void RegisterReflection() { + namespace refl = tvm::ffi::reflection; + refl::ObjectDef(); + } + friend class Tokenizer; static constexpr const bool _type_has_method_sequal_reduce = false; static constexpr const bool _type_has_method_shash_reduce = false;