blob: c8657185361ddb5113d31e59d71ba6eabaf16fb2 [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
Elliott Hughes719ace42012-03-09 18:06:03 -080023struct Memstats {
Bill Buzbeea114add2012-05-03 15:00:40 -070024 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];
Elliott Hughes719ace42012-03-09 18:06:03 -080032};
buzbee5abfa3e2012-01-31 17:01:43 -080033
34const char* allocNames[kNumAllocKinds] = {
Bill Buzbeea114add2012-05-03 15:00:40 -070035 "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 ",
buzbee5abfa3e2012-01-31 17:01:43 -080048};
49
50const char* listNames[kNumListKinds] = {
Bill Buzbeea114add2012-05-03 15:00:40 -070051 "Misc ",
52 "blockList ",
53 "SSAtoDalvik ",
54 "dfsOrder ",
55 "dfsPostOrder ",
56 "domPostOrderTraversal ",
57 "throwLaunchPads ",
58 "suspendLaunchPads ",
59 "switchTables ",
60 "fillArrayData ",
61 "SuccessorBlocks ",
62 "Predecessors ",
buzbee5abfa3e2012-01-31 17:01:43 -080063};
64
65const char* bitMapNames[kNumBitMapKinds] = {
Bill Buzbeea114add2012-05-03 15:00:40 -070066 "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 ",
buzbee5abfa3e2012-01-31 17:01:43 -080082};
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{
Bill Buzbeea114add2012-05-03 15:00:40 -070090 DCHECK(cUnit->arenaHead == NULL);
91 cUnit->arenaHead =
92 (ArenaMemBlock *) malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
93 if (cUnit->arenaHead == NULL) {
94 LOG(FATAL) << "No memory left to create compiler heap memory";
95 }
96 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;
buzbeeba938cb2012-02-03 14:47:55 -0800101#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 cUnit->mstats = (Memstats*) oatNew(cUnit, sizeof(Memstats), true,
103 kAllocDebugInfo);
buzbeeba938cb2012-02-03 14:47:55 -0800104#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 return true;
buzbee67bf8852011-08-17 17:51:35 -0700106}
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{
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 size = (size + 3) & ~3;
buzbee5abfa3e2012-01-31 17:01:43 -0800112#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 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:
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 /* Normal case - space is available in the current page */
119 if (size + cUnit->currentArena->bytesAllocated <=
120 cUnit->currentArena->blockSize) {
121 void *ptr;
122 ptr = &cUnit->currentArena->ptr[cUnit->currentArena->bytesAllocated];
123 cUnit->currentArena->bytesAllocated += size;
124 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 */
133 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 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700138
139 size_t blockSize = (size < ARENA_DEFAULT_SIZE) ? ARENA_DEFAULT_SIZE : size;
140 /* Time to allocate a new arena */
141 ArenaMemBlock *newArena = (ArenaMemBlock *)
142 malloc(sizeof(ArenaMemBlock) + blockSize);
143 if (newArena == NULL) {
144 LOG(FATAL) << "Arena allocation failure";
145 }
146 newArena->blockSize = blockSize;
147 newArena->bytesAllocated = 0;
148 newArena->next = NULL;
149 cUnit->currentArena->next = newArena;
150 cUnit->currentArena = newArena;
151 cUnit->numArenaBlocks++;
152 if (cUnit->numArenaBlocks > 20000) {
153 LOG(INFO) << "Total arena pages: " << cUnit->numArenaBlocks;
154 }
155 goto retry;
156 }
buzbee67bf8852011-08-17 17:51:35 -0700157}
158
159/* Reclaim all the arena blocks allocated so far */
buzbeeba938cb2012-02-03 14:47:55 -0800160void oatArenaReset(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700161{
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 ArenaMemBlock* head = cUnit->arenaHead;
163 while (head != NULL) {
164 ArenaMemBlock* p = head;
165 head = head->next;
166 free(p);
167 }
168 cUnit->arenaHead = NULL;
169 cUnit->currentArena = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700170}
171
172/* Growable List initialization */
buzbeeba938cb2012-02-03 14:47:55 -0800173void oatInitGrowableList(CompilationUnit* cUnit, GrowableList* gList,
Bill Buzbeea114add2012-05-03 15:00:40 -0700174 size_t initLength, oatListKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700175{
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 gList->numAllocated = initLength;
177 gList->numUsed = 0;
178 gList->elemList = (intptr_t *) oatNew(cUnit, sizeof(intptr_t) * initLength,
179 true, kAllocGrowableList);
buzbee5abfa3e2012-01-31 17:01:43 -0800180#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 cUnit->mstats->listSizes[kind] += sizeof(intptr_t) * initLength;
182 gList->kind = kind;
183 if ((int)initLength > cUnit->mstats->listMaxElems[kind]) {
184 cUnit->mstats->listMaxElems[kind] = initLength;
185 }
buzbee5abfa3e2012-01-31 17:01:43 -0800186#endif
buzbee67bf8852011-08-17 17:51:35 -0700187}
188
189/* Expand the capacity of a growable list */
buzbee31a4a6f2012-02-28 15:36:15 -0800190void expandGrowableList(CompilationUnit* cUnit, GrowableList* gList)
buzbee67bf8852011-08-17 17:51:35 -0700191{
Bill Buzbeea114add2012-05-03 15:00:40 -0700192 int newLength = gList->numAllocated;
193 if (newLength < 128) {
194 newLength <<= 1;
195 } else {
196 newLength += 128;
197 }
198 intptr_t *newArray =
199 (intptr_t *) oatNew(cUnit, sizeof(intptr_t) * newLength, true,
200 kAllocGrowableList);
201 memcpy(newArray, gList->elemList, sizeof(intptr_t) * gList->numAllocated);
buzbee5abfa3e2012-01-31 17:01:43 -0800202#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700203 cUnit->mstats->listSizes[gList->kind] += sizeof(intptr_t) * newLength;
204 cUnit->mstats->listWasted[gList->kind] +=
205 sizeof(intptr_t) * gList->numAllocated;
206 cUnit->mstats->listGrows[gList->kind]++;
207 if (newLength > cUnit->mstats->listMaxElems[gList->kind]) {
208 cUnit->mstats->listMaxElems[gList->kind] = newLength;
209 }
buzbee5abfa3e2012-01-31 17:01:43 -0800210#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700211 gList->numAllocated = newLength;
212 gList->elemList = newArray;
buzbee67bf8852011-08-17 17:51:35 -0700213}
214
215/* Insert a new element into the growable list */
buzbeeba938cb2012-02-03 14:47:55 -0800216void oatInsertGrowableList(CompilationUnit* cUnit, GrowableList* gList,
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 intptr_t elem)
buzbee67bf8852011-08-17 17:51:35 -0700218{
Bill Buzbeea114add2012-05-03 15:00:40 -0700219 DCHECK_NE(gList->numAllocated, 0U);
220 if (gList->numUsed == gList->numAllocated) {
221 expandGrowableList(cUnit, gList);
222 }
223 gList->elemList[gList->numUsed++] = elem;
buzbee67bf8852011-08-17 17:51:35 -0700224}
225
buzbee5abfa3e2012-01-31 17:01:43 -0800226/* Delete an element from a growable list. Element must be present */
227void oatDeleteGrowableList(GrowableList* gList, intptr_t elem)
228{
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 bool found = false;
230 for (unsigned int i = 0; i < gList->numUsed; i++) {
231 if (!found && gList->elemList[i] == elem) {
232 found = true;
buzbee5abfa3e2012-01-31 17:01:43 -0800233 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700234 if (found) {
235 gList->elemList[i] = gList->elemList[i+1];
236 }
237 }
238 DCHECK_EQ(found, true);
239 gList->numUsed--;
buzbee5abfa3e2012-01-31 17:01:43 -0800240}
241
buzbee67bf8852011-08-17 17:51:35 -0700242void oatGrowableListIteratorInit(GrowableList* gList,
Bill Buzbeea114add2012-05-03 15:00:40 -0700243 GrowableListIterator* iterator)
buzbee67bf8852011-08-17 17:51:35 -0700244{
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 iterator->list = gList;
246 iterator->idx = 0;
247 iterator->size = gList->numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700248}
249
250intptr_t oatGrowableListIteratorNext(GrowableListIterator* iterator)
251{
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 DCHECK_EQ(iterator->size, iterator->list->numUsed);
253 if (iterator->idx == iterator->size) return 0;
254 return iterator->list->elemList[iterator->idx++];
buzbee67bf8852011-08-17 17:51:35 -0700255}
256
257intptr_t oatGrowableListGetElement(const GrowableList* gList, size_t idx)
258{
Bill Buzbeea114add2012-05-03 15:00:40 -0700259 DCHECK_LT(idx, gList->numUsed);
260 return gList->elemList[idx];
buzbee67bf8852011-08-17 17:51:35 -0700261}
262
buzbee5abfa3e2012-01-31 17:01:43 -0800263#ifdef WITH_MEMSTATS
264/* Dump memory usage stats */
265void oatDumpMemStats(CompilationUnit* cUnit)
266{
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 u4 total = 0;
268 for (int i = 0; i < kNumAllocKinds; i++) {
269 total += cUnit->mstats->allocStats[i];
270 }
271 if (total > (10 * 1024 * 1024)) {
272 LOG(INFO) << "MEMUSAGE: " << total << " : "
273 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
274 LOG(INFO) << "insnsSize: " << cUnit->insnsSize;
275 if (cUnit->disableDataflow) {
276 LOG(INFO) << " ** Dataflow disabled ** ";
buzbee5abfa3e2012-01-31 17:01:43 -0800277 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 LOG(INFO) << "===== Overall allocations";
279 for (int i = 0; i < kNumAllocKinds; i++) {
280 LOG(INFO) << allocNames[i] << std::setw(10) <<
281 cUnit->mstats->allocStats[i];
282 }
283 LOG(INFO) << "===== GrowableList allocations";
284 for (int i = 0; i < kNumListKinds; i++) {
285 LOG(INFO) << listNames[i]
buzbeeba938cb2012-02-03 14:47:55 -0800286 << " S:" << cUnit->mstats->listSizes[i]
287 << ", W:" << cUnit->mstats->listWasted[i]
288 << ", G:" << cUnit->mstats->listGrows[i]
289 << ", E:" << cUnit->mstats->listMaxElems[i];
Bill Buzbeea114add2012-05-03 15:00:40 -0700290 }
291 LOG(INFO) << "===== GrowableBitMap allocations";
292 for (int i = 0; i < kNumBitMapKinds; i++) {
293 LOG(INFO) << bitMapNames[i]
buzbeeba938cb2012-02-03 14:47:55 -0800294 << " S:" << cUnit->mstats->bitMapSizes[i]
295 << ", W:" << cUnit->mstats->bitMapWasted[i]
296 << ", G:" << cUnit->mstats->bitMapGrows[i];
buzbee5abfa3e2012-01-31 17:01:43 -0800297 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700298 }
buzbee5abfa3e2012-01-31 17:01:43 -0800299}
300#endif
301
buzbee67bf8852011-08-17 17:51:35 -0700302/* Debug Utility - dump a compilation unit */
303void oatDumpCompilationUnit(CompilationUnit* cUnit)
304{
Bill Buzbeea114add2012-05-03 15:00:40 -0700305 BasicBlock* bb;
306 const char* blockTypeNames[] = {
307 "Entry Block",
308 "Code Block",
309 "Exit Block",
310 "Exception Handling",
311 "Catch Block"
312 };
buzbee67bf8852011-08-17 17:51:35 -0700313
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 LOG(INFO) << "Compiling " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
315 LOG(INFO) << cUnit->insns << " insns";
316 LOG(INFO) << cUnit->numBlocks << " blocks in total";
317 GrowableListIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700318
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
buzbee67bf8852011-08-17 17:51:35 -0700320
Bill Buzbeea114add2012-05-03 15:00:40 -0700321 while (true) {
322 bb = (BasicBlock *) oatGrowableListIteratorNext(&iterator);
323 if (bb == NULL) break;
324 LOG(INFO) << StringPrintf("Block %d (%s) (insn %04x - %04x%s)",
325 bb->id,
326 blockTypeNames[bb->blockType],
327 bb->startOffset,
328 bb->lastMIRInsn ? bb->lastMIRInsn->offset : bb->startOffset,
329 bb->lastMIRInsn ? "" : " empty");
330 if (bb->taken) {
331 LOG(INFO) << " Taken branch: block " << bb->taken->id
332 << "(0x" << std::hex << bb->taken->startOffset << ")";
buzbee67bf8852011-08-17 17:51:35 -0700333 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 if (bb->fallThrough) {
335 LOG(INFO) << " Fallthrough : block " << bb->fallThrough->id
336 << " (0x" << std::hex << bb->fallThrough->startOffset << ")";
337 }
338 }
buzbee67bf8852011-08-17 17:51:35 -0700339}
340
buzbee67bc2362011-10-11 18:08:40 -0700341static uint32_t checkMasks[32] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
343 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200,
344 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000,
345 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000,
346 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000,
347 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
348 0x40000000, 0x80000000 };
buzbee67bc2362011-10-11 18:08:40 -0700349
buzbee67bf8852011-08-17 17:51:35 -0700350/*
351 * Allocate a bit vector with enough space to hold at least the specified
352 * number of bits.
353 *
354 * NOTE: memory is allocated from the compiler arena.
355 */
buzbeeba938cb2012-02-03 14:47:55 -0800356ArenaBitVector* oatAllocBitVector(CompilationUnit* cUnit,
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 unsigned int startBits, bool expandable,
358 oatBitMapKind kind)
buzbee67bf8852011-08-17 17:51:35 -0700359{
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 ArenaBitVector* bv;
361 unsigned int count;
buzbee67bf8852011-08-17 17:51:35 -0700362
Bill Buzbeea114add2012-05-03 15:00:40 -0700363 DCHECK_EQ(sizeof(bv->storage[0]), 4U); /* assuming 32-bit units */
buzbee67bf8852011-08-17 17:51:35 -0700364
Bill Buzbeea114add2012-05-03 15:00:40 -0700365 bv = (ArenaBitVector*) oatNew(cUnit, sizeof(ArenaBitVector), false,
366 kAllocGrowableBitMap);
buzbee67bf8852011-08-17 17:51:35 -0700367
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 count = (startBits + 31) >> 5;
buzbee67bf8852011-08-17 17:51:35 -0700369
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 bv->storageSize = count;
371 bv->expandable = expandable;
372 bv->storage = (u4*) oatNew(cUnit, count * sizeof(u4), true,
373 kAllocGrowableBitMap);
buzbee5abfa3e2012-01-31 17:01:43 -0800374#ifdef WITH_MEMSTATS
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 bv->kind = kind;
376 cUnit->mstats->bitMapSizes[kind] += count * sizeof(u4);
buzbee5abfa3e2012-01-31 17:01:43 -0800377#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 return bv;
buzbee67bf8852011-08-17 17:51:35 -0700379}
380
381/*
382 * Determine whether or not the specified bit is set.
383 */
384bool oatIsBitSet(const ArenaBitVector* pBits, unsigned int num)
385{
Bill Buzbeea114add2012-05-03 15:00:40 -0700386 DCHECK_LT(num, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700387
Bill Buzbeea114add2012-05-03 15:00:40 -0700388 unsigned int val = pBits->storage[num >> 5] & checkMasks[num & 0x1f];
389 return (val != 0);
buzbee67bf8852011-08-17 17:51:35 -0700390}
391
392/*
393 * Mark all bits bit as "clear".
394 */
395void oatClearAllBits(ArenaBitVector* pBits)
396{
Bill Buzbeea114add2012-05-03 15:00:40 -0700397 unsigned int count = pBits->storageSize;
398 memset(pBits->storage, 0, count * sizeof(u4));
buzbee67bf8852011-08-17 17:51:35 -0700399}
400
401/*
402 * Mark the specified bit as "set".
403 *
404 * Returns "false" if the bit is outside the range of the vector and we're
405 * not allowed to expand.
406 *
407 * NOTE: memory is allocated from the compiler arena.
408 */
buzbeeba938cb2012-02-03 14:47:55 -0800409bool oatSetBit(CompilationUnit* cUnit, ArenaBitVector* pBits, unsigned int num)
buzbee67bf8852011-08-17 17:51:35 -0700410{
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 if (num >= pBits->storageSize * sizeof(u4) * 8) {
412 if (!pBits->expandable) {
413 LOG(FATAL) << "Can't expand";
buzbee67bf8852011-08-17 17:51:35 -0700414 }
415
Bill Buzbeea114add2012-05-03 15:00:40 -0700416 /* Round up to word boundaries for "num+1" bits */
417 unsigned int newSize = (num + 1 + 31) >> 5;
418 DCHECK_GT(newSize, pBits->storageSize);
419 u4 *newStorage = (u4*)oatNew(cUnit, newSize * sizeof(u4), false,
420 kAllocGrowableBitMap);
421 memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
422 memset(&newStorage[pBits->storageSize], 0,
423 (newSize - pBits->storageSize) * sizeof(u4));
424#ifdef WITH_MEMSTATS
425 cUnit->mstats->bitMapWasted[pBits->kind] +=
426 pBits->storageSize * sizeof(u4);
427 cUnit->mstats->bitMapSizes[pBits->kind] += newSize * sizeof(u4);
428 cUnit->mstats->bitMapGrows[pBits->kind]++;
429#endif
430 pBits->storage = newStorage;
431 pBits->storageSize = newSize;
432 }
433
434 pBits->storage[num >> 5] |= checkMasks[num & 0x1f];
435 return true;
buzbee67bf8852011-08-17 17:51:35 -0700436}
437
438/*
439 * Mark the specified bit as "unset".
440 *
441 * Returns "false" if the bit is outside the range of the vector and we're
442 * not allowed to expand.
443 *
444 * NOTE: memory is allocated from the compiler arena.
445 */
446bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
447{
Bill Buzbeea114add2012-05-03 15:00:40 -0700448 if (num >= pBits->storageSize * sizeof(u4) * 8) {
449 LOG(FATAL) << "Attempt to clear a bit not set in the vector yet";;
450 }
buzbee67bf8852011-08-17 17:51:35 -0700451
Bill Buzbeea114add2012-05-03 15:00:40 -0700452 pBits->storage[num >> 5] &= ~checkMasks[num & 0x1f];
453 return true;
buzbee67bf8852011-08-17 17:51:35 -0700454}
455
456/*
457 * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
458 */
459void oatMarkAllBits(ArenaBitVector* pBits, bool set)
460{
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 int value = set ? -1 : 0;
462 memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
buzbee67bf8852011-08-17 17:51:35 -0700463}
464
465void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
466{
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 int i;
buzbee67bf8852011-08-17 17:51:35 -0700468
Bill Buzbeea114add2012-05-03 15:00:40 -0700469 LOG(INFO) << msg;
470 for (i = 0; i < length; i++) {
471 if (oatIsBitSet(bv, i)) {
472 LOG(INFO) << " Bit " << i << " is set";
buzbee67bf8852011-08-17 17:51:35 -0700473 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 }
buzbee67bf8852011-08-17 17:51:35 -0700475}
476
477void oatAbort(CompilationUnit* cUnit)
478{
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 LOG(FATAL) << "Compiler aborting";
buzbee67bf8852011-08-17 17:51:35 -0700480}
481
482void oatDumpBlockBitVector(const GrowableList* blocks, char* msg,
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 const ArenaBitVector* bv, int length)
buzbee67bf8852011-08-17 17:51:35 -0700484{
Bill Buzbeea114add2012-05-03 15:00:40 -0700485 int i;
buzbee67bf8852011-08-17 17:51:35 -0700486
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 LOG(INFO) << msg;
488 for (i = 0; i < length; i++) {
489 if (oatIsBitSet(bv, i)) {
490 BasicBlock *bb = (BasicBlock *) oatGrowableListGetElement(blocks, i);
491 char blockName[BLOCK_NAME_LEN];
492 oatGetBlockName(bb, blockName);
493 LOG(INFO) << "Bit " << i << " / " << blockName << " is set";
buzbee67bf8852011-08-17 17:51:35 -0700494 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 }
buzbee67bf8852011-08-17 17:51:35 -0700496}
497/* Initialize the iterator structure */
498void oatBitVectorIteratorInit(ArenaBitVector* pBits,
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 ArenaBitVectorIterator* iterator)
buzbee67bf8852011-08-17 17:51:35 -0700500{
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 iterator->pBits = pBits;
502 iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
503 iterator->idx = 0;
buzbee67bf8852011-08-17 17:51:35 -0700504}
505
506/*
507 * If the vector sizes don't match, log an error and abort.
508 */
buzbee31a4a6f2012-02-28 15:36:15 -0800509void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
buzbee67bf8852011-08-17 17:51:35 -0700510{
Bill Buzbeea114add2012-05-03 15:00:40 -0700511 if (bv1->storageSize != bv2->storageSize) {
512 LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize
513 << ", " << bv2->storageSize << ")";
514 }
buzbee67bf8852011-08-17 17:51:35 -0700515}
516
517/*
518 * Copy a whole vector to the other. Only do that when the both vectors have
519 * the same size.
520 */
521void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
522{
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 /* if dest is expandable and < src, we could expand dest to match */
524 checkSizes(dest, src);
buzbee67bf8852011-08-17 17:51:35 -0700525
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
buzbee67bf8852011-08-17 17:51:35 -0700527}
528
529/*
530 * Intersect two bit vectors and store the result to the dest vector.
531 */
532
533bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700535{
Bill Buzbeea114add2012-05-03 15:00:40 -0700536 DCHECK(src1 != NULL);
537 DCHECK(src2 != NULL);
538 if (dest->storageSize != src1->storageSize ||
539 dest->storageSize != src2->storageSize ||
540 dest->expandable != src1->expandable ||
541 dest->expandable != src2->expandable)
542 return false;
buzbee67bf8852011-08-17 17:51:35 -0700543
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 unsigned int idx;
545 for (idx = 0; idx < dest->storageSize; idx++) {
546 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
547 }
548 return true;
buzbee67bf8852011-08-17 17:51:35 -0700549}
550
551/*
552 * Unify two bit vectors and store the result to the dest vector.
553 */
554bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700556{
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 DCHECK(src1 != NULL);
558 DCHECK(src2 != NULL);
559 if (dest->storageSize != src1->storageSize ||
560 dest->storageSize != src2->storageSize ||
561 dest->expandable != src1->expandable ||
562 dest->expandable != src2->expandable)
563 return false;
buzbee67bf8852011-08-17 17:51:35 -0700564
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 unsigned int idx;
566 for (idx = 0; idx < dest->storageSize; idx++) {
567 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
568 }
569 return true;
buzbee67bf8852011-08-17 17:51:35 -0700570}
571
572/*
buzbeee1965672012-03-11 18:39:19 -0700573 * Return true if any bits collide. Vectors must be same size.
574 */
575bool oatTestBitVectors(const ArenaBitVector* src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700576 const ArenaBitVector* src2)
buzbeee1965672012-03-11 18:39:19 -0700577{
Bill Buzbeea114add2012-05-03 15:00:40 -0700578 DCHECK_EQ(src1->storageSize, src2->storageSize);
579 for (uint32_t idx = 0; idx < src1->storageSize; idx++) {
580 if (src1->storage[idx] & src2->storage[idx]) return true;
581 }
582 return false;
buzbeee1965672012-03-11 18:39:19 -0700583}
584
585/*
buzbee67bf8852011-08-17 17:51:35 -0700586 * Compare two bit vectors and return true if difference is seen.
587 */
588bool oatCompareBitVectors(const ArenaBitVector* src1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700589 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700590{
Bill Buzbeea114add2012-05-03 15:00:40 -0700591 if (src1->storageSize != src2->storageSize ||
592 src1->expandable != src2->expandable)
593 return true;
buzbee67bf8852011-08-17 17:51:35 -0700594
Bill Buzbeea114add2012-05-03 15:00:40 -0700595 unsigned int idx;
596 for (idx = 0; idx < src1->storageSize; idx++) {
597 if (src1->storage[idx] != src2->storage[idx]) return true;
598 }
599 return false;
buzbee67bf8852011-08-17 17:51:35 -0700600}
601
602/*
603 * Count the number of bits that are set.
604 */
605int oatCountSetBits(const ArenaBitVector* pBits)
606{
Bill Buzbeea114add2012-05-03 15:00:40 -0700607 unsigned int word;
608 unsigned int count = 0;
buzbee67bf8852011-08-17 17:51:35 -0700609
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 for (word = 0; word < pBits->storageSize; word++) {
611 u4 val = pBits->storage[word];
buzbee67bf8852011-08-17 17:51:35 -0700612
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 if (val != 0) {
614 if (val == 0xffffffff) {
615 count += 32;
616 } else {
617 /* count the number of '1' bits */
618 while (val != 0) {
619 val &= val - 1;
620 count++;
buzbee67bf8852011-08-17 17:51:35 -0700621 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 }
buzbee67bf8852011-08-17 17:51:35 -0700623 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 }
buzbee67bf8852011-08-17 17:51:35 -0700625
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 return count;
buzbee67bf8852011-08-17 17:51:35 -0700627}
628
629/* Return the next position set to 1. -1 means end-of-element reached */
630int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
631{
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 ArenaBitVector* pBits = iterator->pBits;
633 u4 bitIndex = iterator->idx;
634 u4 bitSize = iterator->bitSize;
buzbee67bf8852011-08-17 17:51:35 -0700635
Bill Buzbeea114add2012-05-03 15:00:40 -0700636 DCHECK_EQ(bitSize, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700637
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 if (bitIndex >= bitSize) return -1;
buzbee5b537102012-01-17 17:33:47 -0800639
Bill Buzbeea114add2012-05-03 15:00:40 -0700640 u4 wordIndex = bitIndex >> 5;
641 u4 endWordIndex = bitSize >> 5;
642 u4* storage = pBits->storage;
643 u4 word = storage[wordIndex++];
buzbee5b537102012-01-17 17:33:47 -0800644
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 // Mask out any bits in the first word we've already considered
646 word &= ~((1 << (bitIndex & 0x1f))-1);
buzbee5abfa3e2012-01-31 17:01:43 -0800647
Bill Buzbeea114add2012-05-03 15:00:40 -0700648 for (; wordIndex <= endWordIndex;) {
649 u4 bitPos = bitIndex & 0x1f;
650 if (word == 0) {
651 bitIndex += (32 - bitPos);
652 word = storage[wordIndex++];
653 continue;
buzbee67bf8852011-08-17 17:51:35 -0700654 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 for (; bitPos < 32; bitPos++) {
656 if (word & (1 << bitPos)) {
657 iterator->idx = bitIndex + 1;
658 return bitIndex;
659 }
660 bitIndex++;
661 }
662 word = storage[wordIndex++];
663 }
664 iterator->idx = iterator->bitSize;
665 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700666}
667
668/*
669 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
670 * since there might be unused bits - setting those to one will confuse the
671 * iterator.
672 */
673void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
674{
Bill Buzbeea114add2012-05-03 15:00:40 -0700675 unsigned int idx;
676 DCHECK_LE(((numBits + 31) >> 5), pBits->storageSize);
677 for (idx = 0; idx < (numBits >> 5); idx++) {
678 pBits->storage[idx] = -1;
679 }
680 unsigned int remNumBits = numBits & 0x1f;
681 if (remNumBits) {
682 pBits->storage[idx] = (1 << remNumBits) - 1;
683 }
buzbee67bf8852011-08-17 17:51:35 -0700684}
685
686void oatGetBlockName(BasicBlock* bb, char* name)
687{
Bill Buzbeea114add2012-05-03 15:00:40 -0700688 switch (bb->blockType) {
689 case kEntryBlock:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700690 snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700691 break;
692 case kExitBlock:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700693 snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700694 break;
695 case kDalvikByteCode:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700696 snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->startOffset, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700697 break;
698 case kExceptionHandling:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700699 snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->startOffset,
700 bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700701 break;
702 default:
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700703 snprintf(name, BLOCK_NAME_LEN, "??_%d", bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700704 break;
705 }
buzbee67bf8852011-08-17 17:51:35 -0700706}
buzbeeed3e9302011-09-23 17:34:19 -0700707
708const char* oatGetShortyFromTargetIdx(CompilationUnit *cUnit, int targetIdx)
709{
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 const DexFile::MethodId& methodId = cUnit->dex_file->GetMethodId(targetIdx);
711 return cUnit->dex_file->GetShorty(methodId.proto_idx_);
buzbeeed3e9302011-09-23 17:34:19 -0700712}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800713
714} // namespace art