aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt/lib/memprof
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/memprof')
-rw-r--r--compiler-rt/lib/memprof/memprof_interface_internal.h10
-rw-r--r--compiler-rt/lib/memprof/memprof_rawprofile.cpp32
-rw-r--r--compiler-rt/lib/memprof/tests/CMakeLists.txt1
-rw-r--r--compiler-rt/lib/memprof/tests/histogram_encoding.cpp35
4 files changed, 66 insertions, 12 deletions
diff --git a/compiler-rt/lib/memprof/memprof_interface_internal.h b/compiler-rt/lib/memprof/memprof_interface_internal.h
index 7d3a937..1fd0748 100644
--- a/compiler-rt/lib/memprof/memprof_interface_internal.h
+++ b/compiler-rt/lib/memprof/memprof_interface_internal.h
@@ -36,8 +36,14 @@ SANITIZER_INTERFACE_ATTRIBUTE
void __memprof_record_access(void const volatile *addr);
SANITIZER_INTERFACE_ATTRIBUTE
+void __memprof_record_access_hist(void const volatile *addr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
void __memprof_record_access_range(void const volatile *addr, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __memprof_record_access_range_hist(void const volatile *addr, uptr size);
+
SANITIZER_INTERFACE_ATTRIBUTE void __memprof_print_accumulated_stats();
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE extern char
@@ -51,6 +57,10 @@ extern uptr __memprof_shadow_memory_dynamic_address;
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE extern char
__memprof_profile_filename[1];
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE extern bool
+ __memprof_histogram;
+
SANITIZER_INTERFACE_ATTRIBUTE int __memprof_profile_dump();
SANITIZER_INTERFACE_ATTRIBUTE void __memprof_profile_reset();
diff --git a/compiler-rt/lib/memprof/memprof_rawprofile.cpp b/compiler-rt/lib/memprof/memprof_rawprofile.cpp
index a897648..f579e12 100644
--- a/compiler-rt/lib/memprof/memprof_rawprofile.cpp
+++ b/compiler-rt/lib/memprof/memprof_rawprofile.cpp
@@ -7,10 +7,7 @@
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_array_ref.h"
#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_linux.h"
-#include "sanitizer_common/sanitizer_procmaps.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
-#include "sanitizer_common/sanitizer_stackdepotbase.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_vector.h"
@@ -19,10 +16,20 @@ using ::__sanitizer::Vector;
using ::llvm::memprof::MemInfoBlock;
using SegmentEntry = ::llvm::memprof::SegmentEntry;
using Header = ::llvm::memprof::Header;
+using ::llvm::memprof::encodeHistogramCount;
namespace {
template <class T> char *WriteBytes(const T &Pod, char *Buffer) {
- *(T *)Buffer = Pod;
+ static_assert(is_trivially_copyable<T>::value, "T must be POD");
+ const uint8_t *Src = reinterpret_cast<const uint8_t *>(&Pod);
+
+ for (size_t I = 0; I < sizeof(T); ++I)
+#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ // Reverse byte order since reader is little-endian.
+ Buffer[I] = Src[sizeof(T) - 1 - I];
+#else
+ Buffer[I] = Src[I];
+#endif
return Buffer + sizeof(T);
}
@@ -32,7 +39,6 @@ void RecordStackId(const uptr Key, UNUSED LockedMemInfoBlock *const &MIB,
auto *StackIds = reinterpret_cast<Vector<u64> *>(Arg);
StackIds->PushBack(Key);
}
-} // namespace
u64 SegmentSizeBytes(ArrayRef<LoadedModule> Modules) {
u64 NumSegmentsToRecord = 0;
@@ -169,18 +175,21 @@ void SerializeMIBInfoToBuffer(MIBMapTy &MIBMap, const Vector<u64> &StackIds,
// FIXME: We unnecessarily serialize the AccessHistogram pointer. Adding a
// serialization schema will fix this issue. See also FIXME in
// deserialization.
- Ptr = WriteBytes((*h)->mib, Ptr);
- for (u64 j = 0; j < (*h)->mib.AccessHistogramSize; ++j) {
- u64 HistogramEntry = ((u64 *)((*h)->mib.AccessHistogram))[j];
+ auto &MIB = (*h)->mib;
+ Ptr = WriteBytes(MIB, Ptr);
+ for (u64 j = 0; j < MIB.AccessHistogramSize; ++j) {
+ u16 HistogramEntry =
+ encodeHistogramCount(((u64 *)(MIB.AccessHistogram))[j]);
Ptr = WriteBytes(HistogramEntry, Ptr);
}
- if ((*h)->mib.AccessHistogramSize > 0) {
- InternalFree((void *)((*h)->mib.AccessHistogram));
+ if (MIB.AccessHistogramSize > 0) {
+ InternalFree((void *)MIB.AccessHistogram);
}
}
CHECK(ExpectedNumBytes >= static_cast<u64>(Ptr - Buffer) &&
"Expected num bytes != actual bytes written");
}
+} // namespace
// Format
// ---------- Header
@@ -249,7 +258,7 @@ u64 SerializeToRawProfile(MIBMapTy &MIBMap, ArrayRef<LoadedModule> Modules,
},
reinterpret_cast<void *>(&TotalAccessHistogramEntries));
const u64 NumHistogramBytes =
- RoundUpTo(TotalAccessHistogramEntries * sizeof(uint64_t), 8);
+ RoundUpTo(TotalAccessHistogramEntries * sizeof(uint16_t), 8);
const u64 NumStackBytes = RoundUpTo(StackSizeBytes(StackIds), 8);
@@ -285,5 +294,4 @@ u64 SerializeToRawProfile(MIBMapTy &MIBMap, ArrayRef<LoadedModule> Modules,
return TotalSizeBytes;
}
-
} // namespace __memprof
diff --git a/compiler-rt/lib/memprof/tests/CMakeLists.txt b/compiler-rt/lib/memprof/tests/CMakeLists.txt
index 0b5c302..1603d47 100644
--- a/compiler-rt/lib/memprof/tests/CMakeLists.txt
+++ b/compiler-rt/lib/memprof/tests/CMakeLists.txt
@@ -26,6 +26,7 @@ set(MEMPROF_SOURCES
../memprof_rawprofile.cpp)
set(MEMPROF_UNITTESTS
+ histogram_encoding.cpp
rawprofile.cpp
driver.cpp)
diff --git a/compiler-rt/lib/memprof/tests/histogram_encoding.cpp b/compiler-rt/lib/memprof/tests/histogram_encoding.cpp
new file mode 100644
index 0000000..be20595
--- /dev/null
+++ b/compiler-rt/lib/memprof/tests/histogram_encoding.cpp
@@ -0,0 +1,35 @@
+#include <cstdint>
+#include <vector>
+
+#include "profile/MemProfData.inc"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace memprof {
+namespace {
+TEST(MemProf, F16EncodeDecode) {
+ const std::vector<uint64_t> TestCases = {
+ 0, 100, 4095, 4096, 5000, 8191, 65535, 1000000, 134213640, 200000000,
+ };
+
+ for (const uint64_t TestCase : TestCases) {
+ const uint16_t Encoded = encodeHistogramCount(TestCase);
+ const uint64_t Decoded = decodeHistogramCount(Encoded);
+
+ const uint64_t MaxRepresentable = static_cast<uint64_t>(MaxMantissa)
+ << MaxExponent;
+
+ if (TestCase >= MaxRepresentable) {
+ EXPECT_EQ(Decoded, MaxRepresentable);
+ } else if (TestCase <= MaxMantissa) {
+ EXPECT_EQ(Decoded, TestCase);
+ } else {
+ // The decoded value should be close to the original value.
+ // The error should be less than 1/1024 for larger numbers.
+ EXPECT_NEAR(Decoded, TestCase, static_cast<double>(TestCase) / 1024.0);
+ }
+ }
+}
+} // namespace
+} // namespace memprof
+} // namespace llvm