blob: 9d8e08861643a082595ede5ec12c110bb937eca6 [file] [log] [blame]
Ben Chengba4fc8b2009-06-01 13:00:29 -07001/*
2 * Copyright (C) 2009 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/* Allocate the initial memory block for arena-based allocation */
24bool dvmCompilerHeapInit(void)
25{
26 assert(arenaHead == NULL);
27 arenaHead =
28 (ArenaMemBlock *) malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
29 if (arenaHead == NULL) {
30 LOGE("No memory left to create compiler heap memory\n");
31 return false;
32 }
33 currentArena = arenaHead;
34 currentArena->bytesAllocated = 0;
35 currentArena->next = NULL;
36 numArenaBlocks = 1;
37
38 return true;
39}
40
41/* Arena-based malloc for compilation tasks */
42void * dvmCompilerNew(size_t size, bool zero)
43{
44 size = (size + 3) & ~3;
45retry:
46 /* Normal case - space is available in the current page */
47 if (size + currentArena->bytesAllocated <= ARENA_DEFAULT_SIZE) {
48 void *ptr;
49 ptr = &currentArena->ptr[currentArena->bytesAllocated];
50 currentArena->bytesAllocated += size;
51 if (zero) {
52 memset(ptr, 0, size);
53 }
54 return ptr;
55 } else {
56 /*
57 * See if there are previously allocated arena blocks before the last
58 * reset
59 */
60 if (currentArena->next) {
61 currentArena = currentArena->next;
62 goto retry;
63 }
64 /*
65 * If we allocate really large variable-sized data structures that
66 * could go above the limit we need to enhance the allocation
67 * mechanism.
68 */
69 if (size > ARENA_DEFAULT_SIZE) {
70 LOGE("Requesting %d bytes which exceed the maximal size allowed\n",
71 size);
72 return NULL;
73 }
74 /* Time to allocate a new arena */
75 ArenaMemBlock *newArena = (ArenaMemBlock *)
76 malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
77 newArena->bytesAllocated = 0;
78 newArena->next = NULL;
79 currentArena->next = newArena;
80 currentArena = newArena;
81 numArenaBlocks++;
82 goto retry;
83 }
84 return NULL;
85}
86
87/* Reclaim all the arena blocks allocated so far */
88void dvmCompilerArenaReset(void)
89{
90 ArenaMemBlock *block;
91
92 for (block = arenaHead; block; block = block->next) {
93 block->bytesAllocated = 0;
94 }
95 currentArena = arenaHead;
96}
97
98/* Growable List initialization */
99void dvmInitGrowableList(GrowableList *gList, size_t initLength)
100{
101 gList->numAllocated = initLength;
102 gList->numUsed = 0;
103 gList->elemList = (void **) dvmCompilerNew(sizeof(void *) * initLength,
104 true);
105}
106
107/* Expand the capacity of a growable list */
108static void expandGrowableList(GrowableList *gList)
109{
110 int newLength = gList->numAllocated;
111 if (newLength < 128) {
112 newLength <<= 1;
113 } else {
114 newLength += 128;
115 }
116 void *newArray = dvmCompilerNew(sizeof(void *) * newLength, true);
117 memcpy(newArray, gList->elemList, sizeof(void *) * gList->numAllocated);
118 gList->numAllocated = newLength;
119 gList->elemList = newArray;
120}
121
122/* Insert a new element into the growable list */
123void dvmInsertGrowableList(GrowableList *gList, void *elem)
124{
125 if (gList->numUsed == gList->numAllocated) {
126 expandGrowableList(gList);
127 }
128 gList->elemList[gList->numUsed++] = elem;
129}
130
131/* Debug Utility - dump a compilation unit */
132void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit)
133{
134 int i;
135 BasicBlock *bb;
136 LOGD("%d blocks in total\n", cUnit->numBlocks);
137
138 for (i = 0; i < cUnit->numBlocks; i++) {
139 bb = cUnit->blockList[i];
140 LOGD("Block %d (insn %04x - %04x%s)\n",
141 bb->id, bb->startOffset,
142 bb->lastMIRInsn ? bb->lastMIRInsn->offset : bb->startOffset,
143 bb->lastMIRInsn ? "" : " empty");
144 if (bb->taken) {
145 LOGD(" Taken branch: block %d (%04x)\n",
146 bb->taken->id, bb->taken->startOffset);
147 }
148 if (bb->fallThrough) {
149 LOGD(" Fallthrough : block %d (%04x)\n",
150 bb->fallThrough->id, bb->fallThrough->startOffset);
151 }
152 }
153}
154
155/*
156 * Dump the current stats of the compiler, including number of bytes used in
157 * the code cache, arena size, and work queue length, and various JIT stats.
158 */
159void dvmCompilerDumpStats(void)
160{
161 LOGD("%d compilations using %d bytes",
162 gDvmJit.numCompilations, gDvmJit.codeCacheByteUsed);
163 LOGD("Compiler arena uses %d blocks (%d bytes each)",
164 numArenaBlocks, ARENA_DEFAULT_SIZE);
165 LOGD("Compiler work queue length is %d/%d", gDvmJit.compilerQueueLength,
166 gDvmJit.compilerMaxQueued);
167 dvmJitStats();
168 dvmCompilerArchDump();
169}