mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 20:14:23 +08:00
-- 04cb3b22497190170aa5b774e98080c5de2ba60b by Abseil Team <absl-team@google.com>: Alternative bit mixer for LowLevelHash on ARM LowLevelHash's bit-mixer is inefficient on ARM because it calculates a 128-bit product of two 64-bit numbers. On ARM, this requires a sequence of two instructions with a high combined latency and poor throughput. This change provides alternative bit-mixing code for ARM that uses only 64-bit arithmetic (multiplication, xor, and left-shifts) and speeds things up considerably. The bit-mixing code for ARM was inspired by by Woothash[1] and xxh3[1]. Once I landed on a sequence of operations that provided good mixing, I used a test harness to search for the combination of shift / rotate factors that provided the best mixing, as indicated by SMHasher hash quality tests. The new mixing code passes 13 out of 15 of the hash quality test suites in SMHasher, with the two failures being in the noise range: e.g. 1 collision vs. zero expected in a keyset of ~8m keys. [1]: https://github.com/tommyettinger/waterhash/blob/49f5cf0b63b9/woothash.h#L16-L20 [2]: https://github.com/Cyan4973/xxHash/blob/6853ddc36e46/xxhash.h#L3240-L3265 PiperOrigin-RevId: 391833008 -- 17a4de1f9d623155c75b19285d414cd55a487cd6 by Saleem Abdulrasool <abdulras@google.com>: debugging: add support for unwinding on RISCV Linux This adds partial support for unwinding the RISCV call stack. It is largely duplicated from the AArch64 support with alterations for the ELF RISCV psABI. This covers RISCV64 and RISCV32, though not the ILP32E calling convention. PiperOrigin-RevId: 391818522 -- 32c93e449327b2cea32b32f6365e84b420fe1ed3 by Gennadiy Rozental <rogeeff@google.com>: New storage for types smaller than 8 bytes. Also adding new read interface for types smaller than or rqual to 8 bytes to avoid passing the pointer. PiperOrigin-RevId: 391726822 -- e987ac08a7787801cbfc7d7c96649e97fa8cff1a by Abseil Team <absl-team@google.com>: Extern template `find_first_non_full` to reduce linkage size for TU with single not inlined function. PiperOrigin-RevId: 391718862 -- 73af9bfcb5bf045089133e18bbd20eb5bb699172 by Gennadiy Rozental <rogeeff@google.com>: Make most non-mutable most int128 methods and friend free functions constexpr. Some functions are implemented offline (at least in some configurations) and can't be made constexpr. Mutable methods can't be made constexpr until we drop c++11 support. Fixes #978 PiperOrigin-RevId: 391706535 GitOrigin-RevId: 04cb3b22497190170aa5b774e98080c5de2ba60b Change-Id: If051fad5ff004e2e82fa53618fc04a6fe3d2d4be
143 lines
5.2 KiB
C++
143 lines
5.2 KiB
C++
// Copyright 2017 The Abseil Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Produce stack trace.
|
|
//
|
|
// There are three different ways we can try to get the stack trace:
|
|
//
|
|
// 1) Our hand-coded stack-unwinder. This depends on a certain stack
|
|
// layout, which is used by gcc (and those systems using a
|
|
// gcc-compatible ABI) on x86 systems, at least since gcc 2.95.
|
|
// It uses the frame pointer to do its work.
|
|
//
|
|
// 2) The libunwind library. This is still in development, and as a
|
|
// separate library adds a new dependency, but doesn't need a frame
|
|
// pointer. It also doesn't call malloc.
|
|
//
|
|
// 3) The gdb unwinder -- also the one used by the c++ exception code.
|
|
// It's obviously well-tested, but has a fatal flaw: it can call
|
|
// malloc() from the unwinder. This is a problem because we're
|
|
// trying to use the unwinder to instrument malloc().
|
|
//
|
|
// Note: if you add a new implementation here, make sure it works
|
|
// correctly when absl::GetStackTrace() is called with max_depth == 0.
|
|
// Some code may do that.
|
|
|
|
#include "absl/debugging/stacktrace.h"
|
|
|
|
#include <atomic>
|
|
|
|
#include "absl/base/attributes.h"
|
|
#include "absl/base/port.h"
|
|
#include "absl/debugging/internal/stacktrace_config.h"
|
|
|
|
#if defined(ABSL_STACKTRACE_INL_HEADER)
|
|
#include ABSL_STACKTRACE_INL_HEADER
|
|
#else
|
|
# error Cannot calculate stack trace: will need to write for your environment
|
|
|
|
# include "absl/debugging/internal/stacktrace_aarch64-inl.inc"
|
|
# include "absl/debugging/internal/stacktrace_arm-inl.inc"
|
|
# include "absl/debugging/internal/stacktrace_emscripten-inl.inc"
|
|
# include "absl/debugging/internal/stacktrace_generic-inl.inc"
|
|
# include "absl/debugging/internal/stacktrace_powerpc-inl.inc"
|
|
# include "absl/debugging/internal/stacktrace_riscv-inl.inc"
|
|
# include "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
|
|
# include "absl/debugging/internal/stacktrace_win32-inl.inc"
|
|
# include "absl/debugging/internal/stacktrace_x86-inl.inc"
|
|
#endif
|
|
|
|
namespace absl {
|
|
ABSL_NAMESPACE_BEGIN
|
|
namespace {
|
|
|
|
typedef int (*Unwinder)(void**, int*, int, int, const void*, int*);
|
|
std::atomic<Unwinder> custom;
|
|
|
|
template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
|
|
ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, int* sizes,
|
|
int max_depth, int skip_count,
|
|
const void* uc,
|
|
int* min_dropped_frames) {
|
|
Unwinder f = &UnwindImpl<IS_STACK_FRAMES, IS_WITH_CONTEXT>;
|
|
Unwinder g = custom.load(std::memory_order_acquire);
|
|
if (g != nullptr) f = g;
|
|
|
|
// Add 1 to skip count for the unwinder function itself
|
|
int size = (*f)(result, sizes, max_depth, skip_count + 1, uc,
|
|
min_dropped_frames);
|
|
// To disable tail call to (*f)(...)
|
|
ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
|
|
return size;
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFrames(
|
|
void** result, int* sizes, int max_depth, int skip_count) {
|
|
return Unwind<true, false>(result, sizes, max_depth, skip_count, nullptr,
|
|
nullptr);
|
|
}
|
|
|
|
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
|
|
GetStackFramesWithContext(void** result, int* sizes, int max_depth,
|
|
int skip_count, const void* uc,
|
|
int* min_dropped_frames) {
|
|
return Unwind<true, true>(result, sizes, max_depth, skip_count, uc,
|
|
min_dropped_frames);
|
|
}
|
|
|
|
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace(
|
|
void** result, int max_depth, int skip_count) {
|
|
return Unwind<false, false>(result, nullptr, max_depth, skip_count, nullptr,
|
|
nullptr);
|
|
}
|
|
|
|
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
|
|
GetStackTraceWithContext(void** result, int max_depth, int skip_count,
|
|
const void* uc, int* min_dropped_frames) {
|
|
return Unwind<false, true>(result, nullptr, max_depth, skip_count, uc,
|
|
min_dropped_frames);
|
|
}
|
|
|
|
void SetStackUnwinder(Unwinder w) {
|
|
custom.store(w, std::memory_order_release);
|
|
}
|
|
|
|
int DefaultStackUnwinder(void** pcs, int* sizes, int depth, int skip,
|
|
const void* uc, int* min_dropped_frames) {
|
|
skip++; // For this function
|
|
Unwinder f = nullptr;
|
|
if (sizes == nullptr) {
|
|
if (uc == nullptr) {
|
|
f = &UnwindImpl<false, false>;
|
|
} else {
|
|
f = &UnwindImpl<false, true>;
|
|
}
|
|
} else {
|
|
if (uc == nullptr) {
|
|
f = &UnwindImpl<true, false>;
|
|
} else {
|
|
f = &UnwindImpl<true, true>;
|
|
}
|
|
}
|
|
volatile int x = 0;
|
|
int n = (*f)(pcs, sizes, depth, skip, uc, min_dropped_frames);
|
|
x = 1; (void) x; // To disable tail call to (*f)(...)
|
|
return n;
|
|
}
|
|
|
|
ABSL_NAMESPACE_END
|
|
} // namespace absl
|