diff options
author | battre <battre@chromium.org> | 2015-12-16 19:59:03 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-17 03:59:56 +0000 |
commit | 2bf80eeab7c142f91d45b46504b4485934e29512 (patch) | |
tree | 5d5168986b00288571236f08b10fbd89df7ace32 /third_party/re2/util | |
parent | 0b9dbdd4cb09836efadb090edf7d981fb438cf50 (diff) | |
download | chromium_src-2bf80eeab7c142f91d45b46504b4485934e29512.zip chromium_src-2bf80eeab7c142f91d45b46504b4485934e29512.tar.gz chromium_src-2bf80eeab7c142f91d45b46504b4485934e29512.tar.bz2 |
Update re2 to tip of tree.
This version does not require any Chrome specific patches anymore.
This is an update of https://crrev.com/fd270ec705a75fd4e0883d091d9cf5204918c858
BUG=568119
R=thakis@chromium.org,tfarina@chromium.org
Review URL: https://codereview.chromium.org/1529143002
Cr-Commit-Position: refs/heads/master@{#365736}
Diffstat (limited to 'third_party/re2/util')
25 files changed, 439 insertions, 714 deletions
diff --git a/third_party/re2/util/arena.cc b/third_party/re2/util/arena.cc deleted file mode 100644 index 25753c5..0000000 --- a/third_party/re2/util/arena.cc +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2000 The RE2 Authors. All Rights Reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "util/util.h" - -namespace re2 { - -// ---------------------------------------------------------------------- -// UnsafeArena::UnsafeArena() -// UnsafeArena::~UnsafeArena() -// Destroying the arena automatically calls Reset() -// ---------------------------------------------------------------------- - - -UnsafeArena::UnsafeArena(const size_t block_size) - : block_size_(block_size), - freestart_(NULL), // set for real in Reset() - last_alloc_(NULL), - remaining_(0), - blocks_alloced_(1), - overflow_blocks_(NULL) { - assert(block_size > kDefaultAlignment); - - first_blocks_[0].mem = reinterpret_cast<char*>(malloc(block_size_)); - first_blocks_[0].size = block_size_; - - Reset(); -} - -UnsafeArena::~UnsafeArena() { - FreeBlocks(); - assert(overflow_blocks_ == NULL); // FreeBlocks() should do that - // The first X blocks stay allocated always by default. Delete them now. - for (int i = 0; i < blocks_alloced_; i++) - free(first_blocks_[i].mem); -} - -// ---------------------------------------------------------------------- -// UnsafeArena::Reset() -// Clears all the memory an arena is using. -// ---------------------------------------------------------------------- - -void UnsafeArena::Reset() { - FreeBlocks(); - freestart_ = first_blocks_[0].mem; - remaining_ = first_blocks_[0].size; - last_alloc_ = NULL; - - // We do not know for sure whether or not the first block is aligned, - // so we fix that right now. - const int overage = reinterpret_cast<uintptr_t>(freestart_) & - (kDefaultAlignment-1); - if (overage > 0) { - const int waste = kDefaultAlignment - overage; - freestart_ += waste; - remaining_ -= waste; - } - freestart_when_empty_ = freestart_; - assert(!(reinterpret_cast<uintptr_t>(freestart_)&(kDefaultAlignment-1))); -} - -// ------------------------------------------------------------- -// UnsafeArena::AllocNewBlock() -// Adds and returns an AllocatedBlock. -// The returned AllocatedBlock* is valid until the next call -// to AllocNewBlock or Reset. (i.e. anything that might -// affect overflow_blocks_). -// ------------------------------------------------------------- - -UnsafeArena::AllocatedBlock* UnsafeArena::AllocNewBlock(const size_t block_size) { - AllocatedBlock *block; - // Find the next block. - if ( blocks_alloced_ < arraysize(first_blocks_) ) { - // Use one of the pre-allocated blocks - block = &first_blocks_[blocks_alloced_++]; - } else { // oops, out of space, move to the vector - if (overflow_blocks_ == NULL) overflow_blocks_ = new vector<AllocatedBlock>; - // Adds another block to the vector. - overflow_blocks_->resize(overflow_blocks_->size()+1); - // block points to the last block of the vector. - block = &overflow_blocks_->back(); - } - - block->mem = reinterpret_cast<char*>(malloc(block_size)); - block->size = block_size; - - return block; -} - -// ---------------------------------------------------------------------- -// UnsafeArena::GetMemoryFallback() -// We take memory out of our pool, aligned on the byte boundary -// requested. If we don't have space in our current pool, we -// allocate a new block (wasting the remaining space in the -// current block) and give you that. If your memory needs are -// too big for a single block, we make a special your-memory-only -// allocation -- this is equivalent to not using the arena at all. -// ---------------------------------------------------------------------- - -void* UnsafeArena::GetMemoryFallback(const size_t size, const int align) { - if (size == 0) - return NULL; // stl/stl_alloc.h says this is okay - - assert(align > 0 && 0 == (align & (align - 1))); // must be power of 2 - - // If the object is more than a quarter of the block size, allocate - // it separately to avoid wasting too much space in leftover bytes - if (block_size_ == 0 || size > block_size_/4) { - // then it gets its own block in the arena - assert(align <= kDefaultAlignment); // because that's what new gives us - // This block stays separate from the rest of the world; in particular - // we don't update last_alloc_ so you can't reclaim space on this block. - return AllocNewBlock(size)->mem; - } - - const int overage = - (reinterpret_cast<uintptr_t>(freestart_) & (align-1)); - if (overage) { - const int waste = align - overage; - freestart_ += waste; - if (waste < remaining_) { - remaining_ -= waste; - } else { - remaining_ = 0; - } - } - if (size > remaining_) { - AllocatedBlock *block = AllocNewBlock(block_size_); - freestart_ = block->mem; - remaining_ = block->size; - } - remaining_ -= size; - last_alloc_ = freestart_; - freestart_ += size; - assert((reinterpret_cast<uintptr_t>(last_alloc_) & (align-1)) == 0); - return reinterpret_cast<void*>(last_alloc_); -} - -// ---------------------------------------------------------------------- -// UnsafeArena::FreeBlocks() -// Unlike GetMemory(), which does actual work, ReturnMemory() is a -// no-op: we don't "free" memory until Reset() is called. We do -// update some stats, though. Note we do no checking that the -// pointer you pass in was actually allocated by us, or that it -// was allocated for the size you say, so be careful here! -// FreeBlocks() does the work for Reset(), actually freeing all -// memory allocated in one fell swoop. -// ---------------------------------------------------------------------- - -void UnsafeArena::FreeBlocks() { - for ( int i = 1; i < blocks_alloced_; ++i ) { // keep first block alloced - free(first_blocks_[i].mem); - first_blocks_[i].mem = NULL; - first_blocks_[i].size = 0; - } - blocks_alloced_ = 1; - if (overflow_blocks_ != NULL) { - vector<AllocatedBlock>::iterator it; - for (it = overflow_blocks_->begin(); it != overflow_blocks_->end(); ++it) { - free(it->mem); - } - delete overflow_blocks_; // These should be used very rarely - overflow_blocks_ = NULL; - } -} - -} // namespace re2 diff --git a/third_party/re2/util/arena.h b/third_party/re2/util/arena.h deleted file mode 100644 index 7eb385b..0000000 --- a/third_party/re2/util/arena.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2000 The RE2 Authors. All Rights Reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Sometimes it is necessary to allocate a large number of small -// objects. Doing this the usual way (malloc, new) is slow, -// especially for multithreaded programs. An UnsafeArena provides a -// mark/release method of memory management: it asks for a large chunk -// from the operating system and doles it out bit by bit as required. -// Then you free all the memory at once by calling UnsafeArena::Reset(). -// The "Unsafe" refers to the fact that UnsafeArena is not safe to -// call from multiple threads. -// -// The global operator new that can be used as follows: -// -// #include "lib/arena-inl.h" -// -// UnsafeArena arena(1000); -// Foo* foo = new (AllocateInArena, &arena) Foo; -// - -#ifndef RE2_UTIL_ARENA_H_ -#define RE2_UTIL_ARENA_H_ - -namespace re2 { - -// This class is thread-compatible. -class UnsafeArena { - public: - UnsafeArena(const size_t block_size); - virtual ~UnsafeArena(); - - void Reset(); - - // This should be the worst-case alignment for any type. This is - // good for IA-32, SPARC version 7 (the last one I know), and - // supposedly Alpha. i386 would be more time-efficient with a - // default alignment of 8, but ::operator new() uses alignment of 4, - // and an assertion will fail below after the call to MakeNewBlock() - // if you try to use a larger alignment. -#ifdef __i386__ - static const int kDefaultAlignment = 4; -#else - static const int kDefaultAlignment = 8; -#endif - - private: - void* GetMemoryFallback(const size_t size, const int align); - - public: - void* GetMemory(const size_t size, const int align) { - if ( size > 0 && size < remaining_ && align == 1 ) { // common case - last_alloc_ = freestart_; - freestart_ += size; - remaining_ -= size; - return reinterpret_cast<void*>(last_alloc_); - } - return GetMemoryFallback(size, align); - } - - private: - struct AllocatedBlock { - char *mem; - size_t size; - }; - - // The returned AllocatedBlock* is valid until the next call to AllocNewBlock - // or Reset (i.e. anything that might affect overflow_blocks_). - AllocatedBlock *AllocNewBlock(const size_t block_size); - - const AllocatedBlock *IndexToBlock(int index) const; - - const size_t block_size_; - char* freestart_; // beginning of the free space in most recent block - char* freestart_when_empty_; // beginning of the free space when we're empty - char* last_alloc_; // used to make sure ReturnBytes() is safe - size_t remaining_; - // STL vector isn't as efficient as it could be, so we use an array at first - int blocks_alloced_; // how many of the first_blocks_ have been alloced - AllocatedBlock first_blocks_[16]; // the length of this array is arbitrary - // if the first_blocks_ aren't enough, expand into overflow_blocks_. - vector<AllocatedBlock>* overflow_blocks_; - - void FreeBlocks(); // Frees all except first block - - DISALLOW_EVIL_CONSTRUCTORS(UnsafeArena); -}; - -// Operators for allocation on the arena -// Syntax: new (AllocateInArena, arena) MyClass; -// STL containers, etc. -enum AllocateInArenaType { AllocateInArena }; - -} // namespace re2 - -inline void* operator new(size_t size, - re2::AllocateInArenaType /* unused */, - re2::UnsafeArena *arena) { - return reinterpret_cast<char*>(arena->GetMemory(size, 1)); -} - -#endif // RE2_UTIL_ARENA_H_ - diff --git a/third_party/re2/util/atomicops.h b/third_party/re2/util/atomicops.h index 11c1196..dc944e7 100644 --- a/third_party/re2/util/atomicops.h +++ b/third_party/re2/util/atomicops.h @@ -5,6 +5,35 @@ #ifndef RE2_UTIL_ATOMICOPS_H__ #define RE2_UTIL_ATOMICOPS_H__ +// The memory ordering constraints resemble the ones in C11. +// RELAXED - no memory ordering, just an atomic operation. +// CONSUME - data-dependent ordering. +// ACQUIRE - prevents memory accesses from hoisting above the operation. +// RELEASE - prevents memory accesses from sinking below the operation. + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#if !defined(OS_NACL) && (__has_builtin(__atomic_load_n) || (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ >= 40801)) + +#define ATOMIC_LOAD_RELAXED(x, p) do { (x) = __atomic_load_n((p), __ATOMIC_RELAXED); } while (0) +#define ATOMIC_LOAD_CONSUME(x, p) do { (x) = __atomic_load_n((p), __ATOMIC_CONSUME); } while (0) +#define ATOMIC_LOAD_ACQUIRE(x, p) do { (x) = __atomic_load_n((p), __ATOMIC_ACQUIRE); } while (0) +#define ATOMIC_STORE_RELAXED(p, v) __atomic_store_n((p), (v), __ATOMIC_RELAXED) +#define ATOMIC_STORE_RELEASE(p, v) __atomic_store_n((p), (v), __ATOMIC_RELEASE) + +#else // old compiler + +#define ATOMIC_LOAD_RELAXED(x, p) do { (x) = *(p); } while (0) +#define ATOMIC_LOAD_CONSUME(x, p) do { (x) = *(p); MaybeReadMemoryBarrier(); } while (0) +#define ATOMIC_LOAD_ACQUIRE(x, p) do { (x) = *(p); ReadMemoryBarrier(); } while (0) +#define ATOMIC_STORE_RELAXED(p, v) do { *(p) = (v); } while (0) +#define ATOMIC_STORE_RELEASE(p, v) do { WriteMemoryBarrier(); *(p) = (v); } while (0) + +// WriteMemoryBarrier(), ReadMemoryBarrier() and MaybeReadMemoryBarrier() +// are an implementation detail and must not be used in the rest of the code. + #if defined(__i386__) static inline void WriteMemoryBarrier() { @@ -21,10 +50,16 @@ static inline void WriteMemoryBarrier() { __asm__ __volatile__("sfence" : : : "memory"); } -#elif defined(__ppc__) +#elif defined(__ppc__) || defined(__powerpc64__) static inline void WriteMemoryBarrier() { - __asm__ __volatile__("eieio" : : : "memory"); + __asm__ __volatile__("lwsync" : : : "memory"); +} + +#elif defined(__aarch64__) + +static inline void WriteMemoryBarrier() { + __asm__ __volatile__("dmb st" : : : "memory"); } #elif defined(__alpha__) @@ -33,6 +68,43 @@ static inline void WriteMemoryBarrier() { __asm__ __volatile__("wmb" : : : "memory"); } +#elif defined(__arm__) && defined(__linux__) + +// Linux on ARM puts a suitable memory barrier at a magic address for us to call. +static inline void WriteMemoryBarrier() { + ((void(*)(void))0xffff0fa0)(); +} + +#elif defined(__windows__) || defined(_WIN32) + +#include <intrin.h> +#include <windows.h> + +static inline void WriteMemoryBarrier() { +#if defined(_M_IX86) || defined(_M_X64) + // x86 and x64 CPUs have a strong memory model that prohibits most types of + // reordering, so a non-instruction intrinsic to suppress compiler reordering + // is sufficient. _WriteBarrier is deprecated, but is still appropriate for + // the "old compiler" path (pre C++11). + _WriteBarrier(); +#else + LONG x; + ::InterlockedExchange(&x, 0); +#endif +} + +#elif defined(OS_NACL) + +static inline void WriteMemoryBarrier() { + __sync_synchronize(); +} + +#elif defined(__mips__) + +static inline void WriteMemoryBarrier() { + __asm__ __volatile__("sync" : : : "memory"); +} + #else #include "util/mutex.h" @@ -50,19 +122,9 @@ static inline void WriteMemoryBarrier() { re2::MutexLock l(&mu); } -/* -#error Need WriteMemoryBarrier for architecture. - -// Windows -inline void WriteMemoryBarrier() { - LONG x; - ::InterlockedExchange(&x, 0); -} -*/ - #endif -// Alpha has very weak memory ordering. If relying on WriteBarriers, must one +// Alpha has very weak memory ordering. If relying on WriteBarriers, one must // use read barriers for the readers too. #if defined(__alpha__) @@ -74,6 +136,44 @@ static inline void MaybeReadMemoryBarrier() { static inline void MaybeReadMemoryBarrier() {} -#endif // __alpha__ +#endif // __alpha__ + +// Read barrier for various targets. + +#if defined(__ppc__) || defined(__powerpc64__) + +static inline void ReadMemoryBarrier() { + __asm__ __volatile__("lwsync" : : : "memory"); +} + +#elif defined(__aarch64__) + +static inline void ReadMemoryBarrier() { + __asm__ __volatile__("dmb ld" : : : "memory"); +} + +#elif defined(__alpha__) + +static inline void ReadMemoryBarrier() { + __asm__ __volatile__("mb" : : : "memory"); +} + +#elif defined(__mips__) + +static inline void ReadMemoryBarrier() { + __asm__ __volatile__("sync" : : : "memory"); +} + +#else + +static inline void ReadMemoryBarrier() {} + +#endif + +#endif // old compiler + +#ifndef NO_THREAD_SAFETY_ANALYSIS +#define NO_THREAD_SAFETY_ANALYSIS +#endif #endif // RE2_UTIL_ATOMICOPS_H__ diff --git a/third_party/re2/util/benchmark.cc b/third_party/re2/util/benchmark.cc index c3aad7e..b77e22d 100644 --- a/third_party/re2/util/benchmark.cc +++ b/third_party/re2/util/benchmark.cc @@ -25,10 +25,29 @@ void Benchmark::Register() { } static int64 nsec() { +#if defined(__APPLE__) struct timeval tv; if(gettimeofday(&tv, 0) < 0) return -1; return (int64)tv.tv_sec*1000*1000*1000 + tv.tv_usec*1000; +#elif defined(_WIN32) + // https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408.aspx + // describes how to query ticks and convert to microseconds. Of course, + // what we want in this case are nanoseconds. Also, note that .QuadPart + // is a signed 64-bit integer, so casting to int64 shouldn't be needed. + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + LARGE_INTEGER ticks; + QueryPerformanceCounter(&ticks); + ticks.QuadPart *= 1000*1000*1000; + ticks.QuadPart /= freq.QuadPart; + return ticks.QuadPart; +#else + struct timespec tp; + if(clock_gettime(CLOCK_REALTIME, &tp) < 0) + return -1; + return (int64)tp.tv_sec*1000*1000*1000 + tp.tv_nsec; +#endif } static int64 bytes; @@ -105,9 +124,9 @@ void RunBench(Benchmark* b, int nthread, int siz) { while(ns < (int)1e9 && n < (int)1e9) { last = n; if(ns/n == 0) - n = 1e9; + n = (int)1e9; else - n = 1e9 / (ns/n); + n = (int)1e9 / static_cast<int>(ns/n); n = max(last+1, min(n+n/2, 100*last)); n = round(n); diff --git a/third_party/re2/util/flags.h b/third_party/re2/util/flags.h index 77a06a22..98d5c06 100644 --- a/third_party/re2/util/flags.h +++ b/third_party/re2/util/flags.h @@ -5,7 +5,7 @@ // Simplified version of Google's command line flags. // Does not support parsing the command line. // If you want to do that, see -// http://code.google.com/p/google-gflags +// https://gflags.github.io/gflags/ #ifndef RE2_UTIL_FLAGS_H__ #define RE2_UTIL_FLAGS_H__ diff --git a/third_party/re2/util/logging.cc b/third_party/re2/util/logging.cc new file mode 100644 index 0000000..8a59862 --- /dev/null +++ b/third_party/re2/util/logging.cc @@ -0,0 +1,9 @@ +// Copyright 2015 The RE2 Authors. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "util/logging.h" + +DEFINE_int32(minloglevel, 0, // INFO + "Messages logged at a lower level than this don't actually get " + "logged anywhere"); diff --git a/third_party/re2/util/logging.h b/third_party/re2/util/logging.h index d0a2d87..feac199 100644 --- a/third_party/re2/util/logging.h +++ b/third_party/re2/util/logging.h @@ -7,13 +7,13 @@ #ifndef RE2_UTIL_LOGGING_H__ #define RE2_UTIL_LOGGING_H__ -#ifndef WIN32 -#include <unistd.h> /* for write */ -#endif +#include <stdio.h> /* for fwrite */ #include <sstream> -#ifdef WIN32 -#include <io.h> -#endif + +#include "util/util.h" +#include "util/flags.h" + +DECLARE_int32(minloglevel); // Debug-only checking. #define DCHECK(condition) assert(condition) @@ -33,13 +33,16 @@ #define CHECK_EQ(x, y) CHECK((x) == (y)) #define CHECK_NE(x, y) CHECK((x) != (y)) -#define LOG_INFO LogMessage(__FILE__, __LINE__) -#define LOG_ERROR LOG_INFO -#define LOG_WARNING LOG_INFO +#define LOG_INFO LogMessage(__FILE__, __LINE__, 0) +#define LOG_WARNING LogMessage(__FILE__, __LINE__, 1) +#define LOG_ERROR LogMessage(__FILE__, __LINE__, 2) #define LOG_FATAL LogMessageFatal(__FILE__, __LINE__) #define LOG_QFATAL LOG_FATAL -#define VLOG(x) if((x)>0){}else LOG_INFO.stream() +// It seems that one of the Windows header files defines ERROR as 0. +#ifdef _WIN32 +#define LOG_0 LOG_INFO +#endif #ifdef NDEBUG #define DEBUG_MODE 0 @@ -51,16 +54,21 @@ #define LOG(severity) LOG_ ## severity.stream() +#define VLOG(x) if((x)>0){}else LOG_INFO.stream() + class LogMessage { public: - LogMessage(const char* file, int line) : flushed_(false) { + LogMessage(const char* file, int line, int severity) + : severity_(severity), flushed_(false) { stream() << file << ":" << line << ": "; } void Flush() { stream() << "\n"; - string s = str_.str(); - int n = (int)s.size(); // shut up msvc - if(write(2, s.data(), n) < 0) {} // shut up gcc + if (severity_ >= re2::FLAGS_minloglevel) { + string s = str_.str(); + size_t n = s.size(); + if (fwrite(s.data(), 1, n, stderr) < n) {} // shut up gcc + } flushed_ = true; } ~LogMessage() { @@ -69,23 +77,33 @@ class LogMessage { } } ostream& stream() { return str_; } - + private: + const int severity_; bool flushed_; std::ostringstream str_; - DISALLOW_EVIL_CONSTRUCTORS(LogMessage); + DISALLOW_COPY_AND_ASSIGN(LogMessage); }; +#ifdef _WIN32 +#pragma warning(push) +#pragma warning(disable: 4722) // destructor never returns +#endif + class LogMessageFatal : public LogMessage { public: LogMessageFatal(const char* file, int line) - : LogMessage(file, line) { } + : LogMessage(file, line, 3) {} ~LogMessageFatal() { Flush(); abort(); } private: - DISALLOW_EVIL_CONSTRUCTORS(LogMessageFatal); + DISALLOW_COPY_AND_ASSIGN(LogMessageFatal); }; +#ifdef _WIN32 +#pragma warning(pop) +#endif + #endif // RE2_UTIL_LOGGING_H__ diff --git a/third_party/re2/util/mutex.h b/third_party/re2/util/mutex.h index e321fae..b479e48 100644 --- a/third_party/re2/util/mutex.h +++ b/third_party/re2/util/mutex.h @@ -10,19 +10,40 @@ #ifndef RE2_UTIL_MUTEX_H_ #define RE2_UTIL_MUTEX_H_ +#include <stdlib.h> + +#if !defined(_WIN32) +#include <unistd.h> // For POSIX options +#endif + namespace re2 { -#ifndef WIN32 -#define HAVE_PTHREAD 1 -#define HAVE_RWLOCK 1 +#if !defined(_WIN32) + // Possible values of POSIX options: + // -1 means not supported, + // 0 means maybe supported (query at runtime), + // >0 means supported. +# if defined(_POSIX_THREADS) && _POSIX_THREADS > 0 +# define HAVE_PTHREAD 1 +# else +# define HAVE_PTHREAD 0 +# endif +# if defined(_POSIX_READER_WRITER_LOCKS) && _POSIX_READER_WRITER_LOCKS > 0 +# define HAVE_RWLOCK 1 +# else +# define HAVE_RWLOCK 0 +# endif +#else +# define HAVE_PTHREAD 0 +# define HAVE_RWLOCK 0 #endif #if defined(NO_THREADS) typedef int MutexType; // to keep a lock-count -#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) +#elif HAVE_PTHREAD && HAVE_RWLOCK // Needed for pthread_rwlock_*. If it causes problems, you could take it - // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it - // *does* cause problems for FreeBSD, or MacOSX, but isn't needed + // out, but then you'd have to set HAVE_RWLOCK to 0 (at least on linux -- + // it *does* cause problems for FreeBSD, or MacOSX, but isn't needed // for locking there.) # ifdef __linux__ # undef _XOPEN_SOURCE @@ -30,12 +51,12 @@ namespace re2 { # endif # include <pthread.h> typedef pthread_rwlock_t MutexType; -#elif defined(HAVE_PTHREAD) +#elif HAVE_PTHREAD # include <pthread.h> typedef pthread_mutex_t MutexType; -#elif defined(WIN32) +#elif defined(_WIN32) # ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN // We only need minimal includes +# define WIN32_LEAN_AND_MEAN // We only need minimal includes # endif # ifdef GMUTEX_TRYLOCK // We need Windows NT or later for TryEnterCriticalSection(). If you @@ -104,9 +125,8 @@ bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } void Mutex::ReaderLock() { assert(++mutex_ > 0); } void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } -#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) +#elif HAVE_PTHREAD && HAVE_RWLOCK -#include <stdlib.h> // for abort() #define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0) Mutex::Mutex() { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); } @@ -119,9 +139,8 @@ void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); } #undef SAFE_PTHREAD -#elif defined(HAVE_PTHREAD) +#elif HAVE_PTHREAD -#include <stdlib.h> // for abort() #define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0) Mutex::Mutex() { SAFE_PTHREAD(pthread_mutex_init(&mutex_, NULL)); } @@ -133,7 +152,7 @@ void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks void Mutex::ReaderUnlock() { Unlock(); } #undef SAFE_PTHREAD -#elif defined(WIN32) +#elif defined(_WIN32) Mutex::Mutex() { InitializeCriticalSection(&mutex_); } Mutex::~Mutex() { DeleteCriticalSection(&mutex_); } @@ -190,7 +209,7 @@ class WriterMutexLock { #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) // Provide safe way to declare and use global, linker-initialized mutex. Sigh. -#ifdef HAVE_PTHREAD +#if HAVE_PTHREAD #define GLOBAL_MUTEX(name) \ static pthread_mutex_t (name) = PTHREAD_MUTEX_INITIALIZER diff --git a/third_party/re2/util/pcre.cc b/third_party/re2/util/pcre.cc index 1602133..9a3f32d 100644 --- a/third_party/re2/util/pcre.cc +++ b/third_party/re2/util/pcre.cc @@ -7,15 +7,11 @@ // compilation as PCRE in namespace re2. #include <errno.h> +#include <limits> #include "util/util.h" #include "util/flags.h" #include "util/pcre.h" -#ifdef WIN32 -#define strtoll _strtoi64 -#define strtoull _strtoui64 -#endif - #define PCREPORT(level) LOG(level) // Default PCRE limits. @@ -27,6 +23,42 @@ DEFINE_int32(regexp_stack_limit, 256<<10, "default PCRE stack limit (bytes)"); DEFINE_int32(regexp_match_limit, 1000000, "default PCRE match limit (function calls)"); +#ifndef USEPCRE + +// Fake just enough of the PCRE API to allow this file to build. :) + +struct pcre_extra { + int flags; + int match_limit; + int match_limit_recursion; +}; + +#define PCRE_EXTRA_MATCH_LIMIT 0 +#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0 +#define PCRE_ANCHORED 0 +#define PCRE_NOTEMPTY 0 +#define PCRE_ERROR_NOMATCH 1 +#define PCRE_ERROR_MATCHLIMIT 2 +#define PCRE_ERROR_RECURSIONLIMIT 3 +#define PCRE_INFO_CAPTURECOUNT 0 + +void pcre_free(void*) { +} + +pcre* pcre_compile(const char*, int, const char**, int*, const unsigned char*) { + return NULL; +} + +int pcre_exec(const pcre*, const pcre_extra*, const char*, int, int, int, int*, int) { + return 0; +} + +int pcre_fullinfo(const pcre*, const pcre_extra*, int, void*) { + return 0; +} + +#endif + namespace re2 { // Maximum number of args we can set @@ -118,7 +150,7 @@ pcre* PCRE::Compile(Anchor anchor) { // ANCHOR_BOTH Tack a "\z" to the end of the original pattern // and use a pcre anchored match. - const char* error; + const char* error = ""; int eoffset; pcre* re; if (anchor != ANCHOR_BOTH) { @@ -183,7 +215,7 @@ bool PCRE::FullMatchFunctor::operator ()(const StringPiece& text, done: int consumed; - int vec[kVecSize]; + int vec[kVecSize] = {}; return re.DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize); } @@ -226,7 +258,7 @@ bool PCRE::PartialMatchFunctor::operator ()(const StringPiece& text, done: int consumed; - int vec[kVecSize]; + int vec[kVecSize] = {}; return re.DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize); } @@ -269,7 +301,7 @@ bool PCRE::ConsumeFunctor::operator ()(StringPiece* input, done: int consumed; - int vec[kVecSize]; + int vec[kVecSize] = {}; if (pattern.DoMatchImpl(*input, ANCHOR_START, &consumed, args, n, vec, kVecSize)) { input->remove_prefix(consumed); @@ -318,7 +350,7 @@ bool PCRE::FindAndConsumeFunctor::operator ()(StringPiece* input, done: int consumed; - int vec[kVecSize]; + int vec[kVecSize] = {}; if (pattern.DoMatchImpl(*input, UNANCHORED, &consumed, args, n, vec, kVecSize)) { input->remove_prefix(consumed); @@ -331,7 +363,7 @@ done: bool PCRE::Replace(string *str, const PCRE& pattern, const StringPiece& rewrite) { - int vec[kVecSize]; + int vec[kVecSize] = {}; int matches = pattern.TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize); if (matches == 0) return false; @@ -350,12 +382,12 @@ int PCRE::GlobalReplace(string *str, const PCRE& pattern, const StringPiece& rewrite) { int count = 0; - int vec[kVecSize]; + int vec[kVecSize] = {}; string out; int start = 0; bool last_match_was_empty_string = false; - for (; start <= str->length();) { + while (start <= static_cast<int>(str->size())) { // If the previous match was for the empty string, we shouldn't // just match again: we'll match in the same way and get an // infinite loop. Instead, we do the match in a special way: @@ -371,14 +403,15 @@ int PCRE::GlobalReplace(string *str, matches = pattern.TryMatch(*str, start, ANCHOR_START, false, vec, kVecSize); if (matches <= 0) { - if (start < str->length()) + if (start < static_cast<int>(str->size())) out.push_back((*str)[start]); start++; last_match_was_empty_string = false; continue; } } else { - matches = pattern.TryMatch(*str, start, UNANCHORED, true, vec, kVecSize); + matches = pattern.TryMatch(*str, start, UNANCHORED, true, + vec, kVecSize); if (matches <= 0) break; } @@ -396,8 +429,8 @@ int PCRE::GlobalReplace(string *str, if (count == 0) return 0; - if (start < str->length()) - out.append(*str, start, str->length() - start); + if (start < static_cast<int>(str->size())) + out.append(*str, start, static_cast<int>(str->size()) - start); swap(out, *str); return count; } @@ -406,7 +439,7 @@ bool PCRE::Extract(const StringPiece &text, const PCRE& pattern, const StringPiece &rewrite, string *out) { - int vec[kVecSize]; + int vec[kVecSize] = {}; int matches = pattern.TryMatch(text, 0, UNANCHORED, true, vec, kVecSize); if (matches == 0) return false; @@ -452,7 +485,7 @@ string PCRE::QuoteMeta(const StringPiece& unquoted) { /***** Actual matching and rewriting code *****/ bool PCRE::HitLimit() { - return hit_limit_; + return hit_limit_ != 0; } void PCRE::ClearHitLimit() { @@ -600,9 +633,9 @@ bool PCRE::DoMatch(const StringPiece& text, const Arg* const args[], int n) const { assert(n >= 0); - size_t const vecsize = (1 + n) * 3; // results + PCRE workspace - // (as for kVecSize) - int *vec = new int[vecsize]; + const int vecsize = (1 + n) * 3; // results + PCRE workspace + // (as for kVecSize) + int* vec = new int[vecsize]; bool b = DoMatchImpl(text, anchor, consumed, args, n, vec, vecsize); delete[] vec; return b; @@ -808,7 +841,7 @@ bool PCRE::Arg::parse_short_radix(const char* str, if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse if ((short)r != r) return false; // Out of range if (dest == NULL) return true; - *(reinterpret_cast<short*>(dest)) = r; + *(reinterpret_cast<short*>(dest)) = (short)r; return true; } @@ -820,7 +853,7 @@ bool PCRE::Arg::parse_ushort_radix(const char* str, if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse if ((ushort)r != r) return false; // Out of range if (dest == NULL) return true; - *(reinterpret_cast<unsigned short*>(dest)) = r; + *(reinterpret_cast<unsigned short*>(dest)) = (ushort)r; return true; } @@ -898,7 +931,7 @@ bool PCRE::Arg::parse_double(const char* str, int n, void* dest) { char* end; double r = strtod(buf, &end); if (end != buf + n) { -#ifdef COMPILER_MSVC +#ifdef _WIN32 // Microsoft's strtod() doesn't handle inf and nan, so we have to // handle it explicitly. Speed is not important here because this // code is only called in unit tests. @@ -911,11 +944,11 @@ bool PCRE::Arg::parse_double(const char* str, int n, void* dest) { ++i; } if (0 == stricmp(i, "inf") || 0 == stricmp(i, "infinity")) { - r = numeric_limits<double>::infinity(); + r = std::numeric_limits<double>::infinity(); if (!pos) r = -r; } else if (0 == stricmp(i, "nan")) { - r = numeric_limits<double>::quiet_NaN(); + r = std::numeric_limits<double>::quiet_NaN(); } else { return false; } diff --git a/third_party/re2/util/pcre.h b/third_party/re2/util/pcre.h index 771ac91..20b10c0 100644 --- a/third_party/re2/util/pcre.h +++ b/third_party/re2/util/pcre.h @@ -167,28 +167,9 @@ namespace re2 { const bool UsingPCRE = true; } // namespace re2 #else +struct pcre; // opaque namespace re2 { const bool UsingPCRE = false; -struct pcre; -struct pcre_extra { int flags, match_limit, match_limit_recursion; }; -#define pcre_free(x) {} -#define PCRE_EXTRA_MATCH_LIMIT 0 -#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0 -#define PCRE_ANCHORED 0 -#define PCRE_NOTEMPTY 0 -#define PCRE_ERROR_NOMATCH 1 -#define PCRE_ERROR_MATCHLIMIT 2 -#define PCRE_ERROR_RECURSIONLIMIT 3 -#define PCRE_INFO_CAPTURECOUNT 0 -#ifndef WIN32 -#define pcre_compile(a,b,c,d,e) ({ (void)(a); (void)(b); *(c)=""; *(d)=0; (void)(e); ((pcre*)0); }) -#define pcre_exec(a, b, c, d, e, f, g, h) ({ (void)(a); (void)(b); (void)(c); (void)(d); (void)(e); (void)(f); (void)(g); (void)(h); 0; }) -#define pcre_fullinfo(a, b, c, d) ({ (void)(a); (void)(b); (void)(c); *(d) = 0; 0; }) -#else -#define pcre_compile(a,b,c,d,e) NULL -#define pcre_exec(a, b, c, d, e, f, g, h) NULL -#define pcre_fullinfo(a, b, c, d) NULL -#endif } // namespace re2 #endif @@ -516,7 +497,7 @@ class PCRE { int match_limit_; // Limit on execution resources int stack_limit_; // Limit on stack resources (bytes) mutable int32_t hit_limit_; // Hit limit during execution (bool)? - DISALLOW_EVIL_CONSTRUCTORS(PCRE); + DISALLOW_COPY_AND_ASSIGN(PCRE); }; // PCRE_Options allow you to set the PCRE::Options, plus any pcre diff --git a/third_party/re2/util/rune.cc b/third_party/re2/util/rune.cc index 26442b0..e6231ce 100644 --- a/third_party/re2/util/rune.cc +++ b/third_party/re2/util/rune.cc @@ -133,7 +133,7 @@ runetochar(char *str, const Rune *rune) */ c = *rune; if(c <= Rune1) { - str[0] = c; + str[0] = static_cast<char>(c); return 1; } @@ -142,7 +142,7 @@ runetochar(char *str, const Rune *rune) * 0080-07FF => T2 Tx */ if(c <= Rune2) { - str[0] = T2 | (c >> 1*Bitx); + str[0] = T2 | static_cast<char>(c >> 1*Bitx); str[1] = Tx | (c & Maskx); return 2; } @@ -161,9 +161,9 @@ runetochar(char *str, const Rune *rune) * 0800-FFFF => T3 Tx Tx */ if (c <= Rune3) { - str[0] = T3 | (c >> 2*Bitx); + str[0] = T3 | static_cast<char>(c >> 2*Bitx); str[1] = Tx | ((c >> 1*Bitx) & Maskx); - str[2] = Tx | (c & Maskx); + str[2] = Tx | (c & Maskx); return 3; } @@ -171,7 +171,7 @@ runetochar(char *str, const Rune *rune) * four character sequence (21-bit value) * 10000-1FFFFF => T4 Tx Tx Tx */ - str[0] = T4 | (c >> 3*Bitx); + str[0] = T4 | static_cast<char>(c >> 3*Bitx); str[1] = Tx | ((c >> 2*Bitx) & Maskx); str[2] = Tx | ((c >> 1*Bitx) & Maskx); str[3] = Tx | (c & Maskx); diff --git a/third_party/re2/util/sparse_array.h b/third_party/re2/util/sparse_array.h index 7bc3a86..8f71fa0 100644 --- a/third_party/re2/util/sparse_array.h +++ b/third_party/re2/util/sparse_array.h @@ -220,19 +220,25 @@ class SparseArray { // and at the beginning and end of all public non-const member functions. inline void DebugCheckInvariants() const; + static bool InitMemory() { +#ifdef MEMORY_SANITIZER + return true; +#else + return RunningOnValgrind(); +#endif + } + int size_; int max_size_; int* sparse_to_dense_; vector<IndexValue> dense_; - bool valgrind_; - DISALLOW_EVIL_CONSTRUCTORS(SparseArray); + DISALLOW_COPY_AND_ASSIGN(SparseArray); }; template<typename Value> SparseArray<Value>::SparseArray() - : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(), - valgrind_(RunningOnValgrindOrMemorySanitizer()) {} + : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_() {} // IndexValue pairs: exposed in SparseArray::iterator. template<typename Value> @@ -275,14 +281,20 @@ void SparseArray<Value>::resize(int new_max_size) { memmove(a, sparse_to_dense_, max_size_*sizeof a[0]); delete[] sparse_to_dense_; } - // Don't need to zero the memory but appease Valgrind. - if (valgrind_) { - for (int i = max_size_; i < new_max_size; i++) - a[i] = 0xababababU; - } sparse_to_dense_ = a; dense_.resize(new_max_size); + + // These don't need to be initialized for correctness, + // but Valgrind will warn about use of uninitialized memory, + // so initialize the new memory when compiling debug binaries. + // Initialize it to garbage to detect bugs in the future. + if (InitMemory()) { + for (int i = max_size_; i < new_max_size; i++) { + sparse_to_dense_[i] = 0xababababU; + dense_[i].index_ = 0xababababU; + } + } } max_size_ = new_max_size; if (size_ > max_size_) @@ -295,7 +307,7 @@ template<typename Value> bool SparseArray<Value>::has_index(int i) const { DCHECK_GE(i, 0); DCHECK_LT(i, max_size_); - if (static_cast<uint>(i) >= max_size_) { + if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) { return false; } // Unsigned comparison avoids checking sparse_to_dense_[i] < 0. @@ -307,7 +319,7 @@ bool SparseArray<Value>::has_index(int i) const { template<typename Value> typename SparseArray<Value>::iterator SparseArray<Value>::set(int i, Value v) { DebugCheckInvariants(); - if (static_cast<uint>(i) >= max_size_) { + if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) { // Semantically, end() would be better here, but we already know // the user did something stupid, so begin() insulates them from // dereferencing an invalid pointer. @@ -369,7 +381,7 @@ template<typename Value> typename SparseArray<Value>::iterator SparseArray<Value>::set_new(int i, Value v) { DebugCheckInvariants(); - if (static_cast<uint>(i) >= max_size_) { + if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) { // Semantically, end() would be better here, but we already know // the user did something stupid, so begin() insulates them from // dereferencing an invalid pointer. @@ -419,10 +431,9 @@ void SparseArray<Value>::create_index(int i) { template<typename Value> SparseArray<Value>::SparseArray(int max_size) { max_size_ = max_size; sparse_to_dense_ = new int[max_size]; - valgrind_ = RunningOnValgrindOrMemorySanitizer(); dense_.resize(max_size); // Don't need to zero the new memory, but appease Valgrind. - if (valgrind_) { + if (InitMemory()) { for (int i = 0; i < max_size; i++) { sparse_to_dense_[i] = 0xababababU; dense_[i].index_ = 0xababababU; diff --git a/third_party/re2/util/sparse_array_test.cc b/third_party/re2/util/sparse_array_test.cc deleted file mode 100644 index bc7a19f8..0000000 --- a/third_party/re2/util/sparse_array_test.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2006 The RE2 Authors. All Rights Reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Simple tests that SparseArray behaves. - -#include "util/util.h" -#include "utest/utest.h" - -namespace re2 { - -static const string kNotFound = "NOT FOUND"; - -TEST(SparseArray, BasicOperations) { - static const int n = 50; - SparseArray<int> set(n); - - int order[n]; - int value[n]; - for (int i = 0; i < n; i++) - order[i] = i; - for (int i = 0; i < n; i++) - value[i] = rand()%1000 + 1; - for (int i = 1; i < n; i++) { - int j = rand()%i; - int t = order[i]; - order[i] = order[j]; - order[j] = t; - } - - for (int i = 0;; i++) { - for (int j = 0; j < i; j++) { - ASSERT_TRUE(set.has_index(order[j])); - ASSERT_EQ(value[order[j]], set.get(order[j], -1)); - } - if (i >= n) - break; - for (int j = i; j < n; j++) - ASSERT_FALSE(set.has_index(order[j])); - set.set(order[i], value[order[i]]); - } - - int nn = 0; - for (SparseArray<int>::iterator i = set.begin(); i != set.end(); ++i) { - ASSERT_EQ(order[nn++], i->index()); - ASSERT_EQ(value[i->index()], i->value()); - } - ASSERT_EQ(nn, n); - - set.clear(); - for (int i = 0; i < n; i++) - ASSERT_FALSE(set.has_index(i)); - - ASSERT_EQ(0, set.size()); - ASSERT_EQ(0, distance(set.begin(), set.end())); -} - -class SparseArrayStringTest : public testing::Test { - protected: - SparseArrayStringTest() - : str_map_(10) { - InsertOrUpdate(&str_map_, 1, "a"); - InsertOrUpdate(&str_map_, 5, "b"); - InsertOrUpdate(&str_map_, 2, "c"); - InsertOrUpdate(&str_map_, 7, "d"); - } - - SparseArray<string> str_map_; - typedef SparseArray<string>::iterator iterator; -}; - -TEST_F(SparseArrayStringTest, FindGetsPresentElement) { - iterator it = str_map_.find(2); - ASSERT_TRUE(str_map_.end() != it); - EXPECT_EQ("c", it->second); -} - -TEST_F(SparseArrayStringTest, FindDoesNotFindAbsentElement) { - iterator it = str_map_.find(3); - ASSERT_TRUE(str_map_.end() == it); -} - -TEST_F(SparseArrayStringTest, ContainsKey) { - EXPECT_TRUE(ContainsKey(str_map_, 1)); - EXPECT_TRUE(ContainsKey(str_map_, 2)); - EXPECT_FALSE(ContainsKey(str_map_, 3)); -} - -TEST_F(SparseArrayStringTest, InsertIfNotPresent) { - EXPECT_FALSE(ContainsKey(str_map_, 3)); - EXPECT_TRUE(InsertIfNotPresent(&str_map_, 3, "r")); - EXPECT_EQ("r", FindWithDefault(str_map_, 3, kNotFound)); - EXPECT_FALSE(InsertIfNotPresent(&str_map_, 3, "other value")); - EXPECT_EQ("r", FindWithDefault(str_map_, 3, kNotFound)); -} - -TEST(SparseArrayTest, Erase) { - SparseArray<string> str_map(5); - str_map.set(1, "a"); - str_map.set(2, "b"); - EXPECT_EQ("a", FindWithDefault(str_map, 1, kNotFound)); - EXPECT_EQ("b", FindWithDefault(str_map, 2, kNotFound)); - str_map.erase(1); - EXPECT_EQ("NOT FOUND", FindWithDefault(str_map, 1, kNotFound)); - EXPECT_EQ("b", FindWithDefault(str_map, 2, kNotFound)); -} - -typedef SparseArrayStringTest SparseArrayStringSurvivesInvalidIndexTest; -// TODO(jyasskin): Cover invalid arguments to every method. - -TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetNegative) { - EXPECT_DEBUG_DEATH(str_map_.set(-123456789, "hi"), - "\\(jyasskin\\) Illegal index -123456789 passed to" - " SparseArray\\(10\\).set\\(\\)."); - EXPECT_EQ(4, str_map_.size()); -} - -TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetTooBig) { - EXPECT_DEBUG_DEATH(str_map_.set(12345678, "hi"), - "\\(jyasskin\\) Illegal index 12345678 passed to" - " SparseArray\\(10\\).set\\(\\)."); - EXPECT_EQ(4, str_map_.size()); -} - -TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetNew_Negative) { - EXPECT_DEBUG_DEATH(str_map_.set_new(-123456789, "hi"), - "\\(jyasskin\\) Illegal index -123456789 passed to" - " SparseArray\\(10\\).set_new\\(\\)."); - EXPECT_EQ(4, str_map_.size()); -} - -TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetNew_Existing) { - EXPECT_DEBUG_DEATH({ - str_map_.set_new(2, "hi"); - EXPECT_EQ("hi", FindWithDefault(str_map_, 2, kNotFound)); - - // The old value for 2 is still present, but can never be removed. - // This risks crashing later, if the map fills up. - EXPECT_EQ(5, str_map_.size()); - }, "Check failed: !has_index\\(i\\)"); -} - -TEST_F(SparseArrayStringSurvivesInvalidIndexTest, SetNew_TooBig) { - EXPECT_DEBUG_DEATH(str_map_.set_new(12345678, "hi"), - "\\(jyasskin\\) Illegal index 12345678 passed to" - " SparseArray\\(10\\).set_new\\(\\)."); - EXPECT_EQ(4, str_map_.size()); -} - -} // namespace re2 diff --git a/third_party/re2/util/sparse_set.h b/third_party/re2/util/sparse_set.h index 4a324d7..9dd41ee 100644 --- a/third_party/re2/util/sparse_set.h +++ b/third_party/re2/util/sparse_set.h @@ -54,17 +54,15 @@ namespace re2 { class SparseSet { public: SparseSet() - : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(NULL), - valgrind_(RunningOnValgrindOrMemorySanitizer()) {} + : size_(0), max_size_(0), sparse_to_dense_(NULL), dense_(NULL) {} SparseSet(int max_size) { max_size_ = max_size; sparse_to_dense_ = new int[max_size]; dense_ = new int[max_size]; - valgrind_ = RunningOnValgrindOrMemorySanitizer(); // Don't need to zero the memory, but do so anyway // to appease Valgrind. - if (valgrind_) { + if (InitMemory()) { for (int i = 0; i < max_size; i++) { dense_[i] = 0xababababU; sparse_to_dense_[i] = 0xababababU; @@ -96,7 +94,7 @@ class SparseSet { int* a = new int[new_max_size]; if (sparse_to_dense_) { memmove(a, sparse_to_dense_, max_size_*sizeof a[0]); - if (valgrind_) { + if (InitMemory()) { for (int i = max_size_; i < new_max_size; i++) a[i] = 0xababababU; } @@ -107,7 +105,7 @@ class SparseSet { a = new int[new_max_size]; if (dense_) { memmove(a, dense_, size_*sizeof a[0]); - if (valgrind_) { + if (InitMemory()) { for (int i = size_; i < new_max_size; i++) a[i] = 0xababababU; } @@ -129,7 +127,7 @@ class SparseSet { bool contains(int i) const { DCHECK_GE(i, 0); DCHECK_LT(i, max_size_); - if (static_cast<uint>(i) >= max_size_) { + if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) { return false; } // Unsigned comparison avoids checking sparse_to_dense_[i] < 0. @@ -146,7 +144,7 @@ class SparseSet { // Set the value at the new index i to v. // Fast but unsafe: only use if contains(i) is false. void insert_new(int i) { - if (static_cast<uint>(i) >= max_size_) { + if (static_cast<uint>(i) >= static_cast<uint>(max_size_)) { // Semantically, end() would be better here, but we already know // the user did something stupid, so begin() insulates them from // dereferencing an invalid pointer. @@ -166,13 +164,20 @@ class SparseSet { static bool less(int a, int b) { return a < b; } private: + static bool InitMemory() { +#ifdef MEMORY_SANITIZER + return true; +#else + return RunningOnValgrind(); +#endif + } + int size_; int max_size_; int* sparse_to_dense_; int* dense_; - bool valgrind_; - DISALLOW_EVIL_CONSTRUCTORS(SparseSet); + DISALLOW_COPY_AND_ASSIGN(SparseSet); }; } // namespace re2 diff --git a/third_party/re2/util/stringpiece.cc b/third_party/re2/util/stringpiece.cc deleted file mode 100644 index 37895b0..0000000 --- a/third_party/re2/util/stringpiece.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2004 The RE2 Authors. All Rights Reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "re2/stringpiece.h" -#include "util/util.h" - -using re2::StringPiece; - -std::ostream& operator<<(std::ostream& o, const StringPiece& piece) { - o.write(piece.data(), piece.size()); - return o; -} - -bool StringPiece::_equal(const StringPiece& x, const StringPiece& y) { - int len = x.size(); - if (len != y.size()) { - return false; - } - const char* p = x.data(); - const char* p2 = y.data(); - // Test last byte in case strings share large common prefix - if ((len > 0) && (p[len-1] != p2[len-1])) return false; - const char* p_limit = p + len; - for (; p < p_limit; p++, p2++) { - if (*p != *p2) - return false; - } - return true; -} - -void StringPiece::CopyToString(string* target) const { - target->assign(ptr_, length_); -} - -int StringPiece::copy(char* buf, size_type n, size_type pos) const { - int ret = min(length_ - pos, n); - memcpy(buf, ptr_ + pos, ret); - return ret; -} - -int StringPiece::find(const StringPiece& s, size_type pos) const { - if (length_ < 0 || pos > static_cast<size_type>(length_)) - return npos; - - const char* result = std::search(ptr_ + pos, ptr_ + length_, - s.ptr_, s.ptr_ + s.length_); - const size_type xpos = result - ptr_; - return xpos + s.length_ <= length_ ? xpos : npos; -} - -int StringPiece::find(char c, size_type pos) const { - if (length_ <= 0 || pos >= static_cast<size_type>(length_)) { - return npos; - } - const char* result = std::find(ptr_ + pos, ptr_ + length_, c); - return result != ptr_ + length_ ? result - ptr_ : npos; -} - -int StringPiece::rfind(const StringPiece& s, size_type pos) const { - if (length_ < s.length_) return npos; - const size_t ulen = length_; - if (s.length_ == 0) return min(ulen, pos); - - const char* last = ptr_ + min(ulen - s.length_, pos) + s.length_; - const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); - return result != last ? result - ptr_ : npos; -} - -int StringPiece::rfind(char c, size_type pos) const { - if (length_ <= 0) return npos; - for (int i = min(pos, static_cast<size_type>(length_ - 1)); - i >= 0; --i) { - if (ptr_[i] == c) { - return i; - } - } - return npos; -} - -StringPiece StringPiece::substr(size_type pos, size_type n) const { - if (pos > length_) pos = length_; - if (n > length_ - pos) n = length_ - pos; - return StringPiece(ptr_ + pos, n); -} - -const StringPiece::size_type StringPiece::npos = size_type(-1); diff --git a/third_party/re2/util/stringprintf.cc b/third_party/re2/util/stringprintf.cc index c908181..e71d9938 100644 --- a/third_party/re2/util/stringprintf.cc +++ b/third_party/re2/util/stringprintf.cc @@ -4,7 +4,7 @@ #include "util/util.h" -namespace re2 { +namespace re2 { static void StringAppendV(string* dst, const char* format, va_list ap) { // First try with a small fixed size buffer @@ -18,7 +18,7 @@ static void StringAppendV(string* dst, const char* format, va_list ap) { int result = vsnprintf(space, sizeof(space), format, backup_ap); va_end(backup_ap); - if ((result >= 0) && (result < sizeof(space))) { + if ((result >= 0) && (static_cast<unsigned long>(result) < sizeof(space))) { // It fit dst->append(space, result); return; @@ -38,7 +38,14 @@ static void StringAppendV(string* dst, const char* format, va_list ap) { // Restore the va_list before we use it again va_copy(backup_ap, ap); +#if !defined(_WIN32) result = vsnprintf(buf, length, format, backup_ap); +#else + // On Windows, the function takes five arguments, not four. With an array, + // the buffer size will be inferred, but not with a pointer. C'est la vie. + // (See https://github.com/google/re2/issues/40 for more details.) + result = vsnprintf(buf, length, _TRUNCATE, format, backup_ap); +#endif va_end(backup_ap); if ((result >= 0) && (result < length)) { diff --git a/third_party/re2/util/strutil.cc b/third_party/re2/util/strutil.cc index 6ab79b3..d3a0249 100644 --- a/third_party/re2/util/strutil.cc +++ b/third_party/re2/util/strutil.cc @@ -20,7 +20,7 @@ int CEscapeString(const char* src, int src_len, char* dest, int used = 0; for (; src < src_end; src++) { - if (dest_len - used < 2) // Need space for two letter escape + if (dest_len - used < 2) // space for two-character escape return -1; unsigned char c = *src; @@ -36,9 +36,15 @@ int CEscapeString(const char* src, int src_len, char* dest, // digit then that digit must be escaped too to prevent it being // interpreted as part of the character code by C. if (c < ' ' || c > '~') { - if (dest_len - used < 4) // need space for 4 letter escape + if (dest_len - used < 5) // space for four-character escape + \0 return -1; - sprintf(dest + used, "\\%03o", c); +#if !defined(_WIN32) + snprintf(dest + used, 5, "\\%03o", c); +#else + // On Windows, the function takes 4+VA arguments, not 3+VA. With an + // array, the buffer size will be inferred, but not with a pointer. + snprintf(dest + used, 5, _TRUNCATE, "\\%03o", c); +#endif used += 4; } else { dest[used++] = c; break; @@ -57,7 +63,7 @@ int CEscapeString(const char* src, int src_len, char* dest, // ---------------------------------------------------------------------- // CEscape() // Copies 'src' to result, escaping dangerous characters using -// C-style escape sequences. 'src' and 'dest' should not overlap. +// C-style escape sequences. 'src' and 'dest' should not overlap. // ---------------------------------------------------------------------- string CEscape(const StringPiece& src) { const int dest_length = src.size() * 4 + 1; // Maximum possible expansion @@ -77,7 +83,7 @@ string PrefixSuccessor(const StringPiece& prefix) { // 255's, we just return the empty string. bool done = false; string limit(prefix.data(), prefix.size()); - int index = limit.length() - 1; + int index = static_cast<int>(limit.size()) - 1; while (!done && index >= 0) { if ((limit[index]&255) == 255) { limit.erase(index); diff --git a/third_party/re2/util/test.cc b/third_party/re2/util/test.cc index 2fe1bfa..b0167e7 100644 --- a/third_party/re2/util/test.cc +++ b/third_party/re2/util/test.cc @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. #include <stdio.h> -#ifndef WIN32 +#ifndef _WIN32 #include <sys/resource.h> #endif #include "util/test.h" @@ -23,18 +23,6 @@ void RegisterTest(void (*fn)(void), const char *name) { tests[ntests++].name = name; } -namespace re2 { -int64 VirtualProcessSize() { -#ifndef WIN32 - struct rusage ru; - getrusage(RUSAGE_SELF, &ru); - return (int64)ru.ru_maxrss*1024; -#else - return 0; -#endif -} -} // namespace re2 - int main(int argc, char **argv) { for (int i = 0; i < ntests; i++) { printf("%s\n", tests[i].name); diff --git a/third_party/re2/util/test.h b/third_party/re2/util/test.h index 0f93865..3701eab 100644 --- a/third_party/re2/util/test.h +++ b/third_party/re2/util/test.h @@ -31,27 +31,15 @@ class TestRegisterer { #define EXPECT_GE CHECK_GE #define EXPECT_FALSE(x) CHECK(!(x)) -#define ARRAYSIZE arraysize - -#define EXPECT_TRUE_M(x, y) CHECK(x) << (y) -#define EXPECT_FALSE_M(x, y) CHECK(!(x)) << (y) -#define ASSERT_TRUE_M(x, y) CHECK(x) << (y) -#define ASSERT_EQUALS(x, y) CHECK_EQ(x, y) - -const bool UsingMallocCounter = false; namespace testing { class MallocCounter { public: - MallocCounter(int x) { } + MallocCounter(int x) {} static const int THIS_THREAD_ONLY = 0; long long HeapGrowth() { return 0; } long long PeakHeapGrowth() { return 0; } - void Reset() { } + void Reset() {} }; } // namespace testing -namespace re2 { -int64 VirtualProcessSize(); -} // namespace re2 - #endif // RE2_UTIL_TEST_H__ diff --git a/third_party/re2/util/thread.cc b/third_party/re2/util/thread.cc index 7349991..d97f14b 100644 --- a/third_party/re2/util/thread.cc +++ b/third_party/re2/util/thread.cc @@ -2,10 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include <pthread.h> - -#include "util/util.h" #include "util/thread.h" +#include "util/util.h" Thread::Thread() { pid_ = 0; diff --git a/third_party/re2/util/thread.h b/third_party/re2/util/thread.h index b9610e0..fb67bdc 100644 --- a/third_party/re2/util/thread.h +++ b/third_party/re2/util/thread.h @@ -5,7 +5,11 @@ #ifndef RE2_UTIL_THREAD_H__ #define RE2_UTIL_THREAD_H__ +#ifdef _WIN32 +#include <windows.h> +#else #include <pthread.h> +#endif class Thread { public: @@ -15,12 +19,15 @@ class Thread { void Join(); void SetJoinable(bool); virtual void Run() = 0; - + private: +#ifdef _WIN32 + HANDLE pid_; +#else pthread_t pid_; +#endif bool running_; bool joinable_; }; #endif // RE2_UTIL_THREAD_H__ - diff --git a/third_party/re2/util/threadwin.cc b/third_party/re2/util/threadwin.cc new file mode 100644 index 0000000..d68f2c5 --- /dev/null +++ b/third_party/re2/util/threadwin.cc @@ -0,0 +1,44 @@ +// Copyright 2009 The RE2 Authors. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "util/thread.h" +#include "util/util.h" + +Thread::Thread() { + pid_ = 0; + running_ = 0; + joinable_ = 0; +} + +Thread::~Thread() { +} + +DWORD WINAPI startThread(void *v) { + Thread* t = (Thread*)v; + t->Run(); + return 0; +} + +void Thread::Start() { + CHECK(!running_); + pid_ = CreateThread(NULL, 0, startThread, this, 0, NULL); + running_ = true; + if (!joinable_) { + CloseHandle(pid_); + pid_ = 0; + } +} + +void Thread::Join() { + CHECK(running_); + CHECK(joinable_); + if (pid_ != 0) + WaitForSingleObject(pid_, INFINITE); + running_ = 0; +} + +void Thread::SetJoinable(bool j) { + CHECK(!running_); + joinable_ = j; +} diff --git a/third_party/re2/util/util.h b/third_party/re2/util/util.h index a4fdfcc..c59d91f2 100644 --- a/third_party/re2/util/util.h +++ b/third_party/re2/util/util.h @@ -9,16 +9,18 @@ #include <stdio.h> #include <string.h> #include <stdint.h> -#include <stddef.h> // For size_t +#include <stddef.h> // For size_t #include <assert.h> #include <stdarg.h> -#ifndef WIN32 -#include <sys/time.h> +#include <time.h> // For clock_gettime, CLOCK_REALTIME +#include <ctype.h> // For isdigit, isalpha + +#if !defined(_WIN32) +#include <sys/time.h> // For gettimeofday #endif -#include <time.h> -#include <ctype.h> // For isdigit, isalpha. // C++ +#include <ctime> #include <vector> #include <string> #include <algorithm> @@ -29,9 +31,6 @@ #include <utility> #include <set> -#include "build/build_config.h" -#include "base/third_party/dynamic_annotations/dynamic_annotations.h" - // Use std names. using std::set; using std::pair; @@ -46,7 +45,7 @@ using std::sort; using std::swap; using std::make_pair; -#if defined(__GNUC__) && !defined(USE_CXX0X) && !defined(_LIBCPP_ABI_VERSION) && !defined(OS_ANDROID) +#if defined(__GNUC__) && !defined(USE_CXX0X) && !defined(_LIBCPP_ABI_VERSION) #include <tr1/unordered_set> using std::tr1::unordered_set; @@ -54,7 +53,7 @@ using std::tr1::unordered_set; #else #include <unordered_set> -#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION)) +#if defined(_WIN32) using std::tr1::unordered_set; #else using std::unordered_set; @@ -62,6 +61,17 @@ using std::unordered_set; #endif +#ifdef _WIN32 + +#define snprintf _snprintf_s +#define stricmp _stricmp +#define strtof strtod /* not really correct but best we can do */ +#define strtoll _strtoi64 +#define strtoull _strtoui64 +#define vsnprintf vsnprintf_s + +#endif + namespace re2 { typedef int8_t int8; @@ -77,35 +87,31 @@ typedef unsigned long ulong; typedef unsigned int uint; typedef unsigned short ushort; +// Prevent the compiler from complaining about or optimizing away variables +// that appear unused. +#undef ATTRIBUTE_UNUSED +#if defined(__GNUC__) +#define ATTRIBUTE_UNUSED __attribute__ ((unused)) +#else +#define ATTRIBUTE_UNUSED +#endif + // COMPILE_ASSERT causes a compile error about msg if expr is not true. #if __cplusplus >= 201103L #define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) #else template<bool> struct CompileAssert {}; #define COMPILE_ASSERT(expr, msg) \ - typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] + typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ATTRIBUTE_UNUSED #endif -// DISALLOW_EVIL_CONSTRUCTORS disallows the copy and operator= functions. +// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. // It goes in the private: declarations in a class. -#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&) -#define arraysize(array) (sizeof(array)/sizeof((array)[0])) - -// Fake lock annotations. For real ones, see -// http://code.google.com/p/data-race-test/ -#ifndef ANNOTATE_PUBLISH_MEMORY_RANGE -#define ANNOTATE_PUBLISH_MEMORY_RANGE(a, b) -#define ANNOTATE_IGNORE_WRITES_BEGIN() -#define ANNOTATE_IGNORE_WRITES_END() -#define ANNOTATE_BENIGN_RACE(a, b) -#define NO_THREAD_SAFETY_ANALYSIS -#define ANNOTATE_HAPPENS_BEFORE(x) -#define ANNOTATE_HAPPENS_AFTER(x) -#define ANNOTATE_UNPROTECTED_READ(x) (x) -#endif +#define arraysize(array) (int)(sizeof(array)/sizeof((array)[0])) class StringPiece; @@ -132,17 +138,10 @@ static inline uint64 Hash64StringWithSeed(const char* s, int len, uint32 seed) { return ((uint64)x << 32) | y; } -inline bool RunningOnValgrindOrMemorySanitizer() { -#if defined(MEMORY_SANITIZER) - return true; -#else - return RunningOnValgrind(); -#endif -} +bool RunningOnValgrind(); } // namespace re2 -#include "util/arena.h" #include "util/logging.h" #include "util/mutex.h" #include "util/utf.h" diff --git a/third_party/re2/util/valgrind.cc b/third_party/re2/util/valgrind.cc index 46f804b..19ec22e 100644 --- a/third_party/re2/util/valgrind.cc +++ b/third_party/re2/util/valgrind.cc @@ -3,15 +3,17 @@ // license that can be found in the LICENSE file. #include "util/util.h" +#ifndef _WIN32 #include "util/valgrind.h" +#endif namespace re2 { -int RunningOnValgrind() { +bool RunningOnValgrind() { #ifdef RUNNING_ON_VALGRIND - return RUNNING_ON_VALGRIND; + return RUNNING_ON_VALGRIND != 0; #else - return 0; + return false; #endif } diff --git a/third_party/re2/util/valgrind.h b/third_party/re2/util/valgrind.h index d097b0c..ca10b1a 100644 --- a/third_party/re2/util/valgrind.h +++ b/third_party/re2/util/valgrind.h @@ -4064,7 +4064,6 @@ typedef #endif /* PLAT_ppc64_aix5 */ -#ifndef WIN32 /* ------------------------------------------------------------------ */ /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ /* */ @@ -4171,7 +4170,7 @@ typedef VG_USERREQ__DISCARD_TRANSLATIONS, \ _qzz_addr, _qzz_len, 0, 0, 0); \ } -#endif + /* These requests are for getting Valgrind itself to print something. Possibly with a backtrace. This is a really ugly hack. The return value |