re2 1.22.2 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -4
- package/binding.gyp +5 -1
- package/lib/addon.cc +4 -0
- package/lib/new.cc +1 -246
- package/lib/pattern.cc +252 -0
- package/lib/pattern.h +10 -0
- package/lib/set.cc +777 -0
- package/lib/wrapped_re2_set.h +42 -0
- package/package.json +21 -9
- package/re2.d.ts +46 -9
- package/vendor/abseil-cpp/CMake/AbseilDll.cmake +14 -24
- package/vendor/abseil-cpp/CMake/AbseilHelpers.cmake +3 -3
- package/vendor/abseil-cpp/CMake/README.md +2 -2
- package/vendor/abseil-cpp/CMakeLists.txt +3 -3
- package/vendor/abseil-cpp/MODULE.bazel +6 -9
- package/vendor/abseil-cpp/README.md +6 -8
- package/vendor/abseil-cpp/absl/abseil.podspec.gen.py +6 -4
- package/vendor/abseil-cpp/absl/algorithm/BUILD.bazel +3 -0
- package/vendor/abseil-cpp/absl/algorithm/CMakeLists.txt +1 -0
- package/vendor/abseil-cpp/absl/algorithm/container.h +2 -19
- package/vendor/abseil-cpp/absl/algorithm/container_test.cc +4 -11
- package/vendor/abseil-cpp/absl/base/BUILD.bazel +60 -45
- package/vendor/abseil-cpp/absl/base/CMakeLists.txt +57 -38
- package/vendor/abseil-cpp/absl/base/attributes.h +76 -7
- package/vendor/abseil-cpp/absl/base/attributes_test.cc +43 -0
- package/vendor/abseil-cpp/absl/base/call_once.h +11 -12
- package/vendor/abseil-cpp/absl/base/config.h +22 -129
- package/vendor/abseil-cpp/absl/base/exception_safety_testing_test.cc +0 -4
- package/vendor/abseil-cpp/absl/base/{internal/fast_type_id.h → fast_type_id.h} +11 -16
- package/vendor/abseil-cpp/absl/base/{internal/fast_type_id_test.cc → fast_type_id_test.cc} +34 -30
- package/vendor/abseil-cpp/absl/base/internal/cycleclock.cc +0 -5
- package/vendor/abseil-cpp/absl/base/internal/cycleclock_config.h +7 -7
- package/vendor/abseil-cpp/absl/base/internal/endian.h +34 -38
- package/vendor/abseil-cpp/absl/base/internal/iterator_traits.h +71 -0
- package/vendor/abseil-cpp/absl/base/internal/iterator_traits_test.cc +85 -0
- package/vendor/abseil-cpp/absl/base/internal/iterator_traits_test_helper.h +97 -0
- package/vendor/abseil-cpp/absl/base/internal/low_level_alloc.cc +39 -9
- package/vendor/abseil-cpp/absl/base/internal/low_level_alloc.h +6 -0
- package/vendor/abseil-cpp/absl/base/internal/poison.cc +7 -6
- package/vendor/abseil-cpp/absl/base/internal/spinlock.cc +15 -28
- package/vendor/abseil-cpp/absl/base/internal/spinlock.h +65 -35
- package/vendor/abseil-cpp/absl/base/internal/spinlock_benchmark.cc +2 -2
- package/vendor/abseil-cpp/absl/base/internal/sysinfo_test.cc +2 -2
- package/vendor/abseil-cpp/absl/base/internal/thread_identity_benchmark.cc +1 -1
- package/vendor/abseil-cpp/absl/base/internal/thread_identity_test.cc +4 -4
- package/vendor/abseil-cpp/absl/base/internal/unaligned_access.h +6 -6
- package/vendor/abseil-cpp/absl/base/internal/unscaledcycleclock.cc +4 -0
- package/vendor/abseil-cpp/absl/base/internal/unscaledcycleclock.h +8 -3
- package/vendor/abseil-cpp/absl/base/no_destructor.h +11 -32
- package/vendor/abseil-cpp/absl/base/no_destructor_test.cc +0 -4
- package/vendor/abseil-cpp/absl/base/nullability.h +83 -72
- package/vendor/abseil-cpp/absl/base/nullability_test.cc +25 -64
- package/vendor/abseil-cpp/absl/base/options.h +3 -80
- package/vendor/abseil-cpp/absl/base/policy_checks.h +7 -7
- package/vendor/abseil-cpp/absl/base/raw_logging_test.cc +15 -0
- package/vendor/abseil-cpp/absl/base/spinlock_test_common.cc +50 -30
- package/vendor/abseil-cpp/absl/cleanup/BUILD.bazel +2 -1
- package/vendor/abseil-cpp/absl/cleanup/CMakeLists.txt +0 -1
- package/vendor/abseil-cpp/absl/cleanup/cleanup.h +1 -3
- package/vendor/abseil-cpp/absl/cleanup/cleanup_test.cc +0 -2
- package/vendor/abseil-cpp/absl/cleanup/internal/cleanup.h +3 -4
- package/vendor/abseil-cpp/absl/container/BUILD.bazel +74 -1
- package/vendor/abseil-cpp/absl/container/CMakeLists.txt +73 -0
- package/vendor/abseil-cpp/absl/container/btree_benchmark.cc +51 -9
- package/vendor/abseil-cpp/absl/container/btree_map.h +8 -6
- package/vendor/abseil-cpp/absl/container/btree_set.h +8 -6
- package/vendor/abseil-cpp/absl/container/btree_test.cc +89 -4
- package/vendor/abseil-cpp/absl/container/fixed_array.h +7 -15
- package/vendor/abseil-cpp/absl/container/fixed_array_test.cc +17 -0
- package/vendor/abseil-cpp/absl/container/flat_hash_map.h +20 -15
- package/vendor/abseil-cpp/absl/container/flat_hash_map_test.cc +8 -14
- package/vendor/abseil-cpp/absl/container/flat_hash_set.h +19 -14
- package/vendor/abseil-cpp/absl/container/flat_hash_set_test.cc +46 -0
- package/vendor/abseil-cpp/absl/container/inlined_vector.h +7 -6
- package/vendor/abseil-cpp/absl/container/inlined_vector_test.cc +28 -0
- package/vendor/abseil-cpp/absl/container/internal/btree.h +132 -29
- package/vendor/abseil-cpp/absl/container/internal/btree_container.h +175 -71
- package/vendor/abseil-cpp/absl/container/internal/common.h +43 -0
- package/vendor/abseil-cpp/absl/container/internal/common_policy_traits.h +1 -2
- package/vendor/abseil-cpp/absl/container/internal/compressed_tuple.h +28 -24
- package/vendor/abseil-cpp/absl/container/internal/compressed_tuple_test.cc +4 -17
- package/vendor/abseil-cpp/absl/container/internal/container_memory.h +80 -17
- package/vendor/abseil-cpp/absl/container/internal/container_memory_test.cc +32 -2
- package/vendor/abseil-cpp/absl/container/internal/hash_function_defaults.h +13 -8
- package/vendor/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc +1 -52
- package/vendor/abseil-cpp/absl/container/internal/hash_generator_testing.cc +9 -31
- package/vendor/abseil-cpp/absl/container/internal/hash_generator_testing.h +23 -32
- package/vendor/abseil-cpp/absl/container/internal/hash_policy_testing.h +5 -1
- package/vendor/abseil-cpp/absl/container/internal/hash_policy_traits.h +11 -23
- package/vendor/abseil-cpp/absl/container/internal/hash_policy_traits_test.cc +14 -9
- package/vendor/abseil-cpp/absl/container/internal/hashtable_control_bytes.h +516 -0
- package/vendor/abseil-cpp/absl/container/internal/hashtable_control_bytes_test.cc +259 -0
- package/vendor/abseil-cpp/absl/container/internal/hashtablez_sampler.cc +23 -6
- package/vendor/abseil-cpp/absl/container/internal/hashtablez_sampler.h +32 -13
- package/vendor/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc +8 -8
- package/vendor/abseil-cpp/absl/container/internal/inlined_vector.h +2 -7
- package/vendor/abseil-cpp/absl/container/internal/layout.h +26 -42
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_map.h +199 -68
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_set.cc +1506 -213
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_set.h +1095 -1658
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc +3 -2
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc +31 -29
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc +51 -20
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_resize_impl.h +79 -0
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_resize_impl_test.cc +66 -0
- package/vendor/abseil-cpp/absl/container/internal/raw_hash_set_test.cc +707 -363
- package/vendor/abseil-cpp/absl/container/node_hash_map.h +20 -15
- package/vendor/abseil-cpp/absl/container/node_hash_map_test.cc +0 -3
- package/vendor/abseil-cpp/absl/container/node_hash_set.h +18 -13
- package/vendor/abseil-cpp/absl/container/sample_element_size_test.cc +3 -8
- package/vendor/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake +1 -1
- package/vendor/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake +9 -20
- package/vendor/abseil-cpp/absl/copts/GENERATED_copts.bzl +9 -20
- package/vendor/abseil-cpp/absl/copts/copts.py +24 -15
- package/vendor/abseil-cpp/absl/crc/BUILD.bazel +3 -0
- package/vendor/abseil-cpp/absl/crc/crc32c.cc +0 -4
- package/vendor/abseil-cpp/absl/crc/crc32c.h +7 -5
- package/vendor/abseil-cpp/absl/crc/crc32c_benchmark.cc +17 -4
- package/vendor/abseil-cpp/absl/crc/crc32c_test.cc +30 -0
- package/vendor/abseil-cpp/absl/crc/internal/cpu_detect.cc +17 -0
- package/vendor/abseil-cpp/absl/crc/internal/cpu_detect.h +7 -1
- package/vendor/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h +0 -22
- package/vendor/abseil-cpp/absl/crc/internal/crc_memcpy_x86_arm_combined.cc +5 -0
- package/vendor/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc +136 -165
- package/vendor/abseil-cpp/absl/crc/internal/gen_crc32c_consts.py +90 -0
- package/vendor/abseil-cpp/absl/debugging/BUILD.bazel +7 -0
- package/vendor/abseil-cpp/absl/debugging/CMakeLists.txt +4 -0
- package/vendor/abseil-cpp/absl/debugging/internal/addresses.h +57 -0
- package/vendor/abseil-cpp/absl/debugging/internal/decode_rust_punycode.cc +1 -1
- package/vendor/abseil-cpp/absl/debugging/internal/decode_rust_punycode.h +5 -5
- package/vendor/abseil-cpp/absl/debugging/internal/demangle.cc +8 -35
- package/vendor/abseil-cpp/absl/debugging/internal/demangle_rust.cc +16 -16
- package/vendor/abseil-cpp/absl/debugging/internal/demangle_test.cc +11 -10
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc +40 -37
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc +16 -7
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_config.h +6 -5
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_emscripten-inl.inc +14 -5
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc +10 -4
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc +27 -16
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc +13 -4
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc +4 -3
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc +15 -28
- package/vendor/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc +25 -14
- package/vendor/abseil-cpp/absl/debugging/internal/vdso_support.cc +4 -0
- package/vendor/abseil-cpp/absl/debugging/stacktrace.cc +161 -27
- package/vendor/abseil-cpp/absl/debugging/stacktrace.h +73 -5
- package/vendor/abseil-cpp/absl/debugging/stacktrace_test.cc +435 -1
- package/vendor/abseil-cpp/absl/debugging/symbolize_elf.inc +55 -63
- package/vendor/abseil-cpp/absl/debugging/symbolize_emscripten.inc +3 -2
- package/vendor/abseil-cpp/absl/debugging/symbolize_win32.inc +25 -6
- package/vendor/abseil-cpp/absl/flags/BUILD.bazel +6 -0
- package/vendor/abseil-cpp/absl/flags/CMakeLists.txt +3 -0
- package/vendor/abseil-cpp/absl/flags/commandlineflag.h +2 -2
- package/vendor/abseil-cpp/absl/flags/flag.h +4 -3
- package/vendor/abseil-cpp/absl/flags/internal/commandlineflag.h +2 -2
- package/vendor/abseil-cpp/absl/flags/internal/flag.cc +14 -13
- package/vendor/abseil-cpp/absl/flags/internal/flag.h +34 -34
- package/vendor/abseil-cpp/absl/flags/internal/program_name.cc +2 -2
- package/vendor/abseil-cpp/absl/flags/internal/registry.h +4 -3
- package/vendor/abseil-cpp/absl/flags/internal/usage.cc +2 -2
- package/vendor/abseil-cpp/absl/flags/parse.cc +10 -6
- package/vendor/abseil-cpp/absl/flags/reflection.cc +9 -7
- package/vendor/abseil-cpp/absl/flags/usage.cc +2 -2
- package/vendor/abseil-cpp/absl/flags/usage_config.cc +2 -2
- package/vendor/abseil-cpp/absl/functional/BUILD.bazel +7 -6
- package/vendor/abseil-cpp/absl/functional/CMakeLists.txt +2 -4
- package/vendor/abseil-cpp/absl/functional/any_invocable.h +15 -15
- package/vendor/abseil-cpp/absl/functional/any_invocable_test.cc +10 -42
- package/vendor/abseil-cpp/absl/functional/function_ref.h +2 -9
- package/vendor/abseil-cpp/absl/functional/function_ref_test.cc +10 -0
- package/vendor/abseil-cpp/absl/functional/function_type_benchmark.cc +1 -1
- package/vendor/abseil-cpp/absl/functional/internal/any_invocable.h +112 -227
- package/vendor/abseil-cpp/absl/functional/internal/front_binder.h +10 -12
- package/vendor/abseil-cpp/absl/functional/internal/function_ref.h +2 -5
- package/vendor/abseil-cpp/absl/functional/overload.h +0 -20
- package/vendor/abseil-cpp/absl/functional/overload_test.cc +1 -7
- package/vendor/abseil-cpp/absl/hash/BUILD.bazel +16 -9
- package/vendor/abseil-cpp/absl/hash/CMakeLists.txt +6 -9
- package/vendor/abseil-cpp/absl/hash/hash.h +18 -0
- package/vendor/abseil-cpp/absl/hash/hash_benchmark.cc +3 -0
- package/vendor/abseil-cpp/absl/hash/hash_instantiated_test.cc +1 -1
- package/vendor/abseil-cpp/absl/hash/hash_test.cc +131 -30
- package/vendor/abseil-cpp/absl/hash/hash_testing.h +20 -20
- package/vendor/abseil-cpp/absl/hash/internal/hash.cc +129 -17
- package/vendor/abseil-cpp/absl/hash/internal/hash.h +326 -362
- package/vendor/abseil-cpp/absl/hash/internal/low_level_hash_test.cc +54 -151
- package/vendor/abseil-cpp/absl/hash/internal/spy_hash_state.h +14 -2
- package/vendor/abseil-cpp/absl/{strings/cord_buffer.cc → hash/internal/weakly_mixed_integer.h} +14 -6
- package/vendor/abseil-cpp/absl/log/BUILD.bazel +4 -0
- package/vendor/abseil-cpp/absl/log/CMakeLists.txt +7 -0
- package/vendor/abseil-cpp/absl/log/check.h +2 -1
- package/vendor/abseil-cpp/absl/log/check_test_impl.inc +308 -14
- package/vendor/abseil-cpp/absl/log/die_if_null.h +2 -2
- package/vendor/abseil-cpp/absl/log/flags_test.cc +7 -0
- package/vendor/abseil-cpp/absl/log/globals.h +4 -5
- package/vendor/abseil-cpp/absl/log/internal/BUILD.bazel +13 -9
- package/vendor/abseil-cpp/absl/log/internal/append_truncated.h +28 -0
- package/vendor/abseil-cpp/absl/log/internal/check_op.cc +24 -22
- package/vendor/abseil-cpp/absl/log/internal/check_op.h +149 -94
- package/vendor/abseil-cpp/absl/log/internal/conditions.cc +5 -3
- package/vendor/abseil-cpp/absl/log/internal/conditions.h +7 -2
- package/vendor/abseil-cpp/absl/log/internal/fnmatch_test.cc +1 -0
- package/vendor/abseil-cpp/absl/log/internal/log_message.cc +85 -43
- package/vendor/abseil-cpp/absl/log/internal/log_message.h +84 -59
- package/vendor/abseil-cpp/absl/log/internal/log_sink_set.cc +4 -4
- package/vendor/abseil-cpp/absl/log/internal/nullstream.h +1 -0
- package/vendor/abseil-cpp/absl/log/internal/proto.cc +3 -2
- package/vendor/abseil-cpp/absl/log/internal/proto.h +3 -3
- package/vendor/abseil-cpp/absl/log/internal/strip.h +4 -12
- package/vendor/abseil-cpp/absl/log/internal/structured.h +3 -7
- package/vendor/abseil-cpp/absl/log/internal/vlog_config.cc +9 -9
- package/vendor/abseil-cpp/absl/log/internal/vlog_config.h +8 -6
- package/vendor/abseil-cpp/absl/log/internal/voidify.h +10 -4
- package/vendor/abseil-cpp/absl/log/log.h +48 -35
- package/vendor/abseil-cpp/absl/log/log_basic_test_impl.inc +45 -0
- package/vendor/abseil-cpp/absl/log/log_entry.cc +241 -19
- package/vendor/abseil-cpp/absl/log/log_entry.h +2 -0
- package/vendor/abseil-cpp/absl/log/log_format_test.cc +412 -6
- package/vendor/abseil-cpp/absl/log/log_modifier_methods_test.cc +20 -0
- package/vendor/abseil-cpp/absl/log/log_sink_registry.h +2 -2
- package/vendor/abseil-cpp/absl/log/log_streamer_test.cc +15 -2
- package/vendor/abseil-cpp/absl/log/scoped_mock_log.h +7 -1
- package/vendor/abseil-cpp/absl/log/structured_test.cc +1 -0
- package/vendor/abseil-cpp/absl/memory/BUILD.bazel +2 -0
- package/vendor/abseil-cpp/absl/meta/BUILD.bazel +2 -0
- package/vendor/abseil-cpp/absl/meta/type_traits.h +46 -175
- package/vendor/abseil-cpp/absl/meta/type_traits_test.cc +1 -478
- package/vendor/abseil-cpp/absl/numeric/BUILD.bazel +7 -3
- package/vendor/abseil-cpp/absl/numeric/CMakeLists.txt +2 -0
- package/vendor/abseil-cpp/absl/numeric/bits.h +68 -2
- package/vendor/abseil-cpp/absl/numeric/bits_benchmark.cc +1 -1
- package/vendor/abseil-cpp/absl/numeric/bits_test.cc +83 -0
- package/vendor/abseil-cpp/absl/numeric/int128.cc +0 -52
- package/vendor/abseil-cpp/absl/numeric/int128_benchmark.cc +14 -15
- package/vendor/abseil-cpp/absl/numeric/int128_test.cc +13 -8
- package/vendor/abseil-cpp/absl/numeric/internal/bits.h +39 -7
- package/vendor/abseil-cpp/absl/profiling/BUILD.bazel +47 -0
- package/vendor/abseil-cpp/absl/profiling/CMakeLists.txt +38 -0
- package/vendor/abseil-cpp/absl/profiling/hashtable.cc +124 -0
- package/vendor/abseil-cpp/absl/profiling/hashtable.h +40 -0
- package/vendor/abseil-cpp/absl/profiling/internal/exponential_biased.cc +1 -1
- package/vendor/abseil-cpp/absl/profiling/internal/profile_builder.cc +462 -0
- package/vendor/abseil-cpp/absl/profiling/internal/profile_builder.h +138 -0
- package/vendor/abseil-cpp/absl/profiling/internal/sample_recorder.h +9 -9
- package/vendor/abseil-cpp/absl/profiling/internal/sample_recorder_test.cc +7 -3
- package/vendor/abseil-cpp/absl/random/BUILD.bazel +6 -4
- package/vendor/abseil-cpp/absl/random/CMakeLists.txt +20 -19
- package/vendor/abseil-cpp/absl/random/benchmarks.cc +16 -23
- package/vendor/abseil-cpp/absl/random/bit_gen_ref.h +10 -11
- package/vendor/abseil-cpp/absl/random/bit_gen_ref_test.cc +7 -2
- package/vendor/abseil-cpp/absl/random/distributions.h +6 -8
- package/vendor/abseil-cpp/absl/random/gaussian_distribution.h +1 -1
- package/vendor/abseil-cpp/absl/random/internal/BUILD.bazel +19 -20
- package/vendor/abseil-cpp/absl/random/internal/distribution_caller.h +5 -6
- package/vendor/abseil-cpp/absl/random/internal/{pool_urbg.cc → entropy_pool.cc} +24 -92
- package/vendor/abseil-cpp/absl/{base/inline_variable_test_b.cc → random/internal/entropy_pool.h} +14 -6
- package/vendor/abseil-cpp/absl/random/internal/entropy_pool_test.cc +119 -0
- package/vendor/abseil-cpp/absl/random/internal/mock_helpers.h +6 -7
- package/vendor/abseil-cpp/absl/random/internal/nonsecure_base.h +5 -6
- package/vendor/abseil-cpp/absl/random/internal/nonsecure_base_test.cc +39 -0
- package/vendor/abseil-cpp/absl/random/internal/randen_benchmarks.cc +8 -6
- package/vendor/abseil-cpp/absl/random/internal/randen_detect.cc +1 -1
- package/vendor/abseil-cpp/absl/random/internal/seed_material.cc +20 -12
- package/vendor/abseil-cpp/absl/random/internal/seed_material.h +5 -5
- package/vendor/abseil-cpp/absl/random/internal/seed_material_test.cc +3 -0
- package/vendor/abseil-cpp/absl/random/mock_distributions_test.cc +5 -4
- package/vendor/abseil-cpp/absl/random/mocking_bit_gen.h +8 -10
- package/vendor/abseil-cpp/absl/random/random.h +88 -53
- package/vendor/abseil-cpp/absl/random/seed_sequences.cc +6 -2
- package/vendor/abseil-cpp/absl/status/BUILD.bazel +26 -0
- package/vendor/abseil-cpp/absl/status/internal/status_internal.cc +3 -4
- package/vendor/abseil-cpp/absl/status/internal/status_internal.h +3 -4
- package/vendor/abseil-cpp/absl/status/internal/status_matchers.cc +4 -3
- package/vendor/abseil-cpp/absl/status/internal/statusor_internal.h +194 -32
- package/vendor/abseil-cpp/absl/status/status.cc +4 -8
- package/vendor/abseil-cpp/absl/status/status.h +8 -8
- package/vendor/abseil-cpp/absl/{base/inline_variable_test_a.cc → status/status_benchmark.cc} +20 -10
- package/vendor/abseil-cpp/absl/status/status_matchers_test.cc +65 -0
- package/vendor/abseil-cpp/absl/status/status_payload_printer.h +2 -2
- package/vendor/abseil-cpp/absl/status/statusor.cc +2 -2
- package/vendor/abseil-cpp/absl/status/statusor.h +49 -102
- package/vendor/abseil-cpp/absl/status/statusor_benchmark.cc +480 -0
- package/vendor/abseil-cpp/absl/status/statusor_test.cc +323 -1
- package/vendor/abseil-cpp/absl/strings/BUILD.bazel +70 -34
- package/vendor/abseil-cpp/absl/strings/CMakeLists.txt +6 -3
- package/vendor/abseil-cpp/absl/strings/ascii.cc +9 -9
- package/vendor/abseil-cpp/absl/strings/ascii.h +18 -18
- package/vendor/abseil-cpp/absl/strings/ascii_benchmark.cc +5 -8
- package/vendor/abseil-cpp/absl/strings/charconv.cc +21 -22
- package/vendor/abseil-cpp/absl/strings/charconv.h +5 -5
- package/vendor/abseil-cpp/absl/strings/charconv_benchmark.cc +1 -2
- package/vendor/abseil-cpp/absl/strings/charset_benchmark.cc +1 -1
- package/vendor/abseil-cpp/absl/strings/cord.cc +54 -58
- package/vendor/abseil-cpp/absl/strings/cord.h +94 -84
- package/vendor/abseil-cpp/absl/strings/cord_analysis.cc +11 -11
- package/vendor/abseil-cpp/absl/strings/cord_analysis.h +3 -3
- package/vendor/abseil-cpp/absl/strings/cord_test.cc +23 -0
- package/vendor/abseil-cpp/absl/strings/cordz_test_helpers.h +4 -5
- package/vendor/abseil-cpp/absl/strings/escaping.cc +130 -149
- package/vendor/abseil-cpp/absl/strings/escaping.h +9 -10
- package/vendor/abseil-cpp/absl/strings/escaping_benchmark.cc +2 -3
- package/vendor/abseil-cpp/absl/strings/escaping_test.cc +19 -9
- package/vendor/abseil-cpp/absl/strings/internal/charconv_bigint.cc +1 -1
- package/vendor/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc +1 -1
- package/vendor/abseil-cpp/absl/strings/internal/cord_internal.h +6 -10
- package/vendor/abseil-cpp/absl/strings/internal/cord_rep_btree.cc +0 -4
- package/vendor/abseil-cpp/absl/strings/internal/cordz_handle.cc +6 -6
- package/vendor/abseil-cpp/absl/strings/internal/cordz_info.cc +5 -9
- package/vendor/abseil-cpp/absl/strings/internal/cordz_info.h +2 -4
- package/vendor/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance_benchmark.cc +56 -0
- package/vendor/abseil-cpp/absl/strings/internal/memutil_benchmark.cc +2 -3
- package/vendor/abseil-cpp/absl/strings/internal/ostringstream_benchmark.cc +1 -2
- package/vendor/abseil-cpp/absl/strings/internal/str_format/arg.cc +7 -63
- package/vendor/abseil-cpp/absl/strings/internal/str_format/arg.h +1 -11
- package/vendor/abseil-cpp/absl/strings/internal/str_format/convert_test.cc +1 -6
- package/vendor/abseil-cpp/absl/strings/internal/str_format/extension.cc +0 -22
- package/vendor/abseil-cpp/absl/strings/internal/str_format/extension_test.cc +3 -2
- package/vendor/abseil-cpp/absl/strings/internal/str_format/output.cc +5 -3
- package/vendor/abseil-cpp/absl/strings/internal/str_format/parser.h +4 -2
- package/vendor/abseil-cpp/absl/strings/internal/str_join_internal.h +3 -3
- package/vendor/abseil-cpp/absl/strings/internal/str_split_internal.h +7 -2
- package/vendor/abseil-cpp/absl/strings/internal/string_constant.h +0 -5
- package/vendor/abseil-cpp/absl/strings/internal/utf8.cc +96 -1
- package/vendor/abseil-cpp/absl/strings/internal/utf8.h +15 -1
- package/vendor/abseil-cpp/absl/strings/internal/utf8_test.cc +196 -3
- package/vendor/abseil-cpp/absl/strings/numbers.cc +53 -32
- package/vendor/abseil-cpp/absl/strings/numbers.h +87 -58
- package/vendor/abseil-cpp/absl/strings/numbers_benchmark.cc +1 -1
- package/vendor/abseil-cpp/absl/strings/numbers_test.cc +634 -120
- package/vendor/abseil-cpp/absl/strings/str_cat.cc +6 -7
- package/vendor/abseil-cpp/absl/strings/str_cat.h +32 -32
- package/vendor/abseil-cpp/absl/strings/str_cat_benchmark.cc +25 -1
- package/vendor/abseil-cpp/absl/strings/str_cat_test.cc +2 -7
- package/vendor/abseil-cpp/absl/strings/str_format.h +18 -18
- package/vendor/abseil-cpp/absl/strings/str_format_test.cc +8 -14
- package/vendor/abseil-cpp/absl/strings/str_join_benchmark.cc +2 -3
- package/vendor/abseil-cpp/absl/strings/str_replace.cc +3 -3
- package/vendor/abseil-cpp/absl/strings/str_replace.h +6 -6
- package/vendor/abseil-cpp/absl/strings/str_replace_benchmark.cc +2 -3
- package/vendor/abseil-cpp/absl/strings/str_split.h +2 -2
- package/vendor/abseil-cpp/absl/strings/str_split_benchmark.cc +2 -3
- package/vendor/abseil-cpp/absl/strings/string_view.cc +4 -9
- package/vendor/abseil-cpp/absl/strings/string_view.h +38 -39
- package/vendor/abseil-cpp/absl/strings/string_view_benchmark.cc +4 -6
- package/vendor/abseil-cpp/absl/strings/string_view_test.cc +2 -50
- package/vendor/abseil-cpp/absl/strings/strip.h +4 -4
- package/vendor/abseil-cpp/absl/strings/substitute.cc +5 -4
- package/vendor/abseil-cpp/absl/strings/substitute.h +66 -64
- package/vendor/abseil-cpp/absl/strings/substitute_benchmark.cc +158 -0
- package/vendor/abseil-cpp/absl/synchronization/BUILD.bazel +6 -1
- package/vendor/abseil-cpp/absl/synchronization/CMakeLists.txt +2 -1
- package/vendor/abseil-cpp/absl/synchronization/barrier.cc +1 -1
- package/vendor/abseil-cpp/absl/synchronization/barrier_test.cc +3 -3
- package/vendor/abseil-cpp/absl/synchronization/blocking_counter.cc +2 -2
- package/vendor/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc +3 -3
- package/vendor/abseil-cpp/absl/synchronization/internal/futex_waiter.cc +0 -4
- package/vendor/abseil-cpp/absl/synchronization/internal/graphcycles.cc +30 -33
- package/vendor/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc +2 -3
- package/vendor/abseil-cpp/absl/synchronization/internal/graphcycles_test.cc +6 -5
- package/vendor/abseil-cpp/absl/synchronization/internal/kernel_timeout.cc +0 -5
- package/vendor/abseil-cpp/absl/synchronization/internal/pthread_waiter.cc +0 -4
- package/vendor/abseil-cpp/absl/synchronization/internal/sem_waiter.cc +0 -4
- package/vendor/abseil-cpp/absl/synchronization/internal/stdcpp_waiter.cc +0 -4
- package/vendor/abseil-cpp/absl/synchronization/internal/thread_pool.h +3 -3
- package/vendor/abseil-cpp/absl/synchronization/internal/waiter_base.cc +0 -4
- package/vendor/abseil-cpp/absl/synchronization/internal/waiter_test.cc +12 -3
- package/vendor/abseil-cpp/absl/synchronization/internal/win32_waiter.cc +0 -4
- package/vendor/abseil-cpp/absl/synchronization/lifetime_test.cc +4 -4
- package/vendor/abseil-cpp/absl/synchronization/mutex.cc +27 -29
- package/vendor/abseil-cpp/absl/synchronization/mutex.h +205 -126
- package/vendor/abseil-cpp/absl/synchronization/mutex_benchmark.cc +13 -31
- package/vendor/abseil-cpp/absl/synchronization/mutex_test.cc +183 -169
- package/vendor/abseil-cpp/absl/synchronization/notification.cc +5 -5
- package/vendor/abseil-cpp/absl/synchronization/notification.h +1 -1
- package/vendor/abseil-cpp/absl/synchronization/notification_test.cc +3 -3
- package/vendor/abseil-cpp/absl/time/BUILD.bazel +9 -1
- package/vendor/abseil-cpp/absl/time/CMakeLists.txt +3 -1
- package/vendor/abseil-cpp/absl/time/civil_time.cc +1 -0
- package/vendor/abseil-cpp/absl/time/civil_time_test.cc +134 -0
- package/vendor/abseil-cpp/absl/time/clock.cc +11 -14
- package/vendor/abseil-cpp/absl/time/duration.cc +14 -9
- package/vendor/abseil-cpp/absl/time/duration_test.cc +6 -7
- package/vendor/abseil-cpp/absl/time/internal/cctz/BUILD.bazel +14 -3
- package/vendor/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h +12 -0
- package/vendor/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h +1 -1
- package/vendor/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc +4 -490
- package/vendor/abseil-cpp/absl/time/internal/cctz/src/test_time_zone_names.cc +515 -0
- package/vendor/abseil-cpp/absl/time/internal/cctz/src/test_time_zone_names.h +33 -0
- package/vendor/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc +41 -4
- package/vendor/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc +22 -23
- package/vendor/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc +90 -111
- package/vendor/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc +1 -488
- package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/version +1 -1
- package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Coyhaique +0 -0
- package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran +0 -0
- package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iran +0 -0
- package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab +2 -1
- package/vendor/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab +1 -1
- package/vendor/abseil-cpp/absl/time/time.h +24 -18
- package/vendor/abseil-cpp/absl/time/time_test.cc +26 -0
- package/vendor/abseil-cpp/absl/types/BUILD.bazel +11 -164
- package/vendor/abseil-cpp/absl/types/CMakeLists.txt +23 -167
- package/vendor/abseil-cpp/absl/types/any.h +9 -484
- package/vendor/abseil-cpp/absl/types/optional.h +7 -747
- package/vendor/abseil-cpp/absl/types/span.h +46 -19
- package/vendor/abseil-cpp/absl/types/span_test.cc +27 -0
- package/vendor/abseil-cpp/absl/types/variant.h +5 -784
- package/vendor/abseil-cpp/absl/types/variant_test.cc +43 -2597
- package/vendor/abseil-cpp/absl/utility/BUILD.bazel +1 -41
- package/vendor/abseil-cpp/absl/utility/CMakeLists.txt +0 -40
- package/vendor/abseil-cpp/absl/utility/utility.h +10 -185
- package/vendor/abseil-cpp/ci/absl_alternate_options.h +2 -3
- package/vendor/abseil-cpp/ci/cmake_common.sh +2 -2
- package/vendor/abseil-cpp/ci/linux_arm_clang-latest_libcxx_bazel.sh +12 -13
- package/vendor/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh +24 -21
- package/vendor/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh +12 -12
- package/vendor/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh +23 -22
- package/vendor/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh +20 -19
- package/vendor/abseil-cpp/ci/linux_docker_containers.sh +4 -4
- package/vendor/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh +17 -17
- package/vendor/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh +10 -10
- package/vendor/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh +1 -1
- package/vendor/abseil-cpp/ci/linux_gcc_alpine_cmake.sh +1 -1
- package/vendor/abseil-cpp/ci/macos_xcode_bazel.sh +9 -10
- package/vendor/abseil-cpp/ci/macos_xcode_cmake.sh +9 -1
- package/vendor/abseil-cpp/ci/windows_clangcl_bazel.bat +14 -6
- package/vendor/abseil-cpp/ci/windows_msvc_bazel.bat +14 -6
- package/vendor/abseil-cpp/ci/windows_msvc_cmake.bat +1 -1
- package/vendor/re2/.bazelrc +4 -4
- package/vendor/re2/.bcr/metadata.template.json +16 -0
- package/vendor/re2/.bcr/presubmit.yml +57 -0
- package/vendor/re2/.bcr/source.template.json +5 -0
- package/vendor/re2/.github/bazel.sh +1 -7
- package/vendor/re2/.github/workflows/ci-bazel.yml +5 -5
- package/vendor/re2/.github/workflows/ci-cmake.yml +4 -4
- package/vendor/re2/.github/workflows/ci.yml +5 -6
- package/vendor/re2/.github/workflows/pages.yml +3 -3
- package/vendor/re2/.github/workflows/python.yml +29 -24
- package/vendor/re2/.github/workflows/release-bazel.yml +42 -0
- package/vendor/re2/.github/workflows/release.yml +15 -4
- package/vendor/re2/BUILD.bazel +25 -0
- package/vendor/re2/CMakeLists.txt +100 -85
- package/vendor/re2/CONTRIBUTING.md +0 -1
- package/vendor/re2/MODULE.bazel +10 -10
- package/vendor/re2/Makefile +1 -1
- package/vendor/re2/README.md +259 -0
- package/vendor/re2/python/BUILD.bazel +8 -0
- package/vendor/re2/python/re2.py +1 -1
- package/vendor/re2/python/re2_test.py +6 -0
- package/vendor/re2/python/setup.py +3 -3
- package/vendor/re2/re2/bitmap256.cc +3 -4
- package/vendor/re2/re2/bitstate.cc +15 -10
- package/vendor/re2/re2/dfa.cc +1 -2
- package/vendor/re2/re2/parse.cc +3 -4
- package/vendor/re2/re2/prog.cc +1 -2
- package/vendor/re2/re2/prog.h +1 -0
- package/vendor/re2/re2/re2.cc +5 -0
- package/vendor/re2/re2/re2.h +9 -9
- package/vendor/re2/re2/set.cc +6 -0
- package/vendor/re2/re2/set.h +5 -0
- package/vendor/re2/re2/testing/re2_arg_test.cc +3 -3
- package/vendor/re2/re2/testing/re2_test.cc +8 -0
- package/vendor/re2/re2/testing/set_test.cc +5 -0
- package/vendor/re2/re2/walker-inl.h +1 -1
- package/vendor/abseil-cpp/WORKSPACE +0 -76
- package/vendor/abseil-cpp/WORKSPACE.bzlmod +0 -19
- package/vendor/abseil-cpp/absl/base/inline_variable_test.cc +0 -64
- package/vendor/abseil-cpp/absl/base/internal/inline_variable.h +0 -108
- package/vendor/abseil-cpp/absl/base/internal/inline_variable_testing.h +0 -46
- package/vendor/abseil-cpp/absl/base/internal/invoke.h +0 -241
- package/vendor/abseil-cpp/absl/base/internal/nullability_impl.h +0 -69
- package/vendor/abseil-cpp/absl/base/invoke_test.cc +0 -331
- package/vendor/abseil-cpp/absl/hash/internal/low_level_hash.cc +0 -148
- package/vendor/abseil-cpp/absl/hash/internal/low_level_hash.h +0 -54
- package/vendor/abseil-cpp/absl/random/internal/pool_urbg.h +0 -131
- package/vendor/abseil-cpp/absl/random/internal/pool_urbg_test.cc +0 -182
- package/vendor/abseil-cpp/absl/types/any_exception_safety_test.cc +0 -173
- package/vendor/abseil-cpp/absl/types/any_test.cc +0 -778
- package/vendor/abseil-cpp/absl/types/bad_any_cast.cc +0 -64
- package/vendor/abseil-cpp/absl/types/bad_any_cast.h +0 -75
- package/vendor/abseil-cpp/absl/types/bad_optional_access.cc +0 -66
- package/vendor/abseil-cpp/absl/types/bad_optional_access.h +0 -78
- package/vendor/abseil-cpp/absl/types/bad_variant_access.cc +0 -82
- package/vendor/abseil-cpp/absl/types/bad_variant_access.h +0 -82
- package/vendor/abseil-cpp/absl/types/internal/optional.h +0 -352
- package/vendor/abseil-cpp/absl/types/internal/variant.h +0 -1622
- package/vendor/abseil-cpp/absl/types/optional_exception_safety_test.cc +0 -292
- package/vendor/abseil-cpp/absl/types/optional_test.cc +0 -1615
- package/vendor/abseil-cpp/absl/types/variant_benchmark.cc +0 -222
- package/vendor/abseil-cpp/absl/types/variant_exception_safety_test.cc +0 -532
- package/vendor/abseil-cpp/absl/utility/internal/if_constexpr.h +0 -70
- package/vendor/abseil-cpp/absl/utility/internal/if_constexpr_test.cc +0 -79
- package/vendor/abseil-cpp/absl/utility/utility_test.cc +0 -239
- package/vendor/re2/.github/workflows/pr.yml +0 -34
- package/vendor/re2/README +0 -47
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
#include <algorithm>
|
|
18
18
|
#include <array>
|
|
19
19
|
#include <atomic>
|
|
20
|
+
#include <bitset>
|
|
20
21
|
#include <cmath>
|
|
21
22
|
#include <cstddef>
|
|
22
23
|
#include <cstdint>
|
|
24
|
+
#include <cstring>
|
|
23
25
|
#include <deque>
|
|
24
26
|
#include <functional>
|
|
25
27
|
#include <iostream>
|
|
@@ -51,8 +53,11 @@
|
|
|
51
53
|
#include "absl/container/internal/container_memory.h"
|
|
52
54
|
#include "absl/container/internal/hash_function_defaults.h"
|
|
53
55
|
#include "absl/container/internal/hash_policy_testing.h"
|
|
56
|
+
#include "absl/random/random.h"
|
|
57
|
+
#include "absl/container/internal/hashtable_control_bytes.h"
|
|
54
58
|
#include "absl/container/internal/hashtable_debug.h"
|
|
55
59
|
#include "absl/container/internal/hashtablez_sampler.h"
|
|
60
|
+
#include "absl/container/internal/raw_hash_set_resize_impl.h"
|
|
56
61
|
#include "absl/container/internal/test_allocator.h"
|
|
57
62
|
#include "absl/container/internal/test_instance_tracker.h"
|
|
58
63
|
#include "absl/container/node_hash_set.h"
|
|
@@ -62,6 +67,7 @@
|
|
|
62
67
|
#include "absl/log/log.h"
|
|
63
68
|
#include "absl/memory/memory.h"
|
|
64
69
|
#include "absl/meta/type_traits.h"
|
|
70
|
+
#include "absl/numeric/int128.h"
|
|
65
71
|
#include "absl/strings/str_cat.h"
|
|
66
72
|
#include "absl/strings/string_view.h"
|
|
67
73
|
#include "absl/types/optional.h"
|
|
@@ -72,8 +78,8 @@ namespace container_internal {
|
|
|
72
78
|
|
|
73
79
|
struct RawHashSetTestOnlyAccess {
|
|
74
80
|
template <typename C>
|
|
75
|
-
static auto GetCommon(
|
|
76
|
-
return c.common();
|
|
81
|
+
static auto GetCommon(C&& c) -> decltype(std::forward<C>(c).common()) {
|
|
82
|
+
return std::forward<C>(c).common();
|
|
77
83
|
}
|
|
78
84
|
template <typename C>
|
|
79
85
|
static auto GetSlots(const C& c) -> decltype(c.slot_array()) {
|
|
@@ -88,16 +94,33 @@ struct RawHashSetTestOnlyAccess {
|
|
|
88
94
|
namespace {
|
|
89
95
|
|
|
90
96
|
using ::testing::ElementsAre;
|
|
91
|
-
using ::testing::ElementsAreArray;
|
|
92
97
|
using ::testing::Eq;
|
|
93
98
|
using ::testing::Ge;
|
|
94
99
|
using ::testing::Lt;
|
|
95
100
|
using ::testing::Pair;
|
|
96
101
|
using ::testing::UnorderedElementsAre;
|
|
102
|
+
using ::testing::UnorderedElementsAreArray;
|
|
97
103
|
|
|
98
104
|
// Convenience function to static cast to ctrl_t.
|
|
99
105
|
ctrl_t CtrlT(int i) { return static_cast<ctrl_t>(i); }
|
|
100
106
|
|
|
107
|
+
// Enables sampling with 1 percent sampling rate and
|
|
108
|
+
// resets the rate counter for the current thread.
|
|
109
|
+
void SetSamplingRateTo1Percent() {
|
|
110
|
+
SetHashtablezEnabled(true);
|
|
111
|
+
SetHashtablezSampleParameter(100); // Sample ~1% of tables.
|
|
112
|
+
// Reset rate counter for the current thread.
|
|
113
|
+
TestOnlyRefreshSamplingStateForCurrentThread();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Disables sampling and resets the rate counter for the current thread.
|
|
117
|
+
void DisableSampling() {
|
|
118
|
+
SetHashtablezEnabled(false);
|
|
119
|
+
SetHashtablezSampleParameter(1 << 16);
|
|
120
|
+
// Reset rate counter for the current thread.
|
|
121
|
+
TestOnlyRefreshSamplingStateForCurrentThread();
|
|
122
|
+
}
|
|
123
|
+
|
|
101
124
|
TEST(GrowthInfoTest, GetGrowthLeft) {
|
|
102
125
|
GrowthInfo gi;
|
|
103
126
|
gi.InitGrowthLeftNoDeleted(5);
|
|
@@ -186,6 +209,60 @@ TEST(GrowthInfoTest, OverwriteControlAsFull) {
|
|
|
186
209
|
EXPECT_FALSE(gi.HasNoDeleted());
|
|
187
210
|
}
|
|
188
211
|
|
|
212
|
+
TEST(GrowthInfoTest, HasNoGrowthLeftAssumingMayHaveDeleted) {
|
|
213
|
+
GrowthInfo gi;
|
|
214
|
+
gi.InitGrowthLeftNoDeleted(1);
|
|
215
|
+
gi.OverwriteFullAsDeleted();
|
|
216
|
+
EXPECT_EQ(gi.GetGrowthLeft(), 1);
|
|
217
|
+
EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
|
|
218
|
+
gi.OverwriteControlAsFull(ctrl_t::kDeleted);
|
|
219
|
+
EXPECT_EQ(gi.GetGrowthLeft(), 1);
|
|
220
|
+
EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
|
|
221
|
+
gi.OverwriteFullAsEmpty();
|
|
222
|
+
EXPECT_EQ(gi.GetGrowthLeft(), 2);
|
|
223
|
+
EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
|
|
224
|
+
gi.OverwriteEmptyAsFull();
|
|
225
|
+
EXPECT_EQ(gi.GetGrowthLeft(), 1);
|
|
226
|
+
EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
|
|
227
|
+
gi.OverwriteEmptyAsFull();
|
|
228
|
+
EXPECT_EQ(gi.GetGrowthLeft(), 0);
|
|
229
|
+
EXPECT_TRUE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
TEST(Util, OptimalMemcpySizeForSooSlotTransfer) {
|
|
233
|
+
EXPECT_EQ(1, OptimalMemcpySizeForSooSlotTransfer(1));
|
|
234
|
+
ASSERT_EQ(4, OptimalMemcpySizeForSooSlotTransfer(2));
|
|
235
|
+
ASSERT_EQ(4, OptimalMemcpySizeForSooSlotTransfer(3));
|
|
236
|
+
for (size_t slot_size = 4; slot_size <= 8; ++slot_size) {
|
|
237
|
+
ASSERT_EQ(8, OptimalMemcpySizeForSooSlotTransfer(slot_size));
|
|
238
|
+
}
|
|
239
|
+
// If maximum amount of memory is 16, then we can copy up to 16 bytes.
|
|
240
|
+
for (size_t slot_size = 9; slot_size <= 16; ++slot_size) {
|
|
241
|
+
ASSERT_EQ(16,
|
|
242
|
+
OptimalMemcpySizeForSooSlotTransfer(slot_size,
|
|
243
|
+
/*max_soo_slot_size=*/16));
|
|
244
|
+
ASSERT_EQ(16,
|
|
245
|
+
OptimalMemcpySizeForSooSlotTransfer(slot_size,
|
|
246
|
+
/*max_soo_slot_size=*/24));
|
|
247
|
+
}
|
|
248
|
+
// But we shouldn't try to copy more than maximum amount of memory.
|
|
249
|
+
for (size_t slot_size = 9; slot_size <= 12; ++slot_size) {
|
|
250
|
+
ASSERT_EQ(12, OptimalMemcpySizeForSooSlotTransfer(
|
|
251
|
+
slot_size, /*max_soo_slot_size=*/12));
|
|
252
|
+
}
|
|
253
|
+
for (size_t slot_size = 17; slot_size <= 24; ++slot_size) {
|
|
254
|
+
ASSERT_EQ(24,
|
|
255
|
+
OptimalMemcpySizeForSooSlotTransfer(slot_size,
|
|
256
|
+
/*max_soo_slot_size=*/24));
|
|
257
|
+
}
|
|
258
|
+
// We shouldn't copy more than maximum.
|
|
259
|
+
for (size_t slot_size = 17; slot_size <= 20; ++slot_size) {
|
|
260
|
+
ASSERT_EQ(20,
|
|
261
|
+
OptimalMemcpySizeForSooSlotTransfer(slot_size,
|
|
262
|
+
/*max_soo_slot_size=*/20));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
189
266
|
TEST(Util, NormalizeCapacity) {
|
|
190
267
|
EXPECT_EQ(1, NormalizeCapacity(0));
|
|
191
268
|
EXPECT_EQ(1, NormalizeCapacity(1));
|
|
@@ -202,9 +279,14 @@ TEST(Util, NormalizeCapacity) {
|
|
|
202
279
|
TEST(Util, GrowthAndCapacity) {
|
|
203
280
|
// Verify that GrowthToCapacity gives the minimum capacity that has enough
|
|
204
281
|
// growth.
|
|
205
|
-
|
|
282
|
+
EXPECT_EQ(SizeToCapacity(0), 0);
|
|
283
|
+
EXPECT_EQ(SizeToCapacity(1), 1);
|
|
284
|
+
EXPECT_EQ(SizeToCapacity(2), 3);
|
|
285
|
+
EXPECT_EQ(SizeToCapacity(3), 3);
|
|
286
|
+
for (size_t growth = 1; growth < 10000; ++growth) {
|
|
206
287
|
SCOPED_TRACE(growth);
|
|
207
|
-
size_t capacity =
|
|
288
|
+
size_t capacity = SizeToCapacity(growth);
|
|
289
|
+
ASSERT_TRUE(IsValidCapacity(capacity));
|
|
208
290
|
// The capacity is large enough for `growth`.
|
|
209
291
|
EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth));
|
|
210
292
|
// For (capacity+1) < kWidth, growth should equal capacity.
|
|
@@ -224,8 +306,8 @@ TEST(Util, GrowthAndCapacity) {
|
|
|
224
306
|
SCOPED_TRACE(capacity);
|
|
225
307
|
size_t growth = CapacityToGrowth(capacity);
|
|
226
308
|
EXPECT_THAT(growth, Lt(capacity));
|
|
227
|
-
|
|
228
|
-
EXPECT_EQ(NormalizeCapacity(
|
|
309
|
+
EXPECT_EQ(SizeToCapacity(growth), capacity);
|
|
310
|
+
EXPECT_EQ(NormalizeCapacity(SizeToCapacity(growth)), capacity);
|
|
229
311
|
}
|
|
230
312
|
}
|
|
231
313
|
|
|
@@ -244,203 +326,6 @@ TEST(Util, probe_seq) {
|
|
|
244
326
|
EXPECT_THAT(offsets, ElementsAre(0, 16, 48, 96, 32, 112, 80, 64));
|
|
245
327
|
}
|
|
246
328
|
|
|
247
|
-
TEST(BitMask, Smoke) {
|
|
248
|
-
EXPECT_FALSE((BitMask<uint8_t, 8>(0)));
|
|
249
|
-
EXPECT_TRUE((BitMask<uint8_t, 8>(5)));
|
|
250
|
-
|
|
251
|
-
EXPECT_THAT((BitMask<uint8_t, 8>(0)), ElementsAre());
|
|
252
|
-
EXPECT_THAT((BitMask<uint8_t, 8>(0x1)), ElementsAre(0));
|
|
253
|
-
EXPECT_THAT((BitMask<uint8_t, 8>(0x2)), ElementsAre(1));
|
|
254
|
-
EXPECT_THAT((BitMask<uint8_t, 8>(0x3)), ElementsAre(0, 1));
|
|
255
|
-
EXPECT_THAT((BitMask<uint8_t, 8>(0x4)), ElementsAre(2));
|
|
256
|
-
EXPECT_THAT((BitMask<uint8_t, 8>(0x5)), ElementsAre(0, 2));
|
|
257
|
-
EXPECT_THAT((BitMask<uint8_t, 8>(0x55)), ElementsAre(0, 2, 4, 6));
|
|
258
|
-
EXPECT_THAT((BitMask<uint8_t, 8>(0xAA)), ElementsAre(1, 3, 5, 7));
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
TEST(BitMask, WithShift_MatchPortable) {
|
|
262
|
-
// See the non-SSE version of Group for details on what this math is for.
|
|
263
|
-
uint64_t ctrl = 0x1716151413121110;
|
|
264
|
-
uint64_t hash = 0x12;
|
|
265
|
-
constexpr uint64_t lsbs = 0x0101010101010101ULL;
|
|
266
|
-
auto x = ctrl ^ (lsbs * hash);
|
|
267
|
-
uint64_t mask = (x - lsbs) & ~x & kMsbs8Bytes;
|
|
268
|
-
EXPECT_EQ(0x0000000080800000, mask);
|
|
269
|
-
|
|
270
|
-
BitMask<uint64_t, 8, 3> b(mask);
|
|
271
|
-
EXPECT_EQ(*b, 2);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
constexpr uint64_t kSome8BytesMask = /* */ 0x8000808080008000ULL;
|
|
275
|
-
constexpr uint64_t kSome8BytesMaskAllOnes = 0xff00ffffff00ff00ULL;
|
|
276
|
-
constexpr auto kSome8BytesMaskBits = std::array<int, 5>{1, 3, 4, 5, 7};
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
TEST(BitMask, WithShift_FullMask) {
|
|
280
|
-
EXPECT_THAT((BitMask<uint64_t, 8, 3>(kMsbs8Bytes)),
|
|
281
|
-
ElementsAre(0, 1, 2, 3, 4, 5, 6, 7));
|
|
282
|
-
EXPECT_THAT(
|
|
283
|
-
(BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(kMsbs8Bytes)),
|
|
284
|
-
ElementsAre(0, 1, 2, 3, 4, 5, 6, 7));
|
|
285
|
-
EXPECT_THAT(
|
|
286
|
-
(BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(~uint64_t{0})),
|
|
287
|
-
ElementsAre(0, 1, 2, 3, 4, 5, 6, 7));
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
TEST(BitMask, WithShift_EmptyMask) {
|
|
291
|
-
EXPECT_THAT((BitMask<uint64_t, 8, 3>(0)), ElementsAre());
|
|
292
|
-
EXPECT_THAT((BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(0)),
|
|
293
|
-
ElementsAre());
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
TEST(BitMask, WithShift_SomeMask) {
|
|
297
|
-
EXPECT_THAT((BitMask<uint64_t, 8, 3>(kSome8BytesMask)),
|
|
298
|
-
ElementsAreArray(kSome8BytesMaskBits));
|
|
299
|
-
EXPECT_THAT((BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(
|
|
300
|
-
kSome8BytesMask)),
|
|
301
|
-
ElementsAreArray(kSome8BytesMaskBits));
|
|
302
|
-
EXPECT_THAT((BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(
|
|
303
|
-
kSome8BytesMaskAllOnes)),
|
|
304
|
-
ElementsAreArray(kSome8BytesMaskBits));
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
TEST(BitMask, WithShift_SomeMaskExtraBitsForNullify) {
|
|
308
|
-
// Verify that adding extra bits into non zero bytes is fine.
|
|
309
|
-
uint64_t extra_bits = 77;
|
|
310
|
-
for (int i = 0; i < 100; ++i) {
|
|
311
|
-
// Add extra bits, but keep zero bytes untouched.
|
|
312
|
-
uint64_t extra_mask = extra_bits & kSome8BytesMaskAllOnes;
|
|
313
|
-
EXPECT_THAT((BitMask<uint64_t, 8, 3, /*NullifyBitsOnIteration=*/true>(
|
|
314
|
-
kSome8BytesMask | extra_mask)),
|
|
315
|
-
ElementsAreArray(kSome8BytesMaskBits))
|
|
316
|
-
<< i << " " << extra_mask;
|
|
317
|
-
extra_bits = (extra_bits + 1) * 3;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
TEST(BitMask, LeadingTrailing) {
|
|
322
|
-
EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).LeadingZeros()), 3);
|
|
323
|
-
EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).TrailingZeros()), 6);
|
|
324
|
-
|
|
325
|
-
EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).LeadingZeros()), 15);
|
|
326
|
-
EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).TrailingZeros()), 0);
|
|
327
|
-
|
|
328
|
-
EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).LeadingZeros()), 0);
|
|
329
|
-
EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).TrailingZeros()), 15);
|
|
330
|
-
|
|
331
|
-
EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).LeadingZeros()), 3);
|
|
332
|
-
EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).TrailingZeros()), 1);
|
|
333
|
-
|
|
334
|
-
EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000000000000080).LeadingZeros()), 7);
|
|
335
|
-
EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000000000000080).TrailingZeros()), 0);
|
|
336
|
-
|
|
337
|
-
EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x8000000000000000).LeadingZeros()), 0);
|
|
338
|
-
EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x8000000000000000).TrailingZeros()), 7);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
TEST(Group, EmptyGroup) {
|
|
342
|
-
for (h2_t h = 0; h != 128; ++h) EXPECT_FALSE(Group{EmptyGroup()}.Match(h));
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
TEST(Group, Match) {
|
|
346
|
-
if (Group::kWidth == 16) {
|
|
347
|
-
ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted, CtrlT(3),
|
|
348
|
-
ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),
|
|
349
|
-
CtrlT(7), CtrlT(5), CtrlT(3), CtrlT(1),
|
|
350
|
-
CtrlT(1), CtrlT(1), CtrlT(1), CtrlT(1)};
|
|
351
|
-
EXPECT_THAT(Group{group}.Match(0), ElementsAre());
|
|
352
|
-
EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15));
|
|
353
|
-
EXPECT_THAT(Group{group}.Match(3), ElementsAre(3, 10));
|
|
354
|
-
EXPECT_THAT(Group{group}.Match(5), ElementsAre(5, 9));
|
|
355
|
-
EXPECT_THAT(Group{group}.Match(7), ElementsAre(7, 8));
|
|
356
|
-
} else if (Group::kWidth == 8) {
|
|
357
|
-
ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), CtrlT(2),
|
|
358
|
-
ctrl_t::kDeleted, CtrlT(2), CtrlT(1),
|
|
359
|
-
ctrl_t::kSentinel, CtrlT(1)};
|
|
360
|
-
EXPECT_THAT(Group{group}.Match(0), ElementsAre());
|
|
361
|
-
EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 5, 7));
|
|
362
|
-
EXPECT_THAT(Group{group}.Match(2), ElementsAre(2, 4));
|
|
363
|
-
} else {
|
|
364
|
-
FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
TEST(Group, MaskEmpty) {
|
|
369
|
-
if (Group::kWidth == 16) {
|
|
370
|
-
ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted, CtrlT(3),
|
|
371
|
-
ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),
|
|
372
|
-
CtrlT(7), CtrlT(5), CtrlT(3), CtrlT(1),
|
|
373
|
-
CtrlT(1), CtrlT(1), CtrlT(1), CtrlT(1)};
|
|
374
|
-
EXPECT_THAT(Group{group}.MaskEmpty().LowestBitSet(), 0);
|
|
375
|
-
EXPECT_THAT(Group{group}.MaskEmpty().HighestBitSet(), 4);
|
|
376
|
-
} else if (Group::kWidth == 8) {
|
|
377
|
-
ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), CtrlT(2),
|
|
378
|
-
ctrl_t::kDeleted, CtrlT(2), CtrlT(1),
|
|
379
|
-
ctrl_t::kSentinel, CtrlT(1)};
|
|
380
|
-
EXPECT_THAT(Group{group}.MaskEmpty().LowestBitSet(), 0);
|
|
381
|
-
EXPECT_THAT(Group{group}.MaskEmpty().HighestBitSet(), 0);
|
|
382
|
-
} else {
|
|
383
|
-
FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
TEST(Group, MaskFull) {
|
|
388
|
-
if (Group::kWidth == 16) {
|
|
389
|
-
ctrl_t group[] = {
|
|
390
|
-
ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted, CtrlT(3),
|
|
391
|
-
ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),
|
|
392
|
-
CtrlT(7), CtrlT(5), ctrl_t::kDeleted, CtrlT(1),
|
|
393
|
-
CtrlT(1), ctrl_t::kSentinel, ctrl_t::kEmpty, CtrlT(1)};
|
|
394
|
-
EXPECT_THAT(Group{group}.MaskFull(),
|
|
395
|
-
ElementsAre(1, 3, 5, 7, 8, 9, 11, 12, 15));
|
|
396
|
-
} else if (Group::kWidth == 8) {
|
|
397
|
-
ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kEmpty,
|
|
398
|
-
ctrl_t::kDeleted, CtrlT(2), ctrl_t::kSentinel,
|
|
399
|
-
ctrl_t::kSentinel, CtrlT(1)};
|
|
400
|
-
EXPECT_THAT(Group{group}.MaskFull(), ElementsAre(1, 4, 7));
|
|
401
|
-
} else {
|
|
402
|
-
FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
TEST(Group, MaskNonFull) {
|
|
407
|
-
if (Group::kWidth == 16) {
|
|
408
|
-
ctrl_t group[] = {
|
|
409
|
-
ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted, CtrlT(3),
|
|
410
|
-
ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),
|
|
411
|
-
CtrlT(7), CtrlT(5), ctrl_t::kDeleted, CtrlT(1),
|
|
412
|
-
CtrlT(1), ctrl_t::kSentinel, ctrl_t::kEmpty, CtrlT(1)};
|
|
413
|
-
EXPECT_THAT(Group{group}.MaskNonFull(),
|
|
414
|
-
ElementsAre(0, 2, 4, 6, 10, 13, 14));
|
|
415
|
-
} else if (Group::kWidth == 8) {
|
|
416
|
-
ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kEmpty,
|
|
417
|
-
ctrl_t::kDeleted, CtrlT(2), ctrl_t::kSentinel,
|
|
418
|
-
ctrl_t::kSentinel, CtrlT(1)};
|
|
419
|
-
EXPECT_THAT(Group{group}.MaskNonFull(), ElementsAre(0, 2, 3, 5, 6));
|
|
420
|
-
} else {
|
|
421
|
-
FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
TEST(Group, MaskEmptyOrDeleted) {
|
|
426
|
-
if (Group::kWidth == 16) {
|
|
427
|
-
ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kEmpty, CtrlT(3),
|
|
428
|
-
ctrl_t::kDeleted, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),
|
|
429
|
-
CtrlT(7), CtrlT(5), CtrlT(3), CtrlT(1),
|
|
430
|
-
CtrlT(1), CtrlT(1), CtrlT(1), CtrlT(1)};
|
|
431
|
-
EXPECT_THAT(Group{group}.MaskEmptyOrDeleted().LowestBitSet(), 0);
|
|
432
|
-
EXPECT_THAT(Group{group}.MaskEmptyOrDeleted().HighestBitSet(), 4);
|
|
433
|
-
} else if (Group::kWidth == 8) {
|
|
434
|
-
ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), CtrlT(2),
|
|
435
|
-
ctrl_t::kDeleted, CtrlT(2), CtrlT(1),
|
|
436
|
-
ctrl_t::kSentinel, CtrlT(1)};
|
|
437
|
-
EXPECT_THAT(Group{group}.MaskEmptyOrDeleted().LowestBitSet(), 0);
|
|
438
|
-
EXPECT_THAT(Group{group}.MaskEmptyOrDeleted().HighestBitSet(), 3);
|
|
439
|
-
} else {
|
|
440
|
-
FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
329
|
TEST(Batch, DropDeletes) {
|
|
445
330
|
constexpr size_t kCapacity = 63;
|
|
446
331
|
constexpr size_t kGroupWidth = container_internal::Group::kWidth;
|
|
@@ -466,30 +351,6 @@ TEST(Batch, DropDeletes) {
|
|
|
466
351
|
}
|
|
467
352
|
}
|
|
468
353
|
|
|
469
|
-
TEST(Group, CountLeadingEmptyOrDeleted) {
|
|
470
|
-
const std::vector<ctrl_t> empty_examples = {ctrl_t::kEmpty, ctrl_t::kDeleted};
|
|
471
|
-
const std::vector<ctrl_t> full_examples = {
|
|
472
|
-
CtrlT(0), CtrlT(1), CtrlT(2), CtrlT(3),
|
|
473
|
-
CtrlT(5), CtrlT(9), CtrlT(127), ctrl_t::kSentinel};
|
|
474
|
-
|
|
475
|
-
for (ctrl_t empty : empty_examples) {
|
|
476
|
-
std::vector<ctrl_t> e(Group::kWidth, empty);
|
|
477
|
-
EXPECT_EQ(Group::kWidth, Group{e.data()}.CountLeadingEmptyOrDeleted());
|
|
478
|
-
for (ctrl_t full : full_examples) {
|
|
479
|
-
for (size_t i = 0; i != Group::kWidth; ++i) {
|
|
480
|
-
std::vector<ctrl_t> f(Group::kWidth, empty);
|
|
481
|
-
f[i] = full;
|
|
482
|
-
EXPECT_EQ(i, Group{f.data()}.CountLeadingEmptyOrDeleted());
|
|
483
|
-
}
|
|
484
|
-
std::vector<ctrl_t> f(Group::kWidth, empty);
|
|
485
|
-
f[Group::kWidth * 2 / 3] = full;
|
|
486
|
-
f[Group::kWidth / 2] = full;
|
|
487
|
-
EXPECT_EQ(Group::kWidth / 2,
|
|
488
|
-
Group{f.data()}.CountLeadingEmptyOrDeleted());
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
354
|
template <class T, bool kTransferable = false, bool kSoo = false>
|
|
494
355
|
struct ValuePolicy {
|
|
495
356
|
using slot_type = T;
|
|
@@ -525,7 +386,7 @@ struct ValuePolicy {
|
|
|
525
386
|
std::forward<F>(f), std::forward<Args>(args)...);
|
|
526
387
|
}
|
|
527
388
|
|
|
528
|
-
template <class Hash>
|
|
389
|
+
template <class Hash, bool kIsDefault>
|
|
529
390
|
static constexpr HashSlotFn get_hash_slot_fn() {
|
|
530
391
|
return nullptr;
|
|
531
392
|
}
|
|
@@ -536,8 +397,6 @@ struct ValuePolicy {
|
|
|
536
397
|
using IntPolicy = ValuePolicy<int64_t>;
|
|
537
398
|
using Uint8Policy = ValuePolicy<uint8_t>;
|
|
538
399
|
|
|
539
|
-
using TranferableIntPolicy = ValuePolicy<int64_t, /*kTransferable=*/true>;
|
|
540
|
-
|
|
541
400
|
// For testing SOO.
|
|
542
401
|
template <int N>
|
|
543
402
|
class SizedValue {
|
|
@@ -576,6 +435,48 @@ template <int N, bool kSoo>
|
|
|
576
435
|
using SizedValuePolicy =
|
|
577
436
|
ValuePolicy<SizedValue<N>, /*kTransferable=*/true, kSoo>;
|
|
578
437
|
|
|
438
|
+
// Value is aligned as type T and contains N copies of it.
|
|
439
|
+
template <typename T, int N>
|
|
440
|
+
class AlignedValue {
|
|
441
|
+
public:
|
|
442
|
+
AlignedValue(int64_t v) { // NOLINT
|
|
443
|
+
for (int i = 0; i < N; ++i) {
|
|
444
|
+
vals_[i] = v;
|
|
445
|
+
if (sizeof(T) < sizeof(int64_t)) {
|
|
446
|
+
v >>= (8 * sizeof(T));
|
|
447
|
+
} else {
|
|
448
|
+
v = 0;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
AlignedValue() : AlignedValue(0) {}
|
|
453
|
+
AlignedValue(const AlignedValue&) = default;
|
|
454
|
+
AlignedValue& operator=(const AlignedValue&) = default;
|
|
455
|
+
|
|
456
|
+
int64_t operator*() const {
|
|
457
|
+
if (sizeof(T) == sizeof(int64_t)) {
|
|
458
|
+
return vals_[0];
|
|
459
|
+
}
|
|
460
|
+
int64_t result = 0;
|
|
461
|
+
for (int i = N - 1; i >= 0; --i) {
|
|
462
|
+
result <<= (8 * sizeof(T));
|
|
463
|
+
result += vals_[i];
|
|
464
|
+
}
|
|
465
|
+
return result;
|
|
466
|
+
}
|
|
467
|
+
explicit operator int() const { return **this; }
|
|
468
|
+
explicit operator int64_t() const { return **this; }
|
|
469
|
+
|
|
470
|
+
template <typename H>
|
|
471
|
+
friend H AbslHashValue(H h, AlignedValue sv) {
|
|
472
|
+
return H::combine(std::move(h), *sv);
|
|
473
|
+
}
|
|
474
|
+
bool operator==(const AlignedValue& rhs) const { return **this == *rhs; }
|
|
475
|
+
|
|
476
|
+
private:
|
|
477
|
+
T vals_[N];
|
|
478
|
+
};
|
|
479
|
+
|
|
579
480
|
class StringPolicy {
|
|
580
481
|
template <class F, class K, class V,
|
|
581
482
|
class = typename std::enable_if<
|
|
@@ -633,7 +534,7 @@ class StringPolicy {
|
|
|
633
534
|
PairArgs(std::forward<Args>(args)...));
|
|
634
535
|
}
|
|
635
536
|
|
|
636
|
-
template <class Hash>
|
|
537
|
+
template <class Hash, bool kIsDefault>
|
|
637
538
|
static constexpr HashSlotFn get_hash_slot_fn() {
|
|
638
539
|
return nullptr;
|
|
639
540
|
}
|
|
@@ -653,10 +554,11 @@ struct StringTable
|
|
|
653
554
|
using Base::Base;
|
|
654
555
|
};
|
|
655
556
|
|
|
656
|
-
template <typename T, bool kTransferable = false, bool kSoo = false
|
|
557
|
+
template <typename T, bool kTransferable = false, bool kSoo = false,
|
|
558
|
+
class Alloc = std::allocator<T>>
|
|
657
559
|
struct ValueTable
|
|
658
560
|
: raw_hash_set<ValuePolicy<T, kTransferable, kSoo>, hash_default_hash<T>,
|
|
659
|
-
std::equal_to<T>,
|
|
561
|
+
std::equal_to<T>, Alloc> {
|
|
660
562
|
using Base = typename ValueTable::raw_hash_set;
|
|
661
563
|
using Base::Base;
|
|
662
564
|
};
|
|
@@ -666,11 +568,6 @@ using Uint8Table = ValueTable<uint8_t>;
|
|
|
666
568
|
|
|
667
569
|
using TransferableIntTable = ValueTable<int64_t, /*kTransferable=*/true>;
|
|
668
570
|
|
|
669
|
-
constexpr size_t kNonSooSize = sizeof(HeapOrSoo) + 8;
|
|
670
|
-
static_assert(sizeof(SizedValue<kNonSooSize>) >= kNonSooSize, "too small");
|
|
671
|
-
using NonSooIntTable = ValueTable<SizedValue<kNonSooSize>>;
|
|
672
|
-
using SooIntTable = ValueTable<int64_t, /*kTransferable=*/true, /*kSoo=*/true>;
|
|
673
|
-
|
|
674
571
|
template <typename T>
|
|
675
572
|
struct CustomAlloc : std::allocator<T> {
|
|
676
573
|
CustomAlloc() = default;
|
|
@@ -691,6 +588,50 @@ struct CustomAllocIntTable
|
|
|
691
588
|
using Base::Base;
|
|
692
589
|
};
|
|
693
590
|
|
|
591
|
+
template <typename T>
|
|
592
|
+
struct ChangingSizeAndTrackingTypeAlloc : std::allocator<T> {
|
|
593
|
+
ChangingSizeAndTrackingTypeAlloc() = default;
|
|
594
|
+
|
|
595
|
+
template <typename U>
|
|
596
|
+
explicit ChangingSizeAndTrackingTypeAlloc(
|
|
597
|
+
const ChangingSizeAndTrackingTypeAlloc<U>& other) {
|
|
598
|
+
EXPECT_EQ(other.type_id,
|
|
599
|
+
ChangingSizeAndTrackingTypeAlloc<U>::ComputeTypeId());
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
template <class U>
|
|
603
|
+
struct rebind {
|
|
604
|
+
using other = ChangingSizeAndTrackingTypeAlloc<U>;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
T* allocate(size_t n) {
|
|
608
|
+
EXPECT_EQ(type_id, ComputeTypeId());
|
|
609
|
+
return std::allocator<T>::allocate(n);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
void deallocate(T* p, std::size_t n) {
|
|
613
|
+
EXPECT_EQ(type_id, ComputeTypeId());
|
|
614
|
+
return std::allocator<T>::deallocate(p, n);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
static size_t ComputeTypeId() { return absl::HashOf(typeid(T).name()); }
|
|
618
|
+
|
|
619
|
+
// We add extra data to make the allocator size being changed.
|
|
620
|
+
// This also make type_id positioned differently, so that assertions in the
|
|
621
|
+
// allocator can catch bugs more likely.
|
|
622
|
+
char data_before[sizeof(T) * 3] = {0};
|
|
623
|
+
size_t type_id = ComputeTypeId();
|
|
624
|
+
char data_after[sizeof(T) * 5] = {0};
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
struct ChangingSizeAllocIntTable
|
|
628
|
+
: raw_hash_set<IntPolicy, hash_default_hash<int64_t>,
|
|
629
|
+
std::equal_to<int64_t>,
|
|
630
|
+
ChangingSizeAndTrackingTypeAlloc<int64_t>> {
|
|
631
|
+
using Base = typename ChangingSizeAllocIntTable::raw_hash_set;
|
|
632
|
+
using Base::Base;
|
|
633
|
+
};
|
|
634
|
+
|
|
694
635
|
struct MinimumAlignmentUint8Table
|
|
695
636
|
: raw_hash_set<Uint8Policy, hash_default_hash<uint8_t>,
|
|
696
637
|
std::equal_to<uint8_t>, MinimumAlignmentAlloc<uint8_t>> {
|
|
@@ -744,28 +685,44 @@ struct BadHashFreezableIntTable
|
|
|
744
685
|
using Base::Base;
|
|
745
686
|
};
|
|
746
687
|
|
|
747
|
-
struct BadTable : raw_hash_set<IntPolicy, BadFastHash, std::equal_to<
|
|
688
|
+
struct BadTable : raw_hash_set<IntPolicy, BadFastHash, std::equal_to<int64_t>,
|
|
748
689
|
std::allocator<int>> {
|
|
749
690
|
using Base = typename BadTable::raw_hash_set;
|
|
750
691
|
BadTable() = default;
|
|
751
692
|
using Base::Base;
|
|
752
693
|
};
|
|
753
694
|
|
|
695
|
+
constexpr size_t kNonSooSize = sizeof(HeapOrSoo) + 8;
|
|
696
|
+
using NonSooIntTableSlotType = SizedValue<kNonSooSize>;
|
|
697
|
+
static_assert(sizeof(NonSooIntTableSlotType) >= kNonSooSize, "too small");
|
|
698
|
+
using NonSooIntTable = ValueTable<NonSooIntTableSlotType>;
|
|
699
|
+
using SooInt32Table =
|
|
700
|
+
ValueTable<int32_t, /*kTransferable=*/true, /*kSoo=*/true>;
|
|
701
|
+
using SooIntTable = ValueTable<int64_t, /*kTransferable=*/true, /*kSoo=*/true>;
|
|
702
|
+
using NonMemcpyableSooIntTable =
|
|
703
|
+
ValueTable<int64_t, /*kTransferable=*/false, /*kSoo=*/true>;
|
|
704
|
+
using MemcpyableSooIntCustomAllocTable =
|
|
705
|
+
ValueTable<int64_t, /*kTransferable=*/true, /*kSoo=*/true,
|
|
706
|
+
ChangingSizeAndTrackingTypeAlloc<int64_t>>;
|
|
707
|
+
using NonMemcpyableSooIntCustomAllocTable =
|
|
708
|
+
ValueTable<int64_t, /*kTransferable=*/false, /*kSoo=*/true,
|
|
709
|
+
ChangingSizeAndTrackingTypeAlloc<int64_t>>;
|
|
710
|
+
|
|
754
711
|
TEST(Table, EmptyFunctorOptimization) {
|
|
755
712
|
static_assert(std::is_empty<std::equal_to<absl::string_view>>::value, "");
|
|
756
713
|
static_assert(std::is_empty<std::allocator<int>>::value, "");
|
|
757
714
|
|
|
758
715
|
struct MockTable {
|
|
716
|
+
size_t capacity;
|
|
717
|
+
uint64_t size;
|
|
759
718
|
void* ctrl;
|
|
760
719
|
void* slots;
|
|
761
|
-
size_t size;
|
|
762
|
-
size_t capacity;
|
|
763
720
|
};
|
|
764
721
|
struct StatelessHash {
|
|
765
722
|
size_t operator()(absl::string_view) const { return 0; }
|
|
766
723
|
};
|
|
767
724
|
struct StatefulHash : StatelessHash {
|
|
768
|
-
|
|
725
|
+
uint64_t dummy;
|
|
769
726
|
};
|
|
770
727
|
|
|
771
728
|
struct GenerationData {
|
|
@@ -803,7 +760,10 @@ TEST(Table, EmptyFunctorOptimization) {
|
|
|
803
760
|
template <class TableType>
|
|
804
761
|
class SooTest : public testing::Test {};
|
|
805
762
|
|
|
806
|
-
using SooTableTypes =
|
|
763
|
+
using SooTableTypes =
|
|
764
|
+
::testing::Types<SooIntTable, NonSooIntTable, NonMemcpyableSooIntTable,
|
|
765
|
+
MemcpyableSooIntCustomAllocTable,
|
|
766
|
+
NonMemcpyableSooIntCustomAllocTable>;
|
|
807
767
|
TYPED_TEST_SUITE(SooTest, SooTableTypes);
|
|
808
768
|
|
|
809
769
|
TYPED_TEST(SooTest, Empty) {
|
|
@@ -812,6 +772,21 @@ TYPED_TEST(SooTest, Empty) {
|
|
|
812
772
|
EXPECT_TRUE(t.empty());
|
|
813
773
|
}
|
|
814
774
|
|
|
775
|
+
TEST(Table, Prefetch) {
|
|
776
|
+
IntTable t;
|
|
777
|
+
t.emplace(1);
|
|
778
|
+
// Works for both present and absent keys.
|
|
779
|
+
t.prefetch(1);
|
|
780
|
+
t.prefetch(2);
|
|
781
|
+
|
|
782
|
+
static constexpr int size = 10;
|
|
783
|
+
for (int i = 0; i < size; ++i) t.insert(i);
|
|
784
|
+
for (int i = 0; i < size; ++i) {
|
|
785
|
+
t.prefetch(i);
|
|
786
|
+
ASSERT_TRUE(t.find(i) != t.end()) << i;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
815
790
|
TYPED_TEST(SooTest, LookupEmpty) {
|
|
816
791
|
TypeParam t;
|
|
817
792
|
auto it = t.find(0);
|
|
@@ -942,8 +917,41 @@ TYPED_TEST(SooTest, InsertWithinCapacity) {
|
|
|
942
917
|
template <class TableType>
|
|
943
918
|
class SmallTableResizeTest : public testing::Test {};
|
|
944
919
|
|
|
945
|
-
using SmallTableTypes =
|
|
946
|
-
|
|
920
|
+
using SmallTableTypes = ::testing::Types<
|
|
921
|
+
IntTable, TransferableIntTable, SooIntTable,
|
|
922
|
+
// int8
|
|
923
|
+
ValueTable<int8_t, /*kTransferable=*/true, /*kSoo=*/true>,
|
|
924
|
+
ValueTable<int8_t, /*kTransferable=*/false, /*kSoo=*/true>,
|
|
925
|
+
// int16
|
|
926
|
+
ValueTable<int16_t, /*kTransferable=*/true, /*kSoo=*/true>,
|
|
927
|
+
ValueTable<int16_t, /*kTransferable=*/false, /*kSoo=*/true>,
|
|
928
|
+
// int128
|
|
929
|
+
ValueTable<SizedValue<16>, /*kTransferable=*/true, /*kSoo=*/true>,
|
|
930
|
+
ValueTable<SizedValue<16>, /*kTransferable=*/false, /*kSoo=*/true>,
|
|
931
|
+
// int192
|
|
932
|
+
ValueTable<SizedValue<24>, /*kTransferable=*/true, /*kSoo=*/true>,
|
|
933
|
+
ValueTable<SizedValue<24>, /*kTransferable=*/false, /*kSoo=*/true>,
|
|
934
|
+
// Special tables.
|
|
935
|
+
MinimumAlignmentUint8Table, CustomAllocIntTable, ChangingSizeAllocIntTable,
|
|
936
|
+
BadTable,
|
|
937
|
+
// alignment 1, size 2.
|
|
938
|
+
ValueTable<AlignedValue<uint8_t, 2>, /*kTransferable=*/true, /*kSoo=*/true>,
|
|
939
|
+
ValueTable<AlignedValue<uint8_t, 2>, /*kTransferable=*/false,
|
|
940
|
+
/*kSoo=*/true>,
|
|
941
|
+
// alignment 1, size 7.
|
|
942
|
+
ValueTable<AlignedValue<uint8_t, 7>, /*kTransferable=*/true, /*kSoo=*/true>,
|
|
943
|
+
ValueTable<AlignedValue<uint8_t, 7>, /*kTransferable=*/false,
|
|
944
|
+
/*kSoo=*/true>,
|
|
945
|
+
// alignment 2, size 6.
|
|
946
|
+
ValueTable<AlignedValue<uint16_t, 3>, /*kTransferable=*/true,
|
|
947
|
+
/*kSoo=*/true>,
|
|
948
|
+
ValueTable<AlignedValue<uint16_t, 3>, /*kTransferable=*/false,
|
|
949
|
+
/*kSoo=*/true>,
|
|
950
|
+
// alignment 2, size 10.
|
|
951
|
+
ValueTable<AlignedValue<uint16_t, 5>, /*kTransferable=*/true,
|
|
952
|
+
/*kSoo=*/true>,
|
|
953
|
+
ValueTable<AlignedValue<uint16_t, 5>, /*kTransferable=*/false,
|
|
954
|
+
/*kSoo=*/true>>;
|
|
947
955
|
TYPED_TEST_SUITE(SmallTableResizeTest, SmallTableTypes);
|
|
948
956
|
|
|
949
957
|
TYPED_TEST(SmallTableResizeTest, InsertIntoSmallTable) {
|
|
@@ -952,7 +960,7 @@ TYPED_TEST(SmallTableResizeTest, InsertIntoSmallTable) {
|
|
|
952
960
|
t.insert(i);
|
|
953
961
|
ASSERT_EQ(t.size(), i + 1);
|
|
954
962
|
for (int j = 0; j < i + 1; ++j) {
|
|
955
|
-
|
|
963
|
+
ASSERT_TRUE(t.find(j) != t.end());
|
|
956
964
|
EXPECT_EQ(*t.find(j), j);
|
|
957
965
|
}
|
|
958
966
|
}
|
|
@@ -962,6 +970,9 @@ TYPED_TEST(SmallTableResizeTest, ResizeGrowSmallTables) {
|
|
|
962
970
|
for (size_t source_size = 0; source_size < 32; ++source_size) {
|
|
963
971
|
for (size_t target_size = source_size; target_size < 32; ++target_size) {
|
|
964
972
|
for (bool rehash : {false, true}) {
|
|
973
|
+
SCOPED_TRACE(absl::StrCat("source_size: ", source_size,
|
|
974
|
+
", target_size: ", target_size,
|
|
975
|
+
", rehash: ", rehash));
|
|
965
976
|
TypeParam t;
|
|
966
977
|
for (size_t i = 0; i < source_size; ++i) {
|
|
967
978
|
t.insert(static_cast<int>(i));
|
|
@@ -972,7 +983,7 @@ TYPED_TEST(SmallTableResizeTest, ResizeGrowSmallTables) {
|
|
|
972
983
|
t.reserve(target_size);
|
|
973
984
|
}
|
|
974
985
|
for (size_t i = 0; i < source_size; ++i) {
|
|
975
|
-
|
|
986
|
+
ASSERT_TRUE(t.find(static_cast<int>(i)) != t.end());
|
|
976
987
|
EXPECT_EQ(*t.find(static_cast<int>(i)), static_cast<int>(i));
|
|
977
988
|
}
|
|
978
989
|
}
|
|
@@ -981,6 +992,7 @@ TYPED_TEST(SmallTableResizeTest, ResizeGrowSmallTables) {
|
|
|
981
992
|
}
|
|
982
993
|
|
|
983
994
|
TYPED_TEST(SmallTableResizeTest, ResizeReduceSmallTables) {
|
|
995
|
+
DisableSampling();
|
|
984
996
|
for (size_t source_size = 0; source_size < 32; ++source_size) {
|
|
985
997
|
for (size_t target_size = 0; target_size <= source_size; ++target_size) {
|
|
986
998
|
TypeParam t;
|
|
@@ -996,7 +1008,7 @@ TYPED_TEST(SmallTableResizeTest, ResizeReduceSmallTables) {
|
|
|
996
1008
|
<< "rehash(0) must resize to the minimum capacity";
|
|
997
1009
|
}
|
|
998
1010
|
for (size_t i = 0; i < inserted_count; ++i) {
|
|
999
|
-
|
|
1011
|
+
ASSERT_TRUE(t.find(static_cast<int>(i)) != t.end());
|
|
1000
1012
|
EXPECT_EQ(*t.find(static_cast<int>(i)), static_cast<int>(i));
|
|
1001
1013
|
}
|
|
1002
1014
|
}
|
|
@@ -1047,6 +1059,9 @@ TYPED_TEST(SooTest, Contains2) {
|
|
|
1047
1059
|
|
|
1048
1060
|
t.clear();
|
|
1049
1061
|
EXPECT_FALSE(t.contains(0));
|
|
1062
|
+
|
|
1063
|
+
EXPECT_TRUE(t.insert(0).second);
|
|
1064
|
+
EXPECT_TRUE(t.contains(0));
|
|
1050
1065
|
}
|
|
1051
1066
|
|
|
1052
1067
|
int decompose_constructed;
|
|
@@ -1116,7 +1131,7 @@ struct DecomposePolicy {
|
|
|
1116
1131
|
return std::forward<F>(f)(x, x);
|
|
1117
1132
|
}
|
|
1118
1133
|
|
|
1119
|
-
template <class Hash>
|
|
1134
|
+
template <class Hash, bool kIsDefault>
|
|
1120
1135
|
static constexpr HashSlotFn get_hash_slot_fn() {
|
|
1121
1136
|
return nullptr;
|
|
1122
1137
|
}
|
|
@@ -1284,7 +1299,7 @@ struct Modulo1000Hash {
|
|
|
1284
1299
|
};
|
|
1285
1300
|
|
|
1286
1301
|
struct Modulo1000HashTable
|
|
1287
|
-
: public raw_hash_set<IntPolicy, Modulo1000Hash, std::equal_to<
|
|
1302
|
+
: public raw_hash_set<IntPolicy, Modulo1000Hash, std::equal_to<int64_t>,
|
|
1288
1303
|
std::allocator<int>> {};
|
|
1289
1304
|
|
|
1290
1305
|
// Test that rehash with no resize happen in case of many deleted slots.
|
|
@@ -1338,18 +1353,18 @@ TEST(Table, RehashWithNoResize) {
|
|
|
1338
1353
|
|
|
1339
1354
|
TYPED_TEST(SooTest, InsertEraseStressTest) {
|
|
1340
1355
|
TypeParam t;
|
|
1341
|
-
const size_t kMinElementCount =
|
|
1356
|
+
const size_t kMinElementCount = 50;
|
|
1342
1357
|
std::deque<int> keys;
|
|
1343
1358
|
size_t i = 0;
|
|
1344
1359
|
for (; i < MaxDensitySize(kMinElementCount); ++i) {
|
|
1345
|
-
t.emplace(i);
|
|
1360
|
+
t.emplace(static_cast<int64_t>(i));
|
|
1346
1361
|
keys.push_back(i);
|
|
1347
1362
|
}
|
|
1348
|
-
const size_t kNumIterations =
|
|
1363
|
+
const size_t kNumIterations = 20000;
|
|
1349
1364
|
for (; i < kNumIterations; ++i) {
|
|
1350
1365
|
ASSERT_EQ(1, t.erase(keys.front()));
|
|
1351
1366
|
keys.pop_front();
|
|
1352
|
-
t.emplace(i);
|
|
1367
|
+
t.emplace(static_cast<int64_t>(i));
|
|
1353
1368
|
keys.push_back(i);
|
|
1354
1369
|
}
|
|
1355
1370
|
}
|
|
@@ -1367,8 +1382,11 @@ TEST(Table, InsertOverloads) {
|
|
|
1367
1382
|
|
|
1368
1383
|
TYPED_TEST(SooTest, LargeTable) {
|
|
1369
1384
|
TypeParam t;
|
|
1370
|
-
for (int64_t i = 0; i !=
|
|
1371
|
-
|
|
1385
|
+
for (int64_t i = 0; i != 10000; ++i) {
|
|
1386
|
+
t.emplace(i << 40);
|
|
1387
|
+
ASSERT_EQ(t.size(), i + 1);
|
|
1388
|
+
}
|
|
1389
|
+
for (int64_t i = 0; i != 10000; ++i)
|
|
1372
1390
|
ASSERT_EQ(i << 40, static_cast<int64_t>(*t.find(i << 40)));
|
|
1373
1391
|
}
|
|
1374
1392
|
|
|
@@ -1699,8 +1717,7 @@ ProbeStats CollectProbeStatsOnLinearlyTransformedKeys(
|
|
|
1699
1717
|
const std::vector<int64_t>& keys, size_t num_iters) {
|
|
1700
1718
|
ProbeStats stats;
|
|
1701
1719
|
|
|
1702
|
-
|
|
1703
|
-
std::mt19937 rng(rd());
|
|
1720
|
+
absl::InsecureBitGen rng;
|
|
1704
1721
|
auto linear_transform = [](size_t x, size_t y) { return x * 17 + y * 13; };
|
|
1705
1722
|
std::uniform_int_distribution<size_t> dist(0, keys.size() - 1);
|
|
1706
1723
|
while (num_iters--) {
|
|
@@ -1845,8 +1862,6 @@ TEST(Table, EraseInsertProbing) {
|
|
|
1845
1862
|
|
|
1846
1863
|
TEST(Table, GrowthInfoDeletedBit) {
|
|
1847
1864
|
BadTable t;
|
|
1848
|
-
EXPECT_TRUE(
|
|
1849
|
-
RawHashSetTestOnlyAccess::GetCommon(t).growth_info().HasNoDeleted());
|
|
1850
1865
|
int64_t init_count = static_cast<int64_t>(
|
|
1851
1866
|
CapacityToGrowth(NormalizeCapacity(Group::kWidth + 1)));
|
|
1852
1867
|
for (int64_t i = 0; i < init_count; ++i) {
|
|
@@ -1966,6 +1981,43 @@ TYPED_TEST(SooTest, CopyConstruct) {
|
|
|
1966
1981
|
}
|
|
1967
1982
|
}
|
|
1968
1983
|
|
|
1984
|
+
TYPED_TEST(SooTest, CopyAssignment) {
|
|
1985
|
+
std::vector<size_t> sizes = {0, 1, 7, 25};
|
|
1986
|
+
for (size_t source_size : sizes) {
|
|
1987
|
+
for (size_t target_size : sizes) {
|
|
1988
|
+
SCOPED_TRACE(absl::StrCat("source_size: ", source_size,
|
|
1989
|
+
" target_size: ", target_size));
|
|
1990
|
+
TypeParam source;
|
|
1991
|
+
std::vector<int> source_elements;
|
|
1992
|
+
for (size_t i = 0; i < source_size; ++i) {
|
|
1993
|
+
source.emplace(static_cast<int>(i) * 2);
|
|
1994
|
+
source_elements.push_back(static_cast<int>(i) * 2);
|
|
1995
|
+
}
|
|
1996
|
+
TypeParam target;
|
|
1997
|
+
for (size_t i = 0; i < target_size; ++i) {
|
|
1998
|
+
target.emplace(static_cast<int>(i) * 3);
|
|
1999
|
+
}
|
|
2000
|
+
target = source;
|
|
2001
|
+
ASSERT_EQ(target.size(), source_size);
|
|
2002
|
+
ASSERT_THAT(target, UnorderedElementsAreArray(source_elements));
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
TYPED_TEST(SooTest, CopyConstructWithSampling) {
|
|
2008
|
+
SetSamplingRateTo1Percent();
|
|
2009
|
+
for (int i = 0; i < 10000; ++i) {
|
|
2010
|
+
TypeParam t;
|
|
2011
|
+
t.emplace(0);
|
|
2012
|
+
EXPECT_EQ(1, t.size());
|
|
2013
|
+
{
|
|
2014
|
+
TypeParam u(t);
|
|
2015
|
+
EXPECT_EQ(1, u.size());
|
|
2016
|
+
EXPECT_THAT(*u.find(0), 0);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
|
|
1969
2021
|
TYPED_TEST(SooTest, CopyDifferentSizes) {
|
|
1970
2022
|
TypeParam t;
|
|
1971
2023
|
|
|
@@ -2153,7 +2205,7 @@ TYPED_TEST(SooTest, FindFullDeletedRegression) {
|
|
|
2153
2205
|
|
|
2154
2206
|
TYPED_TEST(SooTest, ReplacingDeletedSlotDoesNotRehash) {
|
|
2155
2207
|
// We need to disable hashtablez to avoid issues related to SOO and sampling.
|
|
2156
|
-
|
|
2208
|
+
DisableSampling();
|
|
2157
2209
|
|
|
2158
2210
|
size_t n;
|
|
2159
2211
|
{
|
|
@@ -2195,12 +2247,10 @@ TEST(Table, NoThrowMoveAssign) {
|
|
|
2195
2247
|
}
|
|
2196
2248
|
|
|
2197
2249
|
TEST(Table, NoThrowSwappable) {
|
|
2198
|
-
ASSERT_TRUE(
|
|
2199
|
-
|
|
2200
|
-
ASSERT_TRUE(
|
|
2201
|
-
|
|
2202
|
-
ASSERT_TRUE(container_internal::IsNoThrowSwappable<std::allocator<int>>());
|
|
2203
|
-
EXPECT_TRUE(container_internal::IsNoThrowSwappable<StringTable>());
|
|
2250
|
+
ASSERT_TRUE(std::is_nothrow_swappable<absl::Hash<absl::string_view>>());
|
|
2251
|
+
ASSERT_TRUE(std::is_nothrow_swappable<std::equal_to<absl::string_view>>());
|
|
2252
|
+
ASSERT_TRUE(std::is_nothrow_swappable<std::allocator<int>>());
|
|
2253
|
+
EXPECT_TRUE(std::is_nothrow_swappable<StringTable>());
|
|
2204
2254
|
}
|
|
2205
2255
|
|
|
2206
2256
|
TEST(Table, HeterogeneousLookup) {
|
|
@@ -2329,6 +2379,19 @@ TEST(Table, Merge) {
|
|
|
2329
2379
|
EXPECT_THAT(t2, UnorderedElementsAre(Pair("0", "~0")));
|
|
2330
2380
|
}
|
|
2331
2381
|
|
|
2382
|
+
TEST(Table, MergeSmall) {
|
|
2383
|
+
StringTable t1, t2;
|
|
2384
|
+
t1.emplace("1", "1");
|
|
2385
|
+
t2.emplace("2", "2");
|
|
2386
|
+
|
|
2387
|
+
EXPECT_THAT(t1, UnorderedElementsAre(Pair("1", "1")));
|
|
2388
|
+
EXPECT_THAT(t2, UnorderedElementsAre(Pair("2", "2")));
|
|
2389
|
+
|
|
2390
|
+
t2.merge(t1);
|
|
2391
|
+
EXPECT_EQ(t1.size(), 0);
|
|
2392
|
+
EXPECT_THAT(t2, UnorderedElementsAre(Pair("1", "1"), Pair("2", "2")));
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2332
2395
|
TEST(Table, IteratorEmplaceConstructibleRequirement) {
|
|
2333
2396
|
struct Value {
|
|
2334
2397
|
explicit Value(absl::string_view view) : value(view) {}
|
|
@@ -2415,6 +2478,24 @@ TEST(Nodes, ExtractInsert) {
|
|
|
2415
2478
|
EXPECT_FALSE(node); // NOLINT(bugprone-use-after-move)
|
|
2416
2479
|
}
|
|
2417
2480
|
|
|
2481
|
+
TEST(Nodes, ExtractInsertSmall) {
|
|
2482
|
+
constexpr char k0[] = "Very long string zero.";
|
|
2483
|
+
StringTable t = {{k0, ""}};
|
|
2484
|
+
EXPECT_THAT(t, UnorderedElementsAre(Pair(k0, "")));
|
|
2485
|
+
|
|
2486
|
+
auto node = t.extract(k0);
|
|
2487
|
+
EXPECT_EQ(t.size(), 0);
|
|
2488
|
+
EXPECT_TRUE(node);
|
|
2489
|
+
EXPECT_FALSE(node.empty());
|
|
2490
|
+
|
|
2491
|
+
StringTable t2;
|
|
2492
|
+
StringTable::insert_return_type res = t2.insert(std::move(node));
|
|
2493
|
+
EXPECT_TRUE(res.inserted);
|
|
2494
|
+
EXPECT_THAT(*res.position, Pair(k0, ""));
|
|
2495
|
+
EXPECT_FALSE(res.node);
|
|
2496
|
+
EXPECT_THAT(t2, UnorderedElementsAre(Pair(k0, "")));
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2418
2499
|
TYPED_TEST(SooTest, HintInsert) {
|
|
2419
2500
|
TypeParam t = {1, 2, 3};
|
|
2420
2501
|
auto node = t.extract(1);
|
|
@@ -2450,38 +2531,41 @@ std::vector<int> OrderOfIteration(const T& t) {
|
|
|
2450
2531
|
return res;
|
|
2451
2532
|
}
|
|
2452
2533
|
|
|
2534
|
+
// Generate irrelevant seeds to avoid being stuck in the same last bit
|
|
2535
|
+
// in seed.
|
|
2536
|
+
void GenerateIrrelevantSeeds(int cnt) {
|
|
2537
|
+
for (int i = cnt % 17; i > 0; --i) {
|
|
2538
|
+
NextSeed();
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2453
2542
|
// These IterationOrderChanges tests depend on non-deterministic behavior.
|
|
2454
|
-
// We are injecting non-determinism
|
|
2455
|
-
//
|
|
2456
|
-
//
|
|
2457
|
-
// We also need to keep the old tables around to avoid getting the same memory
|
|
2458
|
-
// blocks over and over.
|
|
2543
|
+
// We are injecting non-determinism to the table.
|
|
2544
|
+
// We have to retry enough times to make sure that the seed changes in bits that
|
|
2545
|
+
// matter for the iteration order.
|
|
2459
2546
|
TYPED_TEST(SooTest, IterationOrderChangesByInstance) {
|
|
2547
|
+
DisableSampling(); // We do not want test to pass only because of sampling.
|
|
2460
2548
|
for (bool do_reserve : {false, true}) {
|
|
2461
2549
|
for (size_t size : {2u, 6u, 12u, 20u}) {
|
|
2462
2550
|
SCOPED_TRACE(absl::StrCat("size: ", size, " do_reserve: ", do_reserve));
|
|
2463
2551
|
const auto reference_table = MakeSimpleTable<TypeParam>(size, do_reserve);
|
|
2464
2552
|
const auto reference = OrderOfIteration(reference_table);
|
|
2465
2553
|
|
|
2466
|
-
std::vector<TypeParam> tables;
|
|
2467
2554
|
bool found_difference = false;
|
|
2468
|
-
for (int i = 0; !found_difference && i <
|
|
2469
|
-
|
|
2470
|
-
found_difference = OrderOfIteration(
|
|
2555
|
+
for (int i = 0; !found_difference && i < 500; ++i) {
|
|
2556
|
+
auto new_table = MakeSimpleTable<TypeParam>(size, do_reserve);
|
|
2557
|
+
found_difference = OrderOfIteration(new_table) != reference;
|
|
2558
|
+
GenerateIrrelevantSeeds(i);
|
|
2471
2559
|
}
|
|
2472
2560
|
if (!found_difference) {
|
|
2473
|
-
FAIL() << "Iteration order remained the same across many attempts
|
|
2474
|
-
"size "
|
|
2475
|
-
<< size;
|
|
2561
|
+
FAIL() << "Iteration order remained the same across many attempts.";
|
|
2476
2562
|
}
|
|
2477
2563
|
}
|
|
2478
2564
|
}
|
|
2479
2565
|
}
|
|
2480
2566
|
|
|
2481
2567
|
TYPED_TEST(SooTest, IterationOrderChangesOnRehash) {
|
|
2482
|
-
|
|
2483
|
-
GTEST_SKIP() << "Hash quality is lower in asan mode, causing flakiness.";
|
|
2484
|
-
#endif
|
|
2568
|
+
DisableSampling(); // We do not want test to pass only because of sampling.
|
|
2485
2569
|
|
|
2486
2570
|
// We test different sizes with many small numbers, because small table
|
|
2487
2571
|
// resize has a different codepath.
|
|
@@ -2494,11 +2578,17 @@ TYPED_TEST(SooTest, IterationOrderChangesOnRehash) {
|
|
|
2494
2578
|
}) {
|
|
2495
2579
|
SCOPED_TRACE(absl::StrCat("size: ", size, " rehash_size: ", rehash_size,
|
|
2496
2580
|
" do_reserve: ", do_reserve));
|
|
2497
|
-
std::vector<TypeParam> garbage;
|
|
2498
2581
|
bool ok = false;
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2582
|
+
auto t = MakeSimpleTable<TypeParam>(size, do_reserve);
|
|
2583
|
+
const size_t original_capacity = t.capacity();
|
|
2584
|
+
auto reference = OrderOfIteration(t);
|
|
2585
|
+
for (int i = 0; i < 500; ++i) {
|
|
2586
|
+
if (i > 0 && rehash_size != 0) {
|
|
2587
|
+
// Rehash back to original size.
|
|
2588
|
+
t.rehash(0);
|
|
2589
|
+
ASSERT_EQ(t.capacity(), original_capacity);
|
|
2590
|
+
reference = OrderOfIteration(t);
|
|
2591
|
+
}
|
|
2502
2592
|
// Force rehash.
|
|
2503
2593
|
t.rehash(rehash_size);
|
|
2504
2594
|
auto trial = OrderOfIteration(t);
|
|
@@ -2507,7 +2597,7 @@ TYPED_TEST(SooTest, IterationOrderChangesOnRehash) {
|
|
|
2507
2597
|
ok = true;
|
|
2508
2598
|
break;
|
|
2509
2599
|
}
|
|
2510
|
-
|
|
2600
|
+
GenerateIrrelevantSeeds(i);
|
|
2511
2601
|
}
|
|
2512
2602
|
EXPECT_TRUE(ok)
|
|
2513
2603
|
<< "Iteration order remained the same across many attempts " << size
|
|
@@ -2521,7 +2611,7 @@ TYPED_TEST(SooTest, IterationOrderChangesOnRehash) {
|
|
|
2521
2611
|
// This prevents dependency on pointer stability on small tables.
|
|
2522
2612
|
TYPED_TEST(SooTest, UnstablePointers) {
|
|
2523
2613
|
// We need to disable hashtablez to avoid issues related to SOO and sampling.
|
|
2524
|
-
|
|
2614
|
+
DisableSampling();
|
|
2525
2615
|
|
|
2526
2616
|
TypeParam table;
|
|
2527
2617
|
|
|
@@ -2544,12 +2634,12 @@ TEST(TableDeathTest, InvalidIteratorAsserts) {
|
|
|
2544
2634
|
|
|
2545
2635
|
NonSooIntTable t;
|
|
2546
2636
|
// Extra simple "regexp" as regexp support is highly varied across platforms.
|
|
2547
|
-
EXPECT_DEATH_IF_SUPPORTED(t.
|
|
2548
|
-
"erase.* called on end.. iterator.");
|
|
2637
|
+
EXPECT_DEATH_IF_SUPPORTED(++t.end(), "operator.* called on end.. iterator.");
|
|
2549
2638
|
typename NonSooIntTable::iterator iter;
|
|
2550
2639
|
EXPECT_DEATH_IF_SUPPORTED(
|
|
2551
2640
|
++iter, "operator.* called on default-constructed iterator.");
|
|
2552
2641
|
t.insert(0);
|
|
2642
|
+
t.insert(1);
|
|
2553
2643
|
iter = t.begin();
|
|
2554
2644
|
t.erase(iter);
|
|
2555
2645
|
const char* const kErasedDeathMessage =
|
|
@@ -2653,18 +2743,29 @@ TYPED_TEST(SooTest, IteratorInvalidAssertsEqualityOperatorRehash) {
|
|
|
2653
2743
|
template <typename T>
|
|
2654
2744
|
class RawHashSamplerTest : public testing::Test {};
|
|
2655
2745
|
|
|
2656
|
-
using RawHashSamplerTestTypes = ::testing::Types<
|
|
2746
|
+
using RawHashSamplerTestTypes = ::testing::Types<
|
|
2747
|
+
// 32 bits to make sure that table is Soo for 32 bits platform as well.
|
|
2748
|
+
// 64 bits table is not SOO due to alignment.
|
|
2749
|
+
SooInt32Table,
|
|
2750
|
+
NonSooIntTable>;
|
|
2657
2751
|
TYPED_TEST_SUITE(RawHashSamplerTest, RawHashSamplerTestTypes);
|
|
2658
2752
|
|
|
2659
2753
|
TYPED_TEST(RawHashSamplerTest, Sample) {
|
|
2660
|
-
constexpr bool soo_enabled = std::is_same<
|
|
2754
|
+
constexpr bool soo_enabled = std::is_same<SooInt32Table, TypeParam>::value;
|
|
2661
2755
|
// Enable the feature even if the prod default is off.
|
|
2662
|
-
|
|
2663
|
-
|
|
2756
|
+
SetSamplingRateTo1Percent();
|
|
2757
|
+
|
|
2758
|
+
ASSERT_EQ(TypeParam().capacity(), soo_enabled ? SooCapacity() : 0);
|
|
2664
2759
|
|
|
2665
2760
|
auto& sampler = GlobalHashtablezSampler();
|
|
2666
2761
|
size_t start_size = 0;
|
|
2667
|
-
|
|
2762
|
+
|
|
2763
|
+
// Reserve these utility tables, so that if they sampled, they'll be
|
|
2764
|
+
// preexisting.
|
|
2765
|
+
absl::flat_hash_set<const HashtablezInfo*> preexisting_info(10);
|
|
2766
|
+
absl::flat_hash_map<size_t, int> observed_checksums(10);
|
|
2767
|
+
absl::flat_hash_map<ssize_t, int> reservations(10);
|
|
2768
|
+
|
|
2668
2769
|
start_size += sampler.Iterate([&](const HashtablezInfo& info) {
|
|
2669
2770
|
preexisting_info.insert(&info);
|
|
2670
2771
|
++start_size;
|
|
@@ -2691,8 +2792,6 @@ TYPED_TEST(RawHashSamplerTest, Sample) {
|
|
|
2691
2792
|
}
|
|
2692
2793
|
}
|
|
2693
2794
|
size_t end_size = 0;
|
|
2694
|
-
absl::flat_hash_map<size_t, int> observed_checksums;
|
|
2695
|
-
absl::flat_hash_map<ssize_t, int> reservations;
|
|
2696
2795
|
end_size += sampler.Iterate([&](const HashtablezInfo& info) {
|
|
2697
2796
|
++end_size;
|
|
2698
2797
|
if (preexisting_info.contains(&info)) return;
|
|
@@ -2713,12 +2812,12 @@ TYPED_TEST(RawHashSamplerTest, Sample) {
|
|
|
2713
2812
|
// Expect that we sampled at the requested sampling rate of ~1%.
|
|
2714
2813
|
EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
|
|
2715
2814
|
0.01, 0.005);
|
|
2716
|
-
|
|
2815
|
+
ASSERT_EQ(observed_checksums.size(), 5);
|
|
2717
2816
|
for (const auto& [_, count] : observed_checksums) {
|
|
2718
2817
|
EXPECT_NEAR((100 * count) / static_cast<double>(tables.size()), 0.2, 0.05);
|
|
2719
2818
|
}
|
|
2720
2819
|
|
|
2721
|
-
|
|
2820
|
+
ASSERT_EQ(reservations.size(), 10);
|
|
2722
2821
|
for (const auto& [reservation, count] : reservations) {
|
|
2723
2822
|
EXPECT_GE(reservation, 0);
|
|
2724
2823
|
EXPECT_LT(reservation, 100);
|
|
@@ -2729,25 +2828,25 @@ TYPED_TEST(RawHashSamplerTest, Sample) {
|
|
|
2729
2828
|
}
|
|
2730
2829
|
|
|
2731
2830
|
std::vector<const HashtablezInfo*> SampleSooMutation(
|
|
2732
|
-
absl::FunctionRef<void(
|
|
2831
|
+
absl::FunctionRef<void(SooInt32Table&)> mutate_table) {
|
|
2733
2832
|
// Enable the feature even if the prod default is off.
|
|
2734
|
-
|
|
2735
|
-
SetHashtablezSampleParameter(100); // Sample ~1% of tables.
|
|
2833
|
+
SetSamplingRateTo1Percent();
|
|
2736
2834
|
|
|
2737
2835
|
auto& sampler = GlobalHashtablezSampler();
|
|
2738
|
-
|
|
2739
|
-
|
|
2836
|
+
int64_t start_size = 0;
|
|
2837
|
+
// Reserve the table, so that if it sampled, it'll be preexisting.
|
|
2838
|
+
absl::flat_hash_set<const HashtablezInfo*> preexisting_info(10);
|
|
2740
2839
|
start_size += sampler.Iterate([&](const HashtablezInfo& info) {
|
|
2741
2840
|
preexisting_info.insert(&info);
|
|
2742
2841
|
++start_size;
|
|
2743
2842
|
});
|
|
2744
2843
|
|
|
2745
|
-
std::vector<
|
|
2844
|
+
std::vector<SooInt32Table> tables;
|
|
2746
2845
|
for (int i = 0; i < 1000000; ++i) {
|
|
2747
2846
|
tables.emplace_back();
|
|
2748
2847
|
mutate_table(tables.back());
|
|
2749
2848
|
}
|
|
2750
|
-
|
|
2849
|
+
int64_t end_size = 0;
|
|
2751
2850
|
std::vector<const HashtablezInfo*> infos;
|
|
2752
2851
|
end_size += sampler.Iterate([&](const HashtablezInfo& info) {
|
|
2753
2852
|
++end_size;
|
|
@@ -2762,16 +2861,16 @@ std::vector<const HashtablezInfo*> SampleSooMutation(
|
|
|
2762
2861
|
}
|
|
2763
2862
|
|
|
2764
2863
|
TEST(RawHashSamplerTest, SooTableInsertToEmpty) {
|
|
2765
|
-
if (
|
|
2864
|
+
if (SooInt32Table().capacity() != SooCapacity()) {
|
|
2766
2865
|
CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
|
|
2767
2866
|
GTEST_SKIP() << "not SOO on this platform";
|
|
2768
2867
|
}
|
|
2769
2868
|
std::vector<const HashtablezInfo*> infos =
|
|
2770
|
-
SampleSooMutation([](
|
|
2869
|
+
SampleSooMutation([](SooInt32Table& t) { t.insert(1); });
|
|
2771
2870
|
|
|
2772
2871
|
for (const HashtablezInfo* info : infos) {
|
|
2773
2872
|
ASSERT_EQ(info->inline_element_size,
|
|
2774
|
-
sizeof(typename
|
|
2873
|
+
sizeof(typename SooInt32Table::value_type));
|
|
2775
2874
|
ASSERT_EQ(info->soo_capacity, SooCapacity());
|
|
2776
2875
|
ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));
|
|
2777
2876
|
ASSERT_EQ(info->size, 1);
|
|
@@ -2783,16 +2882,16 @@ TEST(RawHashSamplerTest, SooTableInsertToEmpty) {
|
|
|
2783
2882
|
}
|
|
2784
2883
|
|
|
2785
2884
|
TEST(RawHashSamplerTest, SooTableReserveToEmpty) {
|
|
2786
|
-
if (
|
|
2885
|
+
if (SooInt32Table().capacity() != SooCapacity()) {
|
|
2787
2886
|
CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
|
|
2788
2887
|
GTEST_SKIP() << "not SOO on this platform";
|
|
2789
2888
|
}
|
|
2790
2889
|
std::vector<const HashtablezInfo*> infos =
|
|
2791
|
-
SampleSooMutation([](
|
|
2890
|
+
SampleSooMutation([](SooInt32Table& t) { t.reserve(100); });
|
|
2792
2891
|
|
|
2793
2892
|
for (const HashtablezInfo* info : infos) {
|
|
2794
2893
|
ASSERT_EQ(info->inline_element_size,
|
|
2795
|
-
sizeof(typename
|
|
2894
|
+
sizeof(typename SooInt32Table::value_type));
|
|
2796
2895
|
ASSERT_EQ(info->soo_capacity, SooCapacity());
|
|
2797
2896
|
ASSERT_GE(info->capacity, 100);
|
|
2798
2897
|
ASSERT_EQ(info->size, 0);
|
|
@@ -2806,19 +2905,19 @@ TEST(RawHashSamplerTest, SooTableReserveToEmpty) {
|
|
|
2806
2905
|
// This tests that reserve on a full SOO table doesn't incorrectly result in new
|
|
2807
2906
|
// (over-)sampling.
|
|
2808
2907
|
TEST(RawHashSamplerTest, SooTableReserveToFullSoo) {
|
|
2809
|
-
if (
|
|
2908
|
+
if (SooInt32Table().capacity() != SooCapacity()) {
|
|
2810
2909
|
CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
|
|
2811
2910
|
GTEST_SKIP() << "not SOO on this platform";
|
|
2812
2911
|
}
|
|
2813
2912
|
std::vector<const HashtablezInfo*> infos =
|
|
2814
|
-
SampleSooMutation([](
|
|
2913
|
+
SampleSooMutation([](SooInt32Table& t) {
|
|
2815
2914
|
t.insert(1);
|
|
2816
2915
|
t.reserve(100);
|
|
2817
2916
|
});
|
|
2818
2917
|
|
|
2819
2918
|
for (const HashtablezInfo* info : infos) {
|
|
2820
2919
|
ASSERT_EQ(info->inline_element_size,
|
|
2821
|
-
sizeof(typename
|
|
2920
|
+
sizeof(typename SooInt32Table::value_type));
|
|
2822
2921
|
ASSERT_EQ(info->soo_capacity, SooCapacity());
|
|
2823
2922
|
ASSERT_GE(info->capacity, 100);
|
|
2824
2923
|
ASSERT_EQ(info->size, 1);
|
|
@@ -2829,15 +2928,38 @@ TEST(RawHashSamplerTest, SooTableReserveToFullSoo) {
|
|
|
2829
2928
|
}
|
|
2830
2929
|
}
|
|
2831
2930
|
|
|
2931
|
+
TEST(RawHashSamplerTest, SooTableSampleOnCopy) {
|
|
2932
|
+
if (SooInt32Table().capacity() != SooCapacity()) {
|
|
2933
|
+
CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
|
|
2934
|
+
GTEST_SKIP() << "not SOO on this platform";
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
SooInt32Table t_orig;
|
|
2938
|
+
t_orig.insert(1);
|
|
2939
|
+
|
|
2940
|
+
std::vector<const HashtablezInfo*> infos =
|
|
2941
|
+
SampleSooMutation([&t_orig](SooInt32Table& t) {
|
|
2942
|
+
t = t_orig;
|
|
2943
|
+
});
|
|
2944
|
+
|
|
2945
|
+
for (const HashtablezInfo* info : infos) {
|
|
2946
|
+
ASSERT_EQ(info->inline_element_size,
|
|
2947
|
+
sizeof(typename SooInt32Table::value_type));
|
|
2948
|
+
ASSERT_EQ(info->soo_capacity, SooCapacity());
|
|
2949
|
+
ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));
|
|
2950
|
+
ASSERT_EQ(info->size, 1);
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2832
2954
|
// This tests that rehash(0) on a sampled table with size that fits in SOO
|
|
2833
2955
|
// doesn't incorrectly result in losing sampling.
|
|
2834
2956
|
TEST(RawHashSamplerTest, SooTableRehashShrinkWhenSizeFitsInSoo) {
|
|
2835
|
-
if (
|
|
2957
|
+
if (SooInt32Table().capacity() != SooCapacity()) {
|
|
2836
2958
|
CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
|
|
2837
2959
|
GTEST_SKIP() << "not SOO on this platform";
|
|
2838
2960
|
}
|
|
2839
2961
|
std::vector<const HashtablezInfo*> infos =
|
|
2840
|
-
SampleSooMutation([](
|
|
2962
|
+
SampleSooMutation([](SooInt32Table& t) {
|
|
2841
2963
|
t.reserve(100);
|
|
2842
2964
|
t.insert(1);
|
|
2843
2965
|
EXPECT_GE(t.capacity(), 100);
|
|
@@ -2846,7 +2968,7 @@ TEST(RawHashSamplerTest, SooTableRehashShrinkWhenSizeFitsInSoo) {
|
|
|
2846
2968
|
|
|
2847
2969
|
for (const HashtablezInfo* info : infos) {
|
|
2848
2970
|
ASSERT_EQ(info->inline_element_size,
|
|
2849
|
-
sizeof(typename
|
|
2971
|
+
sizeof(typename SooInt32Table::value_type));
|
|
2850
2972
|
ASSERT_EQ(info->soo_capacity, SooCapacity());
|
|
2851
2973
|
ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));
|
|
2852
2974
|
ASSERT_EQ(info->size, 1);
|
|
@@ -2860,19 +2982,19 @@ TEST(RawHashSamplerTest, SooTableRehashShrinkWhenSizeFitsInSoo) {
|
|
|
2860
2982
|
|
|
2861
2983
|
TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
|
|
2862
2984
|
// Enable the feature even if the prod default is off.
|
|
2863
|
-
|
|
2864
|
-
SetHashtablezSampleParameter(100); // Sample ~1% of tables.
|
|
2985
|
+
SetSamplingRateTo1Percent();
|
|
2865
2986
|
|
|
2866
2987
|
auto& sampler = GlobalHashtablezSampler();
|
|
2867
|
-
|
|
2988
|
+
int64_t start_size = 0;
|
|
2868
2989
|
start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
|
|
2869
2990
|
|
|
2870
2991
|
std::vector<CustomAllocIntTable> tables;
|
|
2871
|
-
for (int i = 0; i <
|
|
2992
|
+
for (int i = 0; i < 100000; ++i) {
|
|
2872
2993
|
tables.emplace_back();
|
|
2873
2994
|
tables.back().insert(1);
|
|
2995
|
+
tables.push_back(tables.back()); // Copies the table.
|
|
2874
2996
|
}
|
|
2875
|
-
|
|
2997
|
+
int64_t end_size = 0;
|
|
2876
2998
|
end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; });
|
|
2877
2999
|
|
|
2878
3000
|
EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
|
|
@@ -2904,6 +3026,20 @@ TYPED_TEST(SanitizerTest, PoisoningUnused) {
|
|
|
2904
3026
|
}
|
|
2905
3027
|
}
|
|
2906
3028
|
|
|
3029
|
+
TYPED_TEST(SanitizerTest, PoisoningUnusedOnGrowth) {
|
|
3030
|
+
TypeParam t;
|
|
3031
|
+
for (int64_t i = 0; i < 100; ++i) {
|
|
3032
|
+
t.insert(i);
|
|
3033
|
+
|
|
3034
|
+
int64_t* slots = RawHashSetTestOnlyAccess::GetSlots(t);
|
|
3035
|
+
int poisoned = 0;
|
|
3036
|
+
for (size_t i = 0; i < t.capacity(); ++i) {
|
|
3037
|
+
poisoned += static_cast<int>(__asan_address_is_poisoned(slots + i));
|
|
3038
|
+
}
|
|
3039
|
+
ASSERT_EQ(poisoned, t.capacity() - t.size());
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
|
|
2907
3043
|
// TODO(b/289225379): poison inline space when empty SOO.
|
|
2908
3044
|
TEST(Sanitizer, PoisoningOnErase) {
|
|
2909
3045
|
NonSooIntTable t;
|
|
@@ -2926,28 +3062,27 @@ TYPED_TEST(AlignOneTest, AlignOne) {
|
|
|
2926
3062
|
// first slot when alignof(value_type) is 1. We test repeated
|
|
2927
3063
|
// insertions/erases and verify that the behavior is correct.
|
|
2928
3064
|
TypeParam t;
|
|
2929
|
-
std::
|
|
3065
|
+
std::bitset<256> verifier;
|
|
2930
3066
|
|
|
2931
3067
|
// Do repeated insertions/erases from the table.
|
|
2932
|
-
for (int64_t i = 0; i <
|
|
3068
|
+
for (int64_t i = 0; i < 10000; ++i) {
|
|
2933
3069
|
SCOPED_TRACE(i);
|
|
2934
3070
|
const uint8_t u = (i * -i) & 0xFF;
|
|
2935
3071
|
auto it = t.find(u);
|
|
2936
|
-
auto verifier_it = verifier.find(u);
|
|
2937
3072
|
if (it == t.end()) {
|
|
2938
|
-
|
|
3073
|
+
ASSERT_FALSE(verifier.test(u));
|
|
2939
3074
|
t.insert(u);
|
|
2940
|
-
verifier.
|
|
3075
|
+
verifier.set(u);
|
|
2941
3076
|
} else {
|
|
2942
|
-
|
|
3077
|
+
ASSERT_TRUE(verifier.test(u));
|
|
2943
3078
|
t.erase(it);
|
|
2944
|
-
verifier.
|
|
3079
|
+
verifier.reset(u);
|
|
2945
3080
|
}
|
|
2946
3081
|
}
|
|
2947
3082
|
|
|
2948
|
-
EXPECT_EQ(t.size(), verifier.
|
|
3083
|
+
EXPECT_EQ(t.size(), verifier.count());
|
|
2949
3084
|
for (uint8_t u : t) {
|
|
2950
|
-
|
|
3085
|
+
ASSERT_TRUE(verifier.test(u));
|
|
2951
3086
|
}
|
|
2952
3087
|
}
|
|
2953
3088
|
|
|
@@ -3315,11 +3450,13 @@ TEST(Iterator, InvalidComparisonDifferentTables) {
|
|
|
3315
3450
|
EXPECT_DEATH_IF_SUPPORTED(void(t1.end() == default_constructed_iter),
|
|
3316
3451
|
"Invalid iterator comparison.*default-constructed");
|
|
3317
3452
|
t1.insert(0);
|
|
3453
|
+
t1.insert(1);
|
|
3318
3454
|
EXPECT_DEATH_IF_SUPPORTED(void(t1.begin() == t2.end()),
|
|
3319
3455
|
"Invalid iterator comparison.*empty hashtable");
|
|
3320
3456
|
EXPECT_DEATH_IF_SUPPORTED(void(t1.begin() == default_constructed_iter),
|
|
3321
3457
|
"Invalid iterator comparison.*default-constructed");
|
|
3322
3458
|
t2.insert(0);
|
|
3459
|
+
t2.insert(1);
|
|
3323
3460
|
EXPECT_DEATH_IF_SUPPORTED(void(t1.begin() == t2.end()),
|
|
3324
3461
|
"Invalid iterator comparison.*end.. iterator");
|
|
3325
3462
|
EXPECT_DEATH_IF_SUPPORTED(void(t1.begin() == t2.begin()),
|
|
@@ -3358,73 +3495,80 @@ TEST(Table, CountedHash) {
|
|
|
3358
3495
|
GTEST_SKIP() << "Only run under NDEBUG: `assert` statements may cause "
|
|
3359
3496
|
"redundant hashing.";
|
|
3360
3497
|
}
|
|
3498
|
+
// When the table is sampled, we need to hash on the first insertion.
|
|
3499
|
+
DisableSampling();
|
|
3361
3500
|
|
|
3362
3501
|
using Table = CountedHashIntTable;
|
|
3363
3502
|
auto HashCount = [](const Table& t) { return t.hash_function().count; };
|
|
3364
3503
|
{
|
|
3365
3504
|
Table t;
|
|
3505
|
+
t.find(0);
|
|
3366
3506
|
EXPECT_EQ(HashCount(t), 0);
|
|
3367
3507
|
}
|
|
3368
3508
|
{
|
|
3369
3509
|
Table t;
|
|
3370
3510
|
t.insert(1);
|
|
3371
|
-
|
|
3511
|
+
t.find(1);
|
|
3512
|
+
EXPECT_EQ(HashCount(t), 0);
|
|
3372
3513
|
t.erase(1);
|
|
3514
|
+
EXPECT_EQ(HashCount(t), 0);
|
|
3515
|
+
t.insert(1);
|
|
3516
|
+
t.insert(2);
|
|
3373
3517
|
EXPECT_EQ(HashCount(t), 2);
|
|
3374
3518
|
}
|
|
3375
3519
|
{
|
|
3376
3520
|
Table t;
|
|
3377
3521
|
t.insert(3);
|
|
3378
|
-
EXPECT_EQ(HashCount(t),
|
|
3522
|
+
EXPECT_EQ(HashCount(t), 0);
|
|
3379
3523
|
auto node = t.extract(3);
|
|
3380
|
-
EXPECT_EQ(HashCount(t),
|
|
3524
|
+
EXPECT_EQ(HashCount(t), 0);
|
|
3381
3525
|
t.insert(std::move(node));
|
|
3382
|
-
EXPECT_EQ(HashCount(t),
|
|
3526
|
+
EXPECT_EQ(HashCount(t), 0);
|
|
3383
3527
|
}
|
|
3384
3528
|
{
|
|
3385
3529
|
Table t;
|
|
3386
3530
|
t.emplace(5);
|
|
3387
|
-
EXPECT_EQ(HashCount(t),
|
|
3531
|
+
EXPECT_EQ(HashCount(t), 0);
|
|
3388
3532
|
}
|
|
3389
3533
|
{
|
|
3390
3534
|
Table src;
|
|
3391
3535
|
src.insert(7);
|
|
3392
3536
|
Table dst;
|
|
3393
3537
|
dst.merge(src);
|
|
3394
|
-
EXPECT_EQ(HashCount(dst),
|
|
3538
|
+
EXPECT_EQ(HashCount(dst), 0);
|
|
3395
3539
|
}
|
|
3396
3540
|
}
|
|
3397
3541
|
|
|
3398
3542
|
// IterateOverFullSlots doesn't support SOO.
|
|
3399
3543
|
TEST(Table, IterateOverFullSlotsEmpty) {
|
|
3400
3544
|
NonSooIntTable t;
|
|
3401
|
-
|
|
3402
|
-
|
|
3545
|
+
using SlotType = NonSooIntTableSlotType;
|
|
3546
|
+
auto fail_if_any = [](const ctrl_t*, void* i) {
|
|
3547
|
+
FAIL() << "expected no slots " << **static_cast<SlotType*>(i);
|
|
3403
3548
|
};
|
|
3404
|
-
|
|
3405
|
-
RawHashSetTestOnlyAccess::GetCommon(t),
|
|
3406
|
-
RawHashSetTestOnlyAccess::GetSlots(t), fail_if_any);
|
|
3407
|
-
for (size_t i = 0; i < 256; ++i) {
|
|
3549
|
+
for (size_t i = 2; i < 256; ++i) {
|
|
3408
3550
|
t.reserve(i);
|
|
3409
3551
|
container_internal::IterateOverFullSlots(
|
|
3410
|
-
RawHashSetTestOnlyAccess::GetCommon(t),
|
|
3411
|
-
RawHashSetTestOnlyAccess::GetSlots(t), fail_if_any);
|
|
3552
|
+
RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType), fail_if_any);
|
|
3412
3553
|
}
|
|
3413
3554
|
}
|
|
3414
3555
|
|
|
3415
3556
|
TEST(Table, IterateOverFullSlotsFull) {
|
|
3416
3557
|
NonSooIntTable t;
|
|
3558
|
+
using SlotType = NonSooIntTableSlotType;
|
|
3417
3559
|
|
|
3418
3560
|
std::vector<int64_t> expected_slots;
|
|
3419
|
-
|
|
3561
|
+
t.insert(0);
|
|
3562
|
+
expected_slots.push_back(0);
|
|
3563
|
+
for (int64_t idx = 1; idx < 128; ++idx) {
|
|
3420
3564
|
t.insert(idx);
|
|
3421
3565
|
expected_slots.push_back(idx);
|
|
3422
3566
|
|
|
3423
3567
|
std::vector<int64_t> slots;
|
|
3424
3568
|
container_internal::IterateOverFullSlots(
|
|
3425
|
-
RawHashSetTestOnlyAccess::GetCommon(t),
|
|
3426
|
-
|
|
3427
|
-
|
|
3569
|
+
RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),
|
|
3570
|
+
[&t, &slots](const ctrl_t* ctrl, void* slot) {
|
|
3571
|
+
SlotType* i = static_cast<SlotType*>(slot);
|
|
3428
3572
|
ptrdiff_t ctrl_offset =
|
|
3429
3573
|
ctrl - RawHashSetTestOnlyAccess::GetCommon(t).control();
|
|
3430
3574
|
ptrdiff_t slot_offset = i - RawHashSetTestOnlyAccess::GetSlots(t);
|
|
@@ -3443,16 +3587,16 @@ TEST(Table, IterateOverFullSlotsDeathOnRemoval) {
|
|
|
3443
3587
|
if (reserve_size == -1) reserve_size = size;
|
|
3444
3588
|
for (int64_t idx = 0; idx < size; ++idx) {
|
|
3445
3589
|
NonSooIntTable t;
|
|
3590
|
+
using SlotType = NonSooIntTableSlotType;
|
|
3446
3591
|
t.reserve(static_cast<size_t>(reserve_size));
|
|
3447
3592
|
for (int val = 0; val <= idx; ++val) {
|
|
3448
3593
|
t.insert(val);
|
|
3449
3594
|
}
|
|
3450
3595
|
|
|
3451
3596
|
container_internal::IterateOverFullSlots(
|
|
3452
|
-
RawHashSetTestOnlyAccess::GetCommon(t),
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
int64_t value = **i;
|
|
3597
|
+
RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),
|
|
3598
|
+
[&t](const ctrl_t*, void* slot) {
|
|
3599
|
+
int64_t value = **static_cast<SlotType*>(slot);
|
|
3456
3600
|
// Erase the other element from 2*k and 2*k+1 pair.
|
|
3457
3601
|
t.erase(value ^ 1);
|
|
3458
3602
|
});
|
|
@@ -3478,16 +3622,16 @@ TEST(Table, IterateOverFullSlotsDeathOnInsert) {
|
|
|
3478
3622
|
int64_t size = reserve_size / size_divisor;
|
|
3479
3623
|
for (int64_t idx = 1; idx <= size; ++idx) {
|
|
3480
3624
|
NonSooIntTable t;
|
|
3625
|
+
using SlotType = NonSooIntTableSlotType;
|
|
3481
3626
|
t.reserve(static_cast<size_t>(reserve_size));
|
|
3482
3627
|
for (int val = 1; val <= idx; ++val) {
|
|
3483
3628
|
t.insert(val);
|
|
3484
3629
|
}
|
|
3485
3630
|
|
|
3486
3631
|
container_internal::IterateOverFullSlots(
|
|
3487
|
-
RawHashSetTestOnlyAccess::GetCommon(t),
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
int64_t value = **i;
|
|
3632
|
+
RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),
|
|
3633
|
+
[&t](const ctrl_t*, void* slot) {
|
|
3634
|
+
int64_t value = **static_cast<SlotType*>(slot);
|
|
3491
3635
|
t.insert(-value);
|
|
3492
3636
|
});
|
|
3493
3637
|
}
|
|
@@ -3550,7 +3694,7 @@ TEST(Table, RehashToSooUnsampled) {
|
|
|
3550
3694
|
|
|
3551
3695
|
// We disable hashtablez sampling for this test to ensure that the table isn't
|
|
3552
3696
|
// sampled. When the table is sampled, it won't rehash down to SOO.
|
|
3553
|
-
|
|
3697
|
+
DisableSampling();
|
|
3554
3698
|
|
|
3555
3699
|
t.reserve(100);
|
|
3556
3700
|
t.insert(0);
|
|
@@ -3566,7 +3710,7 @@ TEST(Table, RehashToSooUnsampled) {
|
|
|
3566
3710
|
}
|
|
3567
3711
|
|
|
3568
3712
|
TEST(Table, ReserveToNonSoo) {
|
|
3569
|
-
for (
|
|
3713
|
+
for (size_t reserve_capacity : {2u, 8u, 100000u}) {
|
|
3570
3714
|
SooIntTable t;
|
|
3571
3715
|
t.insert(0);
|
|
3572
3716
|
|
|
@@ -3679,17 +3823,68 @@ TEST(Table, ReentrantCallsFail) {
|
|
|
3679
3823
|
#endif
|
|
3680
3824
|
}
|
|
3681
3825
|
|
|
3826
|
+
// TODO(b/328794765): this check is very useful to run with ASAN in opt mode.
|
|
3682
3827
|
TEST(Table, DestroyedCallsFail) {
|
|
3683
3828
|
#ifdef NDEBUG
|
|
3684
|
-
|
|
3829
|
+
ASSERT_EQ(SwisstableAssertAccessToDestroyedTable(),
|
|
3830
|
+
SwisstableGenerationsEnabled());
|
|
3685
3831
|
#else
|
|
3832
|
+
ASSERT_TRUE(SwisstableAssertAccessToDestroyedTable());
|
|
3833
|
+
#endif
|
|
3834
|
+
if (!SwisstableAssertAccessToDestroyedTable()) {
|
|
3835
|
+
GTEST_SKIP() << "Validation not enabled.";
|
|
3836
|
+
}
|
|
3837
|
+
#if !defined(__clang__) && defined(__GNUC__)
|
|
3838
|
+
GTEST_SKIP() << "Flaky on GCC.";
|
|
3839
|
+
#endif
|
|
3686
3840
|
absl::optional<IntTable> t;
|
|
3687
3841
|
t.emplace({1});
|
|
3688
3842
|
IntTable* t_ptr = &*t;
|
|
3689
3843
|
EXPECT_TRUE(t_ptr->contains(1));
|
|
3690
3844
|
t.reset();
|
|
3691
|
-
|
|
3845
|
+
std::string expected_death_message =
|
|
3846
|
+
#if defined(ABSL_HAVE_MEMORY_SANITIZER)
|
|
3847
|
+
"use-of-uninitialized-value";
|
|
3848
|
+
#else
|
|
3849
|
+
"destroyed hash table";
|
|
3692
3850
|
#endif
|
|
3851
|
+
EXPECT_DEATH_IF_SUPPORTED(t_ptr->contains(1), expected_death_message);
|
|
3852
|
+
}
|
|
3853
|
+
|
|
3854
|
+
TEST(Table, DestroyedCallsFailDuringDestruction) {
|
|
3855
|
+
if (!SwisstableAssertAccessToDestroyedTable()) {
|
|
3856
|
+
GTEST_SKIP() << "Validation not enabled.";
|
|
3857
|
+
}
|
|
3858
|
+
#if !defined(__clang__) && defined(__GNUC__)
|
|
3859
|
+
GTEST_SKIP() << "Flaky on GCC.";
|
|
3860
|
+
#endif
|
|
3861
|
+
// When EXPECT_DEATH_IF_SUPPORTED is not executed, the code after it is not
|
|
3862
|
+
// executed as well.
|
|
3863
|
+
// We need to destruct the table correctly in such a case.
|
|
3864
|
+
// Must be defined before the table for correct destruction order.
|
|
3865
|
+
bool do_lookup = false;
|
|
3866
|
+
|
|
3867
|
+
using Table = absl::flat_hash_map<int, std::shared_ptr<int>>;
|
|
3868
|
+
absl::optional<Table> t = Table();
|
|
3869
|
+
Table* t_ptr = &*t;
|
|
3870
|
+
auto destroy = [&](int* ptr) {
|
|
3871
|
+
if (do_lookup) {
|
|
3872
|
+
ASSERT_TRUE(t_ptr->contains(*ptr));
|
|
3873
|
+
}
|
|
3874
|
+
delete ptr;
|
|
3875
|
+
};
|
|
3876
|
+
t->insert({0, std::shared_ptr<int>(new int(0), destroy)});
|
|
3877
|
+
auto destroy_with_lookup = [&] {
|
|
3878
|
+
do_lookup = true;
|
|
3879
|
+
t.reset();
|
|
3880
|
+
};
|
|
3881
|
+
std::string expected_death_message =
|
|
3882
|
+
#ifdef NDEBUG
|
|
3883
|
+
"destroyed hash table";
|
|
3884
|
+
#else
|
|
3885
|
+
"Reentrant container access";
|
|
3886
|
+
#endif
|
|
3887
|
+
EXPECT_DEATH_IF_SUPPORTED(destroy_with_lookup(), expected_death_message);
|
|
3693
3888
|
}
|
|
3694
3889
|
|
|
3695
3890
|
TEST(Table, MovedFromCallsFail) {
|
|
@@ -3737,12 +3932,161 @@ TEST(Table, MovedFromCallsFail) {
|
|
|
3737
3932
|
}
|
|
3738
3933
|
}
|
|
3739
3934
|
|
|
3935
|
+
TEST(HashtableSize, GenerateNewSeedDoesntChangeSize) {
|
|
3936
|
+
size_t size = 1;
|
|
3937
|
+
do {
|
|
3938
|
+
HashtableSize hs(no_seed_empty_tag_t{});
|
|
3939
|
+
hs.increment_size(size);
|
|
3940
|
+
EXPECT_EQ(hs.size(), size);
|
|
3941
|
+
hs.generate_new_seed();
|
|
3942
|
+
EXPECT_EQ(hs.size(), size);
|
|
3943
|
+
size = size * 2 + 1;
|
|
3944
|
+
} while (size < MaxValidSizeFor1ByteSlot());
|
|
3945
|
+
}
|
|
3946
|
+
|
|
3947
|
+
TEST(Table, MaxValidSize) {
|
|
3948
|
+
IntTable t;
|
|
3949
|
+
EXPECT_EQ(MaxValidSize(sizeof(IntTable::value_type)), t.max_size());
|
|
3950
|
+
if constexpr (sizeof(size_t) == 8) {
|
|
3951
|
+
for (size_t i = 0; i < 35; ++i) {
|
|
3952
|
+
SCOPED_TRACE(i);
|
|
3953
|
+
size_t slot_size = size_t{1} << i;
|
|
3954
|
+
size_t max_size = MaxValidSize(slot_size);
|
|
3955
|
+
ASSERT_FALSE(IsAboveValidSize(max_size, slot_size));
|
|
3956
|
+
ASSERT_TRUE(IsAboveValidSize(max_size + 1, slot_size));
|
|
3957
|
+
ASSERT_LT(max_size, uint64_t{1} << 60);
|
|
3958
|
+
// For non gigantic slot sizes we expect max size to be at least 2^40.
|
|
3959
|
+
if (i <= 22) {
|
|
3960
|
+
ASSERT_FALSE(IsAboveValidSize(size_t{1} << 40, slot_size));
|
|
3961
|
+
ASSERT_GE(max_size, uint64_t{1} << 40);
|
|
3962
|
+
}
|
|
3963
|
+
ASSERT_LT(SizeToCapacity(max_size),
|
|
3964
|
+
uint64_t{1} << HashtableSize::kSizeBitCount);
|
|
3965
|
+
ASSERT_LT(absl::uint128(max_size) * slot_size, uint64_t{1} << 63);
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
EXPECT_LT(MaxValidSize</*kSizeOfSizeT=*/4>(1), 1 << 30);
|
|
3969
|
+
EXPECT_LT(MaxValidSize</*kSizeOfSizeT=*/4>(2), 1 << 29);
|
|
3970
|
+
for (size_t i = 0; i < 29; ++i) {
|
|
3971
|
+
size_t slot_size = size_t{1} << i;
|
|
3972
|
+
size_t max_size = MaxValidSize</*kSizeOfSizeT=*/4>(slot_size);
|
|
3973
|
+
ASSERT_FALSE(IsAboveValidSize</*kSizeOfSizeT=*/4>(max_size, slot_size));
|
|
3974
|
+
ASSERT_TRUE(IsAboveValidSize</*kSizeOfSizeT=*/4>(max_size + 1, slot_size));
|
|
3975
|
+
ASSERT_LT(max_size, 1 << 30);
|
|
3976
|
+
size_t max_capacity = SizeToCapacity(max_size);
|
|
3977
|
+
ASSERT_LT(max_capacity, (size_t{1} << 31) / slot_size);
|
|
3978
|
+
ASSERT_GT(max_capacity, (1 << 29) / slot_size);
|
|
3979
|
+
ASSERT_LT(max_capacity * slot_size, size_t{1} << 31);
|
|
3980
|
+
}
|
|
3981
|
+
}
|
|
3982
|
+
|
|
3740
3983
|
TEST(Table, MaxSizeOverflow) {
|
|
3741
3984
|
size_t overflow = (std::numeric_limits<size_t>::max)();
|
|
3742
3985
|
EXPECT_DEATH_IF_SUPPORTED(IntTable t(overflow), "Hash table size overflow");
|
|
3743
3986
|
IntTable t;
|
|
3744
3987
|
EXPECT_DEATH_IF_SUPPORTED(t.reserve(overflow), "Hash table size overflow");
|
|
3745
3988
|
EXPECT_DEATH_IF_SUPPORTED(t.rehash(overflow), "Hash table size overflow");
|
|
3989
|
+
size_t slightly_overflow = MaxValidSize(sizeof(IntTable::value_type)) + 1;
|
|
3990
|
+
size_t slightly_overflow_capacity =
|
|
3991
|
+
NextCapacity(NormalizeCapacity(slightly_overflow));
|
|
3992
|
+
EXPECT_DEATH_IF_SUPPORTED(IntTable t2(slightly_overflow_capacity - 10),
|
|
3993
|
+
"Hash table size overflow");
|
|
3994
|
+
EXPECT_DEATH_IF_SUPPORTED(t.reserve(slightly_overflow),
|
|
3995
|
+
"Hash table size overflow");
|
|
3996
|
+
EXPECT_DEATH_IF_SUPPORTED(t.rehash(slightly_overflow),
|
|
3997
|
+
"Hash table size overflow");
|
|
3998
|
+
IntTable non_empty_table;
|
|
3999
|
+
non_empty_table.insert(0);
|
|
4000
|
+
EXPECT_DEATH_IF_SUPPORTED(non_empty_table.reserve(slightly_overflow),
|
|
4001
|
+
"Hash table size overflow");
|
|
4002
|
+
}
|
|
4003
|
+
|
|
4004
|
+
// TODO(b/397453582): Remove support for const hasher and remove this test.
|
|
4005
|
+
TEST(Table, ConstLambdaHash) {
|
|
4006
|
+
int64_t multiplier = 17;
|
|
4007
|
+
// Make sure that code compiles and work OK with non-empty hasher with const
|
|
4008
|
+
// qualifier.
|
|
4009
|
+
const auto hash = [multiplier](SizedValue<64> value) -> size_t {
|
|
4010
|
+
return static_cast<size_t>(static_cast<int64_t>(value) * multiplier);
|
|
4011
|
+
};
|
|
4012
|
+
static_assert(!std::is_empty_v<decltype(hash)>);
|
|
4013
|
+
absl::flat_hash_set<SizedValue<64>, decltype(hash)> t(0, hash);
|
|
4014
|
+
t.insert(1);
|
|
4015
|
+
EXPECT_EQ(t.size(), 1);
|
|
4016
|
+
EXPECT_EQ(t.find(1), t.begin());
|
|
4017
|
+
EXPECT_EQ(t.find(2), t.end());
|
|
4018
|
+
t.insert(2);
|
|
4019
|
+
EXPECT_EQ(t.size(), 2);
|
|
4020
|
+
EXPECT_NE(t.find(1), t.end());
|
|
4021
|
+
EXPECT_NE(t.find(2), t.end());
|
|
4022
|
+
EXPECT_EQ(t.find(3), t.end());
|
|
4023
|
+
}
|
|
4024
|
+
|
|
4025
|
+
struct ConstUint8Hash {
|
|
4026
|
+
size_t operator()(uint8_t) const { return *value; }
|
|
4027
|
+
size_t* value;
|
|
4028
|
+
};
|
|
4029
|
+
|
|
4030
|
+
// This test is imitating growth of a very big table and triggers all buffer
|
|
4031
|
+
// overflows.
|
|
4032
|
+
// We try to insert all elements into the first probe group.
|
|
4033
|
+
// So the resize codepath in test does the following:
|
|
4034
|
+
// 1. Insert 16 elements into the first probe group. No other elements will be
|
|
4035
|
+
// inserted into the first probe group.
|
|
4036
|
+
// 2. There will be enough elements to fill up the local buffer even for
|
|
4037
|
+
// encoding with 4 bytes.
|
|
4038
|
+
// 3. After local buffer is full, we will fill up the control buffer till
|
|
4039
|
+
// some point.
|
|
4040
|
+
// 4. Then a few times we will extend control buffer end.
|
|
4041
|
+
// 5. Finally we will catch up and go to overflow codepath.
|
|
4042
|
+
TEST(Table, GrowExtremelyLargeTable) {
|
|
4043
|
+
constexpr size_t kTargetCapacity =
|
|
4044
|
+
#if defined(__wasm__) || defined(__asmjs__) || defined(__i386__)
|
|
4045
|
+
NextCapacity(ProbedItem4Bytes::kMaxNewCapacity); // OOMs on WASM, 32-bit.
|
|
4046
|
+
#else
|
|
4047
|
+
NextCapacity(ProbedItem8Bytes::kMaxNewCapacity);
|
|
4048
|
+
#endif
|
|
4049
|
+
|
|
4050
|
+
size_t hash = 0;
|
|
4051
|
+
// In order to save memory we use 1 byte slot.
|
|
4052
|
+
// There are not enough different values to achieve big capacity, so we
|
|
4053
|
+
// artificially update growth info to force resize.
|
|
4054
|
+
absl::flat_hash_set<uint8_t, ConstUint8Hash> t(63, ConstUint8Hash{&hash});
|
|
4055
|
+
CommonFields& common = RawHashSetTestOnlyAccess::GetCommon(t);
|
|
4056
|
+
// Set 0 seed so that H1 is always 0.
|
|
4057
|
+
common.set_no_seed_for_testing();
|
|
4058
|
+
ASSERT_EQ(H1(t.hash_function()(75)), 0);
|
|
4059
|
+
uint8_t inserted_till = 210;
|
|
4060
|
+
for (uint8_t i = 0; i < inserted_till; ++i) {
|
|
4061
|
+
t.insert(i);
|
|
4062
|
+
}
|
|
4063
|
+
for (uint8_t i = 0; i < inserted_till; ++i) {
|
|
4064
|
+
ASSERT_TRUE(t.contains(i));
|
|
4065
|
+
}
|
|
4066
|
+
|
|
4067
|
+
for (size_t cap = t.capacity(); cap < kTargetCapacity;
|
|
4068
|
+
cap = NextCapacity(cap)) {
|
|
4069
|
+
ASSERT_EQ(t.capacity(), cap);
|
|
4070
|
+
// Update growth info to force resize on the next insert.
|
|
4071
|
+
common.growth_info().OverwriteManyEmptyAsFull(CapacityToGrowth(cap) -
|
|
4072
|
+
t.size());
|
|
4073
|
+
t.insert(inserted_till++);
|
|
4074
|
+
ASSERT_EQ(t.capacity(), NextCapacity(cap));
|
|
4075
|
+
for (uint8_t i = 0; i < inserted_till; ++i) {
|
|
4076
|
+
ASSERT_TRUE(t.contains(i));
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
EXPECT_EQ(t.capacity(), kTargetCapacity);
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
// Test that after calling generate_new_seed(), the high bits of the returned
|
|
4083
|
+
// seed are non-zero.
|
|
4084
|
+
TEST(PerTableSeed, HighBitsAreNonZero) {
|
|
4085
|
+
HashtableSize hs(no_seed_empty_tag_t{});
|
|
4086
|
+
for (int i = 0; i < 100; ++i) {
|
|
4087
|
+
hs.generate_new_seed();
|
|
4088
|
+
ASSERT_GT(hs.seed().seed() >> 16, 0);
|
|
4089
|
+
}
|
|
3746
4090
|
}
|
|
3747
4091
|
|
|
3748
4092
|
} // namespace
|