blob: c76143b928a9999b4bbd76ef2823c965503d31c0 [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);
buzbee5b537102012-01-17 17:33:47 -0800234 bv->firstDirty = true;
235 bv->lastDirty = true;
buzbee67bf8852011-08-17 17:51:35 -0700236 return bv;
237}
238
239/*
240 * Determine whether or not the specified bit is set.
241 */
242bool oatIsBitSet(const ArenaBitVector* pBits, unsigned int num)
243{
buzbeeed3e9302011-09-23 17:34:19 -0700244 DCHECK_LT(num, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700245
buzbee67bc2362011-10-11 18:08:40 -0700246 unsigned int val = pBits->storage[num >> 5] & checkMasks[num & 0x1f];
buzbee67bf8852011-08-17 17:51:35 -0700247 return (val != 0);
248}
249
250/*
251 * Mark all bits bit as "clear".
252 */
253void oatClearAllBits(ArenaBitVector* pBits)
254{
255 unsigned int count = pBits->storageSize;
256 memset(pBits->storage, 0, count * sizeof(u4));
buzbee5b537102012-01-17 17:33:47 -0800257 pBits->firstDirty = true;
258 pBits->lastDirty = true;
buzbee67bf8852011-08-17 17:51:35 -0700259}
260
261/*
262 * Mark the specified bit as "set".
263 *
264 * Returns "false" if the bit is outside the range of the vector and we're
265 * not allowed to expand.
266 *
267 * NOTE: memory is allocated from the compiler arena.
268 */
269bool oatSetBit(ArenaBitVector* pBits, unsigned int num)
270{
271 if (num >= pBits->storageSize * sizeof(u4) * 8) {
272 if (!pBits->expandable) {
273 LOG(FATAL) << "Can't expand";
274 }
275
276 /* Round up to word boundaries for "num+1" bits */
277 unsigned int newSize = (num + 1 + 31) >> 5;
buzbeeed3e9302011-09-23 17:34:19 -0700278 DCHECK_GT(newSize, pBits->storageSize);
buzbee67bf8852011-08-17 17:51:35 -0700279 u4 *newStorage = (u4*)oatNew(newSize * sizeof(u4), false);
280 memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
281 memset(&newStorage[pBits->storageSize], 0,
282 (newSize - pBits->storageSize) * sizeof(u4));
283 pBits->storage = newStorage;
284 pBits->storageSize = newSize;
285 }
286
buzbee67bc2362011-10-11 18:08:40 -0700287 pBits->storage[num >> 5] |= checkMasks[num & 0x1f];
buzbee5b537102012-01-17 17:33:47 -0800288 if (!pBits->firstDirty && ((int)num < pBits->firstBitSet)) {
289 pBits->firstBitSet = num;
290 }
291 if (!pBits->lastDirty && ((int)num > pBits->lastBitSet)) {
292 pBits->lastBitSet = num;
293 }
buzbee67bf8852011-08-17 17:51:35 -0700294 return true;
295}
296
297/*
298 * Mark the specified bit as "unset".
299 *
300 * Returns "false" if the bit is outside the range of the vector and we're
301 * not allowed to expand.
302 *
303 * NOTE: memory is allocated from the compiler arena.
304 */
305bool oatClearBit(ArenaBitVector* pBits, unsigned int num)
306{
307 if (num >= pBits->storageSize * sizeof(u4) * 8) {
308 LOG(FATAL) << "Attempt to clear a bit not set in the vector yet";;
309 }
310
buzbee67bc2362011-10-11 18:08:40 -0700311 pBits->storage[num >> 5] &= ~checkMasks[num & 0x1f];
buzbee5b537102012-01-17 17:33:47 -0800312 pBits->firstDirty = true;
313 pBits->lastDirty = true;
buzbee67bf8852011-08-17 17:51:35 -0700314 return true;
315}
316
317/*
318 * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
319 */
320void oatMarkAllBits(ArenaBitVector* pBits, bool set)
321{
322 int value = set ? -1 : 0;
323 memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
buzbee5b537102012-01-17 17:33:47 -0800324 pBits->firstDirty = true;
325 pBits->lastDirty = true;
buzbee67bf8852011-08-17 17:51:35 -0700326}
327
328void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length)
329{
330 int i;
331
332 LOG(INFO) << msg;
333 for (i = 0; i < length; i++) {
334 if (oatIsBitSet(bv, i)) {
335 LOG(INFO) << " Bit " << i << " is set";
336 }
337 }
338}
339
340void oatAbort(CompilationUnit* cUnit)
341{
342 LOG(FATAL) << "Compiler aborting";
343}
344
345void oatDumpBlockBitVector(const GrowableList* blocks, char* msg,
346 const ArenaBitVector* bv, int length)
347{
348 int i;
349
350 LOG(INFO) << msg;
351 for (i = 0; i < length; i++) {
352 if (oatIsBitSet(bv, i)) {
353 BasicBlock *bb =
354 (BasicBlock *) oatGrowableListGetElement(blocks, i);
355 char blockName[BLOCK_NAME_LEN];
356 oatGetBlockName(bb, blockName);
357 LOG(INFO) << "Bit " << i << " / " << blockName << " is set";
358 }
359 }
360}
361/* Initialize the iterator structure */
362void oatBitVectorIteratorInit(ArenaBitVector* pBits,
363 ArenaBitVectorIterator* iterator)
364{
365 iterator->pBits = pBits;
366 iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
367 iterator->idx = 0;
368}
369
370/*
371 * If the vector sizes don't match, log an error and abort.
372 */
buzbeeed3e9302011-09-23 17:34:19 -0700373STATIC void checkSizes(const ArenaBitVector* bv1, const ArenaBitVector* bv2)
buzbee67bf8852011-08-17 17:51:35 -0700374{
375 if (bv1->storageSize != bv2->storageSize) {
376 LOG(FATAL) << "Mismatched vector sizes (" << bv1->storageSize <<
377 ", " << bv2->storageSize << ")";
378 }
379}
380
381/*
382 * Copy a whole vector to the other. Only do that when the both vectors have
383 * the same size.
384 */
385void oatCopyBitVector(ArenaBitVector* dest, const ArenaBitVector* src)
386{
387 /* if dest is expandable and < src, we could expand dest to match */
388 checkSizes(dest, src);
389
390 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
buzbee5b537102012-01-17 17:33:47 -0800391 dest->firstDirty = src->firstDirty;
392 dest->firstBitSet = src->firstBitSet;
393 dest->lastDirty = src->lastDirty;
394 dest->lastBitSet = src->lastBitSet;
buzbee67bf8852011-08-17 17:51:35 -0700395}
396
397/*
398 * Intersect two bit vectors and store the result to the dest vector.
399 */
400
401bool oatIntersectBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
402 const ArenaBitVector* src2)
403{
buzbeeaad72012011-09-21 21:52:09 -0700404 DCHECK(src1 != NULL);
405 DCHECK(src2 != NULL);
406 if (dest->storageSize != src1->storageSize ||
buzbee67bf8852011-08-17 17:51:35 -0700407 dest->storageSize != src2->storageSize ||
408 dest->expandable != src1->expandable ||
409 dest->expandable != src2->expandable)
410 return false;
411
412 unsigned int idx;
413 for (idx = 0; idx < dest->storageSize; idx++) {
414 dest->storage[idx] = src1->storage[idx] & src2->storage[idx];
415 }
buzbee5b537102012-01-17 17:33:47 -0800416 dest->firstDirty = true;
417 dest->lastDirty = true;
buzbee67bf8852011-08-17 17:51:35 -0700418 return true;
419}
420
421/*
422 * Unify two bit vectors and store the result to the dest vector.
423 */
424bool oatUnifyBitVectors(ArenaBitVector* dest, const ArenaBitVector* src1,
425 const ArenaBitVector* src2)
426{
buzbeeaad72012011-09-21 21:52:09 -0700427 DCHECK(src1 != NULL);
428 DCHECK(src2 != NULL);
429 if (dest->storageSize != src1->storageSize ||
buzbee67bf8852011-08-17 17:51:35 -0700430 dest->storageSize != src2->storageSize ||
431 dest->expandable != src1->expandable ||
432 dest->expandable != src2->expandable)
433 return false;
434
435 unsigned int idx;
436 for (idx = 0; idx < dest->storageSize; idx++) {
437 dest->storage[idx] = src1->storage[idx] | src2->storage[idx];
438 }
buzbee5b537102012-01-17 17:33:47 -0800439 dest->firstDirty = true;
440 dest->lastDirty = true;
buzbee67bf8852011-08-17 17:51:35 -0700441 return true;
442}
443
444/*
445 * Compare two bit vectors and return true if difference is seen.
446 */
447bool oatCompareBitVectors(const ArenaBitVector* src1,
448 const ArenaBitVector* src2)
449{
450 if (src1->storageSize != src2->storageSize ||
451 src1->expandable != src2->expandable)
452 return true;
453
454 unsigned int idx;
455 for (idx = 0; idx < src1->storageSize; idx++) {
456 if (src1->storage[idx] != src2->storage[idx]) return true;
457 }
458 return false;
459}
460
461/*
462 * Count the number of bits that are set.
463 */
464int oatCountSetBits(const ArenaBitVector* pBits)
465{
466 unsigned int word;
467 unsigned int count = 0;
468
469 for (word = 0; word < pBits->storageSize; word++) {
470 u4 val = pBits->storage[word];
471
472 if (val != 0) {
473 if (val == 0xffffffff) {
474 count += 32;
475 } else {
476 /* count the number of '1' bits */
477 while (val != 0) {
478 val &= val - 1;
479 count++;
480 }
481 }
482 }
483 }
484
485 return count;
486}
487
488/* Return the next position set to 1. -1 means end-of-element reached */
489int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator)
490{
buzbee5b537102012-01-17 17:33:47 -0800491 ArenaBitVector* pBits = iterator->pBits;
buzbee67bf8852011-08-17 17:51:35 -0700492 u4 bitIndex = iterator->idx;
493
buzbeeed3e9302011-09-23 17:34:19 -0700494 DCHECK_EQ(iterator->bitSize, pBits->storageSize * sizeof(u4) * 8);
buzbee67bf8852011-08-17 17:51:35 -0700495 if (bitIndex >= iterator->bitSize) return -1;
496
buzbee5b537102012-01-17 17:33:47 -0800497 /* If we know, skip past leading zeros */
498 if (!pBits->firstDirty && ((int)bitIndex < pBits->firstBitSet)) {
499 iterator->idx = pBits->firstBitSet + 1;
500 return pBits->firstBitSet;
501 }
502
503 /* If we know, skip past trailing zeroes */
504 if (!pBits->lastDirty && ((int)bitIndex > pBits->lastBitSet)) {
505 iterator->idx = iterator->bitSize;
506 return -1;
507 }
508
509 bool firstPass = (bitIndex == 0);
510 u4 startIndex = bitIndex;
buzbee67bc2362011-10-11 18:08:40 -0700511 for (; bitIndex < iterator->bitSize;) {
buzbee67bf8852011-08-17 17:51:35 -0700512 unsigned int wordIndex = bitIndex >> 5;
buzbee67bc2362011-10-11 18:08:40 -0700513 unsigned int bitPos = bitIndex & 0x1f;
514 unsigned int word = pBits->storage[wordIndex];
515 if (word & checkMasks[bitPos]) {
buzbee67bf8852011-08-17 17:51:35 -0700516 iterator->idx = bitIndex+1;
buzbee5b537102012-01-17 17:33:47 -0800517 if (firstPass && pBits->firstDirty) {
518 pBits->firstBitSet = bitIndex;
519 pBits->firstDirty = false;
520 }
buzbee67bf8852011-08-17 17:51:35 -0700521 return bitIndex;
522 }
buzbee67bc2362011-10-11 18:08:40 -0700523 if (word == 0) {
524 // Helps if this is a sparse vector
525 bitIndex += (32 - bitPos);
526 } else {
527 bitIndex++;
528 }
buzbee67bf8852011-08-17 17:51:35 -0700529 }
530 /* No more set bits */
buzbee5b537102012-01-17 17:33:47 -0800531 if (firstPass) {
532 // Empty
533 pBits->firstBitSet = -1;
534 pBits->firstDirty = false;
535 } else {
536 pBits->lastBitSet = startIndex - 1;
537 pBits->lastDirty = false;
538 }
buzbee67bf8852011-08-17 17:51:35 -0700539 return -1;
540}
541
542/*
543 * Mark specified number of bits as "set". Cannot set all bits like ClearAll
544 * since there might be unused bits - setting those to one will confuse the
545 * iterator.
546 */
547void oatSetInitialBits(ArenaBitVector* pBits, unsigned int numBits)
548{
549 unsigned int idx;
buzbeeed3e9302011-09-23 17:34:19 -0700550 DCHECK_LE(((numBits + 31) >> 5), pBits->storageSize);
buzbee67bf8852011-08-17 17:51:35 -0700551 for (idx = 0; idx < (numBits >> 5); idx++) {
552 pBits->storage[idx] = -1;
553 }
554 unsigned int remNumBits = numBits & 0x1f;
555 if (remNumBits) {
556 pBits->storage[idx] = (1 << remNumBits) - 1;
557 }
buzbee5b537102012-01-17 17:33:47 -0800558 pBits->firstDirty = true;
559 pBits->lastDirty = true;
buzbee67bf8852011-08-17 17:51:35 -0700560}
561
562void oatGetBlockName(BasicBlock* bb, char* name)
563{
564 switch (bb->blockType) {
565 case kEntryBlock:
566 snprintf(name, BLOCK_NAME_LEN, "entry");
567 break;
568 case kExitBlock:
569 snprintf(name, BLOCK_NAME_LEN, "exit");
570 break;
571 case kDalvikByteCode:
572 snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
573 break;
574 case kExceptionHandling:
575 snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
576 break;
577 default:
578 snprintf(name, BLOCK_NAME_LEN, "??");
579 break;
580 }
581}
buzbeeed3e9302011-09-23 17:34:19 -0700582
583const char* oatGetShortyFromTargetIdx(CompilationUnit *cUnit, int targetIdx)
584{
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800585 const DexFile::MethodId& methodId = cUnit->dex_file->GetMethodId(targetIdx);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800586 return cUnit->dex_file->GetShorty(methodId.proto_idx_);
buzbeeed3e9302011-09-23 17:34:19 -0700587}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800588
589} // namespace art