Remove the functionality in ReduceConstants.[ch].

It was a good experiment to try, but it was never made production-ready,
and it doesn't look like it would be a net win at this point. We
metaphorically pour out a beer in its honor.

Change-Id: I7f6ac95f5b7c963df0a3015ed33595fa1a928636
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c
index 714a0f8..636408a 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.c
@@ -482,12 +482,6 @@
         case kDexChunkRegisterMaps:
             verboseStr = "register maps";
             break;
-        case kDexChunkReducingIndexMap:
-            verboseStr = "'reducing' index map";
-            break;
-        case kDexChunkExpandingIndexMap:
-            verboseStr = "'expanding' index map";
-            break;
         default:
             verboseStr = "(unknown chunk type)";
             break;
diff --git a/libdex/DexFile.h b/libdex/DexFile.h
index 279650f..06dc864 100644
--- a/libdex/DexFile.h
+++ b/libdex/DexFile.h
@@ -167,9 +167,6 @@
     kDexChunkClassLookup            = 0x434c4b50,   /* CLKP */
     kDexChunkRegisterMaps           = 0x524d4150,   /* RMAP */
 
-    kDexChunkReducingIndexMap       = 0x5249584d,   /* RIXM */
-    kDexChunkExpandingIndexMap      = 0x4549584d,   /* EIXM */
-
     kDexChunkEnd                    = 0x41454e44,   /* AEND */
 };
 
@@ -444,30 +441,6 @@
 } DexClassLookup;
 
 /*
- * Map constant pool indices from one form to another.  Some or all of these
- * may be NULL.
- *
- * The map values are 16-bit unsigned values.  If the values we map to
- * require a larger range, we omit the mapping for that category (which
- * requires that the lookup code recognize that the data will not be
- * there for all DEX files in all categories.)
- */
-typedef struct DexIndexMap {
-    const u2* classMap;         /* map, either expanding or reducing */
-    u4  classFullCount;         /* same as typeIdsSize */
-    u4  classReducedCount;      /* post-reduction count */
-    const u2* methodMap;
-    u4  methodFullCount;
-    u4  methodReducedCount;
-    const u2* fieldMap;
-    u4  fieldFullCount;
-    u4  fieldReducedCount;
-    const u2* stringMap;
-    u4  stringFullCount;
-    u4  stringReducedCount;
-} DexIndexMap;
-
-/*
  * Header added by DEX optimization pass.  Values are always written in
  * local byte and structure padding.  The first field (magic + version)
  * is guaranteed to be present and directly readable for all expected
@@ -523,7 +496,6 @@
      * included in the file.
      */
     const DexClassLookup* pClassLookup;
-    DexIndexMap         indexMap;
     const void*         pRegisterMapPool;       // RegisterMapClassPool
 
     /* points to start of DEX file data */
diff --git a/libdex/DexOptData.c b/libdex/DexOptData.c
index 995b655..10a4b5d 100644
--- a/libdex/DexOptData.c
+++ b/libdex/DexOptData.c
@@ -45,130 +45,6 @@
     return (u4) adler32(adler, start, end - start);
 }
 
-/*
- * Parse out an index map entry, advancing "*pData" and reducing "*pSize".
- */
-static bool parseIndexMapEntry(const u1** pData, u4* pSize, bool expanding,
-    u4* pFullCount, u4* pReducedCount, const u2** pMap)
-{
-    const u4* wordPtr = (const u4*) *pData;
-    u4 size = *pSize;
-    u4 mapCount;
-
-    if (expanding) {
-        if (size < 4)
-            return false;
-        mapCount = *pReducedCount = *wordPtr++;
-        *pFullCount = (u4) -1;
-        size -= sizeof(u4);
-    } else {
-        if (size < 8)
-            return false;
-        mapCount = *pFullCount = *wordPtr++;
-        *pReducedCount = *wordPtr++;
-        size -= sizeof(u4) * 2;
-    }
-
-    u4 mapSize = mapCount * sizeof(u2);
-
-    if (size < mapSize)
-        return false;
-    *pMap = (const u2*) wordPtr;
-    size -= mapSize;
-
-    /* advance the pointer */
-    const u1* ptr = (const u1*) wordPtr;
-    ptr += (mapSize + 3) & ~0x3;
-
-    /* update pass-by-reference values */
-    *pData = (const u1*) ptr;
-    *pSize = size;
-
-    return true;
-}
-
-/*
- * Set up some pointers into the mapped data.
- *
- * See analysis/ReduceConstants.c for the data layout description.
- */
-static bool parseIndexMap(DexFile* pDexFile, const u1* data, u4 size,
-    bool expanding)
-{
-    if (!parseIndexMapEntry(&data, &size, expanding,
-            &pDexFile->indexMap.classFullCount,
-            &pDexFile->indexMap.classReducedCount,
-            &pDexFile->indexMap.classMap))
-    {
-        return false;
-    }
-
-    if (!parseIndexMapEntry(&data, &size, expanding,
-            &pDexFile->indexMap.methodFullCount,
-            &pDexFile->indexMap.methodReducedCount,
-            &pDexFile->indexMap.methodMap))
-    {
-        return false;
-    }
-
-    if (!parseIndexMapEntry(&data, &size, expanding,
-            &pDexFile->indexMap.fieldFullCount,
-            &pDexFile->indexMap.fieldReducedCount,
-            &pDexFile->indexMap.fieldMap))
-    {
-        return false;
-    }
-
-    if (!parseIndexMapEntry(&data, &size, expanding,
-            &pDexFile->indexMap.stringFullCount,
-            &pDexFile->indexMap.stringReducedCount,
-            &pDexFile->indexMap.stringMap))
-    {
-        return false;
-    }
-
-    if (expanding) {
-        /*
-         * The map includes the "reduced" counts; pull the original counts
-         * out of the DexFile so that code has a consistent source.
-         */
-        assert(pDexFile->indexMap.classFullCount == (u4) -1);
-        assert(pDexFile->indexMap.methodFullCount == (u4) -1);
-        assert(pDexFile->indexMap.fieldFullCount == (u4) -1);
-        assert(pDexFile->indexMap.stringFullCount == (u4) -1);
-
-#if 0   // TODO: not available yet -- do later or just skip this
-        pDexFile->indexMap.classFullCount =
-            pDexFile->pHeader->typeIdsSize;
-        pDexFile->indexMap.methodFullCount =
-            pDexFile->pHeader->methodIdsSize;
-        pDexFile->indexMap.fieldFullCount =
-            pDexFile->pHeader->fieldIdsSize;
-        pDexFile->indexMap.stringFullCount =
-            pDexFile->pHeader->stringIdsSize;
-#endif
-    }
-
-    LOGI("Class : %u %u %u\n",
-        pDexFile->indexMap.classFullCount,
-        pDexFile->indexMap.classReducedCount,
-        pDexFile->indexMap.classMap[0]);
-    LOGI("Method: %u %u %u\n",
-        pDexFile->indexMap.methodFullCount,
-        pDexFile->indexMap.methodReducedCount,
-        pDexFile->indexMap.methodMap[0]);
-    LOGI("Field : %u %u %u\n",
-        pDexFile->indexMap.fieldFullCount,
-        pDexFile->indexMap.fieldReducedCount,
-        pDexFile->indexMap.fieldMap[0]);
-    LOGI("String: %u %u %u\n",
-        pDexFile->indexMap.stringFullCount,
-        pDexFile->indexMap.stringReducedCount,
-        pDexFile->indexMap.stringMap[0]);
-
-    return true;
-}
-
 /* (documented in header file) */
 bool dexParseOptData(const u1* data, size_t length, DexFile* pDexFile)
 {
@@ -176,7 +52,6 @@
     const void* pOptEnd = data + length;
     const u4* pOpt = pOptStart;
     u4 optLength = (const u1*) pOptEnd - (const u1*) pOptStart;
-    u4 indexMapType = 0;
 
     /*
      * Make sure the opt data start is in range and aligned. This may
@@ -233,22 +108,6 @@
         case kDexChunkClassLookup:
             pDexFile->pClassLookup = (const DexClassLookup*) pOptData;
             break;
-        case kDexChunkReducingIndexMap:
-            LOGI("+++ found reducing index map, size=%u\n", size);
-            if (!parseIndexMap(pDexFile, pOptData, size, false)) {
-                LOGE("Failed parsing reducing index map\n");
-                return false;
-            }
-            indexMapType = *pOpt;
-            break;
-        case kDexChunkExpandingIndexMap:
-            LOGI("+++ found expanding index map, size=%u\n", size);
-            if (!parseIndexMap(pDexFile, pOptData, size, true)) {
-                LOGE("Failed parsing expanding index map\n");
-                return false;
-            }
-            indexMapType = *pOpt;
-            break;
         case kDexChunkRegisterMaps:
             LOGV("+++ found register maps, size=%u\n", size);
             pDexFile->pRegisterMapPool = pOptData;
@@ -265,19 +124,5 @@
         pOpt = pNextOpt;
     }
 
-#if 0   // TODO: propagate expected map type from the VM through the API
-    /*
-     * If we're configured to expect an index map, and we don't find one,
-     * reject this DEX so we'll regenerate it.  Also, if we found an
-     * "expanding" map but we're not configured to use it, we have to fail
-     * because the constants aren't usable without translation.
-     */
-    if (indexMapType != expectedIndexMapType) {
-        LOGW("Incompatible index map configuration: found 0x%04x, need %d\n",
-            indexMapType, DVM_REDUCE_CONSTANTS);
-        return false;
-    }
-#endif
-
     return true;
 }
diff --git a/vm/Dalvik.h b/vm/Dalvik.h
index 6418bf2..5779b08 100644
--- a/vm/Dalvik.h
+++ b/vm/Dalvik.h
@@ -30,7 +30,6 @@
 #include "libdex/DexFile.h"
 #include "libdex/DexProto.h"
 #include "libdex/ZipArchive.h"
-#include "analysis/ReduceConstants.h"
 #include "DvmDex.h"
 #include "RawDexFile.h"
 #include "Sync.h"
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index d5f5e27..85fc598 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -32,9 +32,6 @@
 # Optional features.  These may impact the size or performance of the VM.
 #
 
-# 0=full cache, 1/2=reduced, 3=no cache
-LOCAL_CFLAGS += -DDVM_RESOLVER_CACHE=0
-
 ifeq ($(WITH_DEADLOCK_PREDICTION),true)
   LOCAL_CFLAGS += -DWITH_DEADLOCK_PREDICTION
   WITH_MONITOR_TRACKING := true
@@ -142,7 +139,6 @@
 	analysis/DexPrepare.c \
 	analysis/DexVerify.c \
 	analysis/Optimize.c \
-	analysis/ReduceConstants.c \
 	analysis/RegisterMap.c \
 	analysis/VerifySubs.c \
 	interp/Interp.c.arm \
diff --git a/vm/DvmDex.c b/vm/DvmDex.c
index 02dd758..94422b3 100644
--- a/vm/DvmDex.c
+++ b/vm/DvmDex.c
@@ -57,20 +57,6 @@
     methodCount = pHeader->methodIdsSize;
     fieldCount = pHeader->fieldIdsSize;
 
-#if (DVM_RESOLVER_CACHE == DVM_RC_REDUCING) || \
-    (DVM_RESOLVER_CACHE == DVM_RC_EXPANDING)
-    if (pDexFile->indexMap.stringReducedCount > 0)
-        stringCount = pDexFile->indexMap.stringReducedCount;
-    if (pDexFile->indexMap.classReducedCount > 0)
-        classCount = pDexFile->indexMap.classReducedCount;
-    if (pDexFile->indexMap.methodReducedCount > 0)
-        methodCount = pDexFile->indexMap.methodReducedCount;
-    if (pDexFile->indexMap.fieldReducedCount > 0)
-        fieldCount = pDexFile->indexMap.fieldReducedCount;
-#elif (DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE)
-    stringCount = classCount = methodCount = fieldCount = 0;
-#endif
-
     pDvmDex->pResStrings = (struct StringObject**)
         calloc(stringCount, sizeof(struct StringObject*));
 
diff --git a/vm/DvmDex.h b/vm/DvmDex.h
index 803be1f..f36940b 100644
--- a/vm/DvmDex.h
+++ b/vm/DvmDex.h
@@ -100,9 +100,6 @@
 bool dvmDexChangeDex2(DvmDex* pDvmDex, u2* addr, u2 newVal);
 
 
-#if DVM_RESOLVER_CACHE == DVM_RC_DISABLED
-/* 1:1 mapping */
-
 /*
  * Return the requested item if it has been resolved, or NULL if it hasn't.
  */
@@ -160,179 +157,4 @@
     pDvmDex->pResFields[fieldIdx] = field;
 }
 
-#elif DVM_RESOLVER_CACHE == DVM_RC_REDUCING
-/* reduce request to fit in a less-than-full-size cache table */
-
-/*
- * Return the requested item if it has been resolved, or NULL if it hasn't.
- *
- * If we have a mapping table defined for this category, but there's no
- * entry for this index, we always return NULL.  Otherwise, we return the
- * entry.  (To regain some performance we may want to assume that the
- * table exists when compiled in this mode -- avoids a null check but
- * prevents us from switching back and forth without rebuilding the VM.)
- *
- * We could save an integer compare here by ensuring that map[kNoIndexMapping]
- * always evalutes to NULL (e.g. set kNoIndexMapping = 0).
- */
-INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
-    u4 stringIdx)
-{
-    const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
-
-    assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
-    if (pIndexMap->stringReducedCount > 0) {
-        stringIdx = pIndexMap->stringMap[stringIdx];
-        if (stringIdx == kNoIndexMapping)
-            return NULL;
-    }
-    return pDvmDex->pResStrings[stringIdx];
-}
-INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
-    u4 classIdx)
-{
-    const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
-
-    assert(classIdx < pDvmDex->pHeader->typeIdsSize);
-    if (pIndexMap->classReducedCount > 0) {
-        classIdx = pIndexMap->classMap[classIdx];
-        if (classIdx == kNoIndexMapping)
-            return NULL;
-    }
-    return pDvmDex->pResClasses[classIdx];
-}
-INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
-    u4 methodIdx)
-{
-    const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
-
-    assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
-    if (pIndexMap->methodReducedCount > 0) {
-        methodIdx = pIndexMap->methodMap[methodIdx];
-        if (methodIdx == kNoIndexMapping)
-            return NULL;
-    }
-    return pDvmDex->pResMethods[methodIdx];
-}
-INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
-    u4 fieldIdx)
-{
-    const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
-
-    assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
-    if (pIndexMap->fieldReducedCount > 0) {
-        fieldIdx = pIndexMap->fieldMap[fieldIdx];
-        if (fieldIdx == kNoIndexMapping)
-            return NULL;
-    }
-    return pDvmDex->pResFields[fieldIdx];
-}
-
-/*
- * Update the resolved item table.  Resolution always produces the same
- * result, so we're not worried about atomicity here.
- */
-INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
-    struct StringObject* str)
-{
-    const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
-    u4 newIdx;
-
-    assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
-    if (pIndexMap->stringReducedCount > 0) {
-        newIdx = pIndexMap->stringMap[stringIdx];
-        if (newIdx != kNoIndexMapping)
-            pDvmDex->pResStrings[newIdx] = str;
-    }
-}
-INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
-    struct ClassObject* clazz)
-{
-    const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
-    u4 newIdx;
-
-    assert(classIdx < pDvmDex->pHeader->typeIdsSize);
-    if (pIndexMap->classReducedCount > 0) {
-        newIdx = pIndexMap->classMap[classIdx];
-        if (newIdx != kNoIndexMapping)
-            pDvmDex->pResClasses[newIdx] = clazz;
-    }
-}
-INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
-    struct Method* method)
-{
-    const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
-    u4 newIdx;
-
-    assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
-    if (pIndexMap->methodReducedCount > 0) {
-        newIdx = pIndexMap->methodMap[methodIdx];
-        if (newIdx != kNoIndexMapping)
-            pDvmDex->pResMethods[newIdx] = method;
-    }
-}
-INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
-    struct Field* field)
-{
-    const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
-    u4 newIdx;
-
-    assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
-    if (pIndexMap->fieldReducedCount > 0) {
-        newIdx = pIndexMap->fieldMap[fieldIdx];
-        if (newIdx != kNoIndexMapping)
-            pDvmDex->pResFields[newIdx] = field;
-    }
-}
-
-#elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
-
-#error "not implemented"    /* TODO */
-
-#elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
-
-/*
- * There's no cache, so we always return NULL.
- */
-INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
-    u4 stringIdx)
-{
-    return NULL;
-}
-INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
-    u4 classIdx)
-{
-    return NULL;
-}
-INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
-    u4 methodIdx)
-{
-    return NULL;
-}
-INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
-    u4 fieldIdx)
-{
-    return NULL;
-}
-
-/*
- * Update the resolved item table.  There is no table, so do nothing.
- */
-INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
-    struct StringObject* str)
-{}
-INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
-    struct ClassObject* clazz)
-{}
-INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
-    struct Method* method)
-{}
-INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
-    struct Field* field)
-{}
-
-#else
-#error "huh?"
-#endif /*DVM_RESOLVER_CACHE==N*/
-
 #endif /*_DALVIK_DVMDEX*/
diff --git a/vm/Init.c b/vm/Init.c
index 81a385a..f5a8b3c 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -181,13 +181,6 @@
 #ifdef PROFILE_FIELD_ACCESS
         " profile_field_access"
 #endif
-#if DVM_RESOLVER_CACHE == DVM_RC_REDUCING
-        " resolver_cache_reducing"
-#elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
-        " resolver_cache_expanding"
-#elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
-        " resolver_cache_disabled"
-#endif
 #if defined(WITH_JIT)
         " jit"
 #endif
diff --git a/vm/analysis/DexPrepare.c b/vm/analysis/DexPrepare.c
index e43042f..11fd7be 100644
--- a/vm/analysis/DexPrepare.c
+++ b/vm/analysis/DexPrepare.c
@@ -52,7 +52,7 @@
 static void updateChecksum(u1* addr, int len, DexHeader* pHeader);
 static int writeDependencies(int fd, u4 modWhen, u4 crc);
 static bool writeOptData(int fd, const DexClassLookup* pClassLookup,\
-    const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder);
+    const RegisterMapBuilder* pRegMapBuilder);
 static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum);
 
 
@@ -475,7 +475,6 @@
     const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
 {
     DexClassLookup* pClassLookup = NULL;
-    IndexMapSet* pIndexMapSet = NULL;
     RegisterMapBuilder* pRegMapBuilder = NULL;
     u4 headerFlags = 0;
 
@@ -544,15 +543,6 @@
                 success = false;
             } else {
                 /*
-                 * If configured to do so, scan the instructions, looking
-                 * for ways to reduce the size of the resolved-constant table.
-                 * This is done post-optimization, across the instructions
-                 * in all methods in all classes (even the ones that failed
-                 * to load).
-                 */
-                pIndexMapSet = dvmRewriteConstants(pDvmDex);
-
-                /*
                  * If configured to do so, generate register map output
                  * for all verified classes.  The register maps were
                  * generated during verification, and will now be serialized.
@@ -635,7 +625,7 @@
     /*
      * Append any optimized pre-computed data structures.
      */
-    if (!writeOptData(fd, pClassLookup, pIndexMapSet, pRegMapBuilder)) {
+    if (!writeOptData(fd, pClassLookup, pRegMapBuilder)) {
         LOGW("Failed writing opt data\n");
         goto bail;
     }
@@ -680,7 +670,6 @@
     //dvmRegisterMapDumpStats();
 
 bail:
-    dvmFreeIndexMapSet(pIndexMapSet);
     dvmFreeRegisterMapBuilder(pRegMapBuilder);
     free(pClassLookup);
     return result;
@@ -1365,7 +1354,7 @@
  * so it can be used directly when the file is mapped for reading.
  */
 static bool writeOptData(int fd, const DexClassLookup* pClassLookup,
-    const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder)
+    const RegisterMapBuilder* pRegMapBuilder)
 {
     /* pre-computed class lookup hash table */
     if (!writeChunk(fd, (u4) kDexChunkClassLookup,
@@ -1374,15 +1363,6 @@
         return false;
     }
 
-    /* remapped constants (optional) */
-    if (pIndexMapSet != NULL) {
-        if (!writeChunk(fd, pIndexMapSet->chunkType,
-                pIndexMapSet->chunkData, pIndexMapSet->chunkDataLen))
-        {
-            return false;
-        }
-    }
-
     /* register maps (optional) */
     if (pRegMapBuilder != NULL) {
         if (!writeChunk(fd, (u4) kDexChunkRegisterMaps,
diff --git a/vm/analysis/ReduceConstants.c b/vm/analysis/ReduceConstants.c
deleted file mode 100644
index 69657e3..0000000
--- a/vm/analysis/ReduceConstants.c
+++ /dev/null
@@ -1,1059 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Compress the range of "constant pool" indexes in instructions and
- * annotations to lower runtime RAM footprint.
- *
- * NOTE: this is an incomplete experimental feature.  Do not try to use it.
- */
-#include "Dalvik.h"
-#include "libdex/InstrUtils.h"
-#include "libdex/OptInvocation.h"
-#include "libdex/DexClass.h"
-
-/*
-Overview
-
-When a class, method, field, or string constant is referred to from
-Dalvik bytecode, the reference takes the form of an integer index value.
-This value indexes into an array of type_id_item, method_id_item,
-field_id_item, or string_id_item in the DEX file.  The first three
-themselves contain (directly or indirectly) indexes to strings that the
-resolver uses to convert the instruction stream index into a pointer to
-the appropriate object or struct.
-
-For example, an invoke-virtual instruction needs to specify which method
-is to be invoked.  The method constant indexes into the method_id_item
-array, each entry of which has indexes that specify the defining class
-(type_id_item), method name (string_id_item), and method prototype
-(proto_id_item).  The type_id_item just holds an index to a string_id_item,
-which holds the file offset to the string with the class name.  The VM
-finds the class by name, then searches through the class' table of virtual
-methods to find one with a matching name and prototype.
-
-This process is fairly expensive, so after the first time it completes
-successfully, the VM records that the method index resolved to a specific
-Method struct.  On subsequent execution, the VM just pulls the Method ptr
-out of the resolved-methods array.  A similar approach is used with
-the indexes for classes, fields, and string constants.
-
-The problem with this approach is that we need to have a "resolved" entry
-for every possible class, method, field, and string constant in every
-DEX file, even if some of those aren't used from code.  The DEX string
-constant table has entries for method prototypes and class names that are
-never used by the code, and "public static final" fields often turn into
-immediate constants.  The resolution table entries are only 4 bytes each,
-but there are roughly 200,000 of them in the bootstrap classes alone.
-
-DEX optimization removes many index references by replacing virtual method
-indexes with vtable offsets and instance field indexes with byte offsets.
-In the earlier example, the method would be resolved at "dexopt" time, and
-the instruction rewritten as invoke-virtual-quick with the vtable offset.
-
-(There are comparatively few classes compared to other constant pool
-entries, and a much higher percentage (typically 60-70%) are used.  The
-biggest gains come from the string pool.)
-
-Using the resolved-entity tables provides a substantial performance
-improvement, but results in applications allocating 1MB+ of tables that
-are 70% unused.  The used and unused entries are freely intermixed,
-preventing effective sharing with the zygote process, and resulting in
-large numbers of private/dirty pages on the native heap as the tables
-populate on first use.
-
-The trick is to reduce the memory usage without decreasing performance.
-Using smaller resolved-entity tables can actually give us a speed boost,
-because we'll have a smaller "live" set of pages and make more effective
-use of the data cache.
-
-
-The approach we're going to use is to determine the set of indexes that
-could potentially be resolved, generate a mapping from the minimal set to
-the full set, and append the mapping to the DEX file.  This is done at
-"dexopt" time, because we need to keep the changes in shared/read-only
-pages or we'll lose the benefits of doing the work.
-
-There are two ways to create and use the new mapping:
-
- (1) Write the entire full->minimal mapping to the ".odex" file.  On every
- instruction that uses an index, use the mapping to determine the
- "compressed" constant value, and then use that to index into the
- resolved-entity tables on the heap.  The instruction stream is unchanged,
- and the resolver can easily tell if a given index is cacheable.
-
- (2) Write the inverse miminal->full mapping to the ".odex" file, and
- rewrite the constants in the instruction stream.  The interpreter is
- unchanged, and the resolver code uses the mapping to find the original
- data in the DEX.
-
-Approach #1 is easier and safer to implement, but it requires a table
-lookup every time we execute an instruction that includes a constant
-pool reference.  This causes an unacceptable performance hit, chiefly
-because we're hitting semi-random memory pages and hosing the data cache.
-This is mitigated somewhat by DEX optimizations that replace the constant
-with a vtable index or field byte offset.  Approach #1 also requires
-a larger map table, increasing the size of the DEX on disk.  One nice
-property of approach #1 is that most of the DEX file is unmodified,
-so use of the mapping is a runtime decision.
-
-Approach #2 is preferred for performance reasons.
-
-
-The class/method/field/string resolver code has to handle indices from
-three sources: interpreted instructions, annotations, and exception
-"catch" lists.  Sometimes these occur indirectly, e.g. we need to resolve
-the declaring class associated with fields and methods when the latter
-two are themselves resolved.  Parsing and rewriting instructions is fairly
-straightforward, but annotations use a complex format with variable-width
-index values.
-
-We can safely rewrite index values in annotations if we guarantee that the
-new value is smaller than the original.  This implies a two-pass approach:
-the first determines the set of indexes actually used, the second does the
-rewrite.  Doing the rewrite in a single pass would be much harder.
-
-Instances of the "original" indices will still be found in the file; if
-we try to be all-inclusive we will include some stuff that doesn't need
-to be there (e.g. we don't generally need to cache the class name string
-index result, since once we have the class resolved we don't need to look
-it up by name through the resolver again).  There is some potential for
-performance improvement by caching more than we strictly need, but we can
-afford to give up a little performance during class loading if it allows
-us to regain some memory.
-
-For safety and debugging, it's useful to distinguish the "compressed"
-constants in some way, e.g. setting the high bit when we rewrite them.
-In practice we don't have any free bits: indexes are usually 16-bit
-values, and we have more than 32,767 string constants in at least one of
-our core DEX files.  Also, this does not work with constants embedded in
-annotations, because of the variable-width encoding.
-
-We should be safe if we can establish a clear distinction between sources
-of "original" and "compressed" indices.  If the values get crossed up we
-can end up with elusive bugs.  The easiest approach is to declare that
-only indices pulled from certain locations (the instruction stream and/or
-annotations) are compressed.  This prevents us from adding indices in
-arbitrary locations to the compressed set, but should allow a reasonably
-robust implementation.
-
-
-Further implementation thoughts:
-
- - We don't have to do annotations in the first pass.  At heart the
-   resolved entity cache is a performance optimization, not necessary for
-   correctness, and we're not making annotation performance a priority
-   at this stage.
- - The most important "fast path" is instruction processing.  Everything
-   else can do additional work without having a measurable impact.
-   However...
- - We need to keep an eye on uncached resolves to ensure that we haven't
-   introduced noticeable performance losses.  In particular, the use of
-   runtime annotations with string constants may suffer if we don't include
-   annotation rewriting in the solution.
- - We can have separate resolver functions for "original" and "compressed"
-   indices.  This way we don't have to add a flag argument to the resolver
-   functions (which would require passing an additional parameter in from
-   the interpreter).
- - The VM spec has some specific things to say about string constant
-   equality and interning.  Index compression should have no effect on
-   that; we just change how long it takes to find the interned string in
-   certain circumstances.  The impact can be mitigated somewhat by
-   improving the performance of the interned string table code.
- - This can make e.g. method resolution slower.  The method_id_item has
-   an index to a method name string, and we will no longer cache the
-   result of resolving that string.  This impacts resolution of any method
-   with the same name as a previously-resolved method.
- - We may need to tweak the tools, particularly "dexdump", to show the
-   translated values.
- - We can use 16-bit values in the mapping table, since we should have
-   fewer than 2^16 remapped entries.  If we overflow we can skip the remap
-   for that table or for the entire DEX file.  The resolver will need to
-   check for the existence of the table to determine whether or not entries
-   must be remapped.  The cost of the extra check is acceptable for
-   approach #2, since it's only at resolve time, but may be undesirable
-   for approach #1.
-*/
-/*
-Output Formats
-
-There are two possible output formats, from which we choose based on how
-we plan to take advantage of the remapped constants.  At most one of these
-will appear in the DEX.
-
-NOTE: if EIXM appears in the DEX, the VM *must* be configured with
-DVM_RESOLVER_CACHE=DVM_RC_EXPANDING (2).  Otherwise the constants we
-pull from the instruction stream will be wrong and we will fail quickly.
-
-For approach #1: map from original indices to the reduced set.
-
-  This includes the four "mapToNew" tables.
-
-  Format (RIXM):
-   u4 classCount            // #of entries in classMap[]; == typeIdsSize
-   u4 reducedClassCount     // #of entries in remapped table (for alloc)
-   u2 classMap[]
-   u4 methodCount
-   u4 reducedMethodCount
-   u2 methodMap[]
-   u4 fieldCount
-   u4 reducedFieldCount
-   u2 fieldMap[]
-   u4 stringCount
-   u4 reducedStringCount
-   u2 stringMap[]
-
-For approach #2: map from the reduced set back to the originals.
-
-  This includes the four "mapToOld" tables.
-
-  Format (EIXM):
-   u4 classCount            // #of entries in classMap[]; post-reduction
-   u2 classMap[]
-   u4 methodCount
-   u2 methodMap[]
-   u4 fieldCount
-   u2 fieldMap[]
-   u4 stringCount
-   u2 stringMap[]
-
-The arrays are padded so that the "count" values are always aligned on
-32-bit boundaries.  All multi-byte values are in native host order.
-*/
-
-
-/*
- * Gather results from the post-optimization instruction scan.
- */
-typedef struct ScanResults {
-    /* output */
-    BitVector*  usedClasses;
-    BitVector*  usedMethods;
-    BitVector*  usedFields;
-    BitVector*  usedStrings;
-} ScanResults;
-
-/* prototype for the for-all-methods function */
-typedef void (AllMethodsFunc)(DexFile* pDexFile, const char* classDescriptor,
-    DexMethod* pDexMethod, void* arg);
-
-
-/*
- * Free scan results.
- */
-static void freeScanResults(ScanResults* pResults)
-{
-    if (pResults == NULL)
-        return;
-
-    dvmFreeBitVector(pResults->usedClasses);
-    dvmFreeBitVector(pResults->usedMethods);
-    dvmFreeBitVector(pResults->usedFields);
-    dvmFreeBitVector(pResults->usedStrings);
-    free(pResults);
-}
-
-/*
- * Allocate storage for the results of the instruction scan.
- */
-static ScanResults* allocScanResults(const DexFile* pDexFile)
-{
-    ScanResults* pResults;
-    const DexHeader* pHeader = pDexFile->pHeader;
-
-    pResults = (ScanResults*) calloc(1, sizeof(ScanResults));
-    if (pResults == NULL)
-        return NULL;
-
-    pResults->usedClasses = dvmAllocBitVector(pHeader->typeIdsSize, false);
-    pResults->usedMethods = dvmAllocBitVector(pHeader->methodIdsSize, false);
-    pResults->usedFields = dvmAllocBitVector(pHeader->fieldIdsSize, false);
-    pResults->usedStrings = dvmAllocBitVector(pHeader->stringIdsSize, false);
-
-    if (pResults->usedClasses == NULL ||
-        pResults->usedMethods == NULL ||
-        pResults->usedFields == NULL ||
-        pResults->usedStrings == NULL)
-    {
-        freeScanResults(pResults);
-        return NULL;
-    }
-
-    return pResults;
-}
-
-/*
- * Call "func(method, arg)" on all methods in the specified class.
- *
- * Pass in a pointer to the class_data_item, positioned at the start of
- * the field data (i.e. just past the class data header).
- *
- * "classDescriptor" is for debug messages.
- */
-static void forAllMethodsInClass(DexFile* pDexFile, const u1** ppEncodedData,
-    const DexClassDataHeader* pHeader, const char* classDescriptor,
-    AllMethodsFunc func, void* arg)
-{
-    int i;
-
-    /*
-     * Consume field data.
-     */
-    if (pHeader->staticFieldsSize != 0) {
-        int count = (int) pHeader->staticFieldsSize;
-        u4 lastIndex = 0;
-        DexField field;
-        for (i = 0; i < count; i++) {
-            dexReadClassDataField(ppEncodedData, &field, &lastIndex);
-        }
-    }
-    if (pHeader->instanceFieldsSize != 0) {
-        int count = (int) pHeader->instanceFieldsSize;
-        u4 lastIndex = 0;
-        DexField field;
-        for (i = 0; i < count; i++) {
-            dexReadClassDataField(ppEncodedData, &field, &lastIndex);
-        }
-    }
-
-    /*
-     * Run through all methods.
-     */
-    if (pHeader->directMethodsSize != 0) {
-        int count = (int) pHeader->directMethodsSize;
-        u4 lastIndex = 0;
-        DexMethod method;
-
-        for (i = 0; i < count; i++) {
-            dexReadClassDataMethod(ppEncodedData, &method, &lastIndex);
-            (func)(pDexFile, classDescriptor, &method, arg);
-        }
-    }
-    if (pHeader->virtualMethodsSize != 0) {
-        int count = (int) pHeader->virtualMethodsSize;
-        u4 lastIndex = 0;
-        DexMethod method;
-
-        for (i = 0; i < count; i++) {
-            dexReadClassDataMethod(ppEncodedData, &method, &lastIndex);
-            (func)(pDexFile, classDescriptor, &method, arg);
-        }
-    }
-}
-
-/*
- * Call "func(method, arg)" on all methods in all classes in DexFile.
- */
-static void forAllMethods(DexFile* pDexFile, AllMethodsFunc func, void* arg)
-{
-    u4 count = pDexFile->pHeader->classDefsSize;
-    u4 idx;
-
-    for (idx = 0; idx < count; idx++) {
-        const DexClassDef* pClassDef;
-        DexClassDataHeader header;
-        const u1* pEncodedData;
-
-        pClassDef = dexGetClassDef(pDexFile, idx);
-        pEncodedData = dexGetClassData(pDexFile, pClassDef);
-
-        const char* classDescriptor;
-        classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
-
-        if (pEncodedData != NULL) {
-            dexReadClassDataHeader(&pEncodedData, &header);
-
-            forAllMethodsInClass(pDexFile, &pEncodedData, &header,
-                classDescriptor, func, arg);
-        } else {
-            //printf("%s: no class data\n", classDescriptor);
-            /* no class data, e.g. "marker interface" */
-        }
-    }
-}
-
-/*
- * Mark a class ID as referenced.
- */
-static void markClass(const u2* ptr, ScanResults* pResults)
-{
-    u2 classIdx = *ptr;
-    if (!dvmSetBit(pResults->usedClasses, classIdx)) {
-        LOGE("Unable to mark class %d as in-use\n", classIdx);
-    }
-}
-
-/*
- * Mark a method ID as referenced.
- */
-static void markMethod(const u2* ptr, ScanResults* pResults)
-{
-    u2 methodIdx = *ptr;
-    if (!dvmSetBit(pResults->usedMethods, methodIdx)) {
-        LOGE("Unable to mark method %d as in-use\n", methodIdx);
-    }
-}
-
-/*
- * Mark a field ID as referenced.
- */
-static void markField(const u2* ptr, ScanResults* pResults)
-{
-    u2 fieldIdx = *ptr;
-    if (!dvmSetBit(pResults->usedFields, fieldIdx)) {
-        LOGE("Unable to mark field %d as in-use\n", fieldIdx);
-    }
-}
-
-/*
- * Mark a string constant as referenced.
- */
-static void markString(const u2* ptr, ScanResults* pResults)
-{
-    u2 stringIdx = *ptr;
-    if (!dvmSetBit(pResults->usedStrings, stringIdx)) {
-        LOGE("Unable to mark string %d as in-use\n", stringIdx);
-    }
-}
-
-/*
- * Mark a "jumbo" string constant as referenced.
- */
-static void markJumboString(u2* ptr, ScanResults* pResults)
-{
-    u4 stringIdx;
-
-    /* it's in native byte order, but might not be 32-bit aligned */
-    memcpy(&stringIdx, ptr, sizeof(u4));
-    if (!dvmSetBit(pResults->usedStrings, stringIdx)) {
-        LOGE("Unable to mark string %d as in-use\n", stringIdx);
-    }
-}
-
-/*
- * Remap a value in the instruction stream.
- */
-static inline void updateValue(u2* ptr, const IndexMapSet* pIndexMapSet,
-    int whichMap)
-{
-    const IndexMap* pMap = &pIndexMapSet->map[whichMap];
-    if (pMap != NULL) {
-        u2 newIdx = pMap->mapToNew[*ptr];
-        assert(newIdx != kNoIndexMapping);
-        *ptr = newIdx;
-    }
-}
-static void updateClass(u2* ptr, const IndexMapSet* pIndexMapSet)
-{
-    updateValue(ptr, pIndexMapSet, kMapClasses);
-}
-static void updateMethod(u2* ptr, const IndexMapSet* pIndexMapSet)
-{
-    updateValue(ptr, pIndexMapSet, kMapMethods);
-}
-static void updateField(u2* ptr, const IndexMapSet* pIndexMapSet)
-{
-    updateValue(ptr, pIndexMapSet, kMapFields);
-}
-static void updateString(u2* ptr, const IndexMapSet* pIndexMapSet)
-{
-    updateValue(ptr, pIndexMapSet, kMapStrings);
-}
-static void updateJumboString(u2* ptr, const IndexMapSet* pIndexMapSet)
-{
-    u4 stringIdx;
-    u4 newIdx;
-
-    /* it's in native byte order, but might not be 32-bit aligned */
-    memcpy(&stringIdx, ptr, sizeof(stringIdx));
-
-    /* get new value */
-    newIdx = pIndexMapSet->map[kMapStrings].mapToNew[*ptr];
-    assert(newIdx != kNoIndexMapping);
-
-    /* copy it out */
-    memcpy(ptr, &newIdx, sizeof(newIdx));
-}
-
-/*
- * Run through an instructions stream, marking constants as we see them.
- *
- * If "pResults" is non-NULL, we populate "pResults" with what we find,
- * making no changes to the instruction stream.
- *
- * If "pIndexMapSet" is non-NULL, we rewrite the constants in the
- * instruction stream.
- */
-static void markUsedConstantsFromInsns(u2* insns, u4 insnsSize,
-    ScanResults* pResults, const IndexMapSet* pIndexMapSet)
-{
-    //printf(" %p %u units\n", insns, insnsSize);
-
-    while (insnsSize > 0) {
-        int width;
-        u2* pConst = insns + 1;
-
-        switch (*insns & 0xff) {
-        case OP_IGET:
-        case OP_IGET_WIDE:
-        case OP_IGET_OBJECT:
-        case OP_IGET_BOOLEAN:
-        case OP_IGET_BYTE:
-        case OP_IGET_CHAR:
-        case OP_IGET_SHORT:
-        case OP_IPUT:
-        case OP_IPUT_WIDE:
-        case OP_IPUT_OBJECT:
-        case OP_IPUT_BOOLEAN:
-        case OP_IPUT_BYTE:
-        case OP_IPUT_CHAR:
-        case OP_IPUT_SHORT:
-        case OP_SGET:
-        case OP_SGET_WIDE:
-        case OP_SGET_OBJECT:
-        case OP_SGET_BOOLEAN:
-        case OP_SGET_BYTE:
-        case OP_SGET_CHAR:
-        case OP_SGET_SHORT:
-        case OP_SPUT:
-        case OP_SPUT_WIDE:
-        case OP_SPUT_OBJECT:
-        case OP_SPUT_BOOLEAN:
-        case OP_SPUT_BYTE:
-        case OP_SPUT_CHAR:
-        case OP_SPUT_SHORT:
-            /* instanceop vA, vB, field@CCCC */
-            /* staticop vAA, field@BBBB */
-            if (pResults != NULL)
-                markField(pConst, pResults);
-            else
-                updateField(pConst, pIndexMapSet);
-            break;
-
-        case OP_CONST_STRING:
-            /* const-string vAA, string@BBBB */
-            if (pResults != NULL)
-                markString(pConst, pResults);
-            else
-                updateString(pConst, pIndexMapSet);
-            break;
-
-        case OP_CONST_STRING_JUMBO:
-            /* const-string/jumbo vAA, string@BBBBBBBB */
-            if (pResults != NULL)
-                markJumboString(pConst, pResults);
-            else
-                updateJumboString(pConst, pIndexMapSet);
-            break;
-
-        case OP_CONST_CLASS:
-        case OP_CHECK_CAST:
-        case OP_NEW_INSTANCE:
-        case OP_FILLED_NEW_ARRAY_RANGE:
-        case OP_INSTANCE_OF:
-        case OP_NEW_ARRAY:
-        case OP_FILLED_NEW_ARRAY:
-            /* const-class vAA, type@BBBB */
-            /* check-cast vAA, type@BBBB */
-            /* new-instance vAA, type@BBBB */
-            /* filled-new-array/range {vCCCC .. vNNNN}, type@BBBB */
-            /* instance-of vA, vB, type@CCCC */
-            /* new-array vA, vB, type@CCCC */
-            /* filled-new-array {vD, vE, vF, vG, vA}, type@CCCC */
-            if (pResults != NULL)
-                markClass(pConst, pResults);
-            else
-                updateClass(pConst, pIndexMapSet);
-            break;
-
-        case OP_INVOKE_VIRTUAL:
-        case OP_INVOKE_SUPER:
-        case OP_INVOKE_DIRECT:
-        case OP_INVOKE_STATIC:
-        case OP_INVOKE_INTERFACE:
-        case OP_INVOKE_VIRTUAL_RANGE:
-        case OP_INVOKE_SUPER_RANGE:
-        case OP_INVOKE_DIRECT_RANGE:
-        case OP_INVOKE_STATIC_RANGE:
-        case OP_INVOKE_INTERFACE_RANGE:
-            /* invoke-kind {vD, vE, vF, vG, vA}, meth@CCCC */
-            /* invoke-kind/range {vCCCC .. vNNNN}, meth@BBBB */
-            if (pResults != NULL)
-                markMethod(pConst, pResults);
-            else
-                updateMethod(pConst, pIndexMapSet);
-            break;
-
-        default:
-            // ignore this instruction
-            ;
-        }
-
-        width = dexGetInstrOrTableWidthAbs(gDvm.instrWidth, insns);
-        assert(width > 0 && width <= (int)insnsSize);
-
-        insns += width;
-        insnsSize -= width;
-    }
-}
-
-/*
- * This is an AllMethodsFunc implementation.
- *
- * Run through the instructions in this method, setting bits in the "pResults"
- * struct as we locate constants.
- */
-static void markUsedConstants(DexFile* pDexFile, const char* classDescriptor,
-    DexMethod* pDexMethod, void* arg)
-{
-    ScanResults* pResults = (ScanResults*) arg;
-    const DexCode* pDexCode = dexGetCode(pDexFile, pDexMethod);
-
-    if (false) {
-        const DexMethodId* pMethodId;
-        const char* methodName;
-        pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
-        methodName = dexStringById(pDexFile, pMethodId->nameIdx);
-        printf(" %s.%s\n", classDescriptor, methodName);
-    }
-
-    if (pDexCode != NULL) {
-        u2* insns = (u2*) pDexCode->insns;
-        u4 insnsSize = pDexCode->insnsSize;
-        markUsedConstantsFromInsns(insns, insnsSize, pResults, NULL);
-    } else {
-        //printf(" (no code)\n");
-    }
-}
-
-/*
- * This is an AllMethodsFunc implementation.
- *
- * Run through the instructions in this method, altering the constants used.
- */
-#if DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
-static void updateUsedConstants(DexFile* pDexFile, const char* classDescriptor,
-    DexMethod* pDexMethod, void* arg)
-{
-    const IndexMapSet* pIndexMapSet = (const IndexMapSet*) arg;
-    const DexCode* pDexCode = dexGetCode(pDexFile, pDexMethod);
-
-    if (false) {
-        const DexMethodId* pMethodId;
-        const char* methodName;
-        pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
-        methodName = dexStringById(pDexFile, pMethodId->nameIdx);
-        printf(" %s.%s\n", classDescriptor, methodName);
-    }
-
-    if (pDexCode != NULL) {
-        u2* insns = (u2*) pDexCode->insns;
-        u4 insnsSize = pDexCode->insnsSize;
-        markUsedConstantsFromInsns(insns, insnsSize, NULL, pIndexMapSet);
-    } else {
-        //printf(" (no code)\n");
-    }
-}
-#endif
-
-/*
- * Count up the bits and show a count.
- */
-static void showBitCount(const char* label, int setCount, int maxCount)
-{
-    printf("%s: %d of %d (%.1f%% unused)\n", label, setCount, maxCount,
-        ((maxCount - setCount) * 100.0f) / maxCount);
-}
-
-/*
- * Print some debug info.
- */
-static void summarizeResults(DvmDex* pDvmDex, ScanResults* pResults)
-{
-    DexFile* pDexFile = pDvmDex->pDexFile;
-#if 0
-    int i;
-
-    for (i = 0; i < (int) pDvmDex->pDexFile->pHeader->typeIdsSize; i++) {
-        const DexTypeId* pDexTypeId;
-        const char* classDescr;
-
-        pDexTypeId = dexGetTypeId(pDexFile, i);
-        classDescr = dexStringById(pDexFile, pDexTypeId->descriptorIdx);
-
-        if (dvmIsBitSet(pResults->usedStrings, i))
-            printf("used  : %04x '%s'\n", i, classDescr);
-        else
-            printf("unused: %04x '%s'\n", i, classDescr);
-    }
-#endif
-#if 0
-    for (i = 0; i < (int) pDvmDex->pDexFile->pHeader->methodIdsSize; i++) {
-        const DexMethodId* pDexMethodId;
-        const DexTypeId* pDexTypeId;
-        const char* classDescr;
-        const char* methodName;
-
-        pDexMethodId = dexGetMethodId(pDexFile, i);
-        methodName = dexStringById(pDexFile, pDexMethodId->nameIdx);
-
-        pDexTypeId = dexGetTypeId(pDexFile, pDexMethodId->classIdx);
-        classDescr = dexStringById(pDexFile, pDexTypeId->descriptorIdx);
-        if (dvmIsBitSet(pResults->usedMethods, i))
-            printf("used  : %s.%s\n", classDescr, methodName);
-        else
-            printf("unused: %s.%s\n", classDescr, methodName);
-    }
-#endif
-#if 0
-    for (i = 0; i < (int) pDvmDex->pDexFile->pHeader->fieldIdsSize; i++) {
-        const DexFieldId* pDexFieldId;
-        const DexTypeId* pDexTypeId;
-        const char* classDescr;
-        const char* fieldName;
-
-        pDexFieldId = dexGetFieldId(pDexFile, i);
-        fieldName = dexStringById(pDexFile, pDexFieldId->nameIdx);
-
-        pDexTypeId = dexGetTypeId(pDexFile, pDexFieldId->classIdx);
-        classDescr = dexStringById(pDexFile, pDexTypeId->descriptorIdx);
-        if (dvmIsBitSet(pResults->usedFields, i))
-            printf("used  : %s.%s\n", classDescr, fieldName);
-        else
-            printf("unused: %s.%s\n", classDescr, fieldName);
-    }
-#endif
-#if 0
-    for (i = 0; i < (int) pDvmDex->pDexFile->pHeader->stringIdsSize; i++) {
-        const char* str;
-
-        str = dexStringById(pDexFile, i);
-
-        if (dvmIsBitSet(pResults->usedStrings, i))
-            printf("used  : %04x '%s'\n", i, str);
-        else
-            printf("unused: %04x '%s'\n", i, str);
-    }
-#endif
-
-    int totalMax, totalSet;
-    int setCount;
-
-    totalMax = totalSet = 0;
-
-    setCount = dvmCountSetBits(pResults->usedClasses);
-    showBitCount("classes", setCount, pDexFile->pHeader->typeIdsSize);
-    totalSet += setCount;
-    totalMax += pDexFile->pHeader->typeIdsSize;
-
-    setCount = dvmCountSetBits(pResults->usedMethods);
-    showBitCount("methods", setCount, pDexFile->pHeader->methodIdsSize);
-    totalSet += setCount;
-    totalMax += pDexFile->pHeader->methodIdsSize;
-
-    setCount = dvmCountSetBits(pResults->usedFields);
-    showBitCount("fields",  setCount, pDexFile->pHeader->fieldIdsSize);
-    totalSet += setCount;
-    totalMax += pDexFile->pHeader->fieldIdsSize;
-
-    setCount = dvmCountSetBits(pResults->usedStrings);
-    showBitCount("strings", setCount, pDexFile->pHeader->stringIdsSize);
-    totalSet += setCount;
-    totalMax += pDexFile->pHeader->stringIdsSize;
-
-    printf("TOTAL %d of %d (%.1f%% unused -- %.1fK)\n", totalSet, totalMax,
-        ((totalMax - totalSet) * 100.0f) / totalMax,
-        (totalMax - totalSet) / 256.0f);
-}
-
-/*
- * Fill out an index map set entry.
- *
- * If we can't fit the map into our base type, we don't create the map.
- *
- * Returns "false" if allocation fails.
- */
-static bool constructIndexMap(int totalCount, const BitVector* pBits,
-    IndexMap* pMap)
-{
-    const int kMaxIndex = 65534;        // 65535, a/k/a -1, is special
-    int setCount;
-
-    setCount = dvmCountSetBits(pBits);
-    if (setCount < 0 || setCount > kMaxIndex)
-        return true;
-
-    u2* mapToOld = (u2*) malloc(setCount * sizeof(u2));
-    u2* mapToNew = (u2*) malloc(totalCount * sizeof(u2));
-    if (mapToOld == NULL || mapToNew == NULL) {
-        free(mapToOld);
-        free(mapToNew);
-        return false;
-    }
-
-    /* fill in both arrays */
-    int entry, idx = 0;
-    for (entry = 0; entry < totalCount; entry++) {
-        if (dvmIsBitSet(pBits, entry)) {
-            mapToNew[entry] = idx;
-            mapToOld[idx] = entry;
-            idx++;
-        } else {
-            mapToNew[entry] = kNoIndexMapping;
-        }
-    }
-
-    if (idx != setCount) {
-        LOGE("GLITCH: idx=%d setCount=%d\n", idx, setCount);
-        dvmAbort();
-    }
-
-    /* success */
-    pMap->mapToOld = mapToOld;
-    pMap->mapToNew = mapToNew;
-    pMap->origCount = totalCount;
-    pMap->newCount = setCount;
-
-    return true;
-}
-
-/*
- * Construct a "reducing" chunk, with maps that convert the constants in
- * instructions to their reduced value for the cache lookup.
- */
-static bool constructReducingDataChunk(IndexMapSet* pIndexMapSet)
-{
-    int chunkLen = 0;
-    int i;
-
-    pIndexMapSet->chunkType = kDexChunkReducingIndexMap;
-
-    /*
-     * Compute space requirements and allocate storage.
-     */
-    for (i = 0; i < kNumIndexMaps; i++) {
-        /* space for the "original" count */
-        chunkLen += sizeof(u4);
-
-        /* space for the "reduced" count */
-        chunkLen += sizeof(u4);
-
-        /* add data length, round up to 32-bit boundary */
-        chunkLen += pIndexMapSet->map[i].origCount * sizeof(u2);
-        chunkLen = (chunkLen + 3) & ~3;
-    }
-
-    pIndexMapSet->chunkDataLen = chunkLen;
-    pIndexMapSet->chunkData = (u1*) calloc(1, chunkLen);
-    if (pIndexMapSet->chunkData == NULL)
-        return false;
-
-    /*
-     * Copy the data in.
-     */
-    u1* ptr = pIndexMapSet->chunkData;
-    for (i = 0; i < kNumIndexMaps; i++) {
-        u4* wordPtr = (u4*) ptr;
-        int dataLen = pIndexMapSet->map[i].origCount * sizeof(u2);
-
-        *wordPtr++ = pIndexMapSet->map[i].origCount;
-        *wordPtr++ = pIndexMapSet->map[i].newCount;
-        if (dataLen != 0)
-            memcpy(wordPtr, pIndexMapSet->map[i].mapToNew, dataLen);
-
-        /* advance pointer, maintaining 32-bit alignment */
-        ptr = ((u1*) wordPtr) + dataLen;
-        ptr = (u1*) (((int) ptr + 3) & ~3);
-    }
-
-    if (ptr - (u1*) pIndexMapSet->chunkData != chunkLen) {
-        LOGE("GLITCH: expected len=%d, actual=%d\n",
-            chunkLen, ptr - (u1*) pIndexMapSet->chunkData);
-        dvmAbort();
-    }
-
-    return true;
-}
-
-/*
- * Construct an "expanding" chunk, with maps that convert instructions
- * with reduced constants back to their full original values.
- */
-#if DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
-static bool constructExpandingDataChunk(IndexMapSet* pIndexMapSet)
-{
-    int chunkLen = 0;
-    int i;
-
-    pIndexMapSet->chunkType = kDexChunkExpandingIndexMap;
-
-    /*
-     * Compute space requirements and allocate storage.
-     */
-    for (i = 0; i < kNumIndexMaps; i++) {
-        /* space for the length word */
-        chunkLen += sizeof(u4);
-
-        /* add data length, round up to 32-bit boundary */
-        chunkLen += pIndexMapSet->map[i].newCount * sizeof(u2);
-        chunkLen = (chunkLen + 3) & ~3;
-    }
-
-    pIndexMapSet->chunkDataLen = chunkLen;
-    pIndexMapSet->chunkData = (u1*) calloc(1, chunkLen);
-    if (pIndexMapSet->chunkData == NULL)
-        return false;
-
-    /*
-     * Copy the data in.
-     */
-    u1* ptr = pIndexMapSet->chunkData;
-    for (i = 0; i < kNumIndexMaps; i++) {
-        u4* wordPtr = (u4*) ptr;
-        int dataLen = pIndexMapSet->map[i].newCount * sizeof(u2);
-
-        *wordPtr++ = pIndexMapSet->map[i].newCount;
-        if (dataLen != 0)
-            memcpy(wordPtr, pIndexMapSet->map[i].mapToOld, dataLen);
-
-        /* advance pointer, maintaining 32-bit alignment */
-        ptr = ((u1*) wordPtr) + dataLen;
-        ptr = (u1*) (((int) ptr + 3) & ~3);
-    }
-
-    if (ptr - (u1*) pIndexMapSet->chunkData != chunkLen) {
-        LOGE("GLITCH: expected len=%d, actual=%d\n",
-            chunkLen, ptr - (u1*) pIndexMapSet->chunkData);
-        dvmAbort();
-    }
-
-    return true;
-}
-#endif
-
-/*
- * Construct the "chunk" of data that will be appended to the optimized DEX
- * file.
- */
-static bool constructDataChunk(IndexMapSet* pIndexMapSet)
-{
-    assert(sizeof(pIndexMapSet->map[0].mapToOld[0]) == sizeof(u2));
-    assert(sizeof(pIndexMapSet->map[0].mapToNew[0]) == sizeof(u2));
-
-#if DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
-    return constructExpandingDataChunk(pIndexMapSet);
-#else
-    return constructReducingDataChunk(pIndexMapSet);
-#endif
-}
-
-/*
- * Allocate storage to hold the maps.
- */
-static IndexMapSet* createIndexMapSet(const DexFile* pDexFile,
-    ScanResults* pResults)
-{
-    IndexMapSet* pIndexMapSet;
-    bool okay = true;
-
-    pIndexMapSet = calloc(1, sizeof(*pIndexMapSet));
-    if (pIndexMapSet == NULL)
-        return NULL;
-
-    okay = okay && constructIndexMap(pDexFile->pHeader->typeIdsSize,
-            pResults->usedClasses, &pIndexMapSet->map[kMapClasses]);
-    okay = okay && constructIndexMap(pDexFile->pHeader->methodIdsSize,
-            pResults->usedMethods, &pIndexMapSet->map[kMapMethods]);
-    okay = okay && constructIndexMap(pDexFile->pHeader->fieldIdsSize,
-            pResults->usedFields, &pIndexMapSet->map[kMapFields]);
-    okay = okay && constructIndexMap(pDexFile->pHeader->stringIdsSize,
-            pResults->usedStrings, &pIndexMapSet->map[kMapStrings]);
-
-    LOGVV("Constr: %d %d %d %d\n",
-        pIndexMapSet->map[kMapClasses].mapToOld[0],
-        pIndexMapSet->map[kMapMethods].mapToOld[0],
-        pIndexMapSet->map[kMapFields].mapToOld[0],
-        pIndexMapSet->map[kMapStrings].mapToOld[0]);
-
-    okay = okay && constructDataChunk(pIndexMapSet);
-
-    if (!okay) {
-        dvmFreeIndexMapSet(pIndexMapSet);
-        return NULL;
-    }
-
-    return pIndexMapSet;
-}
-
-/*
- * Free map storage.
- *
- * "pIndexMapSet" may be incomplete.
- */
-void dvmFreeIndexMapSet(IndexMapSet* pIndexMapSet)
-{
-    int i;
-
-    if (pIndexMapSet == NULL)
-        return;
-
-    for (i = 0; i < kNumIndexMaps; i++) {
-        free(pIndexMapSet->map[i].mapToOld);
-        free(pIndexMapSet->map[i].mapToNew);
-    }
-    free(pIndexMapSet->chunkData);
-    free(pIndexMapSet);
-}
-
-/*
- * Rewrite constant indexes to reduce heap requirements.
- */
-IndexMapSet* dvmRewriteConstants(DvmDex* pDvmDex)
-{
-#if (DVM_RESOLVER_CACHE != DVM_RC_REDUCING) && \
-    (DVM_RESOLVER_CACHE != DVM_RC_EXPANDING)
-    /* nothing to do */
-    return NULL;
-#endif
-
-    /*
-     * We're looking for instructions that use "constant pool" entries for
-     * classes, methods, fields, and strings.  Many field and method entries
-     * are optimized away, and many string constants are never accessed from
-     * code or annotations.
-     */
-    ScanResults* pResults = allocScanResults(pDvmDex->pDexFile);
-    forAllMethods(pDvmDex->pDexFile, markUsedConstants, pResults);
-
-    summarizeResults(pDvmDex, pResults);
-
-    /*
-     * Allocate and populate the index maps.
-     */
-    IndexMapSet* pIndexMapSet = createIndexMapSet(pDvmDex->pDexFile, pResults);
-#if DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
-    if (pIndexMapSet != NULL) {
-        /*
-         * Rewrite the constants to use the reduced set.
-         */
-        forAllMethods(pDvmDex->pDexFile, updateUsedConstants, pIndexMapSet);
-    }
-#endif
-
-    freeScanResults(pResults);
-
-    return pIndexMapSet;
-}
diff --git a/vm/analysis/ReduceConstants.h b/vm/analysis/ReduceConstants.h
deleted file mode 100644
index 342e125..0000000
--- a/vm/analysis/ReduceConstants.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * DEX constant-reduction declarations.
- */
-#ifndef _DALVIK_REDUCECONSTANTS
-#define _DALVIK_REDUCECONSTANTS
-
-#define DVM_RC_DISABLED     0       /* no reduction, 1:1 map */
-#define DVM_RC_REDUCING     1       /* normal constants, reduced lookup table */
-#define DVM_RC_EXPANDING    2       /* reduced constants, expanded on resolve */
-#define DVM_RC_NO_CACHE     3       /* disable the cache (reduce to zero) */
-
-enum {
-    kMapClasses     = 0,
-    kMapMethods     = 1,
-    kMapFields      = 2,
-    kMapStrings     = 3,
-
-    kNumIndexMaps
-};
-
-struct DvmDex;
-
-#define kNoIndexMapping     ((u2) -1)
-
-/*
- * Map indices back to the original.
- */
-typedef struct IndexMap {
-    int origCount;      /* original size; describes range of entries in map */
-    int newCount;       /* reduced size */
-    u2* mapToNew;       /* sparse map, from "orig" to "new" */
-    u2* mapToOld;       /* dense map, from "new" back to "orig" */
-} IndexMap;
-typedef struct IndexMapSet {
-    /* maps for the different sections */
-    IndexMap    map[kNumIndexMaps];
-
-    /* data stream that gets appended to the optimized DEX file */
-    u4          chunkType;
-    int         chunkDataLen;
-    u1*         chunkData;
-} IndexMapSet;
-
-/*
- * Constant pool compaction.
- *
- * The caller is responsible for freeing the returned structure by
- * calling dvmFreeIndexMap().
- */
-IndexMapSet* dvmRewriteConstants(struct DvmDex* pDvmDex);
-
-/* free an index map set */
-void dvmFreeIndexMapSet(IndexMapSet* indexMapSet);
-
-#endif /*_DALVIK_REDUCECONSTANTS*/