blob: 0cdcfd3931d1d71dbd402f6571dc6ae37083177c [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
buzbee67bf8852011-08-17 17:51:35 -070022static ArenaMemBlock *arenaHead, *currentArena;
23static int numArenaBlocks;
24
buzbee5abfa3e2012-01-31 17:01:43 -080025#ifdef WITH_MEMSTATS
26static u4 allocStats[kNumAllocKinds];
27static int listSizes[kNumListKinds];
28static int listWasted[kNumListKinds];
29static int listGrows[kNumListKinds];
30static int listMaxElems[kNumListKinds];
31static int bitMapSizes[kNumBitMapKinds];
32static int bitMapWasted[kNumBitMapKinds];
33static int bitMapGrows[kNumBitMapKinds];
34
35const char* allocNames[kNumAllocKinds] = {
36 "Misc ",
37 "BasicBlock ",
38 "LIR ",
39 "MIR ",
40 "DataFlow ",
41 "GrowList ",
42 "GrowBitMap ",
43 "Dalvik2SSA ",
44 "DebugInfo ",
45 "Successor ",
46 "RegAlloc ",
47 "Data ",
48 "Preds ",
49};
50
51const char* listNames[kNumListKinds] = {
52 "Misc ",
53 "blockList ",
54 "SSAtoDalvik ",
55 "dfsOrder ",
56 "dfsPostOrder ",
57 "domPostOrderTraversal ",
58 "throwLaunchPads ",
59 "suspendLaunchPads ",
60 "switchTables ",
61 "fillArrayData ",
62 "SuccessorBlocks ",
63 "Predecessors ",
64};
65
66const char* bitMapNames[kNumBitMapKinds] = {
67 "Misc ",
68 "Use ",
69 "Def ",
70 "LiveIn ",
71 "BlockMatrix ",
72 "Dominators ",
73 "IDominated ",
74 "DomFrontier ",
75 "Phi ",
76 "TmpBlocks ",
77 "InputBlocks ",
78 "RegisterV ",
79 "TempSSARegisterV ",
80 "Null Check ",
81 "TmpBlockV ",
82 "Predecessors ",
83};
84#endif
85
buzbee67bf8852011-08-17 17:51:35 -070086#define kArenaBitVectorGrowth 4 /* increase by 4 u4s when limit hit */
87
88/* Allocate the initial memory block for arena-based allocation */
89bool oatHeapInit(void)
90{
buzbeeed3e9302011-09-23 17:34:19 -070091 DCHECK(arenaHead == NULL);
buzbee67bf8852011-08-17 17:51:35 -070092 arenaHead =
93 (ArenaMemBlock *) malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
94 if (arenaHead == NULL) {
95 LOG(FATAL) << "No memory left to create compiler heap memory";
96 }
97 arenaHead->blockSize = ARENA_DEFAULT_SIZE;
98 currentArena = arenaHead;
99 currentArena->bytesAllocated = 0;
100 currentArena->next = NULL;
101 numArenaBlocks = 1;
buzbee67bf8852011-08-17 17:51:35 -0700102 return true;
103}
104
105/* Arena-based malloc for compilation tasks */
buzbee5abfa3e2012-01-31 17:01:43 -0800106void* oatNew(size_t size, bool zero, oatAllocKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700107{
108 size = (size + 3) & ~3;
buzbee5abfa3e2012-01-31 17:01:43 -0800109#ifdef WITH_MEMSTATS
110 allocStats[kind] += size;
111#endif
buzbee67bf8852011-08-17 17:51:35 -0700112retry:
113 /* Normal case - space is available in the current page */
114 if (size + currentArena->bytesAllocated <= currentArena->blockSize) {
115 void *ptr;
116 ptr = &currentArena->ptr[currentArena->bytesAllocated];
117 currentArena->bytesAllocated += size;
118 if (zero) {
119 memset(ptr, 0, size);
120 }
121 return ptr;
122 } else {
123 /*
124 * See if there are previously allocated arena blocks before the last
125 * reset
126 */
127 if (currentArena->next) {
128 currentArena = currentArena->next;
buzbee67bc2362011-10-11 18:08:40 -0700129 currentArena->bytesAllocated = 0;
buzbee67bf8852011-08-17 17:51:35 -0700130 goto retry;
131 }
132
133 size_t blockSize = (size < ARENA_DEFAULT_SIZE) ?
134 ARENA_DEFAULT_SIZE : size;
135 /* Time to allocate a new arena */
136 ArenaMemBlock *newArena = (ArenaMemBlock *)
137 malloc(sizeof(ArenaMemBlock) + blockSize);
138 if (newArena == NULL) {
139 LOG(FATAL) << "Arena allocation failure";
140 }
141 newArena->blockSize = blockSize;
142 newArena->bytesAllocated = 0;
143 newArena->next = NULL;
144 currentArena->next = newArena;
145 currentArena = newArena;
146 numArenaBlocks++;
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700147 if (numArenaBlocks > 20000) {
buzbee67bf8852011-08-17 17:51:35 -0700148 LOG(INFO) << "Total arena pages: " << numArenaBlocks;
149 }
150 goto retry;
151 }
152}
153
154/* Reclaim all the arena blocks allocated so far */
155void oatArenaReset(void)
156{
buzbee5abfa3e2012-01-31 17:01:43 -0800157#ifdef WITH_MEMSTATS
158 memset(&allocStats[0], 0, sizeof(allocStats));
159 memset(&listSizes[0], 0, sizeof(listSizes));
160 memset(&listWasted[0], 0, sizeof(listWasted));
161 memset(&listGrows[0], 0, sizeof(listGrows));
162 memset(&listMaxElems[0], 0, sizeof(listMaxElems));
163 memset(&bitMapSizes[0], 0, sizeof(bitMapSizes));
164 memset(&bitMapWasted[0], 0, sizeof(bitMapWasted));
165 memset(&bitMapGrows[0], 0, sizeof(bitMapGrows));
166#endif
buzbee67bf8852011-08-17 17:51:35 -0700167 currentArena = arenaHead;
buzbee67bc2362011-10-11 18:08:40 -0700168 if (currentArena) {
169 currentArena->bytesAllocated = 0;
170 }
buzbee67bf8852011-08-17 17:51:35 -0700171}
172
173/* Growable List initialization */
buzbee5abfa3e2012-01-31 17:01:43 -0800174void oatInitGrowableList(GrowableList* gList, size_t initLength,
175 oatListKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700176{
177 gList->numAllocated = initLength;
178 gList->numUsed = 0;
179 gList->elemList = (intptr_t *) oatNew(sizeof(intptr_t) * initLength,
buzbee5abfa3e2012-01-31 17:01:43 -0800180 true, kAllocGrowableList);
181#ifdef WITH_MEMSTATS
182 listSizes[kind] += sizeof(intptr_t) * initLength;
183 gList->kind = kind;
184 if ((int)initLength > listMaxElems[kind]) {
185 listMaxElems[kind] = initLength;
186 }
187#endif
buzbee67bf8852011-08-17 17:51:35 -0700188}
189
190/* Expand the capacity of a growable list */
buzbeeed3e9302011-09-23 17:34:19 -0700191STATIC void expandGrowableList(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 =
buzbee5abfa3e2012-01-31 17:01:43 -0800200 (intptr_t *) oatNew(sizeof(intptr_t) * newLength, true,
201 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
204 listSizes[gList->kind] += sizeof(intptr_t) * newLength;
205 listWasted[gList->kind] += sizeof(intptr_t) * gList->numAllocated;
206 listGrows[gList->kind]++;
207 if (newLength > listMaxElems[gList->kind]) {
208 listMaxElems[gList->kind] = newLength;
209 }
210#endif
buzbee67bf8852011-08-17 17:51:35 -0700211 gList->numAllocated = newLength;
212 gList->elemList = newArray;
213}
214
215/* Insert a new element into the growable list */
216void oatInsertGrowableList(GrowableList* gList, intptr_t elem)
217{
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700218 DCHECK_NE(gList->numAllocated, 0U);
buzbee67bf8852011-08-17 17:51:35 -0700219 if (gList->numUsed == gList->numAllocated) {
220 expandGrowableList(gList);
221 }
222 gList->elemList[gList->numUsed++] = elem;
223}
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{
228 bool found = false;
229 for (unsigned int i = 0; i < gList->numUsed; i++) {
230 if (!found && gList->elemList[i] == elem) {
231 found = true;
232 }
233 if (found) {
234 gList->elemList[i] = gList->elemList[i+1];
235 }
236 }
237 DCHECK_EQ(found, true);
238 gList->numUsed--;
239}
240
buzbee67bf8852011-08-17 17:51:35 -0700241void oatGrowableListIteratorInit(GrowableList* gList,
242 GrowableListIterator* iterator)
243{
244 iterator->list = gList;
245 iterator->idx = 0;
246 iterator->size = gList->numUsed;
247}
248
249intptr_t oatGrowableListIteratorNext(GrowableListIterator* iterator)
250{
buzbeeed3e9302011-09-23 17:34:19 -0700251 DCHECK_EQ(iterator->size, iterator->list->numUsed);
buzbee67bf8852011-08-17 17:51:35 -0700252 if (iterator->idx == iterator->size) return 0;
253 return iterator->list->elemList[iterator->idx++];
254}
255
256intptr_t oatGrowableListGetElement(const GrowableList* gList, size_t idx)
257{
buzbeeed3e9302011-09-23 17:34:19 -0700258 DCHECK_LT(idx, gList->numUsed);
buzbee67bf8852011-08-17 17:51:35 -0700259 return gList->elemList[idx];
260}
261
buzbee5abfa3e2012-01-31 17:01:43 -0800262#ifdef WITH_MEMSTATS
263/* Dump memory usage stats */
264void oatDumpMemStats(CompilationUnit* cUnit)
265{
266 u4 total = 0;
267 for (int i = 0; i < kNumAllocKinds; i++) {
268 total += 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 ** ";
276 }
277 LOG(INFO) << "===== Overall allocations";
278 for (int i = 0; i < kNumAllocKinds; i++) {
279 LOG(INFO) << allocNames[i] << std::setw(10) <<allocStats[i];
280 }
281 LOG(INFO) << "===== GrowableList allocations";
282 for (int i = 0; i < kNumListKinds; i++) {
283 LOG(INFO) << listNames[i]
284 << " S:" << listSizes[i]
285 << ", W:" << listWasted[i]
286 << ", G:" << listGrows[i]
287 << ", E:" << listMaxElems[i];
288 }
289 LOG(INFO) << "===== GrowableBitMap allocations";
290 for (int i = 0; i < kNumBitMapKinds; i++) {
291 LOG(INFO) << bitMapNames[i]
292 << " S:" << bitMapSizes[i]
293 << ", W:" << bitMapWasted[i]
294 << ", G:" << bitMapGrows[i];
295 }
296 }
297}
298#endif
299
buzbee67bf8852011-08-17 17:51:35 -0700300/* Debug Utility - dump a compilation unit */
301void oatDumpCompilationUnit(CompilationUnit* cUnit)
302{
303 BasicBlock* bb;
304 const char* blockTypeNames[] = {
305 "Entry Block",
306 "Code Block",
307 "Exit Block",
308 "Exception Handling",
309 "Catch Block"
310 };
311
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800312 LOG(INFO) << "Compiling " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
buzbee67bf8852011-08-17 17:51:35 -0700313 LOG(INFO) << cUnit->insns << " insns";
314 LOG(INFO) << cUnit->numBlocks << " blocks in total";
315 GrowableListIterator iterator;
316
317 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
318
319 while (true) {
320 bb = (BasicBlock *) oatGrowableListIteratorNext(&iterator);
321 if (bb == NULL) break;
322 char buf[100];
323 snprintf(buf, 100, "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 LOG(INFO) << buf;
330 if (bb->taken) {
331 LOG(INFO) << " Taken branch: block " << bb->taken->id <<
332 "(0x" << std::hex << bb->taken->startOffset << ")";
333 }
334 if (bb->fallThrough) {
335 LOG(INFO) << " Fallthrough : block " << bb->fallThrough->id <<
336 " (0x" << std::hex << bb->fallThrough->startOffset << ")";
337 }
338 }
339}
340
341/*
342 * Dump the current stats of the compiler.
343 */
344void oatDumpStats(void)
345{
346 oatArchDump();
347}
348
buzbee67bc2362011-10-11 18:08:40 -0700349static uint32_t checkMasks[32] = {
350 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
351 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200,
352 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000,
353 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000,
354 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000,
355 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
356 0x40000000, 0x80000000 };
357
buzbee67bf8852011-08-17 17:51:35 -0700358/*
359 * Allocate a bit vector with enough space to hold at least the specified
360 * number of bits.
361 *
362 * NOTE: memory is allocated from the compiler arena.
363 */
buzbee5abfa3e2012-01-31 17:01:43 -0800364ArenaBitVector* oatAllocBitVector(unsigned int startBits, bool expandable,
365 oatBitMapKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700366{
367 ArenaBitVector* bv;
368 unsigned int count;
369
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700370 DCHECK_EQ(sizeof(bv->storage[0]), 4U); /* assuming 32-bit units */
buzbee67bf8852011-08-17 17:51:35 -0700371
buzbee5abfa3e2012-01-31 17:01:43 -0800372 bv = (ArenaBitVector*) oatNew(sizeof(ArenaBitVector), false,
373 kAllocGrowableBitMap);
buzbee67bf8852011-08-17 17:51:35 -0700374
375 count = (startBits + 31) >> 5;
376
377 bv->storageSize = count;
378 bv->expandable = expandable;
buzbee5abfa3e2012-01-31 17:01:43 -0800379 bv->storage = (u4*) oatNew(count * sizeof(u4), true, kAllocGrowableBitMap);
380#ifdef WITH_MEMSTATS
381 bv->kind = kind;
382 bitMapSizes[kind] += count * sizeof(u4);
383#endif
buzbee67bf8852011-08-17 17:51:35 -0700384 return bv;
385}
386
387/*
388 * Determine whether or not the specified bit is set.
389 */
390bool oatIsBitSet(const ArenaBitVector* pBits, unsigned int num)
391{
buzbeeed3e9302011-09-23 17:34:19 -0700392 DCHECK_LT(num, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700393
buzbee67bc2362011-10-11 18:08:40 -0700394 unsigned int val = pBits->storage[num >> 5] & checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700395 return (val != 0);
396}
397
398/*
399 * Mark all bits bit as "clear".
400 */
401void oatClearAllBits(ArenaBitVector* pBits)
402{
403 unsigned int count = pBits->storageSize;
404 memset(pBits->storage, 0, count * sizeof(u4));
405}
406
407/*
408 * Mark the specified bit as "set".
409 *
410 * Returns "false" if the bit is outside the range of the vector and we're
411 * not allowed to expand.
412 *
413 * NOTE: memory is allocated from the compiler arena.
414 */
415bool oatSetBit(ArenaBitVector* pBits, unsigned int num)
416{
417 if (num >= pBits->storageSize * sizeof(u4) * 8) {
418 if (!pBits->expandable) {
419 LOG(FATAL) << "Can't expand";
420 }
421
422 /* Round up to word boundaries for "num+1" bits */
423 unsigned int newSize = (num + 1 + 31) >> 5;
buzbeeed3e9302011-09-23 17:34:19 -0700424 DCHECK_GT(newSize, pBits->storageSize);
buzbee5abfa3e2012-01-31 17:01:43 -0800425 u4 *newStorage = (u4*)oatNew(newSize * sizeof(u4), false,
426 kAllocGrowableBitMap);
buzbee67bf8852011-08-17 17:51:35 -0700427 memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
428 memset(&newStorage[pBits->storageSize], 0,
429 (newSize - pBits->storageSize) * sizeof(u4));
buzbee5abfa3e2012-01-31 17:01:43 -0800430#ifdef WITH_MEMSTATS
431 bitMapWasted[pBits->kind] += pBits->storageSize * sizeof(u4);
432 bitMapSizes[pBits->kind] += newSize * sizeof(u4);
433 bitMapGrows[pBits->kind]++;
434#endif
buzbee67bf8852011-08-17 17:51:35 -0700435 pBits->storage = newStorage;
436 pBits->storageSize = newSize;
437 }
438
buzbee67bc2362011-10-11 18:08:40 -0700439 pBits->storage[num >> 5] |= checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700440 return true;
441}
442
443/*
444 * Mark the specified bit as "unset".
445 *
446 * Returns "false" if the bit is outside the range of the vector and we're
447 * not allowed to expand.
448 *
449 * NOTE: memory is allocated from the compiler arena.
450 */
451bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
452{
453 if (num >= pBits->storageSize * sizeof(u4) * 8) {
454 LOG(FATAL) << "Attempt to clear a bit not set in the vector yet";;
455 }
456
buzbee67bc2362011-10-11 18:08:40 -0700457 pBits->storage[num >> 5] &= ~checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700458 return true;
459}
460
461/*
462 * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
463 */
464void oatMarkAllBits(ArenaBitVector* pBits, bool set)
465{
466 int value = set ? -1 : 0;
467 memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
468}
469
470void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
471{
472 int i;
473
474 LOG(INFO) << msg;
475 for (i = 0; i < length; i++) {
476 if (oatIsBitSet(bv, i)) {
477 LOG(INFO) << " Bit " << i << " is set";
478 }
479 }
480}
481
482void oatAbort(CompilationUnit* cUnit)
483{
484 LOG(FATAL) << "Compiler aborting";
485}
486
487void oatDumpBlockBitVector(const GrowableList* blocks, char* msg,
488 const ArenaBitVector* bv, int length)
489{
490 int i;
491
492 LOG(INFO) << msg;
493 for (i = 0; i < length; i++) {
494 if (oatIsBitSet(bv, i)) {
495 BasicBlock *bb =
496 (BasicBlock *) oatGrowableListGetElement(blocks, i);
497 char blockName[BLOCK_NAME_LEN];
498 oatGetBlockName(bb, blockName);
499 LOG(INFO) << "Bit " << i << " / " << blockName << " is set";
500 }
501 }
502}
503/* Initialize the iterator structure */
504void oatBitVectorIteratorInit(ArenaBitVector* pBits,
505 ArenaBitVectorIterator* iterator)
506{
507 iterator->pBits = pBits;
508 iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
509 iterator->idx = 0;
510}
511
512/*
513 * If the vector sizes don't match, log an error and abort.
514 */
buzbeeed3e9302011-09-23 17:34:19 -0700515STATIC void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
buzbee67bf8852011-08-17 17:51:35 -0700516{
517 if (bv1->storageSize != bv2->storageSize) {
518 LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize <<
519 ", " << bv2->storageSize << ")";
520 }
521}
522
523/*
524 * Copy a whole vector to the other. Only do that when the both vectors have
525 * the same size.
526 */
527void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
528{
529 /* if dest is expandable and < src, we could expand dest to match */
530 checkSizes(dest, src);
531
532 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
533}
534
535/*
536 * Intersect two bit vectors and store the result to the dest vector.
537 */
538
539bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
540 const ArenaBitVector* src2)
541{
buzbeeaad72012011-09-21 21:52:09 -0700542 DCHECK(src1 != NULL);
543 DCHECK(src2 != NULL);
544 if (dest->storageSize != src1->storageSize ||
buzbee67bf8852011-08-17 17:51:35 -0700545 dest->storageSize != src2->storageSize ||
546 dest->expandable != src1->expandable ||
547 dest->expandable != src2->expandable)
548 return false;
549
550 unsigned int idx;
551 for (idx = 0; idx < dest->storageSize; idx++) {
552 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
553 }
554 return true;
555}
556
557/*
558 * Unify two bit vectors and store the result to the dest vector.
559 */
560bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
561 const ArenaBitVector* src2)
562{
buzbeeaad72012011-09-21 21:52:09 -0700563 DCHECK(src1 != NULL);
564 DCHECK(src2 != NULL);
565 if (dest->storageSize != src1->storageSize ||
buzbee67bf8852011-08-17 17:51:35 -0700566 dest->storageSize != src2->storageSize ||
567 dest->expandable != src1->expandable ||
568 dest->expandable != src2->expandable)
569 return false;
570
571 unsigned int idx;
572 for (idx = 0; idx < dest->storageSize; idx++) {
573 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
574 }
575 return true;
576}
577
578/*
579 * Compare two bit vectors and return true if difference is seen.
580 */
581bool oatCompareBitVectors(const ArenaBitVector* src1,
582 const ArenaBitVector* src2)
583{
584 if (src1->storageSize != src2->storageSize ||
585 src1->expandable != src2->expandable)
586 return true;
587
588 unsigned int idx;
589 for (idx = 0; idx < src1->storageSize; idx++) {
590 if (src1->storage[idx] != src2->storage[idx]) return true;
591 }
592 return false;
593}
594
595/*
596 * Count the number of bits that are set.
597 */
598int oatCountSetBits(const ArenaBitVector* pBits)
599{
600 unsigned int word;
601 unsigned int count = 0;
602
603 for (word = 0; word < pBits->storageSize; word++) {
604 u4 val = pBits->storage[word];
605
606 if (val != 0) {
607 if (val == 0xffffffff) {
608 count += 32;
609 } else {
610 /* count the number of '1' bits */
611 while (val != 0) {
612 val &= val - 1;
613 count++;
614 }
615 }
616 }
617 }
618
619 return count;
620}
621
622/* Return the next position set to 1. -1 means end-of-element reached */
623int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
624{
buzbee5b537102012-01-17 17:33:47 -0800625 ArenaBitVector* pBits = iterator->pBits;
buzbee67bf8852011-08-17 17:51:35 -0700626 u4 bitIndex = iterator->idx;
buzbee5abfa3e2012-01-31 17:01:43 -0800627 u4 bitSize = iterator->bitSize;
buzbee67bf8852011-08-17 17:51:35 -0700628
buzbee5abfa3e2012-01-31 17:01:43 -0800629 DCHECK_EQ(bitSize, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700630
buzbee5abfa3e2012-01-31 17:01:43 -0800631 if (bitIndex >= bitSize) return -1;
buzbee5b537102012-01-17 17:33:47 -0800632
buzbee5abfa3e2012-01-31 17:01:43 -0800633 u4 wordIndex = bitIndex >> 5;
634 u4 endWordIndex = bitSize >> 5;
635 u4* storage = pBits->storage;
636 u4 word = storage[wordIndex++];
buzbee5b537102012-01-17 17:33:47 -0800637
buzbee5abfa3e2012-01-31 17:01:43 -0800638 // Mask out any bits in the first word we've already considered
639 word &= ~((1 << (bitIndex & 0x1f))-1);
640
641 for (; wordIndex <= endWordIndex;) {
642 u4 bitPos = bitIndex & 0x1f;
buzbee67bc2362011-10-11 18:08:40 -0700643 if (word == 0) {
buzbee67bc2362011-10-11 18:08:40 -0700644 bitIndex += (32 - bitPos);
buzbee5abfa3e2012-01-31 17:01:43 -0800645 word = storage[wordIndex++];
646 continue;
647 }
648 for (; bitPos < 32; bitPos++) {
649 if (word & (1 << bitPos)) {
650 iterator->idx = bitIndex + 1;
651 return bitIndex;
652 }
buzbee67bc2362011-10-11 18:08:40 -0700653 bitIndex++;
654 }
buzbee5abfa3e2012-01-31 17:01:43 -0800655 word = storage[wordIndex++];
buzbee67bf8852011-08-17 17:51:35 -0700656 }
buzbee5abfa3e2012-01-31 17:01:43 -0800657 iterator->idx = iterator->bitSize;
buzbee67bf8852011-08-17 17:51:35 -0700658 return -1;
659}
660
661/*
662 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
663 * since there might be unused bits - setting those to one will confuse the
664 * iterator.
665 */
666void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
667{
668 unsigned int idx;
buzbeeed3e9302011-09-23 17:34:19 -0700669 DCHECK_LE(((numBits + 31) >> 5), pBits->storageSize);
buzbee67bf8852011-08-17 17:51:35 -0700670 for (idx = 0; idx < (numBits >> 5); idx++) {
671 pBits->storage[idx] = -1;
672 }
673 unsigned int remNumBits = numBits & 0x1f;
674 if (remNumBits) {
675 pBits->storage[idx] = (1 << remNumBits) - 1;
676 }
677}
678
679void oatGetBlockName(BasicBlock* bb, char* name)
680{
681 switch (bb->blockType) {
682 case kEntryBlock:
683 snprintf(name, BLOCK_NAME_LEN, "entry");
684 break;
685 case kExitBlock:
686 snprintf(name, BLOCK_NAME_LEN, "exit");
687 break;
688 case kDalvikByteCode:
689 snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
690 break;
691 case kExceptionHandling:
692 snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
693 break;
694 default:
695 snprintf(name, BLOCK_NAME_LEN, "??");
696 break;
697 }
698}
buzbeeed3e9302011-09-23 17:34:19 -0700699
700const char* oatGetShortyFromTargetIdx(CompilationUnit *cUnit, int targetIdx)
701{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800702 const DexFile::MethodId& methodId = cUnit->dex_file->GetMethodId(targetIdx);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800703 return cUnit->dex_file->GetShorty(methodId.proto_idx_);
buzbeeed3e9302011-09-23 17:34:19 -0700704}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800705
706} // namespace art