Ensuring that stage 1's json_block and cie are never copied and using explicit constructors (issue 1475) (#1478)
This commit is contained in:
parent
79e94227c2
commit
dc2f767171
|
@ -19,17 +19,28 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {gen: Visual Studio 15 2017, arch: Win32}
|
||||
- {gen: Visual Studio 15 2017, arch: x64}
|
||||
- {gen: Visual Studio 15 2017, arch: Win32, static: ON}
|
||||
- {gen: Visual Studio 15 2017, arch: Win32, static: OFF}
|
||||
- {gen: Visual Studio 15 2017, arch: x64, static: ON}
|
||||
- {gen: Visual Studio 15 2017, arch: x64, static: OFF}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build
|
||||
cd build && cmake -DSIMDJSON_COMPETITION=OFF -G "${{matrix.gen}}" -A ${{matrix.arch}} ..
|
||||
- name: Build
|
||||
run: cmake --build build --config Release --parallel
|
||||
- name: 'Run CTest'
|
||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_BUILD_STATIC=${{matrix.static}} -B build
|
||||
- name: Build Debug
|
||||
run: cmake --build build --config Debug --verbose
|
||||
- name: Build Release
|
||||
run: cmake --build build --config Release --verbose
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd build
|
||||
ctest -C Release -LE explicitonly --output-on-failure
|
||||
- name: Install
|
||||
run: |
|
||||
cmake --install build --config Release
|
||||
- name: Test Installation
|
||||
run: |
|
||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -B build_install_test tests/installation_tests/find
|
||||
cmake --build build_install_test --config Release
|
|
@ -19,6 +19,8 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {gen: Visual Studio 16 2019, arch: Win32, static: ON}
|
||||
- {gen: Visual Studio 16 2019, arch: Win32, static: OFF}
|
||||
- {gen: Visual Studio 16 2019, arch: x64, static: ON}
|
||||
- {gen: Visual Studio 16 2019, arch: x64, static: OFF}
|
||||
steps:
|
||||
|
@ -27,8 +29,10 @@ jobs:
|
|||
- name: Configure
|
||||
run: |
|
||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_BUILD_STATIC=${{matrix.static}} -B build
|
||||
- name: Build
|
||||
run: cmake --build build --config Release
|
||||
- name: Build Debug
|
||||
run: cmake --build build --config Debug --verbose
|
||||
- name: Build Release
|
||||
run: cmake --build build --config Release --verbose
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd build
|
||||
|
|
|
@ -421,7 +421,7 @@ simdjson_really_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x
|
|||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T> other) = delete; // no assignment allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
simd8x64() = delete; // no default constructor allowed
|
||||
|
||||
simdjson_really_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
|
||||
|
|
|
@ -297,7 +297,7 @@ namespace simd {
|
|||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T> other) = delete; // no assignment allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
simd8x64() = delete; // no default constructor allowed
|
||||
|
||||
simdjson_really_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1) : chunks{chunk0, chunk1} {}
|
||||
|
|
|
@ -400,7 +400,7 @@ template <typename T> struct simd8x64 {
|
|||
|
||||
simd8x64(const simd8x64<T> &o) = delete; // no copy allowed
|
||||
simd8x64<T> &
|
||||
operator=(const simd8<T> other) = delete; // no assignment allowed
|
||||
operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
simd8x64() = delete; // no default constructor allowed
|
||||
|
||||
simdjson_really_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1,
|
||||
|
|
|
@ -267,7 +267,7 @@ namespace simd {
|
|||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T> other) = delete; // no assignment allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
simd8x64() = delete; // no default constructor allowed
|
||||
|
||||
simdjson_really_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
|
||||
|
|
|
@ -12,9 +12,9 @@ using namespace simd;
|
|||
struct json_character_block {
|
||||
static simdjson_really_inline json_character_block classify(const simd::simd8x64<uint8_t>& in);
|
||||
|
||||
simdjson_really_inline uint64_t whitespace() const { return _whitespace; }
|
||||
simdjson_really_inline uint64_t op() const { return _op; }
|
||||
simdjson_really_inline uint64_t scalar() { return ~(op() | whitespace()); }
|
||||
simdjson_really_inline uint64_t whitespace() const noexcept { return _whitespace; }
|
||||
simdjson_really_inline uint64_t op() const noexcept { return _op; }
|
||||
simdjson_really_inline uint64_t scalar() const noexcept { return ~(op() | whitespace()); }
|
||||
|
||||
uint64_t _whitespace;
|
||||
uint64_t _op;
|
||||
|
|
|
@ -19,13 +19,13 @@ private:
|
|||
{}
|
||||
template<size_t STEP_SIZE>
|
||||
simdjson_really_inline void step(const uint8_t *block_buf, buf_block_reader<STEP_SIZE> &reader) noexcept;
|
||||
simdjson_really_inline void next(const simd::simd8x64<uint8_t>& in, json_block block);
|
||||
simdjson_really_inline void next(const simd::simd8x64<uint8_t>& in, const json_block& block);
|
||||
simdjson_really_inline error_code finish(uint8_t *dst_start, size_t &dst_len);
|
||||
json_scanner scanner{};
|
||||
uint8_t *dst;
|
||||
};
|
||||
|
||||
simdjson_really_inline void json_minifier::next(const simd::simd8x64<uint8_t>& in, json_block block) {
|
||||
simdjson_really_inline void json_minifier::next(const simd::simd8x64<uint8_t>& in, const json_block& block) {
|
||||
uint64_t mask = block.whitespace();
|
||||
in.compress(mask, dst);
|
||||
dst += 64 - count_ones(mask);
|
||||
|
|
|
@ -22,20 +22,26 @@ namespace stage1 {
|
|||
*/
|
||||
struct json_block {
|
||||
public:
|
||||
// We spell out the constructors in the hope of resolving inlining issues with Visual Studio 2017
|
||||
simdjson_really_inline json_block(json_string_block&& string, json_character_block characters, uint64_t follows_potential_nonquote_scalar) :
|
||||
_string(std::move(string)), _characters(characters), _follows_potential_nonquote_scalar(follows_potential_nonquote_scalar) {}
|
||||
simdjson_really_inline json_block(json_string_block string, json_character_block characters, uint64_t follows_potential_nonquote_scalar) :
|
||||
_string(string), _characters(characters), _follows_potential_nonquote_scalar(follows_potential_nonquote_scalar) {}
|
||||
|
||||
/**
|
||||
* The start of structurals.
|
||||
* In simdjson prior to v0.3, these were called the pseudo-structural characters.
|
||||
**/
|
||||
simdjson_really_inline uint64_t structural_start() { return potential_structural_start() & ~_string.string_tail(); }
|
||||
simdjson_really_inline uint64_t structural_start() const noexcept { return potential_structural_start() & ~_string.string_tail(); }
|
||||
/** All JSON whitespace (i.e. not in a string) */
|
||||
simdjson_really_inline uint64_t whitespace() { return non_quote_outside_string(_characters.whitespace()); }
|
||||
simdjson_really_inline uint64_t whitespace() const noexcept { return non_quote_outside_string(_characters.whitespace()); }
|
||||
|
||||
// Helpers
|
||||
|
||||
/** Whether the given characters are inside a string (only works on non-quotes) */
|
||||
simdjson_really_inline uint64_t non_quote_inside_string(uint64_t mask) { return _string.non_quote_inside_string(mask); }
|
||||
simdjson_really_inline uint64_t non_quote_inside_string(uint64_t mask) const noexcept { return _string.non_quote_inside_string(mask); }
|
||||
/** Whether the given characters are outside a string (only works on non-quotes) */
|
||||
simdjson_really_inline uint64_t non_quote_outside_string(uint64_t mask) { return _string.non_quote_outside_string(mask); }
|
||||
simdjson_really_inline uint64_t non_quote_outside_string(uint64_t mask) const noexcept { return _string.non_quote_outside_string(mask); }
|
||||
|
||||
// string and escape characters
|
||||
json_string_block _string;
|
||||
|
@ -50,12 +56,12 @@ private:
|
|||
* structural elements ([,],{,},:, comma) plus scalar starts like 123, true and "abc".
|
||||
* They may reside inside a string.
|
||||
**/
|
||||
simdjson_really_inline uint64_t potential_structural_start() { return _characters.op() | potential_scalar_start(); }
|
||||
simdjson_really_inline uint64_t potential_structural_start() const noexcept { return _characters.op() | potential_scalar_start(); }
|
||||
/**
|
||||
* The start of non-operator runs, like 123, true and "abc".
|
||||
* It main reside inside a string.
|
||||
**/
|
||||
simdjson_really_inline uint64_t potential_scalar_start() {
|
||||
simdjson_really_inline uint64_t potential_scalar_start() const noexcept {
|
||||
// The term "scalar" refers to anything except structural characters and white space
|
||||
// (so letters, numbers, quotes).
|
||||
// Whenever it is preceded by something that is not a structural element ({,},[,],:, ") nor a white-space
|
||||
|
@ -66,7 +72,7 @@ private:
|
|||
* Whether the given character is immediately after a non-operator like 123, true.
|
||||
* The characters following a quote are not included.
|
||||
*/
|
||||
simdjson_really_inline uint64_t follows_potential_scalar() {
|
||||
simdjson_really_inline uint64_t follows_potential_scalar() const noexcept {
|
||||
// _follows_potential_nonquote_scalar: is defined as marking any character that follows a character
|
||||
// that is not a structural element ({,},[,],:, comma) nor a quote (") and that is not a
|
||||
// white space.
|
||||
|
@ -132,11 +138,13 @@ simdjson_really_inline json_block json_scanner::next(const simd::simd8x64<uint8_
|
|||
// Performance: there are many ways to skin this cat.
|
||||
const uint64_t nonquote_scalar = characters.scalar() & ~strings.quote();
|
||||
uint64_t follows_nonquote_scalar = follows(nonquote_scalar, prev_scalar);
|
||||
return {
|
||||
strings,
|
||||
// We are returning a function-local object so either we get a move constructor
|
||||
// or we get copy elision.
|
||||
return json_block(
|
||||
strings,// strings is a function-local object so either it moves or the copy is elided.
|
||||
characters,
|
||||
follows_nonquote_scalar
|
||||
};
|
||||
);
|
||||
}
|
||||
|
||||
simdjson_really_inline error_code json_scanner::finish() {
|
||||
|
|
|
@ -4,6 +4,10 @@ namespace {
|
|||
namespace stage1 {
|
||||
|
||||
struct json_string_block {
|
||||
// We spell out the constructors in the hope of resolving inlining issues with Visual Studio 2017
|
||||
simdjson_really_inline json_string_block(uint64_t backslash, uint64_t escaped, uint64_t quote, uint64_t in_string) :
|
||||
_backslash(backslash), _escaped(escaped), _quote(quote), _in_string(in_string) {}
|
||||
|
||||
// Escaped characters (characters following an escape() character)
|
||||
simdjson_really_inline uint64_t escaped() const { return _escaped; }
|
||||
// Escape characters (backslashes that are not escaped--i.e. in \\, includes only the first \)
|
||||
|
@ -125,12 +129,15 @@ simdjson_really_inline json_string_block json_string_scanner::next(const simd::s
|
|||
prev_in_string = uint64_t(static_cast<int64_t>(in_string) >> 63);
|
||||
|
||||
// Use ^ to turn the beginning quote off, and the end quote on.
|
||||
return {
|
||||
|
||||
// We are returning a function-local object so either we get a move constructor
|
||||
// or we get copy elision.
|
||||
return json_string_block(
|
||||
backslash,
|
||||
escaped,
|
||||
quote,
|
||||
in_string
|
||||
};
|
||||
);
|
||||
}
|
||||
|
||||
simdjson_really_inline error_code json_string_scanner::finish() {
|
||||
|
|
|
@ -80,7 +80,7 @@ private:
|
|||
simdjson_really_inline json_structural_indexer(uint32_t *structural_indexes);
|
||||
template<size_t STEP_SIZE>
|
||||
simdjson_really_inline void step(const uint8_t *block, buf_block_reader<STEP_SIZE> &reader) noexcept;
|
||||
simdjson_really_inline void next(const simd::simd8x64<uint8_t>& in, json_block block, size_t idx);
|
||||
simdjson_really_inline void next(const simd::simd8x64<uint8_t>& in, const json_block& block, size_t idx);
|
||||
simdjson_really_inline error_code finish(dom_parser_implementation &parser, size_t idx, size_t len, bool partial);
|
||||
|
||||
json_scanner scanner{};
|
||||
|
@ -170,7 +170,7 @@ simdjson_really_inline void json_structural_indexer::step<64>(const uint8_t *blo
|
|||
reader.advance();
|
||||
}
|
||||
|
||||
simdjson_really_inline void json_structural_indexer::next(const simd::simd8x64<uint8_t>& in, json_block block, size_t idx) {
|
||||
simdjson_really_inline void json_structural_indexer::next(const simd::simd8x64<uint8_t>& in, const json_block& block, size_t idx) {
|
||||
uint64_t unescaped = in.lteq(0x1F);
|
||||
checker.check_next_input(in);
|
||||
indexer.write(uint32_t(idx-64), prev_structurals); // Output *last* iteration's structurals to the parser
|
||||
|
|
|
@ -13,19 +13,19 @@ using namespace simd;
|
|||
struct json_character_block {
|
||||
static simdjson_really_inline json_character_block classify(const simd::simd8x64<uint8_t>& in);
|
||||
// ASCII white-space ('\r','\n','\t',' ')
|
||||
simdjson_really_inline uint64_t whitespace() const;
|
||||
simdjson_really_inline uint64_t whitespace() const noexcept;
|
||||
// non-quote structural characters (comma, colon, braces, brackets)
|
||||
simdjson_really_inline uint64_t op() const;
|
||||
simdjson_really_inline uint64_t op() const noexcept;
|
||||
// neither a structural character nor a white-space, so letters, numbers and quotes
|
||||
simdjson_really_inline uint64_t scalar() const;
|
||||
simdjson_really_inline uint64_t scalar() const noexcept;
|
||||
|
||||
uint64_t _whitespace; // ASCII white-space ('\r','\n','\t',' ')
|
||||
uint64_t _op; // structural characters (comma, colon, braces, brackets but not quotes)
|
||||
};
|
||||
|
||||
simdjson_really_inline uint64_t json_character_block::whitespace() const { return _whitespace; }
|
||||
simdjson_really_inline uint64_t json_character_block::op() const { return _op; }
|
||||
simdjson_really_inline uint64_t json_character_block::scalar() const { return ~(op() | whitespace()); }
|
||||
simdjson_really_inline uint64_t json_character_block::whitespace() const noexcept { return _whitespace; }
|
||||
simdjson_really_inline uint64_t json_character_block::op() const noexcept { return _op; }
|
||||
simdjson_really_inline uint64_t json_character_block::scalar() const noexcept { return ~(op() | whitespace()); }
|
||||
|
||||
// This identifies structural characters (comma, colon, braces, brackets),
|
||||
// and ASCII white-space ('\r','\n','\t',' ').
|
||||
|
|
|
@ -12,9 +12,9 @@ using namespace simd;
|
|||
struct json_character_block {
|
||||
static simdjson_really_inline json_character_block classify(const simd::simd8x64<uint8_t>& in);
|
||||
|
||||
simdjson_really_inline uint64_t whitespace() const { return _whitespace; }
|
||||
simdjson_really_inline uint64_t op() const { return _op; }
|
||||
simdjson_really_inline uint64_t scalar() { return ~(op() | whitespace()); }
|
||||
simdjson_really_inline uint64_t whitespace() const noexcept { return _whitespace; }
|
||||
simdjson_really_inline uint64_t op() const noexcept { return _op; }
|
||||
simdjson_really_inline uint64_t scalar() const noexcept { return ~(op() | whitespace()); }
|
||||
|
||||
uint64_t _whitespace;
|
||||
uint64_t _op;
|
||||
|
|
|
@ -13,9 +13,9 @@ using namespace simd;
|
|||
struct json_character_block {
|
||||
static simdjson_really_inline json_character_block classify(const simd::simd8x64<uint8_t>& in);
|
||||
|
||||
simdjson_really_inline uint64_t whitespace() const { return _whitespace; }
|
||||
simdjson_really_inline uint64_t op() const { return _op; }
|
||||
simdjson_really_inline uint64_t scalar() { return ~(op() | whitespace()); }
|
||||
simdjson_really_inline uint64_t whitespace() const noexcept { return _whitespace; }
|
||||
simdjson_really_inline uint64_t op() const noexcept { return _op; }
|
||||
simdjson_really_inline uint64_t scalar() const noexcept { return ~(op() | whitespace()); }
|
||||
|
||||
uint64_t _whitespace;
|
||||
uint64_t _op;
|
||||
|
|
Loading…
Reference in New Issue