aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/simdjson/src/implementation.cpp
diff options
context:
space:
mode:
authorAlexander Smirnov <alex@ydb.tech>2024-10-03 14:09:02 +0000
committerAlexander Smirnov <alex@ydb.tech>2024-10-03 14:09:02 +0000
commit812d97f62befea9d9b47a410d28548ef9f274510 (patch)
treed52031e2d62a9e7e9c25c43bb564dce30368e780 /contrib/libs/simdjson/src/implementation.cpp
parent1e9cd6bece572c59f55fdcf55c68b9c48e5aa6da (diff)
parentd7525e0eec8e7242a5cedd5fbdaf3bdaaeea02c7 (diff)
downloadydb-812d97f62befea9d9b47a410d28548ef9f274510.tar.gz
Merge branch 'rightlib' into mergelibs-241003-1407
Diffstat (limited to 'contrib/libs/simdjson/src/implementation.cpp')
-rw-r--r--contrib/libs/simdjson/src/implementation.cpp330
1 files changed, 330 insertions, 0 deletions
diff --git a/contrib/libs/simdjson/src/implementation.cpp b/contrib/libs/simdjson/src/implementation.cpp
new file mode 100644
index 0000000000..4323e76bfe
--- /dev/null
+++ b/contrib/libs/simdjson/src/implementation.cpp
@@ -0,0 +1,330 @@
+#ifndef SIMDJSON_SRC_IMPLEMENTATION_CPP
+#define SIMDJSON_SRC_IMPLEMENTATION_CPP
+
+#include <base.h>
+#include <simdjson/generic/dependencies.h>
+#include <simdjson/implementation.h>
+#include <internal/isadetection.h>
+
+#include <initializer_list>
+#include <type_traits>
+
+namespace simdjson {
+
+bool implementation::supported_by_runtime_system() const {
+ uint32_t required_instruction_sets = this->required_instruction_sets();
+ uint32_t supported_instruction_sets = internal::detect_supported_architectures();
+ return ((supported_instruction_sets & required_instruction_sets) == required_instruction_sets);
+}
+
+} // namespace simdjson
+
+#define SIMDJSON_CONDITIONAL_INCLUDE
+
+#if SIMDJSON_IMPLEMENTATION_ARM64
+#include <simdjson/arm64/implementation.h>
+namespace simdjson {
+namespace internal {
+static const arm64::implementation* get_arm64_singleton() {
+ static const arm64::implementation arm64_singleton{};
+ return &arm64_singleton;
+}
+} // namespace internal
+} // namespace simdjson
+#endif // SIMDJSON_IMPLEMENTATION_ARM64
+
+#if SIMDJSON_IMPLEMENTATION_FALLBACK
+#include <simdjson/fallback/implementation.h>
+namespace simdjson {
+namespace internal {
+static const fallback::implementation* get_fallback_singleton() {
+ static const fallback::implementation fallback_singleton{};
+ return &fallback_singleton;
+}
+} // namespace internal
+} // namespace simdjson
+#endif // SIMDJSON_IMPLEMENTATION_FALLBACK
+
+
+#if SIMDJSON_IMPLEMENTATION_HASWELL
+#include <simdjson/haswell/implementation.h>
+namespace simdjson {
+namespace internal {
+static const haswell::implementation* get_haswell_singleton() {
+ static const haswell::implementation haswell_singleton{};
+ return &haswell_singleton;
+}
+} // namespace internal
+} // namespace simdjson
+#endif
+
+#if SIMDJSON_IMPLEMENTATION_ICELAKE
+#include <simdjson/icelake/implementation.h>
+namespace simdjson {
+namespace internal {
+static const icelake::implementation* get_icelake_singleton() {
+ static const icelake::implementation icelake_singleton{};
+ return &icelake_singleton;
+}
+} // namespace internal
+} // namespace simdjson
+#endif
+
+#if SIMDJSON_IMPLEMENTATION_PPC64
+#error #include <simdjson/ppc64/implementation.h>
+namespace simdjson {
+namespace internal {
+static const ppc64::implementation* get_ppc64_singleton() {
+ static const ppc64::implementation ppc64_singleton{};
+ return &ppc64_singleton;
+}
+} // namespace internal
+} // namespace simdjson
+#endif // SIMDJSON_IMPLEMENTATION_PPC64
+
+#if SIMDJSON_IMPLEMENTATION_WESTMERE
+#include <simdjson/westmere/implementation.h>
+namespace simdjson {
+namespace internal {
+static const simdjson::westmere::implementation* get_westmere_singleton() {
+ static const simdjson::westmere::implementation westmere_singleton{};
+ return &westmere_singleton;
+}
+} // namespace internal
+} // namespace simdjson
+#endif // SIMDJSON_IMPLEMENTATION_WESTMERE
+
+#if SIMDJSON_IMPLEMENTATION_LSX
+#include <simdjson/lsx/implementation.h>
+namespace simdjson {
+namespace internal {
+static const simdjson::lsx::implementation* get_lsx_singleton() {
+ static const simdjson::lsx::implementation lsx_singleton{};
+ return &lsx_singleton;
+}
+} // namespace internal
+} // namespace simdjson
+#endif // SIMDJSON_IMPLEMENTATION_LSX
+
+#if SIMDJSON_IMPLEMENTATION_LASX
+#include <simdjson/lasx/implementation.h>
+namespace simdjson {
+namespace internal {
+static const simdjson::lasx::implementation* get_lasx_singleton() {
+ static const simdjson::lasx::implementation lasx_singleton{};
+ return &lasx_singleton;
+}
+} // namespace internal
+} // namespace simdjson
+#endif // SIMDJSON_IMPLEMENTATION_LASX
+
+#undef SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace internal {
+
+// When there is a single implementation, we should not pay a price
+// for dispatching to the best implementation. We should just use the
+// one we have. This is a compile-time check.
+#define SIMDJSON_SINGLE_IMPLEMENTATION (SIMDJSON_IMPLEMENTATION_ICELAKE \
+ + SIMDJSON_IMPLEMENTATION_HASWELL + SIMDJSON_IMPLEMENTATION_WESTMERE \
+ + SIMDJSON_IMPLEMENTATION_ARM64 + SIMDJSON_IMPLEMENTATION_PPC64 \
+ + SIMDJSON_IMPLEMENTATION_LSX + SIMDJSON_IMPLEMENTATION_LASX \
+ + SIMDJSON_IMPLEMENTATION_FALLBACK == 1)
+
+#if SIMDJSON_SINGLE_IMPLEMENTATION
+ static const implementation* get_single_implementation() {
+ return
+#if SIMDJSON_IMPLEMENTATION_ICELAKE
+ get_icelake_singleton();
+#endif
+#if SIMDJSON_IMPLEMENTATION_HASWELL
+ get_haswell_singleton();
+#endif
+#if SIMDJSON_IMPLEMENTATION_WESTMERE
+ get_westmere_singleton();
+#endif
+#if SIMDJSON_IMPLEMENTATION_ARM64
+ get_arm64_singleton();
+#endif
+#if SIMDJSON_IMPLEMENTATION_PPC64
+ get_ppc64_singleton();
+#endif
+#if SIMDJSON_IMPLEMENTATION_LSX
+ get_lsx_singleton();
+#endif
+#if SIMDJSON_IMPLEMENTATION_LASX
+ get_lasx_singleton();
+#endif
+#if SIMDJSON_IMPLEMENTATION_FALLBACK
+ get_fallback_singleton();
+#endif
+}
+#endif
+
+// Static array of known implementations. We're hoping these get baked into the executable
+// without requiring a static initializer.
+
+/**
+ * @private Detects best supported implementation on first use, and sets it
+ */
+class detect_best_supported_implementation_on_first_use final : public implementation {
+public:
+ std::string name() const noexcept final { return set_best()->name(); }
+ std::string description() const noexcept final { return set_best()->description(); }
+ uint32_t required_instruction_sets() const noexcept final { return set_best()->required_instruction_sets(); }
+ simdjson_warn_unused error_code create_dom_parser_implementation(
+ size_t capacity,
+ size_t max_length,
+ std::unique_ptr<internal::dom_parser_implementation>& dst
+ ) const noexcept final {
+ return set_best()->create_dom_parser_implementation(capacity, max_length, dst);
+ }
+ simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final {
+ return set_best()->minify(buf, len, dst, dst_len);
+ }
+ simdjson_warn_unused bool validate_utf8(const char * buf, size_t len) const noexcept final override {
+ return set_best()->validate_utf8(buf, len);
+ }
+ simdjson_inline detect_best_supported_implementation_on_first_use() noexcept : implementation("best_supported_detector", "Detects the best supported implementation and sets it", 0) {}
+private:
+ const implementation *set_best() const noexcept;
+};
+
+static_assert(std::is_trivially_destructible<detect_best_supported_implementation_on_first_use>::value, "detect_best_supported_implementation_on_first_use should be trivially destructible");
+
+static const std::initializer_list<const implementation *>& get_available_implementation_pointers() {
+ static const std::initializer_list<const implementation *> available_implementation_pointers {
+#if SIMDJSON_IMPLEMENTATION_ICELAKE
+ get_icelake_singleton(),
+#endif
+#if SIMDJSON_IMPLEMENTATION_HASWELL
+ get_haswell_singleton(),
+#endif
+#if SIMDJSON_IMPLEMENTATION_WESTMERE
+ get_westmere_singleton(),
+#endif
+#if SIMDJSON_IMPLEMENTATION_ARM64
+ get_arm64_singleton(),
+#endif
+#if SIMDJSON_IMPLEMENTATION_PPC64
+ get_ppc64_singleton(),
+#endif
+#if SIMDJSON_IMPLEMENTATION_LSX
+ get_lsx_singleton(),
+#endif
+#if SIMDJSON_IMPLEMENTATION_LASX
+ get_lasx_singleton(),
+#endif
+#if SIMDJSON_IMPLEMENTATION_FALLBACK
+ get_fallback_singleton(),
+#endif
+ }; // available_implementation_pointers
+ return available_implementation_pointers;
+}
+
+// So we can return UNSUPPORTED_ARCHITECTURE from the parser when there is no support
+class unsupported_implementation final : public implementation {
+public:
+ simdjson_warn_unused error_code create_dom_parser_implementation(
+ size_t,
+ size_t,
+ std::unique_ptr<internal::dom_parser_implementation>&
+ ) const noexcept final {
+ return UNSUPPORTED_ARCHITECTURE;
+ }
+ simdjson_warn_unused error_code minify(const uint8_t *, size_t, uint8_t *, size_t &) const noexcept final override {
+ return UNSUPPORTED_ARCHITECTURE;
+ }
+ simdjson_warn_unused bool validate_utf8(const char *, size_t) const noexcept final override {
+ return false; // Just refuse to validate. Given that we have a fallback implementation
+ // it seems unlikely that unsupported_implementation will ever be used. If it is used,
+ // then it will flag all strings as invalid. The alternative is to return an error_code
+ // from which the user has to figure out whether the string is valid UTF-8... which seems
+ // like a lot of work just to handle the very unlikely case that we have an unsupported
+ // implementation. And, when it does happen (that we have an unsupported implementation),
+ // what are the chances that the programmer has a fallback? Given that *we* provide the
+ // fallback, it implies that the programmer would need a fallback for our fallback.
+ }
+ unsupported_implementation() : implementation("unsupported", "Unsupported CPU (no detected SIMD instructions)", 0) {}
+};
+
+static_assert(std::is_trivially_destructible<unsupported_implementation>::value, "unsupported_singleton should be trivially destructible");
+
+const unsupported_implementation* get_unsupported_singleton() {
+ static const unsupported_implementation unsupported_singleton{};
+ return &unsupported_singleton;
+}
+
+size_t available_implementation_list::size() const noexcept {
+ return internal::get_available_implementation_pointers().size();
+}
+const implementation * const *available_implementation_list::begin() const noexcept {
+ return internal::get_available_implementation_pointers().begin();
+}
+const implementation * const *available_implementation_list::end() const noexcept {
+ return internal::get_available_implementation_pointers().end();
+}
+const implementation *available_implementation_list::detect_best_supported() const noexcept {
+ // They are prelisted in priority order, so we just go down the list
+ uint32_t supported_instruction_sets = internal::detect_supported_architectures();
+ for (const implementation *impl : internal::get_available_implementation_pointers()) {
+ uint32_t required_instruction_sets = impl->required_instruction_sets();
+ if ((supported_instruction_sets & required_instruction_sets) == required_instruction_sets) { return impl; }
+ }
+ return get_unsupported_singleton(); // this should never happen?
+}
+
+const implementation *detect_best_supported_implementation_on_first_use::set_best() const noexcept {
+ SIMDJSON_PUSH_DISABLE_WARNINGS
+ SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
+ char *force_implementation_name = getenv("SIMDJSON_FORCE_IMPLEMENTATION");
+ SIMDJSON_POP_DISABLE_WARNINGS
+
+ if (force_implementation_name) {
+ auto force_implementation = get_available_implementations()[force_implementation_name];
+ if (force_implementation) {
+ return get_active_implementation() = force_implementation;
+ } else {
+ // Note: abort() and stderr usage within the library is forbidden.
+ return get_active_implementation() = get_unsupported_singleton();
+ }
+ }
+ return get_active_implementation() = get_available_implementations().detect_best_supported();
+}
+
+} // namespace internal
+
+SIMDJSON_DLLIMPORTEXPORT const internal::available_implementation_list& get_available_implementations() {
+ static const internal::available_implementation_list available_implementations{};
+ return available_implementations;
+}
+
+SIMDJSON_DLLIMPORTEXPORT internal::atomic_ptr<const implementation>& get_active_implementation() {
+#if SIMDJSON_SINGLE_IMPLEMENTATION
+ // We immediately select the only implementation we have, skipping the
+ // detect_best_supported_implementation_on_first_use_singleton.
+ static internal::atomic_ptr<const implementation> active_implementation{internal::get_single_implementation()};
+ return active_implementation;
+#else
+ static const internal::detect_best_supported_implementation_on_first_use detect_best_supported_implementation_on_first_use_singleton;
+ static internal::atomic_ptr<const implementation> active_implementation{&detect_best_supported_implementation_on_first_use_singleton};
+ return active_implementation;
+#endif
+}
+
+simdjson_warn_unused error_code minify(const char *buf, size_t len, char *dst, size_t &dst_len) noexcept {
+ return get_active_implementation()->minify(reinterpret_cast<const uint8_t *>(buf), len, reinterpret_cast<uint8_t *>(dst), dst_len);
+}
+simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept {
+ return get_active_implementation()->validate_utf8(buf, len);
+}
+const implementation * builtin_implementation() {
+ static const implementation * builtin_impl = get_available_implementations()[SIMDJSON_STRINGIFY(SIMDJSON_BUILTIN_IMPLEMENTATION)];
+ assert(builtin_impl);
+ return builtin_impl;
+}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_SRC_IMPLEMENTATION_CPP