/*
 * Copyright (C) 2009 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.
 */

/*
 * Indirect reference table management.
 */
#include "Dalvik.h"

/*
 * Initialize an IndirectRefTable structure.
 */
bool dvmInitIndirectRefTable(IndirectRefTable* pRef, int initialCount,
    int maxCount, IndirectRefKind kind)
{
    assert(initialCount > 0);
    assert(initialCount <= maxCount);
    assert(kind == kIndirectKindLocal || kind == kIndirectKindGlobal);

    pRef->table = (Object**) malloc(initialCount * sizeof(Object*));
    if (pRef->table == NULL)
        return false;
#ifndef NDEBUG
    memset(pRef->table, 0xd1, initialCount * sizeof(Object*));
#endif

    pRef->slotData =
        (IndirectRefSlot*) calloc(maxCount, sizeof(IndirectRefSlot));
    if (pRef->slotData == NULL)
        return false;

    pRef->segmentState.all = IRT_FIRST_SEGMENT;
    pRef->allocEntries = initialCount;
    pRef->maxEntries = maxCount;
    pRef->kind = kind;

    return true;
}

/*
 * Clears out the contents of a IndirectRefTable, freeing allocated storage.
 */
void dvmClearIndirectRefTable(IndirectRefTable* pRef)
{
    free(pRef->table);
    pRef->table = NULL;
    pRef->allocEntries = pRef->maxEntries = -1;
}

/*
 * Remove one or more segments from the top.  The table entry identified
 * by "cookie" becomes the new top-most entry.
 *
 * Returns false if "cookie" is invalid or the table has only one segment.
 */
bool dvmPopIndirectRefTableSegmentCheck(IndirectRefTable* pRef, u4 cookie)
{
    IRTSegmentState sst;

    /*
     * The new value for "top" must be <= the current value.  Otherwise
     * this would represent an expansion of the table.
     */
    sst.all = cookie;
    if (sst.parts.topIndex > pRef->segmentState.parts.topIndex) {
        LOGE("Attempt to expand table with segment pop (%d to %d)\n",
            pRef->segmentState.parts.topIndex, sst.parts.topIndex);
        return false;
    }
    if (sst.parts.numHoles >= sst.parts.topIndex) {
        LOGE("Absurd numHoles in cookie (%d bi=%d)\n",
            sst.parts.numHoles, sst.parts.topIndex);
        return false;
    }

    LOGV("IRT %p[%d]: pop, top=%d holes=%d\n",
        pRef, pRef->kind, sst.parts.topIndex, sst.parts.numHoles);

    return true;
}

/*
 * Make sure that the entry at "idx" is correctly paired with "iref".
 */
static bool checkEntry(IndirectRefTable* pRef, IndirectRef iref, int idx)
{
    Object* obj = pRef->table[idx];
    IndirectRef checkRef = dvmObjectToIndirectRef(pRef, obj, idx, pRef->kind);
    if (checkRef != iref) {
        LOGW("IRT %p[%d]: iref mismatch (req=%p vs cur=%p)\n",
            pRef, pRef->kind, iref, checkRef);
        return false;
    }
    return true;
}

/*
 * Update extended debug info when an entry is added.
 *
 * We advance the serial number, invalidating any outstanding references to
 * this slot.
 */
static inline void updateSlotAdd(IndirectRefTable* pRef, Object* obj, int slot)
{
    if (pRef->slotData != NULL) {
        IndirectRefSlot* pSlot = &pRef->slotData[slot];
        pSlot->serial++;
        //LOGI("+++ add [%d] slot %d (%p->%p), serial=%d\n",
        //    pRef->kind, slot, obj, iref, pSlot->serial);
        pSlot->previous[pSlot->serial % kIRTPrevCount] = obj;
    }
}

/*
 * Update extended debug info when an entry is removed.
 */
static inline void updateSlotRemove(IndirectRefTable* pRef, int slot)
{
    if (pRef->slotData != NULL) {
        IndirectRefSlot* pSlot = &pRef->slotData[slot];
        //LOGI("+++ remove [%d] slot %d, serial now %d\n",
        //    pRef->kind, slot, pSlot->serial);
    }
}

/*
 * Add "obj" to "pRef".
 */
IndirectRef dvmAddToIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
    Object* obj)
{
    IRTSegmentState prevState;
    prevState.all = cookie;
    int topIndex = pRef->segmentState.parts.topIndex;
    int bottomIndex = prevState.parts.topIndex;

    assert(obj != NULL);
    assert(dvmIsValidObject(obj));
    assert(pRef->table != NULL);
    assert(pRef->allocEntries <= pRef->maxEntries);
    assert(pRef->segmentState.parts.numHoles >= prevState.parts.numHoles);

    if (topIndex == pRef->allocEntries) {
        /* reached end of allocated space; did we hit buffer max? */
        if (topIndex == pRef->maxEntries) {
            LOGW("IndirectRefTable overflow (max=%d)\n", pRef->maxEntries);
            return NULL;
        }

        Object** newTable;
        int newSize;

        newSize = pRef->allocEntries * 2;
        if (newSize > pRef->maxEntries)
            newSize = pRef->maxEntries;
        assert(newSize > pRef->allocEntries);

        newTable = (Object**) realloc(pRef->table, newSize * sizeof(Object*));
        if (newTable == NULL) {
            LOGE("Unable to expand iref table (from %d to %d, max=%d)\n",
                pRef->allocEntries, newSize, pRef->maxEntries);
            return false;
        }
        LOGI("Growing ireftab %p from %d to %d (max=%d)\n",
            pRef, pRef->allocEntries, newSize, pRef->maxEntries);

        /* update entries; adjust "nextEntry" in case memory moved */
        pRef->table = newTable;
        pRef->allocEntries = newSize;
    }

    IndirectRef result;

    /*
     * We know there's enough room in the table.  Now we just need to find
     * the right spot.  If there's a hole, find it and fill it; otherwise,
     * add to the end of the list.
     */
    int numHoles = pRef->segmentState.parts.numHoles - prevState.parts.numHoles;
    if (numHoles > 0) {
        assert(topIndex > 1);
        /* find the first hole; likely to be near the end of the list */
        Object** pScan = &pRef->table[topIndex - 1];
        assert(*pScan != NULL);
        while (*--pScan != NULL) {
            assert(pScan >= pRef->table + bottomIndex);
        }
        updateSlotAdd(pRef, obj, pScan - pRef->table);
        result = dvmObjectToIndirectRef(pRef, obj, pScan - pRef->table,
            pRef->kind);
        *pScan = obj;
        pRef->segmentState.parts.numHoles--;
    } else {
        /* add to the end */
        updateSlotAdd(pRef, obj, topIndex);
        result = dvmObjectToIndirectRef(pRef, obj, topIndex, pRef->kind);
        pRef->table[topIndex++] = obj;
        pRef->segmentState.parts.topIndex = topIndex;
    }

    assert(result != NULL);
    return result;
}

/*
 * Verify that the indirect table lookup is valid.
 *
 * Returns "false" if something looks bad.
 */
bool dvmGetFromIndirectRefTableCheck(IndirectRefTable* pRef, IndirectRef iref)
{
    if (dvmGetIndirectRefType(iref) == kIndirectKindInvalid) {
        LOGW("Invalid indirect reference 0x%08x\n", (u4) iref);
        return false;
    }

    int topIndex = pRef->segmentState.parts.topIndex;
    int idx = dvmIndirectRefToIndex(iref);

    if (iref == NULL) {
        LOGI("--- lookup on NULL iref\n");
        return false;
    }
    if (idx >= topIndex) {
        /* bad -- stale reference? */
        LOGI("Attempt to access invalid index %d (top=%d)\n",
            idx, topIndex);
        return false;
    }

    Object* obj = pRef->table[idx];
    if (obj == NULL) {
        LOGI("Attempt to read from hole, iref=%p\n", iref);
        return false;
    }
    if (!checkEntry(pRef, iref, idx))
        return false;

    return true;
}

/*
 * Remove "obj" from "pRef".  We extract the table offset bits from "iref"
 * and zap the corresponding entry, leaving a hole if it's not at the top.
 *
 * If the entry is not between the current top index and the bottom index
 * specified by the cookie, we don't remove anything.  This is the behavior
 * required by JNI's DeleteLocalRef function.
 *
 * Note this is NOT called when a local frame is popped.  This is only used
 * for explict single removals.
 *
 * Returns "false" if nothing was removed.
 */
bool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
    IndirectRef iref)
{
    IRTSegmentState prevState;
    prevState.all = cookie;
    int topIndex = pRef->segmentState.parts.topIndex;
    int bottomIndex = prevState.parts.topIndex;

    assert(pRef->table != NULL);
    assert(pRef->allocEntries <= pRef->maxEntries);
    assert(pRef->segmentState.parts.numHoles >= prevState.parts.numHoles);

    int idx = dvmIndirectRefToIndex(iref);
    if (idx < bottomIndex) {
        /* wrong segment */
        LOGV("Attempt to remove index outside index area (%d vs %d-%d)\n",
            idx, bottomIndex, topIndex);
        return false;
    }
    if (idx >= topIndex) {
        /* bad -- stale reference? */
        LOGI("Attempt to remove invalid index %d (bottom=%d top=%d)\n",
            idx, bottomIndex, topIndex);
        return false;
    }

    if (idx == topIndex-1) {
        /*
         * Top-most entry.  Scan up and consume holes.  No need to NULL
         * out the entry, since the test vs. topIndex will catch it.
         */
        if (!checkEntry(pRef, iref, idx))
            return false;
        updateSlotRemove(pRef, idx);

#ifndef NDEBUG
        pRef->table[idx] = (IndirectRef) 0xd3d3d3d3;
#endif

        int numHoles =
            pRef->segmentState.parts.numHoles - prevState.parts.numHoles;
        if (numHoles != 0) {
            while (--topIndex > bottomIndex && numHoles != 0) {
                LOGV("+++ checking for hole at %d (cookie=0x%08x) val=%p\n",
                    topIndex-1, cookie, pRef->table[topIndex-1]);
                if (pRef->table[topIndex-1] != NULL)
                    break;
                LOGV("+++ ate hole at %d\n", topIndex-1);
                numHoles--;
            }
            pRef->segmentState.parts.numHoles =
                numHoles + prevState.parts.numHoles;
            pRef->segmentState.parts.topIndex = topIndex;
        } else {
            pRef->segmentState.parts.topIndex = topIndex-1;
            LOGV("+++ ate last entry %d\n", topIndex-1);
        }
    } else {
        /*
         * Not the top-most entry.  This creates a hole.  We NULL out the
         * entry to prevent somebody from deleting it twice and screwing up
         * the hole count.
         */
        if (pRef->table[idx] == NULL) {
            LOGV("--- WEIRD: removing null entry %d\n", idx);
            return false;
        }
        if (!checkEntry(pRef, iref, idx))
            return false;
        updateSlotRemove(pRef, idx);

        pRef->table[idx] = NULL;
        pRef->segmentState.parts.numHoles++;
        LOGV("+++ left hole at %d, holes=%d\n",
            idx, pRef->segmentState.parts.numHoles);
    }

    return true;
}

/*
 * This is a qsort() callback.  We sort Object* by class, allocation size,
 * and then by the Object* itself.
 */
static int compareObject(const void* vobj1, const void* vobj2)
{
    Object* obj1 = *((Object**) vobj1);
    Object* obj2 = *((Object**) vobj2);

    /* ensure null references appear at the end */
    if (obj1 == NULL) {
        if (obj2 == NULL) {
            return 0;
        } else {
            return 1;
        }
    } else if (obj2 == NULL) {
        return -1;
    }

    if (obj1->clazz != obj2->clazz) {
        return (u1*)obj1->clazz - (u1*)obj2->clazz;
    } else {
        int size1 = dvmObjectSizeInHeap(obj1);
        int size2 = dvmObjectSizeInHeap(obj2);
        if (size1 != size2) {
            return size1 - size2;
        } else {
            return (u1*)obj1 - (u1*)obj2;
        }
    }
}

/*
 * Log an object with some additional info.
 *
 * Pass in the number of additional elements that are identical to or
 * equivalent to the original.
 */
static void logObject(Object* obj, int size, int identical, int equiv)
{
    if (obj == NULL) {
        LOGW("  NULL reference (count=%d)\n", equiv);
        return;
    }

    if (identical + equiv != 0) {
        LOGW("%5d of %s %dB (%d unique)\n", identical + equiv +1,
            obj->clazz->descriptor, size, equiv +1);
    } else {
        LOGW("%5d of %s %dB\n", identical + equiv +1,
            obj->clazz->descriptor, size);
    }
}

/*
 * Dump the contents of a IndirectRefTable to the log.
 */
void dvmDumpIndirectRefTable(const IndirectRefTable* pRef, const char* descr)
{
    const int kLast = 10;
    int count = dvmIndirectRefTableEntries(pRef);
    Object** refs;
    int i;

    if (count == 0) {
        LOGW("Reference table has no entries\n");
        return;
    }
    assert(count > 0);

    /*
     * Dump the most recent N entries.  If there are holes, we will show
     * fewer than N.
     */
    LOGW("Last %d entries in %s reference table:\n", kLast, descr);
    refs = pRef->table;         // use unsorted list
    int size;
    int start = count - kLast;
    if (start < 0)
        start = 0;

    for (i = start; i < count; i++) {
        if (refs[i] == NULL)
            continue;
        size = dvmObjectSizeInHeap(refs[i]);
        Object* ref = refs[i];
        if (ref->clazz == gDvm.classJavaLangClass) {
            ClassObject* clazz = (ClassObject*) ref;
            LOGW("%5d: %p cls=%s '%s' (%d bytes)\n", i, ref,
                (refs[i] == NULL) ? "-" : ref->clazz->descriptor,
                clazz->descriptor, size);
        } else {
            LOGW("%5d: %p cls=%s (%d bytes)\n", i, ref,
                (refs[i] == NULL) ? "-" : ref->clazz->descriptor, size);
        }
    }

    /*
     * Make a copy of the table, and sort it.
     *
     * The NULL "holes" wind up at the end, so we can strip them off easily.
     */
    Object** tableCopy = (Object**)malloc(sizeof(Object*) * count);
    memcpy(tableCopy, pRef->table, sizeof(Object*) * count);
    qsort(tableCopy, count, sizeof(Object*), compareObject);
    refs = tableCopy;       // use sorted list

    if (false) {
        int q;
        for (q = 0; q < count; q++)
            LOGI("%d %p\n", q, refs[q]);
    }

    int holes = 0;
    while (refs[count-1] == NULL) {
        count--;
        holes++;
    }

    /*
     * Dump uniquified table summary.  While we're at it, generate a
     * cumulative total amount of pinned memory based on the unique entries.
     */
    LOGW("%s reference table summary (%d entries / %d holes):\n",
        descr, count, holes);
    int equiv, identical, total;
    total = equiv = identical = 0;
    for (i = 1; i < count; i++) {
        size = dvmObjectSizeInHeap(refs[i-1]);

        if (refs[i] == refs[i-1]) {
            /* same reference, added more than once */
            identical++;
        } else if (refs[i]->clazz == refs[i-1]->clazz &&
            (int) dvmObjectSizeInHeap(refs[i]) == size)
        {
            /* same class / size, different object */
            total += size;
            equiv++;
        } else {
            /* different class */
            total += size;
            logObject(refs[i-1], size, identical, equiv);
            equiv = identical = 0;
        }
    }

    /* handle the last entry (everything above outputs refs[i-1]) */
    size = (refs[count-1] == NULL) ? 0 : dvmObjectSizeInHeap(refs[count-1]);
    total += size;
    logObject(refs[count-1], size, identical, equiv);

    LOGW("Memory held directly by native code is %d bytes\n", total);
    free(tableCopy);
}

