[sanitizer] A low-level vector implementation to be used in leak checking code. Patch...
authorKostya Serebryany <kcc@google.com>
Tue, 26 Feb 2013 13:30:27 +0000 (13:30 +0000)
committerKostya Serebryany <kcc@google.com>
Tue, 26 Feb 2013 13:30:27 +0000 (13:30 +0000)
llvm-svn: 176089

compiler-rt/lib/sanitizer_common/sanitizer_common.h
compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc

index 6fb447d..ce04919 100644 (file)
@@ -17,6 +17,7 @@
 #define SANITIZER_COMMON_H
 
 #include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
 
 namespace __sanitizer {
 struct StackTrace;
@@ -259,6 +260,57 @@ INLINE int ToLower(int c) {
 # define FIRST_32_SECOND_64(a, b) (a)
 #endif
 
+// A low-level vector based on mmap. May incur a significant memory overhead for
+// small vectors.
+// WARNING: The current implementation supports only POD types.
+template<typename T>
+class InternalVector {
+ public:
+  explicit InternalVector(uptr initial_capacity) {
+    CHECK_GT(initial_capacity, 0);
+    capacity_ = initial_capacity;
+    size_ = 0;
+    data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalVector");
+  }
+  ~InternalVector() {
+    UnmapOrDie(data_, capacity_ * sizeof(T));
+  }
+  T &operator[](uptr i) {
+    CHECK_LT(i, size_);
+    return data_[i];
+  }
+  void push_back(const T &element) {
+    CHECK_LE(size_, capacity_);
+    if (size_ == capacity_) {
+      uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
+      Resize(new_capacity);
+    }
+    data_[size_++] = element;
+  }
+  uptr size() {
+    return size_;
+  }
+
+ private:
+  void Resize(uptr new_capacity) {
+    CHECK_GT(new_capacity, 0);
+    CHECK_LE(size_, new_capacity);
+    T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T),
+                                 "InternalVector");
+    internal_memcpy(new_data, data_, size_ * sizeof(T));
+    T *old_data = data_;
+    data_ = new_data;
+    UnmapOrDie(old_data, capacity_ * sizeof(T));
+    capacity_ = new_capacity;
+  }
+  // Disallow evil constructors.
+  InternalVector(const InternalVector&);
+  void operator=(const InternalVector&);
+
+  T *data_;
+  uptr capacity_;
+  uptr size_;
+};
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_COMMON_H
index a32d9df..1ffcde2 100644 (file)
@@ -96,4 +96,15 @@ TEST(SanitizerCommon, SanitizerSetThreadName) {
 }
 #endif
 
+TEST(SanitizerCommon, InternalVector) {
+  InternalVector<uptr> vector(1);
+  for (uptr i = 0; i < 100; i++) {
+    EXPECT_EQ(vector.size(), i);
+    vector.push_back(i);
+  }
+  for (uptr i = 0; i < 100; i++) {
+    EXPECT_EQ(vector[i], i);
+  }
+}
+
 }  // namespace __sanitizer