diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index 624a3c7..61e1ae4 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake
@@ -326,7 +326,12 @@ ) if (_build_type STREQUAL "dll") - set(ABSL_CC_LIB_DEPS abseil_dll) + if(${_in_dll}) + set(ABSL_CC_LIB_DEPS abseil_dll) + endif() + if(${_in_test_dll}) + set(ABSL_CC_LIB_DEPS abseil_test_dll) + endif() endif() target_link_libraries(${_NAME}
diff --git a/absl/base/internal/spinlock.cc b/absl/base/internal/spinlock.cc index 4168b8b..41d2b48 100644 --- a/absl/base/internal/spinlock.cc +++ b/absl/base/internal/spinlock.cc
@@ -71,17 +71,23 @@ } // Monitor the lock to see if its value changes within some time period -// (adaptive_spin_count loop iterations). The last value read from the lock +// (adaptive_spin_count_ loop iterations). The last value read from the lock // is returned from the method. +ABSL_CONST_INIT std::atomic<int> SpinLock::adaptive_spin_count_{0}; uint32_t SpinLock::SpinLoop() { // We are already in the slow path of SpinLock, initialize the // adaptive_spin_count here. - ABSL_CONST_INIT static absl::once_flag init_adaptive_spin_count; - ABSL_CONST_INIT static int adaptive_spin_count = 0; - LowLevelCallOnce(&init_adaptive_spin_count, - []() { adaptive_spin_count = NumCPUs() > 1 ? 1000 : 1; }); - - int c = adaptive_spin_count; + if (adaptive_spin_count_.load(std::memory_order_relaxed) == 0) { + int current_spin_count = 0; + int new_spin_count = NumCPUs() > 1 ? 1000 : 1; + // If this fails, the value will remain unchanged. We may not spin for the + // intended duration, but that is still safe. We will try again on the next + // call to SpinLoop. + adaptive_spin_count_.compare_exchange_weak( + current_spin_count, new_spin_count, std::memory_order_relaxed, + std::memory_order_relaxed); + } + int c = adaptive_spin_count_.load(std::memory_order_relaxed); uint32_t lock_value; do { lock_value = lockword_.load(std::memory_order_relaxed);
diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h index ff2b087..d0e1649 100644 --- a/absl/base/internal/spinlock.h +++ b/absl/base/internal/spinlock.h
@@ -47,6 +47,7 @@ namespace tcmalloc_internal { class AllocationGuardSpinLockHolder; +class Static; } // namespace tcmalloc_internal } // namespace tcmalloc @@ -173,6 +174,16 @@ // Provide access to protected method above. Use for testing only. friend struct SpinLockTest; friend class tcmalloc::tcmalloc_internal::AllocationGuardSpinLockHolder; + friend class tcmalloc::tcmalloc_internal::Static; + + static int GetAdaptiveSpinCount() { + return adaptive_spin_count_.load(std::memory_order_relaxed); + } + static void SetAdaptiveSpinCount(int count) { + adaptive_spin_count_.store(count, std::memory_order_relaxed); + } + + static std::atomic<int> adaptive_spin_count_; private: // lockword_ is used to store the following:
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc index e750655..09076b4 100644 --- a/absl/container/internal/raw_hash_set.cc +++ b/absl/container/internal/raw_hash_set.cc
@@ -131,6 +131,16 @@ } // namespace +// Must be defined out-of-line to avoid MSVC error C2482 on some platforms, +// which is caused by non-constexpr initialization. +uint16_t HashtableSize::NextSeed() { + static_assert(PerTableSeed::kBitCount == 16); + thread_local uint16_t seed = + static_cast<uint16_t>(reinterpret_cast<uintptr_t>(&seed)); + seed += uint16_t{0xad53}; + return seed; +} + GenerationType* EmptyGeneration() { if (SwisstableGenerationsEnabled()) { constexpr size_t kNumEmptyGenerations = 1024;
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 9033982..ab6657c 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h
@@ -461,15 +461,6 @@ const uint16_t seed_; }; -// Returns next per-table seed. -inline uint16_t NextSeed() { - static_assert(PerTableSeed::kBitCount == 16); - thread_local uint16_t seed = - static_cast<uint16_t>(reinterpret_cast<uintptr_t>(&seed)); - seed += uint16_t{0xad53}; - return seed; -} - // The size and also has additionally // 1) one bit that stores whether we have infoz. // 2) PerTableSeed::kBitCount bits for the seed. @@ -517,6 +508,9 @@ void set_no_seed_for_testing() { data_ &= ~kSeedMask; } + // Returns next per-table seed. + static uint16_t NextSeed(); + private: void set_seed(uint16_t seed) { data_ = (data_ & ~kSeedMask) | (seed | PerTableSeed::kSignBit);
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index d411709..e3b5b72 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc
@@ -2560,7 +2560,7 @@ // in seed. void GenerateIrrelevantSeeds(int cnt) { for (int i = cnt % 17; i > 0; --i) { - NextSeed(); + HashtableSize::NextSeed(); } }
diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc index d31f5a1..16609f1 100644 --- a/absl/debugging/failure_signal_handler.cc +++ b/absl/debugging/failure_signal_handler.cc
@@ -157,8 +157,8 @@ #ifdef ABSL_HAVE_SIGALTSTACK static bool SetupAlternateStackOnce() { -#if defined(__wasm__) || defined(__asjms__) - const size_t page_mask = getpagesize() - 1; +#if defined(__wasm__) || defined(__asmjs__) + const size_t page_mask = static_cast<size_t>(getpagesize()) - 1; #else const size_t page_mask = static_cast<size_t>(sysconf(_SC_PAGESIZE)) - 1; #endif
diff --git a/absl/status/status_matchers.h b/absl/status/status_matchers.h index 6db7355..03e5f49 100644 --- a/absl/status/status_matchers.h +++ b/absl/status/status_matchers.h
@@ -26,7 +26,7 @@ // ABSL_ASSERT_OK(s) // ================= // Convenience macros for `EXPECT_THAT(s, IsOk())`, where `s` is either -// a `Status` or a `StatusOr<T>` or a `StatusProto`. +// a `Status` or a `StatusOr<T>`. // // There are no EXPECT_NOT_OK/ASSERT_NOT_OK macros since they would not // provide much value (when they fail, they would just print the OK status
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 2e64f1a..9dde5e5 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel
@@ -182,6 +182,7 @@ ":resize_and_overwrite", "//absl/base:config", "//absl/base:core_headers", + "//absl/base:throw_delegate", ], )
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 24408ca..2b97fb5 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt
@@ -183,6 +183,7 @@ absl::config absl::core_headers absl::strings_resize_and_overwrite + absl::throw_delegate ) absl_cc_test(
diff --git a/absl/strings/internal/append_and_overwrite.h b/absl/strings/internal/append_and_overwrite.h index 0bb1215..9dec73b 100644 --- a/absl/strings/internal/append_and_overwrite.h +++ b/absl/strings/internal/append_and_overwrite.h
@@ -16,6 +16,7 @@ #define ABSL_STRINGS_INTERNAL_APPEND_AND_OVERWRITE_H_ #include "absl/base/config.h" +#include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/optimization.h" #include "absl/strings/resize_and_overwrite.h" @@ -44,17 +45,24 @@ template <typename T, typename Op> void StringAppendAndOverwrite(T& str, typename T::size_type append_n, Op append_op) { - ABSL_HARDENING_ASSERT(str.size() <= str.max_size() - append_n); + if (ABSL_PREDICT_FALSE(append_n > str.max_size() - str.size())) { + absl::base_internal::ThrowStdLengthError( + "absl::strings_internal::StringAppendAndOverwrite"); + } + auto old_size = str.size(); auto resize = old_size + append_n; - // Make sure to always grow by at least a factor of 2x. if (resize > str.capacity()) { - if (ABSL_PREDICT_FALSE(str.capacity() > str.max_size() / 2)) { + // Make sure to always grow by at least a factor of 2x. + const auto min_growth = str.capacity(); + if (ABSL_PREDICT_FALSE(str.capacity() > str.max_size() - min_growth)) { resize = str.max_size(); - } else if (resize < str.capacity() * 2) { - resize = str.capacity() * 2; + } else if (resize < str.capacity() + min_growth) { + resize = str.capacity() + min_growth; } + } else { + resize = str.capacity(); } // Avoid calling StringResizeAndOverwrite() here since it does an MSAN
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc index 01caf78..60e43e0 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc
@@ -50,11 +50,15 @@ bool SimpleAtof(absl::string_view str, float* absl_nonnull out) { *out = 0.0; str = StripAsciiWhitespace(str); + if (str.empty()) { + // absl::from_chars doesn't accept empty strings. + return false; + } // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one // is present, skip it, while avoiding accepting "+-0" as valid. - if (!str.empty() && str[0] == '+') { + if (str[0] == '+') { str.remove_prefix(1); - if (!str.empty() && str[0] == '-') { + if (str.empty() || str[0] == '-') { return false; } }
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index 1a82087..ca13da0 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc
@@ -451,6 +451,20 @@ VerifySimpleAtoiGood<std::string::size_type>(42, 42); } +TEST(NumbersTest, AtodEmpty) { + double d; + EXPECT_FALSE(absl::SimpleAtod("", &d)); + // Empty string_view takes a different code path from "". + EXPECT_FALSE(absl::SimpleAtod({}, &d)); +} + +TEST(NumbersTest, AtofEmpty) { + float f; + EXPECT_FALSE(absl::SimpleAtof("", &f)); + // Empty string_view takes a different code path from "". + EXPECT_FALSE(absl::SimpleAtof({}, &f)); +} + TEST(NumbersTest, Atod) { // DBL_TRUE_MIN and FLT_TRUE_MIN were not mandated in <cfloat> before C++17. #if !defined(DBL_TRUE_MIN)
diff --git a/absl/strings/resize_and_overwrite.h b/absl/strings/resize_and_overwrite.h index 169c685..04c12d2 100644 --- a/absl/strings/resize_and_overwrite.h +++ b/absl/strings/resize_and_overwrite.h
@@ -159,7 +159,7 @@ } else if constexpr (strings_internal::has_Resize_and_overwrite<T>::value) { str._Resize_and_overwrite(n, std::move(op)); } else { - strings_internal::StringResizeAndOverwriteFallback(str, n, op); + strings_internal::StringResizeAndOverwriteFallback(str, n, std::move(op)); } #endif }