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 "UniquePtr.h"
     25 #include "analysis/CodeVerify.h"
     26 #include "analysis/RegisterMap.h"
     27 #include "libdex/DexCatch.h"
     28 #include "libdex/InstrUtils.h"
     29 #include "libdex/Leb128.h"
     30 
     31 #include <stddef.h>
     32 
     33 /* double-check the compression */
     34 #define REGISTER_MAP_VERIFY     false
     35 
     36 /* verbose logging */
     37 #define REGISTER_MAP_VERBOSE    false
     38 
     39 //#define REGISTER_MAP_STATS
     40 
     41 // fwd
     42 static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data);
     43 static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap);
     44 static int compareMaps(const RegisterMap* pMap1, const RegisterMap* pMap2);
     45 
     46 #ifdef REGISTER_MAP_STATS
     47 static void computeMapStats(RegisterMap* pMap, const Method* method);
     48 #endif
     49 static RegisterMap* compressMapDifferential(const RegisterMap* pMap,\
     50     const Method* meth);
     51 static RegisterMap* uncompressMapDifferential(const RegisterMap* pMap);
     52 
     53 #ifdef REGISTER_MAP_STATS
     54 /*
     55  * Generate some statistics on the register maps we create and use.
     56  */
     57 #define kMaxGcPointGap      50
     58 #define kUpdatePosnMinRegs  24
     59 #define kNumUpdatePosns     8
     60 #define kMaxDiffBits        20
     61 struct MapStats {
     62     /*
     63      * Buckets measuring the distance between GC points.  This tells us how
     64      * many bits we need to encode the advancing program counter.  We ignore
     65      * some of the "long tail" entries.
     66      */
     67     int gcPointGap[kMaxGcPointGap];
     68 
     69     /*
     70      * Number of gaps.  Equal to (number of gcPoints - number of methods),
     71      * since the computation isn't including the initial gap.
     72      */
     73     int gcGapCount;
     74 
     75     /*
     76      * Number of gaps.
     77      */
     78     int totalGcPointCount;
     79 
     80     /*
     81      * For larger methods (>= 24 registers), measure in which octant register
     82      * updates occur.  This should help us understand whether register
     83      * changes tend to cluster in the low regs even for large methods.
     84      */
     85     int updatePosn[kNumUpdatePosns];
     86 
     87     /*
     88      * For all methods, count up the number of changes to registers < 16
     89      * and >= 16.
     90      */
     91     int updateLT16;
     92     int updateGE16;
     93 
     94     /*
     95      * Histogram of the number of bits that differ between adjacent entries.
     96      */
     97     int numDiffBits[kMaxDiffBits];
     98 
     99 
    100     /*
    101      * Track the number of expanded maps, and the heap space required to
    102      * hold them.
    103      */
    104     int numExpandedMaps;
    105     int totalExpandedMapSize;
    106 };
    107 #endif
    108 
    109 /*
    110  * Prepare some things.
    111  */
    112 bool dvmRegisterMapStartup()
    113 {
    114 #ifdef REGISTER_MAP_STATS
    115     MapStats* pStats = calloc(1, sizeof(MapStats));
    116     gDvm.registerMapStats = pStats;
    117 #endif
    118     return true;
    119 }
    120 
    121 /*
    122  * Clean up.
    123  */
    124 void dvmRegisterMapShutdown()
    125 {
    126 #ifdef REGISTER_MAP_STATS
    127     free(gDvm.registerMapStats);
    128 #endif
    129 }
    130 
    131 /*
    132  * Write stats to log file.
    133  */
    134 void dvmRegisterMapDumpStats()
    135 {
    136 #ifdef REGISTER_MAP_STATS
    137     MapStats* pStats = (MapStats*) gDvm.registerMapStats;
    138     int i, end;
    139 
    140     for (end = kMaxGcPointGap-1; end >= 0; end--) {
    141         if (pStats->gcPointGap[end] != 0)
    142             break;
    143     }
    144 
    145     ALOGI("Register Map gcPointGap stats (diff count=%d, total=%d):",
    146         pStats->gcGapCount, pStats->totalGcPointCount);
    147     assert(pStats->gcPointGap[0] == 0);
    148     for (i = 1; i <= end; i++) {
    149         ALOGI(" %2d %d", i, pStats->gcPointGap[i]);
    150     }
    151 
    152 
    153     for (end = kMaxDiffBits-1; end >= 0; end--) {
    154         if (pStats->numDiffBits[end] != 0)
    155             break;
    156     }
    157 
    158     ALOGI("Register Map bit difference stats:");
    159     for (i = 0; i <= end; i++) {
    160         ALOGI(" %2d %d", i, pStats->numDiffBits[i]);
    161     }
    162 
    163 
    164     ALOGI("Register Map update position stats (lt16=%d ge16=%d):",
    165         pStats->updateLT16, pStats->updateGE16);
    166     for (i = 0; i < kNumUpdatePosns; i++) {
    167         ALOGI(" %2d %d", i, pStats->updatePosn[i]);
    168     }
    169 #endif
    170 }
    171 
    172 
    173 /*
    174  * ===========================================================================
    175  *      Map generation
    176  * ===========================================================================
    177  */
    178 
    179 /*
    180  * Generate the register map for a method that has just been verified
    181  * (i.e. we're doing this as part of verification).
    182  *
    183  * For type-precise determination we have all the data we need, so we
    184  * just need to encode it in some clever fashion.
    185  *
    186  * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
    187  */
    188 RegisterMap* dvmGenerateRegisterMapV(VerifierData* vdata)
    189 {
    190     static const int kHeaderSize = offsetof(RegisterMap, data);
    191     RegisterMap* pMap = NULL;
    192     RegisterMap* pResult = NULL;
    193     RegisterMapFormat format;
    194     u1 regWidth;
    195     u1* mapData;
    196     int i, bytesForAddr, gcPointCount;
    197     int bufSize;
    198 
    199     if (vdata->method->registersSize >= 2048) {
    200         ALOGE("ERROR: register map can't handle %d registers",
    201             vdata->method->registersSize);
    202         goto bail;
    203     }
    204     regWidth = (vdata->method->registersSize + 7) / 8;
    205 
    206     /*
    207      * Decide if we need 8 or 16 bits to hold the address.  Strictly speaking
    208      * we only need 16 bits if we actually encode an address >= 256 -- if
    209      * the method has a section at the end without GC points (e.g. array
    210      * data) we don't need to count it.  The situation is unusual, and
    211      * detecting it requires scanning the entire method, so we don't bother.
    212      */
    213     if (vdata->insnsSize < 256) {
    214         format = kRegMapFormatCompact8;
    215         bytesForAddr = 1;
    216     } else {
    217         format = kRegMapFormatCompact16;
    218         bytesForAddr = 2;
    219     }
    220 
    221     /*
    222      * Count up the number of GC point instructions.
    223      *
    224      * NOTE: this does not automatically include the first instruction,
    225      * since we don't count method entry as a GC point.
    226      */
    227     gcPointCount = 0;
    228     for (i = 0; i < (int) vdata->insnsSize; i++) {
    229         if (dvmInsnIsGcPoint(vdata->insnFlags, i))
    230             gcPointCount++;
    231     }
    232     if (gcPointCount >= 65536) {
    233         /* we could handle this, but in practice we don't get near this */
    234         ALOGE("ERROR: register map can't handle %d gc points in one method",
    235             gcPointCount);
    236         goto bail;
    237     }
    238 
    239     /*
    240      * Allocate a buffer to hold the map data.
    241      */
    242     bufSize = kHeaderSize + gcPointCount * (bytesForAddr + regWidth);
    243 
    244     ALOGV("+++ grm: %s.%s (adr=%d gpc=%d rwd=%d bsz=%d)",
    245         vdata->method->clazz->descriptor, vdata->method->name,
    246         bytesForAddr, gcPointCount, regWidth, bufSize);
    247 
    248     pMap = (RegisterMap*) malloc(bufSize);
    249     dvmRegisterMapSetFormat(pMap, format);
    250     dvmRegisterMapSetOnHeap(pMap, true);
    251     dvmRegisterMapSetRegWidth(pMap, regWidth);
    252     dvmRegisterMapSetNumEntries(pMap, gcPointCount);
    253 
    254     /*
    255      * Populate it.
    256      */
    257     mapData = pMap->data;
    258     for (i = 0; i < (int) vdata->insnsSize; i++) {
    259         if (dvmInsnIsGcPoint(vdata->insnFlags, i)) {
    260             assert(vdata->registerLines[i].regTypes != NULL);
    261             if (format == kRegMapFormatCompact8) {
    262                 *mapData++ = i;
    263             } else /*kRegMapFormatCompact16*/ {
    264                 *mapData++ = i & 0xff;
    265                 *mapData++ = i >> 8;
    266             }
    267             outputTypeVector(vdata->registerLines[i].regTypes,
    268                 vdata->insnRegCount, mapData);
    269             mapData += regWidth;
    270         }
    271     }
    272 
    273     ALOGV("mapData=%p pMap=%p bufSize=%d", mapData, pMap, bufSize);
    274     assert(mapData - (const u1*) pMap == bufSize);
    275 
    276     if (REGISTER_MAP_VERIFY && !verifyMap(vdata, pMap))
    277         goto bail;
    278 #ifdef REGISTER_MAP_STATS
    279     computeMapStats(pMap, vdata->method);
    280 #endif
    281 
    282     /*
    283      * Try to compress the map.
    284      */
    285     RegisterMap* pCompMap;
    286 
    287     pCompMap = compressMapDifferential(pMap, vdata->method);
    288     if (pCompMap != NULL) {
    289         if (REGISTER_MAP_VERIFY) {
    290             /*
    291              * Expand the compressed map we just created, and compare it
    292              * to the original.  Abort the VM if it doesn't match up.
    293              */
    294             RegisterMap* pUncompMap;
    295             pUncompMap = uncompressMapDifferential(pCompMap);
    296             if (pUncompMap == NULL) {
    297                 ALOGE("Map failed to uncompress - %s.%s",
    298                     vdata->method->clazz->descriptor,
    299                     vdata->method->name);
    300                 free(pCompMap);
    301                 /* bad - compression is broken or we're out of memory */
    302                 dvmAbort();
    303             } else {
    304                 if (compareMaps(pMap, pUncompMap) != 0) {
    305                     ALOGE("Map comparison failed - %s.%s",
    306                         vdata->method->clazz->descriptor,
    307                         vdata->method->name);
    308                     free(pCompMap);
    309                     /* bad - compression is broken */
    310                     dvmAbort();
    311                 }
    312 
    313                 /* verify succeeded */
    314                 delete pUncompMap;
    315             }
    316         }
    317 
    318         if (REGISTER_MAP_VERBOSE) {
    319             ALOGD("Good compress on %s.%s",
    320                 vdata->method->clazz->descriptor,
    321                 vdata->method->name);
    322         }
    323         free(pMap);
    324         pMap = pCompMap;
    325     } else {
    326         if (REGISTER_MAP_VERBOSE) {
    327             ALOGD("Unable to compress %s.%s (ent=%d rw=%d)",
    328                 vdata->method->clazz->descriptor,
    329                 vdata->method->name,
    330                 dvmRegisterMapGetNumEntries(pMap),
    331                 dvmRegisterMapGetRegWidth(pMap));
    332         }
    333     }
    334 
    335     pResult = pMap;
    336 
    337 bail:
    338     return pResult;
    339 }
    340 
    341 /*
    342  * Release the storage held by a RegisterMap.
    343  */
    344 void dvmFreeRegisterMap(RegisterMap* pMap)
    345 {
    346     if (pMap == NULL)
    347         return;
    348 
    349     assert(dvmRegisterMapGetOnHeap(pMap));
    350     free(pMap);
    351 }
    352 
    353 /*
    354  * Determine if the RegType value is a reference type.
    355  *
    356  * Ordinarily we include kRegTypeZero in the "is it a reference"
    357  * check.  There's no value in doing so here, because we know
    358  * the register can't hold anything but zero.
    359  */
    360 static inline bool isReferenceType(RegType type)
    361 {
    362     return (type > kRegTypeMAX || type == kRegTypeUninit);
    363 }
    364 
    365 /*
    366  * Given a line of registers, output a bit vector that indicates whether
    367  * or not the register holds a reference type (which could be null).
    368  *
    369  * We use '1' to indicate it's a reference, '0' for anything else (numeric
    370  * value, uninitialized data, merge conflict).  Register 0 will be found
    371  * in the low bit of the first byte.
    372  */
    373 static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data)
    374 {
    375     u1 val = 0;
    376     int i;
    377 
    378     for (i = 0; i < insnRegCount; i++) {
    379         RegType type = *regs++;
    380         val >>= 1;
    381         if (isReferenceType(type))
    382             val |= 0x80;        /* set hi bit */
    383 
    384         if ((i & 0x07) == 7)
    385             *data++ = val;
    386     }
    387     if ((i & 0x07) != 0) {
    388         /* flush bits from last byte */
    389         val >>= 8 - (i & 0x07);
    390         *data++ = val;
    391     }
    392 }
    393 
    394 /*
    395  * Print the map as a series of binary strings.
    396  *
    397  * Pass in method->registersSize if known, or -1 if not.
    398  */
    399 static void dumpRegisterMap(const RegisterMap* pMap, int registersSize)
    400 {
    401     const u1* rawMap = pMap->data;
    402     const RegisterMapFormat format = dvmRegisterMapGetFormat(pMap);
    403     const int numEntries = dvmRegisterMapGetNumEntries(pMap);
    404     const int regWidth = dvmRegisterMapGetRegWidth(pMap);
    405     int addrWidth;
    406 
    407     switch (format) {
    408     case kRegMapFormatCompact8:
    409         addrWidth = 1;
    410         break;
    411     case kRegMapFormatCompact16:
    412         addrWidth = 2;
    413         break;
    414     default:
    415         /* can't happen */
    416         ALOGE("Can only dump Compact8 / Compact16 maps (not %d)", format);
    417         return;
    418     }
    419 
    420     if (registersSize < 0)
    421         registersSize = 8 * regWidth;
    422     assert(registersSize <= regWidth * 8);
    423 
    424     int ent;
    425     for (ent = 0; ent < numEntries; ent++) {
    426         int i, addr;
    427 
    428         addr = *rawMap++;
    429         if (addrWidth > 1)
    430             addr |= (*rawMap++) << 8;
    431 
    432         const u1* dataStart = rawMap;
    433         u1 val = 0;
    434 
    435         /* create binary string */
    436         char outBuf[registersSize +1];
    437         for (i = 0; i < registersSize; i++) {
    438             val >>= 1;
    439             if ((i & 0x07) == 0)
    440                 val = *rawMap++;
    441 
    442             outBuf[i] = '0' + (val & 0x01);
    443         }
    444         outBuf[i] = '\0';
    445 
    446         /* back up and create hex dump */
    447         char hexBuf[regWidth * 3 +1];
    448         char* cp = hexBuf;
    449         rawMap = dataStart;
    450         for (i = 0; i < regWidth; i++) {
    451             sprintf(cp, " %02x", *rawMap++);
    452             cp += 3;
    453         }
    454         hexBuf[i * 3] = '\0';
    455 
    456         ALOGD("  %04x %s %s", addr, outBuf, hexBuf);
    457     }
    458 }
    459 
    460 /*
    461  * Double-check the map.
    462  *
    463  * We run through all of the data in the map, and compare it to the original.
    464  * Only works on uncompressed data.
    465  */
    466 static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap)
    467 {
    468     const u1* rawMap = pMap->data;
    469     const RegisterMapFormat format = dvmRegisterMapGetFormat(pMap);
    470     const int numEntries = dvmRegisterMapGetNumEntries(pMap);
    471     int ent;
    472     bool dumpMap = false;
    473 
    474     if (false) {
    475         const char* cd = "Landroid/net/http/Request;";
    476         const char* mn = "readResponse";
    477         if (strcmp(vdata->method->clazz->descriptor, cd) == 0 &&
    478             strcmp(vdata->method->name, mn) == 0)
    479         {
    480             char* desc;
    481             desc = dexProtoCopyMethodDescriptor(&vdata->method->prototype);
    482             ALOGI("Map for %s.%s %s", vdata->method->clazz->descriptor,
    483                 vdata->method->name, desc);
    484             free(desc);
    485 
    486             dumpMap = true;
    487         }
    488     }
    489 
    490     if ((vdata->method->registersSize + 7) / 8 != pMap->regWidth) {
    491         ALOGE("GLITCH: registersSize=%d, regWidth=%d",
    492             vdata->method->registersSize, pMap->regWidth);
    493         return false;
    494     }
    495 
    496     for (ent = 0; ent < numEntries; ent++) {
    497         int addr;
    498 
    499         switch (format) {
    500         case kRegMapFormatCompact8:
    501             addr = *rawMap++;
    502             break;
    503         case kRegMapFormatCompact16:
    504             addr = *rawMap++;
    505             addr |= (*rawMap++) << 8;
    506             break;
    507         default:
    508             /* shouldn't happen */
    509             ALOGE("GLITCH: bad format (%d)", format);
    510             dvmAbort();
    511             /* Make compiler happy */
    512             addr = 0;
    513         }
    514 
    515         const RegType* regs = vdata->registerLines[addr].regTypes;
    516         if (regs == NULL) {
    517             ALOGE("GLITCH: addr %d has no data", addr);
    518             return false;
    519         }
    520 
    521         u1 val = 0;
    522         int i;
    523 
    524         for (i = 0; i < vdata->method->registersSize; i++) {
    525             bool bitIsRef, regIsRef;
    526 
    527             val >>= 1;
    528             if ((i & 0x07) == 0) {
    529                 /* load next byte of data */
    530                 val = *rawMap++;
    531             }
    532 
    533             bitIsRef = val & 0x01;
    534 
    535             RegType type = regs[i];
    536             regIsRef = isReferenceType(type);
    537 
    538             if (bitIsRef != regIsRef) {
    539                 ALOGE("GLITCH: addr %d reg %d: bit=%d reg=%d(%d)",
    540                     addr, i, bitIsRef, regIsRef, type);
    541                 return false;
    542             }
    543         }
    544 
    545         /* rawMap now points to the address field of the next entry */
    546     }
    547 
    548     if (dumpMap)
    549         dumpRegisterMap(pMap, vdata->method->registersSize);
    550 
    551     return true;
    552 }
    553 
    554 
    555 /*
    556  * ===========================================================================
    557  *      DEX generation & parsing
    558  * ===========================================================================
    559  */
    560 
    561 /*
    562  * Advance "ptr" to ensure 32-bit alignment.
    563  */
    564 static inline u1* align32(u1* ptr)
    565 {
    566     return (u1*) (((int) ptr + 3) & ~0x03);
    567 }
    568 
    569 /*
    570  * Compute the size, in bytes, of a register map.
    571  */
    572 static size_t computeRegisterMapSize(const RegisterMap* pMap)
    573 {
    574     static const int kHeaderSize = offsetof(RegisterMap, data);
    575     u1 format = dvmRegisterMapGetFormat(pMap);
    576     u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
    577 
    578     assert(pMap != NULL);
    579 
    580     switch (format) {
    581     case kRegMapFormatNone:
    582         return 1;
    583     case kRegMapFormatCompact8:
    584         return kHeaderSize + (1 + pMap->regWidth) * numEntries;
    585     case kRegMapFormatCompact16:
    586         return kHeaderSize + (2 + pMap->regWidth) * numEntries;
    587     case kRegMapFormatDifferential:
    588         {
    589             /* kHeaderSize + decoded ULEB128 length */
    590             const u1* ptr = pMap->data;
    591             int len = readUnsignedLeb128(&ptr);
    592             return len + (ptr - (u1*) pMap);
    593         }
    594     default:
    595         ALOGE("Bad register map format %d", format);
    596         dvmAbort();
    597         return 0;
    598     }
    599 }
    600 
    601 /*
    602  * Output the map for a single method, if it has one.
    603  *
    604  * Abstract and native methods have no map.  All others are expected to
    605  * have one, since we know the class verified successfully.
    606  *
    607  * This strips the "allocated on heap" flag from the format byte, so that
    608  * direct-mapped maps are correctly identified as such.
    609  */
    610 static bool writeMapForMethod(const Method* meth, u1** pPtr)
    611 {
    612     if (meth->registerMap == NULL) {
    613         if (!dvmIsAbstractMethod(meth) && !dvmIsNativeMethod(meth)) {
    614             ALOGW("Warning: no map available for %s.%s",
    615                 meth->clazz->descriptor, meth->name);
    616             /* weird, but keep going */
    617         }
    618         *(*pPtr)++ = kRegMapFormatNone;
    619         return true;
    620     }
    621 
    622     /* serialize map into the buffer */
    623     size_t mapSize = computeRegisterMapSize(meth->registerMap);
    624     memcpy(*pPtr, meth->registerMap, mapSize);
    625 
    626     /* strip the "on heap" flag out of the format byte, which is always first */
    627     assert(**pPtr == meth->registerMap->format);
    628     **pPtr &= ~(kRegMapFormatOnHeap);
    629 
    630     *pPtr += mapSize;
    631 
    632     return true;
    633 }
    634 
    635 /*
    636  * Write maps for all methods in the specified class to the buffer, which
    637  * can hold at most "length" bytes.  "*pPtr" will be advanced past the end
    638  * of the data we write.
    639  */
    640 static bool writeMapsAllMethods(DvmDex* pDvmDex, const ClassObject* clazz,
    641     u1** pPtr, size_t length)
    642 {
    643     RegisterMapMethodPool* pMethodPool;
    644     u1* ptr = *pPtr;
    645     int i, methodCount;
    646 
    647     /* artificial limit */
    648     if (clazz->virtualMethodCount + clazz->directMethodCount >= 65536) {
    649         ALOGE("Too many methods in %s", clazz->descriptor);
    650         return false;
    651     }
    652 
    653     pMethodPool = (RegisterMapMethodPool*) ptr;
    654     ptr += offsetof(RegisterMapMethodPool, methodData);
    655     methodCount = 0;
    656 
    657     /*
    658      * Run through all methods, direct then virtual.  The class loader will
    659      * traverse them in the same order.  (We could split them into two
    660      * distinct pieces, but there doesn't appear to be any value in doing
    661      * so other than that it makes class loading slightly less fragile.)
    662      *
    663      * The class loader won't know about miranda methods at the point
    664      * where it parses this, so we omit those.
    665      *
    666      * TODO: consider omitting all native/abstract definitions.  Should be
    667      * safe, though we lose the ability to sanity-check against the
    668      * method counts in the DEX file.
    669      */
    670     for (i = 0; i < clazz->directMethodCount; i++) {
    671         const Method* meth = &clazz->directMethods[i];
    672         if (dvmIsMirandaMethod(meth))
    673             continue;
    674         if (!writeMapForMethod(&clazz->directMethods[i], &ptr)) {
    675             return false;
    676         }
    677         methodCount++;
    678         //ptr = align32(ptr);
    679     }
    680 
    681     for (i = 0; i < clazz->virtualMethodCount; i++) {
    682         const Method* meth = &clazz->virtualMethods[i];
    683         if (dvmIsMirandaMethod(meth))
    684             continue;
    685         if (!writeMapForMethod(&clazz->virtualMethods[i], &ptr)) {
    686             return false;
    687         }
    688         methodCount++;
    689         //ptr = align32(ptr);
    690     }
    691 
    692     pMethodPool->methodCount = methodCount;
    693 
    694     *pPtr = ptr;
    695     return true;
    696 }
    697 
    698 /*
    699  * Write maps for all classes to the specified buffer, which can hold at
    700  * most "length" bytes.
    701  *
    702  * Returns the actual length used, or 0 on failure.
    703  */
    704 static size_t writeMapsAllClasses(DvmDex* pDvmDex, u1* basePtr, size_t length)
    705 {
    706     DexFile* pDexFile = pDvmDex->pDexFile;
    707     u4 count = pDexFile->pHeader->classDefsSize;
    708     RegisterMapClassPool* pClassPool;
    709     u4* offsetTable;
    710     u1* ptr = basePtr;
    711     u4 idx;
    712 
    713     assert(gDvm.optimizing);
    714 
    715     pClassPool = (RegisterMapClassPool*) ptr;
    716     ptr += offsetof(RegisterMapClassPool, classDataOffset);
    717     offsetTable = (u4*) ptr;
    718     ptr += count * sizeof(u4);
    719 
    720     pClassPool->numClasses = count;
    721 
    722     /*
    723      * We want an entry for every class, loaded or not.
    724      */
    725     for (idx = 0; idx < count; idx++) {
    726         const DexClassDef* pClassDef;
    727         const char* classDescriptor;
    728         ClassObject* clazz;
    729 
    730         pClassDef = dexGetClassDef(pDexFile, idx);
    731         classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
    732 
    733         /*
    734          * All classes have been loaded into the bootstrap class loader.
    735          * If we can find it, and it was successfully pre-verified, we
    736          * run through its methods and add the register maps.
    737          *
    738          * If it wasn't pre-verified then we know it can't have any
    739          * register maps.  Classes that can't be loaded or failed
    740          * verification get an empty slot in the index.
    741          */
    742         clazz = NULL;
    743         if ((pClassDef->accessFlags & CLASS_ISPREVERIFIED) != 0)
    744             clazz = dvmLookupClass(classDescriptor, NULL, false);
    745 
    746         if (clazz != NULL) {
    747             offsetTable[idx] = ptr - basePtr;
    748             LOGVV("%d -> offset %d (%p-%p)",
    749                 idx, offsetTable[idx], ptr, basePtr);
    750 
    751             if (!writeMapsAllMethods(pDvmDex, clazz, &ptr,
    752                     length - (ptr - basePtr)))
    753             {
    754                 return 0;
    755             }
    756 
    757             ptr = align32(ptr);
    758             LOGVV("Size %s (%d+%d methods): %d", clazz->descriptor,
    759                 clazz->directMethodCount, clazz->virtualMethodCount,
    760                 (ptr - basePtr) - offsetTable[idx]);
    761         } else {
    762             ALOGV("%4d NOT mapadding '%s'", idx, classDescriptor);
    763             assert(offsetTable[idx] == 0);
    764         }
    765     }
    766 
    767     if (ptr - basePtr >= (int)length) {
    768         /* a bit late */
    769         ALOGE("Buffer overrun");
    770         dvmAbort();
    771     }
    772 
    773     return ptr - basePtr;
    774 }
    775 
    776 /*
    777  * Generate a register map set for all verified classes in "pDvmDex".
    778  */
    779 RegisterMapBuilder* dvmGenerateRegisterMaps(DvmDex* pDvmDex)
    780 {
    781     RegisterMapBuilder* pBuilder;
    782 
    783     pBuilder = (RegisterMapBuilder*) calloc(1, sizeof(RegisterMapBuilder));
    784     if (pBuilder == NULL)
    785         return NULL;
    786 
    787     /*
    788      * We have a couple of options here:
    789      *  (1) Compute the size of the output, and malloc a buffer.
    790      *  (2) Create a "large-enough" anonymous mmap region.
    791      *
    792      * The nice thing about option #2 is that we don't have to traverse
    793      * all of the classes and methods twice.  The risk is that we might
    794      * not make the region large enough.  Since the pages aren't mapped
    795      * until used we can allocate a semi-absurd amount of memory without
    796      * worrying about the effect on the rest of the system.
    797      *
    798      * The basic encoding on the largest jar file requires about 1MB of
    799      * storage.  We map out 4MB here.  (TODO: guarantee that the last
    800      * page of the mapping is marked invalid, so we reliably fail if
    801      * we overrun.)
    802      */
    803     if (sysCreatePrivateMap(4 * 1024 * 1024, &pBuilder->memMap) != 0) {
    804         free(pBuilder);
    805         return NULL;
    806     }
    807 
    808     /*
    809      * Create the maps.
    810      */
    811     size_t actual = writeMapsAllClasses(pDvmDex, (u1*)pBuilder->memMap.addr,
    812                                         pBuilder->memMap.length);
    813     if (actual == 0) {
    814         dvmFreeRegisterMapBuilder(pBuilder);
    815         return NULL;
    816     }
    817 
    818     ALOGV("TOTAL size of register maps: %d", actual);
    819 
    820     pBuilder->data = pBuilder->memMap.addr;
    821     pBuilder->size = actual;
    822     return pBuilder;
    823 }
    824 
    825 /*
    826  * Free the builder.
    827  */
    828 void dvmFreeRegisterMapBuilder(RegisterMapBuilder* pBuilder)
    829 {
    830     if (pBuilder == NULL)
    831         return;
    832 
    833     sysReleaseShmem(&pBuilder->memMap);
    834     free(pBuilder);
    835 }
    836 
    837 
    838 /*
    839  * Find the data for the specified class.
    840  *
    841  * If there's no register map data, or none for this class, we return NULL.
    842  */
    843 const void* dvmRegisterMapGetClassData(const DexFile* pDexFile, u4 classIdx,
    844     u4* pNumMaps)
    845 {
    846     const RegisterMapClassPool* pClassPool;
    847     const RegisterMapMethodPool* pMethodPool;
    848 
    849     pClassPool = (const RegisterMapClassPool*) pDexFile->pRegisterMapPool;
    850     if (pClassPool == NULL)
    851         return NULL;
    852 
    853     if (classIdx >= pClassPool->numClasses) {
    854         ALOGE("bad class index (%d vs %d)", classIdx, pClassPool->numClasses);
    855         dvmAbort();
    856     }
    857 
    858     u4 classOffset = pClassPool->classDataOffset[classIdx];
    859     if (classOffset == 0) {
    860         ALOGV("+++ no map for classIdx=%d", classIdx);
    861         return NULL;
    862     }
    863 
    864     pMethodPool =
    865         (const RegisterMapMethodPool*) (((u1*) pClassPool) + classOffset);
    866     if (pNumMaps != NULL)
    867         *pNumMaps = pMethodPool->methodCount;
    868     return pMethodPool->methodData;
    869 }
    870 
    871 /*
    872  * This advances "*pPtr" and returns its original value.
    873  */
    874 const RegisterMap* dvmRegisterMapGetNext(const void** pPtr)
    875 {
    876     const RegisterMap* pMap = (const RegisterMap*) *pPtr;
    877 
    878     *pPtr = /*align32*/(((u1*) pMap) + computeRegisterMapSize(pMap));
    879     LOGVV("getNext: %p -> %p (f=%#x w=%d e=%d)",
    880         pMap, *pPtr, pMap->format, pMap->regWidth,
    881         dvmRegisterMapGetNumEntries(pMap));
    882     return pMap;
    883 }
    884 
    885 
    886 /*
    887  * ===========================================================================
    888  *      Utility functions
    889  * ===========================================================================
    890  */
    891 
    892 /*
    893  * Return the data for the specified address, or NULL if not found.
    894  *
    895  * The result must be released with dvmReleaseRegisterMapLine().
    896  */
    897 const u1* dvmRegisterMapGetLine(const RegisterMap* pMap, int addr)
    898 {
    899     int addrWidth, lineWidth;
    900     u1 format = dvmRegisterMapGetFormat(pMap);
    901     u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
    902 
    903     assert(numEntries > 0);
    904 
    905     switch (format) {
    906     case kRegMapFormatNone:
    907         return NULL;
    908     case kRegMapFormatCompact8:
    909         addrWidth = 1;
    910         break;
    911     case kRegMapFormatCompact16:
    912         addrWidth = 2;
    913         break;
    914     default:
    915         ALOGE("Unknown format %d", format);
    916         dvmAbort();
    917         return NULL;
    918     }
    919 
    920     lineWidth = addrWidth + pMap->regWidth;
    921 
    922     /*
    923      * Find the appropriate entry.  Many maps are very small, some are very
    924      * large.
    925      */
    926     static const int kSearchThreshold = 8;
    927     const u1* data = NULL;
    928     int lineAddr;
    929 
    930     if (numEntries < kSearchThreshold) {
    931         int i;
    932         data = pMap->data;
    933         for (i = numEntries; i > 0; i--) {
    934             lineAddr = data[0];
    935             if (addrWidth > 1)
    936                 lineAddr |= data[1] << 8;
    937             if (lineAddr == addr)
    938                 return data + addrWidth;
    939 
    940             data += lineWidth;
    941         }
    942         assert(data == pMap->data + lineWidth * numEntries);
    943     } else {
    944         int hi, lo, mid;
    945 
    946         lo = 0;
    947         hi = numEntries -1;
    948 
    949         while (hi >= lo) {
    950             mid = (hi + lo) / 2;
    951             data = pMap->data + lineWidth * mid;
    952 
    953             lineAddr = data[0];
    954             if (addrWidth > 1)
    955                 lineAddr |= data[1] << 8;
    956 
    957             if (addr > lineAddr) {
    958                 lo = mid + 1;
    959             } else if (addr < lineAddr) {
    960                 hi = mid - 1;
    961             } else {
    962                 return data + addrWidth;
    963             }
    964         }
    965     }
    966 
    967     return NULL;
    968 }
    969 
    970 /*
    971  * Compare two register maps.
    972  *
    973  * Returns 0 if they're equal, nonzero if not.
    974  */
    975 static int compareMaps(const RegisterMap* pMap1, const RegisterMap* pMap2)
    976 {
    977     size_t size1, size2;
    978 
    979     size1 = computeRegisterMapSize(pMap1);
    980     size2 = computeRegisterMapSize(pMap2);
    981     if (size1 != size2) {
    982         ALOGI("compareMaps: size mismatch (%zd vs %zd)", size1, size2);
    983         return -1;
    984     }
    985 
    986     if (memcmp(pMap1, pMap2, size1) != 0) {
    987         ALOGI("compareMaps: content mismatch");
    988         return -1;
    989     }
    990 
    991     return 0;
    992 }
    993 
    994 
    995 /*
    996  * Get the expanded form of the register map associated with the method.
    997  *
    998  * If the map is already in one of the uncompressed formats, we return
    999  * immediately.  Otherwise, we expand the map and replace method's register
   1000  * map pointer, freeing it if it was allocated on the heap.
   1001  *
   1002  * NOTE: this function is not synchronized; external locking is mandatory
   1003  * (unless we're in the zygote, where single-threaded access is guaranteed).
   1004  */
   1005 const RegisterMap* dvmGetExpandedRegisterMap0(Method* method)
   1006 {
   1007     const RegisterMap* curMap = method->registerMap;
   1008     RegisterMap* newMap;
   1009 
   1010     if (curMap == NULL)
   1011         return NULL;
   1012 
   1013     /* sanity check to ensure this isn't called w/o external locking */
   1014     /* (if we use this at a time other than during GC, fix/remove this test) */
   1015     if (true) {
   1016         if (!gDvm.zygote && dvmTryLockMutex(&gDvm.gcHeapLock) == 0) {
   1017             ALOGE("GLITCH: dvmGetExpandedRegisterMap not called at GC time");
   1018             dvmAbort();
   1019         }
   1020     }
   1021 
   1022     RegisterMapFormat format = dvmRegisterMapGetFormat(curMap);
   1023     switch (format) {
   1024     case kRegMapFormatCompact8:
   1025     case kRegMapFormatCompact16:
   1026         if (REGISTER_MAP_VERBOSE) {
   1027             if (dvmRegisterMapGetOnHeap(curMap)) {
   1028                 ALOGD("RegMap: already expanded: %s.%s",
   1029                     method->clazz->descriptor, method->name);
   1030             } else {
   1031                 ALOGD("RegMap: stored w/o compression: %s.%s",
   1032                     method->clazz->descriptor, method->name);
   1033             }
   1034         }
   1035         return curMap;
   1036     case kRegMapFormatDifferential:
   1037         newMap = uncompressMapDifferential(curMap);
   1038         break;
   1039     default:
   1040         ALOGE("Unknown format %d in dvmGetExpandedRegisterMap", format);
   1041         dvmAbort();
   1042         newMap = NULL;      // make gcc happy
   1043     }
   1044 
   1045     if (newMap == NULL) {
   1046         ALOGE("Map failed to uncompress (fmt=%d) %s.%s",
   1047             format, method->clazz->descriptor, method->name);
   1048         return NULL;
   1049     }
   1050 
   1051 #ifdef REGISTER_MAP_STATS
   1052     /*
   1053      * Gather and display some stats.
   1054      */
   1055     {
   1056         MapStats* pStats = (MapStats*) gDvm.registerMapStats;
   1057         pStats->numExpandedMaps++;
   1058         pStats->totalExpandedMapSize += computeRegisterMapSize(newMap);
   1059         ALOGD("RMAP: count=%d size=%d",
   1060             pStats->numExpandedMaps, pStats->totalExpandedMapSize);
   1061     }
   1062 #endif
   1063 
   1064     IF_ALOGV() {
   1065         char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
   1066         ALOGV("Expanding map -> %s.%s:%s",
   1067             method->clazz->descriptor, method->name, desc);
   1068         free(desc);
   1069     }
   1070 
   1071     /*
   1072      * Update method, and free compressed map if it was sitting on the heap.
   1073      */
   1074     dvmSetRegisterMap(method, newMap);
   1075 
   1076     if (dvmRegisterMapGetOnHeap(curMap))
   1077         dvmFreeRegisterMap((RegisterMap*) curMap);
   1078 
   1079     return newMap;
   1080 }
   1081 
   1082 
   1083 /*
   1084  * ===========================================================================
   1085  *      Map compression
   1086  * ===========================================================================
   1087  */
   1088 
   1089 /*
   1090 Notes on map compression
   1091 
   1092 The idea is to create a compressed form that will be uncompressed before
   1093 use, with the output possibly saved in a cache.  This means we can use an
   1094 approach that is unsuited for random access if we choose.
   1095 
   1096 In the event that a map simply does not work with our compression scheme,
   1097 it's reasonable to store the map without compression.  In the future we
   1098 may want to have more than one compression scheme, and try each in turn,
   1099 retaining the best.  (We certainly want to keep the uncompressed form if it
   1100 turns out to be smaller or even slightly larger than the compressed form.)
   1101 
   1102 Each entry consists of an address and a bit vector.  Adjacent entries are
   1103 strongly correlated, suggesting differential encoding.
   1104 
   1105 
   1106 Ideally we would avoid outputting adjacent entries with identical
   1107 bit vectors.  However, the register values at a given address do not
   1108 imply anything about the set of valid registers at subsequent addresses.
   1109 We therefore cannot omit an entry.
   1110 
   1111   If the thread stack has a PC at an address without a corresponding
   1112   entry in the register map, we must conservatively scan the registers in
   1113   that thread.  This can happen when single-stepping in the debugger,
   1114   because the debugger is allowed to invoke arbitrary methods when
   1115   a thread is stopped at a breakpoint.  If we can guarantee that a GC
   1116   thread scan will never happen while the debugger has that thread stopped,
   1117   then we can lift this restriction and simply omit entries that don't
   1118   change the bit vector from its previous state.
   1119 
   1120 Each entry advances the address value by at least 1 (measured in 16-bit
   1121 "code units").  Looking at the bootclasspath entries, advancing by 2 units
   1122 is most common.  Advances by 1 unit are far less common than advances by
   1123 2 units, but more common than 5, and things fall off rapidly.  Gaps of
   1124 up to 220 code units appear in some computationally intensive bits of code,
   1125 but are exceedingly rare.
   1126 
   1127 If we sum up the number of transitions in a couple of ranges in framework.jar:
   1128   [1,4]: 188998 of 218922 gaps (86.3%)
   1129   [1,7]: 211647 of 218922 gaps (96.7%)
   1130 Using a 3-bit delta, with one value reserved as an escape code, should
   1131 yield good results for the address.
   1132 
   1133 These results would change dramatically if we reduced the set of GC
   1134 points by e.g. removing instructions like integer divide that are only
   1135 present because they can throw and cause an allocation.
   1136 
   1137 We also need to include an "initial gap", because the first few instructions
   1138 in a method may not be GC points.
   1139 
   1140 
   1141 By observation, many entries simply repeat the previous bit vector, or
   1142 change only one or two bits.  (This is with type-precise information;
   1143 the rate of change of bits will be different if live-precise information
   1144 is factored in).
   1145 
   1146 Looking again at adjacent entries in framework.jar:
   1147   0 bits changed: 63.0%
   1148   1 bit changed: 32.2%
   1149 After that it falls off rapidly, e.g. the number of entries with 2 bits
   1150 changed is usually less than 1/10th of the number of entries with 1 bit
   1151 changed.  A solution that allows us to encode 0- or 1- bit changes
   1152 efficiently will do well.
   1153 
   1154 We still need to handle cases where a large number of bits change.  We
   1155 probably want a way to drop in a full copy of the bit vector when it's
   1156 smaller than the representation of multiple bit changes.
   1157 
   1158 
   1159 The bit-change information can be encoded as an index that tells the
   1160 decoder to toggle the state.  We want to encode the index in as few bits
   1161 as possible, but we need to allow for fairly wide vectors (e.g. we have a
   1162 method with 175 registers).  We can deal with this in a couple of ways:
   1163 (1) use an encoding that assumes few registers and has an escape code
   1164 for larger numbers of registers; or (2) use different encodings based
   1165 on how many total registers the method has.  The choice depends to some
   1166 extent on whether methods with large numbers of registers tend to modify
   1167 the first 16 regs more often than the others.
   1168 
   1169 The last N registers hold method arguments.  If the bytecode is expected
   1170 to be examined in a debugger, "dx" ensures that the contents of these
   1171 registers won't change.  Depending upon the encoding format, we may be
   1172 able to take advantage of this.  We still have to encode the initial
   1173 state, but we know we'll never have to output a bit change for the last
   1174 N registers.
   1175 
   1176 Considering only methods with 16 or more registers, the "target octant"
   1177 for register changes looks like this:
   1178   [ 43.1%, 16.4%, 6.5%, 6.2%, 7.4%, 8.8%, 9.7%, 1.8% ]
   1179 As expected, there are fewer changes at the end of the list where the
   1180 arguments are kept, and more changes at the start of the list because
   1181 register values smaller than 16 can be used in compact Dalvik instructions
   1182 and hence are favored for frequently-used values.  In general, the first
   1183 octant is considerably more active than later entries, the last octant
   1184 is much less active, and the rest are all about the same.
   1185 
   1186 Looking at all bit changes in all methods, 94% are to registers 0-15.  The
   1187 encoding will benefit greatly by favoring the low-numbered registers.
   1188 
   1189 
   1190 Some of the smaller methods have identical maps, and space could be
   1191 saved by simply including a pointer to an earlier definition.  This would
   1192 be best accomplished by specifying a "pointer" format value, followed by
   1193 a 3-byte (or ULEB128) offset.  Implementing this would probably involve
   1194 generating a hash value for each register map and maintaining a hash table.
   1195 
   1196 In some cases there are repeating patterns in the bit vector that aren't
   1197 adjacent.  These could benefit from a dictionary encoding.  This doesn't
   1198 really become useful until the methods reach a certain size though,
   1199 and managing the dictionary may incur more overhead than we want.
   1200 
   1201 Large maps can be compressed significantly.  The trouble is that, when
   1202 we need to use them, we have to uncompress them onto the heap.  We may
   1203 get a better trade-off between storage size and heap usage by refusing to
   1204 compress large maps, so that they can be memory mapped and used directly.
   1205 (OTOH, only about 2% of the maps will ever actually be used.)
   1206 
   1207 
   1208 ----- differential format -----
   1209 
   1210 // common header
   1211 +00 1B format
   1212 +01 1B regWidth
   1213 +02 2B numEntries (little-endian)
   1214 +04 nB length in bytes of the data that follows, in ULEB128 format
   1215        (not strictly necessary; allows determination of size w/o full parse)
   1216 +05+ 1B initial address (0-127), high bit set if max addr >= 256
   1217 +06+ nB initial value for bit vector
   1218 
   1219 // for each entry
   1220 +00: CCCCBAAA
   1221 
   1222   AAA: address difference.  Values from 0 to 6 indicate an increment of 1
   1223   to 7.  A value of 7 indicates that the address difference is large,
   1224   and the next byte is a ULEB128-encoded difference value.
   1225 
   1226   B: determines the meaning of CCCC.
   1227 
   1228   CCCC: if B is 0, this is the number of the bit to toggle (0-15).
   1229   If B is 1, this is a count of the number of changed bits (1-14).  A value
   1230   of 0 means that no bits were changed, and a value of 15 indicates
   1231   that enough bits were changed that it required less space to output
   1232   the entire bit vector.
   1233 
   1234 +01: (optional) ULEB128-encoded address difference
   1235 
   1236 +01+: (optional) one or more ULEB128-encoded bit numbers, OR the entire
   1237   bit vector.
   1238 
   1239 The most common situation is an entry whose address has changed by 2-4
   1240 code units, has no changes or just a single bit change, and the changed
   1241 register is less than 16.  We should therefore be able to encode a large
   1242 number of entries with a single byte, which is half the size of the
   1243 Compact8 encoding method.
   1244 */
   1245 
   1246 /*
   1247  * Compute some stats on an uncompressed register map.
   1248  */
   1249 #ifdef REGISTER_MAP_STATS
   1250 static void computeMapStats(RegisterMap* pMap, const Method* method)
   1251 {
   1252     MapStats* pStats = (MapStats*) gDvm.registerMapStats;
   1253     const u1 format = dvmRegisterMapGetFormat(pMap);
   1254     const u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
   1255     const u1* rawMap = pMap->data;
   1256     const u1* prevData = NULL;
   1257     int ent, addr, prevAddr = -1;
   1258 
   1259     for (ent = 0; ent < numEntries; ent++) {
   1260         switch (format) {
   1261         case kRegMapFormatCompact8:
   1262             addr = *rawMap++;
   1263             break;
   1264         case kRegMapFormatCompact16:
   1265             addr = *rawMap++;
   1266             addr |= (*rawMap++) << 8;
   1267             break;
   1268         default:
   1269             /* shouldn't happen */
   1270             ALOGE("GLITCH: bad format (%d)", format);
   1271             dvmAbort();
   1272         }
   1273 
   1274         const u1* dataStart = rawMap;
   1275 
   1276         pStats->totalGcPointCount++;
   1277 
   1278         /*
   1279          * Gather "gap size" stats, i.e. the difference in addresses between
   1280          * successive GC points.
   1281          */
   1282         if (prevData != NULL) {
   1283             assert(prevAddr >= 0);
   1284             int addrDiff = addr - prevAddr;
   1285 
   1286             if (addrDiff < 0) {
   1287                 ALOGE("GLITCH: address went backward (0x%04x->0x%04x, %s.%s)",
   1288                     prevAddr, addr, method->clazz->descriptor, method->name);
   1289             } else if (addrDiff > kMaxGcPointGap) {
   1290                 if (REGISTER_MAP_VERBOSE) {
   1291                     ALOGI("HEY: addrDiff is %d, max %d (0x%04x->0x%04x %s.%s)",
   1292                         addrDiff, kMaxGcPointGap, prevAddr, addr,
   1293                         method->clazz->descriptor, method->name);
   1294                 }
   1295                 /* skip this one */
   1296             } else {
   1297                 pStats->gcPointGap[addrDiff]++;
   1298             }
   1299             pStats->gcGapCount++;
   1300 
   1301 
   1302             /*
   1303              * Compare bit vectors in adjacent entries.  We want to count
   1304              * up the number of bits that differ (to see if we frequently
   1305              * change 0 or 1 bits) and get a sense for which part of the
   1306              * vector changes the most often (near the start, middle, end).
   1307              *
   1308              * We only do the vector position quantization if we have at
   1309              * least 16 registers in the method.
   1310              */
   1311             int numDiff = 0;
   1312             float div = (float) kNumUpdatePosns / method->registersSize;
   1313             int regByte;
   1314             for (regByte = 0; regByte < pMap->regWidth; regByte++) {
   1315                 int prev, cur, bit;
   1316 
   1317                 prev = prevData[regByte];
   1318                 cur = dataStart[regByte];
   1319 
   1320                 for (bit = 0; bit < 8; bit++) {
   1321                     if (((prev >> bit) & 1) != ((cur >> bit) & 1)) {
   1322                         numDiff++;
   1323 
   1324                         int bitNum = regByte * 8 + bit;
   1325 
   1326                         if (bitNum < 16)
   1327                             pStats->updateLT16++;
   1328                         else
   1329                             pStats->updateGE16++;
   1330 
   1331                         if (method->registersSize < 16)
   1332                             continue;
   1333 
   1334                         if (bitNum >= method->registersSize) {
   1335                             /* stuff off the end should be zero in both */
   1336                             ALOGE("WEIRD: bit=%d (%d/%d), prev=%02x cur=%02x",
   1337                                 bit, regByte, method->registersSize,
   1338                                 prev, cur);
   1339                             assert(false);
   1340                         }
   1341                         int idx = (int) (bitNum * div);
   1342                         if (!(idx >= 0 && idx < kNumUpdatePosns)) {
   1343                             ALOGE("FAIL: bitNum=%d (of %d) div=%.3f idx=%d",
   1344                                 bitNum, method->registersSize, div, idx);
   1345                             assert(false);
   1346                         }
   1347                         pStats->updatePosn[idx]++;
   1348                     }
   1349                 }
   1350             }
   1351 
   1352             if (numDiff > kMaxDiffBits) {
   1353                 if (REGISTER_MAP_VERBOSE) {
   1354                     ALOGI("WOW: numDiff is %d, max %d", numDiff, kMaxDiffBits);
   1355                 }
   1356             } else {
   1357                 pStats->numDiffBits[numDiff]++;
   1358             }
   1359         }
   1360 
   1361         /* advance to start of next line */
   1362         rawMap += pMap->regWidth;
   1363 
   1364         prevAddr = addr;
   1365         prevData = dataStart;
   1366     }
   1367 }
   1368 #endif
   1369 
   1370 /*
   1371  * Compute the difference between two bit vectors.
   1372  *
   1373  * If "lebOutBuf" is non-NULL, we output the bit indices in ULEB128 format
   1374  * as we go.  Otherwise, we just generate the various counts.
   1375  *
   1376  * The bit vectors are compared byte-by-byte, so any unused bits at the
   1377  * end must be zero.
   1378  *
   1379  * Returns the number of bytes required to hold the ULEB128 output.
   1380  *
   1381  * If "pFirstBitChanged" or "pNumBitsChanged" are non-NULL, they will
   1382  * receive the index of the first changed bit and the number of changed
   1383  * bits, respectively.
   1384  */
   1385 static int computeBitDiff(const u1* bits1, const u1* bits2, int byteWidth,
   1386     int* pFirstBitChanged, int* pNumBitsChanged, u1* lebOutBuf)
   1387 {
   1388     int numBitsChanged = 0;
   1389     int firstBitChanged = -1;
   1390     int lebSize = 0;
   1391     int byteNum;
   1392 
   1393     /*
   1394      * Run through the vectors, first comparing them at the byte level.  This
   1395      * will yield a fairly quick result if nothing has changed between them.
   1396      */
   1397     for (byteNum = 0; byteNum < byteWidth; byteNum++) {
   1398         u1 byte1 = *bits1++;
   1399         u1 byte2 = *bits2++;
   1400         if (byte1 != byte2) {
   1401             /*
   1402              * Walk through the byte, identifying the changed bits.
   1403              */
   1404             int bitNum;
   1405             for (bitNum = 0; bitNum < 8; bitNum++) {
   1406                 if (((byte1 >> bitNum) & 0x01) != ((byte2 >> bitNum) & 0x01)) {
   1407                     int bitOffset = (byteNum << 3) + bitNum;
   1408 
   1409                     if (firstBitChanged < 0)
   1410                         firstBitChanged = bitOffset;
   1411                     numBitsChanged++;
   1412 
   1413                     if (lebOutBuf == NULL) {
   1414                         lebSize += unsignedLeb128Size(bitOffset);
   1415                     } else {
   1416                         u1* curBuf = lebOutBuf;
   1417                         lebOutBuf = writeUnsignedLeb128(lebOutBuf, bitOffset);
   1418                         lebSize += lebOutBuf - curBuf;
   1419                     }
   1420                 }
   1421             }
   1422         }
   1423     }
   1424 
   1425     if (numBitsChanged > 0)
   1426         assert(firstBitChanged >= 0);
   1427 
   1428     if (pFirstBitChanged != NULL)
   1429         *pFirstBitChanged = firstBitChanged;
   1430     if (pNumBitsChanged != NULL)
   1431         *pNumBitsChanged = numBitsChanged;
   1432 
   1433     return lebSize;
   1434 }
   1435 
   1436 /*
   1437  * Compress the register map with differential encoding.
   1438  *
   1439  * "meth" is only needed for debug output.
   1440  *
   1441  * On success, returns a newly-allocated RegisterMap.  If the map is not
   1442  * compatible for some reason, or fails to get smaller, this will return NULL.
   1443  */
   1444 static RegisterMap* compressMapDifferential(const RegisterMap* pMap,
   1445     const Method* meth)
   1446 {
   1447     RegisterMap* pNewMap = NULL;
   1448     int origSize = computeRegisterMapSize(pMap);
   1449     u1* tmpPtr;
   1450     int addrWidth, regWidth, numEntries;
   1451     bool debug = false;
   1452 
   1453     if (false &&
   1454         strcmp(meth->clazz->descriptor, "Landroid/text/StaticLayout;") == 0 &&
   1455         strcmp(meth->name, "generate") == 0)
   1456     {
   1457         debug = true;
   1458     }
   1459 
   1460     u1 format = dvmRegisterMapGetFormat(pMap);
   1461     switch (format) {
   1462     case kRegMapFormatCompact8:
   1463         addrWidth = 1;
   1464         break;
   1465     case kRegMapFormatCompact16:
   1466         addrWidth = 2;
   1467         break;
   1468     default:
   1469         ALOGE("ERROR: can't compress map with format=%d", format);
   1470         return NULL;
   1471     }
   1472 
   1473     regWidth = dvmRegisterMapGetRegWidth(pMap);
   1474     numEntries = dvmRegisterMapGetNumEntries(pMap);
   1475 
   1476     if (debug) {
   1477         ALOGI("COMPRESS: %s.%s aw=%d rw=%d ne=%d",
   1478             meth->clazz->descriptor, meth->name,
   1479             addrWidth, regWidth, numEntries);
   1480         dumpRegisterMap(pMap, -1);
   1481     }
   1482 
   1483     if (numEntries <= 1) {
   1484         ALOGV("Can't compress map with 0 or 1 entries");
   1485         return NULL;
   1486     }
   1487 
   1488     /*
   1489      * We don't know how large the compressed data will be.  It's possible
   1490      * for it to expand and become larger than the original.  The header
   1491      * itself is variable-sized, so we generate everything into a temporary
   1492      * buffer and then copy it to form-fitting storage once we know how big
   1493      * it will be (and that it's smaller than the original).
   1494      *
   1495      * If we use a size that is equal to the size of the input map plus
   1496      * a value longer than a single entry can possibly expand to, we need
   1497      * only check for overflow at the end of each entry.  The worst case
   1498      * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
   1499      * Addresses are 16 bits, so that's (1 + 3 + regWidth).
   1500      *
   1501      * The initial address offset and bit vector will take up less than
   1502      * or equal to the amount of space required when uncompressed -- large
   1503      * initial offsets are rejected.
   1504      */
   1505     UniquePtr<u1[]> tmpBuf(new u1[origSize + (1 + 3 + regWidth)]);
   1506     if (tmpBuf.get() == NULL)
   1507         return NULL;
   1508 
   1509     tmpPtr = tmpBuf.get();
   1510 
   1511     const u1* mapData = pMap->data;
   1512     const u1* prevBits;
   1513     u2 addr, prevAddr;
   1514 
   1515     addr = *mapData++;
   1516     if (addrWidth > 1)
   1517         addr |= (*mapData++) << 8;
   1518 
   1519     if (addr >= 128) {
   1520         ALOGV("Can't compress map with starting address >= 128");
   1521         return NULL;
   1522     }
   1523 
   1524     /*
   1525      * Start by writing the initial address and bit vector data.  The high
   1526      * bit of the initial address is used to indicate the required address
   1527      * width (which the decoder can't otherwise determine without parsing
   1528      * the compressed data).
   1529      */
   1530     *tmpPtr++ = addr | (addrWidth > 1 ? 0x80 : 0x00);
   1531     memcpy(tmpPtr, mapData, regWidth);
   1532 
   1533     prevBits = mapData;
   1534     prevAddr = addr;
   1535 
   1536     tmpPtr += regWidth;
   1537     mapData += regWidth;
   1538 
   1539     /*
   1540      * Loop over all following entries.
   1541      */
   1542     for (int entry = 1; entry < numEntries; entry++) {
   1543         int addrDiff;
   1544         u1 key;
   1545 
   1546         /*
   1547          * Pull out the address and figure out how to encode it.
   1548          */
   1549         addr = *mapData++;
   1550         if (addrWidth > 1)
   1551             addr |= (*mapData++) << 8;
   1552 
   1553         if (debug)
   1554             ALOGI(" addr=0x%04x ent=%d (aw=%d)", addr, entry, addrWidth);
   1555 
   1556         addrDiff = addr - prevAddr;
   1557         assert(addrDiff > 0);
   1558         if (addrDiff < 8) {
   1559             /* small difference, encode in 3 bits */
   1560             key = addrDiff -1;          /* set 00000AAA */
   1561             if (debug)
   1562                 ALOGI(" : small %d, key=0x%02x", addrDiff, key);
   1563         } else {
   1564             /* large difference, output escape code */
   1565             key = 0x07;                 /* escape code for AAA */
   1566             if (debug)
   1567                 ALOGI(" : large %d, key=0x%02x", addrDiff, key);
   1568         }
   1569 
   1570         int numBitsChanged, firstBitChanged, lebSize;
   1571 
   1572         lebSize = computeBitDiff(prevBits, mapData, regWidth,
   1573             &firstBitChanged, &numBitsChanged, NULL);
   1574 
   1575         if (debug) {
   1576             ALOGI(" : diff fbc=%d nbc=%d ls=%d (rw=%d)",
   1577                 firstBitChanged, numBitsChanged, lebSize, regWidth);
   1578         }
   1579 
   1580         if (numBitsChanged == 0) {
   1581             /* set B to 1 and CCCC to zero to indicate no bits were changed */
   1582             key |= 0x08;
   1583             if (debug) ALOGI(" : no bits changed");
   1584         } else if (numBitsChanged == 1 && firstBitChanged < 16) {
   1585             /* set B to 0 and CCCC to the index of the changed bit */
   1586             key |= firstBitChanged << 4;
   1587             if (debug) ALOGI(" : 1 low bit changed");
   1588         } else if (numBitsChanged < 15 && lebSize < regWidth) {
   1589             /* set B to 1 and CCCC to the number of bits */
   1590             key |= 0x08 | (numBitsChanged << 4);
   1591             if (debug) ALOGI(" : some bits changed");
   1592         } else {
   1593             /* set B to 1 and CCCC to 0x0f so we store the entire vector */
   1594             key |= 0x08 | 0xf0;
   1595             if (debug) ALOGI(" : encode original");
   1596         }
   1597 
   1598         /*
   1599          * Encode output.  Start with the key, follow with the address
   1600          * diff (if it didn't fit in 3 bits), then the changed bit info.
   1601          */
   1602         *tmpPtr++ = key;
   1603         if ((key & 0x07) == 0x07)
   1604             tmpPtr = writeUnsignedLeb128(tmpPtr, addrDiff);
   1605 
   1606         if ((key & 0x08) != 0) {
   1607             int bitCount = key >> 4;
   1608             if (bitCount == 0) {
   1609                 /* nothing changed, no additional output required */
   1610             } else if (bitCount == 15) {
   1611                 /* full vector is most compact representation */
   1612                 memcpy(tmpPtr, mapData, regWidth);
   1613                 tmpPtr += regWidth;
   1614             } else {
   1615                 /* write bit indices in LEB128 format */
   1616                 (void) computeBitDiff(prevBits, mapData, regWidth,
   1617                     NULL, NULL, tmpPtr);
   1618                 tmpPtr += lebSize;
   1619             }
   1620         } else {
   1621             /* single-bit changed, value encoded in key byte */
   1622         }
   1623 
   1624         prevBits = mapData;
   1625         prevAddr = addr;
   1626         mapData += regWidth;
   1627 
   1628         /*
   1629          * See if we've run past the original size.
   1630          */
   1631         if (tmpPtr - tmpBuf.get() >= origSize) {
   1632             if (debug) {
   1633                 ALOGD("Compressed size >= original (%d vs %d): %s.%s",
   1634                     tmpPtr - tmpBuf.get(), origSize,
   1635                     meth->clazz->descriptor, meth->name);
   1636             }
   1637             return NULL;
   1638         }
   1639     }
   1640 
   1641     /*
   1642      * Create a RegisterMap with the contents.
   1643      *
   1644      * TODO: consider using a threshold other than merely ">=".  We would
   1645      * get poorer compression but potentially use less native heap space.
   1646      */
   1647     static const int kHeaderSize = offsetof(RegisterMap, data);
   1648     int newDataSize = tmpPtr - tmpBuf.get();
   1649     int newMapSize;
   1650 
   1651     newMapSize = kHeaderSize + unsignedLeb128Size(newDataSize) + newDataSize;
   1652     if (newMapSize >= origSize) {
   1653         if (debug) {
   1654             ALOGD("Final comp size >= original (%d vs %d): %s.%s",
   1655                 newMapSize, origSize, meth->clazz->descriptor, meth->name);
   1656         }
   1657         return NULL;
   1658     }
   1659 
   1660     pNewMap = (RegisterMap*) malloc(newMapSize);
   1661     if (pNewMap == NULL)
   1662         return NULL;
   1663     dvmRegisterMapSetFormat(pNewMap, kRegMapFormatDifferential);
   1664     dvmRegisterMapSetOnHeap(pNewMap, true);
   1665     dvmRegisterMapSetRegWidth(pNewMap, regWidth);
   1666     dvmRegisterMapSetNumEntries(pNewMap, numEntries);
   1667 
   1668     tmpPtr = pNewMap->data;
   1669     tmpPtr = writeUnsignedLeb128(tmpPtr, newDataSize);
   1670     memcpy(tmpPtr, tmpBuf.get(), newDataSize);
   1671 
   1672     if (REGISTER_MAP_VERBOSE) {
   1673         ALOGD("Compression successful (%d -> %d) from aw=%d rw=%d ne=%d",
   1674             computeRegisterMapSize(pMap), computeRegisterMapSize(pNewMap),
   1675             addrWidth, regWidth, numEntries);
   1676     }
   1677 
   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     static const int kHeaderSize = offsetof(RegisterMap, data);
   1700     u1 format = dvmRegisterMapGetFormat(pMap);
   1701     RegisterMapFormat newFormat;
   1702     int regWidth, numEntries, newAddrWidth, newMapSize;
   1703 
   1704     if (format != kRegMapFormatDifferential) {
   1705         ALOGE("Not differential (%d)", format);
   1706         return NULL;
   1707     }
   1708 
   1709     regWidth = dvmRegisterMapGetRegWidth(pMap);
   1710     numEntries = dvmRegisterMapGetNumEntries(pMap);
   1711 
   1712     /* get the data size; we can check this at the end */
   1713     const u1* srcPtr = pMap->data;
   1714     int expectedSrcLen = readUnsignedLeb128(&srcPtr);
   1715     const u1* srcStart = srcPtr;
   1716 
   1717     /* get the initial address and the 16-bit address flag */
   1718     int addr = *srcPtr & 0x7f;
   1719     if ((*srcPtr & 0x80) == 0) {
   1720         newFormat = kRegMapFormatCompact8;
   1721         newAddrWidth = 1;
   1722     } else {
   1723         newFormat = kRegMapFormatCompact16;
   1724         newAddrWidth = 2;
   1725     }
   1726     srcPtr++;
   1727 
   1728     /* now we know enough to allocate the new map */
   1729     if (REGISTER_MAP_VERBOSE) {
   1730         ALOGI("Expanding to map aw=%d rw=%d ne=%d",
   1731             newAddrWidth, regWidth, numEntries);
   1732     }
   1733     newMapSize = kHeaderSize + (newAddrWidth + regWidth) * numEntries;
   1734     RegisterMap* pNewMap = (RegisterMap*) malloc(newMapSize);
   1735 
   1736     if (pNewMap == NULL)
   1737       return NULL;
   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         ALOGE("ERROR: output %d bytes, expected %d",
   1817             dstPtr - (u1*) pNewMap, newMapSize);
   1818         free(pNewMap);
   1819         return NULL;
   1820     }
   1821 
   1822     if (srcPtr - srcStart != expectedSrcLen) {
   1823         ALOGE("ERROR: consumed %d bytes, expected %d",
   1824             srcPtr - srcStart, expectedSrcLen);
   1825         free(pNewMap);
   1826         return NULL;
   1827     }
   1828 
   1829     if (REGISTER_MAP_VERBOSE) {
   1830         ALOGD("Expansion successful (%d -> %d)",
   1831             computeRegisterMapSize(pMap), computeRegisterMapSize(pNewMap));
   1832     }
   1833 
   1834     return pNewMap;
   1835 }
   1836