📄 class.c
字号:
int depth = 1; for (;;) { if (!IS_ARRAY_CLASS(subClass)) { /* subClass is a base type */ return getArrayClass(depth, (INSTANCE_CLASS)subClass, '\0'); } else if (((ARRAY_CLASS)subClass)->gcType == GCT_ARRAY) { /* subClass is an array of primitives of depth 1. */ int typeCode = ((ARRAY_CLASS)subClass)->u.primType; char signCode = typeCodeToSignature((char)typeCode); return getArrayClass(depth + 1, NULL, signCode); } else { /* iterate down one level */ subClass = ((ARRAY_CLASS)subClass)->u.elemClass; depth++; } }}/*========================================================================= * FUNCTION: getClassName, getClassName_inBuffer * TYPE: public instance-level operation on runtime classes * OVERVIEW: Gets the name of a class * * INTERFACE: * parameters: clazz: Any class * str_buffer: Where to put the result * * returns: getClassName() returns a pointer to the result * getClassName_inBuffer() returns a pointer to the NULL * at the end of the result. The result is in the * passed buffer. * * DANGER: getClassName_inBuffer() does not return what you expect. *=======================================================================*/char *getClassName(CLASS clazz) { UString UPackageName = clazz->packageName; UString UBaseName = clazz->baseName; int baseLength = UBaseName->length; int packageLength = UPackageName == 0 ? 0 : UPackageName->length; char *result = mallocBytes(baseLength + packageLength + 5); getClassName_inBuffer(clazz, result); return result;}char* /* returns pointer to '\0' at end of resultBuffer */getClassName_inBuffer(CLASS clazz, char *resultBuffer) { UString UPackageName = clazz->packageName; UString UBaseName = clazz->baseName; char *baseName = UStringInfo(UBaseName); char *from = baseName; /* pointer into baseName */ char *to = resultBuffer; /* used for creating the output */ int fromLength = UBaseName->length; bool_t isArrayOfObject; /* The result should have exactly as many "["s as the baseName has at * its beginning. Then skip over that part in both the input and the * output */ for (from = baseName; *from == '['; from++, fromLength--) { *to++ = '['; } /* We're an array of objects if we've actually written something already * to "from", and more than one character remains */ isArrayOfObject = (from != baseName && fromLength != 1); if (isArrayOfObject) { *to++ = 'L'; } /* Now print out the package name, followed by the rest of the baseName */ if (UPackageName != NULL) { int packageLength = UPackageName->length; memcpy(to, UStringInfo(UPackageName), packageLength); to += packageLength; *to++ = '/'; } if (isArrayOfObject) { memcpy(to, from + 1, fromLength - 2); /* skip L and ; */ to += (fromLength - 2); *to++ = ';'; } else { memcpy(to, from, fromLength); to += fromLength; } *to = '\0'; return to;}/*========================================================================= * FUNCTION: printClassName() * TYPE: public instance-level operation * OVERVIEW: Print the name of a class * for debugging purposes. * INTERFACE: * parameters: class pointer * returns: <nothing> *=======================================================================*/#if INCLUDEDEBUGCODEvoid printClassName(CLASS thisClass){ /* This shouldn't allocate memory. */ char buffer[256]; getClassName_inBuffer(thisClass, buffer); fprintf(stdout, "Class '%s'\n", buffer);}#endif /* INCLUDEDEBUGCODE *//*========================================================================= * Type conversion helper functions *=======================================================================*//*========================================================================= * FUNCTION: typeCodeToSignature, signatureToTypeCode * TYPE: private function * OVERVIEW: Converts signature characters to the corresponding * type code small integer, and back. *=======================================================================*/chartypeCodeToSignature(char typeCode) { switch(typeCode) { case T_CHAR : return 'C'; case T_BYTE : return 'B'; case T_BOOLEAN : return 'Z'; case T_FLOAT : return 'F'; case T_DOUBLE : return 'D'; case T_SHORT : return 'S'; case T_INT : return 'I'; case T_LONG : return 'J'; case T_VOID: return 'V'; case T_CLASS: return 'L'; default : fatalVMError(KVM_MSG_BAD_SIGNATURE); return 0; }}/*========================================================================= * Operations on instances *=======================================================================*//*========================================================================= * FUNCTION: instantiate() * TYPE: constructor * OVERVIEW: Create an instance of the given class. * INTERFACE: * parameters: class pointer * returns: pointer to object instance * * NOTE: This operation only allocates the space for the * instance and initializes its instance variables to zero. * Actual constructor for initializing the variables * must be invoked separately. *=======================================================================*/INSTANCE instantiate(INSTANCE_CLASS thisClass){ long size = SIZEOF_INSTANCE(thisClass->instSize); INSTANCE newInstance = (INSTANCE)mallocHeapObject(size, GCT_INSTANCE); if (newInstance != NULL) { memset(newInstance, 0, size << log2CELL); /* initialize the class pointer (zeroeth field in the instance) */ newInstance->ofClass = thisClass; } else { throwException(&OutOfMemoryObject); } return newInstance;}/*========================================================================= * FUNCTION: objectHashCode() * TYPE: public function * OVERVIEW: Return the identity of the object. * INTERFACE: * parameters: object pointer * returns: object identity as long * * NOTE: This operation needs to take into account that * objects can move. Therefore, we can't simply use * the address of the object as identity. *=======================================================================*/long objectHashCode(OBJECT object){ unsigned static long lastHash = 0xCAFEBABE; /* The following may GC, but only if the result it returns is non-NULL */ long* hashAddress = monitorHashCodeAddress(object); long result = (hashAddress == NULL) ? object->mhc.hashCode : *hashAddress; if (result == 0) { do { lastHash = lastHash * 0xDEECE66DL + 0xB; result = lastHash & ~03; } while (result == 0); if (hashAddress == NULL) { SET_OBJECT_HASHCODE(object, result); } else { *hashAddress = result; } } return result >> 2;}/*========================================================================= * FUNCTION: implementsInterface() * TYPE: public instance-level operation on runtime objects * OVERVIEW: Check if the given class implements the given * interface. * INTERFACE: * parameters: thisClass: class * interface: the interface to implement * returns: boolean *=======================================================================*/bool_timplementsInterface(INSTANCE_CLASS thisClass, INSTANCE_CLASS thisInterface){ unsigned short *ifaceTable; if (thisClass == thisInterface) { return TRUE; } if (!IS_ARRAY_CLASS(thisClass) && (((INSTANCE_CLASS)thisClass)->status == CLASS_RAW)){ loadClassfile((INSTANCE_CLASS)thisClass, TRUE); } for (;;) { ifaceTable = thisClass->ifaceTable; if (ifaceTable != NULL) { int tableLength = ifaceTable[0]; int i; for (i = 1; i <= tableLength; i++) { INSTANCE_CLASS ifaceClass = (INSTANCE_CLASS)resolveClassReference(thisClass->constPool, ifaceTable[i], thisClass); if (implementsInterface(ifaceClass, thisInterface)) { return TRUE; } } } if (thisClass == JavaLangObject) { return FALSE; } thisClass = thisClass->superClass; }}/*========================================================================= * FUNCTION: isAssignableTo() * TYPE: public instance-level operation * OVERVIEW: Check if the class 'fromClass' can be assigned * to a variable of type 'toClass'. * INTERFACE: * parameters: fromClass, toClass: class pointers * returns: true if is assignable, false otherwise * * NOTE: This code now implements all the hairy checks * required by Java Language Specification. *=======================================================================*/bool_tisAssignableTo(CLASS fromClass, CLASS toClass) { for (;;) { /* You might be wondering how fromClass could ever be an interface, * since objects of never of type "fromClass". This can only happen * on the second or subsequent iteration through the loop, when * fromClass was originally of type someInterface[] */ if ((fromClass == toClass) || (toClass == (CLASS)JavaLangObject)) { return TRUE; } if (IS_ARRAY_CLASS(toClass)) { loadArrayClass((ARRAY_CLASS)toClass); } else { if (((INSTANCE_CLASS)toClass)->status == CLASS_RAW) { loadClassfile((INSTANCE_CLASS)toClass, TRUE); } } if (IS_ARRAY_CLASS(toClass)) { /* Only a compatible array can be assigned to an array */ if (!IS_ARRAY_CLASS(fromClass)) { /* a non-array class can't be a subclass of an array class */ return FALSE; } else { /* assigning an array to an array */ int fromType = ((ARRAY_CLASS)fromClass)->gcType; int toType = ((ARRAY_CLASS)toClass)->gcType; /* fromType, toType are either GCT_OBJECTARRAY or GCT_ARRAY */ if (toType != fromType) { /* An array of primitives, and an array of non-primitives */ return FALSE; } else if (toType == GCT_ARRAY) { /* Two arrays of primitive types */ return ((ARRAY_CLASS)fromClass)->u.primType == ((ARRAY_CLASS)toClass)->u.primType; } else { /* Two object array types. Look at there element * types and recurse. */ fromClass = ((ARRAY_CLASS)fromClass)->u.elemClass; toClass = ((ARRAY_CLASS)toClass)->u.elemClass; continue; } } } else if ((toClass->accessFlags & ACC_INTERFACE) != 0) { /* Assigning to an interface. fromClass must be a non-array that * implements the interface. * NB: If we ever have Cloneable or Serializable, we must fix * this, since arrays do implement those. */ return (!(IS_ARRAY_CLASS(fromClass)) && implementsInterface((INSTANCE_CLASS)fromClass, (INSTANCE_CLASS)toClass)); } else { /* Assigning to a non-array, non-interface, honest-to-god class, * that's not java.lang.Object */ if (IS_ARRAY_CLASS(fromClass) || ((fromClass->accessFlags & ACC_INTERFACE) != 0)) { /* arrays and interfaces can only be assigned to * java.lang.Object. We already know that's it's not */ return FALSE; } else { /* fromClass is also a non-array, non-interface class. We * need to check to see if fromClass is a subclass of toClass. * We've know fromClass != toClass from the shortcut test * way above */ INSTANCE_CLASS fromIClass = (INSTANCE_CLASS)fromClass; INSTANCE_CLASS toIClass = (INSTANCE_CLASS)toClass; while (fromIClass != JavaLangObject) { if (!IS_ARRAY_CLASS(fromIClass) && (((INSTANCE_CLASS)fromIClass)->status == CLASS_RAW)){ loadClassfile((INSTANCE_CLASS)fromIClass, TRUE); } fromIClass = fromIClass->superClass; if (fromIClass == toIClass) { return TRUE; } } return FALSE; } } }} /*========================================================================= * FUNCTION: isAssignableToFast() * TYPE: public instance-level operation * OVERVIEW: Does a fast, non-GCing check to see if fromClass is * assignable to toClass. TRUE means yes. FALSE means * don't know. * INTERFACE: * parameters: fromClass, toClass: class pointers * returns: true if is assignable, false if uncertain * * THIS FUNCTION IS GUARANTEED NOT TO GARBAGE COLLECT *=======================================================================*/bool_tisAssignableToFast(CLASS fromClass, CLASS toClass) { if ((fromClass == toClass) || (toClass == (CLASS)JavaLangObject)) { return TRUE; } else if (IS_ARRAY_CLASS(fromClass) || IS_ARRAY_CLASS(toClass)) { /* We don't want to waste our time on these. Just say "don't know" */ return FALSE; } else { INSTANCE_CLASS fromIClass = (INSTANCE_CLASS)fromClass; INSTANCE_CLASS toIClass = (INSTANCE_CLASS)toClass; while (fromIClass != JavaLangObject) { if (fromIClass->status == CLASS_RAW) { /* Can't get more information without GC'ing. */ return FALSE; } fromIClass = fromIClass->superClass; if (fromIClass == toIClass) { return TRUE; } } return FALSE; }}/*========================================================================= * FUNCTION: printInstance() * TYPE: public instance-level operation * OVERVIEW: Print the contents of an object instance * for debugging purposes. * INTERFACE: * parameters: instance pointer * returns: <nothing> *=======================================================================*/#if INCLUDEDEBUGCODEvoid printInstance(INSTANCE thisInstance){ INSTANCE_CLASS thisClass = thisInstance->ofClass; int instSize = thisClass->instSize; int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -