Ensuring that stage 1's json_block and cie are never copied and using explicit constructors (issue 1475) (#1478)

This commit is contained in:
Daniel Lemire 2021-03-04 07:59:36 -05:00 committed by GitHub
parent 79e94227c2
commit dc2f767171
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 77 additions and 47 deletions

View File

@ -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

View File

@ -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

View File

@ -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} {}

View File

@ -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} {}

View File

@ -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,

View File

@ -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} {}

View File

@ -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;

View File

@ -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);

View File

@ -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() {

View File

@ -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() {

View File

@ -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

View File

@ -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',' ').

View File

@ -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;

View File

@ -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;