blob: 8d70136e02b565c6a89eb1c9c3ae6d30e2a22788 [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
25#define kArenaBitVectorGrowth 4 /* increase by 4 u4s when limit hit */
26
27/* Allocate the initial memory block for arena-based allocation */
28bool oatHeapInit(void)
29{
buzbeeed3e9302011-09-23 17:34:19 -070030 DCHECK(arenaHead == NULL);
buzbee67bf8852011-08-17 17:51:35 -070031 arenaHead =
32 (ArenaMemBlock *) malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
33 if (arenaHead == NULL) {
34 LOG(FATAL) << "No memory left to create compiler heap memory";
35 }
36 arenaHead->blockSize = ARENA_DEFAULT_SIZE;
37 currentArena = arenaHead;
38 currentArena->bytesAllocated = 0;
39 currentArena->next = NULL;
40 numArenaBlocks = 1;
41
42 return true;
43}
44
45/* Arena-based malloc for compilation tasks */
46void* oatNew(size_t size, bool zero)
47{
48 size = (size + 3) & ~3;
49retry:
50 /* Normal case - space is available in the current page */
51 if (size + currentArena->bytesAllocated <= currentArena->blockSize) {
52 void *ptr;
53 ptr = &currentArena->ptr[currentArena->bytesAllocated];
54 currentArena->bytesAllocated += size;
55 if (zero) {
56 memset(ptr, 0, size);
57 }
58 return ptr;
59 } else {
60 /*
61 * See if there are previously allocated arena blocks before the last
62 * reset
63 */
64 if (currentArena->next) {
65 currentArena = currentArena->next;
buzbee67bc2362011-10-11 18:08:40 -070066 currentArena->bytesAllocated = 0;
buzbee67bf8852011-08-17 17:51:35 -070067 goto retry;
68 }
69
70 size_t blockSize = (size < ARENA_DEFAULT_SIZE) ?
71 ARENA_DEFAULT_SIZE : size;
72 /* Time to allocate a new arena */
73 ArenaMemBlock *newArena = (ArenaMemBlock *)
74 malloc(sizeof(ArenaMemBlock) + blockSize);
75 if (newArena == NULL) {
76 LOG(FATAL) << "Arena allocation failure";
77 }
78 newArena->blockSize = blockSize;
79 newArena->bytesAllocated = 0;
80 newArena->next = NULL;
81 currentArena->next = newArena;
82 currentArena = newArena;
83 numArenaBlocks++;
Brian Carlstrom27ec9612011-09-19 20:20:38 -070084 if (numArenaBlocks > 20000) {
buzbee67bf8852011-08-17 17:51:35 -070085 LOG(INFO) << "Total arena pages: " << numArenaBlocks;
86 }
87 goto retry;
88 }
89}
90
91/* Reclaim all the arena blocks allocated so far */
92void oatArenaReset(void)
93{
buzbee67bf8852011-08-17 17:51:35 -070094 currentArena = arenaHead;
buzbee67bc2362011-10-11 18:08:40 -070095 if (currentArena) {
96 currentArena->bytesAllocated = 0;
97 }
buzbee67bf8852011-08-17 17:51:35 -070098}
99
100/* Growable List initialization */
101void oatInitGrowableList(GrowableList* gList, size_t initLength)
102{
103 gList->numAllocated = initLength;
104 gList->numUsed = 0;
105 gList->elemList = (intptr_t *) oatNew(sizeof(intptr_t) * initLength,
106 true);
107}
108
109/* Expand the capacity of a growable list */
buzbeeed3e9302011-09-23 17:34:19 -0700110STATIC void expandGrowableList(GrowableList* gList)
buzbee67bf8852011-08-17 17:51:35 -0700111{
112 int newLength = gList->numAllocated;
113 if (newLength < 128) {
114 newLength <<= 1;
115 } else {
116 newLength += 128;
117 }
118 intptr_t *newArray =
119 (intptr_t *) oatNew(sizeof(intptr_t) * newLength, true);
120 memcpy(newArray, gList->elemList, sizeof(intptr_t) * gList->numAllocated);
121 gList->numAllocated = newLength;
122 gList->elemList = newArray;
123}
124
125/* Insert a new element into the growable list */
126void oatInsertGrowableList(GrowableList* gList, intptr_t elem)
127{
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700128 DCHECK_NE(gList->numAllocated, 0U);
buzbee67bf8852011-08-17 17:51:35 -0700129 if (gList->numUsed == gList->numAllocated) {
130 expandGrowableList(gList);
131 }
132 gList->elemList[gList->numUsed++] = elem;
133}
134
135void oatGrowableListIteratorInit(GrowableList* gList,
136 GrowableListIterator* iterator)
137{
138 iterator->list = gList;
139 iterator->idx = 0;
140 iterator->size = gList->numUsed;
141}
142
143intptr_t oatGrowableListIteratorNext(GrowableListIterator* iterator)
144{
buzbeeed3e9302011-09-23 17:34:19 -0700145 DCHECK_EQ(iterator->size, iterator->list->numUsed);
buzbee67bf8852011-08-17 17:51:35 -0700146 if (iterator->idx == iterator->size) return 0;
147 return iterator->list->elemList[iterator->idx++];
148}
149
150intptr_t oatGrowableListGetElement(const GrowableList* gList, size_t idx)
151{
buzbeeed3e9302011-09-23 17:34:19 -0700152 DCHECK_LT(idx, gList->numUsed);
buzbee67bf8852011-08-17 17:51:35 -0700153 return gList->elemList[idx];
154}
155
156/* Debug Utility - dump a compilation unit */
157void oatDumpCompilationUnit(CompilationUnit* cUnit)
158{
159 BasicBlock* bb;
160 const char* blockTypeNames[] = {
161 "Entry Block",
162 "Code Block",
163 "Exit Block",
164 "Exception Handling",
165 "Catch Block"
166 };
167
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800168 LOG(INFO) << "Compiling " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
buzbee67bf8852011-08-17 17:51:35 -0700169 LOG(INFO) << cUnit->insns << " insns";
170 LOG(INFO) << cUnit->numBlocks << " blocks in total";
171 GrowableListIterator iterator;
172
173 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
174
175 while (true) {
176 bb = (BasicBlock *) oatGrowableListIteratorNext(&iterator);
177 if (bb == NULL) break;
178 char buf[100];
179 snprintf(buf, 100, "Block %d (%s) (insn %04x - %04x%s)",
180 bb->id,
181 blockTypeNames[bb->blockType],
182 bb->startOffset,
183 bb->lastMIRInsn ? bb->lastMIRInsn->offset : bb->startOffset,
184 bb->lastMIRInsn ? "" : " empty");
185 LOG(INFO) << buf;
186 if (bb->taken) {
187 LOG(INFO) << " Taken branch: block " << bb->taken->id <<
188 "(0x" << std::hex << bb->taken->startOffset << ")";
189 }
190 if (bb->fallThrough) {
191 LOG(INFO) << " Fallthrough : block " << bb->fallThrough->id <<
192 " (0x" << std::hex << bb->fallThrough->startOffset << ")";
193 }
194 }
195}
196
197/*
198 * Dump the current stats of the compiler.
199 */
200void oatDumpStats(void)
201{
202 oatArchDump();
203}
204
buzbee67bc2362011-10-11 18:08:40 -0700205static uint32_t checkMasks[32] = {
206 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
207 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200,
208 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000,
209 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000,
210 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000,
211 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
212 0x40000000, 0x80000000 };
213
buzbee67bf8852011-08-17 17:51:35 -0700214/*
215 * Allocate a bit vector with enough space to hold at least the specified
216 * number of bits.
217 *
218 * NOTE: memory is allocated from the compiler arena.
219 */
220ArenaBitVector* oatAllocBitVector(unsigned int startBits, bool expandable)
221{
222 ArenaBitVector* bv;
223 unsigned int count;
224
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700225 DCHECK_EQ(sizeof(bv->storage[0]), 4U); /* assuming 32-bit units */
buzbee67bf8852011-08-17 17:51:35 -0700226
227 bv = (ArenaBitVector*) oatNew(sizeof(ArenaBitVector), false);
228
229 count = (startBits + 31) >> 5;
230
231 bv->storageSize = count;
232 bv->expandable = expandable;
233 bv->storage = (u4*) oatNew(count * sizeof(u4), true);
234 return bv;
235}
236
237/*
238 * Determine whether or not the specified bit is set.
239 */
240bool oatIsBitSet(const ArenaBitVector* pBits, unsigned int num)
241{
buzbeeed3e9302011-09-23 17:34:19 -0700242 DCHECK_LT(num, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700243
buzbee67bc2362011-10-11 18:08:40 -0700244 unsigned int val = pBits->storage[num >> 5] & checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700245 return (val != 0);
246}
247
248/*
249 * Mark all bits bit as "clear".
250 */
251void oatClearAllBits(ArenaBitVector* pBits)
252{
253 unsigned int count = pBits->storageSize;
254 memset(pBits->storage, 0, count * sizeof(u4));
255}
256
257/*
258 * Mark the specified bit as "set".
259 *
260 * Returns "false" if the bit is outside the range of the vector and we're
261 * not allowed to expand.
262 *
263 * NOTE: memory is allocated from the compiler arena.
264 */
265bool oatSetBit(ArenaBitVector* pBits, unsigned int num)
266{
267 if (num >= pBits->storageSize * sizeof(u4) * 8) {
268 if (!pBits->expandable) {
269 LOG(FATAL) << "Can't expand";
270 }
271
272 /* Round up to word boundaries for "num+1" bits */
273 unsigned int newSize = (num + 1 + 31) >> 5;
buzbeeed3e9302011-09-23 17:34:19 -0700274 DCHECK_GT(newSize, pBits->storageSize);
buzbee67bf8852011-08-17 17:51:35 -0700275 u4 *newStorage = (u4*)oatNew(newSize * sizeof(u4), false);
276 memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
277 memset(&newStorage[pBits->storageSize], 0,
278 (newSize - pBits->storageSize) * sizeof(u4));
279 pBits->storage = newStorage;
280 pBits->storageSize = newSize;
281 }
282
buzbee67bc2362011-10-11 18:08:40 -0700283 pBits->storage[num >> 5] |= checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700284 return true;
285}
286
287/*
288 * Mark the specified bit as "unset".
289 *
290 * Returns "false" if the bit is outside the range of the vector and we're
291 * not allowed to expand.
292 *
293 * NOTE: memory is allocated from the compiler arena.
294 */
295bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
296{
297 if (num >= pBits->storageSize * sizeof(u4) * 8) {
298 LOG(FATAL) << "Attempt to clear a bit not set in the vector yet";;
299 }
300
buzbee67bc2362011-10-11 18:08:40 -0700301 pBits->storage[num >> 5] &= ~checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700302 return true;
303}
304
305/*
306 * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
307 */
308void oatMarkAllBits(ArenaBitVector* pBits, bool set)
309{
310 int value = set ? -1 : 0;
311 memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
312}
313
314void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
315{
316 int i;
317
318 LOG(INFO) << msg;
319 for (i = 0; i < length; i++) {
320 if (oatIsBitSet(bv, i)) {
321 LOG(INFO) << " Bit " << i << " is set";
322 }
323 }
324}
325
326void oatAbort(CompilationUnit* cUnit)
327{
328 LOG(FATAL) << "Compiler aborting";
329}
330
331void oatDumpBlockBitVector(const GrowableList* blocks, char* msg,
332 const ArenaBitVector* bv, int length)
333{
334 int i;
335
336 LOG(INFO) << msg;
337 for (i = 0; i < length; i++) {
338 if (oatIsBitSet(bv, i)) {
339 BasicBlock *bb =
340 (BasicBlock *) oatGrowableListGetElement(blocks, i);
341 char blockName[BLOCK_NAME_LEN];
342 oatGetBlockName(bb, blockName);
343 LOG(INFO) << "Bit " << i << " / " << blockName << " is set";
344 }
345 }
346}
347/* Initialize the iterator structure */
348void oatBitVectorIteratorInit(ArenaBitVector* pBits,
349 ArenaBitVectorIterator* iterator)
350{
351 iterator->pBits = pBits;
352 iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
353 iterator->idx = 0;
354}
355
356/*
357 * If the vector sizes don't match, log an error and abort.
358 */
buzbeeed3e9302011-09-23 17:34:19 -0700359STATIC void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
buzbee67bf8852011-08-17 17:51:35 -0700360{
361 if (bv1->storageSize != bv2->storageSize) {
362 LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize <<
363 ", " << bv2->storageSize << ")";
364 }
365}
366
367/*
368 * Copy a whole vector to the other. Only do that when the both vectors have
369 * the same size.
370 */
371void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
372{
373 /* if dest is expandable and < src, we could expand dest to match */
374 checkSizes(dest, src);
375
376 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
377}
378
379/*
380 * Intersect two bit vectors and store the result to the dest vector.
381 */
382
383bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
384 const ArenaBitVector* src2)
385{
buzbeeaad72012011-09-21 21:52:09 -0700386 DCHECK(src1 != NULL);
387 DCHECK(src2 != NULL);
388 if (dest->storageSize != src1->storageSize ||
buzbee67bf8852011-08-17 17:51:35 -0700389 dest->storageSize != src2->storageSize ||
390 dest->expandable != src1->expandable ||
391 dest->expandable != src2->expandable)
392 return false;
393
394 unsigned int idx;
395 for (idx = 0; idx < dest->storageSize; idx++) {
396 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
397 }
398 return true;
399}
400
401/*
402 * Unify two bit vectors and store the result to the dest vector.
403 */
404bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
405 const ArenaBitVector* src2)
406{
buzbeeaad72012011-09-21 21:52:09 -0700407 DCHECK(src1 != NULL);
408 DCHECK(src2 != NULL);
409 if (dest->storageSize != src1->storageSize ||
buzbee67bf8852011-08-17 17:51:35 -0700410 dest->storageSize != src2->storageSize ||
411 dest->expandable != src1->expandable ||
412 dest->expandable != src2->expandable)
413 return false;
414
415 unsigned int idx;
416 for (idx = 0; idx < dest->storageSize; idx++) {
417 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
418 }
419 return true;
420}
421
422/*
423 * Compare two bit vectors and return true if difference is seen.
424 */
425bool oatCompareBitVectors(const ArenaBitVector* src1,
426 const ArenaBitVector* src2)
427{
428 if (src1->storageSize != src2->storageSize ||
429 src1->expandable != src2->expandable)
430 return true;
431
432 unsigned int idx;
433 for (idx = 0; idx < src1->storageSize; idx++) {
434 if (src1->storage[idx] != src2->storage[idx]) return true;
435 }
436 return false;
437}
438
439/*
440 * Count the number of bits that are set.
441 */
442int oatCountSetBits(const ArenaBitVector* pBits)
443{
444 unsigned int word;
445 unsigned int count = 0;
446
447 for (word = 0; word < pBits->storageSize; word++) {
448 u4 val = pBits->storage[word];
449
450 if (val != 0) {
451 if (val == 0xffffffff) {
452 count += 32;
453 } else {
454 /* count the number of '1' bits */
455 while (val != 0) {
456 val &= val - 1;
457 count++;
458 }
459 }
460 }
461 }
462
463 return count;
464}
465
466/* Return the next position set to 1. -1 means end-of-element reached */
467int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
468{
469 const ArenaBitVector* pBits = iterator->pBits;
470 u4 bitIndex = iterator->idx;
471
buzbeeed3e9302011-09-23 17:34:19 -0700472 DCHECK_EQ(iterator->bitSize, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700473 if (bitIndex >= iterator->bitSize) return -1;
474
buzbee67bc2362011-10-11 18:08:40 -0700475 for (; bitIndex < iterator->bitSize;) {
buzbee67bf8852011-08-17 17:51:35 -0700476 unsigned int wordIndex = bitIndex >> 5;
buzbee67bc2362011-10-11 18:08:40 -0700477 unsigned int bitPos = bitIndex & 0x1f;
478 unsigned int word = pBits->storage[wordIndex];
479 if (word & checkMasks[bitPos]) {
buzbee67bf8852011-08-17 17:51:35 -0700480 iterator->idx = bitIndex+1;
481 return bitIndex;
482 }
buzbee67bc2362011-10-11 18:08:40 -0700483 if (word == 0) {
484 // Helps if this is a sparse vector
485 bitIndex += (32 - bitPos);
486 } else {
487 bitIndex++;
488 }
buzbee67bf8852011-08-17 17:51:35 -0700489 }
490 /* No more set bits */
491 return -1;
492}
493
494/*
495 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
496 * since there might be unused bits - setting those to one will confuse the
497 * iterator.
498 */
499void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
500{
501 unsigned int idx;
buzbeeed3e9302011-09-23 17:34:19 -0700502 DCHECK_LE(((numBits + 31) >> 5), pBits->storageSize);
buzbee67bf8852011-08-17 17:51:35 -0700503 for (idx = 0; idx < (numBits >> 5); idx++) {
504 pBits->storage[idx] = -1;
505 }
506 unsigned int remNumBits = numBits & 0x1f;
507 if (remNumBits) {
508 pBits->storage[idx] = (1 << remNumBits) - 1;
509 }
510}
511
512void oatGetBlockName(BasicBlock* bb, char* name)
513{
514 switch (bb->blockType) {
515 case kEntryBlock:
516 snprintf(name, BLOCK_NAME_LEN, "entry");
517 break;
518 case kExitBlock:
519 snprintf(name, BLOCK_NAME_LEN, "exit");
520 break;
521 case kDalvikByteCode:
522 snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
523 break;
524 case kExceptionHandling:
525 snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
526 break;
527 default:
528 snprintf(name, BLOCK_NAME_LEN, "??");
529 break;
530 }
531}
buzbeeed3e9302011-09-23 17:34:19 -0700532
533const char* oatGetShortyFromTargetIdx(CompilationUnit *cUnit, int targetIdx)
534{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800535 const DexFile::MethodId& methodId = cUnit->dex_file->GetMethodId(targetIdx);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800536 return cUnit->dex_file->GetShorty(methodId.proto_idx_);
buzbeeed3e9302011-09-23 17:34:19 -0700537}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800538
539} // namespace art