blob: b4dd80c7bdebb1f6f710f6dc83bacaa0a7e3eaa0 [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{
28 assert(arenaHead == NULL);
29 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;
64 goto retry;
65 }
66
67 size_t blockSize = (size < ARENA_DEFAULT_SIZE) ?
68 ARENA_DEFAULT_SIZE : size;
69 /* Time to allocate a new arena */
70 ArenaMemBlock *newArena = (ArenaMemBlock *)
71 malloc(sizeof(ArenaMemBlock) + blockSize);
72 if (newArena == NULL) {
73 LOG(FATAL) << "Arena allocation failure";
74 }
75 newArena->blockSize = blockSize;
76 newArena->bytesAllocated = 0;
77 newArena->next = NULL;
78 currentArena->next = newArena;
79 currentArena = newArena;
80 numArenaBlocks++;
81 if (numArenaBlocks > 10) {
82 LOG(INFO) << "Total arena pages: " << numArenaBlocks;
83 }
84 goto retry;
85 }
86}
87
88/* Reclaim all the arena blocks allocated so far */
89void oatArenaReset(void)
90{
91 ArenaMemBlock *block;
92
93 for (block = arenaHead; block; block = block->next) {
94 block->bytesAllocated = 0;
95 }
96 currentArena = arenaHead;
97}
98
99/* Growable List initialization */
100void oatInitGrowableList(GrowableList* gList, size_t initLength)
101{
102 gList->numAllocated = initLength;
103 gList->numUsed = 0;
104 gList->elemList = (intptr_t *) oatNew(sizeof(intptr_t) * initLength,
105 true);
106}
107
108/* Expand the capacity of a growable list */
109static void expandGrowableList(GrowableList* gList)
110{
111 int newLength = gList->numAllocated;
112 if (newLength < 128) {
113 newLength <<= 1;
114 } else {
115 newLength += 128;
116 }
117 intptr_t *newArray =
118 (intptr_t *) oatNew(sizeof(intptr_t) * newLength, true);
119 memcpy(newArray, gList->elemList, sizeof(intptr_t) * gList->numAllocated);
120 gList->numAllocated = newLength;
121 gList->elemList = newArray;
122}
123
124/* Insert a new element into the growable list */
125void oatInsertGrowableList(GrowableList* gList, intptr_t elem)
126{
127 assert(gList->numAllocated != 0);
128 if (gList->numUsed == gList->numAllocated) {
129 expandGrowableList(gList);
130 }
131 gList->elemList[gList->numUsed++] = elem;
132}
133
134void oatGrowableListIteratorInit(GrowableList* gList,
135 GrowableListIterator* iterator)
136{
137 iterator->list = gList;
138 iterator->idx = 0;
139 iterator->size = gList->numUsed;
140}
141
142intptr_t oatGrowableListIteratorNext(GrowableListIterator* iterator)
143{
144 assert(iterator->size == iterator->list->numUsed);
145 if (iterator->idx == iterator->size) return 0;
146 return iterator->list->elemList[iterator->idx++];
147}
148
149intptr_t oatGrowableListGetElement(const GrowableList* gList, size_t idx)
150{
151 assert(idx < gList->numUsed);
152 return gList->elemList[idx];
153}
154
155/* Debug Utility - dump a compilation unit */
156void oatDumpCompilationUnit(CompilationUnit* cUnit)
157{
158 BasicBlock* bb;
159 const char* blockTypeNames[] = {
160 "Entry Block",
161 "Code Block",
162 "Exit Block",
163 "Exception Handling",
164 "Catch Block"
165 };
166
167 LOG(INFO) << "Compiling " << cUnit->method->clazz->descriptor << " " <<
168 cUnit->method->name;
169 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
205/*
206 * Allocate a bit vector with enough space to hold at least the specified
207 * number of bits.
208 *
209 * NOTE: memory is allocated from the compiler arena.
210 */
211ArenaBitVector* oatAllocBitVector(unsigned int startBits, bool expandable)
212{
213 ArenaBitVector* bv;
214 unsigned int count;
215
216 assert(sizeof(bv->storage[0]) == 4); /* assuming 32-bit units */
217
218 bv = (ArenaBitVector*) oatNew(sizeof(ArenaBitVector), false);
219
220 count = (startBits + 31) >> 5;
221
222 bv->storageSize = count;
223 bv->expandable = expandable;
224 bv->storage = (u4*) oatNew(count * sizeof(u4), true);
225 return bv;
226}
227
228/*
229 * Determine whether or not the specified bit is set.
230 */
231bool oatIsBitSet(const ArenaBitVector* pBits, unsigned int num)
232{
233 assert(num < pBits->storageSize * sizeof(u4) * 8);
234
235 unsigned int val = pBits->storage[num >> 5] & (1 << (num & 0x1f));
236 return (val != 0);
237}
238
239/*
240 * Mark all bits bit as "clear".
241 */
242void oatClearAllBits(ArenaBitVector* pBits)
243{
244 unsigned int count = pBits->storageSize;
245 memset(pBits->storage, 0, count * sizeof(u4));
246}
247
248/*
249 * Mark the specified bit as "set".
250 *
251 * Returns "false" if the bit is outside the range of the vector and we're
252 * not allowed to expand.
253 *
254 * NOTE: memory is allocated from the compiler arena.
255 */
256bool oatSetBit(ArenaBitVector* pBits, unsigned int num)
257{
258 if (num >= pBits->storageSize * sizeof(u4) * 8) {
259 if (!pBits->expandable) {
260 LOG(FATAL) << "Can't expand";
261 }
262
263 /* Round up to word boundaries for "num+1" bits */
264 unsigned int newSize = (num + 1 + 31) >> 5;
265 assert(newSize > pBits->storageSize);
266 u4 *newStorage = (u4*)oatNew(newSize * sizeof(u4), false);
267 memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
268 memset(&newStorage[pBits->storageSize], 0,
269 (newSize - pBits->storageSize) * sizeof(u4));
270 pBits->storage = newStorage;
271 pBits->storageSize = newSize;
272 }
273
274 pBits->storage[num >> 5] |= 1 << (num & 0x1f);
275 return true;
276}
277
278/*
279 * Mark the specified bit as "unset".
280 *
281 * Returns "false" if the bit is outside the range of the vector and we're
282 * not allowed to expand.
283 *
284 * NOTE: memory is allocated from the compiler arena.
285 */
286bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
287{
288 if (num >= pBits->storageSize * sizeof(u4) * 8) {
289 LOG(FATAL) << "Attempt to clear a bit not set in the vector yet";;
290 }
291
292 pBits->storage[num >> 5] &= ~(1 << (num & 0x1f));
293 return true;
294}
295
296/*
297 * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
298 */
299void oatMarkAllBits(ArenaBitVector* pBits, bool set)
300{
301 int value = set ? -1 : 0;
302 memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
303}
304
305void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
306{
307 int i;
308
309 LOG(INFO) << msg;
310 for (i = 0; i < length; i++) {
311 if (oatIsBitSet(bv, i)) {
312 LOG(INFO) << " Bit " << i << " is set";
313 }
314 }
315}
316
317void oatAbort(CompilationUnit* cUnit)
318{
319 LOG(FATAL) << "Compiler aborting";
320}
321
322void oatDumpBlockBitVector(const GrowableList* blocks, char* msg,
323 const ArenaBitVector* bv, int length)
324{
325 int i;
326
327 LOG(INFO) << msg;
328 for (i = 0; i < length; i++) {
329 if (oatIsBitSet(bv, i)) {
330 BasicBlock *bb =
331 (BasicBlock *) oatGrowableListGetElement(blocks, i);
332 char blockName[BLOCK_NAME_LEN];
333 oatGetBlockName(bb, blockName);
334 LOG(INFO) << "Bit " << i << " / " << blockName << " is set";
335 }
336 }
337}
338/* Initialize the iterator structure */
339void oatBitVectorIteratorInit(ArenaBitVector* pBits,
340 ArenaBitVectorIterator* iterator)
341{
342 iterator->pBits = pBits;
343 iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
344 iterator->idx = 0;
345}
346
347/*
348 * If the vector sizes don't match, log an error and abort.
349 */
350static void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
351{
352 if (bv1->storageSize != bv2->storageSize) {
353 LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize <<
354 ", " << bv2->storageSize << ")";
355 }
356}
357
358/*
359 * Copy a whole vector to the other. Only do that when the both vectors have
360 * the same size.
361 */
362void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
363{
364 /* if dest is expandable and < src, we could expand dest to match */
365 checkSizes(dest, src);
366
367 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
368}
369
370/*
371 * Intersect two bit vectors and store the result to the dest vector.
372 */
373
374bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
375 const ArenaBitVector* src2)
376{
377 if (dest->storageSize != src1->storageSize ||
378 dest->storageSize != src2->storageSize ||
379 dest->expandable != src1->expandable ||
380 dest->expandable != src2->expandable)
381 return false;
382
383 unsigned int idx;
384 for (idx = 0; idx < dest->storageSize; idx++) {
385 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
386 }
387 return true;
388}
389
390/*
391 * Unify two bit vectors and store the result to the dest vector.
392 */
393bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
394 const ArenaBitVector* src2)
395{
396 if (dest->storageSize != src1->storageSize ||
397 dest->storageSize != src2->storageSize ||
398 dest->expandable != src1->expandable ||
399 dest->expandable != src2->expandable)
400 return false;
401
402 unsigned int idx;
403 for (idx = 0; idx < dest->storageSize; idx++) {
404 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
405 }
406 return true;
407}
408
409/*
410 * Compare two bit vectors and return true if difference is seen.
411 */
412bool oatCompareBitVectors(const ArenaBitVector* src1,
413 const ArenaBitVector* src2)
414{
415 if (src1->storageSize != src2->storageSize ||
416 src1->expandable != src2->expandable)
417 return true;
418
419 unsigned int idx;
420 for (idx = 0; idx < src1->storageSize; idx++) {
421 if (src1->storage[idx] != src2->storage[idx]) return true;
422 }
423 return false;
424}
425
426/*
427 * Count the number of bits that are set.
428 */
429int oatCountSetBits(const ArenaBitVector* pBits)
430{
431 unsigned int word;
432 unsigned int count = 0;
433
434 for (word = 0; word < pBits->storageSize; word++) {
435 u4 val = pBits->storage[word];
436
437 if (val != 0) {
438 if (val == 0xffffffff) {
439 count += 32;
440 } else {
441 /* count the number of '1' bits */
442 while (val != 0) {
443 val &= val - 1;
444 count++;
445 }
446 }
447 }
448 }
449
450 return count;
451}
452
453/* Return the next position set to 1. -1 means end-of-element reached */
454int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
455{
456 const ArenaBitVector* pBits = iterator->pBits;
457 u4 bitIndex = iterator->idx;
458
459 assert(iterator->bitSize == pBits->storageSize * sizeof(u4) * 8);
460 if (bitIndex >= iterator->bitSize) return -1;
461
462 for (; bitIndex < iterator->bitSize; bitIndex++) {
463 unsigned int wordIndex = bitIndex >> 5;
464 unsigned int mask = 1 << (bitIndex & 0x1f);
465 if (pBits->storage[wordIndex] & mask) {
466 iterator->idx = bitIndex+1;
467 return bitIndex;
468 }
469 }
470 /* No more set bits */
471 return -1;
472}
473
474/*
475 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
476 * since there might be unused bits - setting those to one will confuse the
477 * iterator.
478 */
479void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
480{
481 unsigned int idx;
482 assert(((numBits + 31) >> 5) <= pBits->storageSize);
483 for (idx = 0; idx < (numBits >> 5); idx++) {
484 pBits->storage[idx] = -1;
485 }
486 unsigned int remNumBits = numBits & 0x1f;
487 if (remNumBits) {
488 pBits->storage[idx] = (1 << remNumBits) - 1;
489 }
490}
491
492void oatGetBlockName(BasicBlock* bb, char* name)
493{
494 switch (bb->blockType) {
495 case kEntryBlock:
496 snprintf(name, BLOCK_NAME_LEN, "entry");
497 break;
498 case kExitBlock:
499 snprintf(name, BLOCK_NAME_LEN, "exit");
500 break;
501 case kDalvikByteCode:
502 snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
503 break;
504 case kExceptionHandling:
505 snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
506 break;
507 default:
508 snprintf(name, BLOCK_NAME_LEN, "??");
509 break;
510 }
511}