Compare commits

..

5 Commits

Author SHA1 Message Date
SaberAlterr 11d9dbb7b7 [RISC-V Vector]Add 128-bit fixed-width SIMD layer (#2472)
* Fix riscv intrinsics header missing SIMDJSON_CONDITIONAL_INCLUDE guard

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Fix riscv intrinsics header missing SIMDJSON_CONDITIONAL_INCLUDE guard

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Implement simd8/simd8x64 with RVV intrinsics and fallback bitmanipulation

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Fix missing SIMDJSON_CONDITIONAL_INCLUDE guard

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Fix missing SIMDJSON_CONDITIONAL_INCLUDE guard

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

---------

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>
2025-09-26 12:51:37 -04:00
SaberAlterr 896fb5d6a5 [RISC-V Vector] Add initial 128-bit SIMD layer and fix intrinsics header (#2469)
* Fix riscv intrinsics header missing SIMDJSON_CONDITIONAL_INCLUDE guard

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Fix riscv intrinsics header missing SIMDJSON_CONDITIONAL_INCLUDE guard

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Fix intrinsics header and add 128-bit SIMD layer

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

---------

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>
2025-09-24 14:48:59 -04:00
SaberAlterr e3d3b4b5a4 [RISC-V Vector] Stage1 Intrinsics and SIMD Namespace Implementation for RVV Optimization (#2455)
* implement rvv/intrinsics.h for dynamic vector length

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Fix riscv intrinsics header missing SIMDJSON_CONDITIONAL_INCLUDE guard

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Fix riscv intrinsics header missing SIMDJSON_CONDITIONAL_INCLUDE guard

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

---------

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>
2025-09-18 09:17:13 -06:00
Daniel Lemire 08e5943efc Merge branch 'master' into riscv_develop 2025-09-15 09:27:00 -06:00
SaberAlterr 7068894be3 [RISC-V Vector] Add RVV Backend Registration (#2430)
* WIP: initial RVV implementation

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* Fix issue with SIMDJSON_CONDITIONAL_INCLUDE in rvv/implementation.h

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* drop RISC-V V-extension auto-detection in cmake

- Remove CMake logic that adds -DSIMDJSON_IS_RVV=1.
- Let SIMDJSON_IS_RVV be determined by portability.h.
- Translate placeholder comment to English.

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* fixing amalgamation.

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

* adding base

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>

---------

Co-authored-by: gong-flying <gongxiaofei24@iscas.ac.cn>
Co-authored-by: Daniel Lemire <daniel@lemire.me>
2025-09-14 08:14:41 -06:00
39 changed files with 622 additions and 242 deletions
+1
View File
@@ -88,6 +88,7 @@ objs
# Build outputs
/build*/
/visual_studio/
/originbuild/
# Fuzzer outputs generated by instructions in fuzz/Fuzzing.md
/corpus.zip
+1 -1
View File
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
project(
simdjson
# The version number is modified by tools/release.py
VERSION 4.0.3
VERSION 4.0.2
DESCRIPTION "Parsing gigabytes of JSON per second"
HOMEPAGE_URL "https://simdjson.org/"
LANGUAGES CXX C
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "4.0.3"
PROJECT_NUMBER = "4.0.2"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+1 -2
View File
@@ -117,10 +117,9 @@ Godbolt
-------------
Some users may want to browse code along with the compiled assembly. You want to check out the following lists of examples:
* [C++26 reflection example](https://godbolt.org/z/K3Px64TqK)
* [simdjson examples with errors handled through exceptions](https://godbolt.org/z/7G5qE4sr9)
* [simdjson examples with errors without exceptions](https://godbolt.org/z/e9dWb9E4v)
* [C++26 reflection example](https://godbolt.org/z/xK5TGKdPb)
Performance results
-------------------
+29 -33
View File
@@ -6,42 +6,38 @@ CPMAddPackage(
EXCLUDE_FROM_ALL YES
)
option(SIMDJSON_USE_RUST "Build the static_reflect benchmark" OFF)
if(SIMDJSON_USER_RUST)
if(NOT WIN32)
# We want the check whether Rust is available before trying to build a crate.
CPMAddPackage(
NAME corrosion
GITHUB_REPOSITORY corrosion-rs/corrosion
VERSION 0.4.4
DOWNLOAD_ONLY ON
OPTIONS "Rust_FIND_QUIETLY OFF"
)
include("${corrosion_SOURCE_DIR}/cmake/FindRust.cmake")
endif()
if(RUST_FOUND)
message(STATUS "Rust found: " ${Rust_VERSION} )
add_subdirectory("${corrosion_SOURCE_DIR}" "${PROJECT_BINARY_DIR}/_deps/corrosion" EXCLUDE_FROM_ALL)
# Important: we want to build in release mode!
corrosion_import_crate(MANIFEST_PATH "serde-benchmark/Cargo.toml" NO_LINKER_OVERRIDE PROFILE release)
else()
message(STATUS "Rust/Cargo is unavailable." )
message(STATUS "We will not benchmark serde-benchmark." )
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
message(STATUS "Under macOS, you may be able to install rust with")
message(STATUS "curl https://sh.rustup.rs -sSf | sh")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(STATUS "Under Linux, you may be able to install rust with a command such as")
message(STATUS "apt-get install cargo" )
message(STATUS "or" )
message(STATUS "curl https://sh.rustup.rs -sSf | sh")
endif()
endif()
else(SIMDJSON_USER_RUST)
if(NOT WIN32)
# We want the check whether Rust is available before trying to build a crate.
CPMAddPackage(
NAME corrosion
GITHUB_REPOSITORY corrosion-rs/corrosion
VERSION 0.4.4
DOWNLOAD_ONLY ON
OPTIONS "Rust_FIND_QUIETLY OFF"
)
include("${corrosion_SOURCE_DIR}/cmake/FindRust.cmake")
endif()
if(RUST_FOUND)
message(STATUS "Rust found: " ${Rust_VERSION} )
add_subdirectory("${corrosion_SOURCE_DIR}" "${PROJECT_BINARY_DIR}/_deps/corrosion" EXCLUDE_FROM_ALL)
# Important: we want to build in release mode!
corrosion_import_crate(MANIFEST_PATH "serde-benchmark/Cargo.toml" NO_LINKER_OVERRIDE PROFILE release)
else()
message(STATUS "Rust/Cargo is unavailable." )
message(STATUS "We will not benchmark serde-benchmark." )
endif(SIMDJSON_USER_RUST)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
message(STATUS "Under macOS, you may be able to install rust with")
message(STATUS "curl https://sh.rustup.rs -sSf | sh")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(STATUS "Under Linux, you may be able to install rust with a command such as")
message(STATUS "apt-get install cargo" )
message(STATUS "or" )
message(STATUS "curl https://sh.rustup.rs -sSf | sh")
endif()
endif()
# Add the benchmark executable targets
add_subdirectory(twitter_benchmark)
+2 -2
View File
@@ -1,7 +1,7 @@
#
# Implementation selection
#
set(SIMDJSON_ALL_IMPLEMENTATIONS fallback westmere haswell icelake arm64 ppc64)
set(SIMDJSON_ALL_IMPLEMENTATIONS fallback westmere haswell icelake arm64 ppc64 rvv)
set(
SIMDJSON_IMPLEMENTATION ""
@@ -15,7 +15,7 @@ set(
SIMDJSON_EXCLUDE_IMPLEMENTATION ""
CACHE STRING "\
Semicolon-separated list of implementations to exclude \
(icelake/haswell/westmere/arm64/ppc64/fallback). By default, excludes any \
(icelake/haswell/westmere/arm64/ppc64/rvv/fallback). By default, excludes any \
implementations that are unsupported at compile time or cannot be selected at \
runtime."
)
+2 -2
View File
@@ -1395,7 +1395,7 @@ Car c = doc.get<Car>();
We try to automate the parsing of any given structure or class
by looking at its non-static public members. At compile-time,
the library looks at a simple structure like `Car` and
the library looks at a simple structre like `Car` and
maps it to parsing code. We call the default constructor,
and then assign values to the public members.
@@ -1450,7 +1450,7 @@ struct complicated_weather_data {
};
```
The code might be as simple as the following.
The code might as simple as the following.
```cpp
auto padded = R"({"time":["2023-03-15T12:00:00Z"],"temperature":[42]})"_padded;
+1 -1
View File
@@ -41,7 +41,7 @@ Parameters:
- `append_raw(std::string_view input)`: Appends a string view directly to the JSON buffer without escaping.
- `append_raw(const char *str, size_t len)`: Appends a specified number of characters from a C string directly to the JSON
After writing the content, if you have reasons to believe that the content might violate UTF-8 conventions, you can check it as follows:
After writting the content, if you have reasons to believe that the content might violate UTF-8 conventions, you can check it as follows:
- `validate_unicode()`: Checks if the content in the JSON buffer is valid UTF-8. Returns: true if the content is valid UTF-8, false otherwise.
+1 -1
View File
@@ -129,7 +129,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
The strings contain unescaped valid UTF-8 strings: no unmatched surrogate is allowed.
Internally, numbers are stored as either 64-bit integers or 64-bit floating-point numbers.
Thus it is possible to get the full 64-bit integer range (either signed or unsigned).
By default, the string `-0` is parsed as the integer 0 as in Python or C++. If you set the macro
By default, the string `-0` is parsed as the integer 0 as in Pytho or C++. If you set the macro
`SIMDJSON_MINUS_ZERO_AS_FLOAT` to `1` when building simdjson, you can get that `-0` is mapped to `-0.0`
as in JavaScript. You can get the desired effect by building simdjson with cmake setting the
`SIMDJSON_MINUS_ZERO_AS_FLOAT` to on: `cmake -B build -D SIMDJSON_MINUS_ZERO_AS_FLOAT=ON`.
+2
View File
@@ -24,6 +24,8 @@
#include "simdjson/lsx.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
#include "simdjson/lasx.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv)
#include "simdjson/rvv.h"
#else
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
#endif
+2
View File
@@ -21,6 +21,8 @@ namespace simdjson {
namespace lsx {}
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
namespace lasx {}
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv)
namespace rvv {}
#else
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
#endif
@@ -23,6 +23,8 @@
#include "simdjson/lsx/implementation.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
#include "simdjson/lasx/implementation.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv)
#include "simdjson/rvv/implementation.h"
#else
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
#endif
+2
View File
@@ -24,6 +24,8 @@
#include "simdjson/lsx/ondemand.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
#include "simdjson/lasx/ondemand.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv)
#include "simdjson/rvv/ondemand.h"
#else
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
#endif
-10
View File
@@ -116,16 +116,6 @@ template <typename T>
inline auto to_adaptor<T>::operator()(ondemand::parser &parser, padded_string_view const str) const noexcept {
return auto_parser<ondemand::parser *>{parser, str};
}
template <typename T>
inline auto to_adaptor<T>::operator()(std::string str) const noexcept {
return auto_parser{pad_with_reserve(str)};
}
template <typename T>
inline auto to_adaptor<T>::operator()(ondemand::parser &parser, std::string str) const noexcept {
return auto_parser<ondemand::parser *>{parser, pad_with_reserve(str)};
}
} // namespace internal
} // namespace convert
} // namespace simdjson
-5
View File
@@ -72,11 +72,6 @@ struct to_adaptor {
T operator()(simdjson_result<ondemand::value> &val) const noexcept;
auto operator()(padded_string_view const str) const noexcept;
auto operator()(ondemand::parser &parser, padded_string_view const str) const noexcept;
// The std::string is padded with reserve to ensure there is enough space for padding.
// Some sanitizers may not like this, so you can use simdjson::pad instead.
// simdjson::from(simdjson::pad(str))
auto operator()(std::string str) const noexcept;
auto operator()(ondemand::parser &parser, std::string str) const noexcept;
};
} // namespace internal
} // namespace convert
@@ -284,12 +284,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -301,8 +299,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -333,11 +332,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -288,7 +288,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
+13 -1
View File
@@ -12,6 +12,7 @@
#define SIMDJSON_IMPLEMENTATION_ID_westmere 6
#define SIMDJSON_IMPLEMENTATION_ID_lsx 7
#define SIMDJSON_IMPLEMENTATION_ID_lasx 8
#define SIMDJSON_IMPLEMENTATION_ID_rvv 9
#define SIMDJSON_IMPLEMENTATION_ID_FOR(IMPL) SIMDJSON_CAT(SIMDJSON_IMPLEMENTATION_ID_, IMPL)
#define SIMDJSON_IMPLEMENTATION_ID SIMDJSON_IMPLEMENTATION_ID_FOR(SIMDJSON_IMPLEMENTATION)
@@ -23,6 +24,15 @@
// in which we include them.
//
#ifndef SIMDJSON_IMPLEMENTATION_RVV
#define SIMDJSON_IMPLEMENTATION_RVV (SIMDJSON_IS_RISCV64 && SIMDJSON_IS_RVV)
#endif
#if SIMDJSON_IMPLEMENTATION_RVV && SIMDJSON_IS_RISCV64 && SIMDJSON_IS_RVV
#define SIMDJSON_CAN_ALWAYS_RUN_RVV 1
#else
#define SIMDJSON_CAN_ALWAYS_RUN_RVV 0
#endif
#ifndef SIMDJSON_IMPLEMENTATION_ARM64
#define SIMDJSON_IMPLEMENTATION_ARM64 (SIMDJSON_IS_ARM64)
#endif
@@ -128,7 +138,7 @@
// Default Fallback to on unless a builtin implementation has already been selected.
#ifndef SIMDJSON_IMPLEMENTATION_FALLBACK
#if SIMDJSON_CAN_ALWAYS_RUN_ARM64 || SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL || SIMDJSON_CAN_ALWAYS_RUN_WESTMERE || SIMDJSON_CAN_ALWAYS_RUN_PPC64 || SIMDJSON_CAN_ALWAYS_RUN_LSX || SIMDJSON_CAN_ALWAYS_RUN_LASX
#if SIMDJSON_CAN_ALWAYS_RUN_ARM64 || SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL || SIMDJSON_CAN_ALWAYS_RUN_WESTMERE || SIMDJSON_CAN_ALWAYS_RUN_PPC64 || SIMDJSON_CAN_ALWAYS_RUN_LSX || SIMDJSON_CAN_ALWAYS_RUN_LASX || SIMDJSON_CAN_ALWAYS_RUN_RVV
// if anything at all except fallback can always run, then disable fallback.
#define SIMDJSON_IMPLEMENTATION_FALLBACK 0
#else
@@ -154,6 +164,8 @@
#define SIMDJSON_BUILTIN_IMPLEMENTATION lsx
#elif SIMDJSON_CAN_ALWAYS_RUN_LASX
#define SIMDJSON_BUILTIN_IMPLEMENTATION lasx
#elif SIMDJSON_CAN_ALWAYS_RUN_RVV
#define SIMDJSON_BUILTIN_IMPLEMENTATION rvv
#elif SIMDJSON_CAN_ALWAYS_RUN_FALLBACK
#define SIMDJSON_BUILTIN_IMPLEMENTATION fallback
#else
+8
View File
@@ -0,0 +1,8 @@
#ifndef SIMDJSON_RVV_H
#define SIMDJSON_RVV_H
#include "simdjson/rvv/begin.h"
#include "simdjson/generic/amalgamated.h"
#include "simdjson/rvv/end.h"
#endif // SIMDJSON_RVV_H
+20
View File
@@ -0,0 +1,20 @@
#ifndef SIMDJSON_RVV_BASE_H
#define SIMDJSON_RVV_BASE_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace rvv {
class implementation;
namespace {
namespace simd {
template <typename T> struct simd8;
template <typename T> struct simd8x64;
} // namespace simd
} // unnamed namespace
} // namespace rvv
} // namespace simdjson
#endif // SIMDJSON_RVV_BASE_H
+13
View File
@@ -0,0 +1,13 @@
#define SIMDJSON_IMPLEMENTATION rvv
// include RVV intrinsics and definitions
#include <riscv_vector.h>
#include "simdjson/rvv/base.h"
#include "simdjson/rvv/intrinsics.h"
#include "simdjson/rvv/bitmanipulation.h"
#include "simdjson/rvv/bitmask.h"
#include "simdjson/rvv/numberparsing_defs.h"
#include "simdjson/rvv/simd.h"
#include "simdjson/rvv/stringparsing_defs.h"
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
+54
View File
@@ -0,0 +1,54 @@
#ifndef SIMDJSON_RVV_BITMANIPULATION_H
#define SIMDJSON_RVV_BITMANIPULATION_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/rvv/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace rvv {
namespace {
/* result might be undefined when input_num is zero */
simdjson_inline int leading_zeroes(uint64_t input_num) {
#if defined(_MSC_VER) && !defined(__clang__)
unsigned long leading_zero = 0;
if (_BitScanReverse64(&leading_zero, input_num))
return (int)(63 - leading_zero);
else
return 64;
#else
return __builtin_clzll(input_num);
#endif
}
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
return input_num & (input_num - 1);
}
simdjson_inline int count_ones(uint64_t input_num) {
return __builtin_popcountll(input_num);
}
inline simdjson::internal::value128 full_multiplication(uint64_t a, uint64_t b) {
#if __SIZEOF_INT128__
unsigned __int128 p = (unsigned __int128)a * b;
return { (uint64_t)p, (uint64_t)(p >> 64) };
#else
uint64_t lo = a * b;
uint64_t a0 = (uint32_t)a, a1 = a >> 32;
uint64_t b0 = (uint32_t)b, b1 = b >> 32;
uint64_t mid1 = a0 * b1;
uint64_t mid2 = a1 * b0;
uint64_t carry = ((mid1 & 0xFFFFFFFF) + (mid2 & 0xFFFFFFFF) + (lo >> 32)) >> 32;
uint64_t hi = a1 * b1 + (mid1 >> 32) + (mid2 >> 32) + carry;
return { lo, hi };
#endif
}
} // unnamed namespace
} // namespace rvv
} // namespace simdjson
#endif // SIMDJSON_RVV_BITMANIPULATION_H
View File
+6
View File
@@ -0,0 +1,6 @@
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/rvv/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
#undef SIMDJSON_IMPLEMENTATION
+29
View File
@@ -0,0 +1,29 @@
#ifndef SIMDJSON_RVV_IMPLEMENTATION_H
#define SIMDJSON_RVV_IMPLEMENTATION_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/base.h"
#include "simdjson/implementation.h"
#include "simdjson/internal/instruction_set.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace rvv {
class implementation final: public simdjson::implementation {
public:
simdjson_inline implementation() : simdjson::implementation("rvv", "RISC-V Vector Extension", 0) {}
simdjson_warn_unused error_code create_dom_parser_implementation(
size_t capacity,
size_t max_depth,
std::unique_ptr<internal::dom_parser_implementation>& dst
) const noexcept final;
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
};
} // namespace rvv
} // namespace simdjson
#endif // SIMDJSON_RVV_IMPLEMENTATION_H
+8
View File
@@ -0,0 +1,8 @@
#ifndef SIMDJSON_RVV_INTRINSICS_H
#define SIMDJSON_RVV_INTRINSICS_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/rvv/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#endif // SIMDJSON_RVV_INTRINSICS_H
+9
View File
@@ -0,0 +1,9 @@
#ifndef SIMDJSON_RVV_ONDEMAND_H
#define SIMDJSON_RVV_ONDEMAND_H
#include "simdjson/rvv/begin.h"
#include "simdjson/generic/ondemand/amalgamated.h"
#include "simdjson/rvv/end.h"
#endif // SIMDJSON_RVV_ONDEMAND_H
+298
View File
@@ -0,0 +1,298 @@
#ifndef SIMDJSON_RVV_SIMD_H
#define SIMDJSON_RVV_SIMD_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/rvv/base.h"
#include "simdjson/rvv/intrinsics.h"
#include "simdjson/internal/simdprune_tables.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace rvv {
namespace {
namespace simd {
// ---------- 128-bit fixed vectors ----------
using vuint8x16 = vuint8m1_t __attribute__((riscv_rvv_vector_bits(128)));
using vint8x16 = vint8m1_t __attribute__((riscv_rvv_vector_bits(128)));
using vbool8x16 = vbool8_t;
static constexpr size_t fixed_vl = 16;
// ---------- forward ----------
template<typename T> struct simd8;
template<typename T> struct simd8x64;
// ---------- base<Child> ----------
template<typename Child>
struct base {
vuint8x16 value{};
base() = default;
base(vuint8x16 v) : value(v) {}
operator vuint8x16() const { return value; }
operator vuint8x16&() { return value; }
simdjson_inline Child operator|(const Child o) const { return __riscv_vor_vv_u8m1(value, o, fixed_vl); }
simdjson_inline Child operator&(const Child o) const { return __riscv_vand_vv_u8m1(value, o, fixed_vl); }
simdjson_inline Child operator^(const Child o) const { return __riscv_vxor_vv_u8m1(value, o, fixed_vl); }
simdjson_inline Child bit_andnot(const Child o) const { return __riscv_vandn_vv_u8m1(value, o, fixed_vl); }
simdjson_inline Child& operator|=(const Child o) { auto* c = static_cast<Child*>(this); *c = *c | o; return *c; }
simdjson_inline Child& operator&=(const Child o) { auto* c = static_cast<Child*>(this); *c = *c & o; return *c; }
simdjson_inline Child& operator^=(const Child o) { auto* c = static_cast<Child*>(this); *c = *c ^ o; return *c; }
};
// ---------- base8<T,Mask> ----------
template<typename T, typename Mask = simd8<bool>>
struct base8 : base<simd8<T>> {
using base<simd8<T>>::value;
using bitmask_t = uint32_t;
base8() = default;
base8(vuint8x16 v) : base<simd8<T>>(v) {}
friend simdjson_inline Mask operator==(const simd8<T> a, const simd8<T> b) {
return simd8<bool>(__riscv_vmseq_vv_u8m1_b8(a, b, fixed_vl));
}
template<int N=1>
simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
return __riscv_vslideup_vx_u8m1(prev_chunk, value, fixed_vl - N, 2 * fixed_vl);
}
};
// ---------- simd8<bool> ----------
template<>
struct simd8<bool> : base8<bool> {
simd8() = default;
simd8(vuint8x16 v) : base8(v) {}
simd8(vbool8_t m) : base8(__riscv_vmerge_vvm_u8m1(
__riscv_vmv_v_x_u8m1(0, fixed_vl),
__riscv_vmv_v_x_u8m1(0xFFu, fixed_vl),
m, fixed_vl)) {}
static simdjson_inline simd8<bool> splat(bool b) {
return __riscv_vmv_v_x_u8m1(uint8_t(-b), fixed_vl);
}
simdjson_inline simd8(bool b) : simd8(splat(b)) {}
simdjson_inline int to_bitmask() const {
vuint8x16 bits = __riscv_vand_vx_u8m1(value, 0xFFu, fixed_vl);
vbool8x16 mask = __riscv_vmseq_vx_u8m1_b8(bits, 0xFFu, fixed_vl);
return __riscv_vcpop_m_b8(mask, fixed_vl);
}
simdjson_inline bool any_bits_set_anywhere() const {
return to_bitmask() != 0;
}
simdjson_inline simd8<bool> operator~() const { return *this ^ splat(true); }
};
// ---------- simd8<uint8_t> ----------
template<>
struct simd8<uint8_t> : base8<uint8_t> {
simd8() = default;
simd8(vuint8x16 v) : base8(v) {}
static simdjson_inline simd8<uint8_t> splat(uint8_t v) {
return __riscv_vmv_v_x_u8m1(v, fixed_vl);
}
static simdjson_inline simd8<uint8_t> zero() { return splat(0); }
static simdjson_inline simd8<uint8_t> load(const uint8_t* p) {
return __riscv_vle8_v_u8m1(p, fixed_vl);
}
simdjson_inline simd8(uint8_t v) : simd8(splat(v)) {}
simdjson_inline simd8(const uint8_t* p) : simd8(load(p)) {}
simdjson_inline void store(uint8_t* p) const {
__riscv_vse8_v_u8m1(p, value, fixed_vl);
}
simdjson_inline simd8<uint8_t> operator+(const simd8<uint8_t> o) const {
return __riscv_vadd_vv_u8m1(value, o, fixed_vl);
}
simdjson_inline simd8<uint8_t> operator-(const simd8<uint8_t> o) const {
return __riscv_vsub_vv_u8m1(value, o, fixed_vl);
}
simdjson_inline simd8<uint8_t>& operator+=(const simd8<uint8_t> o) {
*this = *this + o; return *this;
}
simdjson_inline simd8<uint8_t>& operator-=(const simd8<uint8_t> o) {
*this = *this - o; return *this;
}
simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> o) const {
return __riscv_vsaddu_vv_u8m1(value, o, fixed_vl);
}
simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> o) const {
return __riscv_vssubu_vv_u8m1(value, o, fixed_vl);
}
simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> o) const {
return __riscv_vmaxu_vv_u8m1(value, o, fixed_vl);
}
simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> o) const {
return __riscv_vminu_vv_u8m1(value, o, fixed_vl);
}
simdjson_inline simd8<bool> operator>(const simd8<uint8_t> o) const {
return simd8<bool>(__riscv_vmsgtu_vv_u8m1_b8(value, o, fixed_vl));
}
simdjson_inline simd8<bool> operator<(const simd8<uint8_t> o) const {
return simd8<bool>(__riscv_vmsgtu_vv_u8m1_b8(o, value, fixed_vl));
}
simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> o) const {
return simd8<bool>(__riscv_vmsleu_vv_u8m1_b8(value, o, fixed_vl));
}
simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> o) const {
return simd8<bool>(__riscv_vmsleu_vv_u8m1_b8(o, value, fixed_vl));
}
template<int NS>
simdjson_inline simd8<uint8_t> shr() const {
return __riscv_vsrl_vx_u8m1(value, NS, fixed_vl);
}
template<int NS>
simdjson_inline simd8<uint8_t> shl() const {
return __riscv_vsll_vx_u8m1(value, NS, fixed_vl);
}
template <typename Ret>
simdjson_inline simd8<Ret> lookup_16(const Ret* table) const {
alignas(16) uint8_t idx[16];
store(idx);
alignas(16) Ret res[16];
for (int i = 0; i < 16; ++i) res[i] = table[idx[i]];
return simd8<Ret>::load(reinterpret_cast<const Ret*>(res));
}
simdjson_inline void compress(uint16_t mask, uint8_t* out) const {
alignas(16) uint8_t tmp[16];
store(tmp);
for (int i = 0, j = 0; i < 16; ++i)
if (mask & (1u << i)) out[j++] = tmp[i];
}
simdjson_inline uint64_t gt_bits(uint8_t max_value) const {
return (*this > splat(max_value)).to_bitmask();
}
simdjson_inline uint64_t gt_bits(const simd8<uint8_t>& max_vec) const {
return (*this > max_vec).to_bitmask();
}
simdjson_inline bool any_bits_set_anywhere() const {
return (*this > zero()).any_bits_set_anywhere();
}
};
// ---------- simd8<int8_t> ----------
template<>
struct simd8<int8_t> {
vint8x16 value{};
simd8() = default;
simd8(vint8x16 v) : value(v) {}
static simdjson_inline simd8<int8_t> splat(int8_t v) {
return __riscv_vmv_v_x_i8m1(v, fixed_vl);
}
static simdjson_inline simd8<int8_t> zero() { return splat(0); }
static simdjson_inline simd8<int8_t> load(const int8_t* p) {
return __riscv_vle8_v_i8m1(p, fixed_vl);
}
simdjson_inline simd8(int8_t v) : simd8(splat(v)) {}
simdjson_inline simd8(const int8_t* p) : simd8(load(p)) {}
simdjson_inline void store(int8_t* p) const {
__riscv_vse8_v_i8m1(p, value, fixed_vl);
}
simdjson_inline simd8<int8_t> operator+(const simd8<int8_t> o) const {
return __riscv_vadd_vv_i8m1(value, o.value, fixed_vl);
}
simdjson_inline simd8<int8_t> operator-(const simd8<int8_t> o) const {
return __riscv_vsub_vv_i8m1(value, o.value, fixed_vl);
}
simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> o) const {
return __riscv_vmax_vv_i8m1(value, o.value, fixed_vl);
}
simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> o) const {
return __riscv_vmin_vv_i8m1(value, o.value, fixed_vl);
}
simdjson_inline simd8<bool> operator>(const simd8<int8_t> o) const {
return simd8<bool>(__riscv_vmsgt_vv_i8m1_b8(value, o.value, fixed_vl));
}
simdjson_inline simd8<bool> operator<(const simd8<int8_t> o) const {
return simd8<bool>(__riscv_vmsgt_vv_i8m1_b8(o.value, value, fixed_vl));
}
simdjson_inline simd8<bool> operator==(const simd8<int8_t> o) const {
return simd8<bool>(__riscv_vmseq_vv_i8m1_b8(value, o.value, fixed_vl));
}
template<int N=1>
simdjson_inline simd8<int8_t> prev(const simd8<int8_t> prev_chunk) const {
return __riscv_vslideup_vx_i8m1(prev_chunk.value, value, fixed_vl - N, 2 * fixed_vl);
}
};
// ---------- simd8x64<T> ----------
template<typename T>
struct simd8x64 {
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
static_assert(NUM_CHUNKS == 4, "RVV kernel uses 4×128-bit chunks per 64-byte block.");
const simd8<T> chunks[4];
simd8x64(const simd8x64&) = delete;
simd8x64& operator=(const simd8x64&) = delete;
simd8x64() = delete;
simdjson_inline simd8x64(const simd8<T> c0, const simd8<T> c1,
const simd8<T> c2, const simd8<T> c3)
: chunks{c0, c1, c2, c3} {}
simdjson_inline simd8x64(const T* ptr)
: chunks{simd8<T>::load(ptr),
simd8<T>::load(ptr + 16),
simd8<T>::load(ptr + 32),
simd8<T>::load(ptr + 48)} {}
simdjson_inline void store(T* ptr) const {
chunks[0].store(ptr);
chunks[1].store(ptr + 16);
chunks[2].store(ptr + 32);
chunks[3].store(ptr + 48);
}
simdjson_inline simd8<T> reduce_or() const {
return (chunks[0] | chunks[1]) | (chunks[2] | chunks[3]);
}
simdjson_inline uint64_t to_bitmask() const {
uint16_t m0 = uint16_t(chunks[0].to_bitmask());
uint16_t m1 = uint16_t(chunks[1].to_bitmask());
uint16_t m2 = uint16_t(chunks[2].to_bitmask());
uint16_t m3 = uint16_t(chunks[3].to_bitmask());
return m0 | (uint64_t(m1) << 16) | (uint64_t(m2) << 32) | (uint64_t(m3) << 48);
}
simdjson_inline uint64_t eq(const T m) const {
simd8<T> spl = simd8<T>::splat(m);
return simd8x64<bool>(chunks[0] == spl,
chunks[1] == spl,
chunks[2] == spl,
chunks[3] == spl).to_bitmask();
}
simdjson_inline uint64_t lteq(const T m) const {
simd8<T> spl = simd8<T>::splat(m);
return simd8x64<bool>(chunks[0] <= spl,
chunks[1] <= spl,
chunks[2] <= spl,
chunks[3] <= spl).to_bitmask();
}
simdjson_inline uint64_t compress(uint64_t mask, T* out) const {
using internal::BitsSetTable256mul2;
uint32_t m0 = uint32_t(mask);
uint32_t m1 = uint32_t(mask >> 16);
uint32_t m2 = uint32_t(mask >> 32);
uint32_t m3 = uint32_t(mask >> 48);
int pop0 = BitsSetTable256mul2[uint8_t(m0)];
int pop1 = BitsSetTable256mul2[uint8_t(m1)];
int pop2 = BitsSetTable256mul2[uint8_t(m2)];
chunks[0].compress(uint16_t(m0), out);
chunks[1].compress(uint16_t(m1), out + 16 - pop0);
chunks[2].compress(uint16_t(m2), out + 32 - pop0 - pop1);
chunks[3].compress(uint16_t(m3), out + 48 - pop0 - pop1 - pop2);
return 64 - __builtin_popcountll(mask);
}
};
} // namespace simd
} // unnamed namespace
} // namespace rvv
} // namespace simdjson
#endif // SIMDJSON_RVV_SIMD_H
+2 -2
View File
@@ -4,7 +4,7 @@
#define SIMDJSON_SIMDJSON_VERSION_H
/** The version of simdjson being used (major.minor.revision) */
#define SIMDJSON_VERSION "4.0.3"
#define SIMDJSON_VERSION "4.0.2"
namespace simdjson {
enum {
@@ -19,7 +19,7 @@ enum {
/**
* The revision (major.minor.REVISION) of simdjson being used.
*/
SIMDJSON_VERSION_REVISION = 3
SIMDJSON_VERSION_REVISION = 2
};
} // namespace simdjson
+1 -2
View File
@@ -71,7 +71,7 @@ else:
RelativeRoot = str # Literal['src','include'] # Literal not supported in Python 3.7 (CI)
RELATIVE_ROOTS: List[RelativeRoot] = ['src', 'include' ]
Implementation = str # Literal['arm64', 'fallback', 'haswell', 'icelake', 'ppc64', 'westmere', 'lsx', 'lasx'] # Literal not supported in Python 3.7 (CI)
IMPLEMENTATIONS: List[Implementation] = [ 'arm64', 'haswell', 'icelake', 'lasx', 'lsx', 'ppc64', 'westmere', 'fallback' ]
IMPLEMENTATIONS: List[Implementation] = [ 'arm64', 'haswell', 'icelake', 'lasx', 'lsx', 'ppc64', 'westmere', 'fallback', 'rvv' ]
GENERIC_INCLUDE = "simdjson/generic"
GENERIC_SRC = "generic"
BUILTIN = "simdjson/builtin"
@@ -358,7 +358,6 @@ class Amalgamator:
self.include_stack.append(file)
file.processed = False
self.write(f"/* begin file {self.file_to_str(file)} */")
if file == BUILTIN_BEGIN_H:
+1 -1
View File
@@ -1,4 +1,4 @@
/* auto-generated on 2025-09-15 19:47:29 -0600. version 4.0.3 Do not edit! */
/* auto-generated on 2025-09-14 09:01:41 -0600. version 4.0.2 Do not edit! */
/* including simdjson.cpp: */
/* begin file simdjson.cpp */
#define SIMDJSON_SRC_SIMDJSON_CPP
+59 -114
View File
@@ -1,4 +1,4 @@
/* auto-generated on 2025-09-15 19:47:29 -0600. version 4.0.3 Do not edit! */
/* auto-generated on 2025-09-14 09:01:41 -0600. version 4.0.2 Do not edit! */
/* including simdjson.h: */
/* begin file simdjson.h */
#ifndef SIMDJSON_H
@@ -2508,7 +2508,7 @@ namespace std {
#define SIMDJSON_SIMDJSON_VERSION_H
/** The version of simdjson being used (major.minor.revision) */
#define SIMDJSON_VERSION "4.0.3"
#define SIMDJSON_VERSION "4.0.2"
namespace simdjson {
enum {
@@ -2523,7 +2523,7 @@ enum {
/**
* The revision (major.minor.REVISION) of simdjson being used.
*/
SIMDJSON_VERSION_REVISION = 3
SIMDJSON_VERSION_REVISION = 2
};
} // namespace simdjson
@@ -38968,7 +38968,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
@@ -45345,12 +45345,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -45362,8 +45360,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -45394,11 +45393,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -51932,7 +51927,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
@@ -58309,12 +58304,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -58326,8 +58319,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -58358,11 +58352,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -65395,7 +65385,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
@@ -71772,12 +71762,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -71789,8 +71777,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -71821,11 +71810,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -78858,7 +78843,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
@@ -85235,12 +85220,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -85252,8 +85235,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -85284,11 +85268,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -92436,7 +92416,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
@@ -98813,12 +98793,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -98830,8 +98808,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -98862,11 +98841,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -106330,7 +106305,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
@@ -112707,12 +112682,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -112724,8 +112697,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -112756,11 +112730,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -119701,7 +119671,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
@@ -126078,12 +126048,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -126095,8 +126063,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -126127,11 +126096,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -133085,7 +133050,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
}
error_code e = simdjson::SUCCESS;
template for (constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Note: removed static assert as optional types are now handled generically
// as long we are succesful or the field is not found, we continue
@@ -139462,12 +139427,10 @@ simdjson_inline void string_builder::clear() noexcept {
namespace internal {
// We could specialize further for 32-bit integers.
simdjson_really_inline int int_log2(uint32_t x) { return (63 - leading_zeroes(x | 1)); }
template <typename number_type, typename = typename std::enable_if<
std::is_unsigned<number_type>::value>::type>
simdjson_really_inline int int_log2(number_type x) { return 63 - leading_zeroes(uint64_t(x) | 1); }
simdjson_really_inline int fast_digit_count_32(uint32_t x) {
simdjson_really_inline int fast_digit_count(uint32_t x) {
static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
@@ -139479,8 +139442,9 @@ simdjson_really_inline int fast_digit_count_32(uint32_t x) {
return uint32_t((x + table[int_log2(x)]) >> 32);
}
simdjson_really_inline int int_log2(uint64_t x) { return 63 - leading_zeroes(x | 1); }
simdjson_really_inline int fast_digit_count_64(uint64_t x) {
simdjson_really_inline int fast_digit_count(uint64_t x) {
static uint64_t table[] = {9,
99,
999,
@@ -139511,11 +139475,7 @@ simdjson_really_inline size_t digit_count(number_type v) noexcept {
static_assert(sizeof(number_type) == 8 || sizeof(number_type) == 4 ||
sizeof(number_type) == 2 || sizeof(number_type) == 1,
"We only support 8-bit, 16-bit, 32-bit and 64-bit numbers");
SIMDJSON_IF_CONSTEXPR(sizeof(number_type) <= 4) {
return fast_digit_count_32(static_cast<uint32_t>(v));
} else {
return fast_digit_count_64(static_cast<uint64_t>(v));
}
return fast_digit_count(v);
}
static const char decimal_table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
@@ -140284,11 +140244,6 @@ struct to_adaptor {
T operator()(simdjson_result<ondemand::value> &val) const noexcept;
auto operator()(padded_string_view const str) const noexcept;
auto operator()(ondemand::parser &parser, padded_string_view const str) const noexcept;
// The std::string is padded with reserve to ensure there is enough space for padding.
// Some sanitizers may not like this, so you can use simdjson::pad instead.
// simdjson::from(simdjson::pad(str))
auto operator()(std::string str) const noexcept;
auto operator()(ondemand::parser &parser, std::string str) const noexcept;
};
} // namespace internal
} // namespace convert
@@ -140447,16 +140402,6 @@ template <typename T>
inline auto to_adaptor<T>::operator()(ondemand::parser &parser, padded_string_view const str) const noexcept {
return auto_parser<ondemand::parser *>{parser, str};
}
template <typename T>
inline auto to_adaptor<T>::operator()(std::string str) const noexcept {
return auto_parser{pad_with_reserve(str)};
}
template <typename T>
inline auto to_adaptor<T>::operator()(ondemand::parser &parser, std::string str) const noexcept {
return auto_parser<ondemand::parser *>{parser, pad_with_reserve(str)};
}
} // namespace internal
} // namespace convert
} // namespace simdjson
Binary file not shown.
+20
View File
@@ -21,6 +21,19 @@ bool implementation::supported_by_runtime_system() const {
#define SIMDJSON_CONDITIONAL_INCLUDE
#if SIMDJSON_IMPLEMENTATION_RVV
#include <simdjson/rvv/implementation.h>
namespace simdjson {
namespace internal {
static const rvv::implementation* get_rvv_singleton() {
static const rvv::implementation rvv_singleton{};
return &rvv_singleton;
}
} // namespace internal
} // namespace simdjson
#endif // SIMDJSON_IMPLEMENTATION_RVV
#if SIMDJSON_IMPLEMENTATION_ARM64
#include <simdjson/arm64/implementation.h>
namespace simdjson {
@@ -130,6 +143,7 @@ namespace internal {
+ SIMDJSON_IMPLEMENTATION_HASWELL + SIMDJSON_IMPLEMENTATION_WESTMERE \
+ SIMDJSON_IMPLEMENTATION_ARM64 + SIMDJSON_IMPLEMENTATION_PPC64 \
+ SIMDJSON_IMPLEMENTATION_LSX + SIMDJSON_IMPLEMENTATION_LASX \
+ SIMDJSON_IMPLEMENTATION_RVV \
+ SIMDJSON_IMPLEMENTATION_FALLBACK == 1)
#if SIMDJSON_SINGLE_IMPLEMENTATION
@@ -156,6 +170,9 @@ namespace internal {
#if SIMDJSON_IMPLEMENTATION_LASX
get_lasx_singleton();
#endif
#if SIMDJSON_IMPLEMENTATION_RVV
get_rvv_singleton();
#endif
#if SIMDJSON_IMPLEMENTATION_FALLBACK
get_fallback_singleton();
#endif
@@ -216,6 +233,9 @@ static const std::initializer_list<const implementation *>& get_available_implem
#if SIMDJSON_IMPLEMENTATION_LASX
get_lasx_singleton(),
#endif
#if SIMDJSON_IMPLEMENTATION_RVV
get_rvv_singleton(),
#endif
#if SIMDJSON_IMPLEMENTATION_FALLBACK
get_fallback_singleton(),
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef SIMDJSON_SRC_RVV_CPP
#define SIMDJSON_SRC_RVV_CPP
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include <base.h>
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#include <simdjson/rvv.h>
#include <simdjson/rvv/implementation.h>
namespace simdjson {
namespace rvv {
error_code implementation::create_dom_parser_implementation(
size_t, size_t,
std::unique_ptr<simdjson::internal::dom_parser_implementation>&) const noexcept {
return error_code::UNSUPPORTED_ARCHITECTURE;
}
} // namespace rvv
} // namespace simdjson
#endif // SIMDJSON_SRC_RVV_CPP
+3
View File
@@ -41,6 +41,9 @@ SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
#if SIMDJSON_IMPLEMENTATION_LASX
#include <lasx.cpp>
#endif
#if SIMDJSON_IMPLEMENTATION_RVV
#include <rvv.cpp>
#endif
#if SIMDJSON_IMPLEMENTATION_FALLBACK
#include <fallback.cpp>
#endif
+1 -52
View File
@@ -2,7 +2,6 @@
#include "simdjson/convert.h"
#include "test_ondemand.h"
#include <chrono>
#include <map>
#include <ranges>
#include <string>
@@ -22,24 +21,6 @@ private:
std::string date_str;
};
struct Meeting {
std::string title;
std::vector<std::string> attendees;
std::optional<std::string> location;
bool is_recurring;
};
struct MeetingTime {
std::string title;
std::chrono::system_clock::time_point start_time;
std::vector<std::string> attendees;
std::optional<std::string> location;
bool is_recurring;
};
namespace simdjson {
template <typename simdjson_value>
auto tag_invoke(deserialize_tag, simdjson_value &val, MyDate& date) {
@@ -179,38 +160,6 @@ bool simple() {
ASSERT_SUCCESS(doc.get(p));
TEST_SUCCEED();
}
bool meeting_test() {
TEST_START();
std::string json = simdjson::to_json(Meeting{
.title = "CppCon Planning",
.attendees = {"Alice", "Bob", "Charlie"},
.location = "Denver",
.is_recurring = true
});
Meeting m2 = simdjson::from(json);
std::cout << m2.title << std::endl;
TEST_SUCCEED();
}
bool meeting_time_test() {
TEST_START();
auto start_time = std::chrono::system_clock::now();
std::string json = simdjson::to_json(MeetingTime{
.title = "CppCon Planning",
.start_time = start_time,
.attendees = {"Alice", "Bob", "Charlie"},
.location = "Denver",
.is_recurring = true
});
std::cout << json << std::endl;
MeetingTime m2 = simdjson::from(json);
//ASSERT_EQUAL(m2.start_time, start_time);
std::cout << m2.title << std::endl;
TEST_SUCCEED();
}
#endif
bool broken() {
TEST_START();
@@ -466,7 +415,7 @@ bool test_to_vs_from_equivalence() {
bool run() {
return
#if SIMDJSON_STATIC_REFLECTION
meeting_time_test() && meeting_test() && bad_player() && good_player() && complicated_weather_test() &&
bad_player() && good_player() && complicated_weather_test() &&
#endif
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_CONCEPTS
broken() && simple() && simple_optional() && with_parser() && to_array() &&