📄 fields.c
字号:
/* * Copyright (c) 1998-2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * * Use is subject to license terms. *//*========================================================================= * SYSTEM: KVM * SUBSYSTEM: Internal runtime structures * FILE: fields.c * OVERVIEW: Internal runtime structures for storing different kinds * of fields (constants, variables, methods, interfaces). * Tables of these fields are created every time a new class * is loaded into the virtual machine. * AUTHOR: Antero Taivalsaari, Sun Labs * Edited by Doug Simon 11/1998 * Sheng Liang, Frank Yellin *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include "global.h"/*========================================================================= * Static variables and definitions (specific to this file) *=======================================================================*/static void change_Key_to_MethodSignatureInternal(unsigned char**, char**);static void change_MethodSignature_to_KeyInternal(CONST_CHAR_HANDLE, int *offsetP, unsigned char **to);/*========================================================================= * Operations on field and method tables *=======================================================================*//*========================================================================= * FUNCTION: lookupField() * TYPE: public instance-level operation * OVERVIEW: Find a field table entry with the given field name. * INTERFACE: * parameters: class pointer, field name pointer * returns: pointer to the field or NIL *=======================================================================*/FIELD lookupField(INSTANCE_CLASS thisClass, NameTypeKey key) { do { FIELDTABLE fieldTable = thisClass->fieldTable; /* Get the length of the field table */ FOR_EACH_FIELD(thisField, fieldTable) if (thisField->nameTypeKey.i == key.i) { return thisField; } END_FOR_EACH_FIELD thisClass = thisClass->superClass; } while (thisClass != NULL); return NULL;}/*========================================================================= * FUNCTION: lookupMethod() * TYPE: public instance-level operation * OVERVIEW: Find a method table entry with the given name and type * using a simple linear lookup strategy. * INTERFACE: * parameters: class pointer, method name and signature pointers * returns: pointer to the method or NIL * * NOTES: This is a naive implementation with linear search. * In most cases this does not matter, however, since * inline caching (turning ENABLEFASTBYTECODES on) * allows us to avoid the method lookup overhead. *=======================================================================*/METHOD lookupMethod(CLASS thisClass, NameTypeKey key, INSTANCE_CLASS currentClass){ INSTANCE_CLASS thisInstanceClass = IS_ARRAY_CLASS(thisClass) ? JavaLangObject : (INSTANCE_CLASS)thisClass; do { METHODTABLE methodTable = thisInstanceClass->methodTable; FOR_EACH_METHOD(thisMethod, methodTable) if (thisMethod->nameTypeKey.i == key.i) { if ( currentClass == NULL || currentClass == thisInstanceClass || ((ACC_PUBLIC|ACC_PROTECTED) & thisMethod->accessFlags) || ( ((thisMethod->accessFlags & ACC_PRIVATE) == 0) && thisInstanceClass->clazz.packageName == currentClass->clazz.packageName) ) { return thisMethod; } } END_FOR_EACH_METHOD /* If the class has a superclass, look its methods as well */ thisInstanceClass = thisInstanceClass->superClass; } while (thisInstanceClass != NULL); /* Before we give up on an interface class, check any interfaces that * it implements */ if ((thisClass->accessFlags & ACC_INTERFACE) && (((INSTANCE_CLASS)thisClass)->ifaceTable != NULL)) { CONSTANTPOOL constantPool = ((INSTANCE_CLASS)thisClass)->constPool; unsigned short *ifaceTable = ((INSTANCE_CLASS)thisClass)->ifaceTable; int tableLength = ifaceTable[0]; int i; for (i = 1; i <= tableLength; i++) { int cpIndex = ifaceTable[i]; CLASS intf = constantPool->entries[cpIndex].clazz; METHOD temp = lookupMethod(intf, key, currentClass); if (temp != NULL) { return temp; } } } return NULL;}/* Return true if thisClass or some superclass of it is in the indicated * package and has a public declaration of the method */static bool_t has_public_declaration(INSTANCE_CLASS thisClass, UString packageName, NameTypeKey key) { for( ; thisClass != NULL; thisClass = thisClass->superClass) { if (thisClass->clazz.packageName == packageName) { METHODTABLE methodTable = thisClass->methodTable; FOR_EACH_METHOD(thisMethod, methodTable) if ((thisMethod->nameTypeKey.i == key.i) && ((thisMethod->accessFlags & ACC_STATIC) == 0) && ((thisMethod->accessFlags & (ACC_PUBLIC|ACC_PROTECTED)))) { return TRUE; } END_FOR_EACH_METHOD } } return FALSE;}/*========================================================================= * FUNCTION: lookupDynamicMethod() * TYPE: public instance-level operation * OVERVIEW: Find a method table entry with the given name. * INTERFACE: * parameters: class pointer, and declared method name * returns: pointer to the method or NIL * * NOTES: This function is called by invokevirtual only. * It can make at most two passes through the superClass * hierarchy. If a method match is found, but it is in * a different package, it will call the helper function, * has_public_declaration. This helper function will also * traverse through the class hierarchy to determine if * this class or some superclass of it is in the indicated * package, and has a public declaration of it. * A boolean, guaranteed_not_public, is used to ensure that * has_public_declaration is only called once. *=======================================================================*/METHOD lookupDynamicMethod(CLASS thisClass, METHOD declaredMethod) { NameTypeKey key = declaredMethod->nameTypeKey; INSTANCE_CLASS currentClass = declaredMethod->ofClass; INSTANCE_CLASS thisInstanceClass = IS_ARRAY_CLASS(thisClass) ? JavaLangObject : (INSTANCE_CLASS)thisClass; bool_t guaranteed_not_public = FALSE; bool_t accept_any = (declaredMethod->accessFlags & (ACC_PUBLIC | ACC_PROTECTED)) != 0; if ((declaredMethod->accessFlags & ACC_PRIVATE) != 0) { /* invokevirtual of a private method always return that method */ return declaredMethod; } do { METHODTABLE methodTable = thisInstanceClass->methodTable; FOR_EACH_METHOD(thisMethod, methodTable) if ((thisMethod->nameTypeKey.i == key.i) && ((thisMethod->accessFlags & ACC_STATIC) == 0)) { /* static methods are in a completely different namespace * and are therefore ignored */ if (currentClass == thisInstanceClass) { return thisMethod; } if ((thisMethod->accessFlags & ACC_PRIVATE) == 0) { if (accept_any || (thisInstanceClass->clazz.packageName == currentClass->clazz.packageName)) { return thisMethod; } /* We have a match, but it is in the wrong package */ if (!guaranteed_not_public) { INSTANCE_CLASS super = thisInstanceClass->superClass; UString packageName = currentClass->clazz.packageName; if (has_public_declaration(super, packageName, key)) { return thisMethod; } else { /* No need to ever go through this again */ guaranteed_not_public = TRUE; } } } } END_FOR_EACH_METHOD /* If the class has a superclass, look its methods as well */ thisInstanceClass = thisInstanceClass->superClass; } while (thisInstanceClass != NULL); return NULL;}/*========================================================================= * FUNCTION: getSpecialMethod() * TYPE: public instance-level operation * OVERVIEW: Find a specific special method (<clinit>, main) * using a simple linear lookup strategy. * INTERFACE: * parameters: class pointer, method name and signature pointers * returns: pointer to the method or NIL *=======================================================================*/METHOD getSpecialMethod(INSTANCE_CLASS thisClass, NameTypeKey key){ METHODTABLE methodTable = thisClass->methodTable; FOR_EACH_METHOD(thisMethod, methodTable) if ( (thisMethod->accessFlags & ACC_STATIC) && (thisMethod->nameTypeKey.i == key.i)) return thisMethod; END_FOR_EACH_METHOD return NIL;}/*========================================================================= * FUNCTION: getMethodTableSize() * TYPE: public instance-level operation * OVERVIEW: Return the size of a method table * INTERFACE: * parameters: pointer to a method table * returns: the size of the given method table *=======================================================================*/#if ENABLEPROFILINGint getMethodTableSize(METHODTABLE methodTable){#if !USESTATIC int size = getObjectSize((cell *)methodTable); FOR_EACH_METHOD(entry, methodTable) /* Add the size of the code segment for a non-native method */ if ((entry->accessFlags & ACC_NATIVE) == 0) { if (entry->u.java.code != NULL) { size += getObjectSize((cell*)entry->u.java.code); } /* Add the size of an exception handler table */ if (entry->u.java.handlers != NIL) { size += SIZEOF_HANDLERTABLE(entry->u.java.handlers->length); } } END_FOR_EACH_METHOD return size;#else /* All of the pieces of code mentioned above are in Static memory, and * there's no easy way to get its size. So we just ignore them. */ UNUSEDPARAMETER(methodTable) return 0;#endif /* !USESTATIC */}#endif /* ENABLEPROFILING */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -