2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * This code generate "register maps" for Dalvik bytecode. In a stack-based
19 * VM we might call these "stack maps". They are used to increase the
20 * precision in the garbage collector when scanning references in the
21 * interpreter thread stacks.
24 #include "analysis/CodeVerify.h"
25 #include "analysis/RegisterMap.h"
26 #include "libdex/DexCatch.h"
27 #include "libdex/InstrUtils.h"
28 #include "libdex/Leb128.h"
32 /* double-check the compression */
33 #define REGISTER_MAP_VERIFY false
36 #define REGISTER_MAP_VERBOSE false
38 //#define REGISTER_MAP_STATS
41 static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data);
42 static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap);
43 static int compareMaps(const RegisterMap* pMap1, const RegisterMap* pMap2);
45 #ifdef REGISTER_MAP_STATS
46 static void computeMapStats(RegisterMap* pMap, const Method* method);
48 static RegisterMap* compressMapDifferential(const RegisterMap* pMap,\
50 static RegisterMap* uncompressMapDifferential(const RegisterMap* pMap);
52 #ifdef REGISTER_MAP_STATS
54 * Generate some statistics on the register maps we create and use.
56 #define kMaxGcPointGap 50
57 #define kUpdatePosnMinRegs 24
58 #define kNumUpdatePosns 8
59 #define kMaxDiffBits 20
60 typedef struct MapStats {
62 * Buckets measuring the distance between GC points. This tells us how
63 * many bits we need to encode the advancing program counter. We ignore
64 * some of the "long tail" entries.
66 int gcPointGap[kMaxGcPointGap];
69 * Number of gaps. Equal to (number of gcPoints - number of methods),
70 * since the computation isn't including the initial gap.
77 int totalGcPointCount;
80 * For larger methods (>= 24 registers), measure in which octant register
81 * updates occur. This should help us understand whether register
82 * changes tend to cluster in the low regs even for large methods.
84 int updatePosn[kNumUpdatePosns];
87 * For all methods, count up the number of changes to registers < 16
94 * Histogram of the number of bits that differ between adjacent entries.
96 int numDiffBits[kMaxDiffBits];
100 * Track the number of expanded maps, and the heap space required to
104 int totalExpandedMapSize;
109 * Prepare some things.
111 bool dvmRegisterMapStartup(void)
113 #ifdef REGISTER_MAP_STATS
114 MapStats* pStats = calloc(1, sizeof(MapStats));
115 gDvm.registerMapStats = pStats;
123 void dvmRegisterMapShutdown(void)
125 #ifdef REGISTER_MAP_STATS
126 free(gDvm.registerMapStats);
131 * Write stats to log file.
133 void dvmRegisterMapDumpStats(void)
135 #ifdef REGISTER_MAP_STATS
136 MapStats* pStats = (MapStats*) gDvm.registerMapStats;
139 for (end = kMaxGcPointGap-1; end >= 0; end--) {
140 if (pStats->gcPointGap[end] != 0)
144 LOGI("Register Map gcPointGap stats (diff count=%d, total=%d):\n",
145 pStats->gcGapCount, pStats->totalGcPointCount);
146 assert(pStats->gcPointGap[0] == 0);
147 for (i = 1; i <= end; i++) {
148 LOGI(" %2d %d\n", i, pStats->gcPointGap[i]);
152 for (end = kMaxDiffBits-1; end >= 0; end--) {
153 if (pStats->numDiffBits[end] != 0)
157 LOGI("Register Map bit difference stats:\n");
158 for (i = 0; i <= end; i++) {
159 LOGI(" %2d %d\n", i, pStats->numDiffBits[i]);
163 LOGI("Register Map update position stats (lt16=%d ge16=%d):\n",
164 pStats->updateLT16, pStats->updateGE16);
165 for (i = 0; i < kNumUpdatePosns; i++) {
166 LOGI(" %2d %d\n", i, pStats->updatePosn[i]);
173 * ===========================================================================
175 * ===========================================================================
179 * Generate the register map for a method that has just been verified
180 * (i.e. we're doing this as part of verification).
182 * For type-precise determination we have all the data we need, so we
183 * just need to encode it in some clever fashion.
185 * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
187 RegisterMap* dvmGenerateRegisterMapV(VerifierData* vdata)
189 static const int kHeaderSize = offsetof(RegisterMap, data);
190 RegisterMap* pMap = NULL;
191 RegisterMap* pResult = NULL;
192 RegisterMapFormat format;
195 int i, bytesForAddr, gcPointCount;
198 if (vdata->method->registersSize >= 2048) {
199 LOGE("ERROR: register map can't handle %d registers\n",
200 vdata->method->registersSize);
203 regWidth = (vdata->method->registersSize + 7) / 8;
206 * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
207 * we only need 16 bits if we actually encode an address >= 256 -- if
208 * the method has a section at the end without GC points (e.g. array
209 * data) we don't need to count it. The situation is unusual, and
210 * detecting it requires scanning the entire method, so we don't bother.
212 if (vdata->insnsSize < 256) {
213 format = kRegMapFormatCompact8;
216 format = kRegMapFormatCompact16;
221 * Count up the number of GC point instructions.
223 * NOTE: this does not automatically include the first instruction,
224 * since we don't count method entry as a GC point.
227 for (i = 0; i < (int) vdata->insnsSize; i++) {
228 if (dvmInsnIsGcPoint(vdata->insnFlags, i))
231 if (gcPointCount >= 65536) {
232 /* we could handle this, but in practice we don't get near this */
233 LOGE("ERROR: register map can't handle %d gc points in one method\n",
239 * Allocate a buffer to hold the map data.
241 bufSize = kHeaderSize + gcPointCount * (bytesForAddr + regWidth);
243 LOGV("+++ grm: %s.%s (adr=%d gpc=%d rwd=%d bsz=%d)\n",
244 vdata->method->clazz->descriptor, vdata->method->name,
245 bytesForAddr, gcPointCount, regWidth, bufSize);
247 pMap = (RegisterMap*) malloc(bufSize);
248 dvmRegisterMapSetFormat(pMap, format);
249 dvmRegisterMapSetOnHeap(pMap, true);
250 dvmRegisterMapSetRegWidth(pMap, regWidth);
251 dvmRegisterMapSetNumEntries(pMap, gcPointCount);
256 mapData = pMap->data;
257 for (i = 0; i < (int) vdata->insnsSize; i++) {
258 if (dvmInsnIsGcPoint(vdata->insnFlags, i)) {
259 assert(vdata->addrRegs[i] != NULL);
260 if (format == kRegMapFormatCompact8) {
262 } else /*kRegMapFormatCompact16*/ {
263 *mapData++ = i & 0xff;
266 outputTypeVector(vdata->addrRegs[i], vdata->insnRegCount, mapData);
271 LOGV("mapData=%p pMap=%p bufSize=%d\n", mapData, pMap, bufSize);
272 assert(mapData - (const u1*) pMap == bufSize);
274 if (REGISTER_MAP_VERIFY && !verifyMap(vdata, pMap))
276 #ifdef REGISTER_MAP_STATS
277 computeMapStats(pMap, vdata->method);
281 * Try to compress the map.
283 RegisterMap* pCompMap;
285 pCompMap = compressMapDifferential(pMap, vdata->method);
286 if (pCompMap != NULL) {
287 if (REGISTER_MAP_VERIFY) {
289 * Expand the compressed map we just created, and compare it
290 * to the original. Abort the VM if it doesn't match up.
292 RegisterMap* pUncompMap;
293 pUncompMap = uncompressMapDifferential(pCompMap);
294 if (pUncompMap == NULL) {
295 LOGE("Map failed to uncompress - %s.%s\n",
296 vdata->method->clazz->descriptor,
297 vdata->method->name);
299 /* bad - compression is broken or we're out of memory */
302 if (compareMaps(pMap, pUncompMap) != 0) {
303 LOGE("Map comparison failed - %s.%s\n",
304 vdata->method->clazz->descriptor,
305 vdata->method->name);
307 /* bad - compression is broken */
311 /* verify succeeded */
316 if (REGISTER_MAP_VERBOSE) {
317 LOGD("Good compress on %s.%s\n",
318 vdata->method->clazz->descriptor,
319 vdata->method->name);
324 if (REGISTER_MAP_VERBOSE) {
325 LOGD("Unable to compress %s.%s (ent=%d rw=%d)\n",
326 vdata->method->clazz->descriptor,
328 dvmRegisterMapGetNumEntries(pMap),
329 dvmRegisterMapGetRegWidth(pMap));
340 * Release the storage held by a RegisterMap.
342 void dvmFreeRegisterMap(RegisterMap* pMap)
347 assert(dvmRegisterMapGetOnHeap(pMap));
352 * Determine if the RegType value is a reference type.
354 * Ordinarily we include kRegTypeZero in the "is it a reference"
355 * check. There's no value in doing so here, because we know
356 * the register can't hold anything but zero.
358 static inline bool isReferenceType(RegType type)
360 return (type > kRegTypeMAX || type == kRegTypeUninit);
364 * Given a line of registers, output a bit vector that indicates whether
365 * or not the register holds a reference type (which could be null).
367 * We use '1' to indicate it's a reference, '0' for anything else (numeric
368 * value, uninitialized data, merge conflict). Register 0 will be found
369 * in the low bit of the first byte.
371 static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data)
376 for (i = 0; i < insnRegCount; i++) {
377 RegType type = *regs++;
379 if (isReferenceType(type))
380 val |= 0x80; /* set hi bit */
385 if ((i & 0x07) != 0) {
386 /* flush bits from last byte */
387 val >>= 8 - (i & 0x07);
393 * Print the map as a series of binary strings.
395 * Pass in method->registersSize if known, or -1 if not.
397 static void dumpRegisterMap(const RegisterMap* pMap, int registersSize)
399 const u1* rawMap = pMap->data;
400 const RegisterMapFormat format = dvmRegisterMapGetFormat(pMap);
401 const int numEntries = dvmRegisterMapGetNumEntries(pMap);
402 const int regWidth = dvmRegisterMapGetRegWidth(pMap);
406 case kRegMapFormatCompact8:
409 case kRegMapFormatCompact16:
414 LOGE("Can only dump Compact8 / Compact16 maps (not %d)\n", format);
418 if (registersSize < 0)
419 registersSize = 8 * regWidth;
420 assert(registersSize <= regWidth * 8);
423 for (ent = 0; ent < numEntries; ent++) {
428 addr |= (*rawMap++) << 8;
430 const u1* dataStart = rawMap;
433 /* create binary string */
434 char outBuf[registersSize +1];
435 for (i = 0; i < registersSize; i++) {
440 outBuf[i] = '0' + (val & 0x01);
444 /* back up and create hex dump */
445 char hexBuf[regWidth * 3 +1];
448 for (i = 0; i < regWidth; i++) {
449 sprintf(cp, " %02x", *rawMap++);
452 hexBuf[i * 3] = '\0';
454 LOGD(" %04x %s %s\n", addr, outBuf, hexBuf);
459 * Double-check the map.
461 * We run through all of the data in the map, and compare it to the original.
462 * Only works on uncompressed data.
464 static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap)
466 const u1* rawMap = pMap->data;
467 const RegisterMapFormat format = dvmRegisterMapGetFormat(pMap);
468 const int numEntries = dvmRegisterMapGetNumEntries(pMap);
470 bool dumpMap = false;
473 const char* cd = "Landroid/net/http/Request;";
474 const char* mn = "readResponse";
475 if (strcmp(vdata->method->clazz->descriptor, cd) == 0 &&
476 strcmp(vdata->method->name, mn) == 0)
479 desc = dexProtoCopyMethodDescriptor(&vdata->method->prototype);
480 LOGI("Map for %s.%s %s\n", vdata->method->clazz->descriptor,
481 vdata->method->name, desc);
488 if ((vdata->method->registersSize + 7) / 8 != pMap->regWidth) {
489 LOGE("GLITCH: registersSize=%d, regWidth=%d\n",
490 vdata->method->registersSize, pMap->regWidth);
494 for (ent = 0; ent < numEntries; ent++) {
498 case kRegMapFormatCompact8:
501 case kRegMapFormatCompact16:
503 addr |= (*rawMap++) << 8;
506 /* shouldn't happen */
507 LOGE("GLITCH: bad format (%d)", format);
511 const RegType* regs = vdata->addrRegs[addr];
513 LOGE("GLITCH: addr %d has no data\n", addr);
520 for (i = 0; i < vdata->method->registersSize; i++) {
521 bool bitIsRef, regIsRef;
524 if ((i & 0x07) == 0) {
525 /* load next byte of data */
529 bitIsRef = val & 0x01;
531 RegType type = regs[i];
532 regIsRef = isReferenceType(type);
534 if (bitIsRef != regIsRef) {
535 LOGE("GLITCH: addr %d reg %d: bit=%d reg=%d(%d)\n",
536 addr, i, bitIsRef, regIsRef, type);
541 /* rawMap now points to the address field of the next entry */
545 dumpRegisterMap(pMap, vdata->method->registersSize);
552 * ===========================================================================
553 * DEX generation & parsing
554 * ===========================================================================
558 * Advance "ptr" to ensure 32-bit alignment.
560 static inline u1* align32(u1* ptr)
562 return (u1*) (((int) ptr + 3) & ~0x03);
566 * Compute the size, in bytes, of a register map.
568 static size_t computeRegisterMapSize(const RegisterMap* pMap)
570 static const int kHeaderSize = offsetof(RegisterMap, data);
571 u1 format = dvmRegisterMapGetFormat(pMap);
572 u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
574 assert(pMap != NULL);
577 case kRegMapFormatNone:
579 case kRegMapFormatCompact8:
580 return kHeaderSize + (1 + pMap->regWidth) * numEntries;
581 case kRegMapFormatCompact16:
582 return kHeaderSize + (2 + pMap->regWidth) * numEntries;
583 case kRegMapFormatDifferential:
585 /* kHeaderSize + decoded ULEB128 length */
586 const u1* ptr = pMap->data;
587 int len = readUnsignedLeb128(&ptr);
588 return len + (ptr - (u1*) pMap);
591 LOGE("Bad register map format %d\n", format);
598 * Output the map for a single method, if it has one.
600 * Abstract and native methods have no map. All others are expected to
601 * have one, since we know the class verified successfully.
603 * This strips the "allocated on heap" flag from the format byte, so that
604 * direct-mapped maps are correctly identified as such.
606 static bool writeMapForMethod(const Method* meth, u1** pPtr)
608 if (meth->registerMap == NULL) {
609 if (!dvmIsAbstractMethod(meth) && !dvmIsNativeMethod(meth)) {
610 LOGW("Warning: no map available for %s.%s\n",
611 meth->clazz->descriptor, meth->name);
612 /* weird, but keep going */
614 *(*pPtr)++ = kRegMapFormatNone;
618 /* serialize map into the buffer */
619 size_t mapSize = computeRegisterMapSize(meth->registerMap);
620 memcpy(*pPtr, meth->registerMap, mapSize);
622 /* strip the "on heap" flag out of the format byte, which is always first */
623 assert(**pPtr == meth->registerMap->format);
624 **pPtr &= ~(kRegMapFormatOnHeap);
632 * Write maps for all methods in the specified class to the buffer, which
633 * can hold at most "length" bytes. "*pPtr" will be advanced past the end
634 * of the data we write.
636 static bool writeMapsAllMethods(DvmDex* pDvmDex, const ClassObject* clazz,
637 u1** pPtr, size_t length)
639 RegisterMapMethodPool* pMethodPool;
643 /* artificial limit */
644 if (clazz->virtualMethodCount + clazz->directMethodCount >= 65536) {
645 LOGE("Too many methods in %s\n", clazz->descriptor);
649 pMethodPool = (RegisterMapMethodPool*) ptr;
650 ptr += offsetof(RegisterMapMethodPool, methodData);
654 * Run through all methods, direct then virtual. The class loader will
655 * traverse them in the same order. (We could split them into two
656 * distinct pieces, but there doesn't appear to be any value in doing
657 * so other than that it makes class loading slightly less fragile.)
659 * The class loader won't know about miranda methods at the point
660 * where it parses this, so we omit those.
662 * TODO: consider omitting all native/abstract definitions. Should be
663 * safe, though we lose the ability to sanity-check against the
664 * method counts in the DEX file.
666 for (i = 0; i < clazz->directMethodCount; i++) {
667 const Method* meth = &clazz->directMethods[i];
668 if (dvmIsMirandaMethod(meth))
670 if (!writeMapForMethod(&clazz->directMethods[i], &ptr)) {
674 //ptr = align32(ptr);
677 for (i = 0; i < clazz->virtualMethodCount; i++) {
678 const Method* meth = &clazz->virtualMethods[i];
679 if (dvmIsMirandaMethod(meth))
681 if (!writeMapForMethod(&clazz->virtualMethods[i], &ptr)) {
685 //ptr = align32(ptr);
688 pMethodPool->methodCount = methodCount;
695 * Write maps for all classes to the specified buffer, which can hold at
696 * most "length" bytes.
698 * Returns the actual length used, or 0 on failure.
700 static size_t writeMapsAllClasses(DvmDex* pDvmDex, u1* basePtr, size_t length)
702 DexFile* pDexFile = pDvmDex->pDexFile;
703 u4 count = pDexFile->pHeader->classDefsSize;
704 RegisterMapClassPool* pClassPool;
709 assert(gDvm.optimizing);
711 pClassPool = (RegisterMapClassPool*) ptr;
712 ptr += offsetof(RegisterMapClassPool, classDataOffset);
713 offsetTable = (u4*) ptr;
714 ptr += count * sizeof(u4);
716 pClassPool->numClasses = count;
719 * We want an entry for every class, loaded or not.
721 for (idx = 0; idx < count; idx++) {
722 const DexClassDef* pClassDef;
723 const char* classDescriptor;
726 pClassDef = dexGetClassDef(pDexFile, idx);
727 classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
730 * All classes have been loaded into the bootstrap class loader.
731 * If we can find it, and it was successfully pre-verified, we
732 * run through its methods and add the register maps.
734 * If it wasn't pre-verified then we know it can't have any
735 * register maps. Classes that can't be loaded or failed
736 * verification get an empty slot in the index.
739 if ((pClassDef->accessFlags & CLASS_ISPREVERIFIED) != 0)
740 clazz = dvmLookupClass(classDescriptor, NULL, false);
743 offsetTable[idx] = ptr - basePtr;
744 LOGVV("%d -> offset %d (%p-%p)\n",
745 idx, offsetTable[idx], ptr, basePtr);
747 if (!writeMapsAllMethods(pDvmDex, clazz, &ptr,
748 length - (ptr - basePtr)))
754 LOGVV("Size %s (%d+%d methods): %d\n", clazz->descriptor,
755 clazz->directMethodCount, clazz->virtualMethodCount,
756 (ptr - basePtr) - offsetTable[idx]);
758 LOGV("%4d NOT mapadding '%s'\n", idx, classDescriptor);
759 assert(offsetTable[idx] == 0);
763 if (ptr - basePtr >= (int)length) {
765 LOGE("Buffer overrun\n");
769 return ptr - basePtr;
773 * Generate a register map set for all verified classes in "pDvmDex".
775 RegisterMapBuilder* dvmGenerateRegisterMaps(DvmDex* pDvmDex)
777 RegisterMapBuilder* pBuilder;
779 pBuilder = (RegisterMapBuilder*) calloc(1, sizeof(RegisterMapBuilder));
780 if (pBuilder == NULL)
784 * We have a couple of options here:
785 * (1) Compute the size of the output, and malloc a buffer.
786 * (2) Create a "large-enough" anonymous mmap region.
788 * The nice thing about option #2 is that we don't have to traverse
789 * all of the classes and methods twice. The risk is that we might
790 * not make the region large enough. Since the pages aren't mapped
791 * until used we can allocate a semi-absurd amount of memory without
792 * worrying about the effect on the rest of the system.
794 * The basic encoding on the largest jar file requires about 1MB of
795 * storage. We map out 4MB here. (TODO: guarantee that the last
796 * page of the mapping is marked invalid, so we reliably fail if
799 if (sysCreatePrivateMap(4 * 1024 * 1024, &pBuilder->memMap) != 0) {
807 size_t actual = writeMapsAllClasses(pDvmDex, (u1*)pBuilder->memMap.addr,
808 pBuilder->memMap.length);
810 dvmFreeRegisterMapBuilder(pBuilder);
814 LOGV("TOTAL size of register maps: %d\n", actual);
816 pBuilder->data = pBuilder->memMap.addr;
817 pBuilder->size = actual;
824 void dvmFreeRegisterMapBuilder(RegisterMapBuilder* pBuilder)
826 if (pBuilder == NULL)
829 sysReleaseShmem(&pBuilder->memMap);
835 * Find the data for the specified class.
837 * If there's no register map data, or none for this class, we return NULL.
839 const void* dvmRegisterMapGetClassData(const DexFile* pDexFile, u4 classIdx,
842 const RegisterMapClassPool* pClassPool;
843 const RegisterMapMethodPool* pMethodPool;
845 pClassPool = (const RegisterMapClassPool*) pDexFile->pRegisterMapPool;
846 if (pClassPool == NULL)
849 if (classIdx >= pClassPool->numClasses) {
850 LOGE("bad class index (%d vs %d)\n", classIdx, pClassPool->numClasses);
854 u4 classOffset = pClassPool->classDataOffset[classIdx];
855 if (classOffset == 0) {
856 LOGV("+++ no map for classIdx=%d\n", classIdx);
861 (const RegisterMapMethodPool*) (((u1*) pClassPool) + classOffset);
862 if (pNumMaps != NULL)
863 *pNumMaps = pMethodPool->methodCount;
864 return pMethodPool->methodData;
868 * This advances "*pPtr" and returns its original value.
870 const RegisterMap* dvmRegisterMapGetNext(const void** pPtr)
872 const RegisterMap* pMap = *pPtr;
874 *pPtr = /*align32*/(((u1*) pMap) + computeRegisterMapSize(pMap));
875 LOGVV("getNext: %p -> %p (f=0x%x w=%d e=%d)\n",
876 pMap, *pPtr, pMap->format, pMap->regWidth,
877 dvmRegisterMapGetNumEntries(pMap));
883 * ===========================================================================
885 * ===========================================================================
889 * Return the data for the specified address, or NULL if not found.
891 * The result must be released with dvmReleaseRegisterMapLine().
893 const u1* dvmRegisterMapGetLine(const RegisterMap* pMap, int addr)
895 int addrWidth, lineWidth;
896 u1 format = dvmRegisterMapGetFormat(pMap);
897 u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
899 assert(numEntries > 0);
902 case kRegMapFormatNone:
904 case kRegMapFormatCompact8:
907 case kRegMapFormatCompact16:
911 LOGE("Unknown format %d\n", format);
916 lineWidth = addrWidth + pMap->regWidth;
919 * Find the appropriate entry. Many maps are very small, some are very
922 static const int kSearchThreshold = 8;
923 const u1* data = NULL;
926 if (numEntries < kSearchThreshold) {
929 for (i = numEntries; i > 0; i--) {
932 lineAddr |= data[1] << 8;
933 if (lineAddr == addr)
934 return data + addrWidth;
938 assert(data == pMap->data + lineWidth * numEntries);
947 data = pMap->data + lineWidth * mid;
951 lineAddr |= data[1] << 8;
953 if (addr > lineAddr) {
955 } else if (addr < lineAddr) {
958 return data + addrWidth;
967 * Compare two register maps.
969 * Returns 0 if they're equal, nonzero if not.
971 static int compareMaps(const RegisterMap* pMap1, const RegisterMap* pMap2)
975 size1 = computeRegisterMapSize(pMap1);
976 size2 = computeRegisterMapSize(pMap2);
977 if (size1 != size2) {
978 LOGI("compareMaps: size mismatch (%zd vs %zd)\n", size1, size2);
982 if (memcmp(pMap1, pMap2, size1) != 0) {
983 LOGI("compareMaps: content mismatch\n");
992 * Get the expanded form of the register map associated with the method.
994 * If the map is already in one of the uncompressed formats, we return
995 * immediately. Otherwise, we expand the map and replace method's register
996 * map pointer, freeing it if it was allocated on the heap.
998 * NOTE: this function is not synchronized; external locking is mandatory
999 * (unless we're in the zygote, where single-threaded access is guaranteed).
1001 const RegisterMap* dvmGetExpandedRegisterMap0(Method* method)
1003 const RegisterMap* curMap = method->registerMap;
1004 RegisterMap* newMap;
1009 /* sanity check to ensure this isn't called w/o external locking */
1010 /* (if we use this at a time other than during GC, fix/remove this test) */
1012 if (!gDvm.zygote && dvmTryLockMutex(&gDvm.gcHeapLock) == 0) {
1013 LOGE("GLITCH: dvmGetExpandedRegisterMap not called at GC time\n");
1018 RegisterMapFormat format = dvmRegisterMapGetFormat(curMap);
1020 case kRegMapFormatCompact8:
1021 case kRegMapFormatCompact16:
1022 if (REGISTER_MAP_VERBOSE) {
1023 if (dvmRegisterMapGetOnHeap(curMap)) {
1024 LOGD("RegMap: already expanded: %s.%s\n",
1025 method->clazz->descriptor, method->name);
1027 LOGD("RegMap: stored w/o compression: %s.%s\n",
1028 method->clazz->descriptor, method->name);
1032 case kRegMapFormatDifferential:
1033 newMap = uncompressMapDifferential(curMap);
1036 LOGE("Unknown format %d in dvmGetExpandedRegisterMap\n", format);
1038 newMap = NULL; // make gcc happy
1041 if (newMap == NULL) {
1042 LOGE("Map failed to uncompress (fmt=%d) %s.%s\n",
1043 format, method->clazz->descriptor, method->name);
1047 #ifdef REGISTER_MAP_STATS
1049 * Gather and display some stats.
1052 MapStats* pStats = (MapStats*) gDvm.registerMapStats;
1053 pStats->numExpandedMaps++;
1054 pStats->totalExpandedMapSize += computeRegisterMapSize(newMap);
1055 LOGD("RMAP: count=%d size=%d\n",
1056 pStats->numExpandedMaps, pStats->totalExpandedMapSize);
1061 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1062 LOGV("Expanding map -> %s.%s:%s\n",
1063 method->clazz->descriptor, method->name, desc);
1068 * Update method, and free compressed map if it was sitting on the heap.
1070 dvmSetRegisterMap(method, newMap);
1072 if (dvmRegisterMapGetOnHeap(curMap))
1073 dvmFreeRegisterMap((RegisterMap*) curMap);
1080 * ===========================================================================
1082 * ===========================================================================
1086 Notes on map compression
1088 The idea is to create a compressed form that will be uncompressed before
1089 use, with the output possibly saved in a cache. This means we can use an
1090 approach that is unsuited for random access if we choose.
1092 In the event that a map simply does not work with our compression scheme,
1093 it's reasonable to store the map without compression. In the future we
1094 may want to have more than one compression scheme, and try each in turn,
1095 retaining the best. (We certainly want to keep the uncompressed form if it
1096 turns out to be smaller or even slightly larger than the compressed form.)
1098 Each entry consists of an address and a bit vector. Adjacent entries are
1099 strongly correlated, suggesting differential encoding.
1102 Ideally we would avoid outputting adjacent entries with identical
1103 bit vectors. However, the register values at a given address do not
1104 imply anything about the set of valid registers at subsequent addresses.
1105 We therefore cannot omit an entry.
1107 If the thread stack has a PC at an address without a corresponding
1108 entry in the register map, we must conservatively scan the registers in
1109 that thread. This can happen when single-stepping in the debugger,
1110 because the debugger is allowed to invoke arbitrary methods when
1111 a thread is stopped at a breakpoint. If we can guarantee that a GC
1112 thread scan will never happen while the debugger has that thread stopped,
1113 then we can lift this restriction and simply omit entries that don't
1114 change the bit vector from its previous state.
1116 Each entry advances the address value by at least 1 (measured in 16-bit
1117 "code units"). Looking at the bootclasspath entries, advancing by 2 units
1118 is most common. Advances by 1 unit are far less common than advances by
1119 2 units, but more common than 5, and things fall off rapidly. Gaps of
1120 up to 220 code units appear in some computationally intensive bits of code,
1121 but are exceedingly rare.
1123 If we sum up the number of transitions in a couple of ranges in framework.jar:
1124 [1,4]: 188998 of 218922 gaps (86.3%)
1125 [1,7]: 211647 of 218922 gaps (96.7%)
1126 Using a 3-bit delta, with one value reserved as an escape code, should
1127 yield good results for the address.
1129 These results would change dramatically if we reduced the set of GC
1130 points by e.g. removing instructions like integer divide that are only
1131 present because they can throw and cause an allocation.
1133 We also need to include an "initial gap", because the first few instructions
1134 in a method may not be GC points.
1137 By observation, many entries simply repeat the previous bit vector, or
1138 change only one or two bits. (This is with type-precise information;
1139 the rate of change of bits will be different if live-precise information
1142 Looking again at adjacent entries in framework.jar:
1143 0 bits changed: 63.0%
1144 1 bit changed: 32.2%
1145 After that it falls off rapidly, e.g. the number of entries with 2 bits
1146 changed is usually less than 1/10th of the number of entries with 1 bit
1147 changed. A solution that allows us to encode 0- or 1- bit changes
1148 efficiently will do well.
1150 We still need to handle cases where a large number of bits change. We
1151 probably want a way to drop in a full copy of the bit vector when it's
1152 smaller than the representation of multiple bit changes.
1155 The bit-change information can be encoded as an index that tells the
1156 decoder to toggle the state. We want to encode the index in as few bits
1157 as possible, but we need to allow for fairly wide vectors (e.g. we have a
1158 method with 175 registers). We can deal with this in a couple of ways:
1159 (1) use an encoding that assumes few registers and has an escape code
1160 for larger numbers of registers; or (2) use different encodings based
1161 on how many total registers the method has. The choice depends to some
1162 extent on whether methods with large numbers of registers tend to modify
1163 the first 16 regs more often than the others.
1165 The last N registers hold method arguments. If the bytecode is expected
1166 to be examined in a debugger, "dx" ensures that the contents of these
1167 registers won't change. Depending upon the encoding format, we may be
1168 able to take advantage of this. We still have to encode the initial
1169 state, but we know we'll never have to output a bit change for the last
1172 Considering only methods with 16 or more registers, the "target octant"
1173 for register changes looks like this:
1174 [ 43.1%, 16.4%, 6.5%, 6.2%, 7.4%, 8.8%, 9.7%, 1.8% ]
1175 As expected, there are fewer changes at the end of the list where the
1176 arguments are kept, and more changes at the start of the list because
1177 register values smaller than 16 can be used in compact Dalvik instructions
1178 and hence are favored for frequently-used values. In general, the first
1179 octant is considerably more active than later entries, the last octant
1180 is much less active, and the rest are all about the same.
1182 Looking at all bit changes in all methods, 94% are to registers 0-15. The
1183 encoding will benefit greatly by favoring the low-numbered registers.
1186 Some of the smaller methods have identical maps, and space could be
1187 saved by simply including a pointer to an earlier definition. This would
1188 be best accomplished by specifying a "pointer" format value, followed by
1189 a 3-byte (or ULEB128) offset. Implementing this would probably involve
1190 generating a hash value for each register map and maintaining a hash table.
1192 In some cases there are repeating patterns in the bit vector that aren't
1193 adjacent. These could benefit from a dictionary encoding. This doesn't
1194 really become useful until the methods reach a certain size though,
1195 and managing the dictionary may incur more overhead than we want.
1197 Large maps can be compressed significantly. The trouble is that, when
1198 we need to use them, we have to uncompress them onto the heap. We may
1199 get a better trade-off between storage size and heap usage by refusing to
1200 compress large maps, so that they can be memory mapped and used directly.
1201 (OTOH, only about 2% of the maps will ever actually be used.)
1204 ----- differential format -----
1209 +02 2B numEntries (little-endian)
1210 +04 nB length in bytes of the data that follows, in ULEB128 format
1211 (not strictly necessary; allows determination of size w/o full parse)
1212 +05+ 1B initial address (0-127), high bit set if max addr >= 256
1213 +06+ nB initial value for bit vector
1218 AAA: address difference. Values from 0 to 6 indicate an increment of 1
1219 to 7. A value of 7 indicates that the address difference is large,
1220 and the next byte is a ULEB128-encoded difference value.
1222 B: determines the meaning of CCCC.
1224 CCCC: if B is 0, this is the number of the bit to toggle (0-15).
1225 If B is 1, this is a count of the number of changed bits (1-14). A value
1226 of 0 means that no bits were changed, and a value of 15 indicates
1227 that enough bits were changed that it required less space to output
1228 the entire bit vector.
1230 +01: (optional) ULEB128-encoded address difference
1232 +01+: (optional) one or more ULEB128-encoded bit numbers, OR the entire
1235 The most common situation is an entry whose address has changed by 2-4
1236 code units, has no changes or just a single bit change, and the changed
1237 register is less than 16. We should therefore be able to encode a large
1238 number of entries with a single byte, which is half the size of the
1239 Compact8 encoding method.
1243 * Compute some stats on an uncompressed register map.
1245 #ifdef REGISTER_MAP_STATS
1246 static void computeMapStats(RegisterMap* pMap, const Method* method)
1248 MapStats* pStats = (MapStats*) gDvm.registerMapStats;
1249 const u1 format = dvmRegisterMapGetFormat(pMap);
1250 const u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
1251 const u1* rawMap = pMap->data;
1252 const u1* prevData = NULL;
1253 int ent, addr, prevAddr = -1;
1255 for (ent = 0; ent < numEntries; ent++) {
1257 case kRegMapFormatCompact8:
1260 case kRegMapFormatCompact16:
1262 addr |= (*rawMap++) << 8;
1265 /* shouldn't happen */
1266 LOGE("GLITCH: bad format (%d)", format);
1270 const u1* dataStart = rawMap;
1272 pStats->totalGcPointCount++;
1275 * Gather "gap size" stats, i.e. the difference in addresses between
1276 * successive GC points.
1278 if (prevData != NULL) {
1279 assert(prevAddr >= 0);
1280 int addrDiff = addr - prevAddr;
1283 LOGE("GLITCH: address went backward (0x%04x->0x%04x, %s.%s)\n",
1284 prevAddr, addr, method->clazz->descriptor, method->name);
1285 } else if (addrDiff > kMaxGcPointGap) {
1286 if (REGISTER_MAP_VERBOSE) {
1287 LOGI("HEY: addrDiff is %d, max %d (0x%04x->0x%04x %s.%s)\n",
1288 addrDiff, kMaxGcPointGap, prevAddr, addr,
1289 method->clazz->descriptor, method->name);
1293 pStats->gcPointGap[addrDiff]++;
1295 pStats->gcGapCount++;
1299 * Compare bit vectors in adjacent entries. We want to count
1300 * up the number of bits that differ (to see if we frequently
1301 * change 0 or 1 bits) and get a sense for which part of the
1302 * vector changes the most often (near the start, middle, end).
1304 * We only do the vector position quantization if we have at
1305 * least 16 registers in the method.
1308 float div = (float) kNumUpdatePosns / method->registersSize;
1310 for (regByte = 0; regByte < pMap->regWidth; regByte++) {
1313 prev = prevData[regByte];
1314 cur = dataStart[regByte];
1316 for (bit = 0; bit < 8; bit++) {
1317 if (((prev >> bit) & 1) != ((cur >> bit) & 1)) {
1320 int bitNum = regByte * 8 + bit;
1323 pStats->updateLT16++;
1325 pStats->updateGE16++;
1327 if (method->registersSize < 16)
1330 if (bitNum >= method->registersSize) {
1331 /* stuff off the end should be zero in both */
1332 LOGE("WEIRD: bit=%d (%d/%d), prev=%02x cur=%02x\n",
1333 bit, regByte, method->registersSize,
1337 int idx = (int) (bitNum * div);
1338 if (!(idx >= 0 && idx < kNumUpdatePosns)) {
1339 LOGE("FAIL: bitNum=%d (of %d) div=%.3f idx=%d\n",
1340 bitNum, method->registersSize, div, idx);
1343 pStats->updatePosn[idx]++;
1348 if (numDiff > kMaxDiffBits) {
1349 if (REGISTER_MAP_VERBOSE) {
1350 LOGI("WOW: numDiff is %d, max %d\n", numDiff, kMaxDiffBits);
1353 pStats->numDiffBits[numDiff]++;
1357 /* advance to start of next line */
1358 rawMap += pMap->regWidth;
1361 prevData = dataStart;
1367 * Compute the difference between two bit vectors.
1369 * If "lebOutBuf" is non-NULL, we output the bit indices in ULEB128 format
1370 * as we go. Otherwise, we just generate the various counts.
1372 * The bit vectors are compared byte-by-byte, so any unused bits at the
1375 * Returns the number of bytes required to hold the ULEB128 output.
1377 * If "pFirstBitChanged" or "pNumBitsChanged" are non-NULL, they will
1378 * receive the index of the first changed bit and the number of changed
1379 * bits, respectively.
1381 static int computeBitDiff(const u1* bits1, const u1* bits2, int byteWidth,
1382 int* pFirstBitChanged, int* pNumBitsChanged, u1* lebOutBuf)
1384 int numBitsChanged = 0;
1385 int firstBitChanged = -1;
1390 * Run through the vectors, first comparing them at the byte level. This
1391 * will yield a fairly quick result if nothing has changed between them.
1393 for (byteNum = 0; byteNum < byteWidth; byteNum++) {
1394 u1 byte1 = *bits1++;
1395 u1 byte2 = *bits2++;
1396 if (byte1 != byte2) {
1398 * Walk through the byte, identifying the changed bits.
1401 for (bitNum = 0; bitNum < 8; bitNum++) {
1402 if (((byte1 >> bitNum) & 0x01) != ((byte2 >> bitNum) & 0x01)) {
1403 int bitOffset = (byteNum << 3) + bitNum;
1405 if (firstBitChanged < 0)
1406 firstBitChanged = bitOffset;
1409 if (lebOutBuf == NULL) {
1410 lebSize += unsignedLeb128Size(bitOffset);
1412 u1* curBuf = lebOutBuf;
1413 lebOutBuf = writeUnsignedLeb128(lebOutBuf, bitOffset);
1414 lebSize += lebOutBuf - curBuf;
1421 if (numBitsChanged > 0)
1422 assert(firstBitChanged >= 0);
1424 if (pFirstBitChanged != NULL)
1425 *pFirstBitChanged = firstBitChanged;
1426 if (pNumBitsChanged != NULL)
1427 *pNumBitsChanged = numBitsChanged;
1433 * Compress the register map with differential encoding.
1435 * "meth" is only needed for debug output.
1437 * On success, returns a newly-allocated RegisterMap. If the map is not
1438 * compatible for some reason, or fails to get smaller, this will return NULL.
1440 static RegisterMap* compressMapDifferential(const RegisterMap* pMap,
1443 RegisterMap* pNewMap = NULL;
1444 int origSize = computeRegisterMapSize(pMap);
1447 int addrWidth, regWidth, numEntries;
1451 strcmp(meth->clazz->descriptor, "Landroid/text/StaticLayout;") == 0 &&
1452 strcmp(meth->name, "generate") == 0)
1457 u1 format = dvmRegisterMapGetFormat(pMap);
1459 case kRegMapFormatCompact8:
1462 case kRegMapFormatCompact16:
1466 LOGE("ERROR: can't compress map with format=%d\n", format);
1470 regWidth = dvmRegisterMapGetRegWidth(pMap);
1471 numEntries = dvmRegisterMapGetNumEntries(pMap);
1474 LOGI("COMPRESS: %s.%s aw=%d rw=%d ne=%d\n",
1475 meth->clazz->descriptor, meth->name,
1476 addrWidth, regWidth, numEntries);
1477 dumpRegisterMap(pMap, -1);
1480 if (numEntries <= 1) {
1481 LOGV("Can't compress map with 0 or 1 entries\n");
1486 * We don't know how large the compressed data will be. It's possible
1487 * for it to expand and become larger than the original. The header
1488 * itself is variable-sized, so we generate everything into a temporary
1489 * buffer and then copy it to form-fitting storage once we know how big
1490 * it will be (and that it's smaller than the original).
1492 * If we use a size that is equal to the size of the input map plus
1493 * a value longer than a single entry can possibly expand to, we need
1494 * only check for overflow at the end of each entry. The worst case
1495 * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
1496 * Addresses are 16 bits, so that's (1 + 3 + regWidth).
1498 * The initial address offset and bit vector will take up less than
1499 * or equal to the amount of space required when uncompressed -- large
1500 * initial offsets are rejected.
1502 tmpBuf = (u1*) malloc(origSize + (1 + 3 + regWidth));
1508 const u1* mapData = pMap->data;
1514 addr |= (*mapData++) << 8;
1517 LOGV("Can't compress map with starting address >= 128\n");
1522 * Start by writing the initial address and bit vector data. The high
1523 * bit of the initial address is used to indicate the required address
1524 * width (which the decoder can't otherwise determine without parsing
1525 * the compressed data).
1527 *tmpPtr++ = addr | (addrWidth > 1 ? 0x80 : 0x00);
1528 memcpy(tmpPtr, mapData, regWidth);
1534 mapData += regWidth;
1537 * Loop over all following entries.
1540 for (entry = 1; entry < numEntries; entry++) {
1545 * Pull out the address and figure out how to encode it.
1549 addr |= (*mapData++) << 8;
1552 LOGI(" addr=0x%04x ent=%d (aw=%d)\n", addr, entry, addrWidth);
1554 addrDiff = addr - prevAddr;
1555 assert(addrDiff > 0);
1557 /* small difference, encode in 3 bits */
1558 key = addrDiff -1; /* set 00000AAA */
1560 LOGI(" : small %d, key=0x%02x\n", addrDiff, key);
1562 /* large difference, output escape code */
1563 key = 0x07; /* escape code for AAA */
1565 LOGI(" : large %d, key=0x%02x\n", addrDiff, key);
1568 int numBitsChanged, firstBitChanged, lebSize;
1570 lebSize = computeBitDiff(prevBits, mapData, regWidth,
1571 &firstBitChanged, &numBitsChanged, NULL);
1574 LOGI(" : diff fbc=%d nbc=%d ls=%d (rw=%d)\n",
1575 firstBitChanged, numBitsChanged, lebSize, regWidth);
1578 if (numBitsChanged == 0) {
1579 /* set B to 1 and CCCC to zero to indicate no bits were changed */
1581 if (debug) LOGI(" : no bits changed\n");
1582 } else if (numBitsChanged == 1 && firstBitChanged < 16) {
1583 /* set B to 0 and CCCC to the index of the changed bit */
1584 key |= firstBitChanged << 4;
1585 if (debug) LOGI(" : 1 low bit changed\n");
1586 } else if (numBitsChanged < 15 && lebSize < regWidth) {
1587 /* set B to 1 and CCCC to the number of bits */
1588 key |= 0x08 | (numBitsChanged << 4);
1589 if (debug) LOGI(" : some bits changed\n");
1591 /* set B to 1 and CCCC to 0x0f so we store the entire vector */
1593 if (debug) LOGI(" : encode original\n");
1597 * Encode output. Start with the key, follow with the address
1598 * diff (if it didn't fit in 3 bits), then the changed bit info.
1601 if ((key & 0x07) == 0x07)
1602 tmpPtr = writeUnsignedLeb128(tmpPtr, addrDiff);
1604 if ((key & 0x08) != 0) {
1605 int bitCount = key >> 4;
1606 if (bitCount == 0) {
1607 /* nothing changed, no additional output required */
1608 } else if (bitCount == 15) {
1609 /* full vector is most compact representation */
1610 memcpy(tmpPtr, mapData, regWidth);
1613 /* write bit indices in LEB128 format */
1614 (void) computeBitDiff(prevBits, mapData, regWidth,
1615 NULL, NULL, tmpPtr);
1619 /* single-bit changed, value encoded in key byte */
1624 mapData += regWidth;
1627 * See if we've run past the original size.
1629 if (tmpPtr - tmpBuf >= origSize) {
1631 LOGD("Compressed size >= original (%d vs %d): %s.%s\n",
1632 tmpPtr - tmpBuf, origSize,
1633 meth->clazz->descriptor, meth->name);
1640 * Create a RegisterMap with the contents.
1642 * TODO: consider using a threshold other than merely ">=". We would
1643 * get poorer compression but potentially use less native heap space.
1645 static const int kHeaderSize = offsetof(RegisterMap, data);
1646 int newDataSize = tmpPtr - tmpBuf;
1649 newMapSize = kHeaderSize + unsignedLeb128Size(newDataSize) + newDataSize;
1650 if (newMapSize >= origSize) {
1652 LOGD("Final comp size >= original (%d vs %d): %s.%s\n",
1653 newMapSize, origSize, meth->clazz->descriptor, meth->name);
1658 pNewMap = (RegisterMap*) malloc(newMapSize);
1659 if (pNewMap == NULL)
1661 dvmRegisterMapSetFormat(pNewMap, kRegMapFormatDifferential);
1662 dvmRegisterMapSetOnHeap(pNewMap, true);
1663 dvmRegisterMapSetRegWidth(pNewMap, regWidth);
1664 dvmRegisterMapSetNumEntries(pNewMap, numEntries);
1666 tmpPtr = pNewMap->data;
1667 tmpPtr = writeUnsignedLeb128(tmpPtr, newDataSize);
1668 memcpy(tmpPtr, tmpBuf, newDataSize);
1670 if (REGISTER_MAP_VERBOSE) {
1671 LOGD("Compression successful (%d -> %d) from aw=%d rw=%d ne=%d\n",
1672 computeRegisterMapSize(pMap), computeRegisterMapSize(pNewMap),
1673 addrWidth, regWidth, numEntries);
1682 * Toggle the value of the "idx"th bit in "ptr".
1684 static inline void toggleBit(u1* ptr, int idx)
1686 ptr[idx >> 3] ^= 1 << (idx & 0x07);
1690 * Expand a compressed map to an uncompressed form.
1692 * Returns a newly-allocated RegisterMap on success, or NULL on failure.
1694 * TODO: consider using the linear allocator or a custom allocator with
1695 * LRU replacement for these instead of the native heap.
1697 static RegisterMap* uncompressMapDifferential(const RegisterMap* pMap)
1699 RegisterMap* pNewMap = NULL;
1700 static const int kHeaderSize = offsetof(RegisterMap, data);
1701 u1 format = dvmRegisterMapGetFormat(pMap);
1702 RegisterMapFormat newFormat;
1703 int regWidth, numEntries, newAddrWidth, newMapSize;
1705 if (format != kRegMapFormatDifferential) {
1706 LOGE("Not differential (%d)\n", format);
1710 regWidth = dvmRegisterMapGetRegWidth(pMap);
1711 numEntries = dvmRegisterMapGetNumEntries(pMap);
1713 /* get the data size; we can check this at the end */
1714 const u1* srcPtr = pMap->data;
1715 int expectedSrcLen = readUnsignedLeb128(&srcPtr);
1716 const u1* srcStart = srcPtr;
1718 /* get the initial address and the 16-bit address flag */
1719 int addr = *srcPtr & 0x7f;
1720 if ((*srcPtr & 0x80) == 0) {
1721 newFormat = kRegMapFormatCompact8;
1724 newFormat = kRegMapFormatCompact16;
1729 /* now we know enough to allocate the new map */
1730 if (REGISTER_MAP_VERBOSE) {
1731 LOGI("Expanding to map aw=%d rw=%d ne=%d\n",
1732 newAddrWidth, regWidth, numEntries);
1734 newMapSize = kHeaderSize + (newAddrWidth + regWidth) * numEntries;
1735 pNewMap = (RegisterMap*) malloc(newMapSize);
1736 if (pNewMap == NULL)
1739 dvmRegisterMapSetFormat(pNewMap, newFormat);
1740 dvmRegisterMapSetOnHeap(pNewMap, true);
1741 dvmRegisterMapSetRegWidth(pNewMap, regWidth);
1742 dvmRegisterMapSetNumEntries(pNewMap, numEntries);
1745 * Write the start address and initial bits to the new map.
1747 u1* dstPtr = pNewMap->data;
1749 *dstPtr++ = addr & 0xff;
1750 if (newAddrWidth > 1)
1751 *dstPtr++ = (u1) (addr >> 8);
1753 memcpy(dstPtr, srcPtr, regWidth);
1755 int prevAddr = addr;
1756 const u1* prevBits = dstPtr; /* point at uncompressed data */
1762 * Walk through, uncompressing one line at a time.
1765 for (entry = 1; entry < numEntries; entry++) {
1771 /* get the address */
1772 if ((key & 0x07) == 7) {
1773 /* address diff follows in ULEB128 */
1774 addrDiff = readUnsignedLeb128(&srcPtr);
1776 addrDiff = (key & 0x07) +1;
1779 addr = prevAddr + addrDiff;
1780 *dstPtr++ = addr & 0xff;
1781 if (newAddrWidth > 1)
1782 *dstPtr++ = (u1) (addr >> 8);
1784 /* unpack the bits */
1785 if ((key & 0x08) != 0) {
1786 int bitCount = (key >> 4);
1787 if (bitCount == 0) {
1788 /* no bits changed, just copy previous */
1789 memcpy(dstPtr, prevBits, regWidth);
1790 } else if (bitCount == 15) {
1791 /* full copy of bit vector is present; ignore prevBits */
1792 memcpy(dstPtr, srcPtr, regWidth);
1795 /* copy previous bits and modify listed indices */
1796 memcpy(dstPtr, prevBits, regWidth);
1797 while (bitCount--) {
1798 int bitIndex = readUnsignedLeb128(&srcPtr);
1799 toggleBit(dstPtr, bitIndex);
1803 /* copy previous bits and modify the specified one */
1804 memcpy(dstPtr, prevBits, regWidth);
1806 /* one bit, from 0-15 inclusive, was changed */
1807 toggleBit(dstPtr, key >> 4);
1815 if (dstPtr - (u1*) pNewMap != newMapSize) {
1816 LOGE("ERROR: output %d bytes, expected %d\n",
1817 dstPtr - (u1*) pNewMap, newMapSize);
1821 if (srcPtr - srcStart != expectedSrcLen) {
1822 LOGE("ERROR: consumed %d bytes, expected %d\n",
1823 srcPtr - srcStart, expectedSrcLen);
1827 if (REGISTER_MAP_VERBOSE) {
1828 LOGD("Expansion successful (%d -> %d)\n",
1829 computeRegisterMapSize(pMap), computeRegisterMapSize(pNewMap));
1841 * ===========================================================================
1842 * Just-in-time generation
1843 * ===========================================================================
1846 #if 0 /* incomplete implementation; may be removed entirely in the future */
1849 Notes on just-in-time RegisterMap generation
1851 Generating RegisterMap tables as part of verification is convenient because
1852 we generate most of what we need to know as part of doing the verify.
1853 The negative aspect of doing it this way is that we must store the
1854 result in the DEX file (if we're verifying ahead of time) or in memory
1855 (if verifying during class load) for every concrete non-native method,
1856 even if we never actually need the map during a GC.
1858 A simple but compact encoding of register map data increases the size of
1859 optimized DEX files by about 25%, so size considerations are important.
1861 We can instead generate the RegisterMap at the point where it is needed.
1862 In a typical application we only need to convert about 2% of the loaded
1863 methods, and we can generate type-precise roots reasonably quickly because
1864 (a) we know the method has already been verified and hence can make a
1865 lot of assumptions, and (b) we don't care what type of object a register
1866 holds, just whether or not it holds a reference, and hence can skip a
1867 lot of class resolution gymnastics.
1869 There are a couple of problems with this approach however. First, to
1870 get good performance we really want an implementation that is largely
1871 independent from the verifier, which means some duplication of effort.
1872 Second, we're dealing with post-dexopt code, which contains "quickened"
1873 instructions. We can't process those without either tracking type
1874 information (which slows us down) or storing additional data in the DEX
1875 file that allows us to reconstruct the original instructions (adds ~5%
1876 to the size of the ODEX).
1879 Implementation notes...
1881 Both type-precise and live-precise information can be generated knowing
1882 only whether or not a register holds a reference. We don't need to
1883 know what kind of reference or whether the object has been initialized.
1884 Not only can we skip many of the fancy steps in the verifier, we can
1885 initialize from simpler sources, e.g. the initial registers and return
1886 type are set from the "shorty" signature rather than the full signature.
1888 The short-term storage needs for just-in-time register map generation can
1889 be much lower because we can use a 1-byte SRegType instead of a 4-byte
1890 RegType. On the other hand, if we're not doing type-precise analysis
1891 in the verifier we only need to store register contents at every branch
1892 target, rather than every GC point (which are much more frequent).
1894 Whether it happens in the verifier or independently, because this is done
1895 with native heap allocations that may be difficult to return to the system,
1896 an effort should be made to minimize memory use.
1900 * This is like RegType in the verifier, but simplified. It holds a value
1901 * from the reg type enum, or kRegTypeReference.
1903 typedef u1 SRegType;
1904 #define kRegTypeReference kRegTypeMAX
1907 * We need an extra "pseudo register" to hold the return type briefly. It
1908 * can be category 1 or 2, so we need two slots.
1910 #define kExtraRegs 2
1911 #define RESULT_REGISTER(_insnRegCountPlus) (_insnRegCountPlus - kExtraRegs)
1916 typedef struct WorkState {
1918 * The method we're working on.
1920 const Method* method;
1923 * Number of instructions in the method.
1928 * Number of registers we track for each instruction. This is equal
1929 * to the method's declared "registersSize" plus kExtraRegs.
1931 int insnRegCountPlus;
1934 * Instruction widths and flags, one entry per code unit.
1936 InsnFlags* insnFlags;
1939 * Array of SRegType arrays, one entry per code unit. We only need
1940 * to create an entry when an instruction starts at this address.
1941 * We can further reduce this to instructions that are GC points.
1943 * We could just go ahead and allocate one per code unit, but for
1944 * larger methods that can represent a significant bit of short-term
1947 SRegType** addrRegs;
1950 * A single large alloc, with all of the storage needed for addrRegs.
1956 static bool generateMap(WorkState* pState, RegisterMap* pMap);
1957 static bool analyzeMethod(WorkState* pState);
1958 static bool handleInstruction(WorkState* pState, SRegType* workRegs,\
1959 int insnIdx, int* pStartGuess);
1960 static void updateRegisters(WorkState* pState, int nextInsn,\
1961 const SRegType* workRegs);
1965 * Set instruction flags.
1967 static bool setInsnFlags(WorkState* pState, int* pGcPointCount)
1969 const Method* meth = pState->method;
1970 InsnFlags* insnFlags = pState->insnFlags;
1971 int insnsSize = pState->insnsSize;
1972 const u2* insns = meth->insns;
1973 int gcPointCount = 0;
1976 /* set the widths */
1977 if (!dvmComputeCodeWidths(meth, pState->insnFlags, NULL))
1980 /* mark "try" regions and exception handler branch targets */
1981 if (!dvmSetTryFlags(meth, pState->insnFlags))
1984 /* the start of the method is a "branch target" */
1985 dvmInsnSetBranchTarget(insnFlags, 0, true);
1988 * Run through the instructions, looking for switches and branches.
1989 * Mark their targets.
1991 * We don't really need to "check" these instructions -- the verifier
1992 * already did that -- but the additional overhead isn't significant
1993 * enough to warrant making a second copy of the "Check" function.
1995 * Mark and count GC points while we're at it.
1997 for (offset = 0; offset < insnsSize; offset++) {
1998 static int gcMask = kInstrCanBranch | kInstrCanSwitch |
1999 kInstrCanThrow | kInstrCanReturn;
2000 u1 opcode = insns[offset] & 0xff;
2001 InstructionFlags opFlags = dexGetInstrFlags(gDvm.instrFlags, opcode);
2003 if (opFlags & kInstrCanBranch) {
2004 if (!dvmCheckBranchTarget(meth, insnFlags, offset, true))
2007 if (opFlags & kInstrCanSwitch) {
2008 if (!dvmCheckSwitchTargets(meth, insnFlags, offset))
2012 if ((opFlags & gcMask) != 0) {
2013 dvmInsnSetGcPoint(pState->insnFlags, offset, true);
2018 *pGcPointCount = gcPointCount;
2023 * Generate the register map for a method.
2025 * Returns a pointer to newly-allocated storage.
2027 RegisterMap* dvmGenerateRegisterMap(const Method* meth)
2029 WorkState* pState = NULL;
2030 RegisterMap* pMap = NULL;
2031 RegisterMap* result = NULL;
2034 pState = (WorkState*) calloc(1, sizeof(WorkState));
2038 pMap = (RegisterMap*) calloc(1, sizeof(RegisterMap));
2042 pState->method = meth;
2043 pState->insnsSize = dvmGetMethodInsnsSize(meth);
2044 pState->insnRegCountPlus = meth->registersSize + kExtraRegs;
2046 pState->insnFlags = calloc(sizeof(InsnFlags), pState->insnsSize);
2047 pState->addrRegs = calloc(sizeof(SRegType*), pState->insnsSize);
2050 * Set flags on instructions, and calculate the number of code units
2051 * that happen to be GC points.
2054 if (!setInsnFlags(pState, &gcPointCount))
2057 if (gcPointCount == 0) {
2058 /* the method doesn't allocate or call, and never returns? unlikely */
2059 LOG_VFY_METH(meth, "Found do-nothing method\n");
2063 pState->regAlloc = (SRegType*)
2064 calloc(sizeof(SRegType), pState->insnsSize * gcPointCount);
2065 regPtr = pState->regAlloc;
2068 * For each instruction that is a GC point, set a pointer into the
2072 for (offset = 0; offset < pState->insnsSize; offset++) {
2073 if (dvmInsnIsGcPoint(pState->insnFlags, offset)) {
2074 pState->addrRegs[offset] = regPtr;
2075 regPtr += pState->insnRegCountPlus;
2078 assert(regPtr - pState->regAlloc == pState->insnsSize * gcPointCount);
2079 assert(pState->addrRegs[0] != NULL);
2082 * Compute the register map.
2084 if (!generateMap(pState, pMap))
2092 if (pState != NULL) {
2093 free(pState->insnFlags);
2094 free(pState->addrRegs);
2095 free(pState->regAlloc);
2099 dvmFreeRegisterMap(pMap);
2104 * Release the storage associated with a RegisterMap.
2106 void dvmFreeRegisterMap(RegisterMap* pMap)
2114 * Create the RegisterMap using the provided state.
2116 static bool generateMap(WorkState* pState, RegisterMap* pMap)
2118 bool result = false;
2121 * Analyze the method and store the results in WorkState.
2123 if (!analyzeMethod(pState))
2127 * Convert the analyzed data into a RegisterMap.
2138 * Set the register types for the method arguments. We can pull the values
2139 * out of the "shorty" signature.
2141 static bool setTypesFromSignature(WorkState* pState)
2143 const Method* meth = pState->method;
2144 int argReg = meth->registersSize - meth->insSize; /* first arg */
2145 SRegType* pRegs = pState->addrRegs[0];
2146 SRegType* pCurReg = &pRegs[argReg];
2150 * Include "this" pointer, if appropriate.
2152 if (!dvmIsStaticMethod(meth)) {
2153 *pCurReg++ = kRegTypeReference;
2156 ccp = meth->shorty +1; /* skip first byte, which holds return type */
2161 *pCurReg++ = kRegTypeReference;
2164 *pCurReg++ = kRegTypeBoolean;
2167 *pCurReg++ = kRegTypeChar;
2170 *pCurReg++ = kRegTypeByte;
2173 *pCurReg++ = kRegTypeInteger;
2176 *pCurReg++ = kRegTypeShort;
2179 *pCurReg++ = kRegTypeFloat;
2182 *pCurReg++ = kRegTypeDoubleLo;
2183 *pCurReg++ = kRegTypeDoubleHi;
2186 *pCurReg++ = kRegTypeLongLo;
2187 *pCurReg++ = kRegTypeLongHi;
2195 assert(pCurReg - pRegs == meth->insSize);
2200 * Find the start of the register set for the specified instruction in
2201 * the current method.
2203 static inline SRegType* getRegisterLine(const WorkState* pState, int insnIdx)
2205 return pState->addrRegs[insnIdx];
2209 * Copy a set of registers.
2211 static inline void copyRegisters(SRegType* dst, const SRegType* src,
2214 memcpy(dst, src, numRegs * sizeof(SRegType));
2218 * Compare a set of registers. Returns 0 if they match.
2220 static inline int compareRegisters(const SRegType* src1, const SRegType* src2,
2223 return memcmp(src1, src2, numRegs * sizeof(SRegType));
2227 * Run through the instructions repeatedly until we have exercised all
2230 static bool analyzeMethod(WorkState* pState)
2232 const Method* meth = pState->method;
2233 SRegType workRegs[pState->insnRegCountPlus];
2234 InsnFlags* insnFlags = pState->insnFlags;
2235 int insnsSize = pState->insnsSize;
2236 int insnIdx, startGuess;
2237 bool result = false;
2240 * Initialize the types of the registers that correspond to method
2243 if (!setTypesFromSignature(pState))
2247 * Mark the first instruction as "changed".
2249 dvmInsnSetChanged(insnFlags, 0, true);
2254 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
2255 LOGI("Now mapping: %s.%s %s (ins=%d regs=%d)\n",
2256 meth->clazz->descriptor, meth->name, desc,
2257 meth->insSize, meth->registersSize);
2258 LOGI(" ------ [0 4 8 12 16 20 24 28 32 36\n");
2264 * Continue until no instructions are marked "changed".
2268 * Find the first marked one. Use "startGuess" as a way to find
2271 for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) {
2272 if (dvmInsnIsChanged(insnFlags, insnIdx))
2276 if (insnIdx == insnsSize) {
2277 if (startGuess != 0) {
2278 /* try again, starting from the top */
2282 /* all flags are clear */
2288 * We carry the working set of registers from instruction to
2289 * instruction. If this address can be the target of a branch
2290 * (or throw) instruction, or if we're skipping around chasing
2291 * "changed" flags, we need to load the set of registers from
2294 * Because we always prefer to continue on to the next instruction,
2295 * we should never have a situation where we have a stray
2296 * "changed" flag set on an instruction that isn't a branch target.
2298 if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) {
2299 SRegType* insnRegs = getRegisterLine(pState, insnIdx);
2300 assert(insnRegs != NULL);
2301 copyRegisters(workRegs, insnRegs, pState->insnRegCountPlus);
2306 * Sanity check: retrieve the stored register line (assuming
2307 * a full table) and make sure it actually matches.
2309 SRegType* insnRegs = getRegisterLine(pState, insnIdx);
2310 if (insnRegs != NULL &&
2311 compareRegisters(workRegs, insnRegs,
2312 pState->insnRegCountPlus) != 0)
2314 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
2315 LOG_VFY("HUH? workRegs diverged in %s.%s %s\n",
2316 meth->clazz->descriptor, meth->name, desc);
2323 * Update the register sets altered by this instruction.
2325 if (!handleInstruction(pState, workRegs, insnIdx, &startGuess)) {
2329 dvmInsnSetVisited(insnFlags, insnIdx, true);
2330 dvmInsnSetChanged(insnFlags, insnIdx, false);
2333 // TODO - add dead code scan to help validate this code?
2342 * Get a pointer to the method being invoked.
2344 * Returns NULL on failure.
2346 static Method* getInvokedMethod(const Method* meth,
2347 const DecodedInstruction* pDecInsn, MethodType methodType)
2350 char* sigOriginal = NULL;
2353 * Resolve the method. This could be an abstract or concrete method
2354 * depending on what sort of call we're making.
2356 if (methodType == METHOD_INTERFACE) {
2357 resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB);
2359 resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType);
2361 if (resMethod == NULL) {
2362 /* failed; print a meaningful failure message */
2363 DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
2364 const DexMethodId* pMethodId;
2365 const char* methodName;
2367 const char* classDescriptor;
2369 pMethodId = dexGetMethodId(pDexFile, pDecInsn->vB);
2370 methodName = dexStringById(pDexFile, pMethodId->nameIdx);
2371 methodDesc = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
2372 classDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
2374 LOG_VFY("VFY: unable to resolve %s method %u: %s.%s %s\n",
2375 dvmMethodTypeStr(methodType), pDecInsn->vB,
2376 classDescriptor, methodName, methodDesc);
2385 * Return the register type for the method. Since we don't care about
2386 * the actual type, we can just look at the "shorty" signature.
2388 * Returns kRegTypeUnknown for "void".
2390 static SRegType getMethodReturnType(const Method* meth)
2394 switch (meth->shorty[0]) {
2396 type = kRegTypeInteger;
2399 type = kRegTypeChar;
2402 type = kRegTypeShort;
2405 type = kRegTypeByte;
2408 type = kRegTypeBoolean;
2411 type = kRegTypeUnknown;
2414 type = kRegTypeFloat;
2417 type = kRegTypeDoubleLo;
2420 type = kRegTypeLongLo;
2424 type = kRegTypeReference;
2427 /* we verified signature return type earlier, so this is impossible */
2429 type = kRegTypeConflict;
2437 * Copy a category 1 register.
2439 static inline void copyRegister1(SRegType* insnRegs, u4 vdst, u4 vsrc)
2441 insnRegs[vdst] = insnRegs[vsrc];
2445 * Copy a category 2 register. Note the source and destination may overlap.
2447 static inline void copyRegister2(SRegType* insnRegs, u4 vdst, u4 vsrc)
2449 //memmove(&insnRegs[vdst], &insnRegs[vsrc], sizeof(SRegType) * 2);
2450 SRegType r1 = insnRegs[vsrc];
2451 SRegType r2 = insnRegs[vsrc+1];
2452 insnRegs[vdst] = r1;
2453 insnRegs[vdst+1] = r2;
2457 * Set the type of a category 1 register.
2459 static inline void setRegisterType(SRegType* insnRegs, u4 vdst, SRegType type)
2461 insnRegs[vdst] = type;
2465 * Decode the specified instruction and update the register info.
2467 static bool handleInstruction(WorkState* pState, SRegType* workRegs,
2468 int insnIdx, int* pStartGuess)
2470 const Method* meth = pState->method;
2471 const u2* insns = meth->insns + insnIdx;
2472 InsnFlags* insnFlags = pState->insnFlags;
2473 bool result = false;
2476 * Once we finish decoding the instruction, we need to figure out where
2477 * we can go from here. There are three possible ways to transfer
2478 * control to another statement:
2480 * (1) Continue to the next instruction. Applies to all but
2481 * unconditional branches, method returns, and exception throws.
2482 * (2) Branch to one or more possible locations. Applies to branches
2483 * and switch statements.
2484 * (3) Exception handlers. Applies to any instruction that can
2485 * throw an exception that is handled by an encompassing "try"
2486 * block. (We simplify this to be any instruction that can
2487 * throw any exception.)
2489 * We can also return, in which case there is no successor instruction
2492 * The behavior can be determined from the InstrFlags.
2494 DecodedInstruction decInsn;
2495 SRegType entryRegs[pState->insnRegCountPlus];
2496 const int insnRegCountPlus = pState->insnRegCountPlus;
2497 bool justSetResult = false;
2498 int branchTarget = 0;
2501 dexDecodeInstruction(gDvm.instrFormat, insns, &decInsn);
2502 const int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
2505 * Make a copy of the previous register state. If the instruction
2506 * throws an exception, we merge *this* into the destination rather
2507 * than workRegs, because we don't want the result from the "successful"
2508 * code path (e.g. a check-cast that "improves" a type) to be visible
2509 * to the exception handler.
2511 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
2513 copyRegisters(entryRegs, workRegs, insnRegCountPlus);
2516 switch (decInsn.opCode) {
2521 case OP_MOVE_FROM16:
2523 case OP_MOVE_OBJECT:
2524 case OP_MOVE_OBJECT_FROM16:
2525 case OP_MOVE_OBJECT_16:
2526 copyRegister1(workRegs, decInsn.vA, decInsn.vB);
2529 case OP_MOVE_WIDE_FROM16:
2530 case OP_MOVE_WIDE_16:
2531 copyRegister2(workRegs, decInsn.vA, decInsn.vB);
2535 * The move-result instructions copy data out of a "pseudo-register"
2536 * with the results from the last method invocation. In practice we
2537 * might want to hold the result in an actual CPU register, so the
2538 * Dalvik spec requires that these only appear immediately after an
2539 * invoke or filled-new-array.
2541 * These calls invalidate the "result" register. (This is now
2542 * redundant with the reset done below, but it can make the debug info
2543 * easier to read in some cases.)
2545 case OP_MOVE_RESULT:
2546 case OP_MOVE_RESULT_OBJECT:
2547 copyRegister1(workRegs, decInsn.vA, RESULT_REGISTER(insnRegCountPlus));
2549 case OP_MOVE_RESULT_WIDE:
2550 copyRegister2(workRegs, decInsn.vA, RESULT_REGISTER(insnRegCountPlus));
2553 case OP_MOVE_EXCEPTION:
2555 * This statement can only appear as the first instruction in an
2556 * exception handler (though not all exception handlers need to
2557 * have one of these). We verify that as part of extracting the
2558 * exception type from the catch block list.
2560 setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
2563 case OP_RETURN_VOID:
2565 case OP_RETURN_WIDE:
2566 case OP_RETURN_OBJECT:
2572 /* could be boolean, int, float, or a null reference */
2573 setRegisterType(workRegs, decInsn.vA,
2574 dvmDetermineCat1Const((s4)decInsn.vB));
2576 case OP_CONST_HIGH16:
2577 /* could be boolean, int, float, or a null reference */
2578 setRegisterType(workRegs, decInsn.vA,
2579 dvmDetermineCat1Const((s4) decInsn.vB << 16));
2581 case OP_CONST_WIDE_16:
2582 case OP_CONST_WIDE_32:
2584 case OP_CONST_WIDE_HIGH16:
2585 /* could be long or double; default to long and allow conversion */
2586 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2588 case OP_CONST_STRING:
2589 case OP_CONST_STRING_JUMBO:
2590 case OP_CONST_CLASS:
2591 setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
2594 case OP_MONITOR_ENTER:
2595 case OP_MONITOR_EXIT:
2599 setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
2601 case OP_INSTANCE_OF:
2602 /* result is boolean */
2603 setRegisterType(workRegs, decInsn.vA, kRegTypeBoolean);
2606 case OP_ARRAY_LENGTH:
2607 setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
2610 case OP_NEW_INSTANCE:
2612 /* add the new uninitialized reference to the register ste */
2613 setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
2615 case OP_FILLED_NEW_ARRAY:
2616 case OP_FILLED_NEW_ARRAY_RANGE:
2617 setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
2619 justSetResult = true;
2624 setRegisterType(workRegs, decInsn.vA, kRegTypeBoolean);
2626 case OP_CMPL_DOUBLE:
2627 case OP_CMPG_DOUBLE:
2628 setRegisterType(workRegs, decInsn.vA, kRegTypeBoolean);
2631 setRegisterType(workRegs, decInsn.vA, kRegTypeBoolean);
2638 case OP_PACKED_SWITCH:
2639 case OP_SPARSE_SWITCH:
2642 case OP_FILL_ARRAY_DATA:
2660 tmpType = kRegTypeInteger;
2661 goto aget_1nr_common;
2662 case OP_AGET_BOOLEAN:
2663 tmpType = kRegTypeBoolean;
2664 goto aget_1nr_common;
2666 tmpType = kRegTypeByte;
2667 goto aget_1nr_common;
2669 tmpType = kRegTypeChar;
2670 goto aget_1nr_common;
2672 tmpType = kRegTypeShort;
2673 goto aget_1nr_common;
2675 setRegisterType(workRegs, decInsn.vA, tmpType);
2680 * We know this is either long or double, and we don't really
2681 * discriminate between those during verification, so we
2684 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2687 case OP_AGET_OBJECT:
2688 setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
2692 case OP_APUT_BOOLEAN:
2697 case OP_APUT_OBJECT:
2701 tmpType = kRegTypeInteger;
2702 goto iget_1nr_common;
2703 case OP_IGET_BOOLEAN:
2704 tmpType = kRegTypeBoolean;
2705 goto iget_1nr_common;
2707 tmpType = kRegTypeByte;
2708 goto iget_1nr_common;
2710 tmpType = kRegTypeChar;
2711 goto iget_1nr_common;
2713 tmpType = kRegTypeShort;
2714 goto iget_1nr_common;
2716 setRegisterType(workRegs, decInsn.vA, tmpType);
2720 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2723 case OP_IGET_OBJECT:
2724 setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
2728 case OP_IPUT_BOOLEAN:
2733 case OP_IPUT_OBJECT:
2737 tmpType = kRegTypeInteger;
2738 goto sget_1nr_common;
2739 case OP_SGET_BOOLEAN:
2740 tmpType = kRegTypeBoolean;
2741 goto sget_1nr_common;
2743 tmpType = kRegTypeByte;
2744 goto sget_1nr_common;
2746 tmpType = kRegTypeChar;
2747 goto sget_1nr_common;
2749 tmpType = kRegTypeShort;
2750 goto sget_1nr_common;
2752 setRegisterType(workRegs, decInsn.vA, tmpType);
2756 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2759 case OP_SGET_OBJECT:
2760 setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
2764 case OP_SPUT_BOOLEAN:
2769 case OP_SPUT_OBJECT:
2772 case OP_INVOKE_VIRTUAL:
2773 case OP_INVOKE_VIRTUAL_RANGE:
2774 case OP_INVOKE_SUPER:
2775 case OP_INVOKE_SUPER_RANGE:
2777 Method* calledMethod;
2779 calledMethod = getInvokedMethod(meth, &decInsn, METHOD_VIRTUAL);
2780 if (calledMethod == NULL)
2782 setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
2783 getMethodReturnType(calledMethod));
2784 justSetResult = true;
2787 case OP_INVOKE_DIRECT:
2788 case OP_INVOKE_DIRECT_RANGE:
2790 Method* calledMethod;
2792 calledMethod = getInvokedMethod(meth, &decInsn, METHOD_DIRECT);
2793 if (calledMethod == NULL)
2795 setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
2796 getMethodReturnType(calledMethod));
2797 justSetResult = true;
2800 case OP_INVOKE_STATIC:
2801 case OP_INVOKE_STATIC_RANGE:
2803 Method* calledMethod;
2805 calledMethod = getInvokedMethod(meth, &decInsn, METHOD_STATIC);
2806 if (calledMethod == NULL)
2808 setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
2809 getMethodReturnType(calledMethod));
2810 justSetResult = true;
2813 case OP_INVOKE_INTERFACE:
2814 case OP_INVOKE_INTERFACE_RANGE:
2818 absMethod = getInvokedMethod(meth, &decInsn, METHOD_INTERFACE);
2819 if (absMethod == NULL)
2821 setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
2822 getMethodReturnType(absMethod));
2823 justSetResult = true;
2829 setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
2833 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2836 setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
2839 setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
2841 case OP_INT_TO_LONG:
2842 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2844 case OP_INT_TO_FLOAT:
2845 setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
2847 case OP_INT_TO_DOUBLE:
2848 setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
2850 case OP_LONG_TO_INT:
2851 setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
2853 case OP_LONG_TO_FLOAT:
2854 setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
2856 case OP_LONG_TO_DOUBLE:
2857 setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
2859 case OP_FLOAT_TO_INT:
2860 setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
2862 case OP_FLOAT_TO_LONG:
2863 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2865 case OP_FLOAT_TO_DOUBLE:
2866 setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
2868 case OP_DOUBLE_TO_INT:
2869 setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
2871 case OP_DOUBLE_TO_LONG:
2872 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2874 case OP_DOUBLE_TO_FLOAT:
2875 setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
2877 case OP_INT_TO_BYTE:
2878 setRegisterType(workRegs, decInsn.vA, kRegTypeByte);
2880 case OP_INT_TO_CHAR:
2881 setRegisterType(workRegs, decInsn.vA, kRegTypeChar);
2883 case OP_INT_TO_SHORT:
2884 setRegisterType(workRegs, decInsn.vA, kRegTypeShort);
2898 setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
2911 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2918 setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
2925 setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
2927 case OP_ADD_INT_2ADDR:
2928 case OP_SUB_INT_2ADDR:
2929 case OP_MUL_INT_2ADDR:
2930 case OP_REM_INT_2ADDR:
2931 case OP_SHL_INT_2ADDR:
2932 case OP_SHR_INT_2ADDR:
2933 case OP_USHR_INT_2ADDR:
2934 case OP_AND_INT_2ADDR:
2935 case OP_OR_INT_2ADDR:
2936 case OP_XOR_INT_2ADDR:
2937 case OP_DIV_INT_2ADDR:
2938 setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
2940 case OP_ADD_LONG_2ADDR:
2941 case OP_SUB_LONG_2ADDR:
2942 case OP_MUL_LONG_2ADDR:
2943 case OP_DIV_LONG_2ADDR:
2944 case OP_REM_LONG_2ADDR:
2945 case OP_AND_LONG_2ADDR:
2946 case OP_OR_LONG_2ADDR:
2947 case OP_XOR_LONG_2ADDR:
2948 case OP_SHL_LONG_2ADDR:
2949 case OP_SHR_LONG_2ADDR:
2950 case OP_USHR_LONG_2ADDR:
2951 setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
2953 case OP_ADD_FLOAT_2ADDR:
2954 case OP_SUB_FLOAT_2ADDR:
2955 case OP_MUL_FLOAT_2ADDR:
2956 case OP_DIV_FLOAT_2ADDR:
2957 case OP_REM_FLOAT_2ADDR:
2958 setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
2960 case OP_ADD_DOUBLE_2ADDR:
2961 case OP_SUB_DOUBLE_2ADDR:
2962 case OP_MUL_DOUBLE_2ADDR:
2963 case OP_DIV_DOUBLE_2ADDR:
2964 case OP_REM_DOUBLE_2ADDR:
2965 setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
2967 case OP_ADD_INT_LIT16:
2969 case OP_MUL_INT_LIT16:
2970 case OP_DIV_INT_LIT16:
2971 case OP_REM_INT_LIT16:
2972 case OP_AND_INT_LIT16:
2973 case OP_OR_INT_LIT16:
2974 case OP_XOR_INT_LIT16:
2975 case OP_ADD_INT_LIT8:
2976 case OP_RSUB_INT_LIT8:
2977 case OP_MUL_INT_LIT8:
2978 case OP_DIV_INT_LIT8:
2979 case OP_REM_INT_LIT8:
2980 case OP_SHL_INT_LIT8:
2981 case OP_SHR_INT_LIT8:
2982 case OP_USHR_INT_LIT8:
2983 case OP_AND_INT_LIT8:
2984 case OP_OR_INT_LIT8:
2985 case OP_XOR_INT_LIT8:
2986 setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
2991 * See comments in analysis/CodeVerify.c re: why some of these are
2992 * annoying to deal with. It's worse in this implementation, because
2993 * we're not keeping any information about the classes held in each
2994 * reference register.
2996 * Handling most of these would require retaining the field/method
2997 * reference info that we discarded when the instructions were
2998 * quickened. This is feasible but not currently supported.
3000 case OP_EXECUTE_INLINE:
3001 case OP_EXECUTE_INLINE_RANGE:
3002 case OP_INVOKE_DIRECT_EMPTY:
3004 case OP_IGET_WIDE_QUICK:
3005 case OP_IGET_OBJECT_QUICK:
3007 case OP_IPUT_WIDE_QUICK:
3008 case OP_IPUT_OBJECT_QUICK:
3009 case OP_IGET_WIDE_VOLATILE:
3010 case OP_IPUT_WIDE_VOLATILE:
3011 case OP_SGET_WIDE_VOLATILE:
3012 case OP_SPUT_WIDE_VOLATILE:
3013 case OP_INVOKE_VIRTUAL_QUICK:
3014 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
3015 case OP_INVOKE_SUPER_QUICK:
3016 case OP_INVOKE_SUPER_QUICK_RANGE:
3017 dvmAbort(); // not implemented, shouldn't be here
3021 /* these should never appear */
3047 * DO NOT add a "default" clause here. Without it the compiler will
3048 * complain if an instruction is missing (which is desirable).
3054 * If we didn't just set the result register, clear it out. This
3055 * isn't so important here, but does help ensure that our output matches
3058 if (!justSetResult) {
3059 int reg = RESULT_REGISTER(pState->insnRegCountPlus);
3060 workRegs[reg] = workRegs[reg+1] = kRegTypeUnknown;
3064 * Handle "continue". Tag the next consecutive instruction.
3066 if ((nextFlags & kInstrCanContinue) != 0) {
3067 int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx);
3070 * We want to update the registers and set the "changed" flag on the
3071 * next instruction (if necessary). We aren't storing register
3072 * changes for all addresses, so for non-GC-point targets we just
3073 * compare "entry" vs. "work" to see if we've changed anything.
3075 if (getRegisterLine(pState, insnIdx+insnWidth) != NULL) {
3076 updateRegisters(pState, insnIdx+insnWidth, workRegs);
3078 /* if not yet visited, or regs were updated, set "changed" */
3079 if (!dvmInsnIsVisited(insnFlags, insnIdx+insnWidth) ||
3080 compareRegisters(workRegs, entryRegs,
3081 pState->insnRegCountPlus) != 0)
3083 dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true);
3089 * Handle "branch". Tag the branch target.
3091 if ((nextFlags & kInstrCanBranch) != 0) {
3094 dvmGetBranchTarget(meth, insnFlags, insnIdx, &branchTarget,
3096 assert(isConditional || (nextFlags & kInstrCanContinue) == 0);
3097 assert(!isConditional || (nextFlags & kInstrCanContinue) != 0);
3099 updateRegisters(pState, insnIdx+branchTarget, workRegs);
3103 * Handle "switch". Tag all possible branch targets.
3105 if ((nextFlags & kInstrCanSwitch) != 0) {
3106 int offsetToSwitch = insns[1] | (((s4)insns[2]) << 16);
3107 const u2* switchInsns = insns + offsetToSwitch;
3108 int switchCount = switchInsns[1];
3109 int offsetToTargets, targ;
3111 if ((*insns & 0xff) == OP_PACKED_SWITCH) {
3112 /* 0=sig, 1=count, 2/3=firstKey */
3113 offsetToTargets = 4;
3115 /* 0=sig, 1=count, 2..count*2 = keys */
3116 assert((*insns & 0xff) == OP_SPARSE_SWITCH);
3117 offsetToTargets = 2 + 2*switchCount;
3120 /* verify each switch target */
3121 for (targ = 0; targ < switchCount; targ++) {
3122 int offset, absOffset;
3124 /* offsets are 32-bit, and only partly endian-swapped */
3125 offset = switchInsns[offsetToTargets + targ*2] |
3126 (((s4) switchInsns[offsetToTargets + targ*2 +1]) << 16);
3127 absOffset = insnIdx + offset;
3128 assert(absOffset >= 0 && absOffset < pState->insnsSize);
3130 updateRegisters(pState, absOffset, workRegs);
3135 * Handle instructions that can throw and that are sitting in a
3136 * "try" block. (If they're not in a "try" block when they throw,
3137 * control transfers out of the method.)
3139 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
3141 DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
3142 const DexCode* pCode = dvmGetMethodCode(meth);
3143 DexCatchIterator iterator;
3145 if (dexFindCatchHandler(&iterator, pCode, insnIdx)) {
3147 DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
3148 if (handler == NULL)
3151 /* note we use entryRegs, not workRegs */
3152 updateRegisters(pState, handler->address, entryRegs);
3158 * Update startGuess. Advance to the next instruction of that's
3159 * possible, otherwise use the branch target if one was found. If
3160 * neither of those exists we're in a return or throw; leave startGuess
3161 * alone and let the caller sort it out.
3163 if ((nextFlags & kInstrCanContinue) != 0) {
3164 *pStartGuess = insnIdx + dvmInsnGetWidth(insnFlags, insnIdx);
3165 } else if ((nextFlags & kInstrCanBranch) != 0) {
3166 /* we're still okay if branchTarget is zero */
3167 *pStartGuess = insnIdx + branchTarget;
3170 assert(*pStartGuess >= 0 && *pStartGuess < pState->insnsSize &&
3171 dvmInsnGetWidth(insnFlags, *pStartGuess) != 0);
3181 * Merge two SRegType values.
3183 * Sets "*pChanged" to "true" if the result doesn't match "type1".
3185 static SRegType mergeTypes(SRegType type1, SRegType type2, bool* pChanged)
3190 * Check for trivial case so we don't have to hit memory.
3196 * Use the table if we can, and reject any attempts to merge something
3197 * from the table with a reference type.
3199 * The uninitialized table entry at index zero *will* show up as a
3200 * simple kRegTypeUninit value. Since this cannot be merged with
3201 * anything but itself, the rules do the right thing.
3203 if (type1 < kRegTypeMAX) {
3204 if (type2 < kRegTypeMAX) {
3205 result = gDvmMergeTab[type1][type2];
3207 /* simple + reference == conflict, usually */
3208 if (type1 == kRegTypeZero)
3211 result = kRegTypeConflict;
3214 if (type2 < kRegTypeMAX) {
3215 /* reference + simple == conflict, usually */
3216 if (type2 == kRegTypeZero)
3219 result = kRegTypeConflict;
3221 /* merging two references */
3222 assert(type1 == type2);
3227 if (result != type1)
3233 * Control can transfer to "nextInsn".
3235 * Merge the registers from "workRegs" into "addrRegs" at "nextInsn", and
3236 * set the "changed" flag on the target address if the registers have changed.
3238 static void updateRegisters(WorkState* pState, int nextInsn,
3239 const SRegType* workRegs)
3241 const Method* meth = pState->method;
3242 InsnFlags* insnFlags = pState->insnFlags;
3243 const int insnRegCountPlus = pState->insnRegCountPlus;
3244 SRegType* targetRegs = getRegisterLine(pState, nextInsn);
3246 if (!dvmInsnIsVisitedOrChanged(insnFlags, nextInsn)) {
3248 * We haven't processed this instruction before, and we haven't
3249 * touched the registers here, so there's nothing to "merge". Copy
3250 * the registers over and mark it as changed. (This is the only
3251 * way a register can transition out of "unknown", so this is not
3252 * just an optimization.)
3254 LOGVV("COPY into 0x%04x\n", nextInsn);
3255 copyRegisters(targetRegs, workRegs, insnRegCountPlus);
3256 dvmInsnSetChanged(insnFlags, nextInsn, true);
3258 /* merge registers, set Changed only if different */
3259 LOGVV("MERGE into 0x%04x\n", nextInsn);
3260 bool changed = false;
3263 for (i = 0; i < insnRegCountPlus; i++) {
3264 targetRegs[i] = mergeTypes(targetRegs[i], workRegs[i], &changed);
3268 dvmInsnSetChanged(insnFlags, nextInsn, true);