summaryrefslogtreecommitdiff
path: root/src/compiler/Utility.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/Utility.cc')
-rw-r--r--src/compiler/Utility.cc257
1 files changed, 187 insertions, 70 deletions
diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc
index c76143b928..0cdcfd3931 100644
--- a/src/compiler/Utility.cc
+++ b/src/compiler/Utility.cc
@@ -22,6 +22,67 @@ namespace art {
static ArenaMemBlock *arenaHead, *currentArena;
static int numArenaBlocks;
+#ifdef WITH_MEMSTATS
+static u4 allocStats[kNumAllocKinds];
+static int listSizes[kNumListKinds];
+static int listWasted[kNumListKinds];
+static int listGrows[kNumListKinds];
+static int listMaxElems[kNumListKinds];
+static int bitMapSizes[kNumBitMapKinds];
+static int bitMapWasted[kNumBitMapKinds];
+static int bitMapGrows[kNumBitMapKinds];
+
+const char* allocNames[kNumAllocKinds] = {
+ "Misc ",
+ "BasicBlock ",
+ "LIR ",
+ "MIR ",
+ "DataFlow ",
+ "GrowList ",
+ "GrowBitMap ",
+ "Dalvik2SSA ",
+ "DebugInfo ",
+ "Successor ",
+ "RegAlloc ",
+ "Data ",
+ "Preds ",
+};
+
+const char* listNames[kNumListKinds] = {
+ "Misc ",
+ "blockList ",
+ "SSAtoDalvik ",
+ "dfsOrder ",
+ "dfsPostOrder ",
+ "domPostOrderTraversal ",
+ "throwLaunchPads ",
+ "suspendLaunchPads ",
+ "switchTables ",
+ "fillArrayData ",
+ "SuccessorBlocks ",
+ "Predecessors ",
+};
+
+const char* bitMapNames[kNumBitMapKinds] = {
+ "Misc ",
+ "Use ",
+ "Def ",
+ "LiveIn ",
+ "BlockMatrix ",
+ "Dominators ",
+ "IDominated ",
+ "DomFrontier ",
+ "Phi ",
+ "TmpBlocks ",
+ "InputBlocks ",
+ "RegisterV ",
+ "TempSSARegisterV ",
+ "Null Check ",
+ "TmpBlockV ",
+ "Predecessors ",
+};
+#endif
+
#define kArenaBitVectorGrowth 4 /* increase by 4 u4s when limit hit */
/* Allocate the initial memory block for arena-based allocation */
@@ -38,14 +99,16 @@ bool oatHeapInit(void)
currentArena->bytesAllocated = 0;
currentArena->next = NULL;
numArenaBlocks = 1;
-
return true;
}
/* Arena-based malloc for compilation tasks */
-void* oatNew(size_t size, bool zero)
+void* oatNew(size_t size, bool zero, oatAllocKind kind)
{
size = (size + 3) & ~3;
+#ifdef WITH_MEMSTATS
+ allocStats[kind] += size;
+#endif
retry:
/* Normal case - space is available in the current page */
if (size + currentArena->bytesAllocated <= currentArena->blockSize) {
@@ -91,6 +154,16 @@ retry:
/* Reclaim all the arena blocks allocated so far */
void oatArenaReset(void)
{
+#ifdef WITH_MEMSTATS
+ memset(&allocStats[0], 0, sizeof(allocStats));
+ memset(&listSizes[0], 0, sizeof(listSizes));
+ memset(&listWasted[0], 0, sizeof(listWasted));
+ memset(&listGrows[0], 0, sizeof(listGrows));
+ memset(&listMaxElems[0], 0, sizeof(listMaxElems));
+ memset(&bitMapSizes[0], 0, sizeof(bitMapSizes));
+ memset(&bitMapWasted[0], 0, sizeof(bitMapWasted));
+ memset(&bitMapGrows[0], 0, sizeof(bitMapGrows));
+#endif
currentArena = arenaHead;
if (currentArena) {
currentArena->bytesAllocated = 0;
@@ -98,12 +171,20 @@ void oatArenaReset(void)
}
/* Growable List initialization */
-void oatInitGrowableList(GrowableList* gList, size_t initLength)
+void oatInitGrowableList(GrowableList* gList, size_t initLength,
+ oatListKind kind)
{
gList->numAllocated = initLength;
gList->numUsed = 0;
gList->elemList = (intptr_t *) oatNew(sizeof(intptr_t) * initLength,
- true);
+ true, kAllocGrowableList);
+#ifdef WITH_MEMSTATS
+ listSizes[kind] += sizeof(intptr_t) * initLength;
+ gList->kind = kind;
+ if ((int)initLength > listMaxElems[kind]) {
+ listMaxElems[kind] = initLength;
+ }
+#endif
}
/* Expand the capacity of a growable list */
@@ -116,8 +197,17 @@ STATIC void expandGrowableList(GrowableList* gList)
newLength += 128;
}
intptr_t *newArray =
- (intptr_t *) oatNew(sizeof(intptr_t) * newLength, true);
+ (intptr_t *) oatNew(sizeof(intptr_t) * newLength, true,
+ kAllocGrowableList);
memcpy(newArray, gList->elemList, sizeof(intptr_t) * gList->numAllocated);
+#ifdef WITH_MEMSTATS
+ listSizes[gList->kind] += sizeof(intptr_t) * newLength;
+ listWasted[gList->kind] += sizeof(intptr_t) * gList->numAllocated;
+ listGrows[gList->kind]++;
+ if (newLength > listMaxElems[gList->kind]) {
+ listMaxElems[gList->kind] = newLength;
+ }
+#endif
gList->numAllocated = newLength;
gList->elemList = newArray;
}
@@ -132,6 +222,22 @@ void oatInsertGrowableList(GrowableList* gList, intptr_t elem)
gList->elemList[gList->numUsed++] = elem;
}
+/* Delete an element from a growable list. Element must be present */
+void oatDeleteGrowableList(GrowableList* gList, intptr_t elem)
+{
+ bool found = false;
+ for (unsigned int i = 0; i < gList->numUsed; i++) {
+ if (!found && gList->elemList[i] == elem) {
+ found = true;
+ }
+ if (found) {
+ gList->elemList[i] = gList->elemList[i+1];
+ }
+ }
+ DCHECK_EQ(found, true);
+ gList->numUsed--;
+}
+
void oatGrowableListIteratorInit(GrowableList* gList,
GrowableListIterator* iterator)
{
@@ -153,6 +259,44 @@ intptr_t oatGrowableListGetElement(const GrowableList* gList, size_t idx)
return gList->elemList[idx];
}
+#ifdef WITH_MEMSTATS
+/* Dump memory usage stats */
+void oatDumpMemStats(CompilationUnit* cUnit)
+{
+ u4 total = 0;
+ for (int i = 0; i < kNumAllocKinds; i++) {
+ total += allocStats[i];
+ }
+ if (total > (10 * 1024 * 1024)) {
+ LOG(INFO) << "MEMUSAGE: " << total << " : "
+ << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
+ LOG(INFO) << "insnsSize: " << cUnit->insnsSize;
+ if (cUnit->disableDataflow) {
+ LOG(INFO) << " ** Dataflow disabled ** ";
+ }
+ LOG(INFO) << "===== Overall allocations";
+ for (int i = 0; i < kNumAllocKinds; i++) {
+ LOG(INFO) << allocNames[i] << std::setw(10) <<allocStats[i];
+ }
+ LOG(INFO) << "===== GrowableList allocations";
+ for (int i = 0; i < kNumListKinds; i++) {
+ LOG(INFO) << listNames[i]
+ << " S:" << listSizes[i]
+ << ", W:" << listWasted[i]
+ << ", G:" << listGrows[i]
+ << ", E:" << listMaxElems[i];
+ }
+ LOG(INFO) << "===== GrowableBitMap allocations";
+ for (int i = 0; i < kNumBitMapKinds; i++) {
+ LOG(INFO) << bitMapNames[i]
+ << " S:" << bitMapSizes[i]
+ << ", W:" << bitMapWasted[i]
+ << ", G:" << bitMapGrows[i];
+ }
+ }
+}
+#endif
+
/* Debug Utility - dump a compilation unit */
void oatDumpCompilationUnit(CompilationUnit* cUnit)
{
@@ -217,22 +361,26 @@ static uint32_t checkMasks[32] = {
*
* NOTE: memory is allocated from the compiler arena.
*/
-ArenaBitVector* oatAllocBitVector(unsigned int startBits, bool expandable)
+ArenaBitVector* oatAllocBitVector(unsigned int startBits, bool expandable,
+ oatBitMapKind kind)
{
ArenaBitVector* bv;
unsigned int count;
DCHECK_EQ(sizeof(bv->storage[0]), 4U); /* assuming 32-bit units */
- bv = (ArenaBitVector*) oatNew(sizeof(ArenaBitVector), false);
+ bv = (ArenaBitVector*) oatNew(sizeof(ArenaBitVector), false,
+ kAllocGrowableBitMap);
count = (startBits + 31) >> 5;
bv->storageSize = count;
bv->expandable = expandable;
- bv->storage = (u4*) oatNew(count * sizeof(u4), true);
- bv->firstDirty = true;
- bv->lastDirty = true;
+ bv->storage = (u4*) oatNew(count * sizeof(u4), true, kAllocGrowableBitMap);
+#ifdef WITH_MEMSTATS
+ bv->kind = kind;
+ bitMapSizes[kind] += count * sizeof(u4);
+#endif
return bv;
}
@@ -254,8 +402,6 @@ void oatClearAllBits(ArenaBitVector* pBits)
{
unsigned int count = pBits->storageSize;
memset(pBits->storage, 0, count * sizeof(u4));
- pBits->firstDirty = true;
- pBits->lastDirty = true;
}
/*
@@ -276,21 +422,21 @@ bool oatSetBit(ArenaBitVector* pBits, unsigned int num)
/* Round up to word boundaries for "num+1" bits */
unsigned int newSize = (num + 1 + 31) >> 5;
DCHECK_GT(newSize, pBits->storageSize);
- u4 *newStorage = (u4*)oatNew(newSize * sizeof(u4), false);
+ u4 *newStorage = (u4*)oatNew(newSize * sizeof(u4), false,
+ kAllocGrowableBitMap);
memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
memset(&newStorage[pBits->storageSize], 0,
(newSize - pBits->storageSize) * sizeof(u4));
+#ifdef WITH_MEMSTATS
+ bitMapWasted[pBits->kind] += pBits->storageSize * sizeof(u4);
+ bitMapSizes[pBits->kind] += newSize * sizeof(u4);
+ bitMapGrows[pBits->kind]++;
+#endif
pBits->storage = newStorage;
pBits->storageSize = newSize;
}
pBits->storage[num >> 5] |= checkMasks[num & 0x1f];
- if (!pBits->firstDirty && ((int)num < pBits->firstBitSet)) {
- pBits->firstBitSet = num;
- }
- if (!pBits->lastDirty && ((int)num > pBits->lastBitSet)) {
- pBits->lastBitSet = num;
- }
return true;
}
@@ -309,8 +455,6 @@ bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
}
pBits->storage[num >> 5] &= ~checkMasks[num & 0x1f];
- pBits->firstDirty = true;
- pBits->lastDirty = true;
return true;
}
@@ -321,8 +465,6 @@ void oatMarkAllBits(ArenaBitVector* pBits, bool set)
{
int value = set ? -1 : 0;
memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
- pBits->firstDirty = true;
- pBits->lastDirty = true;
}
void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
@@ -388,10 +530,6 @@ void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
checkSizes(dest, src);
memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
- dest->firstDirty = src->firstDirty;
- dest->firstBitSet = src->firstBitSet;
- dest->lastDirty = src->lastDirty;
- dest->lastBitSet = src->lastBitSet;
}
/*
@@ -413,8 +551,6 @@ bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
for (idx = 0; idx < dest->storageSize; idx++) {
dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
}
- dest->firstDirty = true;
- dest->lastDirty = true;
return true;
}
@@ -436,8 +572,6 @@ bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
for (idx = 0; idx < dest->storageSize; idx++) {
dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
}
- dest->firstDirty = true;
- dest->lastDirty = true;
return true;
}
@@ -490,52 +624,37 @@ int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
{
ArenaBitVector* pBits = iterator->pBits;
u4 bitIndex = iterator->idx;
+ u4 bitSize = iterator->bitSize;
- DCHECK_EQ(iterator->bitSize, pBits->storageSize * sizeof(u4) * 8);
- if (bitIndex >= iterator->bitSize) return -1;
+ DCHECK_EQ(bitSize, pBits->storageSize * sizeof(u4) * 8);
- /* If we know, skip past leading zeros */
- if (!pBits->firstDirty && ((int)bitIndex < pBits->firstBitSet)) {
- iterator->idx = pBits->firstBitSet + 1;
- return pBits->firstBitSet;
- }
+ if (bitIndex >= bitSize) return -1;
- /* If we know, skip past trailing zeroes */
- if (!pBits->lastDirty && ((int)bitIndex > pBits->lastBitSet)) {
- iterator->idx = iterator->bitSize;
- return -1;
- }
+ u4 wordIndex = bitIndex >> 5;
+ u4 endWordIndex = bitSize >> 5;
+ u4* storage = pBits->storage;
+ u4 word = storage[wordIndex++];
- bool firstPass = (bitIndex == 0);
- u4 startIndex = bitIndex;
- for (; bitIndex < iterator->bitSize;) {
- unsigned int wordIndex = bitIndex >> 5;
- unsigned int bitPos = bitIndex & 0x1f;
- unsigned int word = pBits->storage[wordIndex];
- if (word & checkMasks[bitPos]) {
- iterator->idx = bitIndex+1;
- if (firstPass && pBits->firstDirty) {
- pBits->firstBitSet = bitIndex;
- pBits->firstDirty = false;
- }
- return bitIndex;
- }
+ // Mask out any bits in the first word we've already considered
+ word &= ~((1 << (bitIndex & 0x1f))-1);
+
+ for (; wordIndex <= endWordIndex;) {
+ u4 bitPos = bitIndex & 0x1f;
if (word == 0) {
- // Helps if this is a sparse vector
bitIndex += (32 - bitPos);
- } else {
+ word = storage[wordIndex++];
+ continue;
+ }
+ for (; bitPos < 32; bitPos++) {
+ if (word & (1 << bitPos)) {
+ iterator->idx = bitIndex + 1;
+ return bitIndex;
+ }
bitIndex++;
}
+ word = storage[wordIndex++];
}
- /* No more set bits */
- if (firstPass) {
- // Empty
- pBits->firstBitSet = -1;
- pBits->firstDirty = false;
- } else {
- pBits->lastBitSet = startIndex - 1;
- pBits->lastDirty = false;
- }
+ iterator->idx = iterator->bitSize;
return -1;
}
@@ -555,8 +674,6 @@ void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
if (remNumBits) {
pBits->storage[idx] = (1 << remNumBits) - 1;
}
- pBits->firstDirty = true;
- pBits->lastDirty = true;
}
void oatGetBlockName(BasicBlock* bb, char* name)