Exemple #1
0
/*
 * 在'clazz'中,我们有一个方法指向另一个方法,但它可能指向派生类中的一个方法,我们想要从虚拟函数表中找到实际入口,如果'class'是一个接口,我们不得不在短时间内做更多的挖掘
 *
 * 对于'direct'方法(private / constructor).我们仅仅返回原生态方法
 *  
 * (这里被适用于反射和JNI调用)
 */
const Method* dvmGetVirtualizedMethod(const ClassObject* clazz,
    const Method* meth)
{
    Method* actualMeth;
    int methodIndex;

    if (dvmIsDirectMethod(meth)) {
        /* no vtable entry for these */
        assert(!dvmIsStaticMethod(meth));
        return meth;
    }

    /*
     * If the method was declared in an interface, we need to scan through
     * the class' list of interfaces for it, and find the vtable index
     * from that.
     *
     * TODO: use the interface cache.
     */
    if (dvmIsInterfaceClass(meth->clazz)) {
        int i;

        for (i = 0; i < clazz->iftableCount; i++) {
            if (clazz->iftable[i].clazz == meth->clazz)
                break;
        }
        if (i == clazz->iftableCount) {
            dvmThrowIncompatibleClassChangeError(
                "invoking method from interface not implemented by class");
            return NULL;
        }

        methodIndex = clazz->iftable[i].methodIndexArray[meth->methodIndex];
    } else {
        methodIndex = meth->methodIndex;
    }

    assert(methodIndex >= 0 && methodIndex < clazz->vtableCount);
    actualMeth = clazz->vtable[methodIndex];

    /*
     * Make sure there's code to execute.
     */
    if (dvmIsAbstractMethod(actualMeth)) {
        dvmThrowAbstractMethodError(NULL);
        return NULL;
    }
    assert(!dvmIsMirandaMethod(actualMeth));

    return actualMeth;
}
/*
 * Convert a method pointer to a slot number.
 *
 * We use positive values starting from 0 for virtual methods, negative
 * values starting from -1 for static methods.
 */
static int methodToSlot(const Method* meth)
{
    ClassObject* clazz = meth->clazz;
    int slot;

    if (dvmIsDirectMethod(meth)) {
        slot = meth - clazz->directMethods;
        assert(slot >= 0 && slot < clazz->directMethodCount);
        slot = -(slot+1);
    } else {
        slot = meth - clazz->virtualMethods;
        assert(slot >= 0 && slot < clazz->virtualMethodCount);
    }

    return slot;
}