[compiler-rt] r271286 - [esan] Add circular buffer data structure
Derek Bruening via llvm-commits
llvm-commits at lists.llvm.org
Tue May 31 07:44:51 PDT 2016
Author: bruening
Date: Tue May 31 09:44:49 2016
New Revision: 271286
URL: http://llvm.org/viewvc/llvm-project?rev=271286&view=rev
Log:
[esan] Add circular buffer data structure
Summary:
Adds a new class, CircularBuffer, for holding a wrap-around fixed-size
sequence of a primitive data type. This will be used initially by the
working set tool.
Adds a unit test for CircularBuffer, including infrastructure support to
include esan headers and to link with the esan library by pretending to
want the working set tool.
Reviewers: aizatsky, filcab
Subscribers: vitalybuka, zhaoqin, kcc, eugenis, llvm-commits, kubabrecka
Differential Revision: http://reviews.llvm.org/D20579
Added:
compiler-rt/trunk/lib/esan/esan_circular_buffer.h (with props)
compiler-rt/trunk/test/esan/Unit/
compiler-rt/trunk/test/esan/Unit/circular_buffer.cpp (with props)
Modified:
compiler-rt/trunk/test/esan/lit.cfg
Added: compiler-rt/trunk/lib/esan/esan_circular_buffer.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/esan/esan_circular_buffer.h?rev=271286&view=auto
==============================================================================
--- compiler-rt/trunk/lib/esan/esan_circular_buffer.h (added)
+++ compiler-rt/trunk/lib/esan/esan_circular_buffer.h Tue May 31 09:44:49 2016
@@ -0,0 +1,92 @@
+//===-- esan_circular_buffer.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of EfficiencySanitizer, a family of performance tuners.
+//
+// Circular buffer data structure.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __esan {
+
+// A circular buffer for POD data whose memory is allocated using mmap.
+// There are two usage models: one is to use initialize/free (for global
+// instances) and the other is to use placement new with the
+// constructor and to call the destructor or free (they are equivalent).
+template<typename T>
+class CircularBuffer {
+ public:
+ // To support global instances we cannot initialize any field in the
+ // default constructor.
+ explicit CircularBuffer() {}
+ CircularBuffer(uptr BufferCapacity) {
+ initialize(BufferCapacity);
+ }
+ ~CircularBuffer() {
+ free();
+ }
+ void initialize(uptr BufferCapacity) {
+ Capacity = BufferCapacity;
+ // MmapOrDie rounds up to the page size for us.
+ Data = (T *)MmapOrDie(Capacity * sizeof(T), "CircularBuffer");
+ StartIdx = 0;
+ Count = 0;
+ }
+ void free() {
+ UnmapOrDie(Data, Capacity * sizeof(T));
+ }
+ T &operator[](uptr Idx) {
+ CHECK_LT(Idx, Count);
+ uptr ArrayIdx = (StartIdx + Idx) % Capacity;
+ return Data[ArrayIdx];
+ }
+ const T &operator[](uptr Idx) const {
+ CHECK_LT(Idx, Count);
+ uptr ArrayIdx = (StartIdx + Idx) % Capacity;
+ return Data[ArrayIdx];
+ }
+ void push_back(const T &Item) {
+ CHECK_GT(Capacity, 0);
+ uptr ArrayIdx = (StartIdx + Count) % Capacity;
+ Data[ArrayIdx] = Item;
+ if (Count < Capacity)
+ ++Count;
+ else
+ StartIdx = (StartIdx + 1) % Capacity;
+ }
+ T &back() {
+ CHECK_GT(Count, 0);
+ uptr ArrayIdx = (StartIdx + Count - 1) % Capacity;
+ return Data[ArrayIdx];
+ }
+ void pop_back() {
+ CHECK_GT(Count, 0);
+ --Count;
+ }
+ uptr size() const {
+ return Count;
+ }
+ void clear() {
+ StartIdx = 0;
+ Count = 0;
+ }
+ bool empty() const { return size() == 0; }
+
+ private:
+ CircularBuffer(const CircularBuffer&);
+ void operator=(const CircularBuffer&);
+
+ T *Data;
+ uptr Capacity;
+ uptr StartIdx;
+ uptr Count;
+};
+
+} // namespace __esan
Propchange: compiler-rt/trunk/lib/esan/esan_circular_buffer.h
------------------------------------------------------------------------------
svn:eol-style = LF
Added: compiler-rt/trunk/test/esan/Unit/circular_buffer.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/esan/Unit/circular_buffer.cpp?rev=271286&view=auto
==============================================================================
--- compiler-rt/trunk/test/esan/Unit/circular_buffer.cpp (added)
+++ compiler-rt/trunk/test/esan/Unit/circular_buffer.cpp Tue May 31 09:44:49 2016
@@ -0,0 +1,61 @@
+// RUN: %clangxx_unit -O0 %s -o %t 2>&1
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include "esan/esan_circular_buffer.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include <assert.h>
+#include <stdio.h>
+
+static const int TestBufCapacity = 4;
+
+// The buffer should have a capacity of TestBufCapacity.
+void testBuffer(__esan::CircularBuffer<int> *Buf) {
+ assert(Buf->size() == 0);
+ assert(Buf->empty());
+
+ Buf->push_back(1);
+ assert(Buf->back() == 1);
+ assert((*Buf)[0] == 1);
+ assert(Buf->size() == 1);
+ assert(!Buf->empty());
+
+ Buf->push_back(2);
+ Buf->push_back(3);
+ Buf->push_back(4);
+ Buf->push_back(5);
+ assert((*Buf)[0] == 2);
+ assert(Buf->size() == 4);
+
+ Buf->pop_back();
+ assert((*Buf)[0] == 2);
+ assert(Buf->size() == 3);
+
+ Buf->pop_back();
+ Buf->pop_back();
+ assert((*Buf)[0] == 2);
+ assert(Buf->size() == 1);
+ assert(!Buf->empty());
+
+ Buf->pop_back();
+ assert(Buf->empty());
+}
+
+int main()
+{
+ // Test initialize/free.
+ __esan::CircularBuffer<int> GlobalBuf;
+ GlobalBuf.initialize(TestBufCapacity);
+ testBuffer(&GlobalBuf);
+ GlobalBuf.free();
+
+ // Test constructor/free.
+ __esan::CircularBuffer<int> *LocalBuf;
+ static char placeholder[sizeof(*LocalBuf)];
+ LocalBuf = new(placeholder) __esan::CircularBuffer<int>(TestBufCapacity);
+ testBuffer(LocalBuf);
+ LocalBuf->free();
+
+ fprintf(stderr, "All checks passed.\n");
+ // CHECK: All checks passed.
+ return 0;
+}
Propchange: compiler-rt/trunk/test/esan/Unit/circular_buffer.cpp
------------------------------------------------------------------------------
svn:eol-style = LF
Modified: compiler-rt/trunk/test/esan/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/esan/lit.cfg?rev=271286&r1=271285&r2=271286&view=diff
==============================================================================
--- compiler-rt/trunk/test/esan/lit.cfg (original)
+++ compiler-rt/trunk/test/esan/lit.cfg Tue May 31 09:44:49 2016
@@ -14,6 +14,10 @@ base_cxxflags = config.cxx_mode_flags +
frag_cflags = (["-fsanitize=efficiency-cache-frag"] + base_cflags)
wset_cflags = (["-fsanitize=efficiency-working-set"] + base_cflags)
+esan_incdir = config.test_source_root + "/../../lib"
+unit_cxxflags = (["-I%s" % esan_incdir, "-std=c++11",
+ # We need to link with the esan runtime.
+ "-fsanitize=efficiency-working-set"] + base_cxxflags)
def build_invocation(compile_flags):
return " " + " ".join([config.clang] + compile_flags) + " "
@@ -22,6 +26,8 @@ config.substitutions.append( ("%clang_es
build_invocation(frag_cflags)) )
config.substitutions.append( ("%clang_esan_wset ",
build_invocation(wset_cflags)) )
+config.substitutions.append( ("%clangxx_unit",
+ build_invocation(unit_cxxflags)) )
default_esan_opts = ''
config.substitutions.append(('%env_esan_opts=',
More information about the llvm-commits
mailing list