/*
 * 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.
 */

/*
 * Perform some simple bytecode optimizations, chiefly "quickening" of
 * opcodes.
 */
#include "Dalvik.h"
#include "libdex/InstrUtils.h"
#include "Optimize.h"

#include <zlib.h>

#include <stdlib.h>

/*
 * Virtual/direct calls to "method" are replaced with an execute-inline
 * instruction with index "idx".
 */
struct InlineSub {
    Method* method;
    int     inlineIdx;
};


/* fwd */
static void optimizeMethod(Method* method, bool essentialOnly);
static void rewriteInstField(Method* method, u2* insns, Opcode quickOpc,
    Opcode volatileOpc);
static void rewriteJumboInstField(Method* method, u2* insns,
    Opcode volatileOpc);
static void rewriteStaticField(Method* method, u2* insns, Opcode volatileOpc);
static void rewriteJumboStaticField(Method* method, u2* insns,
    Opcode volatileOpc);
static void rewriteVirtualInvoke(Method* method, u2* insns, Opcode newOpc);
static bool rewriteInvokeObjectInit(Method* method, u2* insns);
static bool rewriteJumboInvokeObjectInit(Method* method, u2* insns);
static bool rewriteExecuteInline(Method* method, u2* insns,
    MethodType methodType);
static bool rewriteExecuteInlineRange(Method* method, u2* insns,
    MethodType methodType);
static void rewriteReturnVoid(Method* method, u2* insns);
static bool needsReturnBarrier(Method* method);


/*
 * Create a table of inline substitutions.  Sets gDvm.inlineSubs.
 *
 * TODO: this is currently just a linear array.  We will want to put this
 * into a hash table as the list size increases.
 */
bool dvmCreateInlineSubsTable()
{
    const InlineOperation* ops = dvmGetInlineOpsTable();
    const int count = dvmGetInlineOpsTableLength();
    InlineSub* table;
    int i, tableIndex;

    assert(gDvm.inlineSubs == NULL);

    /*
     * One slot per entry, plus an end-of-list marker.
     */
    table = (InlineSub*) calloc(count + 1, sizeof(InlineSub));

    tableIndex = 0;
    for (i = 0; i < count; i++) {
        Method* method = dvmFindInlinableMethod(ops[i].classDescriptor,
            ops[i].methodName, ops[i].methodSignature);
        if (method == NULL) {
            /*
             * Not expected.  We only use this for key methods in core
             * classes, so we should always be able to find them.
             */
            LOGE("Unable to find method for inlining: %s.%s:%s",
                ops[i].classDescriptor, ops[i].methodName,
                ops[i].methodSignature);
            return false;
        }

        table[tableIndex].method = method;
        table[tableIndex].inlineIdx = i;
        tableIndex++;
    }

    /* mark end of table */
    table[tableIndex].method = NULL;

    gDvm.inlineSubs = table;
    return true;
}

/*
 * Release inline sub data structure.
 */
void dvmFreeInlineSubsTable()
{
    free(gDvm.inlineSubs);
    gDvm.inlineSubs = NULL;
}


/*
 * Optimize the specified class.
 *
 * If "essentialOnly" is true, we only do essential optimizations.  For
 * example, accesses to volatile 64-bit fields must be replaced with
 * "-wide-volatile" instructions or the program could behave incorrectly.
 * (Skipping non-essential optimizations makes us a little bit faster, and
 * more importantly avoids dirtying DEX pages.)
 */
void dvmOptimizeClass(ClassObject* clazz, bool essentialOnly)
{
    int i;

    for (i = 0; i < clazz->directMethodCount; i++) {
        optimizeMethod(&clazz->directMethods[i], essentialOnly);
    }
    for (i = 0; i < clazz->virtualMethodCount; i++) {
        optimizeMethod(&clazz->virtualMethods[i], essentialOnly);
    }
}

/*
 * Optimize instructions in a method.
 *
 * This does a single pass through the code, examining each instruction.
 *
 * This is not expected to fail if the class was successfully verified.
 * The only significant failure modes on unverified code occur when an
 * "essential" update fails, but we can't generally identify those: if we
 * can't look up a field, we can't know if the field access was supposed
 * to be handled as volatile.
 *
 * Instead, we give it our best effort, and hope for the best.  For 100%
 * reliability, only optimize a class after verification succeeds.
 */
static void optimizeMethod(Method* method, bool essentialOnly)
{
    bool needRetBar, forSmp;
    u4 insnsSize;
    u2* insns;

    if (dvmIsNativeMethod(method) || dvmIsAbstractMethod(method))
        return;

    forSmp = gDvm.dexOptForSmp;
    needRetBar = needsReturnBarrier(method);

    insns = (u2*) method->insns;
    assert(insns != NULL);
    insnsSize = dvmGetMethodInsnsSize(method);

    while (insnsSize > 0) {
        Opcode opc, quickOpc, volatileOpc;
        size_t width;
        bool matched = true;

        opc = dexOpcodeFromCodeUnit(*insns);
        width = dexGetWidthFromInstruction(insns);
        volatileOpc = OP_NOP;

        /*
         * Each instruction may have:
         * - "volatile" replacement
         *   - may be essential or essential-on-SMP
         * - correctness replacement
         *   - may be essential or essential-on-SMP
         * - performance replacement
         *   - always non-essential
         *
         * Replacements are considered in the order shown, and the first
         * match is applied.  For example, iget-wide will convert to
         * iget-wide-volatile rather than iget-wide-quick if the target
         * field is volatile.
         */

        /*
         * essential substitutions:
         *  {iget,iput,sget,sput}-wide[/jumbo] --> {op}-wide-volatile
         *  invoke-direct[/jumbo][/range] --> invoke-object-init/range
         *
         * essential-on-SMP substitutions:
         *  {iget,iput,sget,sput}-*[/jumbo] --> {op}-volatile
         *  return-void --> return-void-barrier
         *
         * non-essential substitutions:
         *  {iget,iput}-* --> {op}-quick
         *
         * TODO: might be time to merge this with the other two switches
         */
        switch (opc) {
        case OP_IGET:
        case OP_IGET_BOOLEAN:
        case OP_IGET_BYTE:
        case OP_IGET_CHAR:
        case OP_IGET_SHORT:
            quickOpc = OP_IGET_QUICK;
            if (forSmp)
                volatileOpc = OP_IGET_VOLATILE;
            goto rewrite_inst_field;
        case OP_IGET_WIDE:
            quickOpc = OP_IGET_WIDE_QUICK;
            volatileOpc = OP_IGET_WIDE_VOLATILE;
            goto rewrite_inst_field;
        case OP_IGET_OBJECT:
            quickOpc = OP_IGET_OBJECT_QUICK;
            if (forSmp)
                volatileOpc = OP_IGET_OBJECT_VOLATILE;
            goto rewrite_inst_field;
        case OP_IPUT:
        case OP_IPUT_BOOLEAN:
        case OP_IPUT_BYTE:
        case OP_IPUT_CHAR:
        case OP_IPUT_SHORT:
            quickOpc = OP_IPUT_QUICK;
            if (forSmp)
                volatileOpc = OP_IPUT_VOLATILE;
            goto rewrite_inst_field;
        case OP_IPUT_WIDE:
            quickOpc = OP_IPUT_WIDE_QUICK;
            volatileOpc = OP_IPUT_WIDE_VOLATILE;
            goto rewrite_inst_field;
        case OP_IPUT_OBJECT:
            quickOpc = OP_IPUT_OBJECT_QUICK;
            if (forSmp)
                volatileOpc = OP_IPUT_OBJECT_VOLATILE;
            /* fall through */
rewrite_inst_field:
            if (essentialOnly)
                quickOpc = OP_NOP;      /* if essential-only, no "-quick" sub */
            if (quickOpc != OP_NOP || volatileOpc != OP_NOP)
                rewriteInstField(method, insns, quickOpc, volatileOpc);
            break;

        case OP_IGET_JUMBO:
        case OP_IGET_BOOLEAN_JUMBO:
        case OP_IGET_BYTE_JUMBO:
        case OP_IGET_CHAR_JUMBO:
        case OP_IGET_SHORT_JUMBO:
            if (forSmp)
                volatileOpc = OP_IGET_VOLATILE_JUMBO;
            goto rewrite_jumbo_inst_field;
        case OP_IGET_WIDE_JUMBO:
            volatileOpc = OP_IGET_WIDE_VOLATILE_JUMBO;
            goto rewrite_jumbo_inst_field;
        case OP_IGET_OBJECT_JUMBO:
            if (forSmp)
                volatileOpc = OP_IGET_OBJECT_VOLATILE_JUMBO;
            goto rewrite_jumbo_inst_field;
        case OP_IPUT_JUMBO:
        case OP_IPUT_BOOLEAN_JUMBO:
        case OP_IPUT_BYTE_JUMBO:
        case OP_IPUT_CHAR_JUMBO:
        case OP_IPUT_SHORT_JUMBO:
            if (forSmp)
                volatileOpc = OP_IPUT_VOLATILE_JUMBO;
            goto rewrite_jumbo_inst_field;
        case OP_IPUT_WIDE_JUMBO:
            volatileOpc = OP_IPUT_WIDE_VOLATILE_JUMBO;
            goto rewrite_jumbo_inst_field;
        case OP_IPUT_OBJECT_JUMBO:
            if (forSmp)
                volatileOpc = OP_IPUT_OBJECT_VOLATILE_JUMBO;
            /* fall through */
rewrite_jumbo_inst_field:
            if (volatileOpc != OP_NOP)
                rewriteJumboInstField(method, insns, volatileOpc);
            break;

        case OP_SGET:
        case OP_SGET_BOOLEAN:
        case OP_SGET_BYTE:
        case OP_SGET_CHAR:
        case OP_SGET_SHORT:
            if (forSmp)
                volatileOpc = OP_SGET_VOLATILE;
            goto rewrite_static_field;
        case OP_SGET_WIDE:
            volatileOpc = OP_SGET_WIDE_VOLATILE;
            goto rewrite_static_field;
        case OP_SGET_OBJECT:
            if (forSmp)
                volatileOpc = OP_SGET_OBJECT_VOLATILE;
            goto rewrite_static_field;
        case OP_SPUT:
        case OP_SPUT_BOOLEAN:
        case OP_SPUT_BYTE:
        case OP_SPUT_CHAR:
        case OP_SPUT_SHORT:
            if (forSmp)
                volatileOpc = OP_SPUT_VOLATILE;
            goto rewrite_static_field;
        case OP_SPUT_WIDE:
            volatileOpc = OP_SPUT_WIDE_VOLATILE;
            goto rewrite_static_field;
        case OP_SPUT_OBJECT:
            if (forSmp)
                volatileOpc = OP_SPUT_OBJECT_VOLATILE;
            /* fall through */
rewrite_static_field:
            if (volatileOpc != OP_NOP)
                rewriteStaticField(method, insns, volatileOpc);
            break;

        case OP_SGET_JUMBO:
        case OP_SGET_BOOLEAN_JUMBO:
        case OP_SGET_BYTE_JUMBO:
        case OP_SGET_CHAR_JUMBO:
        case OP_SGET_SHORT_JUMBO:
            if (forSmp)
                volatileOpc = OP_SGET_VOLATILE_JUMBO;
            goto rewrite_jumbo_static_field;
        case OP_SGET_WIDE_JUMBO:
            volatileOpc = OP_SGET_WIDE_VOLATILE_JUMBO;
            goto rewrite_jumbo_static_field;
        case OP_SGET_OBJECT_JUMBO:
            if (forSmp)
                volatileOpc = OP_SGET_OBJECT_VOLATILE_JUMBO;
            goto rewrite_jumbo_static_field;
        case OP_SPUT_JUMBO:
        case OP_SPUT_BOOLEAN_JUMBO:
        case OP_SPUT_BYTE_JUMBO:
        case OP_SPUT_CHAR_JUMBO:
        case OP_SPUT_SHORT_JUMBO:
            if (forSmp)
                volatileOpc = OP_SPUT_VOLATILE_JUMBO;
            goto rewrite_jumbo_static_field;
        case OP_SPUT_WIDE_JUMBO:
            volatileOpc = OP_SPUT_WIDE_VOLATILE_JUMBO;
            goto rewrite_jumbo_static_field;
        case OP_SPUT_OBJECT_JUMBO:
            if (forSmp)
                volatileOpc = OP_SPUT_OBJECT_VOLATILE_JUMBO;
            /* fall through */
rewrite_jumbo_static_field:
            if (volatileOpc != OP_NOP)
                rewriteJumboStaticField(method, insns, volatileOpc);
            break;

        case OP_INVOKE_DIRECT:
        case OP_INVOKE_DIRECT_RANGE:
            if (!rewriteInvokeObjectInit(method, insns)) {
                /* may want to try execute-inline, below */
                matched = false;
            }
            break;
        case OP_INVOKE_DIRECT_JUMBO:
            rewriteJumboInvokeObjectInit(method, insns);
            break;
        case OP_RETURN_VOID:
            if (needRetBar)
                rewriteReturnVoid(method, insns);
            break;
        default:
            matched = false;
            break;
        }


        /*
         * non-essential substitutions:
         *  invoke-{virtual,direct,static}[/range] --> execute-inline
         *  invoke-{virtual,super}[/range] --> invoke-*-quick
         */
        if (!matched && !essentialOnly) {
            switch (opc) {
            case OP_INVOKE_VIRTUAL:
                if (!rewriteExecuteInline(method, insns, METHOD_VIRTUAL)) {
                    rewriteVirtualInvoke(method, insns,
                        OP_INVOKE_VIRTUAL_QUICK);
                }
                break;
            case OP_INVOKE_VIRTUAL_RANGE:
                if (!rewriteExecuteInlineRange(method, insns, METHOD_VIRTUAL)) {
                    rewriteVirtualInvoke(method, insns,
                        OP_INVOKE_VIRTUAL_QUICK_RANGE);
                }
                break;
            case OP_INVOKE_SUPER:
                rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK);
                break;
            case OP_INVOKE_SUPER_RANGE:
                rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK_RANGE);
                break;
            case OP_INVOKE_DIRECT:
                rewriteExecuteInline(method, insns, METHOD_DIRECT);
                break;
            case OP_INVOKE_DIRECT_RANGE:
                rewriteExecuteInlineRange(method, insns, METHOD_DIRECT);
                break;
            case OP_INVOKE_STATIC:
                rewriteExecuteInline(method, insns, METHOD_STATIC);
                break;
            case OP_INVOKE_STATIC_RANGE:
                rewriteExecuteInlineRange(method, insns, METHOD_STATIC);
                break;
            default:
                /* nothing to do for this instruction */
                ;
            }
        }

        assert(width > 0);
        assert(width <= insnsSize);
        assert(width == dexGetWidthFromInstruction(insns));

        insns += width;
        insnsSize -= width;
    }

    assert(insnsSize == 0);
}

/*
 * Update a 16-bit code unit in "meth".  The way in which the DEX data was
 * loaded determines how we go about the write.
 *
 * This will be operating on post-byte-swap DEX data, so values will
 * be in host order.
 */
void dvmUpdateCodeUnit(const Method* meth, u2* ptr, u2 newVal)
{
    DvmDex* pDvmDex = meth->clazz->pDvmDex;

    if (!pDvmDex->isMappedReadOnly) {
        /* in-memory DEX (dexopt or byte[]), alter the output directly */
        *ptr = newVal;
    } else {
        /* memory-mapped file, toggle the page read/write status */
        dvmDexChangeDex2(pDvmDex, ptr, newVal);
    }
}

/*
 * Update an instruction's opcode.
 *
 * If "opcode" is an 8-bit op, we just replace that portion.  If it's a
 * 16-bit op, we convert the opcode from "packed" form (e.g. 0x0108) to
 * bytecode form (e.g. 0x08ff).
 */
static inline void updateOpcode(const Method* meth, u2* ptr, Opcode opcode)
{
    if (opcode >= 256) {
        /* opcode low byte becomes high byte, low byte becomes 0xff */
        assert((ptr[0] & 0xff) == 0xff);
        dvmUpdateCodeUnit(meth, ptr, (u2) (opcode << 8) | 0x00ff);
    } else {
        /* 8-bit op, just replace the low byte */
        assert((ptr[0] & 0xff) != 0xff);
        dvmUpdateCodeUnit(meth, ptr, (ptr[0] & 0xff00) | (u2) opcode);
    }
}

/*
 * If "referrer" and "resClass" don't come from the same DEX file, and
 * the DEX we're working on is not destined for the bootstrap class path,
 * tweak the class loader so package-access checks work correctly.
 *
 * Only do this if we're doing pre-verification or optimization.
 */
static void tweakLoader(ClassObject* referrer, ClassObject* resClass)
{
    if (!gDvm.optimizing)
        return;
    assert(referrer->classLoader == NULL);
    assert(resClass->classLoader == NULL);

    if (!gDvm.optimizingBootstrapClass) {
        /* class loader for an array class comes from element type */
        if (dvmIsArrayClass(resClass))
            resClass = resClass->elementClass;
        if (referrer->pDvmDex != resClass->pDvmDex)
            resClass->classLoader = (Object*) 0xdead3333;
    }
}

/*
 * Undo the effects of tweakLoader.
 */
static void untweakLoader(ClassObject* referrer, ClassObject* resClass)
{
    if (!gDvm.optimizing || gDvm.optimizingBootstrapClass)
        return;

    if (dvmIsArrayClass(resClass))
        resClass = resClass->elementClass;
    resClass->classLoader = NULL;
}


/*
 * Alternate version of dvmResolveClass for use with verification and
 * optimization.  Performs access checks on every resolve, and refuses
 * to acknowledge the existence of classes defined in more than one DEX
 * file.
 *
 * Exceptions caused by failures are cleared before returning.
 *
 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
 */
ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx,
    VerifyError* pFailure)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    ClassObject* resClass;

    /*
     * Check the table first.  If not there, do the lookup by name.
     */
    resClass = dvmDexGetResolvedClass(pDvmDex, classIdx);
    if (resClass == NULL) {
        const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, classIdx);
        if (className[0] != '\0' && className[1] == '\0') {
            /* primitive type */
            resClass = dvmFindPrimitiveClass(className[0]);
        } else {
            resClass = dvmFindClassNoInit(className, referrer->classLoader);
        }
        if (resClass == NULL) {
            /* not found, exception should be raised */
            ALOGV("DexOpt: class %d (%s) not found",
                classIdx,
                dexStringByTypeIdx(pDvmDex->pDexFile, classIdx));
            if (pFailure != NULL) {
                /* dig through the wrappers to find the original failure */
                Object* excep = dvmGetException(dvmThreadSelf());
                while (true) {
                    Object* cause = dvmGetExceptionCause(excep);
                    if (cause == NULL)
                        break;
                    excep = cause;
                }
                if (strcmp(excep->clazz->descriptor,
                    "Ljava/lang/IncompatibleClassChangeError;") == 0)
                {
                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
                } else {
                    *pFailure = VERIFY_ERROR_NO_CLASS;
                }
            }
            dvmClearOptException(dvmThreadSelf());
            return NULL;
        }

        /*
         * Add it to the resolved table so we're faster on the next lookup.
         */
        dvmDexSetResolvedClass(pDvmDex, classIdx, resClass);
    }

    /* multiple definitions? */
    if (IS_CLASS_FLAG_SET(resClass, CLASS_MULTIPLE_DEFS)) {
        LOGI("DexOpt: not resolving ambiguous class '%s'",
            resClass->descriptor);
        if (pFailure != NULL)
            *pFailure = VERIFY_ERROR_NO_CLASS;
        return NULL;
    }

    /* access allowed? */
    tweakLoader(referrer, resClass);
    bool allowed = dvmCheckClassAccess(referrer, resClass);
    untweakLoader(referrer, resClass);
    if (!allowed) {
        LOGW("DexOpt: resolve class illegal access: %s -> %s",
            referrer->descriptor, resClass->descriptor);
        if (pFailure != NULL)
            *pFailure = VERIFY_ERROR_ACCESS_CLASS;
        return NULL;
    }

    return resClass;
}

/*
 * Alternate version of dvmResolveInstField().
 *
 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
 */
InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
    VerifyError* pFailure)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    InstField* resField;

    resField = (InstField*) dvmDexGetResolvedField(pDvmDex, ifieldIdx);
    if (resField == NULL) {
        const DexFieldId* pFieldId;
        ClassObject* resClass;

        pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx);

        /*
         * Find the field's class.
         */
        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
        if (resClass == NULL) {
            //dvmClearOptException(dvmThreadSelf());
            assert(!dvmCheckException(dvmThreadSelf()));
            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
            return NULL;
        }

        resField = (InstField*)dvmFindFieldHier(resClass,
            dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
            dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
        if (resField == NULL) {
            ALOGD("DexOpt: couldn't find field %s.%s",
                resClass->descriptor,
                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_NO_FIELD;
            return NULL;
        }
        if (dvmIsStaticField(resField)) {
            ALOGD("DexOpt: wanted instance, got static for field %s.%s",
                resClass->descriptor,
                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_CLASS_CHANGE;
            return NULL;
        }

        /*
         * Add it to the resolved table so we're faster on the next lookup.
         */
        dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*) resField);
    }

    /* access allowed? */
    tweakLoader(referrer, resField->clazz);
    bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField);
    untweakLoader(referrer, resField->clazz);
    if (!allowed) {
        LOGI("DexOpt: access denied from %s to field %s.%s",
            referrer->descriptor, resField->clazz->descriptor,
            resField->name);
        if (pFailure != NULL)
            *pFailure = VERIFY_ERROR_ACCESS_FIELD;
        return NULL;
    }

    return resField;
}

/*
 * Alternate version of dvmResolveStaticField().
 *
 * Does not force initialization of the resolved field's class.
 *
 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
 */
StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
    VerifyError* pFailure)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    StaticField* resField;

    resField = (StaticField*)dvmDexGetResolvedField(pDvmDex, sfieldIdx);
    if (resField == NULL) {
        const DexFieldId* pFieldId;
        ClassObject* resClass;

        pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx);

        /*
         * Find the field's class.
         */
        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
        if (resClass == NULL) {
            //dvmClearOptException(dvmThreadSelf());
            assert(!dvmCheckException(dvmThreadSelf()));
            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
            return NULL;
        }

        const char* fieldName =
            dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);

        resField = (StaticField*)dvmFindFieldHier(resClass, fieldName,
                    dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
        if (resField == NULL) {
            ALOGD("DexOpt: couldn't find static field %s.%s",
                resClass->descriptor, fieldName);
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_NO_FIELD;
            return NULL;
        }
        if (!dvmIsStaticField(resField)) {
            ALOGD("DexOpt: wanted static, got instance for field %s.%s",
                resClass->descriptor, fieldName);
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_CLASS_CHANGE;
            return NULL;
        }

        /*
         * Add it to the resolved table so we're faster on the next lookup.
         *
         * We can only do this if we're in "dexopt", because the presence
         * of a valid value in the resolution table implies that the class
         * containing the static field has been initialized.
         */
        if (gDvm.optimizing)
            dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField);
    }

    /* access allowed? */
    tweakLoader(referrer, resField->clazz);
    bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField);
    untweakLoader(referrer, resField->clazz);
    if (!allowed) {
        LOGI("DexOpt: access denied from %s to field %s.%s",
            referrer->descriptor, resField->clazz->descriptor,
            resField->name);
        if (pFailure != NULL)
            *pFailure = VERIFY_ERROR_ACCESS_FIELD;
        return NULL;
    }

    return resField;
}


/*
 * Rewrite an iget/iput instruction if appropriate.  These all have the form:
 *   op vA, vB, field@CCCC
 *
 * Where vA holds the value, vB holds the object reference, and CCCC is
 * the field reference constant pool offset.  For a non-volatile field,
 * we want to replace the opcode with "quickOpc" and replace CCCC with
 * the byte offset from the start of the object.  For a volatile field,
 * we just want to replace the opcode with "volatileOpc".
 *
 * If "volatileOpc" is OP_NOP we don't check to see if it's a volatile
 * field.  If "quickOpc" is OP_NOP, and this is a non-volatile field,
 * we don't do anything.
 *
 * "method" is the referring method.
 */
static void rewriteInstField(Method* method, u2* insns, Opcode quickOpc,
    Opcode volatileOpc)
{
    ClassObject* clazz = method->clazz;
    u2 fieldIdx = insns[1];
    InstField* instField;

    instField = dvmOptResolveInstField(clazz, fieldIdx, NULL);
    if (instField == NULL) {
        LOGI("DexOpt: unable to optimize instance field ref "
             "0x%04x at 0x%02x in %s.%s",
            fieldIdx, (int) (insns - method->insns), clazz->descriptor,
            method->name);
        return;
    }

    if (volatileOpc != OP_NOP && dvmIsVolatileField(instField)) {
        updateOpcode(method, insns, volatileOpc);
        ALOGV("DexOpt: rewrote ifield access %s.%s --> volatile",
            instField->clazz->descriptor, instField->name);
    } else if (quickOpc != OP_NOP && instField->byteOffset < 65536) {
        updateOpcode(method, insns, quickOpc);
        dvmUpdateCodeUnit(method, insns+1, (u2) instField->byteOffset);
        ALOGV("DexOpt: rewrote ifield access %s.%s --> %d",
            instField->clazz->descriptor, instField->name,
            instField->byteOffset);
    } else {
        ALOGV("DexOpt: no rewrite of ifield access %s.%s",
            instField->clazz->descriptor, instField->name);
    }

    return;
}

/*
 * Rewrite a jumbo instance field access instruction if appropriate.  If
 * the target field is volatile, we replace the opcode with "volatileOpc".
 *
 * "method" is the referring method.
 */
static void rewriteJumboInstField(Method* method, u2* insns, Opcode volatileOpc)
{
    ClassObject* clazz = method->clazz;
    u4 fieldIdx = insns[1] | (u4) insns[2] << 16;
    InstField* instField;

    assert(volatileOpc != OP_NOP);

    instField = dvmOptResolveInstField(clazz, fieldIdx, NULL);
    if (instField == NULL) {
        LOGI("DexOpt: unable to optimize instance field ref "
             "0x%04x at 0x%02x in %s.%s",
            fieldIdx, (int) (insns - method->insns), clazz->descriptor,
            method->name);
        return;
    }

    if (dvmIsVolatileField(instField)) {
        updateOpcode(method, insns, volatileOpc);
        ALOGV("DexOpt: rewrote jumbo ifield access %s.%s --> volatile",
            instField->clazz->descriptor, instField->name);
    } else {
        ALOGV("DexOpt: no rewrite of jumbo ifield access %s.%s",
            instField->clazz->descriptor, instField->name);
    }
}

/*
 * Rewrite a static [jumbo] field access instruction if appropriate.  If
 * the target field is volatile, we replace the opcode with "volatileOpc".
 *
 * "method" is the referring method.
 */
static void rewriteStaticField0(Method* method, u2* insns, Opcode volatileOpc,
    u4 fieldIdx)
{
    ClassObject* clazz = method->clazz;
    StaticField* staticField;

    assert(volatileOpc != OP_NOP);

    staticField = dvmOptResolveStaticField(clazz, fieldIdx, NULL);
    if (staticField == NULL) {
        LOGI("DexOpt: unable to optimize static field ref "
             "0x%04x at 0x%02x in %s.%s",
            fieldIdx, (int) (insns - method->insns), clazz->descriptor,
            method->name);
        return;
    }

    if (dvmIsVolatileField(staticField)) {
        updateOpcode(method, insns, volatileOpc);
        ALOGV("DexOpt: rewrote sfield access %s.%s --> volatile",
            staticField->clazz->descriptor, staticField->name);
    }
}

static void rewriteStaticField(Method* method, u2* insns, Opcode volatileOpc)
{
    u2 fieldIdx = insns[1];
    rewriteStaticField0(method, insns, volatileOpc, fieldIdx);
}
static void rewriteJumboStaticField(Method* method, u2* insns,
    Opcode volatileOpc)
{
    u4 fieldIdx = insns[1] | (u4) insns[2] << 16;
    rewriteStaticField0(method, insns, volatileOpc, fieldIdx);
}


/*
 * Alternate version of dvmResolveMethod().
 *
 * Doesn't throw exceptions, and checks access on every lookup.
 *
 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
 */
Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx,
    MethodType methodType, VerifyError* pFailure)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    Method* resMethod;

    assert(methodType == METHOD_DIRECT ||
           methodType == METHOD_VIRTUAL ||
           methodType == METHOD_STATIC);

    LOGVV("--- resolving method %u (referrer=%s)", methodIdx,
        referrer->descriptor);

    resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
    if (resMethod == NULL) {
        const DexMethodId* pMethodId;
        ClassObject* resClass;

        pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);

        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, pFailure);
        if (resClass == NULL) {
            /*
             * Can't find the class that the method is a part of, or don't
             * have permission to access the class.
             */
            ALOGV("DexOpt: can't find called method's class (?.%s)",
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
            return NULL;
        }
        if (dvmIsInterfaceClass(resClass)) {
            /* method is part of an interface; this is wrong method for that */
            LOGW("DexOpt: method is in an interface");
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_GENERIC;
            return NULL;
        }

        /*
         * We need to chase up the class hierarchy to find methods defined
         * in super-classes.  (We only want to check the current class
         * if we're looking for a constructor.)
         */
        DexProto proto;
        dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);

        if (methodType == METHOD_DIRECT) {
            resMethod = dvmFindDirectMethod(resClass,
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
        } else {
            /* METHOD_STATIC or METHOD_VIRTUAL */
            resMethod = dvmFindMethodHier(resClass,
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
        }

        if (resMethod == NULL) {
            ALOGV("DexOpt: couldn't find method '%s'",
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_NO_METHOD;
            return NULL;
        }
        if (methodType == METHOD_STATIC) {
            if (!dvmIsStaticMethod(resMethod)) {
                ALOGD("DexOpt: wanted static, got instance for method %s.%s",
                    resClass->descriptor, resMethod->name);
                if (pFailure != NULL)
                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
                return NULL;
            }
        } else if (methodType == METHOD_VIRTUAL) {
            if (dvmIsStaticMethod(resMethod)) {
                ALOGD("DexOpt: wanted instance, got static for method %s.%s",
                    resClass->descriptor, resMethod->name);
                if (pFailure != NULL)
                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
                return NULL;
            }
        }

        /* see if this is a pure-abstract method */
        if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
            LOGW("DexOpt: pure-abstract method '%s' in %s",
                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx),
                resClass->descriptor);
            if (pFailure != NULL)
                *pFailure = VERIFY_ERROR_GENERIC;
            return NULL;
        }

        /*
         * Add it to the resolved table so we're faster on the next lookup.
         *
         * We can only do this for static methods if we're not in "dexopt",
         * because the presence of a valid value in the resolution table
         * implies that the class containing the static field has been
         * initialized.
         */
        if (methodType != METHOD_STATIC || gDvm.optimizing)
            dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
    }

    LOGVV("--- found method %d (%s.%s)",
        methodIdx, resMethod->clazz->descriptor, resMethod->name);

    /* access allowed? */
    tweakLoader(referrer, resMethod->clazz);
    bool allowed = dvmCheckMethodAccess(referrer, resMethod);
    untweakLoader(referrer, resMethod->clazz);
    if (!allowed) {
        IF_LOGI() {
            char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
            LOGI("DexOpt: illegal method access (call %s.%s %s from %s)",
                resMethod->clazz->descriptor, resMethod->name, desc,
                referrer->descriptor);
            free(desc);
        }
        if (pFailure != NULL)
            *pFailure = VERIFY_ERROR_ACCESS_METHOD;
        return NULL;
    }

    return resMethod;
}

/*
 * Rewrite invoke-virtual, invoke-virtual/range, invoke-super, and
 * invoke-super/range if appropriate.  These all have the form:
 *   op vAA, meth@BBBB, reg stuff @CCCC
 *
 * We want to replace the method constant pool index BBBB with the
 * vtable index.
 */
static void rewriteVirtualInvoke(Method* method, u2* insns, Opcode newOpc)
{
    ClassObject* clazz = method->clazz;
    Method* baseMethod;
    u2 methodIdx = insns[1];

    baseMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_VIRTUAL, NULL);
    if (baseMethod == NULL) {
        ALOGD("DexOpt: unable to optimize virt call 0x%04x at 0x%02x in %s.%s",
            methodIdx,
            (int) (insns - method->insns), clazz->descriptor,
            method->name);
        return;
    }

    assert((insns[0] & 0xff) == OP_INVOKE_VIRTUAL ||
           (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE ||
           (insns[0] & 0xff) == OP_INVOKE_SUPER ||
           (insns[0] & 0xff) == OP_INVOKE_SUPER_RANGE);

    /*
     * Note: Method->methodIndex is a u2 and is range checked during the
     * initial load.
     */
    updateOpcode(method, insns, newOpc);
    dvmUpdateCodeUnit(method, insns+1, baseMethod->methodIndex);

    //LOGI("DexOpt: rewrote call to %s.%s --> %s.%s",
    //    method->clazz->descriptor, method->name,
    //    baseMethod->clazz->descriptor, baseMethod->name);

    return;
}

/*
 * Rewrite invoke-direct[/range] if the target is Object.<init>.
 *
 * This is useful as an optimization, because otherwise every object
 * instantiation will cause us to call a method that does nothing.
 * It also allows us to inexpensively mark objects as finalizable at the
 * correct time.
 *
 * TODO: verifier should ensure Object.<init> contains only return-void,
 * and issue a warning if not.
 */
static bool rewriteInvokeObjectInit(Method* method, u2* insns)
{
    ClassObject* clazz = method->clazz;
    Method* calledMethod;
    u2 methodIdx = insns[1];

    calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT, NULL);
    if (calledMethod == NULL) {
        ALOGD("DexOpt: unable to opt direct call 0x%04x at 0x%02x in %s.%s",
            methodIdx, (int) (insns - method->insns),
            clazz->descriptor, method->name);
        return false;
    }

    if (calledMethod->clazz == gDvm.classJavaLangObject &&
        dvmCompareNameDescriptorAndMethod("<init>", "()V", calledMethod) == 0)
    {
        /*
         * Replace the instruction.  If the debugger is attached, the
         * interpreter will forward execution to the invoke-direct/range
         * handler.  If this was an invoke-direct/range instruction we can
         * just replace the opcode, but if it was an invoke-direct we
         * have to set the argument count (high 8 bits of first code unit)
         * to 1.
         */
        u1 origOp = insns[0] & 0xff;
        if (origOp == OP_INVOKE_DIRECT) {
            dvmUpdateCodeUnit(method, insns,
                OP_INVOKE_OBJECT_INIT_RANGE | 0x100);
        } else {
            assert(origOp == OP_INVOKE_DIRECT_RANGE);
            assert((insns[0] >> 8) == 1);
            updateOpcode(method, insns, OP_INVOKE_OBJECT_INIT_RANGE);
        }

        LOGVV("DexOpt: replaced Object.<init> in %s.%s",
            method->clazz->descriptor, method->name);
    }

    return true;
}

/*
 * Rewrite invoke-direct/jumbo if the target is Object.<init>.
 */
static bool rewriteJumboInvokeObjectInit(Method* method, u2* insns)
{
    ClassObject* clazz = method->clazz;
    Method* calledMethod;
    u4 methodIdx = insns[1] | (u4) insns[2] << 16;

    calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT, NULL);
    if (calledMethod == NULL) {
        ALOGD("DexOpt: unable to opt direct call 0x%04x at 0x%02x in %s.%s",
            methodIdx, (int) (insns - method->insns),
            clazz->descriptor, method->name);
        return false;
    }

    if (calledMethod->clazz == gDvm.classJavaLangObject &&
        dvmCompareNameDescriptorAndMethod("<init>", "()V", calledMethod) == 0)
    {
        assert(insns[0] == ((u2) (OP_INVOKE_DIRECT_JUMBO << 8) | 0xff));
        updateOpcode(method, insns, OP_INVOKE_OBJECT_INIT_JUMBO);

        LOGVV("DexOpt: replaced jumbo Object.<init> in %s.%s",
            method->clazz->descriptor, method->name);
    }

    return true;
}

/*
 * Resolve an interface method reference.
 *
 * No method access check here -- interface methods are always public.
 *
 * Returns NULL if the method was not found.  Does not throw an exception.
 */
Method* dvmOptResolveInterfaceMethod(ClassObject* referrer, u4 methodIdx)
{
    DvmDex* pDvmDex = referrer->pDvmDex;
    Method* resMethod;

    LOGVV("--- resolving interface method %d (referrer=%s)",
        methodIdx, referrer->descriptor);

    resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
    if (resMethod == NULL) {
        const DexMethodId* pMethodId;
        ClassObject* resClass;

        pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);

        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, NULL);
        if (resClass == NULL) {
            /* can't find the class that the method is a part of */
            dvmClearOptException(dvmThreadSelf());
            return NULL;
        }
        if (!dvmIsInterfaceClass(resClass)) {
            /* whoops */
            LOGI("Interface method not part of interface class");
            return NULL;
        }

        const char* methodName =
            dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
        DexProto proto;
        dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);

        LOGVV("+++ looking for '%s' '%s' in resClass='%s'",
            methodName, methodSig, resClass->descriptor);
        resMethod = dvmFindInterfaceMethodHier(resClass, methodName, &proto);
        if (resMethod == NULL) {
            return NULL;
        }

        /* we're expecting this to be abstract */
        if (!dvmIsAbstractMethod(resMethod)) {
            char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
            LOGW("Found non-abstract interface method %s.%s %s",
                resMethod->clazz->descriptor, resMethod->name, desc);
            free(desc);
            return NULL;
        }

        /*
         * Add it to the resolved table so we're faster on the next lookup.
         */
        dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
    }

    LOGVV("--- found interface method %d (%s.%s)",
        methodIdx, resMethod->clazz->descriptor, resMethod->name);

    /* interface methods are always public; no need to check access */

    return resMethod;
}

/*
 * Replace invoke-virtual, invoke-direct, or invoke-static with an
 * execute-inline operation if appropriate.
 *
 * Returns "true" if we replace it.
 */
static bool rewriteExecuteInline(Method* method, u2* insns,
    MethodType methodType)
{
    const InlineSub* inlineSubs = gDvm.inlineSubs;
    ClassObject* clazz = method->clazz;
    Method* calledMethod;
    u2 methodIdx = insns[1];

    //return false;

    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
    if (calledMethod == NULL) {
        ALOGV("+++ DexOpt inline: can't find %d", methodIdx);
        return false;
    }

    while (inlineSubs->method != NULL) {
        /*
        if (extra) {
            LOGI("comparing %p vs %p %s.%s %s",
                inlineSubs->method, calledMethod,
                inlineSubs->method->clazz->descriptor,
                inlineSubs->method->name,
                inlineSubs->method->signature);
        }
        */
        if (inlineSubs->method == calledMethod) {
            assert((insns[0] & 0xff) == OP_INVOKE_DIRECT ||
                   (insns[0] & 0xff) == OP_INVOKE_STATIC ||
                   (insns[0] & 0xff) == OP_INVOKE_VIRTUAL);
            updateOpcode(method, insns, OP_EXECUTE_INLINE);
            dvmUpdateCodeUnit(method, insns+1, (u2) inlineSubs->inlineIdx);

            //LOGI("DexOpt: execute-inline %s.%s --> %s.%s",
            //    method->clazz->descriptor, method->name,
            //    calledMethod->clazz->descriptor, calledMethod->name);
            return true;
        }

        inlineSubs++;
    }

    return false;
}

/*
 * Replace invoke-virtual/range, invoke-direct/range, or invoke-static/range
 * with an execute-inline operation if appropriate.
 *
 * Returns "true" if we replace it.
 */
static bool rewriteExecuteInlineRange(Method* method, u2* insns,
    MethodType methodType)
{
    const InlineSub* inlineSubs = gDvm.inlineSubs;
    ClassObject* clazz = method->clazz;
    Method* calledMethod;
    u2 methodIdx = insns[1];

    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
    if (calledMethod == NULL) {
        ALOGV("+++ DexOpt inline/range: can't find %d", methodIdx);
        return false;
    }

    while (inlineSubs->method != NULL) {
        if (inlineSubs->method == calledMethod) {
            assert((insns[0] & 0xff) == OP_INVOKE_DIRECT_RANGE ||
                   (insns[0] & 0xff) == OP_INVOKE_STATIC_RANGE ||
                   (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE);
            updateOpcode(method, insns, OP_EXECUTE_INLINE_RANGE);
            dvmUpdateCodeUnit(method, insns+1, (u2) inlineSubs->inlineIdx);

            //LOGI("DexOpt: execute-inline/range %s.%s --> %s.%s",
            //    method->clazz->descriptor, method->name,
            //    calledMethod->clazz->descriptor, calledMethod->name);
            return true;
        }

        inlineSubs++;
    }

    return false;
}

/*
 * Returns "true" if the return-void instructions in this method should
 * be converted to return-void-barrier.
 *
 * This is needed to satisfy a Java Memory Model requirement regarding
 * the construction of objects with final fields.  (This does not apply
 * to <clinit> or static fields, since appropriate barriers are guaranteed
 * by the class initialization process.)
 */
static bool needsReturnBarrier(Method* method)
{
    if (!gDvm.dexOptForSmp)
        return false;
    if (strcmp(method->name, "<init>") != 0)
        return false;

    /*
     * Check to see if the class is finalizable.  The loader sets a flag
     * if the class or one of its superclasses overrides finalize().
     */
    const ClassObject* clazz = method->clazz;
    if (IS_CLASS_FLAG_SET(clazz, CLASS_ISFINALIZABLE))
        return true;

    /*
     * Check to see if the class has any final fields.  If not, we don't
     * need to generate a barrier instruction.
     *
     * In theory, we only need to do this if the method actually modifies
     * a final field.  In practice, non-constructor methods are allowed
     * to modify final fields, and there are 3rd-party tools that rely on
     * this behavior.  (The compiler does not allow it, but the VM does.)
     *
     * If we alter the verifier to restrict final-field updates to
     * constructors, we can tighten this up as well.
     */
    int idx = clazz->ifieldCount;
    while (--idx >= 0) {
        if (dvmIsFinalField(&clazz->ifields[idx]))
            return true;
    }

    return false;
}

/*
 * Convert a return-void to a return-void-barrier.
 */
static void rewriteReturnVoid(Method* method, u2* insns)
{
    assert((insns[0] & 0xff) == OP_RETURN_VOID);
    updateOpcode(method, insns, OP_RETURN_VOID_BARRIER);
}
