blob: f86b72cde9167261c19ea9275c76df2fd63eadb6 [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
17#include "Dalvik.h"
18#include "CompilerInternals.h"
19
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080020namespace art {
21
buzbee5abfa3e2012-01-31 17:01:43 -080022#ifdef WITH_MEMSTATS
buzbeeba938cb2012-02-03 14:47:55 -080023typedef struct Memstats {
24 u4 allocStats[kNumAllocKinds];
25 int listSizes[kNumListKinds];
26 int listWasted[kNumListKinds];
27 int listGrows[kNumListKinds];
28 int listMaxElems[kNumListKinds];
29 int bitMapSizes[kNumBitMapKinds];
30 int bitMapWasted[kNumBitMapKinds];
31 int bitMapGrows[kNumBitMapKinds];
32} memstats;
buzbee5abfa3e2012-01-31 17:01:43 -080033
34const char* allocNames[kNumAllocKinds] = {
35 "Misc ",
36 "BasicBlock ",
37 "LIR ",
38 "MIR ",
39 "DataFlow ",
40 "GrowList ",
41 "GrowBitMap ",
42 "Dalvik2SSA ",
43 "DebugInfo ",
44 "Successor ",
45 "RegAlloc ",
46 "Data ",
47 "Preds ",
48};
49
50const char* listNames[kNumListKinds] = {
51 "Misc ",
52 "blockList ",
53 "SSAtoDalvik ",
54 "dfsOrder ",
55 "dfsPostOrder ",
56 "domPostOrderTraversal ",
57 "throwLaunchPads ",
58 "suspendLaunchPads ",
59 "switchTables ",
60 "fillArrayData ",
61 "SuccessorBlocks ",
62 "Predecessors ",
63};
64
65const char* bitMapNames[kNumBitMapKinds] = {
66 "Misc ",
67 "Use ",
68 "Def ",
69 "LiveIn ",
70 "BlockMatrix ",
71 "Dominators ",
72 "IDominated ",
73 "DomFrontier ",
74 "Phi ",
75 "TmpBlocks ",
76 "InputBlocks ",
77 "RegisterV ",
78 "TempSSARegisterV ",
79 "Null Check ",
80 "TmpBlockV ",
81 "Predecessors ",
82};
83#endif
84
buzbee67bf8852011-08-17 17:51:35 -070085#define kArenaBitVectorGrowth 4 /* increase by 4 u4s when limit hit */
86
87/* Allocate the initial memory block for arena-based allocation */
buzbeeba938cb2012-02-03 14:47:55 -080088bool oatHeapInit(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070089{
buzbeeba938cb2012-02-03 14:47:55 -080090 DCHECK(cUnit->arenaHead == NULL);
91 cUnit->arenaHead =
buzbee67bf8852011-08-17 17:51:35 -070092 (ArenaMemBlock *) malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
buzbeeba938cb2012-02-03 14:47:55 -080093 if (cUnit->arenaHead == NULL) {
buzbee67bf8852011-08-17 17:51:35 -070094 LOG(FATAL) << "No memory left to create compiler heap memory";
95 }
buzbeeba938cb2012-02-03 14:47:55 -080096 cUnit->arenaHead->blockSize = ARENA_DEFAULT_SIZE;
97 cUnit->currentArena = cUnit->arenaHead;
98 cUnit->currentArena->bytesAllocated = 0;
99 cUnit->currentArena->next = NULL;
100 cUnit->numArenaBlocks = 1;
101#ifdef WITH_MEMSTATS
102 cUnit->mstats = (Memstats*) oatNew(cUnit, sizeof(Memstats), true,
103 kAllocDebugInfo);
104#endif
buzbee67bf8852011-08-17 17:51:35 -0700105 return true;
106}
107
108/* Arena-based malloc for compilation tasks */
buzbeeba938cb2012-02-03 14:47:55 -0800109void* oatNew(CompilationUnit* cUnit, size_t size, bool zero, oatAllocKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700110{
111 size = (size + 3) & ~3;
buzbee5abfa3e2012-01-31 17:01:43 -0800112#ifdef WITH_MEMSTATS
buzbeeba938cb2012-02-03 14:47:55 -0800113 if (cUnit->mstats != NULL) {
114 cUnit->mstats->allocStats[kind] += size;
115 }
buzbee5abfa3e2012-01-31 17:01:43 -0800116#endif
buzbee67bf8852011-08-17 17:51:35 -0700117retry:
118 /* Normal case - space is available in the current page */
buzbeeba938cb2012-02-03 14:47:55 -0800119 if (size + cUnit->currentArena->bytesAllocated <=
120 cUnit->currentArena->blockSize) {
buzbee67bf8852011-08-17 17:51:35 -0700121 void *ptr;
buzbeeba938cb2012-02-03 14:47:55 -0800122 ptr = &cUnit->currentArena->ptr[cUnit->currentArena->bytesAllocated];
123 cUnit->currentArena->bytesAllocated += size;
buzbee67bf8852011-08-17 17:51:35 -0700124 if (zero) {
125 memset(ptr, 0, size);
126 }
127 return ptr;
128 } else {
129 /*
130 * See if there are previously allocated arena blocks before the last
131 * reset
132 */
buzbeeba938cb2012-02-03 14:47:55 -0800133 if (cUnit->currentArena->next) {
134 cUnit->currentArena = cUnit->currentArena->next;
135 cUnit->currentArena->bytesAllocated = 0;
buzbee67bf8852011-08-17 17:51:35 -0700136 goto retry;
137 }
138
139 size_t blockSize = (size < ARENA_DEFAULT_SIZE) ?
140 ARENA_DEFAULT_SIZE : size;
141 /* Time to allocate a new arena */
142 ArenaMemBlock *newArena = (ArenaMemBlock *)
143 malloc(sizeof(ArenaMemBlock) + blockSize);
144 if (newArena == NULL) {
145 LOG(FATAL) << "Arena allocation failure";
146 }
147 newArena->blockSize = blockSize;
148 newArena->bytesAllocated = 0;
149 newArena->next = NULL;
buzbeeba938cb2012-02-03 14:47:55 -0800150 cUnit->currentArena->next = newArena;
151 cUnit->currentArena = newArena;
152 cUnit->numArenaBlocks++;
153 if (cUnit->numArenaBlocks > 20000) {
154 LOG(INFO) << "Total arena pages: " << cUnit->numArenaBlocks;
buzbee67bf8852011-08-17 17:51:35 -0700155 }
156 goto retry;
157 }
158}
159
160/* Reclaim all the arena blocks allocated so far */
buzbeeba938cb2012-02-03 14:47:55 -0800161void oatArenaReset(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700162{
buzbeeba938cb2012-02-03 14:47:55 -0800163 ArenaMemBlock* head = cUnit->arenaHead;
164 while (head != NULL) {
165 ArenaMemBlock* p = head;
166 head = head->next;
167 free(p);
buzbee67bc2362011-10-11 18:08:40 -0700168 }
buzbeeba938cb2012-02-03 14:47:55 -0800169 cUnit->arenaHead = NULL;
170 cUnit->currentArena = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700171}
172
173/* Growable List initialization */
buzbeeba938cb2012-02-03 14:47:55 -0800174void oatInitGrowableList(CompilationUnit* cUnit, GrowableList* gList,
175 size_t initLength, oatListKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700176{
177 gList->numAllocated = initLength;
178 gList->numUsed = 0;
buzbeeba938cb2012-02-03 14:47:55 -0800179 gList->elemList = (intptr_t *) oatNew(cUnit, sizeof(intptr_t) * initLength,
180 true, kAllocGrowableList);
buzbee5abfa3e2012-01-31 17:01:43 -0800181#ifdef WITH_MEMSTATS
buzbeeba938cb2012-02-03 14:47:55 -0800182 cUnit->mstats->listSizes[kind] += sizeof(intptr_t) * initLength;
buzbee5abfa3e2012-01-31 17:01:43 -0800183 gList->kind = kind;
buzbeeba938cb2012-02-03 14:47:55 -0800184 if ((int)initLength > cUnit->mstats->listMaxElems[kind]) {
185 cUnit->mstats->listMaxElems[kind] = initLength;
buzbee5abfa3e2012-01-31 17:01:43 -0800186 }
187#endif
buzbee67bf8852011-08-17 17:51:35 -0700188}
189
190/* Expand the capacity of a growable list */
buzbee31a4a6f2012-02-28 15:36:15 -0800191void expandGrowableList(CompilationUnit* cUnit, GrowableList* gList)
buzbee67bf8852011-08-17 17:51:35 -0700192{
193 int newLength = gList->numAllocated;
194 if (newLength < 128) {
195 newLength <<= 1;
196 } else {
197 newLength += 128;
198 }
199 intptr_t *newArray =
buzbeeba938cb2012-02-03 14:47:55 -0800200 (intptr_t *) oatNew(cUnit, sizeof(intptr_t) * newLength, true,
buzbee5abfa3e2012-01-31 17:01:43 -0800201 kAllocGrowableList);
buzbee67bf8852011-08-17 17:51:35 -0700202 memcpy(newArray, gList->elemList, sizeof(intptr_t) * gList->numAllocated);
buzbee5abfa3e2012-01-31 17:01:43 -0800203#ifdef WITH_MEMSTATS
buzbeeba938cb2012-02-03 14:47:55 -0800204 cUnit->mstats->listSizes[gList->kind] += sizeof(intptr_t) * newLength;
205 cUnit->mstats->listWasted[gList->kind] +=
206 sizeof(intptr_t) * gList->numAllocated;
207 cUnit->mstats->listGrows[gList->kind]++;
208 if (newLength > cUnit->mstats->listMaxElems[gList->kind]) {
209 cUnit->mstats->listMaxElems[gList->kind] = newLength;
buzbee5abfa3e2012-01-31 17:01:43 -0800210 }
211#endif
buzbee67bf8852011-08-17 17:51:35 -0700212 gList->numAllocated = newLength;
213 gList->elemList = newArray;
214}
215
216/* Insert a new element into the growable list */
buzbeeba938cb2012-02-03 14:47:55 -0800217void oatInsertGrowableList(CompilationUnit* cUnit, GrowableList* gList,
218 intptr_t elem)
buzbee67bf8852011-08-17 17:51:35 -0700219{
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700220 DCHECK_NE(gList->numAllocated, 0U);
buzbee67bf8852011-08-17 17:51:35 -0700221 if (gList->numUsed == gList->numAllocated) {
buzbeeba938cb2012-02-03 14:47:55 -0800222 expandGrowableList(cUnit, gList);
buzbee67bf8852011-08-17 17:51:35 -0700223 }
224 gList->elemList[gList->numUsed++] = elem;
225}
226
buzbee5abfa3e2012-01-31 17:01:43 -0800227/* Delete an element from a growable list. Element must be present */
228void oatDeleteGrowableList(GrowableList* gList, intptr_t elem)
229{
230 bool found = false;
231 for (unsigned int i = 0; i < gList->numUsed; i++) {
232 if (!found && gList->elemList[i] == elem) {
233 found = true;
234 }
235 if (found) {
236 gList->elemList[i] = gList->elemList[i+1];
237 }
238 }
239 DCHECK_EQ(found, true);
240 gList->numUsed--;
241}
242
buzbee67bf8852011-08-17 17:51:35 -0700243void oatGrowableListIteratorInit(GrowableList* gList,
244 GrowableListIterator* iterator)
245{
246 iterator->list = gList;
247 iterator->idx = 0;
248 iterator->size = gList->numUsed;
249}
250
251intptr_t oatGrowableListIteratorNext(GrowableListIterator* iterator)
252{
buzbeeed3e9302011-09-23 17:34:19 -0700253 DCHECK_EQ(iterator->size, iterator->list->numUsed);
buzbee67bf8852011-08-17 17:51:35 -0700254 if (iterator->idx == iterator->size) return 0;
255 return iterator->list->elemList[iterator->idx++];
256}
257
258intptr_t oatGrowableListGetElement(const GrowableList* gList, size_t idx)
259{
buzbeeed3e9302011-09-23 17:34:19 -0700260 DCHECK_LT(idx, gList->numUsed);
buzbee67bf8852011-08-17 17:51:35 -0700261 return gList->elemList[idx];
262}
263
buzbee5abfa3e2012-01-31 17:01:43 -0800264#ifdef WITH_MEMSTATS
265/* Dump memory usage stats */
266void oatDumpMemStats(CompilationUnit* cUnit)
267{
268 u4 total = 0;
269 for (int i = 0; i < kNumAllocKinds; i++) {
buzbeeba938cb2012-02-03 14:47:55 -0800270 total += cUnit->mstats->allocStats[i];
buzbee5abfa3e2012-01-31 17:01:43 -0800271 }
272 if (total > (10 * 1024 * 1024)) {
273 LOG(INFO) << "MEMUSAGE: " << total << " : "
274 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
275 LOG(INFO) << "insnsSize: " << cUnit->insnsSize;
276 if (cUnit->disableDataflow) {
277 LOG(INFO) << " ** Dataflow disabled ** ";
278 }
279 LOG(INFO) << "===== Overall allocations";
280 for (int i = 0; i < kNumAllocKinds; i++) {
buzbeeba938cb2012-02-03 14:47:55 -0800281 LOG(INFO) << allocNames[i] << std::setw(10) <<
282 cUnit->mstats->allocStats[i];
buzbee5abfa3e2012-01-31 17:01:43 -0800283 }
284 LOG(INFO) << "===== GrowableList allocations";
285 for (int i = 0; i < kNumListKinds; i++) {
286 LOG(INFO) << listNames[i]
buzbeeba938cb2012-02-03 14:47:55 -0800287 << " S:" << cUnit->mstats->listSizes[i]
288 << ", W:" << cUnit->mstats->listWasted[i]
289 << ", G:" << cUnit->mstats->listGrows[i]
290 << ", E:" << cUnit->mstats->listMaxElems[i];
buzbee5abfa3e2012-01-31 17:01:43 -0800291 }
292 LOG(INFO) << "===== GrowableBitMap allocations";
293 for (int i = 0; i < kNumBitMapKinds; i++) {
294 LOG(INFO) << bitMapNames[i]
buzbeeba938cb2012-02-03 14:47:55 -0800295 << " S:" << cUnit->mstats->bitMapSizes[i]
296 << ", W:" << cUnit->mstats->bitMapWasted[i]
297 << ", G:" << cUnit->mstats->bitMapGrows[i];
buzbee5abfa3e2012-01-31 17:01:43 -0800298 }
299 }
300}
301#endif
302
buzbee67bf8852011-08-17 17:51:35 -0700303/* Debug Utility - dump a compilation unit */
304void oatDumpCompilationUnit(CompilationUnit* cUnit)
305{
306 BasicBlock* bb;
307 const char* blockTypeNames[] = {
308 "Entry Block",
309 "Code Block",
310 "Exit Block",
311 "Exception Handling",
312 "Catch Block"
313 };
314
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800315 LOG(INFO) << "Compiling " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
buzbee67bf8852011-08-17 17:51:35 -0700316 LOG(INFO) << cUnit->insns << " insns";
317 LOG(INFO) << cUnit->numBlocks << " blocks in total";
318 GrowableListIterator iterator;
319
320 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
321
322 while (true) {
323 bb = (BasicBlock *) oatGrowableListIteratorNext(&iterator);
324 if (bb == NULL) break;
325 char buf[100];
326 snprintf(buf, 100, "Block %d (%s) (insn %04x - %04x%s)",
327 bb->id,
328 blockTypeNames[bb->blockType],
329 bb->startOffset,
330 bb->lastMIRInsn ? bb->lastMIRInsn->offset : bb->startOffset,
331 bb->lastMIRInsn ? "" : " empty");
332 LOG(INFO) << buf;
333 if (bb->taken) {
334 LOG(INFO) << " Taken branch: block " << bb->taken->id <<
335 "(0x" << std::hex << bb->taken->startOffset << ")";
336 }
337 if (bb->fallThrough) {
338 LOG(INFO) << " Fallthrough : block " << bb->fallThrough->id <<
339 " (0x" << std::hex << bb->fallThrough->startOffset << ")";
340 }
341 }
342}
343
buzbee67bc2362011-10-11 18:08:40 -0700344static uint32_t checkMasks[32] = {
345 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
346 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200,
347 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000,
348 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000,
349 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000,
350 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
351 0x40000000, 0x80000000 };
352
buzbee67bf8852011-08-17 17:51:35 -0700353/*
354 * Allocate a bit vector with enough space to hold at least the specified
355 * number of bits.
356 *
357 * NOTE: memory is allocated from the compiler arena.
358 */
buzbeeba938cb2012-02-03 14:47:55 -0800359ArenaBitVector* oatAllocBitVector(CompilationUnit* cUnit,
360 unsigned int startBits, bool expandable,
buzbee5abfa3e2012-01-31 17:01:43 -0800361 oatBitMapKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700362{
363 ArenaBitVector* bv;
364 unsigned int count;
365
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700366 DCHECK_EQ(sizeof(bv->storage[0]), 4U); /* assuming 32-bit units */
buzbee67bf8852011-08-17 17:51:35 -0700367
buzbeeba938cb2012-02-03 14:47:55 -0800368 bv = (ArenaBitVector*) oatNew(cUnit, sizeof(ArenaBitVector), false,
buzbee5abfa3e2012-01-31 17:01:43 -0800369 kAllocGrowableBitMap);
buzbee67bf8852011-08-17 17:51:35 -0700370
371 count = (startBits + 31) >> 5;
372
373 bv->storageSize = count;
374 bv->expandable = expandable;
buzbeeba938cb2012-02-03 14:47:55 -0800375 bv->storage = (u4*) oatNew(cUnit, count * sizeof(u4), true,
376 kAllocGrowableBitMap);
buzbee5abfa3e2012-01-31 17:01:43 -0800377#ifdef WITH_MEMSTATS
378 bv->kind = kind;
buzbeeba938cb2012-02-03 14:47:55 -0800379 cUnit->mstats->bitMapSizes[kind] += count * sizeof(u4);
buzbee5abfa3e2012-01-31 17:01:43 -0800380#endif
buzbee67bf8852011-08-17 17:51:35 -0700381 return bv;
382}
383
384/*
385 * Determine whether or not the specified bit is set.
386 */
387bool oatIsBitSet(const ArenaBitVector* pBits, unsigned int num)
388{
buzbeeed3e9302011-09-23 17:34:19 -0700389 DCHECK_LT(num, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700390
buzbee67bc2362011-10-11 18:08:40 -0700391 unsigned int val = pBits->storage[num >> 5] & checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700392 return (val != 0);
393}
394
395/*
396 * Mark all bits bit as "clear".
397 */
398void oatClearAllBits(ArenaBitVector* pBits)
399{
400 unsigned int count = pBits->storageSize;
401 memset(pBits->storage, 0, count * sizeof(u4));
402}
403
404/*
405 * Mark the specified bit as "set".
406 *
407 * Returns "false" if the bit is outside the range of the vector and we're
408 * not allowed to expand.
409 *
410 * NOTE: memory is allocated from the compiler arena.
411 */
buzbeeba938cb2012-02-03 14:47:55 -0800412bool oatSetBit(CompilationUnit* cUnit, ArenaBitVector* pBits, unsigned int num)
buzbee67bf8852011-08-17 17:51:35 -0700413{
414 if (num >= pBits->storageSize * sizeof(u4) * 8) {
415 if (!pBits->expandable) {
416 LOG(FATAL) << "Can't expand";
417 }
418
419 /* Round up to word boundaries for "num+1" bits */
420 unsigned int newSize = (num + 1 + 31) >> 5;
buzbeeed3e9302011-09-23 17:34:19 -0700421 DCHECK_GT(newSize, pBits->storageSize);
buzbeeba938cb2012-02-03 14:47:55 -0800422 u4 *newStorage = (u4*)oatNew(cUnit, newSize * sizeof(u4), false,
buzbee5abfa3e2012-01-31 17:01:43 -0800423 kAllocGrowableBitMap);
buzbee67bf8852011-08-17 17:51:35 -0700424 memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
425 memset(&newStorage[pBits->storageSize], 0,
426 (newSize - pBits->storageSize) * sizeof(u4));
buzbee5abfa3e2012-01-31 17:01:43 -0800427#ifdef WITH_MEMSTATS
buzbeeba938cb2012-02-03 14:47:55 -0800428 cUnit->mstats->bitMapWasted[pBits->kind] +=
429 pBits->storageSize * sizeof(u4);
430 cUnit->mstats->bitMapSizes[pBits->kind] += newSize * sizeof(u4);
431 cUnit->mstats->bitMapGrows[pBits->kind]++;
buzbee5abfa3e2012-01-31 17:01:43 -0800432#endif
buzbee67bf8852011-08-17 17:51:35 -0700433 pBits->storage = newStorage;
434 pBits->storageSize = newSize;
435 }
436
buzbee67bc2362011-10-11 18:08:40 -0700437 pBits->storage[num >> 5] |= checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700438 return true;
439}
440
441/*
442 * Mark the specified bit as "unset".
443 *
444 * Returns "false" if the bit is outside the range of the vector and we're
445 * not allowed to expand.
446 *
447 * NOTE: memory is allocated from the compiler arena.
448 */
449bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
450{
451 if (num >= pBits->storageSize * sizeof(u4) * 8) {
452 LOG(FATAL) << "Attempt to clear a bit not set in the vector yet";;
453 }
454
buzbee67bc2362011-10-11 18:08:40 -0700455 pBits->storage[num >> 5] &= ~checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700456 return true;
457}
458
459/*
460 * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
461 */
462void oatMarkAllBits(ArenaBitVector* pBits, bool set)
463{
464 int value = set ? -1 : 0;
465 memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
466}
467
468void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
469{
470 int i;
471
472 LOG(INFO) << msg;
473 for (i = 0; i < length; i++) {
474 if (oatIsBitSet(bv, i)) {
475 LOG(INFO) << " Bit " << i << " is set";
476 }
477 }
478}
479
480void oatAbort(CompilationUnit* cUnit)
481{
482 LOG(FATAL) << "Compiler aborting";
483}
484
485void oatDumpBlockBitVector(const GrowableList* blocks, char* msg,
486 const ArenaBitVector* bv, int length)
487{
488 int i;
489
490 LOG(INFO) << msg;
491 for (i = 0; i < length; i++) {
492 if (oatIsBitSet(bv, i)) {
493 BasicBlock *bb =
494 (BasicBlock *) oatGrowableListGetElement(blocks, i);
495 char blockName[BLOCK_NAME_LEN];
496 oatGetBlockName(bb, blockName);
497 LOG(INFO) << "Bit " << i << " / " << blockName << " is set";
498 }
499 }
500}
501/* Initialize the iterator structure */
502void oatBitVectorIteratorInit(ArenaBitVector* pBits,
503 ArenaBitVectorIterator* iterator)
504{
505 iterator->pBits = pBits;
506 iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
507 iterator->idx = 0;
508}
509
510/*
511 * If the vector sizes don't match, log an error and abort.
512 */
buzbee31a4a6f2012-02-28 15:36:15 -0800513void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
buzbee67bf8852011-08-17 17:51:35 -0700514{
515 if (bv1->storageSize != bv2->storageSize) {
516 LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize <<
517 ", " << bv2->storageSize << ")";
518 }
519}
520
521/*
522 * Copy a whole vector to the other. Only do that when the both vectors have
523 * the same size.
524 */
525void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
526{
527 /* if dest is expandable and < src, we could expand dest to match */
528 checkSizes(dest, src);
529
530 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
531}
532
533/*
534 * Intersect two bit vectors and store the result to the dest vector.
535 */
536
537bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
538 const ArenaBitVector* src2)
539{
buzbeeaad72012011-09-21 21:52:09 -0700540 DCHECK(src1 != NULL);
541 DCHECK(src2 != NULL);
542 if (dest->storageSize != src1->storageSize ||
buzbee67bf8852011-08-17 17:51:35 -0700543 dest->storageSize != src2->storageSize ||
544 dest->expandable != src1->expandable ||
545 dest->expandable != src2->expandable)
546 return false;
547
548 unsigned int idx;
549 for (idx = 0; idx < dest->storageSize; idx++) {
550 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
551 }
552 return true;
553}
554
555/*
556 * Unify two bit vectors and store the result to the dest vector.
557 */
558bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
559 const ArenaBitVector* src2)
560{
buzbeeaad72012011-09-21 21:52:09 -0700561 DCHECK(src1 != NULL);
562 DCHECK(src2 != NULL);
563 if (dest->storageSize != src1->storageSize ||
buzbee67bf8852011-08-17 17:51:35 -0700564 dest->storageSize != src2->storageSize ||
565 dest->expandable != src1->expandable ||
566 dest->expandable != src2->expandable)
567 return false;
568
569 unsigned int idx;
570 for (idx = 0; idx < dest->storageSize; idx++) {
571 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
572 }
573 return true;
574}
575
576/*
577 * Compare two bit vectors and return true if difference is seen.
578 */
579bool oatCompareBitVectors(const ArenaBitVector* src1,
580 const ArenaBitVector* src2)
581{
582 if (src1->storageSize != src2->storageSize ||
583 src1->expandable != src2->expandable)
584 return true;
585
586 unsigned int idx;
587 for (idx = 0; idx < src1->storageSize; idx++) {
588 if (src1->storage[idx] != src2->storage[idx]) return true;
589 }
590 return false;
591}
592
593/*
594 * Count the number of bits that are set.
595 */
596int oatCountSetBits(const ArenaBitVector* pBits)
597{
598 unsigned int word;
599 unsigned int count = 0;
600
601 for (word = 0; word < pBits->storageSize; word++) {
602 u4 val = pBits->storage[word];
603
604 if (val != 0) {
605 if (val == 0xffffffff) {
606 count += 32;
607 } else {
608 /* count the number of '1' bits */
609 while (val != 0) {
610 val &= val - 1;
611 count++;
612 }
613 }
614 }
615 }
616
617 return count;
618}
619
620/* Return the next position set to 1. -1 means end-of-element reached */
621int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
622{
buzbee5b537102012-01-17 17:33:47 -0800623 ArenaBitVector* pBits = iterator->pBits;
buzbee67bf8852011-08-17 17:51:35 -0700624 u4 bitIndex = iterator->idx;
buzbee5abfa3e2012-01-31 17:01:43 -0800625 u4 bitSize = iterator->bitSize;
buzbee67bf8852011-08-17 17:51:35 -0700626
buzbee5abfa3e2012-01-31 17:01:43 -0800627 DCHECK_EQ(bitSize, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700628
buzbee5abfa3e2012-01-31 17:01:43 -0800629 if (bitIndex >= bitSize) return -1;
buzbee5b537102012-01-17 17:33:47 -0800630
buzbee5abfa3e2012-01-31 17:01:43 -0800631 u4 wordIndex = bitIndex >> 5;
632 u4 endWordIndex = bitSize >> 5;
633 u4* storage = pBits->storage;
634 u4 word = storage[wordIndex++];
buzbee5b537102012-01-17 17:33:47 -0800635
buzbee5abfa3e2012-01-31 17:01:43 -0800636 // Mask out any bits in the first word we've already considered
637 word &= ~((1 << (bitIndex & 0x1f))-1);
638
639 for (; wordIndex <= endWordIndex;) {
640 u4 bitPos = bitIndex & 0x1f;
buzbee67bc2362011-10-11 18:08:40 -0700641 if (word == 0) {
buzbee67bc2362011-10-11 18:08:40 -0700642 bitIndex += (32 - bitPos);
buzbee5abfa3e2012-01-31 17:01:43 -0800643 word = storage[wordIndex++];
644 continue;
645 }
646 for (; bitPos < 32; bitPos++) {
647 if (word & (1 << bitPos)) {
648 iterator->idx = bitIndex + 1;
649 return bitIndex;
650 }
buzbee67bc2362011-10-11 18:08:40 -0700651 bitIndex++;
652 }
buzbee5abfa3e2012-01-31 17:01:43 -0800653 word = storage[wordIndex++];
buzbee67bf8852011-08-17 17:51:35 -0700654 }
buzbee5abfa3e2012-01-31 17:01:43 -0800655 iterator->idx = iterator->bitSize;
buzbee67bf8852011-08-17 17:51:35 -0700656 return -1;
657}
658
659/*
660 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
661 * since there might be unused bits - setting those to one will confuse the
662 * iterator.
663 */
664void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
665{
666 unsigned int idx;
buzbeeed3e9302011-09-23 17:34:19 -0700667 DCHECK_LE(((numBits + 31) >> 5), pBits->storageSize);
buzbee67bf8852011-08-17 17:51:35 -0700668 for (idx = 0; idx < (numBits >> 5); idx++) {
669 pBits->storage[idx] = -1;
670 }
671 unsigned int remNumBits = numBits & 0x1f;
672 if (remNumBits) {
673 pBits->storage[idx] = (1 << remNumBits) - 1;
674 }
675}
676
677void oatGetBlockName(BasicBlock* bb, char* name)
678{
679 switch (bb->blockType) {
680 case kEntryBlock:
681 snprintf(name, BLOCK_NAME_LEN, "entry");
682 break;
683 case kExitBlock:
684 snprintf(name, BLOCK_NAME_LEN, "exit");
685 break;
686 case kDalvikByteCode:
687 snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
688 break;
689 case kExceptionHandling:
690 snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
691 break;
692 default:
693 snprintf(name, BLOCK_NAME_LEN, "??");
694 break;
695 }
696}
buzbeeed3e9302011-09-23 17:34:19 -0700697
698const char* oatGetShortyFromTargetIdx(CompilationUnit *cUnit, int targetIdx)
699{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800700 const DexFile::MethodId& methodId = cUnit->dex_file->GetMethodId(targetIdx);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800701 return cUnit->dex_file->GetShorty(methodId.proto_idx_);
buzbeeed3e9302011-09-23 17:34:19 -0700702}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800703
704} // namespace art