blob: 8bd4713adc8bf32d16b9992b0c251e2648f07c6b [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
buzbeeefc63692012-11-14 16:31:52 -080017#include "compiler_internals.h"
buzbee67bf8852011-08-17 17:51:35 -070018
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080019namespace art {
20
buzbee5abfa3e2012-01-31 17:01:43 -080021#ifdef WITH_MEMSTATS
Elliott Hughes719ace42012-03-09 18:06:03 -080022struct Memstats {
buzbeeeaf09bc2012-11-15 14:51:41 -080023 uint32_t allocStats[kNumAllocKinds];
Bill Buzbeea114add2012-05-03 15:00:40 -070024 int listSizes[kNumListKinds];
25 int listWasted[kNumListKinds];
26 int listGrows[kNumListKinds];
27 int listMaxElems[kNumListKinds];
28 int bitMapSizes[kNumBitMapKinds];
29 int bitMapWasted[kNumBitMapKinds];
30 int bitMapGrows[kNumBitMapKinds];
Elliott Hughes719ace42012-03-09 18:06:03 -080031};
buzbee5abfa3e2012-01-31 17:01:43 -080032
33const char* allocNames[kNumAllocKinds] = {
Bill Buzbeea114add2012-05-03 15:00:40 -070034 "Misc ",
35 "BasicBlock ",
36 "LIR ",
37 "MIR ",
38 "DataFlow ",
39 "GrowList ",
40 "GrowBitMap ",
41 "Dalvik2SSA ",
42 "DebugInfo ",
43 "Successor ",
44 "RegAlloc ",
45 "Data ",
46 "Preds ",
buzbee5abfa3e2012-01-31 17:01:43 -080047};
48
49const char* listNames[kNumListKinds] = {
Bill Buzbeea114add2012-05-03 15:00:40 -070050 "Misc ",
51 "blockList ",
52 "SSAtoDalvik ",
53 "dfsOrder ",
54 "dfsPostOrder ",
55 "domPostOrderTraversal ",
56 "throwLaunchPads ",
57 "suspendLaunchPads ",
58 "switchTables ",
59 "fillArrayData ",
60 "SuccessorBlocks ",
61 "Predecessors ",
buzbee5abfa3e2012-01-31 17:01:43 -080062};
63
64const char* bitMapNames[kNumBitMapKinds] = {
Bill Buzbeea114add2012-05-03 15:00:40 -070065 "Misc ",
66 "Use ",
67 "Def ",
68 "LiveIn ",
69 "BlockMatrix ",
70 "Dominators ",
71 "IDominated ",
72 "DomFrontier ",
73 "Phi ",
74 "TmpBlocks ",
75 "InputBlocks ",
76 "RegisterV ",
77 "TempSSARegisterV ",
78 "Null Check ",
79 "TmpBlockV ",
80 "Predecessors ",
buzbee5abfa3e2012-01-31 17:01:43 -080081};
82#endif
83
buzbeeeaf09bc2012-11-15 14:51:41 -080084#define kArenaBitVectorGrowth 4 /* increase by 4 uint32_ts when limit hit */
buzbee67bf8852011-08-17 17:51:35 -070085
86/* Allocate the initial memory block for arena-based allocation */
buzbeeba938cb2012-02-03 14:47:55 -080087bool oatHeapInit(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070088{
Bill Buzbeea114add2012-05-03 15:00:40 -070089 DCHECK(cUnit->arenaHead == NULL);
90 cUnit->arenaHead =
91 (ArenaMemBlock *) malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
92 if (cUnit->arenaHead == NULL) {
93 LOG(FATAL) << "No memory left to create compiler heap memory";
94 }
95 cUnit->arenaHead->blockSize = ARENA_DEFAULT_SIZE;
96 cUnit->currentArena = cUnit->arenaHead;
97 cUnit->currentArena->bytesAllocated = 0;
98 cUnit->currentArena->next = NULL;
99 cUnit->numArenaBlocks = 1;
buzbeeba938cb2012-02-03 14:47:55 -0800100#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700101 cUnit->mstats = (Memstats*) oatNew(cUnit, sizeof(Memstats), true,
102 kAllocDebugInfo);
buzbeeba938cb2012-02-03 14:47:55 -0800103#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 return true;
buzbee67bf8852011-08-17 17:51:35 -0700105}
106
107/* Arena-based malloc for compilation tasks */
buzbeeba938cb2012-02-03 14:47:55 -0800108void* oatNew(CompilationUnit* cUnit, size_t size, bool zero, oatAllocKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700109{
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 size = (size + 3) & ~3;
buzbee5abfa3e2012-01-31 17:01:43 -0800111#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 if (cUnit->mstats != NULL) {
113 cUnit->mstats->allocStats[kind] += size;
114 }
buzbee5abfa3e2012-01-31 17:01:43 -0800115#endif
buzbee67bf8852011-08-17 17:51:35 -0700116retry:
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 /* Normal case - space is available in the current page */
118 if (size + cUnit->currentArena->bytesAllocated <=
119 cUnit->currentArena->blockSize) {
120 void *ptr;
121 ptr = &cUnit->currentArena->ptr[cUnit->currentArena->bytesAllocated];
122 cUnit->currentArena->bytesAllocated += size;
123 if (zero) {
124 memset(ptr, 0, size);
125 }
126 return ptr;
127 } else {
128 /*
129 * See if there are previously allocated arena blocks before the last
130 * reset
131 */
132 if (cUnit->currentArena->next) {
133 cUnit->currentArena = cUnit->currentArena->next;
134 cUnit->currentArena->bytesAllocated = 0;
buzbee67bf8852011-08-17 17:51:35 -0700135 goto retry;
136 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700137
138 size_t blockSize = (size < ARENA_DEFAULT_SIZE) ? ARENA_DEFAULT_SIZE : size;
139 /* Time to allocate a new arena */
140 ArenaMemBlock *newArena = (ArenaMemBlock *)
141 malloc(sizeof(ArenaMemBlock) + blockSize);
142 if (newArena == NULL) {
143 LOG(FATAL) << "Arena allocation failure";
144 }
145 newArena->blockSize = blockSize;
146 newArena->bytesAllocated = 0;
147 newArena->next = NULL;
148 cUnit->currentArena->next = newArena;
149 cUnit->currentArena = newArena;
150 cUnit->numArenaBlocks++;
151 if (cUnit->numArenaBlocks > 20000) {
152 LOG(INFO) << "Total arena pages: " << cUnit->numArenaBlocks;
153 }
154 goto retry;
155 }
buzbee67bf8852011-08-17 17:51:35 -0700156}
157
158/* Reclaim all the arena blocks allocated so far */
buzbeeba938cb2012-02-03 14:47:55 -0800159void oatArenaReset(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700160{
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 ArenaMemBlock* head = cUnit->arenaHead;
162 while (head != NULL) {
163 ArenaMemBlock* p = head;
164 head = head->next;
165 free(p);
166 }
167 cUnit->arenaHead = NULL;
168 cUnit->currentArena = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700169}
170
171/* Growable List initialization */
buzbeeba938cb2012-02-03 14:47:55 -0800172void oatInitGrowableList(CompilationUnit* cUnit, GrowableList* gList,
Bill Buzbeea114add2012-05-03 15:00:40 -0700173 size_t initLength, oatListKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700174{
Bill Buzbeea114add2012-05-03 15:00:40 -0700175 gList->numAllocated = initLength;
176 gList->numUsed = 0;
177 gList->elemList = (intptr_t *) oatNew(cUnit, sizeof(intptr_t) * initLength,
178 true, kAllocGrowableList);
buzbee5abfa3e2012-01-31 17:01:43 -0800179#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700180 cUnit->mstats->listSizes[kind] += sizeof(intptr_t) * initLength;
181 gList->kind = kind;
182 if ((int)initLength > cUnit->mstats->listMaxElems[kind]) {
183 cUnit->mstats->listMaxElems[kind] = initLength;
184 }
buzbee5abfa3e2012-01-31 17:01:43 -0800185#endif
buzbee67bf8852011-08-17 17:51:35 -0700186}
187
188/* Expand the capacity of a growable list */
buzbee31a4a6f2012-02-28 15:36:15 -0800189void expandGrowableList(CompilationUnit* cUnit, GrowableList* gList)
buzbee67bf8852011-08-17 17:51:35 -0700190{
Bill Buzbeea114add2012-05-03 15:00:40 -0700191 int newLength = gList->numAllocated;
192 if (newLength < 128) {
193 newLength <<= 1;
194 } else {
195 newLength += 128;
196 }
197 intptr_t *newArray =
198 (intptr_t *) oatNew(cUnit, sizeof(intptr_t) * newLength, true,
199 kAllocGrowableList);
200 memcpy(newArray, gList->elemList, sizeof(intptr_t) * gList->numAllocated);
buzbee5abfa3e2012-01-31 17:01:43 -0800201#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700202 cUnit->mstats->listSizes[gList->kind] += sizeof(intptr_t) * newLength;
203 cUnit->mstats->listWasted[gList->kind] +=
204 sizeof(intptr_t) * gList->numAllocated;
205 cUnit->mstats->listGrows[gList->kind]++;
206 if (newLength > cUnit->mstats->listMaxElems[gList->kind]) {
207 cUnit->mstats->listMaxElems[gList->kind] = newLength;
208 }
buzbee5abfa3e2012-01-31 17:01:43 -0800209#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 gList->numAllocated = newLength;
211 gList->elemList = newArray;
buzbee67bf8852011-08-17 17:51:35 -0700212}
213
214/* Insert a new element into the growable list */
buzbeeba938cb2012-02-03 14:47:55 -0800215void oatInsertGrowableList(CompilationUnit* cUnit, GrowableList* gList,
Bill Buzbeea114add2012-05-03 15:00:40 -0700216 intptr_t elem)
buzbee67bf8852011-08-17 17:51:35 -0700217{
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 DCHECK_NE(gList->numAllocated, 0U);
219 if (gList->numUsed == gList->numAllocated) {
220 expandGrowableList(cUnit, gList);
221 }
222 gList->elemList[gList->numUsed++] = elem;
buzbee67bf8852011-08-17 17:51:35 -0700223}
224
buzbee5abfa3e2012-01-31 17:01:43 -0800225/* Delete an element from a growable list. Element must be present */
226void oatDeleteGrowableList(GrowableList* gList, intptr_t elem)
227{
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 bool found = false;
229 for (unsigned int i = 0; i < gList->numUsed; i++) {
230 if (!found && gList->elemList[i] == elem) {
231 found = true;
buzbee5abfa3e2012-01-31 17:01:43 -0800232 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 if (found) {
234 gList->elemList[i] = gList->elemList[i+1];
235 }
236 }
237 DCHECK_EQ(found, true);
238 gList->numUsed--;
buzbee5abfa3e2012-01-31 17:01:43 -0800239}
240
buzbee67bf8852011-08-17 17:51:35 -0700241void oatGrowableListIteratorInit(GrowableList* gList,
Bill Buzbeea114add2012-05-03 15:00:40 -0700242 GrowableListIterator* iterator)
buzbee67bf8852011-08-17 17:51:35 -0700243{
Bill Buzbeea114add2012-05-03 15:00:40 -0700244 iterator->list = gList;
245 iterator->idx = 0;
246 iterator->size = gList->numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700247}
248
249intptr_t oatGrowableListIteratorNext(GrowableListIterator* iterator)
250{
Bill Buzbeea114add2012-05-03 15:00:40 -0700251 DCHECK_EQ(iterator->size, iterator->list->numUsed);
252 if (iterator->idx == iterator->size) return 0;
253 return iterator->list->elemList[iterator->idx++];
buzbee67bf8852011-08-17 17:51:35 -0700254}
255
256intptr_t oatGrowableListGetElement(const GrowableList* gList, size_t idx)
257{
Bill Buzbeea114add2012-05-03 15:00:40 -0700258 DCHECK_LT(idx, gList->numUsed);
259 return gList->elemList[idx];
buzbee67bf8852011-08-17 17:51:35 -0700260}
261
buzbee5abfa3e2012-01-31 17:01:43 -0800262#ifdef WITH_MEMSTATS
263/* Dump memory usage stats */
264void oatDumpMemStats(CompilationUnit* cUnit)
265{
buzbeeeaf09bc2012-11-15 14:51:41 -0800266 uint32_t total = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 for (int i = 0; i < kNumAllocKinds; i++) {
268 total += cUnit->mstats->allocStats[i];
269 }
270 if (total > (10 * 1024 * 1024)) {
271 LOG(INFO) << "MEMUSAGE: " << total << " : "
272 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
273 LOG(INFO) << "insnsSize: " << cUnit->insnsSize;
274 if (cUnit->disableDataflow) {
275 LOG(INFO) << " ** Dataflow disabled ** ";
buzbee5abfa3e2012-01-31 17:01:43 -0800276 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 LOG(INFO) << "===== Overall allocations";
278 for (int i = 0; i < kNumAllocKinds; i++) {
279 LOG(INFO) << allocNames[i] << std::setw(10) <<
280 cUnit->mstats->allocStats[i];
281 }
282 LOG(INFO) << "===== GrowableList allocations";
283 for (int i = 0; i < kNumListKinds; i++) {
284 LOG(INFO) << listNames[i]
buzbeeba938cb2012-02-03 14:47:55 -0800285 << " S:" << cUnit->mstats->listSizes[i]
286 << ", W:" << cUnit->mstats->listWasted[i]
287 << ", G:" << cUnit->mstats->listGrows[i]
288 << ", E:" << cUnit->mstats->listMaxElems[i];
Bill Buzbeea114add2012-05-03 15:00:40 -0700289 }
290 LOG(INFO) << "===== GrowableBitMap allocations";
291 for (int i = 0; i < kNumBitMapKinds; i++) {
292 LOG(INFO) << bitMapNames[i]
buzbeeba938cb2012-02-03 14:47:55 -0800293 << " S:" << cUnit->mstats->bitMapSizes[i]
294 << ", W:" << cUnit->mstats->bitMapWasted[i]
295 << ", G:" << cUnit->mstats->bitMapGrows[i];
buzbee5abfa3e2012-01-31 17:01:43 -0800296 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 }
buzbee5abfa3e2012-01-31 17:01:43 -0800298}
299#endif
300
buzbee67bf8852011-08-17 17:51:35 -0700301/* Debug Utility - dump a compilation unit */
302void oatDumpCompilationUnit(CompilationUnit* cUnit)
303{
Bill Buzbeea114add2012-05-03 15:00:40 -0700304 BasicBlock* bb;
305 const char* blockTypeNames[] = {
306 "Entry Block",
307 "Code Block",
308 "Exit Block",
309 "Exception Handling",
310 "Catch Block"
311 };
buzbee67bf8852011-08-17 17:51:35 -0700312
Bill Buzbeea114add2012-05-03 15:00:40 -0700313 LOG(INFO) << "Compiling " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
314 LOG(INFO) << cUnit->insns << " insns";
315 LOG(INFO) << cUnit->numBlocks << " blocks in total";
316 GrowableListIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700317
Bill Buzbeea114add2012-05-03 15:00:40 -0700318 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
buzbee67bf8852011-08-17 17:51:35 -0700319
Bill Buzbeea114add2012-05-03 15:00:40 -0700320 while (true) {
321 bb = (BasicBlock *) oatGrowableListIteratorNext(&iterator);
322 if (bb == NULL) break;
323 LOG(INFO) << StringPrintf("Block %d (%s) (insn %04x - %04x%s)",
324 bb->id,
325 blockTypeNames[bb->blockType],
326 bb->startOffset,
327 bb->lastMIRInsn ? bb->lastMIRInsn->offset : bb->startOffset,
328 bb->lastMIRInsn ? "" : " empty");
329 if (bb->taken) {
330 LOG(INFO) << " Taken branch: block " << bb->taken->id
331 << "(0x" << std::hex << bb->taken->startOffset << ")";
buzbee67bf8852011-08-17 17:51:35 -0700332 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700333 if (bb->fallThrough) {
334 LOG(INFO) << " Fallthrough : block " << bb->fallThrough->id
335 << " (0x" << std::hex << bb->fallThrough->startOffset << ")";
336 }
337 }
buzbee67bf8852011-08-17 17:51:35 -0700338}
339
buzbee67bc2362011-10-11 18:08:40 -0700340static uint32_t checkMasks[32] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700341 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
342 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200,
343 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000,
344 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000,
345 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000,
346 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
347 0x40000000, 0x80000000 };
buzbee67bc2362011-10-11 18:08:40 -0700348
buzbee67bf8852011-08-17 17:51:35 -0700349/*
350 * Allocate a bit vector with enough space to hold at least the specified
351 * number of bits.
352 *
353 * NOTE: memory is allocated from the compiler arena.
354 */
buzbeeba938cb2012-02-03 14:47:55 -0800355ArenaBitVector* oatAllocBitVector(CompilationUnit* cUnit,
Bill Buzbeea114add2012-05-03 15:00:40 -0700356 unsigned int startBits, bool expandable,
357 oatBitMapKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700358{
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 ArenaBitVector* bv;
360 unsigned int count;
buzbee67bf8852011-08-17 17:51:35 -0700361
Bill Buzbeea114add2012-05-03 15:00:40 -0700362 DCHECK_EQ(sizeof(bv->storage[0]), 4U); /* assuming 32-bit units */
buzbee67bf8852011-08-17 17:51:35 -0700363
Bill Buzbeea114add2012-05-03 15:00:40 -0700364 bv = (ArenaBitVector*) oatNew(cUnit, sizeof(ArenaBitVector), false,
365 kAllocGrowableBitMap);
buzbee67bf8852011-08-17 17:51:35 -0700366
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 count = (startBits + 31) >> 5;
buzbee67bf8852011-08-17 17:51:35 -0700368
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 bv->storageSize = count;
370 bv->expandable = expandable;
buzbeeeaf09bc2012-11-15 14:51:41 -0800371 bv->storage = static_cast<uint32_t*>(oatNew(cUnit, count * sizeof(uint32_t), true,
372 kAllocGrowableBitMap));
buzbee5abfa3e2012-01-31 17:01:43 -0800373#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 bv->kind = kind;
buzbeeeaf09bc2012-11-15 14:51:41 -0800375 cUnit->mstats->bitMapSizes[kind] += count * sizeof(uint32_t);
buzbee5abfa3e2012-01-31 17:01:43 -0800376#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700377 return bv;
buzbee67bf8852011-08-17 17:51:35 -0700378}
379
380/*
381 * Determine whether or not the specified bit is set.
382 */
383bool oatIsBitSet(const ArenaBitVector* pBits, unsigned int num)
384{
buzbeeeaf09bc2012-11-15 14:51:41 -0800385 DCHECK_LT(num, pBits->storageSize * sizeof(uint32_t) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700386
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 unsigned int val = pBits->storage[num >> 5] & checkMasks[num & 0x1f];
388 return (val != 0);
buzbee67bf8852011-08-17 17:51:35 -0700389}
390
391/*
392 * Mark all bits bit as "clear".
393 */
394void oatClearAllBits(ArenaBitVector* pBits)
395{
Bill Buzbeea114add2012-05-03 15:00:40 -0700396 unsigned int count = pBits->storageSize;
buzbeeeaf09bc2012-11-15 14:51:41 -0800397 memset(pBits->storage, 0, count * sizeof(uint32_t));
buzbee67bf8852011-08-17 17:51:35 -0700398}
399
400/*
401 * Mark the specified bit as "set".
402 *
403 * Returns "false" if the bit is outside the range of the vector and we're
404 * not allowed to expand.
405 *
406 * NOTE: memory is allocated from the compiler arena.
407 */
buzbeeba938cb2012-02-03 14:47:55 -0800408bool oatSetBit(CompilationUnit* cUnit, ArenaBitVector* pBits, unsigned int num)
buzbee67bf8852011-08-17 17:51:35 -0700409{
buzbeeeaf09bc2012-11-15 14:51:41 -0800410 if (num >= pBits->storageSize * sizeof(uint32_t) * 8) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 if (!pBits->expandable) {
412 LOG(FATAL) << "Can't expand";
buzbee67bf8852011-08-17 17:51:35 -0700413 }
414
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 /* Round up to word boundaries for "num+1" bits */
416 unsigned int newSize = (num + 1 + 31) >> 5;
417 DCHECK_GT(newSize, pBits->storageSize);
buzbeeeaf09bc2012-11-15 14:51:41 -0800418 uint32_t *newStorage = static_cast<uint32_t*>(oatNew(cUnit, newSize * sizeof(uint32_t), false,
419 kAllocGrowableBitMap));
420 memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(uint32_t));
Bill Buzbeea114add2012-05-03 15:00:40 -0700421 memset(&newStorage[pBits->storageSize], 0,
buzbeeeaf09bc2012-11-15 14:51:41 -0800422 (newSize - pBits->storageSize) * sizeof(uint32_t));
Bill Buzbeea114add2012-05-03 15:00:40 -0700423#ifdef WITH_MEMSTATS
424 cUnit->mstats->bitMapWasted[pBits->kind] +=
buzbeeeaf09bc2012-11-15 14:51:41 -0800425 pBits->storageSize * sizeof(uint32_t);
426 cUnit->mstats->bitMapSizes[pBits->kind] += newSize * sizeof(uint32_t);
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 cUnit->mstats->bitMapGrows[pBits->kind]++;
428#endif
429 pBits->storage = newStorage;
430 pBits->storageSize = newSize;
431 }
432
433 pBits->storage[num >> 5] |= checkMasks[num & 0x1f];
434 return true;
buzbee67bf8852011-08-17 17:51:35 -0700435}
436
437/*
438 * Mark the specified bit as "unset".
439 *
440 * Returns "false" if the bit is outside the range of the vector and we're
441 * not allowed to expand.
442 *
443 * NOTE: memory is allocated from the compiler arena.
444 */
445bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
446{
buzbeeeaf09bc2012-11-15 14:51:41 -0800447 if (num >= pBits->storageSize * sizeof(uint32_t) * 8) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700448 LOG(FATAL) << "Attempt to clear a bit not set in the vector yet";;
449 }
buzbee67bf8852011-08-17 17:51:35 -0700450
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 pBits->storage[num >> 5] &= ~checkMasks[num & 0x1f];
452 return true;
buzbee67bf8852011-08-17 17:51:35 -0700453}
454
455/*
456 * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
457 */
458void oatMarkAllBits(ArenaBitVector* pBits, bool set)
459{
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 int value = set ? -1 : 0;
buzbeeeaf09bc2012-11-15 14:51:41 -0800461 memset(pBits->storage, value, pBits->storageSize * static_cast<int>(sizeof(uint32_t)));
buzbee67bf8852011-08-17 17:51:35 -0700462}
463
464void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
465{
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 int i;
buzbee67bf8852011-08-17 17:51:35 -0700467
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 LOG(INFO) << msg;
469 for (i = 0; i < length; i++) {
470 if (oatIsBitSet(bv, i)) {
471 LOG(INFO) << " Bit " << i << " is set";
buzbee67bf8852011-08-17 17:51:35 -0700472 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700473 }
buzbee67bf8852011-08-17 17:51:35 -0700474}
475
476void oatAbort(CompilationUnit* cUnit)
477{
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 LOG(FATAL) << "Compiler aborting";
buzbee67bf8852011-08-17 17:51:35 -0700479}
480
481void oatDumpBlockBitVector(const GrowableList* blocks, char* msg,
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 const ArenaBitVector* bv, int length)
buzbee67bf8852011-08-17 17:51:35 -0700483{
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 int i;
buzbee67bf8852011-08-17 17:51:35 -0700485
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 LOG(INFO) << msg;
487 for (i = 0; i < length; i++) {
488 if (oatIsBitSet(bv, i)) {
489 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blocks, i);
490 char blockName[BLOCK_NAME_LEN];
491 oatGetBlockName(bb, blockName);
492 LOG(INFO) << "Bit " << i << " / " << blockName << " is set";
buzbee67bf8852011-08-17 17:51:35 -0700493 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 }
buzbee67bf8852011-08-17 17:51:35 -0700495}
496/* Initialize the iterator structure */
497void oatBitVectorIteratorInit(ArenaBitVector* pBits,
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 ArenaBitVectorIterator* iterator)
buzbee67bf8852011-08-17 17:51:35 -0700499{
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 iterator->pBits = pBits;
buzbeeeaf09bc2012-11-15 14:51:41 -0800501 iterator->bitSize = pBits->storageSize * sizeof(uint32_t) * 8;
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 iterator->idx = 0;
buzbee67bf8852011-08-17 17:51:35 -0700503}
504
505/*
506 * If the vector sizes don't match, log an error and abort.
507 */
buzbee31a4a6f2012-02-28 15:36:15 -0800508void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
buzbee67bf8852011-08-17 17:51:35 -0700509{
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 if (bv1->storageSize != bv2->storageSize) {
511 LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize
512 << ", " << bv2->storageSize << ")";
513 }
buzbee67bf8852011-08-17 17:51:35 -0700514}
515
516/*
517 * Copy a whole vector to the other. Only do that when the both vectors have
518 * the same size.
519 */
520void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
521{
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 /* if dest is expandable and < src, we could expand dest to match */
523 checkSizes(dest, src);
buzbee67bf8852011-08-17 17:51:35 -0700524
buzbeeeaf09bc2012-11-15 14:51:41 -0800525 memcpy(dest->storage, src->storage, sizeof(uint32_t) * dest->storageSize);
buzbee67bf8852011-08-17 17:51:35 -0700526}
527
528/*
529 * Intersect two bit vectors and store the result to the dest vector.
530 */
531
532bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700534{
Bill Buzbeea114add2012-05-03 15:00:40 -0700535 DCHECK(src1 != NULL);
536 DCHECK(src2 != NULL);
537 if (dest->storageSize != src1->storageSize ||
538 dest->storageSize != src2->storageSize ||
539 dest->expandable != src1->expandable ||
540 dest->expandable != src2->expandable)
541 return false;
buzbee67bf8852011-08-17 17:51:35 -0700542
Bill Buzbeea114add2012-05-03 15:00:40 -0700543 unsigned int idx;
544 for (idx = 0; idx < dest->storageSize; idx++) {
545 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
546 }
547 return true;
buzbee67bf8852011-08-17 17:51:35 -0700548}
549
550/*
551 * Unify two bit vectors and store the result to the dest vector.
552 */
553bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700554 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700555{
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 DCHECK(src1 != NULL);
557 DCHECK(src2 != NULL);
558 if (dest->storageSize != src1->storageSize ||
559 dest->storageSize != src2->storageSize ||
560 dest->expandable != src1->expandable ||
561 dest->expandable != src2->expandable)
562 return false;
buzbee67bf8852011-08-17 17:51:35 -0700563
Bill Buzbeea114add2012-05-03 15:00:40 -0700564 unsigned int idx;
565 for (idx = 0; idx < dest->storageSize; idx++) {
566 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
567 }
568 return true;
buzbee67bf8852011-08-17 17:51:35 -0700569}
570
571/*
buzbeee1965672012-03-11 18:39:19 -0700572 * Return true if any bits collide. Vectors must be same size.
573 */
574bool oatTestBitVectors(const ArenaBitVector* src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 const ArenaBitVector* src2)
buzbeee1965672012-03-11 18:39:19 -0700576{
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 DCHECK_EQ(src1->storageSize, src2->storageSize);
578 for (uint32_t idx = 0; idx < src1->storageSize; idx++) {
579 if (src1->storage[idx] & src2->storage[idx]) return true;
580 }
581 return false;
buzbeee1965672012-03-11 18:39:19 -0700582}
583
584/*
buzbee67bf8852011-08-17 17:51:35 -0700585 * Compare two bit vectors and return true if difference is seen.
586 */
587bool oatCompareBitVectors(const ArenaBitVector* src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700588 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700589{
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 if (src1->storageSize != src2->storageSize ||
591 src1->expandable != src2->expandable)
592 return true;
buzbee67bf8852011-08-17 17:51:35 -0700593
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 unsigned int idx;
595 for (idx = 0; idx < src1->storageSize; idx++) {
596 if (src1->storage[idx] != src2->storage[idx]) return true;
597 }
598 return false;
buzbee67bf8852011-08-17 17:51:35 -0700599}
600
601/*
602 * Count the number of bits that are set.
603 */
604int oatCountSetBits(const ArenaBitVector* pBits)
605{
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 unsigned int word;
607 unsigned int count = 0;
buzbee67bf8852011-08-17 17:51:35 -0700608
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 for (word = 0; word < pBits->storageSize; word++) {
buzbeeeaf09bc2012-11-15 14:51:41 -0800610 uint32_t val = pBits->storage[word];
buzbee67bf8852011-08-17 17:51:35 -0700611
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 if (val != 0) {
613 if (val == 0xffffffff) {
614 count += 32;
615 } else {
616 /* count the number of '1' bits */
617 while (val != 0) {
618 val &= val - 1;
619 count++;
buzbee67bf8852011-08-17 17:51:35 -0700620 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700621 }
buzbee67bf8852011-08-17 17:51:35 -0700622 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 }
buzbee67bf8852011-08-17 17:51:35 -0700624
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 return count;
buzbee67bf8852011-08-17 17:51:35 -0700626}
627
628/* Return the next position set to 1. -1 means end-of-element reached */
629int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
630{
Bill Buzbeea114add2012-05-03 15:00:40 -0700631 ArenaBitVector* pBits = iterator->pBits;
buzbeeeaf09bc2012-11-15 14:51:41 -0800632 uint32_t bitIndex = iterator->idx;
633 uint32_t bitSize = iterator->bitSize;
buzbee67bf8852011-08-17 17:51:35 -0700634
buzbeeeaf09bc2012-11-15 14:51:41 -0800635 DCHECK_EQ(bitSize, pBits->storageSize * sizeof(uint32_t) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700636
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 if (bitIndex >= bitSize) return -1;
buzbee5b537102012-01-17 17:33:47 -0800638
buzbeeeaf09bc2012-11-15 14:51:41 -0800639 uint32_t wordIndex = bitIndex >> 5;
640 uint32_t endWordIndex = bitSize >> 5;
641 uint32_t* storage = pBits->storage;
642 uint32_t word = storage[wordIndex++];
buzbee5b537102012-01-17 17:33:47 -0800643
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 // Mask out any bits in the first word we've already considered
645 word &= ~((1 << (bitIndex & 0x1f))-1);
buzbee5abfa3e2012-01-31 17:01:43 -0800646
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 for (; wordIndex <= endWordIndex;) {
buzbeeeaf09bc2012-11-15 14:51:41 -0800648 uint32_t bitPos = bitIndex & 0x1f;
Bill Buzbeea114add2012-05-03 15:00:40 -0700649 if (word == 0) {
650 bitIndex += (32 - bitPos);
651 word = storage[wordIndex++];
652 continue;
buzbee67bf8852011-08-17 17:51:35 -0700653 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700654 for (; bitPos < 32; bitPos++) {
655 if (word & (1 << bitPos)) {
656 iterator->idx = bitIndex + 1;
657 return bitIndex;
658 }
659 bitIndex++;
660 }
661 word = storage[wordIndex++];
662 }
663 iterator->idx = iterator->bitSize;
664 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700665}
666
667/*
668 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
669 * since there might be unused bits - setting those to one will confuse the
670 * iterator.
671 */
672void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
673{
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 unsigned int idx;
675 DCHECK_LE(((numBits + 31) >> 5), pBits->storageSize);
676 for (idx = 0; idx < (numBits >> 5); idx++) {
677 pBits->storage[idx] = -1;
678 }
679 unsigned int remNumBits = numBits & 0x1f;
680 if (remNumBits) {
681 pBits->storage[idx] = (1 << remNumBits) - 1;
682 }
buzbee67bf8852011-08-17 17:51:35 -0700683}
684
685void oatGetBlockName(BasicBlock* bb, char* name)
686{
Bill Buzbeea114add2012-05-03 15:00:40 -0700687 switch (bb->blockType) {
688 case kEntryBlock:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700689 snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700690 break;
691 case kExitBlock:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700692 snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700693 break;
694 case kDalvikByteCode:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700695 snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 break;
697 case kExceptionHandling:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700698 snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->startOffset,
699 bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700700 break;
701 default:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700702 snprintf(name, BLOCK_NAME_LEN, "??_%d", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700703 break;
704 }
buzbee67bf8852011-08-17 17:51:35 -0700705}
buzbeeed3e9302011-09-23 17:34:19 -0700706
707const char* oatGetShortyFromTargetIdx(CompilationUnit *cUnit, int targetIdx)
708{
Bill Buzbeea114add2012-05-03 15:00:40 -0700709 const DexFile::MethodId& methodId = cUnit->dex_file->GetMethodId(targetIdx);
710 return cUnit->dex_file->GetShorty(methodId.proto_idx_);
buzbeeed3e9302011-09-23 17:34:19 -0700711}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800712
713} // namespace art