blob: 6254b3d48d20f1462eb21556ddc7347baf83a9c9 [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
buzbeedfd3d702011-08-28 12:56:51 -0700167 LOG(INFO) << "Compiling " << art::PrettyMethod(cUnit->method);
buzbee67bf8852011-08-17 17:51:35 -0700168 LOG(INFO) << cUnit->insns << " insns";
169 LOG(INFO) << cUnit->numBlocks << " blocks in total";
170 GrowableListIterator iterator;
171
172 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
173
174 while (true) {
175 bb = (BasicBlock *) oatGrowableListIteratorNext(&iterator);
176 if (bb == NULL) break;
177 char buf[100];
178 snprintf(buf, 100, "Block %d (%s) (insn %04x - %04x%s)",
179 bb->id,
180 blockTypeNames[bb->blockType],
181 bb->startOffset,
182 bb->lastMIRInsn ? bb->lastMIRInsn->offset : bb->startOffset,
183 bb->lastMIRInsn ? "" : " empty");
184 LOG(INFO) << buf;
185 if (bb->taken) {
186 LOG(INFO) << " Taken branch: block " << bb->taken->id <<
187 "(0x" << std::hex << bb->taken->startOffset << ")";
188 }
189 if (bb->fallThrough) {
190 LOG(INFO) << " Fallthrough : block " << bb->fallThrough->id <<
191 " (0x" << std::hex << bb->fallThrough->startOffset << ")";
192 }
193 }
194}
195
196/*
197 * Dump the current stats of the compiler.
198 */
199void oatDumpStats(void)
200{
201 oatArchDump();
202}
203
204/*
205 * Allocate a bit vector with enough space to hold at least the specified
206 * number of bits.
207 *
208 * NOTE: memory is allocated from the compiler arena.
209 */
210ArenaBitVector* oatAllocBitVector(unsigned int startBits, bool expandable)
211{
212 ArenaBitVector* bv;
213 unsigned int count;
214
215 assert(sizeof(bv->storage[0]) == 4); /* assuming 32-bit units */
216
217 bv = (ArenaBitVector*) oatNew(sizeof(ArenaBitVector), false);
218
219 count = (startBits + 31) >> 5;
220
221 bv->storageSize = count;
222 bv->expandable = expandable;
223 bv->storage = (u4*) oatNew(count * sizeof(u4), true);
224 return bv;
225}
226
227/*
228 * Determine whether or not the specified bit is set.
229 */
230bool oatIsBitSet(const ArenaBitVector* pBits, unsigned int num)
231{
232 assert(num < pBits->storageSize * sizeof(u4) * 8);
233
234 unsigned int val = pBits->storage[num >> 5] & (1 << (num & 0x1f));
235 return (val != 0);
236}
237
238/*
239 * Mark all bits bit as "clear".
240 */
241void oatClearAllBits(ArenaBitVector* pBits)
242{
243 unsigned int count = pBits->storageSize;
244 memset(pBits->storage, 0, count * sizeof(u4));
245}
246
247/*
248 * Mark the specified bit as "set".
249 *
250 * Returns "false" if the bit is outside the range of the vector and we're
251 * not allowed to expand.
252 *
253 * NOTE: memory is allocated from the compiler arena.
254 */
255bool oatSetBit(ArenaBitVector* pBits, unsigned int num)
256{
257 if (num >= pBits->storageSize * sizeof(u4) * 8) {
258 if (!pBits->expandable) {
259 LOG(FATAL) << "Can't expand";
260 }
261
262 /* Round up to word boundaries for "num+1" bits */
263 unsigned int newSize = (num + 1 + 31) >> 5;
264 assert(newSize > pBits->storageSize);
265 u4 *newStorage = (u4*)oatNew(newSize * sizeof(u4), false);
266 memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
267 memset(&newStorage[pBits->storageSize], 0,
268 (newSize - pBits->storageSize) * sizeof(u4));
269 pBits->storage = newStorage;
270 pBits->storageSize = newSize;
271 }
272
273 pBits->storage[num >> 5] |= 1 << (num & 0x1f);
274 return true;
275}
276
277/*
278 * Mark the specified bit as "unset".
279 *
280 * Returns "false" if the bit is outside the range of the vector and we're
281 * not allowed to expand.
282 *
283 * NOTE: memory is allocated from the compiler arena.
284 */
285bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
286{
287 if (num >= pBits->storageSize * sizeof(u4) * 8) {
288 LOG(FATAL) << "Attempt to clear a bit not set in the vector yet";;
289 }
290
291 pBits->storage[num >> 5] &= ~(1 << (num & 0x1f));
292 return true;
293}
294
295/*
296 * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
297 */
298void oatMarkAllBits(ArenaBitVector* pBits, bool set)
299{
300 int value = set ? -1 : 0;
301 memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
302}
303
304void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
305{
306 int i;
307
308 LOG(INFO) << msg;
309 for (i = 0; i < length; i++) {
310 if (oatIsBitSet(bv, i)) {
311 LOG(INFO) << " Bit " << i << " is set";
312 }
313 }
314}
315
316void oatAbort(CompilationUnit* cUnit)
317{
318 LOG(FATAL) << "Compiler aborting";
319}
320
321void oatDumpBlockBitVector(const GrowableList* blocks, char* msg,
322 const ArenaBitVector* bv, int length)
323{
324 int i;
325
326 LOG(INFO) << msg;
327 for (i = 0; i < length; i++) {
328 if (oatIsBitSet(bv, i)) {
329 BasicBlock *bb =
330 (BasicBlock *) oatGrowableListGetElement(blocks, i);
331 char blockName[BLOCK_NAME_LEN];
332 oatGetBlockName(bb, blockName);
333 LOG(INFO) << "Bit " << i << " / " << blockName << " is set";
334 }
335 }
336}
337/* Initialize the iterator structure */
338void oatBitVectorIteratorInit(ArenaBitVector* pBits,
339 ArenaBitVectorIterator* iterator)
340{
341 iterator->pBits = pBits;
342 iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
343 iterator->idx = 0;
344}
345
346/*
347 * If the vector sizes don't match, log an error and abort.
348 */
349static void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
350{
351 if (bv1->storageSize != bv2->storageSize) {
352 LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize <<
353 ", " << bv2->storageSize << ")";
354 }
355}
356
357/*
358 * Copy a whole vector to the other. Only do that when the both vectors have
359 * the same size.
360 */
361void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
362{
363 /* if dest is expandable and < src, we could expand dest to match */
364 checkSizes(dest, src);
365
366 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
367}
368
369/*
370 * Intersect two bit vectors and store the result to the dest vector.
371 */
372
373bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
374 const ArenaBitVector* src2)
375{
376 if (dest->storageSize != src1->storageSize ||
377 dest->storageSize != src2->storageSize ||
378 dest->expandable != src1->expandable ||
379 dest->expandable != src2->expandable)
380 return false;
381
382 unsigned int idx;
383 for (idx = 0; idx < dest->storageSize; idx++) {
384 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
385 }
386 return true;
387}
388
389/*
390 * Unify two bit vectors and store the result to the dest vector.
391 */
392bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
393 const ArenaBitVector* src2)
394{
395 if (dest->storageSize != src1->storageSize ||
396 dest->storageSize != src2->storageSize ||
397 dest->expandable != src1->expandable ||
398 dest->expandable != src2->expandable)
399 return false;
400
401 unsigned int idx;
402 for (idx = 0; idx < dest->storageSize; idx++) {
403 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
404 }
405 return true;
406}
407
408/*
409 * Compare two bit vectors and return true if difference is seen.
410 */
411bool oatCompareBitVectors(const ArenaBitVector* src1,
412 const ArenaBitVector* src2)
413{
414 if (src1->storageSize != src2->storageSize ||
415 src1->expandable != src2->expandable)
416 return true;
417
418 unsigned int idx;
419 for (idx = 0; idx < src1->storageSize; idx++) {
420 if (src1->storage[idx] != src2->storage[idx]) return true;
421 }
422 return false;
423}
424
425/*
426 * Count the number of bits that are set.
427 */
428int oatCountSetBits(const ArenaBitVector* pBits)
429{
430 unsigned int word;
431 unsigned int count = 0;
432
433 for (word = 0; word < pBits->storageSize; word++) {
434 u4 val = pBits->storage[word];
435
436 if (val != 0) {
437 if (val == 0xffffffff) {
438 count += 32;
439 } else {
440 /* count the number of '1' bits */
441 while (val != 0) {
442 val &= val - 1;
443 count++;
444 }
445 }
446 }
447 }
448
449 return count;
450}
451
452/* Return the next position set to 1. -1 means end-of-element reached */
453int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
454{
455 const ArenaBitVector* pBits = iterator->pBits;
456 u4 bitIndex = iterator->idx;
457
458 assert(iterator->bitSize == pBits->storageSize * sizeof(u4) * 8);
459 if (bitIndex >= iterator->bitSize) return -1;
460
461 for (; bitIndex < iterator->bitSize; bitIndex++) {
462 unsigned int wordIndex = bitIndex >> 5;
463 unsigned int mask = 1 << (bitIndex & 0x1f);
464 if (pBits->storage[wordIndex] & mask) {
465 iterator->idx = bitIndex+1;
466 return bitIndex;
467 }
468 }
469 /* No more set bits */
470 return -1;
471}
472
473/*
474 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
475 * since there might be unused bits - setting those to one will confuse the
476 * iterator.
477 */
478void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
479{
480 unsigned int idx;
481 assert(((numBits + 31) >> 5) <= pBits->storageSize);
482 for (idx = 0; idx < (numBits >> 5); idx++) {
483 pBits->storage[idx] = -1;
484 }
485 unsigned int remNumBits = numBits & 0x1f;
486 if (remNumBits) {
487 pBits->storage[idx] = (1 << remNumBits) - 1;
488 }
489}
490
491void oatGetBlockName(BasicBlock* bb, char* name)
492{
493 switch (bb->blockType) {
494 case kEntryBlock:
495 snprintf(name, BLOCK_NAME_LEN, "entry");
496 break;
497 case kExitBlock:
498 snprintf(name, BLOCK_NAME_LEN, "exit");
499 break;
500 case kDalvikByteCode:
501 snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
502 break;
503 case kExceptionHandling:
504 snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
505 break;
506 default:
507 snprintf(name, BLOCK_NAME_LEN, "??");
508 break;
509 }
510}