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