Coverage Report

Created: 2026-09-14 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/build-dir/_deps/simdjson-src/src/implementation.cpp
Line
Count
Source
1
#ifndef SIMDJSON_SRC_IMPLEMENTATION_CPP
2
#define SIMDJSON_SRC_IMPLEMENTATION_CPP
3
4
#include <base.h>
5
#include <simdjson/generic/dependencies.h>
6
#include <simdjson/implementation.h>
7
#include <internal/isadetection.h>
8
9
#include <initializer_list>
10
#include <type_traits>
11
12
namespace simdjson {
13
14
0
bool implementation::supported_by_runtime_system() const {
15
0
  uint32_t required_instruction_sets = this->required_instruction_sets();
16
0
  uint32_t supported_instruction_sets = internal::detect_supported_architectures();
17
0
  return ((supported_instruction_sets & required_instruction_sets) == required_instruction_sets);
18
0
}
19
20
} // namespace simdjson
21
22
#define SIMDJSON_CONDITIONAL_INCLUDE
23
24
#if SIMDJSON_IMPLEMENTATION_ARM64
25
#include <simdjson/arm64/implementation.h>
26
namespace simdjson {
27
namespace internal {
28
static const arm64::implementation* get_arm64_singleton() {
29
  static const arm64::implementation arm64_singleton{};
30
  return &arm64_singleton;
31
}
32
} // namespace internal
33
} // namespace simdjson
34
#endif // SIMDJSON_IMPLEMENTATION_ARM64
35
36
#if SIMDJSON_IMPLEMENTATION_FALLBACK
37
#include <simdjson/fallback/implementation.h>
38
namespace simdjson {
39
namespace internal {
40
0
static const fallback::implementation* get_fallback_singleton() {
41
0
  static const fallback::implementation fallback_singleton{};
42
0
  return &fallback_singleton;
43
0
}
44
} // namespace internal
45
} // namespace simdjson
46
#endif // SIMDJSON_IMPLEMENTATION_FALLBACK
47
48
49
#if SIMDJSON_IMPLEMENTATION_HASWELL
50
#include <simdjson/haswell/implementation.h>
51
namespace simdjson {
52
namespace internal {
53
0
static const haswell::implementation* get_haswell_singleton() {
54
0
  static const haswell::implementation haswell_singleton{};
55
0
  return &haswell_singleton;
56
0
}
57
} // namespace internal
58
} // namespace simdjson
59
#endif
60
61
#if SIMDJSON_IMPLEMENTATION_ICELAKE
62
#include <simdjson/icelake/implementation.h>
63
namespace simdjson {
64
namespace internal {
65
0
static const icelake::implementation* get_icelake_singleton() {
66
0
  static const icelake::implementation icelake_singleton{};
67
0
  return &icelake_singleton;
68
0
}
69
} // namespace internal
70
} // namespace simdjson
71
#endif
72
73
#if SIMDJSON_IMPLEMENTATION_PPC64
74
#include <simdjson/ppc64/implementation.h>
75
namespace simdjson {
76
namespace internal {
77
static const ppc64::implementation* get_ppc64_singleton() {
78
  static const ppc64::implementation ppc64_singleton{};
79
  return &ppc64_singleton;
80
}
81
} // namespace internal
82
} // namespace simdjson
83
#endif // SIMDJSON_IMPLEMENTATION_PPC64
84
85
#if SIMDJSON_IMPLEMENTATION_WESTMERE
86
#include <simdjson/westmere/implementation.h>
87
namespace simdjson {
88
namespace internal {
89
0
static const simdjson::westmere::implementation* get_westmere_singleton() {
90
0
  static const simdjson::westmere::implementation westmere_singleton{};
91
0
  return &westmere_singleton;
92
0
}
93
} // namespace internal
94
} // namespace simdjson
95
#endif // SIMDJSON_IMPLEMENTATION_WESTMERE
96
97
#if SIMDJSON_IMPLEMENTATION_LASX
98
#include <simdjson/lasx/implementation.h>
99
namespace simdjson {
100
namespace internal {
101
static const simdjson::lasx::implementation* get_lasx_singleton() {
102
  static const simdjson::lasx::implementation lasx_singleton{};
103
  return &lasx_singleton;
104
}
105
} // namespace internal
106
} // namespace simdjson
107
#endif // SIMDJSON_IMPLEMENTATION_LASX
108
109
#if SIMDJSON_IMPLEMENTATION_LSX
110
#include <simdjson/lsx/implementation.h>
111
namespace simdjson {
112
namespace internal {
113
static const simdjson::lsx::implementation* get_lsx_singleton() {
114
  static const simdjson::lsx::implementation lsx_singleton{};
115
  return &lsx_singleton;
116
}
117
} // namespace internal
118
} // namespace simdjson
119
#endif // SIMDJSON_IMPLEMENTATION_LSX
120
121
#if SIMDJSON_IMPLEMENTATION_RVV_VLS
122
#include <simdjson/rvv-vls/implementation.h>
123
namespace simdjson {
124
namespace internal {
125
static const simdjson::rvv_vls::implementation* get_rvv_vls_singleton() {
126
  static const simdjson::rvv_vls::implementation rvv_vls_singleton{};
127
  return &rvv_vls_singleton;
128
}
129
} // namespace internal
130
} // namespace simdjson
131
#endif // SIMDJSON_IMPLEMENTATION_RVV_VLS
132
133
#undef SIMDJSON_CONDITIONAL_INCLUDE
134
135
namespace simdjson {
136
namespace internal {
137
138
// When there is a single implementation, we should not pay a price
139
// for dispatching to the best implementation. We should just use the
140
// one we have. This is a compile-time check.
141
#define SIMDJSON_SINGLE_IMPLEMENTATION (SIMDJSON_IMPLEMENTATION_ICELAKE \
142
             + SIMDJSON_IMPLEMENTATION_HASWELL + SIMDJSON_IMPLEMENTATION_WESTMERE \
143
             + SIMDJSON_IMPLEMENTATION_ARM64 + SIMDJSON_IMPLEMENTATION_PPC64 \
144
             + SIMDJSON_IMPLEMENTATION_LSX + SIMDJSON_IMPLEMENTATION_LASX \
145
             + SIMDJSON_IMPLEMENTATION_RVV_VLS + SIMDJSON_IMPLEMENTATION_FALLBACK == 1)
146
147
#if SIMDJSON_SINGLE_IMPLEMENTATION
148
  simdjson_really_inline static const implementation* get_single_implementation() {
149
    return
150
#if SIMDJSON_IMPLEMENTATION_ICELAKE
151
    get_icelake_singleton();
152
#endif
153
#if SIMDJSON_IMPLEMENTATION_HASWELL
154
    get_haswell_singleton();
155
#endif
156
#if SIMDJSON_IMPLEMENTATION_WESTMERE
157
    get_westmere_singleton();
158
#endif
159
#if SIMDJSON_IMPLEMENTATION_ARM64
160
    get_arm64_singleton();
161
#endif
162
#if SIMDJSON_IMPLEMENTATION_PPC64
163
    get_ppc64_singleton();
164
#endif
165
#if SIMDJSON_IMPLEMENTATION_LSX
166
    get_lsx_singleton();
167
#endif
168
#if SIMDJSON_IMPLEMENTATION_LASX
169
    get_lasx_singleton();
170
#endif
171
#if SIMDJSON_IMPLEMENTATION_RVV_VLS
172
    get_rvv_vls_singleton();
173
#endif
174
#if SIMDJSON_IMPLEMENTATION_FALLBACK
175
    get_fallback_singleton();
176
#endif
177
}
178
#endif
179
180
// Static array of known implementations. We're hoping these get baked into the executable
181
// without requiring a static initializer.
182
183
/**
184
 * @private Detects best supported implementation on first use, and sets it
185
 */
186
class detect_best_supported_implementation_on_first_use final : public implementation {
187
public:
188
0
  std::string name() const noexcept final { return set_best()->name(); }
189
0
  std::string description() const noexcept final { return set_best()->description(); }
190
0
  uint32_t required_instruction_sets() const noexcept final { return set_best()->required_instruction_sets(); }
191
  simdjson_warn_unused error_code create_dom_parser_implementation(
192
    size_t capacity,
193
    size_t max_length,
194
    std::unique_ptr<internal::dom_parser_implementation>& dst
195
0
  ) const noexcept final {
196
0
    return set_best()->create_dom_parser_implementation(capacity, max_length, dst);
197
0
  }
198
0
  simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final {
199
0
    return set_best()->minify(buf, len, dst, dst_len);
200
0
  }
201
0
  simdjson_warn_unused bool validate_utf8(const char * buf, size_t len) const noexcept final override {
202
0
    return set_best()->validate_utf8(buf, len);
203
0
  }
204
0
  simdjson_inline detect_best_supported_implementation_on_first_use() noexcept : implementation("best_supported_detector", "Detects the best supported implementation and sets it", 0) {}
205
private:
206
  const implementation *set_best() const noexcept;
207
};
208
209
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");
210
211
0
static const std::initializer_list<const implementation *>& get_available_implementation_pointers() {
212
0
  static const std::initializer_list<const implementation *> available_implementation_pointers {
213
0
#if SIMDJSON_IMPLEMENTATION_ICELAKE
214
0
    get_icelake_singleton(),
215
0
#endif
216
0
#if SIMDJSON_IMPLEMENTATION_HASWELL
217
0
    get_haswell_singleton(),
218
0
#endif
219
0
#if SIMDJSON_IMPLEMENTATION_WESTMERE
220
0
    get_westmere_singleton(),
221
0
#endif
222
#if SIMDJSON_IMPLEMENTATION_ARM64
223
    get_arm64_singleton(),
224
#endif
225
#if SIMDJSON_IMPLEMENTATION_PPC64
226
    get_ppc64_singleton(),
227
#endif
228
#if SIMDJSON_IMPLEMENTATION_LASX
229
    get_lasx_singleton(),
230
#endif
231
#if SIMDJSON_IMPLEMENTATION_LSX
232
    get_lsx_singleton(),
233
#endif
234
#if SIMDJSON_IMPLEMENTATION_RVV_VLS
235
    get_rvv_vls_singleton(),
236
#endif
237
0
#if SIMDJSON_IMPLEMENTATION_FALLBACK
238
0
    get_fallback_singleton(),
239
0
#endif
240
0
  }; // available_implementation_pointers
241
0
  return available_implementation_pointers;
242
0
}
243
244
// So we can return UNSUPPORTED_ARCHITECTURE from the parser when there is no support
245
class unsupported_implementation final : public implementation {
246
public:
247
  simdjson_warn_unused error_code create_dom_parser_implementation(
248
    size_t,
249
    size_t,
250
    std::unique_ptr<internal::dom_parser_implementation>&
251
0
  ) const noexcept final {
252
0
    return UNSUPPORTED_ARCHITECTURE;
253
0
  }
254
0
  simdjson_warn_unused error_code minify(const uint8_t *, size_t, uint8_t *, size_t &) const noexcept final override {
255
0
    return UNSUPPORTED_ARCHITECTURE;
256
0
  }
257
0
  simdjson_warn_unused bool validate_utf8(const char *, size_t) const noexcept final override {
258
0
    return false; // Just refuse to validate. Given that we have a fallback implementation
259
    // it seems unlikely that unsupported_implementation will ever be used. If it is used,
260
    // then it will flag all strings as invalid. The alternative is to return an error_code
261
    // from which the user has to figure out whether the string is valid UTF-8... which seems
262
    // like a lot of work just to handle the very unlikely case that we have an unsupported
263
    // implementation. And, when it does happen (that we have an unsupported implementation),
264
    // what are the chances that the programmer has a fallback? Given that *we* provide the
265
    // fallback, it implies that the programmer would need a fallback for our fallback.
266
0
  }
267
0
  unsupported_implementation() : implementation("unsupported", "Unsupported CPU (no detected SIMD instructions)", 0) {}
268
};
269
270
static_assert(std::is_trivially_destructible<unsupported_implementation>::value, "unsupported_singleton should be trivially destructible");
271
272
0
const unsupported_implementation* get_unsupported_singleton() {
273
0
    static const unsupported_implementation unsupported_singleton{};
274
0
    return &unsupported_singleton;
275
0
}
276
277
0
size_t available_implementation_list::size() const noexcept {
278
0
  return internal::get_available_implementation_pointers().size();
279
0
}
280
0
const implementation * const *available_implementation_list::begin() const noexcept {
281
0
  return internal::get_available_implementation_pointers().begin();
282
0
}
283
0
const implementation * const *available_implementation_list::end() const noexcept {
284
0
  return internal::get_available_implementation_pointers().end();
285
0
}
286
0
const implementation *available_implementation_list::detect_best_supported() const noexcept {
287
  // They are prelisted in priority order, so we just go down the list
288
0
  uint32_t supported_instruction_sets = internal::detect_supported_architectures();
289
0
  for (const implementation *impl : internal::get_available_implementation_pointers()) {
290
0
    uint32_t required_instruction_sets = impl->required_instruction_sets();
291
0
    if ((supported_instruction_sets & required_instruction_sets) == required_instruction_sets) { return impl; }
292
0
  }
293
0
  return get_unsupported_singleton(); // this should never happen?
294
0
}
295
296
0
const implementation *detect_best_supported_implementation_on_first_use::set_best() const noexcept {
297
0
  SIMDJSON_PUSH_DISABLE_WARNINGS
298
  SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
299
0
  char *force_implementation_name = getenv("SIMDJSON_FORCE_IMPLEMENTATION");
300
0
  SIMDJSON_POP_DISABLE_WARNINGS
301
302
0
  if (force_implementation_name) {
303
0
    auto force_implementation = get_available_implementations()[force_implementation_name];
304
0
    if (force_implementation) {
305
0
      return get_active_implementation() = force_implementation;
306
0
    } else {
307
      // Note: abort() and stderr usage within the library is forbidden.
308
0
      return get_active_implementation() = get_unsupported_singleton();
309
0
    }
310
0
  }
311
0
  return get_active_implementation() = get_available_implementations().detect_best_supported();
312
0
}
313
314
} // namespace internal
315
316
0
SIMDJSON_DLLIMPORTEXPORT const internal::available_implementation_list& get_available_implementations() {
317
0
  static const internal::available_implementation_list available_implementations{};
318
0
  return available_implementations;
319
0
}
320
321
0
SIMDJSON_DLLIMPORTEXPORT internal::atomic_ptr<const implementation>& get_active_implementation() {
322
#if SIMDJSON_SINGLE_IMPLEMENTATION
323
  // We immediately select the only implementation we have, skipping the
324
  // detect_best_supported_implementation_on_first_use_singleton.
325
  static internal::atomic_ptr<const implementation> active_implementation{internal::get_single_implementation()};
326
  return active_implementation;
327
#else
328
0
  static const internal::detect_best_supported_implementation_on_first_use detect_best_supported_implementation_on_first_use_singleton;
329
0
  static internal::atomic_ptr<const implementation> active_implementation{&detect_best_supported_implementation_on_first_use_singleton};
330
0
  return active_implementation;
331
0
#endif
332
0
}
333
334
0
simdjson_warn_unused error_code minify(const char *buf, size_t len, char *dst, size_t &dst_len) noexcept {
335
0
  return get_active_implementation()->minify(reinterpret_cast<const uint8_t *>(buf), len, reinterpret_cast<uint8_t *>(dst), dst_len);
336
0
}
337
0
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept {
338
0
  return get_active_implementation()->validate_utf8(buf, len);
339
0
}
340
0
const implementation * builtin_implementation() {
341
0
  static const implementation * builtin_impl = get_available_implementations()[SIMDJSON_STRINGIFY(SIMDJSON_BUILTIN_IMPLEMENTATION)];
342
  assert(builtin_impl);
343
0
  return builtin_impl;
344
0
}
345
346
} // namespace simdjson
347
348
#endif // SIMDJSON_SRC_IMPLEMENTATION_CPP