Historam: doesn't allocate additional memory to store counts
authorKonstantin Baladurin <k.baladurin@partner.samsung.com>
Wed, 14 Feb 2018 07:46:19 +0000 (10:46 +0300)
committerKonstantin Baladurin <k.baladurin@partner.samsung.com>
Wed, 14 Feb 2018 14:21:48 +0000 (17:21 +0300)
It allows to remove deallocation in destuctor that can lead to uaf
for static Historgam's objects during shutdown.

src/jit/compiler.cpp
src/jit/emit.cpp
src/jit/jit.h
src/jit/utils.cpp

index c53dd86..ce9b3dc 100644 (file)
@@ -276,18 +276,18 @@ NodeSizeStats genNodeSizeStats;
 NodeSizeStats genNodeSizeStatsPerFunc;
 
 unsigned  genTreeNcntHistBuckets[] = {10, 20, 30, 40, 50, 100, 200, 300, 400, 500, 1000, 5000, 10000, 0};
-Histogram genTreeNcntHist(HostAllocator::getHostAllocator(), genTreeNcntHistBuckets);
+Histogram genTreeNcntHist(genTreeNcntHistBuckets);
 
 unsigned  genTreeNsizHistBuckets[] = {1000, 5000, 10000, 50000, 100000, 500000, 1000000, 0};
-Histogram genTreeNsizHist(HostAllocator::getHostAllocator(), genTreeNsizHistBuckets);
+Histogram genTreeNsizHist(genTreeNsizHistBuckets);
 #endif // MEASURE_NODE_SIZE
 
 /*****************************************************************************/
 #if MEASURE_MEM_ALLOC
 
 unsigned  memSizeHistBuckets[] = {20, 50, 75, 100, 150, 250, 500, 1000, 5000, 0};
-Histogram memAllocHist(HostAllocator::getHostAllocator(), memSizeHistBuckets);
-Histogram memUsedHist(HostAllocator::getHostAllocator(), memSizeHistBuckets);
+Histogram memAllocHist(memSizeHistBuckets);
+Histogram memUsedHist(memSizeHistBuckets);
 
 #endif // MEASURE_MEM_ALLOC
 
@@ -339,16 +339,16 @@ unsigned argTotalGTF_ASGinArgs;
 unsigned argMaxTempsPerMethod;
 
 unsigned  argCntBuckets[] = {0, 1, 2, 3, 4, 5, 6, 10, 0};
-Histogram argCntTable(HostAllocator::getHostAllocator(), argCntBuckets);
+Histogram argCntTable(argCntBuckets);
 
 unsigned  argDWordCntBuckets[] = {0, 1, 2, 3, 4, 5, 6, 10, 0};
-Histogram argDWordCntTable(HostAllocator::getHostAllocator(), argDWordCntBuckets);
+Histogram argDWordCntTable(argDWordCntBuckets);
 
 unsigned  argDWordLngCntBuckets[] = {0, 1, 2, 3, 4, 5, 6, 10, 0};
-Histogram argDWordLngCntTable(HostAllocator::getHostAllocator(), argDWordLngCntBuckets);
+Histogram argDWordLngCntTable(argDWordLngCntBuckets);
 
 unsigned  argTempsCntBuckets[] = {0, 1, 2, 3, 4, 5, 6, 10, 0};
-Histogram argTempsCntTable(HostAllocator::getHostAllocator(), argTempsCntBuckets);
+Histogram argTempsCntTable(argTempsCntBuckets);
 
 #endif // CALL_ARG_STATS
 
@@ -375,12 +375,12 @@ Histogram argTempsCntTable(HostAllocator::getHostAllocator(), argTempsCntBuckets
 //          --------------------------------------------------
 
 unsigned  bbCntBuckets[] = {1, 2, 3, 5, 10, 20, 50, 100, 1000, 10000, 0};
-Histogram bbCntTable(HostAllocator::getHostAllocator(), bbCntBuckets);
+Histogram bbCntTable(bbCntBuckets);
 
 /* Histogram for the IL opcode size of methods with a single basic block */
 
 unsigned  bbSizeBuckets[] = {1, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 0};
-Histogram bbOneBBSizeTable(HostAllocator::getHostAllocator(), bbSizeBuckets);
+Histogram bbOneBBSizeTable(bbSizeBuckets);
 
 #endif // COUNT_BASIC_BLOCKS
 
@@ -411,12 +411,12 @@ bool     loopOverflowThisMethod;  // True if we exceeded the max # of loops in t
 /* Histogram for number of loops in a method */
 
 unsigned  loopCountBuckets[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0};
-Histogram loopCountTable(HostAllocator::getHostAllocator(), loopCountBuckets);
+Histogram loopCountTable(loopCountBuckets);
 
 /* Histogram for number of loop exits */
 
 unsigned  loopExitCountBuckets[] = {0, 1, 2, 3, 4, 5, 6, 0};
-Histogram loopExitCountTable(HostAllocator::getHostAllocator(), loopExitCountBuckets);
+Histogram loopExitCountTable(loopExitCountBuckets);
 
 #endif // COUNT_LOOPS
 
index 9f42aea..5c70e08 100644 (file)
@@ -257,13 +257,13 @@ static unsigned totActualSize;
 unsigned emitter::emitIFcounts[emitter::IF_COUNT];
 
 static unsigned  emitSizeBuckets[] = {100, 1024 * 1, 1024 * 2, 1024 * 3, 1024 * 4, 1024 * 5, 1024 * 10, 0};
-static Histogram emitSizeTable(HostAllocator::getHostAllocator(), emitSizeBuckets);
+static Histogram emitSizeTable(emitSizeBuckets);
 
 static unsigned  GCrefsBuckets[] = {0, 1, 2, 5, 10, 20, 50, 128, 256, 512, 1024, 0};
-static Histogram GCrefsTable(HostAllocator::getHostAllocator(), GCrefsBuckets);
+static Histogram GCrefsTable(GCrefsBuckets);
 
 static unsigned  stkDepthBuckets[] = {0, 1, 2, 5, 10, 16, 32, 128, 1024, 0};
-static Histogram stkDepthTable(HostAllocator::getHostAllocator(), stkDepthBuckets);
+static Histogram stkDepthTable(stkDepthBuckets);
 
 size_t emitter::emitSizeMethod;
 
index 00f5cb2..8297070 100644 (file)
@@ -695,11 +695,12 @@ inline size_t unsigned_abs(ssize_t x)
 
 #if CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE || MEASURE_MEM_ALLOC
 
+#define HISTOGRAM_MAX_SIZE_COUNT 64
+
 class Histogram
 {
 public:
-    Histogram(HostAllocator* allocator, const unsigned* const sizeTable);
-    ~Histogram();
+    Histogram(const unsigned* const sizeTable);
 
     void dump(FILE* output);
     void record(unsigned size);
@@ -707,10 +708,9 @@ public:
 private:
     void ensureAllocated();
 
-    HostAllocator*        m_allocator;
     unsigned              m_sizeCount;
     const unsigned* const m_sizeTable;
-    unsigned*             m_counts;
+    unsigned              m_counts[HISTOGRAM_MAX_SIZE_COUNT];
 };
 
 #endif // CALL_ARG_STATS || COUNT_BASIC_BLOCKS || COUNT_LOOPS || EMITTER_STATS || MEASURE_NODE_SIZE
index fda0d67..46d704c 100644 (file)
@@ -882,8 +882,7 @@ void ConfigMethodRange::InitRanges(const wchar_t* rangeStr, unsigned capacity)
  *  Histogram class.
  */
 
-Histogram::Histogram(HostAllocator* allocator, const unsigned* const sizeTable)
-    : m_allocator(allocator), m_sizeTable(sizeTable), m_counts(nullptr)
+Histogram::Histogram(const unsigned* const sizeTable) : m_sizeTable(sizeTable)
 {
     unsigned sizeCount = 0;
     do
@@ -891,32 +890,15 @@ Histogram::Histogram(HostAllocator* allocator, const unsigned* const sizeTable)
         sizeCount++;
     } while ((sizeTable[sizeCount] != 0) && (sizeCount < 1000));
 
-    m_sizeCount = sizeCount;
-}
+    assert(sizeCount < HISTOGRAM_MAX_SIZE_COUNT - 1);
 
-Histogram::~Histogram()
-{
-    if (m_counts != nullptr)
-    {
-        m_allocator->Free(m_counts);
-    }
-}
+    m_sizeCount = sizeCount;
 
-// We need to lazy allocate the histogram data so static `Histogram` variables don't try to
-// call the host memory allocator in the loader lock, which doesn't work.
-void Histogram::ensureAllocated()
-{
-    if (m_counts == nullptr)
-    {
-        m_counts = new (m_allocator) unsigned[m_sizeCount + 1];
-        memset(m_counts, 0, (m_sizeCount + 1) * sizeof(*m_counts));
-    }
+    memset(m_counts, 0, (m_sizeCount + 1) * sizeof(*m_counts));
 }
 
 void Histogram::dump(FILE* output)
 {
-    ensureAllocated();
-
     unsigned t = 0;
     for (unsigned i = 0; i < m_sizeCount; i++)
     {
@@ -956,8 +938,6 @@ void Histogram::dump(FILE* output)
 
 void Histogram::record(unsigned size)
 {
-    ensureAllocated();
-
     unsigned i;
     for (i = 0; i < m_sizeCount; i++)
     {