⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 已经移植好的java虚拟机
💻 C
📖 第 1 页 / 共 5 页
字号:
            }        }    END_TEMPORARY_ROOTS    return bytesRead;}/*========================================================================= * FUNCTION:      loadMethodAttributes() * TYPE:          private class file load operation * OVERVIEW:      Load the "Code" and "Exceptions" attributes *                of a method in a class file, ignoring all the  *                other possible method attributes. * INTERFACE: *   parameters:  classfile pointer, constant pool pointer,  *                method attribute count, pointer to the runtime method struct *   returns:     <nothing> *=======================================================================*/static unsigned int loadCodeAttribute(FILEPOINTER_HANDLE ClassFileH,                   METHOD_HANDLE thisMethodH,                   POINTERLIST_HANDLE StringPoolH){     unsigned int actualAttrLength;    unsigned int codeLength;    int nCodeAttrs;    int codeAttrIndex;    BYTE *code;    bool_t needStackMap = TRUE;    METHOD thisMethod = unhand(thisMethodH);    /*  Create a code object and store it in the method */    thisMethod->u.java.maxStack    = loadShort(ClassFileH); /*  max stack */    thisMethod->frameSize   = loadShort(ClassFileH); /*  frame size */    codeLength              = loadCell(ClassFileH);  /*  Code length */    if (codeLength >= 0x7FFF) {        fatalError(KVM_MSG_METHOD_LONGER_THAN_32KB);    }    if (thisMethod->u.java.maxStack + thisMethod->frameSize >                MAXIMUM_STACK_AND_LOCALS) {         fatalError(KVM_MSG_TOO_MANY_LOCALS_AND_STACK);    }                /*  Allocate memory for storing the bytecode array */    if (USESTATIC && !ENABLEFASTBYTECODES) {         code = (BYTE *)mallocBytes(codeLength);    } else {         code = (BYTE *)callocPermanentObject(ByteSizeToCellSize(codeLength));    }     thisMethod = unhand(thisMethodH);     thisMethod->u.java.code = code;    thisMethod->u.java.codeLength = codeLength;    loadBytes(ClassFileH, (char *)thisMethod->u.java.code, codeLength);    actualAttrLength = 2 + 2 + 4 + codeLength;        /*  Load exception handlers associated with the method */    actualAttrLength += loadExceptionHandlers(ClassFileH, thisMethodH);        nCodeAttrs = loadShort(ClassFileH);    actualAttrLength += 2;    for (codeAttrIndex = 0; codeAttrIndex < nCodeAttrs; codeAttrIndex++) {        unsigned short codeAttrNameIndex = loadShort(ClassFileH);        unsigned int   codeAttrLength    = loadCell(ClassFileH);        char* codeAttrName = getUTF8String(StringPoolH, codeAttrNameIndex);        /*  Check if the attribute contains stack maps */        if (!strcmp(codeAttrName, "StackMap")) {            unsigned int stackMapAttrSize;            if (!needStackMap) {                 fatalError(KVM_MSG_DUPLICATE_STACKMAP_ATTRIBUTE);            }             needStackMap = FALSE;            stackMapAttrSize = loadStackMaps(ClassFileH, thisMethodH);            if (stackMapAttrSize != codeAttrLength) {                 fatalError(KVM_MSG_BAD_ATTRIBUTE_SIZE);            }        } else {            skipBytes(ClassFileH, codeAttrLength);        }        actualAttrLength += 6 + codeAttrLength;    }    return actualAttrLength;}static void loadMethodAttributes(FILEPOINTER_HANDLE ClassFileH,                      METHOD_HANDLE thisMethodH,                      POINTERLIST_HANDLE StringPoolH){    unsigned short attrCount = loadShort(ClassFileH);    METHOD thisMethod = unhand(thisMethodH);    int attrIndex;    bool_t needCode = !(thisMethod->accessFlags & (ACC_NATIVE | ACC_ABSTRACT));    bool_t needExceptionTable = TRUE;  /* always optional */    /*  See if the field has any attributes in the class file */    for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {        unsigned short attrNameIndex = loadShort(ClassFileH);        unsigned int   attrLength    = loadCell(ClassFileH);        char*          attrName      = getUTF8String(StringPoolH, attrNameIndex);        /*  Check if the attribute contains source code */        if (strcmp(attrName, "Code") == 0) {             unsigned int actualLength;            if (!needCode) {                 fatalError(KVM_MSG_DUPLICATE_CODE_ATTRIBUTE);            }             actualLength = loadCodeAttribute(ClassFileH, thisMethodH, StringPoolH);            if (actualLength != attrLength) {                 fatalError(KVM_MSG_BAD_CODE_ATTRIBUTE_LENGTH);            }            needCode = FALSE;        } else if (!strcmp(attrName, "Exceptions")) {             /* Do minimal checking of this attribute. */            unsigned int exceptionCount;            unsigned int i;            if (!needExceptionTable) {                 fatalError(KVM_MSG_DUPLICATE_EXCEPTION_TABLE);            }             needExceptionTable = FALSE;            exceptionCount = loadShort(ClassFileH);            if (2 * exceptionCount + 2 != attrLength) {                 fatalError(KVM_MSG_BAD_EXCEPTION_ATTRIBUTE);            }             for (i = 0; i < exceptionCount; i++) {                 unsigned short exception = loadShort(ClassFileH);                if (exception != 0) {                    verifyConstantPoolEntry(unhand(thisMethodH)->ofClass,                                            exception, CONSTANT_Class);                }            }        } else {            /*  Unrecognized attribute; skip */            skipBytes(ClassFileH, attrLength);        }    }    if (needCode) {         fatalError(KVM_MSG_MISSING_CODE_ATTRIBUTE);    }}/*========================================================================= * FUNCTION:      loadMethods() * TYPE:          private class file load operation * OVERVIEW:      Load the methods defined in a Java class file. * INTERFACE: *   parameters:  classfile pointer, current class pointer *   returns:     <nothing> *=======================================================================*/static voidloadOneMethod(FILEPOINTER_HANDLE ClassFileH, INSTANCE_CLASS CurrentClass,               METHOD_HANDLE thisMethodH, POINTERLIST_HANDLE StringPoolH) {    METHOD thisMethod;    unsigned short accessFlags =         loadShort(ClassFileH) & RECOGNIZED_METHOD_FLAGS;    unsigned short nameIndex   = loadShort(ClassFileH);    unsigned short typeIndex   = loadShort(ClassFileH);    START_TEMPORARY_ROOTS        DECLARE_TEMPORARY_ROOT(const char *, methodName,                                getUTF8String(StringPoolH, nameIndex));        DECLARE_TEMPORARY_ROOT(const char *, signature,                                getUTF8String(StringPoolH, typeIndex));        NameTypeKey result;        if (strcmp(methodName, "<clinit>") == 0) {            accessFlags = ACC_STATIC;        } else {            verifyMethodFlags(accessFlags,                               CurrentClass->clazz.accessFlags,                               methodName);        }        verifyName(methodName, LegalMethod, TRUE);            result.nt.nameKey =             change_Name_to_Key(&methodName, 0, strlen(methodName));        result.nt.typeKey =             change_MethodSignature_to_Key(&signature, 0, strlen(signature));        ASSERTING_NO_ALLOCATION            thisMethod = unhand(thisMethodH);            thisMethod->nameTypeKey = result;            thisMethod->argCount = verifyMethodType(methodName, signature);            /*  If this is a virtual method, increment argument counter */            if (!(accessFlags & ACC_STATIC)) {                 thisMethod->argCount++;            }            if (thisMethod->argCount > 255) {                fatalError(KVM_MSG_TOO_MANY_METHOD_ARGUMENTS);            }#if INCLUDEDEBUGCODE            if (traceclassloadingverbose) {                 fprintf(stdout, "Method '%s' loaded\n", methodName);            }#endif /* INCLUDEDEBUGCODE */            /* Check if the field is double length, or is a pointer type.  If so             * set the appropriate bit in the word */            switch (strchr(signature, ')')[1]) {                 case 'D': case 'J':   accessFlags |= ACC_DOUBLE;   break;                case 'L': case '[':   accessFlags |= ACC_POINTER;  break;                case 'V':   accessFlags |= (ACC_POINTER | ACC_DOUBLE);  break;            }            thisMethod->accessFlags = accessFlags;            thisMethod->ofClass     = CurrentClass;            /* These values will be initialized later */            thisMethod->frameSize   = 0;            thisMethod->u.java.maxStack    = 0;            thisMethod->u.java.handlers = NIL;        END_ASSERTING_NO_ALLOCATION        loadMethodAttributes(ClassFileH, thisMethodH, StringPoolH);        /* Garbage collection may have happened */        thisMethod = unhand(thisMethodH);        if (!(thisMethod->accessFlags & (ACC_NATIVE | ACC_ABSTRACT))) {            if ( thisMethod->frameSize < thisMethod->argCount) {                fatalError(KVM_MSG_BAD_FRAME_SIZE);            }        }        if (accessFlags & ACC_NATIVE) {            /*  Store native function pointer in the code field */            thisMethod->u.native.info = NULL;            thisMethod->u.native.code =                 getNativeFunction(CurrentClass, methodName, signature);        }    END_TEMPORARY_ROOTS}            static void loadMethods(FILEPOINTER_HANDLE ClassFileH, INSTANCE_CLASS CurrentClass,             POINTERLIST_HANDLE StringPoolH){    unsigned short methodCount = loadShort(ClassFileH);    if (methodCount == 0) {         return;    }     START_TEMPORARY_ROOTS        int tableSize = SIZEOF_METHODTABLE(methodCount);        unsigned int index;#if USESTATIC        DECLARE_TEMPORARY_ROOT(METHODTABLE, methodTable,             (METHODTABLE)callocObject(tableSize, GCT_METHODTABLE));#else        METHODTABLE methodTable = (METHODTABLE)callocPermanentObject(tableSize);#endif        methodTable->length = methodCount;        CurrentClass->methodTable = methodTable;#if INCLUDEDEBUGCODE        if (traceclassloadingverbose) {             fprintf(stdout, "Loading methods\n");        }#endif /* INCLUDEDEBUGCODE */        for (index = 0; index < methodCount; index++) { #if USESTATIC            START_TEMPORARY_ROOTS                DECLARE_TEMPORARY_METHOD_ROOT(thisMethod, methodTable, index);                loadOneMethod(ClassFileH, CurrentClass, &thisMethod, StringPoolH);            END_TEMPORARY_ROOTS#else             METHOD thisMethod = &methodTable->methods[index];            loadOneMethod(ClassFileH, CurrentClass, &thisMethod, StringPoolH);#endif        }    END_TEMPORARY_ROOTS    if (methodCount >= 2) {         /* Check to see if there are two methods with the same name/type */        METHODTABLE methodTable = CurrentClass->methodTable;        METHOD firstMethod = &methodTable->methods[0];        METHOD lastMethod = firstMethod + (methodCount - 1);        METHOD outer, inner;        for (outer = firstMethod; outer < lastMethod; outer++) {             for (inner = outer + 1; inner <= lastMethod; inner++) {                 if (outer->nameTypeKey.i == inner->nameTypeKey.i) {                     fatalError(KVM_MSG_DUPLICATE_METHOD_FOUND);                }            }        }    }#if INCLUDEDEBUGCODE    if (traceclassloadingverbose) {        fprintf(stdout, "Methods loaded ok\n");    }#endif /* INCLUDEDEBUGCODE */}/*========================================================================= * FUNCTION:      ignoreAttributes() * TYPE:          private class file load operation * OVERVIEW:      Load the possible extra attributes (e.g., the  *                "SourceFile" attribute) supplied in a Java class file. *                The current implementation ignores all these attributes. * INTERFACE: *   parameters:  classfile pointer, current class pointer *   returns:     <nothing> *=======================================================================*/static void ignoreAttributes(FILEPOINTER_HANDLE ClassFileH, POINTERLIST_HANDLE StringPoolH){    unsigned short attrCount = loadShort(ClassFileH);    int attrIndex;   #if INCLUDEDEBUGCODE    if (traceclassloadingverbose) {         fprintf(stdout, "Loading extra attributes\n");    }#endif /* INCLUDEDEBUGCODE */    for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {        unsigned short attrNameIndex = loadShort(ClassFileH);        unsigned int   attrLength = loadCell(ClassFileH);        /* This verifies that the attribute index is legitimate */        (void)getUTF8String(StringPoolH, attrNameIndex);        skipBytes(ClassFileH, attrLength);    }#if INCLUDEDEBUGCODE    if (traceclassloadingverbose)         fprintf(stdout, "Extra attributes loaded\n");#endif /* INCLUDEDEBUGCODE */}/*===================================================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -