Home | History | Annotate | Download | only in analysis
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     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.
     22  */
     23 #include "Dalvik.h"
     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"
     29 
     30 #include <stddef.h>
     31 
     32 /* double-check the compression */
     33 #define REGISTER_MAP_VERIFY     false
     34 
     35 /* verbose logging */
     36 #define REGISTER_MAP_VERBOSE    false
     37 
     38 //#define REGISTER_MAP_STATS
     39 
     40 // fwd
     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);
     44 
     45 #ifdef REGISTER_MAP_STATS
     46 static void computeMapStats(RegisterMap* pMap, const Method* method);
     47 #endif
     48 static RegisterMap* compressMapDifferential(const RegisterMap* pMap,\
     49     const Method* meth);
     50 static RegisterMap* uncompressMapDifferential(const RegisterMap* pMap);
     51 
     52 #ifdef REGISTER_MAP_STATS
     53 /*
     54  * Generate some statistics on the register maps we create and use.
     55  */
     56 #define kMaxGcPointGap      50
     57 #define kUpdatePosnMinRegs  24
     58 #define kNumUpdatePosns     8
     59 #define kMaxDiffBits        20
     60 typedef struct MapStats {
     61     /*
     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.
     65      */
     66     int gcPointGap[kMaxGcPointGap];
     67 
     68     /*
     69      * Number of gaps.  Equal to (number of gcPoints - number of methods),
     70      * since the computation isn't including the initial gap.
     71      */
     72     int gcGapCount;
     73 
     74     /*
     75      * Number of gaps.
     76      */
     77     int totalGcPointCount;
     78 
     79     /*
     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.
     83      */
     84     int updatePosn[kNumUpdatePosns];
     85 
     86     /*
     87      * For all methods, count up the number of changes to registers < 16
     88      * and >= 16.
     89      */
     90     int updateLT16;
     91     int updateGE16;
     92 
     93     /*
     94      * Histogram of the number of bits that differ between adjacent entries.
     95      */
     96     int numDiffBits[kMaxDiffBits];
     97 
     98 
     99     /*
    100      * Track the number of expanded maps, and the heap space required to
    101      * hold them.
    102      */
    103     int numExpandedMaps;
    104     int totalExpandedMapSize;
    105 } MapStats;
    106 #endif
    107 
    108 /*
    109  * Prepare some things.
    110  */
    111 bool dvmRegisterMapStartup(void)
    112 {
    113 #ifdef REGISTER_MAP_STATS
    114     MapStats* pStats = calloc(1, sizeof(MapStats));
    115     gDvm.registerMapStats = pStats;
    116 #endif
    117     return true;
    118 }
    119 
    120 /*
    121  * Clean up.
    122  */
    123 void dvmRegisterMapShutdown(void)
    124 {
    125 #ifdef REGISTER_MAP_STATS
    126     free(gDvm.registerMapStats);
    127 #endif
    128 }
    129 
    130 /*
    131  * Write stats to log file.
    132  */
    133 void dvmRegisterMapDumpStats(void)
    134 {
    135 #ifdef REGISTER_MAP_STATS
    136     MapStats* pStats = (MapStats*) gDvm.registerMapStats;
    137     int i, end;
    138 
    139     for (end = kMaxGcPointGap-1; end >= 0; end--) {
    140         if (pStats->gcPointGap[end] != 0)
    141             break;
    142     }
    143 
    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]);
    149     }
    150 
    151 
    152     for (end = kMaxDiffBits-1; end >= 0; end--) {
    153         if (pStats->numDiffBits[end] != 0)
    154             break;
    155     }
    156 
    157     LOGI("Register Map bit difference stats:\n");
    158     for (i = 0; i <= end; i++) {
    159         LOGI(" %2d %d\n", i, pStats->numDiffBits[i]);
    160     }
    161 
    162 
    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]);
    167     }
    168 #endif
    169 }
    170 
    171 
    172 /*
    173  * ===========================================================================
    174  *      Map generation
    175  * ===========================================================================
    176  */
    177 
    178 /*
    179  * Generate the register map for a method that has just been verified
    180  * (i.e. we're doing this as part of verification).
    181  *
    182  * For type-precise determination we have all the data we need, so we
    183  * just need to encode it in some clever fashion.
    184  *
    185  * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
    186  */
    187 RegisterMap* dvmGenerateRegisterMapV(VerifierData* vdata)
    188 {
    189     static const int kHeaderSize = offsetof(RegisterMap, data);
    190     RegisterMap* pMap = NULL;
    191     RegisterMap* pResult = NULL;
    192     RegisterMapFormat format;
    193     u1 regWidth;
    194     u1* mapData;
    195     int i, bytesForAddr, gcPointCount;
    196     int bufSize;
    197 
    198     if (vdata->method->registersSize >= 2048) {
    199         LOGE("ERROR: register map can't handle %d registers\n",
    200             vdata->method->registersSize);
    201         goto bail;
    202     }
    203     regWidth = (vdata->method->registersSize + 7) / 8;
    204 
    205     /*
    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.
    211      */
    212     if (vdata->insnsSize < 256) {
    213         format = kRegMapFormatCompact8;
    214         bytesForAddr = 1;
    215     } else {
    216         format = kRegMapFormatCompact16;
    217         bytesForAddr = 2;
    218     }
    219 
    220     /*
    221      * Count up the number of GC point instructions.
    222      *
    223      * NOTE: this does not automatically include the first instruction,
    224      * since we don't count method entry as a GC point.
    225      */
    226     gcPointCount = 0;
    227     for (i = 0; i < (int) vdata->insnsSize; i++) {
    228         if (dvmInsnIsGcPoint(vdata->insnFlags, i))
    229             gcPointCount++;
    230     }
    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",
    234             gcPointCount);
    235         goto bail;
    236     }
    237 
    238     /*
    239      * Allocate a buffer to hold the map data.
    240      */
    241     bufSize = kHeaderSize + gcPointCount * (bytesForAddr + regWidth);
    242 
    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);
    246 
    247     pMap = (RegisterMap*) malloc(bufSize);
    248     dvmRegisterMapSetFormat(pMap, format);
    249     dvmRegisterMapSetOnHeap(pMap, true);
    250     dvmRegisterMapSetRegWidth(pMap, regWidth);
    251     dvmRegisterMapSetNumEntries(pMap, gcPointCount);
    252 
    253     /*
    254      * Populate it.
    255      */
    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) {
    261                 *mapData++ = i;
    262             } else /*kRegMapFormatCompact16*/ {
    263                 *mapData++ = i & 0xff;
    264                 *mapData++ = i >> 8;
    265             }
    266             outputTypeVector(vdata->addrRegs[i], vdata->insnRegCount, mapData);
    267             mapData += regWidth;
    268         }
    269     }
    270 
    271     LOGV("mapData=%p pMap=%p bufSize=%d\n", mapData, pMap, bufSize);
    272     assert(mapData - (const u1*) pMap == bufSize);
    273 
    274     if (REGISTER_MAP_VERIFY && !verifyMap(vdata, pMap))
    275         goto bail;
    276 #ifdef REGISTER_MAP_STATS
    277     computeMapStats(pMap, vdata->method);
    278 #endif
    279 
    280     /*
    281      * Try to compress the map.
    282      */
    283     RegisterMap* pCompMap;
    284 
    285     pCompMap = compressMapDifferential(pMap, vdata->method);
    286     if (pCompMap != NULL) {
    287         if (REGISTER_MAP_VERIFY) {
    288             /*
    289              * Expand the compressed map we just created, and compare it
    290              * to the original.  Abort the VM if it doesn't match up.
    291              */
    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);
    298                 free(pCompMap);
    299                 /* bad - compression is broken or we're out of memory */
    300                 dvmAbort();
    301             } else {
    302                 if (compareMaps(pMap, pUncompMap) != 0) {
    303                     LOGE("Map comparison failed - %s.%s\n",
    304                         vdata->method->clazz->descriptor,
    305                         vdata->method->name);
    306                     free(pCompMap);
    307                     /* bad - compression is broken */
    308                     dvmAbort();
    309                 }
    310 
    311                 /* verify succeeded */
    312                 free(pUncompMap);
    313             }
    314         }
    315 
    316         if (REGISTER_MAP_VERBOSE) {
    317             LOGD("Good compress on %s.%s\n",
    318                 vdata->method->clazz->descriptor,
    319                 vdata->method->name);
    320         }
    321         free(pMap);
    322         pMap = pCompMap;
    323     } else {
    324         if (REGISTER_MAP_VERBOSE) {
    325             LOGD("Unable to compress %s.%s (ent=%d rw=%d)\n",
    326                 vdata->method->clazz->descriptor,
    327                 vdata->method->name,
    328                 dvmRegisterMapGetNumEntries(pMap),
    329                 dvmRegisterMapGetRegWidth(pMap));
    330         }
    331     }
    332 
    333     pResult = pMap;
    334 
    335 bail:
    336     return pResult;
    337 }
    338 
    339 /*
    340  * Release the storage held by a RegisterMap.
    341  */
    342 void dvmFreeRegisterMap(RegisterMap* pMap)
    343 {
    344     if (pMap == NULL)
    345         return;
    346 
    347     assert(dvmRegisterMapGetOnHeap(pMap));
    348     free(pMap);
    349 }
    350 
    351 /*
    352  * Determine if the RegType value is a reference type.
    353  *
    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.
    357  */
    358 static inline bool isReferenceType(RegType type)
    359 {
    360     return (type > kRegTypeMAX || type == kRegTypeUninit);
    361 }
    362 
    363 /*
    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).
    366  *
    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.
    370  */
    371 static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data)
    372 {
    373     u1 val = 0;
    374     int i;
    375 
    376     for (i = 0; i < insnRegCount; i++) {
    377         RegType type = *regs++;
    378         val >>= 1;
    379         if (isReferenceType(type))
    380             val |= 0x80;        /* set hi bit */
    381 
    382         if ((i & 0x07) == 7)
    383             *data++ = val;
    384     }
    385     if ((i & 0x07) != 0) {
    386         /* flush bits from last byte */
    387         val >>= 8 - (i & 0x07);
    388         *data++ = val;
    389     }
    390 }
    391 
    392 /*
    393  * Print the map as a series of binary strings.
    394  *
    395  * Pass in method->registersSize if known, or -1 if not.
    396  */
    397 static void dumpRegisterMap(const RegisterMap* pMap, int registersSize)
    398 {
    399     const u1* rawMap = pMap->data;
    400     const RegisterMapFormat format = dvmRegisterMapGetFormat(pMap);
    401     const int numEntries = dvmRegisterMapGetNumEntries(pMap);
    402     const int regWidth = dvmRegisterMapGetRegWidth(pMap);
    403     int addrWidth;
    404 
    405     switch (format) {
    406     case kRegMapFormatCompact8:
    407         addrWidth = 1;
    408         break;
    409     case kRegMapFormatCompact16:
    410         addrWidth = 2;
    411         break;
    412     default:
    413         /* can't happen */
    414         LOGE("Can only dump Compact8 / Compact16 maps (not %d)\n", format);
    415         return;
    416     }
    417 
    418     if (registersSize < 0)
    419         registersSize = 8 * regWidth;
    420     assert(registersSize <= regWidth * 8);
    421 
    422     int ent;
    423     for (ent = 0; ent < numEntries; ent++) {
    424         int i, addr;
    425 
    426         addr = *rawMap++;
    427         if (addrWidth > 1)
    428             addr |= (*rawMap++) << 8;
    429 
    430         const u1* dataStart = rawMap;
    431         u1 val = 0;
    432 
    433         /* create binary string */
    434         char outBuf[registersSize +1];
    435         for (i = 0; i < registersSize; i++) {
    436             val >>= 1;
    437             if ((i & 0x07) == 0)
    438                 val = *rawMap++;
    439 
    440             outBuf[i] = '0' + (val & 0x01);
    441         }
    442         outBuf[i] = '\0';
    443 
    444         /* back up and create hex dump */
    445         char hexBuf[regWidth * 3 +1];
    446         char* cp = hexBuf;
    447         rawMap = dataStart;
    448         for (i = 0; i < regWidth; i++) {
    449             sprintf(cp, " %02x", *rawMap++);
    450             cp += 3;
    451         }
    452         hexBuf[i * 3] = '\0';
    453 
    454         LOGD("  %04x %s %s\n", addr, outBuf, hexBuf);
    455     }
    456 }
    457 
    458 /*
    459  * Double-check the map.
    460  *
    461  * We run through all of the data in the map, and compare it to the original.
    462  * Only works on uncompressed data.
    463  */
    464 static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap)
    465 {
    466     const u1* rawMap = pMap->data;
    467     const RegisterMapFormat format = dvmRegisterMapGetFormat(pMap);
    468     const int numEntries = dvmRegisterMapGetNumEntries(pMap);
    469     int ent;
    470     bool dumpMap = false;
    471 
    472     if (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)
    477         {
    478             char* desc;
    479             desc = dexProtoCopyMethodDescriptor(&vdata->method->prototype);
    480             LOGI("Map for %s.%s %s\n", vdata->method->clazz->descriptor,
    481                 vdata->method->name, desc);
    482             free(desc);
    483 
    484             dumpMap = true;
    485         }
    486     }
    487 
    488     if ((vdata->method->registersSize + 7) / 8 != pMap->regWidth) {
    489         LOGE("GLITCH: registersSize=%d, regWidth=%d\n",
    490             vdata->method->registersSize, pMap->regWidth);
    491         return false;
    492     }
    493 
    494     for (ent = 0; ent < numEntries; ent++) {
    495         int addr;
    496 
    497         switch (format) {
    498         case kRegMapFormatCompact8:
    499             addr = *rawMap++;
    500             break;
    501         case kRegMapFormatCompact16:
    502             addr = *rawMap++;
    503             addr |= (*rawMap++) << 8;
    504             break;
    505         default:
    506             /* shouldn't happen */
    507             LOGE("GLITCH: bad format (%d)", format);
    508             dvmAbort();
    509         }
    510 
    511         const RegType* regs = vdata->addrRegs[addr];
    512         if (regs == NULL) {
    513             LOGE("GLITCH: addr %d has no data\n", addr);
    514             return false;
    515         }
    516 
    517         u1 val = 0;
    518         int i;
    519 
    520         for (i = 0; i < vdata->method->registersSize; i++) {
    521             bool bitIsRef, regIsRef;
    522 
    523             val >>= 1;
    524             if ((i & 0x07) == 0) {
    525                 /* load next byte of data */
    526                 val = *rawMap++;
    527             }
    528 
    529             bitIsRef = val & 0x01;
    530 
    531             RegType type = regs[i];
    532             regIsRef = isReferenceType(type);
    533 
    534             if (bitIsRef != regIsRef) {
    535                 LOGE("GLITCH: addr %d reg %d: bit=%d reg=%d(%d)\n",
    536                     addr, i, bitIsRef, regIsRef, type);
    537                 return false;
    538             }
    539         }
    540 
    541         /* rawMap now points to the address field of the next entry */
    542     }
    543 
    544     if (dumpMap)
    545         dumpRegisterMap(pMap, vdata->method->registersSize);
    546 
    547     return true;
    548 }
    549 
    550 
    551 /*
    552  * ===========================================================================
    553  *      DEX generation & parsing
    554  * ===========================================================================
    555  */
    556 
    557 /*
    558  * Advance "ptr" to ensure 32-bit alignment.
    559  */
    560 static inline u1* align32(u1* ptr)
    561 {
    562     return (u1*) (((int) ptr + 3) & ~0x03);
    563 }
    564 
    565 /*
    566  * Compute the size, in bytes, of a register map.
    567  */
    568 static size_t computeRegisterMapSize(const RegisterMap* pMap)
    569 {
    570     static const int kHeaderSize = offsetof(RegisterMap, data);
    571     u1 format = dvmRegisterMapGetFormat(pMap);
    572     u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
    573 
    574     assert(pMap != NULL);
    575 
    576     switch (format) {
    577     case kRegMapFormatNone:
    578         return 1;
    579     case kRegMapFormatCompact8:
    580         return kHeaderSize + (1 + pMap->regWidth) * numEntries;
    581     case kRegMapFormatCompact16:
    582         return kHeaderSize + (2 + pMap->regWidth) * numEntries;
    583     case kRegMapFormatDifferential:
    584         {
    585             /* kHeaderSize + decoded ULEB128 length */
    586             const u1* ptr = pMap->data;
    587             int len = readUnsignedLeb128(&ptr);
    588             return len + (ptr - (u1*) pMap);
    589         }
    590     default:
    591         LOGE("Bad register map format %d\n", format);
    592         dvmAbort();
    593         return 0;
    594     }
    595 }
    596 
    597 /*
    598  * Output the map for a single method, if it has one.
    599  *
    600  * Abstract and native methods have no map.  All others are expected to
    601  * have one, since we know the class verified successfully.
    602  *
    603  * This strips the "allocated on heap" flag from the format byte, so that
    604  * direct-mapped maps are correctly identified as such.
    605  */
    606 static bool writeMapForMethod(const Method* meth, u1** pPtr)
    607 {
    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 */
    613         }
    614         *(*pPtr)++ = kRegMapFormatNone;
    615         return true;
    616     }
    617 
    618     /* serialize map into the buffer */
    619     size_t mapSize = computeRegisterMapSize(meth->registerMap);
    620     memcpy(*pPtr, meth->registerMap, mapSize);
    621 
    622     /* strip the "on heap" flag out of the format byte, which is always first */
    623     assert(**pPtr == meth->registerMap->format);
    624     **pPtr &= ~(kRegMapFormatOnHeap);
    625 
    626     *pPtr += mapSize;
    627 
    628     return true;
    629 }
    630 
    631 /*
    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.
    635  */
    636 static bool writeMapsAllMethods(DvmDex* pDvmDex, const ClassObject* clazz,
    637     u1** pPtr, size_t length)
    638 {
    639     RegisterMapMethodPool* pMethodPool;
    640     u1* ptr = *pPtr;
    641     int i, methodCount;
    642 
    643     /* artificial limit */
    644     if (clazz->virtualMethodCount + clazz->directMethodCount >= 65536) {
    645         LOGE("Too many methods in %s\n", clazz->descriptor);
    646         return false;
    647     }
    648 
    649     pMethodPool = (RegisterMapMethodPool*) ptr;
    650     ptr += offsetof(RegisterMapMethodPool, methodData);
    651     methodCount = 0;
    652 
    653     /*
    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.)
    658      *
    659      * The class loader won't know about miranda methods at the point
    660      * where it parses this, so we omit those.
    661      *
    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.
    665      */
    666     for (i = 0; i < clazz->directMethodCount; i++) {
    667         const Method* meth = &clazz->directMethods[i];
    668         if (dvmIsMirandaMethod(meth))
    669             continue;
    670         if (!writeMapForMethod(&clazz->directMethods[i], &ptr)) {
    671             return false;
    672         }
    673         methodCount++;
    674         //ptr = align32(ptr);
    675     }
    676 
    677     for (i = 0; i < clazz->virtualMethodCount; i++) {
    678         const Method* meth = &clazz->virtualMethods[i];
    679         if (dvmIsMirandaMethod(meth))
    680             continue;
    681         if (!writeMapForMethod(&clazz->virtualMethods[i], &ptr)) {
    682             return false;
    683         }
    684         methodCount++;
    685         //ptr = align32(ptr);
    686     }
    687 
    688     pMethodPool->methodCount = methodCount;
    689 
    690     *pPtr = ptr;
    691     return true;
    692 }
    693 
    694 /*
    695  * Write maps for all classes to the specified buffer, which can hold at
    696  * most "length" bytes.
    697  *
    698  * Returns the actual length used, or 0 on failure.
    699  */
    700 static size_t writeMapsAllClasses(DvmDex* pDvmDex, u1* basePtr, size_t length)
    701 {
    702     DexFile* pDexFile = pDvmDex->pDexFile;
    703     u4 count = pDexFile->pHeader->classDefsSize;
    704     RegisterMapClassPool* pClassPool;
    705     u4* offsetTable;
    706     u1* ptr = basePtr;
    707     u4 idx;
    708 
    709     assert(gDvm.optimizing);
    710 
    711     pClassPool = (RegisterMapClassPool*) ptr;
    712     ptr += offsetof(RegisterMapClassPool, classDataOffset);
    713     offsetTable = (u4*) ptr;
    714     ptr += count * sizeof(u4);
    715 
    716     pClassPool->numClasses = count;
    717 
    718     /*
    719      * We want an entry for every class, loaded or not.
    720      */
    721     for (idx = 0; idx < count; idx++) {
    722         const DexClassDef* pClassDef;
    723         const char* classDescriptor;
    724         ClassObject* clazz;
    725 
    726         pClassDef = dexGetClassDef(pDexFile, idx);
    727         classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
    728 
    729         /*
    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.
    733          *
    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.
    737          */
    738         clazz = NULL;
    739         if ((pClassDef->accessFlags & CLASS_ISPREVERIFIED) != 0)
    740             clazz = dvmLookupClass(classDescriptor, NULL, false);
    741 
    742         if (clazz != NULL) {
    743             offsetTable[idx] = ptr - basePtr;
    744             LOGVV("%d -> offset %d (%p-%p)\n",
    745                 idx, offsetTable[idx], ptr, basePtr);
    746 
    747             if (!writeMapsAllMethods(pDvmDex, clazz, &ptr,
    748                     length - (ptr - basePtr)))
    749             {
    750                 return 0;
    751             }
    752 
    753             ptr = align32(ptr);
    754             LOGVV("Size %s (%d+%d methods): %d\n", clazz->descriptor,
    755                 clazz->directMethodCount, clazz->virtualMethodCount,
    756                 (ptr - basePtr) - offsetTable[idx]);
    757         } else {
    758             LOGV("%4d NOT mapadding '%s'\n", idx, classDescriptor);
    759             assert(offsetTable[idx] == 0);
    760         }
    761     }
    762 
    763     if (ptr - basePtr >= (int)length) {
    764         /* a bit late */
    765         LOGE("Buffer overrun\n");
    766         dvmAbort();
    767     }
    768 
    769     return ptr - basePtr;
    770 }
    771 
    772 /*
    773  * Generate a register map set for all verified classes in "pDvmDex".
    774  */
    775 RegisterMapBuilder* dvmGenerateRegisterMaps(DvmDex* pDvmDex)
    776 {
    777     RegisterMapBuilder* pBuilder;
    778 
    779     pBuilder = (RegisterMapBuilder*) calloc(1, sizeof(RegisterMapBuilder));
    780     if (pBuilder == NULL)
    781         return NULL;
    782 
    783     /*
    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.
    787      *
    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.
    793      *
    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
    797      * we overrun.)
    798      */
    799     if (sysCreatePrivateMap(4 * 1024 * 1024, &pBuilder->memMap) != 0) {
    800         free(pBuilder);
    801         return NULL;
    802     }
    803 
    804     /*
    805      * Create the maps.
    806      */
    807     size_t actual = writeMapsAllClasses(pDvmDex, (u1*)pBuilder->memMap.addr,
    808                                         pBuilder->memMap.length);
    809     if (actual == 0) {
    810         dvmFreeRegisterMapBuilder(pBuilder);
    811         return NULL;
    812     }
    813 
    814     LOGV("TOTAL size of register maps: %d\n", actual);
    815 
    816     pBuilder->data = pBuilder->memMap.addr;
    817     pBuilder->size = actual;
    818     return pBuilder;
    819 }
    820 
    821 /*
    822  * Free the builder.
    823  */
    824 void dvmFreeRegisterMapBuilder(RegisterMapBuilder* pBuilder)
    825 {
    826     if (pBuilder == NULL)
    827         return;
    828 
    829     sysReleaseShmem(&pBuilder->memMap);
    830     free(pBuilder);
    831 }
    832 
    833 
    834 /*
    835  * Find the data for the specified class.
    836  *
    837  * If there's no register map data, or none for this class, we return NULL.
    838  */
    839 const void* dvmRegisterMapGetClassData(const DexFile* pDexFile, u4 classIdx,
    840     u4* pNumMaps)
    841 {
    842     const RegisterMapClassPool* pClassPool;
    843     const RegisterMapMethodPool* pMethodPool;
    844 
    845     pClassPool = (const RegisterMapClassPool*) pDexFile->pRegisterMapPool;
    846     if (pClassPool == NULL)
    847         return NULL;
    848 
    849     if (classIdx >= pClassPool->numClasses) {
    850         LOGE("bad class index (%d vs %d)\n", classIdx, pClassPool->numClasses);
    851         dvmAbort();
    852     }
    853 
    854     u4 classOffset = pClassPool->classDataOffset[classIdx];
    855     if (classOffset == 0) {
    856         LOGV("+++ no map for classIdx=%d\n", classIdx);
    857         return NULL;
    858     }
    859 
    860     pMethodPool =
    861         (const RegisterMapMethodPool*) (((u1*) pClassPool) + classOffset);
    862     if (pNumMaps != NULL)
    863         *pNumMaps = pMethodPool->methodCount;
    864     return pMethodPool->methodData;
    865 }
    866 
    867 /*
    868  * This advances "*pPtr" and returns its original value.
    869  */
    870 const RegisterMap* dvmRegisterMapGetNext(const void** pPtr)
    871 {
    872     const RegisterMap* pMap = *pPtr;
    873 
    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));
    878     return pMap;
    879 }
    880 
    881 
    882 /*
    883  * ===========================================================================
    884  *      Utility functions
    885  * ===========================================================================
    886  */
    887 
    888 /*
    889  * Return the data for the specified address, or NULL if not found.
    890  *
    891  * The result must be released with dvmReleaseRegisterMapLine().
    892  */
    893 const u1* dvmRegisterMapGetLine(const RegisterMap* pMap, int addr)
    894 {
    895     int addrWidth, lineWidth;
    896     u1 format = dvmRegisterMapGetFormat(pMap);
    897     u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
    898 
    899     assert(numEntries > 0);
    900 
    901     switch (format) {
    902     case kRegMapFormatNone:
    903         return NULL;
    904     case kRegMapFormatCompact8:
    905         addrWidth = 1;
    906         break;
    907     case kRegMapFormatCompact16:
    908         addrWidth = 2;
    909         break;
    910     default:
    911         LOGE("Unknown format %d\n", format);
    912         dvmAbort();
    913         return NULL;
    914     }
    915 
    916     lineWidth = addrWidth + pMap->regWidth;
    917 
    918     /*
    919      * Find the appropriate entry.  Many maps are very small, some are very
    920      * large.
    921      */
    922     static const int kSearchThreshold = 8;
    923     const u1* data = NULL;
    924     int lineAddr;
    925 
    926     if (numEntries < kSearchThreshold) {
    927         int i;
    928         data = pMap->data;
    929         for (i = numEntries; i > 0; i--) {
    930             lineAddr = data[0];
    931             if (addrWidth > 1)
    932                 lineAddr |= data[1] << 8;
    933             if (lineAddr == addr)
    934                 return data + addrWidth;
    935 
    936             data += lineWidth;
    937         }
    938         assert(data == pMap->data + lineWidth * numEntries);
    939     } else {
    940         int hi, lo, mid;
    941 
    942         lo = 0;
    943         hi = numEntries -1;
    944 
    945         while (hi >= lo) {
    946             mid = (hi + lo) / 2;
    947             data = pMap->data + lineWidth * mid;
    948 
    949             lineAddr = data[0];
    950             if (addrWidth > 1)
    951                 lineAddr |= data[1] << 8;
    952 
    953             if (addr > lineAddr) {
    954                 lo = mid + 1;
    955             } else if (addr < lineAddr) {
    956                 hi = mid - 1;
    957             } else {
    958                 return data + addrWidth;
    959             }
    960         }
    961     }
    962 
    963     return NULL;
    964 }
    965 
    966 /*
    967  * Compare two register maps.
    968  *
    969  * Returns 0 if they're equal, nonzero if not.
    970  */
    971 static int compareMaps(const RegisterMap* pMap1, const RegisterMap* pMap2)
    972 {
    973     size_t size1, size2;
    974 
    975     size1 = computeRegisterMapSize(pMap1);
    976     size2 = computeRegisterMapSize(pMap2);
    977     if (size1 != size2) {
    978         LOGI("compareMaps: size mismatch (%zd vs %zd)\n", size1, size2);
    979         return -1;
    980     }
    981 
    982     if (memcmp(pMap1, pMap2, size1) != 0) {
    983         LOGI("compareMaps: content mismatch\n");
    984         return -1;
    985     }
    986 
    987     return 0;
    988 }
    989 
    990 
    991 /*
    992  * Get the expanded form of the register map associated with the method.
    993  *
    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.
    997  *
    998  * NOTE: this function is not synchronized; external locking is mandatory
    999  * (unless we're in the zygote, where single-threaded access is guaranteed).
   1000  */
   1001 const RegisterMap* dvmGetExpandedRegisterMap0(Method* method)
   1002 {
   1003     const RegisterMap* curMap = method->registerMap;
   1004     RegisterMap* newMap;
   1005 
   1006     if (curMap == NULL)
   1007         return NULL;
   1008 
   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) */
   1011     if (true) {
   1012         if (!gDvm.zygote && dvmTryLockMutex(&gDvm.gcHeapLock) == 0) {
   1013             LOGE("GLITCH: dvmGetExpandedRegisterMap not called at GC time\n");
   1014             dvmAbort();
   1015         }
   1016     }
   1017 
   1018     RegisterMapFormat format = dvmRegisterMapGetFormat(curMap);
   1019     switch (format) {
   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);
   1026             } else {
   1027                 LOGD("RegMap: stored w/o compression: %s.%s\n",
   1028                     method->clazz->descriptor, method->name);
   1029             }
   1030         }
   1031         return curMap;
   1032     case kRegMapFormatDifferential:
   1033         newMap = uncompressMapDifferential(curMap);
   1034         break;
   1035     default:
   1036         LOGE("Unknown format %d in dvmGetExpandedRegisterMap\n", format);
   1037         dvmAbort();
   1038         newMap = NULL;      // make gcc happy
   1039     }
   1040 
   1041     if (newMap == NULL) {
   1042         LOGE("Map failed to uncompress (fmt=%d) %s.%s\n",
   1043             format, method->clazz->descriptor, method->name);
   1044         return NULL;
   1045     }
   1046 
   1047 #ifdef REGISTER_MAP_STATS
   1048     /*
   1049      * Gather and display some stats.
   1050      */
   1051     {
   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);
   1057     }
   1058 #endif
   1059 
   1060     IF_LOGV() {
   1061         char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
   1062         LOGV("Expanding map -> %s.%s:%s\n",
   1063             method->clazz->descriptor, method->name, desc);
   1064         free(desc);
   1065     }
   1066 
   1067     /*
   1068      * Update method, and free compressed map if it was sitting on the heap.
   1069      */
   1070     dvmSetRegisterMap(method, newMap);
   1071 
   1072     if (dvmRegisterMapGetOnHeap(curMap))
   1073         dvmFreeRegisterMap((RegisterMap*) curMap);
   1074 
   1075     return newMap;
   1076 }
   1077 
   1078 
   1079 /*
   1080  * ===========================================================================
   1081  *      Map compression
   1082  * ===========================================================================
   1083  */
   1084 
   1085 /*
   1086 Notes on map compression
   1087 
   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.
   1091 
   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.)
   1097 
   1098 Each entry consists of an address and a bit vector.  Adjacent entries are
   1099 strongly correlated, suggesting differential encoding.
   1100 
   1101 
   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.
   1106 
   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.
   1115 
   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.
   1122 
   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.
   1128 
   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.
   1132 
   1133 We also need to include an "initial gap", because the first few instructions
   1134 in a method may not be GC points.
   1135 
   1136 
   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
   1140 is factored in).
   1141 
   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.
   1149 
   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.
   1153 
   1154 
   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.
   1164 
   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
   1170 N registers.
   1171 
   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.
   1181 
   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.
   1184 
   1185 
   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.
   1191 
   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.
   1196 
   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.)
   1202 
   1203 
   1204 ----- differential format -----
   1205 
   1206 // common header
   1207 +00 1B format
   1208 +01 1B regWidth
   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
   1214 
   1215 // for each entry
   1216 +00: CCCCBAAA
   1217 
   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.
   1221 
   1222   B: determines the meaning of CCCC.
   1223 
   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.
   1229 
   1230 +01: (optional) ULEB128-encoded address difference
   1231 
   1232 +01+: (optional) one or more ULEB128-encoded bit numbers, OR the entire
   1233   bit vector.
   1234 
   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.
   1240 */
   1241 
   1242 /*
   1243  * Compute some stats on an uncompressed register map.
   1244  */
   1245 #ifdef REGISTER_MAP_STATS
   1246 static void computeMapStats(RegisterMap* pMap, const Method* method)
   1247 {
   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;
   1254 
   1255     for (ent = 0; ent < numEntries; ent++) {
   1256         switch (format) {
   1257         case kRegMapFormatCompact8:
   1258             addr = *rawMap++;
   1259             break;
   1260         case kRegMapFormatCompact16:
   1261             addr = *rawMap++;
   1262             addr |= (*rawMap++) << 8;
   1263             break;
   1264         default:
   1265             /* shouldn't happen */
   1266             LOGE("GLITCH: bad format (%d)", format);
   1267             dvmAbort();
   1268         }
   1269 
   1270         const u1* dataStart = rawMap;
   1271 
   1272         pStats->totalGcPointCount++;
   1273 
   1274         /*
   1275          * Gather "gap size" stats, i.e. the difference in addresses between
   1276          * successive GC points.
   1277          */
   1278         if (prevData != NULL) {
   1279             assert(prevAddr >= 0);
   1280             int addrDiff = addr - prevAddr;
   1281 
   1282             if (addrDiff < 0) {
   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);
   1290                 }
   1291                 /* skip this one */
   1292             } else {
   1293                 pStats->gcPointGap[addrDiff]++;
   1294             }
   1295             pStats->gcGapCount++;
   1296 
   1297 
   1298             /*
   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).
   1303              *
   1304              * We only do the vector position quantization if we have at
   1305              * least 16 registers in the method.
   1306              */
   1307             int numDiff = 0;
   1308             float div = (float) kNumUpdatePosns / method->registersSize;
   1309             int regByte;
   1310             for (regByte = 0; regByte < pMap->regWidth; regByte++) {
   1311                 int prev, cur, bit;
   1312 
   1313                 prev = prevData[regByte];
   1314                 cur = dataStart[regByte];
   1315 
   1316                 for (bit = 0; bit < 8; bit++) {
   1317                     if (((prev >> bit) & 1) != ((cur >> bit) & 1)) {
   1318                         numDiff++;
   1319 
   1320                         int bitNum = regByte * 8 + bit;
   1321 
   1322                         if (bitNum < 16)
   1323                             pStats->updateLT16++;
   1324                         else
   1325                             pStats->updateGE16++;
   1326 
   1327                         if (method->registersSize < 16)
   1328                             continue;
   1329 
   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,
   1334                                 prev, cur);
   1335                             assert(false);
   1336                         }
   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);
   1341                             assert(false);
   1342                         }
   1343                         pStats->updatePosn[idx]++;
   1344                     }
   1345                 }
   1346             }
   1347 
   1348             if (numDiff > kMaxDiffBits) {
   1349                 if (REGISTER_MAP_VERBOSE) {
   1350                     LOGI("WOW: numDiff is %d, max %d\n", numDiff, kMaxDiffBits);
   1351                 }
   1352             } else {
   1353                 pStats->numDiffBits[numDiff]++;
   1354             }
   1355         }
   1356 
   1357         /* advance to start of next line */
   1358         rawMap += pMap->regWidth;
   1359 
   1360         prevAddr = addr;
   1361         prevData = dataStart;
   1362     }
   1363 }
   1364 #endif
   1365 
   1366 /*
   1367  * Compute the difference between two bit vectors.
   1368  *
   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.
   1371  *
   1372  * The bit vectors are compared byte-by-byte, so any unused bits at the
   1373  * end must be zero.
   1374  *
   1375  * Returns the number of bytes required to hold the ULEB128 output.
   1376  *
   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.
   1380  */
   1381 static int computeBitDiff(const u1* bits1, const u1* bits2, int byteWidth,
   1382     int* pFirstBitChanged, int* pNumBitsChanged, u1* lebOutBuf)
   1383 {
   1384     int numBitsChanged = 0;
   1385     int firstBitChanged = -1;
   1386     int lebSize = 0;
   1387     int byteNum;
   1388 
   1389     /*
   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.
   1392      */
   1393     for (byteNum = 0; byteNum < byteWidth; byteNum++) {
   1394         u1 byte1 = *bits1++;
   1395         u1 byte2 = *bits2++;
   1396         if (byte1 != byte2) {
   1397             /*
   1398              * Walk through the byte, identifying the changed bits.
   1399              */
   1400             int bitNum;
   1401             for (bitNum = 0; bitNum < 8; bitNum++) {
   1402                 if (((byte1 >> bitNum) & 0x01) != ((byte2 >> bitNum) & 0x01)) {
   1403                     int bitOffset = (byteNum << 3) + bitNum;
   1404 
   1405                     if (firstBitChanged < 0)
   1406                         firstBitChanged = bitOffset;
   1407                     numBitsChanged++;
   1408 
   1409                     if (lebOutBuf == NULL) {
   1410                         lebSize += unsignedLeb128Size(bitOffset);
   1411                     } else {
   1412                         u1* curBuf = lebOutBuf;
   1413                         lebOutBuf = writeUnsignedLeb128(lebOutBuf, bitOffset);
   1414                         lebSize += lebOutBuf - curBuf;
   1415                     }
   1416                 }
   1417             }
   1418         }
   1419     }
   1420 
   1421     if (numBitsChanged > 0)
   1422         assert(firstBitChanged >= 0);
   1423 
   1424     if (pFirstBitChanged != NULL)
   1425         *pFirstBitChanged = firstBitChanged;
   1426     if (pNumBitsChanged != NULL)
   1427         *pNumBitsChanged = numBitsChanged;
   1428 
   1429     return lebSize;
   1430 }
   1431 
   1432 /*
   1433  * Compress the register map with differential encoding.
   1434  *
   1435  * "meth" is only needed for debug output.
   1436  *
   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.
   1439  */
   1440 static RegisterMap* compressMapDifferential(const RegisterMap* pMap,
   1441     const Method* meth)
   1442 {
   1443     RegisterMap* pNewMap = NULL;
   1444     int origSize = computeRegisterMapSize(pMap);
   1445     u1* tmpBuf = NULL;
   1446     u1* tmpPtr;
   1447     int addrWidth, regWidth, numEntries;
   1448     bool debug = false;
   1449 
   1450     if (false &&
   1451         strcmp(meth->clazz->descriptor, "Landroid/text/StaticLayout;") == 0 &&
   1452         strcmp(meth->name, "generate") == 0)
   1453     {
   1454         debug = true;
   1455     }
   1456 
   1457     u1 format = dvmRegisterMapGetFormat(pMap);
   1458     switch (format) {
   1459     case kRegMapFormatCompact8:
   1460         addrWidth = 1;
   1461         break;
   1462     case kRegMapFormatCompact16:
   1463         addrWidth = 2;
   1464         break;
   1465     default:
   1466         LOGE("ERROR: can't compress map with format=%d\n", format);
   1467         goto bail;
   1468     }
   1469 
   1470     regWidth = dvmRegisterMapGetRegWidth(pMap);
   1471     numEntries = dvmRegisterMapGetNumEntries(pMap);
   1472 
   1473     if (debug) {
   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);
   1478     }
   1479 
   1480     if (numEntries <= 1) {
   1481         LOGV("Can't compress map with 0 or 1 entries\n");
   1482         goto bail;
   1483     }
   1484 
   1485     /*
   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).
   1491      *
   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).
   1497      *
   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.
   1501      */
   1502     tmpBuf = (u1*) malloc(origSize + (1 + 3 + regWidth));
   1503     if (tmpBuf == NULL)
   1504         goto bail;
   1505 
   1506     tmpPtr = tmpBuf;
   1507 
   1508     const u1* mapData = pMap->data;
   1509     const u1* prevBits;
   1510     u2 addr, prevAddr;
   1511 
   1512     addr = *mapData++;
   1513     if (addrWidth > 1)
   1514         addr |= (*mapData++) << 8;
   1515 
   1516     if (addr >= 128) {
   1517         LOGV("Can't compress map with starting address >= 128\n");
   1518         goto bail;
   1519     }
   1520 
   1521     /*
   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).
   1526      */
   1527     *tmpPtr++ = addr | (addrWidth > 1 ? 0x80 : 0x00);
   1528     memcpy(tmpPtr, mapData, regWidth);
   1529 
   1530     prevBits = mapData;
   1531     prevAddr = addr;
   1532 
   1533     tmpPtr += regWidth;
   1534     mapData += regWidth;
   1535 
   1536     /*
   1537      * Loop over all following entries.
   1538      */
   1539     int entry;
   1540     for (entry = 1; entry < numEntries; entry++) {
   1541         int addrDiff;
   1542         u1 key;
   1543 
   1544         /*
   1545          * Pull out the address and figure out how to encode it.
   1546          */
   1547         addr = *mapData++;
   1548         if (addrWidth > 1)
   1549             addr |= (*mapData++) << 8;
   1550 
   1551         if (debug)
   1552             LOGI(" addr=0x%04x ent=%d (aw=%d)\n", addr, entry, addrWidth);
   1553 
   1554         addrDiff = addr - prevAddr;
   1555         assert(addrDiff > 0);
   1556         if (addrDiff < 8) {
   1557             /* small difference, encode in 3 bits */
   1558             key = addrDiff -1;          /* set 00000AAA */
   1559             if (debug)
   1560                 LOGI(" : small %d, key=0x%02x\n", addrDiff, key);
   1561         } else {
   1562             /* large difference, output escape code */
   1563             key = 0x07;                 /* escape code for AAA */
   1564             if (debug)
   1565                 LOGI(" : large %d, key=0x%02x\n", addrDiff, key);
   1566         }
   1567 
   1568         int numBitsChanged, firstBitChanged, lebSize;
   1569 
   1570         lebSize = computeBitDiff(prevBits, mapData, regWidth,
   1571             &firstBitChanged, &numBitsChanged, NULL);
   1572 
   1573         if (debug) {
   1574             LOGI(" : diff fbc=%d nbc=%d ls=%d (rw=%d)\n",
   1575                 firstBitChanged, numBitsChanged, lebSize, regWidth);
   1576         }
   1577 
   1578         if (numBitsChanged == 0) {
   1579             /* set B to 1 and CCCC to zero to indicate no bits were changed */
   1580             key |= 0x08;
   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");
   1590         } else {
   1591             /* set B to 1 and CCCC to 0x0f so we store the entire vector */
   1592             key |= 0x08 | 0xf0;
   1593             if (debug) LOGI(" : encode original\n");
   1594         }
   1595 
   1596         /*
   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.
   1599          */
   1600         *tmpPtr++ = key;
   1601         if ((key & 0x07) == 0x07)
   1602             tmpPtr = writeUnsignedLeb128(tmpPtr, addrDiff);
   1603 
   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);
   1611                 tmpPtr += regWidth;
   1612             } else {
   1613                 /* write bit indices in LEB128 format */
   1614                 (void) computeBitDiff(prevBits, mapData, regWidth,
   1615                     NULL, NULL, tmpPtr);
   1616                 tmpPtr += lebSize;
   1617             }
   1618         } else {
   1619             /* single-bit changed, value encoded in key byte */
   1620         }
   1621 
   1622         prevBits = mapData;
   1623         prevAddr = addr;
   1624         mapData += regWidth;
   1625 
   1626         /*
   1627          * See if we've run past the original size.
   1628          */
   1629         if (tmpPtr - tmpBuf >= origSize) {
   1630             if (debug) {
   1631                 LOGD("Compressed size >= original (%d vs %d): %s.%s\n",
   1632                     tmpPtr - tmpBuf, origSize,
   1633                     meth->clazz->descriptor, meth->name);
   1634             }
   1635             goto bail;
   1636         }
   1637     }
   1638 
   1639     /*
   1640      * Create a RegisterMap with the contents.
   1641      *
   1642      * TODO: consider using a threshold other than merely ">=".  We would
   1643      * get poorer compression but potentially use less native heap space.
   1644      */
   1645     static const int kHeaderSize = offsetof(RegisterMap, data);
   1646     int newDataSize = tmpPtr - tmpBuf;
   1647     int newMapSize;
   1648 
   1649     newMapSize = kHeaderSize + unsignedLeb128Size(newDataSize) + newDataSize;
   1650     if (newMapSize >= origSize) {
   1651         if (debug) {
   1652             LOGD("Final comp size >= original (%d vs %d): %s.%s\n",
   1653                 newMapSize, origSize, meth->clazz->descriptor, meth->name);
   1654         }
   1655         goto bail;
   1656     }
   1657 
   1658     pNewMap = (RegisterMap*) malloc(newMapSize);
   1659     if (pNewMap == NULL)
   1660         goto bail;
   1661     dvmRegisterMapSetFormat(pNewMap, kRegMapFormatDifferential);
   1662     dvmRegisterMapSetOnHeap(pNewMap, true);
   1663     dvmRegisterMapSetRegWidth(pNewMap, regWidth);
   1664     dvmRegisterMapSetNumEntries(pNewMap, numEntries);
   1665 
   1666     tmpPtr = pNewMap->data;
   1667     tmpPtr = writeUnsignedLeb128(tmpPtr, newDataSize);
   1668     memcpy(tmpPtr, tmpBuf, newDataSize);
   1669 
   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);
   1674     }
   1675 
   1676 bail:
   1677     free(tmpBuf);
   1678     return pNewMap;
   1679 }
   1680 
   1681 /*
   1682  * Toggle the value of the "idx"th bit in "ptr".
   1683  */
   1684 static inline void toggleBit(u1* ptr, int idx)
   1685 {
   1686     ptr[idx >> 3] ^= 1 << (idx & 0x07);
   1687 }
   1688 
   1689 /*
   1690  * Expand a compressed map to an uncompressed form.
   1691  *
   1692  * Returns a newly-allocated RegisterMap on success, or NULL on failure.
   1693  *
   1694  * TODO: consider using the linear allocator or a custom allocator with
   1695  * LRU replacement for these instead of the native heap.
   1696  */
   1697 static RegisterMap* uncompressMapDifferential(const RegisterMap* pMap)
   1698 {
   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;
   1704 
   1705     if (format != kRegMapFormatDifferential) {
   1706         LOGE("Not differential (%d)\n", format);
   1707         goto bail;
   1708     }
   1709 
   1710     regWidth = dvmRegisterMapGetRegWidth(pMap);
   1711     numEntries = dvmRegisterMapGetNumEntries(pMap);
   1712 
   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;
   1717 
   1718     /* get the initial address and the 16-bit address flag */
   1719     int addr = *srcPtr & 0x7f;
   1720     if ((*srcPtr & 0x80) == 0) {
   1721         newFormat = kRegMapFormatCompact8;
   1722         newAddrWidth = 1;
   1723     } else {
   1724         newFormat = kRegMapFormatCompact16;
   1725         newAddrWidth = 2;
   1726     }
   1727     srcPtr++;
   1728 
   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);
   1733     }
   1734     newMapSize = kHeaderSize + (newAddrWidth + regWidth) * numEntries;
   1735     pNewMap = (RegisterMap*) malloc(newMapSize);
   1736     if (pNewMap == NULL)
   1737         goto bail;
   1738 
   1739     dvmRegisterMapSetFormat(pNewMap, newFormat);
   1740     dvmRegisterMapSetOnHeap(pNewMap, true);
   1741     dvmRegisterMapSetRegWidth(pNewMap, regWidth);
   1742     dvmRegisterMapSetNumEntries(pNewMap, numEntries);
   1743 
   1744     /*
   1745      * Write the start address and initial bits to the new map.
   1746      */
   1747     u1* dstPtr = pNewMap->data;
   1748 
   1749     *dstPtr++ = addr & 0xff;
   1750     if (newAddrWidth > 1)
   1751         *dstPtr++ = (u1) (addr >> 8);
   1752 
   1753     memcpy(dstPtr, srcPtr, regWidth);
   1754 
   1755     int prevAddr = addr;
   1756     const u1* prevBits = dstPtr;    /* point at uncompressed data */
   1757 
   1758     dstPtr += regWidth;
   1759     srcPtr += regWidth;
   1760 
   1761     /*
   1762      * Walk through, uncompressing one line at a time.
   1763      */
   1764     int entry;
   1765     for (entry = 1; entry < numEntries; entry++) {
   1766         int addrDiff;
   1767         u1 key;
   1768 
   1769         key = *srcPtr++;
   1770 
   1771         /* get the address */
   1772         if ((key & 0x07) == 7) {
   1773             /* address diff follows in ULEB128 */
   1774             addrDiff = readUnsignedLeb128(&srcPtr);
   1775         } else {
   1776             addrDiff = (key & 0x07) +1;
   1777         }
   1778 
   1779         addr = prevAddr + addrDiff;
   1780         *dstPtr++ = addr & 0xff;
   1781         if (newAddrWidth > 1)
   1782             *dstPtr++ = (u1) (addr >> 8);
   1783 
   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);
   1793                 srcPtr += regWidth;
   1794             } else {
   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);
   1800                 }
   1801             }
   1802         } else {
   1803             /* copy previous bits and modify the specified one */
   1804             memcpy(dstPtr, prevBits, regWidth);
   1805 
   1806             /* one bit, from 0-15 inclusive, was changed */
   1807             toggleBit(dstPtr, key >> 4);
   1808         }
   1809 
   1810         prevAddr = addr;
   1811         prevBits = dstPtr;
   1812         dstPtr += regWidth;
   1813     }
   1814 
   1815     if (dstPtr - (u1*) pNewMap != newMapSize) {
   1816         LOGE("ERROR: output %d bytes, expected %d\n",
   1817             dstPtr - (u1*) pNewMap, newMapSize);
   1818         goto bail;
   1819     }
   1820 
   1821     if (srcPtr - srcStart != expectedSrcLen) {
   1822         LOGE("ERROR: consumed %d bytes, expected %d\n",
   1823             srcPtr - srcStart, expectedSrcLen);
   1824         goto bail;
   1825     }
   1826 
   1827     if (REGISTER_MAP_VERBOSE) {
   1828         LOGD("Expansion successful (%d -> %d)\n",
   1829             computeRegisterMapSize(pMap), computeRegisterMapSize(pNewMap));
   1830     }
   1831 
   1832     return pNewMap;
   1833 
   1834 bail:
   1835     free(pNewMap);
   1836     return NULL;
   1837 }
   1838 
   1839 
   1840 /*
   1841  * ===========================================================================
   1842  *      Just-in-time generation
   1843  * ===========================================================================
   1844  */
   1845 
   1846 #if 0   /* incomplete implementation; may be removed entirely in the future */
   1847 
   1848 /*
   1849 Notes on just-in-time RegisterMap generation
   1850 
   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.
   1857 
   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.
   1860 
   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.
   1868 
   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).
   1877 
   1878 
   1879 Implementation notes...
   1880 
   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.
   1887 
   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).
   1893 
   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.
   1897 */
   1898 
   1899 /*
   1900  * This is like RegType in the verifier, but simplified.  It holds a value
   1901  * from the reg type enum, or kRegTypeReference.
   1902  */
   1903 typedef u1 SRegType;
   1904 #define kRegTypeReference kRegTypeMAX
   1905 
   1906 /*
   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.
   1909  */
   1910 #define kExtraRegs  2
   1911 #define RESULT_REGISTER(_insnRegCountPlus)  (_insnRegCountPlus - kExtraRegs)
   1912 
   1913 /*
   1914  * Working state.
   1915  */
   1916 typedef struct WorkState {
   1917     /*
   1918      * The method we're working on.
   1919      */
   1920     const Method* method;
   1921 
   1922     /*
   1923      * Number of instructions in the method.
   1924      */
   1925     int         insnsSize;
   1926 
   1927     /*
   1928      * Number of registers we track for each instruction.  This is equal
   1929      * to the method's declared "registersSize" plus kExtraRegs.
   1930      */
   1931     int         insnRegCountPlus;
   1932 
   1933     /*
   1934      * Instruction widths and flags, one entry per code unit.
   1935      */
   1936     InsnFlags*  insnFlags;
   1937 
   1938     /*
   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.
   1942      *
   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
   1945      * storage.
   1946      */
   1947     SRegType**  addrRegs;
   1948 
   1949     /*
   1950      * A single large alloc, with all of the storage needed for addrRegs.
   1951      */
   1952     SRegType*   regAlloc;
   1953 } WorkState;
   1954 
   1955 // fwd
   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);
   1962 
   1963 
   1964 /*
   1965  * Set instruction flags.
   1966  */
   1967 static bool setInsnFlags(WorkState* pState, int* pGcPointCount)
   1968 {
   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;
   1974     int offset;
   1975 
   1976     /* set the widths */
   1977     if (!dvmComputeCodeWidths(meth, pState->insnFlags, NULL))
   1978         return false;
   1979 
   1980     /* mark "try" regions and exception handler branch targets */
   1981     if (!dvmSetTryFlags(meth, pState->insnFlags))
   1982         return false;
   1983 
   1984     /* the start of the method is a "branch target" */
   1985     dvmInsnSetBranchTarget(insnFlags, 0, true);
   1986 
   1987     /*
   1988      * Run through the instructions, looking for switches and branches.
   1989      * Mark their targets.
   1990      *
   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.
   1994      *
   1995      * Mark and count GC points while we're at it.
   1996      */
   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);
   2002 
   2003         if (opFlags & kInstrCanBranch) {
   2004             if (!dvmCheckBranchTarget(meth, insnFlags, offset, true))
   2005                 return false;
   2006         }
   2007         if (opFlags & kInstrCanSwitch) {
   2008             if (!dvmCheckSwitchTargets(meth, insnFlags, offset))
   2009                 return false;
   2010         }
   2011 
   2012         if ((opFlags & gcMask) != 0) {
   2013             dvmInsnSetGcPoint(pState->insnFlags, offset, true);
   2014             gcPointCount++;
   2015         }
   2016     }
   2017 
   2018     *pGcPointCount = gcPointCount;
   2019     return true;
   2020 }
   2021 
   2022 /*
   2023  * Generate the register map for a method.
   2024  *
   2025  * Returns a pointer to newly-allocated storage.
   2026  */
   2027 RegisterMap* dvmGenerateRegisterMap(const Method* meth)
   2028 {
   2029     WorkState* pState = NULL;
   2030     RegisterMap* pMap = NULL;
   2031     RegisterMap* result = NULL;
   2032     SRegType* regPtr;
   2033 
   2034     pState = (WorkState*) calloc(1, sizeof(WorkState));
   2035     if (pState == NULL)
   2036         goto bail;
   2037 
   2038     pMap = (RegisterMap*) calloc(1, sizeof(RegisterMap));
   2039     if (pMap == NULL)
   2040         goto bail;
   2041 
   2042     pState->method = meth;
   2043     pState->insnsSize = dvmGetMethodInsnsSize(meth);
   2044     pState->insnRegCountPlus = meth->registersSize + kExtraRegs;
   2045 
   2046     pState->insnFlags = calloc(sizeof(InsnFlags), pState->insnsSize);
   2047     pState->addrRegs = calloc(sizeof(SRegType*), pState->insnsSize);
   2048 
   2049     /*
   2050      * Set flags on instructions, and calculate the number of code units
   2051      * that happen to be GC points.
   2052      */
   2053     int gcPointCount;
   2054     if (!setInsnFlags(pState, &gcPointCount))
   2055         goto bail;
   2056 
   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");
   2060         goto bail;
   2061     }
   2062 
   2063     pState->regAlloc = (SRegType*)
   2064         calloc(sizeof(SRegType), pState->insnsSize * gcPointCount);
   2065     regPtr = pState->regAlloc;
   2066 
   2067     /*
   2068      * For each instruction that is a GC point, set a pointer into the
   2069      * regAlloc buffer.
   2070      */
   2071     int offset;
   2072     for (offset = 0; offset < pState->insnsSize; offset++) {
   2073         if (dvmInsnIsGcPoint(pState->insnFlags, offset)) {
   2074             pState->addrRegs[offset] = regPtr;
   2075             regPtr += pState->insnRegCountPlus;
   2076         }
   2077     }
   2078     assert(regPtr - pState->regAlloc == pState->insnsSize * gcPointCount);
   2079     assert(pState->addrRegs[0] != NULL);
   2080 
   2081     /*
   2082      * Compute the register map.
   2083      */
   2084     if (!generateMap(pState, pMap))
   2085         goto bail;
   2086 
   2087     /* success */
   2088     result = pMap;
   2089     pMap = NULL;
   2090 
   2091 bail:
   2092     if (pState != NULL) {
   2093         free(pState->insnFlags);
   2094         free(pState->addrRegs);
   2095         free(pState->regAlloc);
   2096         free(pState);
   2097     }
   2098     if (pMap != NULL)
   2099         dvmFreeRegisterMap(pMap);
   2100     return result;
   2101 }
   2102 
   2103 /*
   2104  * Release the storage associated with a RegisterMap.
   2105  */
   2106 void dvmFreeRegisterMap(RegisterMap* pMap)
   2107 {
   2108     if (pMap == NULL)
   2109         return;
   2110 }
   2111 
   2112 
   2113 /*
   2114  * Create the RegisterMap using the provided state.
   2115  */
   2116 static bool generateMap(WorkState* pState, RegisterMap* pMap)
   2117 {
   2118     bool result = false;
   2119 
   2120     /*
   2121      * Analyze the method and store the results in WorkState.
   2122      */
   2123     if (!analyzeMethod(pState))
   2124         goto bail;
   2125 
   2126     /*
   2127      * Convert the analyzed data into a RegisterMap.
   2128      */
   2129     // TODO
   2130 
   2131     result = true;
   2132 
   2133 bail:
   2134     return result;
   2135 }
   2136 
   2137 /*
   2138  * Set the register types for the method arguments.  We can pull the values
   2139  * out of the "shorty" signature.
   2140  */
   2141 static bool setTypesFromSignature(WorkState* pState)
   2142 {
   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];
   2147     const char* ccp;
   2148 
   2149     /*
   2150      * Include "this" pointer, if appropriate.
   2151      */
   2152     if (!dvmIsStaticMethod(meth)) {
   2153         *pCurReg++ = kRegTypeReference;
   2154     }
   2155 
   2156     ccp = meth->shorty +1;      /* skip first byte, which holds return type */
   2157     while (*ccp != 0) {
   2158         switch (*ccp) {
   2159         case 'L':
   2160         //case '[':
   2161             *pCurReg++ = kRegTypeReference;
   2162             break;
   2163         case 'Z':
   2164             *pCurReg++ = kRegTypeBoolean;
   2165             break;
   2166         case 'C':
   2167             *pCurReg++ = kRegTypeChar;
   2168             break;
   2169         case 'B':
   2170             *pCurReg++ = kRegTypeByte;
   2171             break;
   2172         case 'I':
   2173             *pCurReg++ = kRegTypeInteger;
   2174             break;
   2175         case 'S':
   2176             *pCurReg++ = kRegTypeShort;
   2177             break;
   2178         case 'F':
   2179             *pCurReg++ = kRegTypeFloat;
   2180             break;
   2181         case 'D':
   2182             *pCurReg++ = kRegTypeDoubleLo;
   2183             *pCurReg++ = kRegTypeDoubleHi;
   2184             break;
   2185         case 'J':
   2186             *pCurReg++ = kRegTypeLongLo;
   2187             *pCurReg++ = kRegTypeLongHi;
   2188             break;
   2189         default:
   2190             assert(false);
   2191             return false;
   2192         }
   2193     }
   2194 
   2195     assert(pCurReg - pRegs == meth->insSize);
   2196     return true;
   2197 }
   2198 
   2199 /*
   2200  * Find the start of the register set for the specified instruction in
   2201  * the current method.
   2202  */
   2203 static inline SRegType* getRegisterLine(const WorkState* pState, int insnIdx)
   2204 {
   2205     return pState->addrRegs[insnIdx];
   2206 }
   2207 
   2208 /*
   2209  * Copy a set of registers.
   2210  */
   2211 static inline void copyRegisters(SRegType* dst, const SRegType* src,
   2212     int numRegs)
   2213 {
   2214     memcpy(dst, src, numRegs * sizeof(SRegType));
   2215 }
   2216 
   2217 /*
   2218  * Compare a set of registers.  Returns 0 if they match.
   2219  */
   2220 static inline int compareRegisters(const SRegType* src1, const SRegType* src2,
   2221     int numRegs)
   2222 {
   2223     return memcmp(src1, src2, numRegs * sizeof(SRegType));
   2224 }
   2225 
   2226 /*
   2227  * Run through the instructions repeatedly until we have exercised all
   2228  * possible paths.
   2229  */
   2230 static bool analyzeMethod(WorkState* pState)
   2231 {
   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;
   2238 
   2239     /*
   2240      * Initialize the types of the registers that correspond to method
   2241      * arguments.
   2242      */
   2243     if (!setTypesFromSignature(pState))
   2244         goto bail;
   2245 
   2246     /*
   2247      * Mark the first instruction as "changed".
   2248      */
   2249     dvmInsnSetChanged(insnFlags, 0, true);
   2250     startGuess = 0;
   2251 
   2252     if (true) {
   2253         IF_LOGI() {
   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");
   2259             free(desc);
   2260         }
   2261     }
   2262 
   2263     /*
   2264      * Continue until no instructions are marked "changed".
   2265      */
   2266     while (true) {
   2267         /*
   2268          * Find the first marked one.  Use "startGuess" as a way to find
   2269          * one quickly.
   2270          */
   2271         for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) {
   2272             if (dvmInsnIsChanged(insnFlags, insnIdx))
   2273                 break;
   2274         }
   2275 
   2276         if (insnIdx == insnsSize) {
   2277             if (startGuess != 0) {
   2278                 /* try again, starting from the top */
   2279                 startGuess = 0;
   2280                 continue;
   2281             } else {
   2282                 /* all flags are clear */
   2283                 break;
   2284             }
   2285         }
   2286 
   2287         /*
   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
   2292          * the table.
   2293          *
   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.
   2297          */
   2298         if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) {
   2299             SRegType* insnRegs = getRegisterLine(pState, insnIdx);
   2300             assert(insnRegs != NULL);
   2301             copyRegisters(workRegs, insnRegs, pState->insnRegCountPlus);
   2302 
   2303         } else {
   2304 #ifndef NDEBUG
   2305             /*
   2306              * Sanity check: retrieve the stored register line (assuming
   2307              * a full table) and make sure it actually matches.
   2308              */
   2309             SRegType* insnRegs = getRegisterLine(pState, insnIdx);
   2310             if (insnRegs != NULL &&
   2311                 compareRegisters(workRegs, insnRegs,
   2312                                  pState->insnRegCountPlus) != 0)
   2313             {
   2314                 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
   2315                 LOG_VFY("HUH? workRegs diverged in %s.%s %s\n",
   2316                         meth->clazz->descriptor, meth->name, desc);
   2317                 free(desc);
   2318             }
   2319 #endif
   2320         }
   2321 
   2322         /*
   2323          * Update the register sets altered by this instruction.
   2324          */
   2325         if (!handleInstruction(pState, workRegs, insnIdx, &startGuess)) {
   2326             goto bail;
   2327         }
   2328 
   2329         dvmInsnSetVisited(insnFlags, insnIdx, true);
   2330         dvmInsnSetChanged(insnFlags, insnIdx, false);
   2331     }
   2332 
   2333     // TODO - add dead code scan to help validate this code?
   2334 
   2335     result = true;
   2336 
   2337 bail:
   2338     return result;
   2339 }
   2340 
   2341 /*
   2342  * Get a pointer to the method being invoked.
   2343  *
   2344  * Returns NULL on failure.
   2345  */
   2346 static Method* getInvokedMethod(const Method* meth,
   2347     const DecodedInstruction* pDecInsn, MethodType methodType)
   2348 {
   2349     Method* resMethod;
   2350     char* sigOriginal = NULL;
   2351 
   2352     /*
   2353      * Resolve the method.  This could be an abstract or concrete method
   2354      * depending on what sort of call we're making.
   2355      */
   2356     if (methodType == METHOD_INTERFACE) {
   2357         resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB);
   2358     } else {
   2359         resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType);
   2360     }
   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;
   2366         char* methodDesc;
   2367         const char* classDescriptor;
   2368 
   2369         pMethodId = dexGetMethodId(pDexFile, pDecInsn->vB);
   2370         methodName = dexStringById(pDexFile, pMethodId->nameIdx);
   2371         methodDesc = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
   2372         classDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
   2373 
   2374         LOG_VFY("VFY: unable to resolve %s method %u: %s.%s %s\n",
   2375             dvmMethodTypeStr(methodType), pDecInsn->vB,
   2376             classDescriptor, methodName, methodDesc);
   2377         free(methodDesc);
   2378         return NULL;
   2379     }
   2380 
   2381     return resMethod;
   2382 }
   2383 
   2384 /*
   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.
   2387  *
   2388  * Returns kRegTypeUnknown for "void".
   2389  */
   2390 static SRegType getMethodReturnType(const Method* meth)
   2391 {
   2392     SRegType type;
   2393 
   2394     switch (meth->shorty[0]) {
   2395     case 'I':
   2396         type = kRegTypeInteger;
   2397         break;
   2398     case 'C':
   2399         type = kRegTypeChar;
   2400         break;
   2401     case 'S':
   2402         type = kRegTypeShort;
   2403         break;
   2404     case 'B':
   2405         type = kRegTypeByte;
   2406         break;
   2407     case 'Z':
   2408         type = kRegTypeBoolean;
   2409         break;
   2410     case 'V':
   2411         type = kRegTypeUnknown;
   2412         break;
   2413     case 'F':
   2414         type = kRegTypeFloat;
   2415         break;
   2416     case 'D':
   2417         type = kRegTypeDoubleLo;
   2418         break;
   2419     case 'J':
   2420         type = kRegTypeLongLo;
   2421         break;
   2422     case 'L':
   2423     //case '[':
   2424         type = kRegTypeReference;
   2425         break;
   2426     default:
   2427         /* we verified signature return type earlier, so this is impossible */
   2428         assert(false);
   2429         type = kRegTypeConflict;
   2430         break;
   2431     }
   2432 
   2433     return type;
   2434 }
   2435 
   2436 /*
   2437  * Copy a category 1 register.
   2438  */
   2439 static inline void copyRegister1(SRegType* insnRegs, u4 vdst, u4 vsrc)
   2440 {
   2441     insnRegs[vdst] = insnRegs[vsrc];
   2442 }
   2443 
   2444 /*
   2445  * Copy a category 2 register.  Note the source and destination may overlap.
   2446  */
   2447 static inline void copyRegister2(SRegType* insnRegs, u4 vdst, u4 vsrc)
   2448 {
   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;
   2454 }
   2455 
   2456 /*
   2457  * Set the type of a category 1 register.
   2458  */
   2459 static inline void setRegisterType(SRegType* insnRegs, u4 vdst, SRegType type)
   2460 {
   2461     insnRegs[vdst] = type;
   2462 }
   2463 
   2464 /*
   2465  * Decode the specified instruction and update the register info.
   2466  */
   2467 static bool handleInstruction(WorkState* pState, SRegType* workRegs,
   2468     int insnIdx, int* pStartGuess)
   2469 {
   2470     const Method* meth = pState->method;
   2471     const u2* insns = meth->insns + insnIdx;
   2472     InsnFlags* insnFlags = pState->insnFlags;
   2473     bool result = false;
   2474 
   2475     /*
   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:
   2479      *
   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.)
   2488      *
   2489      * We can also return, in which case there is no successor instruction
   2490      * from this point.
   2491      *
   2492      * The behavior can be determined from the InstrFlags.
   2493      */
   2494     DecodedInstruction decInsn;
   2495     SRegType entryRegs[pState->insnRegCountPlus];
   2496     const int insnRegCountPlus = pState->insnRegCountPlus;
   2497     bool justSetResult = false;
   2498     int branchTarget = 0;
   2499     SRegType tmpType;
   2500 
   2501     dexDecodeInstruction(gDvm.instrFormat, insns, &decInsn);
   2502     const int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
   2503 
   2504     /*
   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.
   2510      */
   2511     if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
   2512     {
   2513         copyRegisters(entryRegs, workRegs, insnRegCountPlus);
   2514     }
   2515 
   2516     switch (decInsn.opCode) {
   2517     case OP_NOP:
   2518         break;
   2519 
   2520     case OP_MOVE:
   2521     case OP_MOVE_FROM16:
   2522     case OP_MOVE_16:
   2523     case OP_MOVE_OBJECT:
   2524     case OP_MOVE_OBJECT_FROM16:
   2525     case OP_MOVE_OBJECT_16:
   2526         copyRegister1(workRegs, decInsn.vA, decInsn.vB);
   2527         break;
   2528     case OP_MOVE_WIDE:
   2529     case OP_MOVE_WIDE_FROM16:
   2530     case OP_MOVE_WIDE_16:
   2531         copyRegister2(workRegs, decInsn.vA, decInsn.vB);
   2532         break;
   2533 
   2534     /*
   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.
   2540      *
   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.)
   2544      */
   2545     case OP_MOVE_RESULT:
   2546     case OP_MOVE_RESULT_OBJECT:
   2547         copyRegister1(workRegs, decInsn.vA, RESULT_REGISTER(insnRegCountPlus));
   2548         break;
   2549     case OP_MOVE_RESULT_WIDE:
   2550         copyRegister2(workRegs, decInsn.vA, RESULT_REGISTER(insnRegCountPlus));
   2551         break;
   2552 
   2553     case OP_MOVE_EXCEPTION:
   2554         /*
   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.
   2559          */
   2560         setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
   2561         break;
   2562 
   2563     case OP_RETURN_VOID:
   2564     case OP_RETURN:
   2565     case OP_RETURN_WIDE:
   2566     case OP_RETURN_OBJECT:
   2567         break;
   2568 
   2569     case OP_CONST_4:
   2570     case OP_CONST_16:
   2571     case OP_CONST:
   2572         /* could be boolean, int, float, or a null reference */
   2573         setRegisterType(workRegs, decInsn.vA,
   2574             dvmDetermineCat1Const((s4)decInsn.vB));
   2575         break;
   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));
   2580         break;
   2581     case OP_CONST_WIDE_16:
   2582     case OP_CONST_WIDE_32:
   2583     case OP_CONST_WIDE:
   2584     case OP_CONST_WIDE_HIGH16:
   2585         /* could be long or double; default to long and allow conversion */
   2586         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2587         break;
   2588     case OP_CONST_STRING:
   2589     case OP_CONST_STRING_JUMBO:
   2590     case OP_CONST_CLASS:
   2591         setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
   2592         break;
   2593 
   2594     case OP_MONITOR_ENTER:
   2595     case OP_MONITOR_EXIT:
   2596         break;
   2597 
   2598     case OP_CHECK_CAST:
   2599         setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
   2600         break;
   2601     case OP_INSTANCE_OF:
   2602         /* result is boolean */
   2603         setRegisterType(workRegs, decInsn.vA, kRegTypeBoolean);
   2604         break;
   2605 
   2606     case OP_ARRAY_LENGTH:
   2607         setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
   2608         break;
   2609 
   2610     case OP_NEW_INSTANCE:
   2611     case OP_NEW_ARRAY:
   2612         /* add the new uninitialized reference to the register ste */
   2613         setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
   2614         break;
   2615     case OP_FILLED_NEW_ARRAY:
   2616     case OP_FILLED_NEW_ARRAY_RANGE:
   2617         setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
   2618             kRegTypeReference);
   2619         justSetResult = true;
   2620         break;
   2621 
   2622     case OP_CMPL_FLOAT:
   2623     case OP_CMPG_FLOAT:
   2624         setRegisterType(workRegs, decInsn.vA, kRegTypeBoolean);
   2625         break;
   2626     case OP_CMPL_DOUBLE:
   2627     case OP_CMPG_DOUBLE:
   2628         setRegisterType(workRegs, decInsn.vA, kRegTypeBoolean);
   2629         break;
   2630     case OP_CMP_LONG:
   2631         setRegisterType(workRegs, decInsn.vA, kRegTypeBoolean);
   2632         break;
   2633 
   2634     case OP_THROW:
   2635     case OP_GOTO:
   2636     case OP_GOTO_16:
   2637     case OP_GOTO_32:
   2638     case OP_PACKED_SWITCH:
   2639     case OP_SPARSE_SWITCH:
   2640         break;
   2641 
   2642     case OP_FILL_ARRAY_DATA:
   2643         break;
   2644 
   2645     case OP_IF_EQ:
   2646     case OP_IF_NE:
   2647     case OP_IF_LT:
   2648     case OP_IF_GE:
   2649     case OP_IF_GT:
   2650     case OP_IF_LE:
   2651     case OP_IF_EQZ:
   2652     case OP_IF_NEZ:
   2653     case OP_IF_LTZ:
   2654     case OP_IF_GEZ:
   2655     case OP_IF_GTZ:
   2656     case OP_IF_LEZ:
   2657         break;
   2658 
   2659     case OP_AGET:
   2660         tmpType = kRegTypeInteger;
   2661         goto aget_1nr_common;
   2662     case OP_AGET_BOOLEAN:
   2663         tmpType = kRegTypeBoolean;
   2664         goto aget_1nr_common;
   2665     case OP_AGET_BYTE:
   2666         tmpType = kRegTypeByte;
   2667         goto aget_1nr_common;
   2668     case OP_AGET_CHAR:
   2669         tmpType = kRegTypeChar;
   2670         goto aget_1nr_common;
   2671     case OP_AGET_SHORT:
   2672         tmpType = kRegTypeShort;
   2673         goto aget_1nr_common;
   2674 aget_1nr_common:
   2675         setRegisterType(workRegs, decInsn.vA, tmpType);
   2676         break;
   2677 
   2678     case OP_AGET_WIDE:
   2679         /*
   2680          * We know this is either long or double, and we don't really
   2681          * discriminate between those during verification, so we
   2682          * call it a long.
   2683          */
   2684         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2685         break;
   2686 
   2687     case OP_AGET_OBJECT:
   2688         setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
   2689         break;
   2690 
   2691     case OP_APUT:
   2692     case OP_APUT_BOOLEAN:
   2693     case OP_APUT_BYTE:
   2694     case OP_APUT_CHAR:
   2695     case OP_APUT_SHORT:
   2696     case OP_APUT_WIDE:
   2697     case OP_APUT_OBJECT:
   2698         break;
   2699 
   2700     case OP_IGET:
   2701         tmpType = kRegTypeInteger;
   2702         goto iget_1nr_common;
   2703     case OP_IGET_BOOLEAN:
   2704         tmpType = kRegTypeBoolean;
   2705         goto iget_1nr_common;
   2706     case OP_IGET_BYTE:
   2707         tmpType = kRegTypeByte;
   2708         goto iget_1nr_common;
   2709     case OP_IGET_CHAR:
   2710         tmpType = kRegTypeChar;
   2711         goto iget_1nr_common;
   2712     case OP_IGET_SHORT:
   2713         tmpType = kRegTypeShort;
   2714         goto iget_1nr_common;
   2715 iget_1nr_common:
   2716         setRegisterType(workRegs, decInsn.vA, tmpType);
   2717         break;
   2718 
   2719     case OP_IGET_WIDE:
   2720         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2721         break;
   2722 
   2723     case OP_IGET_OBJECT:
   2724         setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
   2725         break;
   2726 
   2727     case OP_IPUT:
   2728     case OP_IPUT_BOOLEAN:
   2729     case OP_IPUT_BYTE:
   2730     case OP_IPUT_CHAR:
   2731     case OP_IPUT_SHORT:
   2732     case OP_IPUT_WIDE:
   2733     case OP_IPUT_OBJECT:
   2734         break;
   2735 
   2736     case OP_SGET:
   2737         tmpType = kRegTypeInteger;
   2738         goto sget_1nr_common;
   2739     case OP_SGET_BOOLEAN:
   2740         tmpType = kRegTypeBoolean;
   2741         goto sget_1nr_common;
   2742     case OP_SGET_BYTE:
   2743         tmpType = kRegTypeByte;
   2744         goto sget_1nr_common;
   2745     case OP_SGET_CHAR:
   2746         tmpType = kRegTypeChar;
   2747         goto sget_1nr_common;
   2748     case OP_SGET_SHORT:
   2749         tmpType = kRegTypeShort;
   2750         goto sget_1nr_common;
   2751 sget_1nr_common:
   2752         setRegisterType(workRegs, decInsn.vA, tmpType);
   2753         break;
   2754 
   2755     case OP_SGET_WIDE:
   2756         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2757         break;
   2758 
   2759     case OP_SGET_OBJECT:
   2760         setRegisterType(workRegs, decInsn.vA, kRegTypeReference);
   2761         break;
   2762 
   2763     case OP_SPUT:
   2764     case OP_SPUT_BOOLEAN:
   2765     case OP_SPUT_BYTE:
   2766     case OP_SPUT_CHAR:
   2767     case OP_SPUT_SHORT:
   2768     case OP_SPUT_WIDE:
   2769     case OP_SPUT_OBJECT:
   2770         break;
   2771 
   2772     case OP_INVOKE_VIRTUAL:
   2773     case OP_INVOKE_VIRTUAL_RANGE:
   2774     case OP_INVOKE_SUPER:
   2775     case OP_INVOKE_SUPER_RANGE:
   2776         {
   2777             Method* calledMethod;
   2778 
   2779             calledMethod = getInvokedMethod(meth, &decInsn, METHOD_VIRTUAL);
   2780             if (calledMethod == NULL)
   2781                 goto bail;
   2782             setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
   2783                 getMethodReturnType(calledMethod));
   2784             justSetResult = true;
   2785         }
   2786         break;
   2787     case OP_INVOKE_DIRECT:
   2788     case OP_INVOKE_DIRECT_RANGE:
   2789         {
   2790             Method* calledMethod;
   2791 
   2792             calledMethod = getInvokedMethod(meth, &decInsn, METHOD_DIRECT);
   2793             if (calledMethod == NULL)
   2794                 goto bail;
   2795             setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
   2796                 getMethodReturnType(calledMethod));
   2797             justSetResult = true;
   2798         }
   2799         break;
   2800     case OP_INVOKE_STATIC:
   2801     case OP_INVOKE_STATIC_RANGE:
   2802         {
   2803             Method* calledMethod;
   2804 
   2805             calledMethod = getInvokedMethod(meth, &decInsn, METHOD_STATIC);
   2806             if (calledMethod == NULL)
   2807                 goto bail;
   2808             setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
   2809                 getMethodReturnType(calledMethod));
   2810             justSetResult = true;
   2811         }
   2812         break;
   2813     case OP_INVOKE_INTERFACE:
   2814     case OP_INVOKE_INTERFACE_RANGE:
   2815         {
   2816             Method* absMethod;
   2817 
   2818             absMethod = getInvokedMethod(meth, &decInsn, METHOD_INTERFACE);
   2819             if (absMethod == NULL)
   2820                 goto bail;
   2821             setRegisterType(workRegs, RESULT_REGISTER(insnRegCountPlus),
   2822                 getMethodReturnType(absMethod));
   2823             justSetResult = true;
   2824         }
   2825         break;
   2826 
   2827     case OP_NEG_INT:
   2828     case OP_NOT_INT:
   2829         setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
   2830         break;
   2831     case OP_NEG_LONG:
   2832     case OP_NOT_LONG:
   2833         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2834         break;
   2835     case OP_NEG_FLOAT:
   2836         setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
   2837         break;
   2838     case OP_NEG_DOUBLE:
   2839         setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
   2840         break;
   2841     case OP_INT_TO_LONG:
   2842         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2843         break;
   2844     case OP_INT_TO_FLOAT:
   2845         setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
   2846         break;
   2847     case OP_INT_TO_DOUBLE:
   2848         setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
   2849         break;
   2850     case OP_LONG_TO_INT:
   2851         setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
   2852         break;
   2853     case OP_LONG_TO_FLOAT:
   2854         setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
   2855         break;
   2856     case OP_LONG_TO_DOUBLE:
   2857         setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
   2858         break;
   2859     case OP_FLOAT_TO_INT:
   2860         setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
   2861         break;
   2862     case OP_FLOAT_TO_LONG:
   2863         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2864         break;
   2865     case OP_FLOAT_TO_DOUBLE:
   2866         setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
   2867         break;
   2868     case OP_DOUBLE_TO_INT:
   2869         setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
   2870         break;
   2871     case OP_DOUBLE_TO_LONG:
   2872         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2873         break;
   2874     case OP_DOUBLE_TO_FLOAT:
   2875         setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
   2876         break;
   2877     case OP_INT_TO_BYTE:
   2878         setRegisterType(workRegs, decInsn.vA, kRegTypeByte);
   2879         break;
   2880     case OP_INT_TO_CHAR:
   2881         setRegisterType(workRegs, decInsn.vA, kRegTypeChar);
   2882         break;
   2883     case OP_INT_TO_SHORT:
   2884         setRegisterType(workRegs, decInsn.vA, kRegTypeShort);
   2885         break;
   2886 
   2887     case OP_ADD_INT:
   2888     case OP_SUB_INT:
   2889     case OP_MUL_INT:
   2890     case OP_REM_INT:
   2891     case OP_DIV_INT:
   2892     case OP_SHL_INT:
   2893     case OP_SHR_INT:
   2894     case OP_USHR_INT:
   2895     case OP_AND_INT:
   2896     case OP_OR_INT:
   2897     case OP_XOR_INT:
   2898         setRegisterType(workRegs, decInsn.vA, kRegTypeInteger);
   2899         break;
   2900     case OP_ADD_LONG:
   2901     case OP_SUB_LONG:
   2902     case OP_MUL_LONG:
   2903     case OP_DIV_LONG:
   2904     case OP_REM_LONG:
   2905     case OP_AND_LONG:
   2906     case OP_OR_LONG:
   2907     case OP_XOR_LONG:
   2908     case OP_SHL_LONG:
   2909     case OP_SHR_LONG:
   2910     case OP_USHR_LONG:
   2911         setRegisterType(workRegs, decInsn.vA, kRegTypeLongLo);
   2912         break;
   2913     case OP_ADD_FLOAT:
   2914     case OP_SUB_FLOAT:
   2915     case OP_MUL_FLOAT:
   2916     case OP_DIV_FLOAT:
   2917     case OP_REM_FLOAT:
   2918         setRegisterType(workRegs, decInsn.vA, kRegTypeFloat);
   2919         break;
   2920     case OP_ADD_DOUBLE:
   2921     case OP_SUB_DOUBLE:
   2922     case OP_MUL_DOUBLE:
   2923     case OP_DIV_DOUBLE:
   2924     case OP_REM_DOUBLE:
   2925         setRegisterType(workRegs, decInsn.vA, kRegTypeDoubleLo);
   2926         break;
   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);
   2939         break;
   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);
   2952         break;
   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);
   2959         break;
   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);
   2966         break;
   2967     case OP_ADD_INT_LIT16:
   2968     case OP_RSUB_INT:
   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);
   2987         break;
   2988 
   2989 
   2990     /*
   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.
   2995      *
   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.
   2999      */
   3000     case OP_EXECUTE_INLINE:
   3001     case OP_EXECUTE_INLINE_RANGE:
   3002     case OP_INVOKE_DIRECT_EMPTY:
   3003     case OP_IGET_QUICK:
   3004     case OP_IGET_WIDE_QUICK:
   3005     case OP_IGET_OBJECT_QUICK:
   3006     case OP_IPUT_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
   3018         break;
   3019 
   3020 
   3021     /* these should never appear */
   3022     case OP_UNUSED_3E:
   3023     case OP_UNUSED_3F:
   3024     case OP_UNUSED_40:
   3025     case OP_UNUSED_41:
   3026     case OP_UNUSED_42:
   3027     case OP_UNUSED_43:
   3028     case OP_UNUSED_73:
   3029     case OP_UNUSED_79:
   3030     case OP_UNUSED_7A:
   3031     case OP_UNUSED_E3:
   3032     case OP_UNUSED_E4:
   3033     case OP_UNUSED_E5:
   3034     case OP_UNUSED_E6:
   3035     case OP_UNUSED_E7:
   3036     case OP_BREAKPOINT:
   3037     case OP_UNUSED_ED:
   3038     case OP_UNUSED_F1:
   3039     case OP_UNUSED_FC:
   3040     case OP_UNUSED_FD:
   3041     case OP_UNUSED_FE:
   3042     case OP_UNUSED_FF:
   3043         dvmAbort();
   3044         break;
   3045 
   3046     /*
   3047      * DO NOT add a "default" clause here.  Without it the compiler will
   3048      * complain if an instruction is missing (which is desirable).
   3049      */
   3050     }
   3051 
   3052 
   3053     /*
   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
   3056      * the verifier.
   3057      */
   3058     if (!justSetResult) {
   3059         int reg = RESULT_REGISTER(pState->insnRegCountPlus);
   3060         workRegs[reg] = workRegs[reg+1] = kRegTypeUnknown;
   3061     }
   3062 
   3063     /*
   3064      * Handle "continue".  Tag the next consecutive instruction.
   3065      */
   3066     if ((nextFlags & kInstrCanContinue) != 0) {
   3067         int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx);
   3068 
   3069         /*
   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.
   3074          */
   3075         if (getRegisterLine(pState, insnIdx+insnWidth) != NULL) {
   3076             updateRegisters(pState, insnIdx+insnWidth, workRegs);
   3077         } else {
   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)
   3082             {
   3083                 dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true);
   3084             }
   3085         }
   3086     }
   3087 
   3088     /*
   3089      * Handle "branch".  Tag the branch target.
   3090      */
   3091     if ((nextFlags & kInstrCanBranch) != 0) {
   3092         bool isConditional;
   3093 
   3094         dvmGetBranchTarget(meth, insnFlags, insnIdx, &branchTarget,
   3095                 &isConditional);
   3096         assert(isConditional || (nextFlags & kInstrCanContinue) == 0);
   3097         assert(!isConditional || (nextFlags & kInstrCanContinue) != 0);
   3098 
   3099         updateRegisters(pState, insnIdx+branchTarget, workRegs);
   3100     }
   3101 
   3102     /*
   3103      * Handle "switch".  Tag all possible branch targets.
   3104      */
   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;
   3110 
   3111         if ((*insns & 0xff) == OP_PACKED_SWITCH) {
   3112             /* 0=sig, 1=count, 2/3=firstKey */
   3113             offsetToTargets = 4;
   3114         } else {
   3115             /* 0=sig, 1=count, 2..count*2 = keys */
   3116             assert((*insns & 0xff) == OP_SPARSE_SWITCH);
   3117             offsetToTargets = 2 + 2*switchCount;
   3118         }
   3119 
   3120         /* verify each switch target */
   3121         for (targ = 0; targ < switchCount; targ++) {
   3122             int offset, absOffset;
   3123 
   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);
   3129 
   3130             updateRegisters(pState, absOffset, workRegs);
   3131         }
   3132     }
   3133 
   3134     /*
   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.)
   3138      */
   3139     if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
   3140     {
   3141         DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
   3142         const DexCode* pCode = dvmGetMethodCode(meth);
   3143         DexCatchIterator iterator;
   3144 
   3145         if (dexFindCatchHandler(&iterator, pCode, insnIdx)) {
   3146             while (true) {
   3147                 DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
   3148                 if (handler == NULL)
   3149                     break;
   3150 
   3151                 /* note we use entryRegs, not workRegs */
   3152                 updateRegisters(pState, handler->address, entryRegs);
   3153             }
   3154         }
   3155     }
   3156 
   3157     /*
   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.
   3162      */
   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;
   3168     }
   3169 
   3170     assert(*pStartGuess >= 0 && *pStartGuess < pState->insnsSize &&
   3171         dvmInsnGetWidth(insnFlags, *pStartGuess) != 0);
   3172 
   3173     result = true;
   3174 
   3175 bail:
   3176     return result;
   3177 }
   3178 
   3179 
   3180 /*
   3181  * Merge two SRegType values.
   3182  *
   3183  * Sets "*pChanged" to "true" if the result doesn't match "type1".
   3184  */
   3185 static SRegType mergeTypes(SRegType type1, SRegType type2, bool* pChanged)
   3186 {
   3187     SRegType result;
   3188 
   3189     /*
   3190      * Check for trivial case so we don't have to hit memory.
   3191      */
   3192     if (type1 == type2)
   3193         return type1;
   3194 
   3195     /*
   3196      * Use the table if we can, and reject any attempts to merge something
   3197      * from the table with a reference type.
   3198      *
   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.
   3202      */
   3203     if (type1 < kRegTypeMAX) {
   3204         if (type2 < kRegTypeMAX) {
   3205             result = gDvmMergeTab[type1][type2];
   3206         } else {
   3207             /* simple + reference == conflict, usually */
   3208             if (type1 == kRegTypeZero)
   3209                 result = type2;
   3210             else
   3211                 result = kRegTypeConflict;
   3212         }
   3213     } else {
   3214         if (type2 < kRegTypeMAX) {
   3215             /* reference + simple == conflict, usually */
   3216             if (type2 == kRegTypeZero)
   3217                 result = type1;
   3218             else
   3219                 result = kRegTypeConflict;
   3220         } else {
   3221             /* merging two references */
   3222             assert(type1 == type2);
   3223             result = type1;
   3224         }
   3225     }
   3226 
   3227     if (result != type1)
   3228         *pChanged = true;
   3229     return result;
   3230 }
   3231 
   3232 /*
   3233  * Control can transfer to "nextInsn".
   3234  *
   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.
   3237  */
   3238 static void updateRegisters(WorkState* pState, int nextInsn,
   3239     const SRegType* workRegs)
   3240 {
   3241     const Method* meth = pState->method;
   3242     InsnFlags* insnFlags = pState->insnFlags;
   3243     const int insnRegCountPlus = pState->insnRegCountPlus;
   3244     SRegType* targetRegs = getRegisterLine(pState, nextInsn);
   3245 
   3246     if (!dvmInsnIsVisitedOrChanged(insnFlags, nextInsn)) {
   3247         /*
   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.)
   3253          */
   3254         LOGVV("COPY into 0x%04x\n", nextInsn);
   3255         copyRegisters(targetRegs, workRegs, insnRegCountPlus);
   3256         dvmInsnSetChanged(insnFlags, nextInsn, true);
   3257     } else {
   3258         /* merge registers, set Changed only if different */
   3259         LOGVV("MERGE into 0x%04x\n", nextInsn);
   3260         bool changed = false;
   3261         int i;
   3262 
   3263         for (i = 0; i < insnRegCountPlus; i++) {
   3264             targetRegs[i] = mergeTypes(targetRegs[i], workRegs[i], &changed);
   3265         }
   3266 
   3267         if (changed)
   3268             dvmInsnSetChanged(insnFlags, nextInsn, true);
   3269     }
   3270 }
   3271 
   3272 #endif /*#if 0*/
   3273