Skip to content

Commit

Permalink
Export of internal Abseil changes
Browse files Browse the repository at this point in the history
--
074a799119ac881b8b8ce59ef7a3166d1aa025ac by Tom Manshreck <shreck@google.com>:

nit: Add return info for StrCat

PiperOrigin-RevId: 278647298

--
d58a2a39ab6f50266cc695506ba2e86bdb45d795 by Mark Barolak <mbar@google.com>:

Stop suppressing no-nested-anon-types warnings because there aren't actually any warnings to suppress.

PiperOrigin-RevId: 278440548

--
445051bd280b9a6f608a8c80b3d7cafcc1377a03 by Abseil Team <absl-team@google.com>:

ResetThreadIdentity does not need to clear identity->waiter_state.

ResetThreadIdentity is only called by NewThreadIdentity. NewThreadIdentity is
only called by CreateThreadIdentity. CreateThreadIdentity calls
PerThreadSem::Init, which initializes identity->waiter_state, immediately after
calling NewThreadIdentity. Therefore ResetThreadIdentity does not need to clear
identity->waiter_state.
PiperOrigin-RevId: 278429844

--
c2079b664d92be40d5e365abcca4e9b3505a75a6 by Abseil Team <absl-team@google.com>:

Delete the f->header.magic check in LowLevelAlloc::Free().

The f->header.magic check in LowLevelAlloc::Free() is redundant, because
AddToFreeList() will immediately perform the same check.

Also fix a typo in the comment that documents the lock requirements for
Next(). The comment should say "L >= arena->mu", which is equivalent to
EXCLUSIVE_LOCKS_REQUIRED(arena->mu).

NOTE: LowLevelAlloc::Free() performs the f->header.magic check without
holding the arena lock. This may have caused the TSAN data race warning
reported in bug 143697235.
PiperOrigin-RevId: 278414140

--
5534f35ce677165700117d868f51607ed1f0d73b by Greg Falcon <gfalcon@google.com>:

Add an internal (unsupported) PiecewiseCombiner class to allow hashing buffers piecewise.

PiperOrigin-RevId: 278388902
GitOrigin-RevId: 074a799119ac881b8b8ce59ef7a3166d1aa025ac
Change-Id: I61734850cbbb01c7585e8c736a5bb56e416512a8
  • Loading branch information
Abseil Team authored and Xiaoyi Zhang committed Nov 5, 2019
1 parent 20de2db commit e96ae22
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 15 deletions.
4 changes: 1 addition & 3 deletions absl/base/internal/low_level_alloc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ static inline uintptr_t RoundUp(uintptr_t addr, uintptr_t align) {
// that the freelist is in the correct order, that it
// consists of regions marked "unallocated", and that no two regions
// are adjacent in memory (they should have been coalesced).
// L < arena->mu
// L >= arena->mu
static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena) {
ABSL_RAW_CHECK(i < prev->levels, "too few levels in Next()");
AllocList *next = prev->next[i];
Expand Down Expand Up @@ -508,8 +508,6 @@ void LowLevelAlloc::Free(void *v) {
if (v != nullptr) {
AllocList *f = reinterpret_cast<AllocList *>(
reinterpret_cast<char *>(v) - sizeof (f->header));
ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
"bad magic number in Free()");
LowLevelAlloc::Arena *arena = f->header.arena;
ArenaLock section(arena);
AddToFreelist(v, arena);
Expand Down
2 changes: 0 additions & 2 deletions absl/copts/GENERATED_AbseilCopts.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ list(APPEND ABSL_CLANG_CL_FLAGS
"-Wno-gcc-compat"
"-Wno-global-constructors"
"-Wno-exit-time-destructors"
"-Wno-nested-anon-types"
"-Wno-non-modular-include-in-module"
"-Wno-old-style-cast"
"-Wno-range-loop-analysis"
Expand Down Expand Up @@ -123,7 +122,6 @@ list(APPEND ABSL_LLVM_FLAGS
"-Wno-gcc-compat"
"-Wno-global-constructors"
"-Wno-exit-time-destructors"
"-Wno-nested-anon-types"
"-Wno-non-modular-include-in-module"
"-Wno-old-style-cast"
"-Wno-range-loop-analysis"
Expand Down
2 changes: 0 additions & 2 deletions absl/copts/GENERATED_copts.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ ABSL_CLANG_CL_FLAGS = [
"-Wno-gcc-compat",
"-Wno-global-constructors",
"-Wno-exit-time-destructors",
"-Wno-nested-anon-types",
"-Wno-non-modular-include-in-module",
"-Wno-old-style-cast",
"-Wno-range-loop-analysis",
Expand Down Expand Up @@ -124,7 +123,6 @@ ABSL_LLVM_FLAGS = [
"-Wno-gcc-compat",
"-Wno-global-constructors",
"-Wno-exit-time-destructors",
"-Wno-nested-anon-types",
"-Wno-non-modular-include-in-module",
"-Wno-old-style-cast",
"-Wno-range-loop-analysis",
Expand Down
1 change: 0 additions & 1 deletion absl/copts/copts.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"-Wno-global-constructors",
"-Wno-exit-time-destructors",
###
"-Wno-nested-anon-types",
"-Wno-non-modular-include-in-module",
"-Wno-old-style-cast",
# Warns on preferred usage of non-POD types such as string_view
Expand Down
2 changes: 1 addition & 1 deletion absl/hash/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ cc_test(
deps = [
":hash",
":hash_testing",
":spy_hash_state",
"//absl/base:core_headers",
"//absl/container:flat_hash_set",
"//absl/hash:spy_hash_state",
"//absl/meta:type_traits",
"//absl/numeric:int128",
"@com_google_googletest//:gtest_main",
Expand Down
114 changes: 112 additions & 2 deletions absl/hash/hash_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ TEST(HashValueTest, Strings) {

const std::string small = "foo";
const std::string dup = "foofoo";
const std::string large = "large";
const std::string huge = std::string(5000, 'a');
const std::string large = std::string(2048, 'x'); // multiple of chunk size
const std::string huge = std::string(5000, 'a'); // not a multiple

EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
std::string(), absl::string_view(),
Expand Down Expand Up @@ -378,6 +378,116 @@ struct Private {
}
};

// Test helper for combine_piecewise_buffer. It holds a string_view to the
// buffer-to-be-hashed. Its AbslHashValue specialization will split up its
// contents at the character offsets requested.
class PiecewiseHashTester {
public:
// Create a hash view of a buffer to be hashed contiguously.
explicit PiecewiseHashTester(absl::string_view buf)
: buf_(buf), piecewise_(false), split_locations_() {}

// Create a hash view of a buffer to be hashed piecewise, with breaks at the
// given locations.
PiecewiseHashTester(absl::string_view buf, std::set<size_t> split_locations)
: buf_(buf),
piecewise_(true),
split_locations_(std::move(split_locations)) {}

template <typename H>
friend H AbslHashValue(H h, const PiecewiseHashTester& p) {
if (!p.piecewise_) {
return H::combine_contiguous(std::move(h), p.buf_.data(), p.buf_.size());
}
absl::hash_internal::PiecewiseCombiner combiner;
if (p.split_locations_.empty()) {
h = combiner.add_buffer(std::move(h), p.buf_.data(), p.buf_.size());
return combiner.finalize(std::move(h));
}
size_t begin = 0;
for (size_t next : p.split_locations_) {
absl::string_view chunk = p.buf_.substr(begin, next - begin);
h = combiner.add_buffer(std::move(h), chunk.data(), chunk.size());
begin = next;
}
absl::string_view last_chunk = p.buf_.substr(begin);
if (!last_chunk.empty()) {
h = combiner.add_buffer(std::move(h), last_chunk.data(),
last_chunk.size());
}
return combiner.finalize(std::move(h));
}

private:
absl::string_view buf_;
bool piecewise_;
std::set<size_t> split_locations_;
};

// Dummy object that hashes as two distinct contiguous buffers, "foo" followed
// by "bar"
struct DummyFooBar {
template <typename H>
friend H AbslHashValue(H h, const DummyFooBar&) {
const char* foo = "foo";
const char* bar = "bar";
h = H::combine_contiguous(std::move(h), foo, 3);
h = H::combine_contiguous(std::move(h), bar, 3);
return std::move(h);
}
};

TEST(HashValueTest, CombinePiecewiseBuffer) {
absl::Hash<PiecewiseHashTester> hash;

// Check that hashing an empty buffer through the piecewise API works.
EXPECT_EQ(hash(PiecewiseHashTester("")), hash(PiecewiseHashTester("", {})));

// Similarly, small buffers should give consistent results
EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
hash(PiecewiseHashTester("foobar", {})));
EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
hash(PiecewiseHashTester("foobar", {3})));

// But hashing "foobar" in pieces gives a different answer than hashing "foo"
// contiguously, then "bar" contiguously.
EXPECT_NE(hash(PiecewiseHashTester("foobar", {3})),
absl::Hash<DummyFooBar>()(DummyFooBar{}));

// Test hashing a large buffer incrementally, broken up in several different
// ways. Arrange for breaks on and near the stride boundaries to look for
// off-by-one errors in the implementation.
//
// This test is run on a buffer that is a multiple of the stride size, and one
// that isn't.
for (size_t big_buffer_size : {1024 * 2 + 512, 1024 * 3}) {
SCOPED_TRACE(big_buffer_size);
std::string big_buffer;
for (int i = 0; i < big_buffer_size; ++i) {
// Arbitrary std::string
big_buffer.push_back(32 + (i * (i / 3)) % 64);
}
auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer));

const int possible_breaks = 9;
size_t breaks[possible_breaks] = {1, 512, 1023, 1024, 1025,
1536, 2047, 2048, 2049};
for (unsigned test_mask = 0; test_mask < (1u << possible_breaks);
++test_mask) {
SCOPED_TRACE(test_mask);
std::set<size_t> break_locations;
for (int j = 0; j < possible_breaks; ++j) {
if (test_mask & (1u << j)) {
break_locations.insert(breaks[j]);
}
}
EXPECT_EQ(
hash(PiecewiseHashTester(big_buffer, std::move(break_locations))),
big_buffer_hash);
}
}
}

TEST(HashValueTest, PrivateSanity) {
// Sanity check that Private is working as the tests below expect it to work.
EXPECT_TRUE(is_hashable<Private>::value);
Expand Down
30 changes: 30 additions & 0 deletions absl/hash/internal/hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,36 @@
namespace absl {
namespace hash_internal {

uint64_t CityHashState::CombineLargeContiguousImpl32(uint64_t state,
const unsigned char* first,
size_t len) {
while (len >= PiecewiseChunkSize()) {
state =
Mix(state, absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first),
PiecewiseChunkSize()));
len -= PiecewiseChunkSize();
first += PiecewiseChunkSize();
}
// Handle the remainder.
return CombineContiguousImpl(state, first, len,
std::integral_constant<int, 4>{});
}

uint64_t CityHashState::CombineLargeContiguousImpl64(uint64_t state,
const unsigned char* first,
size_t len) {
while (len >= PiecewiseChunkSize()) {
state =
Mix(state, absl::hash_internal::CityHash64(reinterpret_cast<const char*>(first),
PiecewiseChunkSize()));
len -= PiecewiseChunkSize();
first += PiecewiseChunkSize();
}
// Handle the remainder.
return CombineContiguousImpl(state, first, len,
std::integral_constant<int, 8>{});
}

ABSL_CONST_INIT const void* const CityHashState::kSeed = &kSeed;

} // namespace hash_internal
Expand Down
Loading

0 comments on commit e96ae22

Please sign in to comment.