json 2.15.2 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +10 -0
- data/LEGAL +12 -0
- data/README.md +17 -1
- data/ext/json/ext/fbuffer/fbuffer.h +3 -52
- data/ext/json/ext/generator/generator.c +157 -133
- data/ext/json/ext/json.h +92 -0
- data/ext/json/ext/parser/extconf.rb +2 -0
- data/ext/json/ext/parser/parser.c +400 -316
- data/ext/json/ext/simd/simd.h +15 -12
- data/ext/json/ext/vendor/ryu.h +819 -0
- data/lib/json/common.rb +7 -12
- data/lib/json/ext/generator/state.rb +4 -0
- data/lib/json/truffle_ruby/generator.rb +31 -7
- data/lib/json/version.rb +1 -1
- metadata +3 -1
data/ext/json/ext/simd/simd.h
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
#include "../json.h"
|
|
2
|
+
|
|
1
3
|
typedef enum {
|
|
2
4
|
SIMD_NONE,
|
|
3
5
|
SIMD_NEON,
|
|
4
6
|
SIMD_SSE2
|
|
5
7
|
} SIMD_Implementation;
|
|
6
8
|
|
|
7
|
-
#
|
|
9
|
+
#ifndef __has_builtin // Optional of course.
|
|
10
|
+
#define __has_builtin(x) 0 // Compatibility with non-clang compilers.
|
|
11
|
+
#endif
|
|
8
12
|
|
|
9
13
|
#ifdef __clang__
|
|
10
14
|
# if __has_builtin(__builtin_ctzll)
|
|
@@ -20,6 +24,8 @@ typedef enum {
|
|
|
20
24
|
|
|
21
25
|
static inline uint32_t trailing_zeros64(uint64_t input)
|
|
22
26
|
{
|
|
27
|
+
JSON_ASSERT(input > 0); // __builtin_ctz(0) is undefined behavior
|
|
28
|
+
|
|
23
29
|
#if HAVE_BUILTIN_CTZLL
|
|
24
30
|
return __builtin_ctzll(input);
|
|
25
31
|
#else
|
|
@@ -35,6 +41,8 @@ static inline uint32_t trailing_zeros64(uint64_t input)
|
|
|
35
41
|
|
|
36
42
|
static inline int trailing_zeros(int input)
|
|
37
43
|
{
|
|
44
|
+
JSON_ASSERT(input > 0); // __builtin_ctz(0) is undefined behavior
|
|
45
|
+
|
|
38
46
|
#if HAVE_BUILTIN_CTZLL
|
|
39
47
|
return __builtin_ctz(input);
|
|
40
48
|
#else
|
|
@@ -48,12 +56,7 @@ static inline int trailing_zeros(int input)
|
|
|
48
56
|
#endif
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
#
|
|
52
|
-
#define FORCE_INLINE __attribute__((always_inline))
|
|
53
|
-
#else
|
|
54
|
-
#define FORCE_INLINE
|
|
55
|
-
#endif
|
|
56
|
-
|
|
59
|
+
#ifdef JSON_ENABLE_SIMD
|
|
57
60
|
|
|
58
61
|
#define SIMD_MINIMUM_THRESHOLD 6
|
|
59
62
|
|
|
@@ -70,14 +73,14 @@ static inline SIMD_Implementation find_simd_implementation(void)
|
|
|
70
73
|
#define HAVE_SIMD_NEON 1
|
|
71
74
|
|
|
72
75
|
// See: https://community.arm.com/arm-community-blogs/b/servers-and-cloud-computing-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon
|
|
73
|
-
static
|
|
76
|
+
static ALWAYS_INLINE() uint64_t neon_match_mask(uint8x16_t matches)
|
|
74
77
|
{
|
|
75
78
|
const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(matches), 4);
|
|
76
79
|
const uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(res), 0);
|
|
77
80
|
return mask & 0x8888888888888888ull;
|
|
78
81
|
}
|
|
79
82
|
|
|
80
|
-
static
|
|
83
|
+
static ALWAYS_INLINE() uint64_t compute_chunk_mask_neon(const char *ptr)
|
|
81
84
|
{
|
|
82
85
|
uint8x16_t chunk = vld1q_u8((const unsigned char *)ptr);
|
|
83
86
|
|
|
@@ -90,7 +93,7 @@ static inline FORCE_INLINE uint64_t compute_chunk_mask_neon(const char *ptr)
|
|
|
90
93
|
return neon_match_mask(needs_escape);
|
|
91
94
|
}
|
|
92
95
|
|
|
93
|
-
static
|
|
96
|
+
static ALWAYS_INLINE() int string_scan_simd_neon(const char **ptr, const char *end, uint64_t *mask)
|
|
94
97
|
{
|
|
95
98
|
while (*ptr + sizeof(uint8x16_t) <= end) {
|
|
96
99
|
uint64_t chunk_mask = compute_chunk_mask_neon(*ptr);
|
|
@@ -137,7 +140,7 @@ static inline uint8x16x4_t load_uint8x16_4(const unsigned char *table)
|
|
|
137
140
|
#define _mm_cmpgt_epu8(a, b) _mm_xor_si128(_mm_cmple_epu8(a, b), _mm_set1_epi8(-1))
|
|
138
141
|
#define _mm_cmplt_epu8(a, b) _mm_cmpgt_epu8(b, a)
|
|
139
142
|
|
|
140
|
-
static
|
|
143
|
+
static TARGET_SSE2 ALWAYS_INLINE() int compute_chunk_mask_sse2(const char *ptr)
|
|
141
144
|
{
|
|
142
145
|
__m128i chunk = _mm_loadu_si128((__m128i const*)ptr);
|
|
143
146
|
// Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33
|
|
@@ -148,7 +151,7 @@ static inline TARGET_SSE2 FORCE_INLINE int compute_chunk_mask_sse2(const char *p
|
|
|
148
151
|
return _mm_movemask_epi8(needs_escape);
|
|
149
152
|
}
|
|
150
153
|
|
|
151
|
-
static
|
|
154
|
+
static TARGET_SSE2 ALWAYS_INLINE() int string_scan_simd_sse2(const char **ptr, const char *end, int *mask)
|
|
152
155
|
{
|
|
153
156
|
while (*ptr + sizeof(__m128i) <= end) {
|
|
154
157
|
int chunk_mask = compute_chunk_mask_sse2(*ptr);
|