diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index a90a4a05..0cd9ee7c 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -178,9 +178,9 @@ #ifndef RAPIDJSON_FORCEINLINE //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN -#if defined(_MSC_VER) && !defined(NDEBUG) +#if defined(_MSC_VER) && defined(NDEBUG) #define RAPIDJSON_FORCEINLINE __forceinline -#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG) +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) #define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) #else #define RAPIDJSON_FORCEINLINE diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 9ffc68f2..924e595f 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -800,11 +800,12 @@ private: // Do nothing for generic version } -#if 0 //defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { const char* p = is.src_; // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* start = p; const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); while (p != nextAligned) if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(*p < 0x20)) { @@ -817,16 +818,17 @@ private: // The rest of string using SIMD static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; - static const char space[16] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); for (;; p += 16) { const __m128i s = _mm_load_si128(reinterpret_cast(p)); - __m128i x = _mm_cmpeq_epi8(s, dq); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, bs)); - x = _mm_or_si128(x, _mm_cmplt_epi8(s, sp)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); unsigned short r = static_cast(_mm_movemask_epi8(x)); if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped size_t length; @@ -837,7 +839,10 @@ private: #else length = static_cast(__builtin_ffs(r) - 1); #endif - memcpy(os.Push(length), p, length); + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + p += length; break; } diff --git a/test/perftest/rapidjsontest.cpp b/test/perftest/rapidjsontest.cpp index 46937559..ad9bba32 100644 --- a/test/perftest/rapidjsontest.cpp +++ b/test/perftest/rapidjsontest.cpp @@ -24,14 +24,6 @@ #include "rapidjson/encodedstream.h" #include "rapidjson/memorystream.h" -#ifdef RAPIDJSON_SSE2 -#define SIMD_SUFFIX(name) name##_SSE2 -#elif defined(RAPIDJSON_SSE42) -#define SIMD_SUFFIX(name) name##_SSE42 -#else -#define SIMD_SUFFIX(name) name -#endif - using namespace rapidjson; class RapidJson : public PerfTest { diff --git a/test/unittest/simdtest.cpp b/test/unittest/simdtest.cpp index 4407c25c..963409ea 100644 --- a/test/unittest/simdtest.cpp +++ b/test/unittest/simdtest.cpp @@ -66,3 +66,30 @@ TEST(SIMD, SIMD_SUFFIX(SkipWhitespace)) { TestSkipWhitespace(); TestSkipWhitespace(); } + +template +struct ParseStringHandler : BaseReaderHandler > { + ParseStringHandler() : str_(0), length_(0), copy_() {} + ~ParseStringHandler() { EXPECT_TRUE(str_ != 0); if (copy_) free(const_cast(str_)); } + + ParseStringHandler(const ParseStringHandler&); + ParseStringHandler& operator=(const ParseStringHandler&); + + bool Default() { ADD_FAILURE(); return false; } + bool String(const typename Encoding::Ch* str, size_t length, bool copy) { + EXPECT_EQ(0, str_); + if (copy) { + str_ = static_cast(malloc((length + 1) * sizeof(typename Encoding::Ch))); + memcpy(const_cast(str_), str, (length + 1) * sizeof(typename Encoding::Ch)); + } + else + str_ = str; + length_ = length; + copy_ = copy; + return true; + } + + const typename Encoding::Ch* str_; + size_t length_; + bool copy_; +};