📄 fields.c
字号:
/* And the closing NULL */ *to = '\0'; /* Return the end of the string */ return to;}/* A helper function used above. * * It expects the start of the signature of an argument or return type at * *fromP. It encodes that single argument. Both fromP, and toP are updated * to point just past the argument just read/written. */static voidchange_Key_to_MethodSignatureInternal(unsigned char **fromP, char **toP) { unsigned char *from = *fromP; char *to = *toP; unsigned char tag = *from++; /* normal tags represent themselves */ if ((tag >= 'A' && tag <= 'Z') && (tag != 'L')) { *to++ = (char)tag; } else { FieldTypeKey classKey; if (tag == 'L') { tag = *from++; } classKey = (((int)tag) << 8) + *from++; to = change_Key_to_FieldSignature_inBuffer(classKey, to); } *fromP = from; *toP = to;}/*========================================================================= * FUNCTION: change_FieldSignature_to_Key() * * TYPE: public instance-level operation on runtime classes * * OVERVIEW: Converts a field signature into a unique 16-bit value. * * INTERFACE: * parameters: type: A pointer to the field signature * length: length of signature * * returns: The unique 16-bit key that represents this field type * * The encoding is as follows: * 0 - 255: Primitive types. These use the same encoding as signature. * For example: int is 'I', boolean is 'Z', etc. * * 256 - 0x1FFF Non-array classes. Every class is assigned a unique * key value when it is created. This value is used. * * 0x2000-0xDFFF Arrays of depth 1 - 6. The high three bits represent the * depth, the low 13-bits (0 - 0x1FFF) represent the type. * * 0xE000-0xFFFF Arrays of depth 8 or more. These are specially encoded * so that the low 13-bits are different that the low 13-bits * of any other class. The high bits are set so that we'll * recognize it as an array. * * Note that this scheme lets us encode an array class with out actually * creating it. * * The algorithm that gives key codes to classes cooperates with this scheme. * When an array class is ever created, it is given the appropriate key code. * * NOTE! [Sheng 1/30/00] The verifier now uses the 13th bit (0x1000) to * indicate whether a class instance has been initialized (ITEM_NewObject). * As a result, only the low 12 bits (0 - 0xFFF) represent the base class * type. * *=======================================================================*/FieldTypeKeychange_FieldSignature_to_Key (CONST_CHAR_HANDLE typeH, int offset, int length) { CLASS clazz; const char *start = unhand(typeH); /* volatile */ const char *type = start + offset; /* volatile */ const char *end = type + length; /* volatile */ const char *p = type; /* volatile */ int depth; /* Get the depth, and skip over the initial '[' that indicate the */ while (*p == '[') { p++; } depth = p - type; /* Arrays of depth greater than 6 are just handled as if they were real * classes. They will automatically be assigned */ if (depth >= MAX_FIELD_KEY_ARRAY_DEPTH) { clazz = getRawClassX(typeH, offset, length); /* I haven't decided yet whether these classes' keys will actually * have their 3 high bits set to 7 or not. The following will work * in either case */ return (clazz->key) | (short)(MAX_FIELD_KEY_ARRAY_DEPTH << FIELD_KEY_ARRAY_SHIFT); } else if (*p != 'L') { /* We have a primitive type, or an array thereof (depth < MAX_FIELD_KEY_ARRAY_DEPTH ) */ return (*(unsigned char *)p) + (depth << FIELD_KEY_ARRAY_SHIFT); } else { /* We have an object, or an array thereof. With signatures, these * always have an 'L' at the beginning, and a ';' at the end. * We're not checking that this is a well-formed signature, but we * could */ p++; /* skip over 'L' for non-arrays */ end--; /* ignore ; at the end */ clazz = getRawClassX(typeH, p - start, end - p); return clazz->key + (depth << FIELD_KEY_ARRAY_SHIFT); }} /*========================================================================= * FUNCTION: change_MethodSignature_to_Key() * * TYPE: public instance-level operation on runtime classes * * OVERVIEW: Converts a method signature into a unique 16-bit value. * * INTERFACE: * parameters: type: A pointer to the method signature * length: length of signature * * returns: The unique 16-bit key that represents this field type * * The encoding is as follows: * * We first encode the method signature into an "encoded" signature. This * encoded signature is then treated as it were a name, and that name. We * call change_Name_to_Key on it. * * The character array is created as follows * 1 byte indicates the number of arguments * 1 - 3 bytes indicate the first argument * .. * 1 - 3 bytes indicate the nth argument * 1 - 3 bytes indicate the return type. * * % If the type is primitive, it is encoded using its signature, like 'I', * 'B', etc. * % Otherwise, we get its 16-bit class key. * . If the high byte is in the range 'A'..'Z', we encode it as the 3 * bytes,: 'L', hi, lo * . Otherwise, we encode it as the 2 byte, hi, lo * * We're saving the whole range 'A'..'Z' since we may want to make 'O' be * java.lang.Object, or 'X' be java.lang.String. . . . * * Note that the first argument indicates slots, not arguments. doubles and * longs are two slots. *=======================================================================*/FieldTypeKey change_MethodSignature_to_Key(CONST_CHAR_HANDLE nameH, int offset, int length){ /* We're first going to encode the signature, as indicated above. */ unsigned char *buffer = (unsigned char *)str_buffer;/* temporary storage */ /* unhand(nameH)[fromOffset] points into signature */ int fromOffset = offset + 1; unsigned char *to = buffer + 1; /* pointer into encoding */ int argCount = 0; int result; /* Call a helper function to do the actual work. This help function * converts one field into its encoding. fromOffset and to are updated. * The function returns the number of slots of its argument */ while (unhand(nameH)[fromOffset] != ')') { /* The following may GC */ change_MethodSignature_to_KeyInternal(nameH, &fromOffset, &to); argCount++; } /* Skip over the ')' */ fromOffset++; /* And interpret the return type, too */ change_MethodSignature_to_KeyInternal(nameH, &fromOffset, &to); /* Set the slot type. */ buffer[0] = argCount; if (fromOffset != offset + length) { /* We should have exactly reached the end of the string */ fatalError(KVM_MSG_BAD_METHOD_SIGNATURE); } /* And get the name key for the encoded signature */ result = change_Name_to_Key((CONST_CHAR_HANDLE)&buffer, 0, to - buffer); return result;}/* Helper function used by the above function. It parses the single field * signature starting at *fromP, and puts the result at *toP. Both are * updated to just past where they were. The size of the argument is returned. */static voidchange_MethodSignature_to_KeyInternal(CONST_CHAR_HANDLE nameH, int *fromOffsetP, unsigned char **toP){ const char *start = unhand(nameH); const int fromOffset = *fromOffsetP; const char *const from = start + fromOffset; unsigned char *to = *toP; const char *endFrom; switch (*from) { default: endFrom = from + 1; break; case 'L': endFrom = strchr(from + 1, ';') + 1; break; case '[': endFrom = from + 1; while (*endFrom == '[') endFrom++; if (*endFrom == 'L') { endFrom = strchr(endFrom + 1, ';') + 1; } else { endFrom++; } break; } if (endFrom == from + 1) { *to++ = (unsigned char)*from; } else { FieldTypeKey key = change_FieldSignature_to_Key(nameH, from - start, endFrom - from); unsigned char hiChar = ((unsigned)key) >> 8; unsigned char loChar = key & 0xFF; if (hiChar >= 'A' && hiChar <= 'Z') { *to++ = 'L'; } *to++ = hiChar; *to++ = loChar; } *to = '\0'; /* always helps debugging */ *toP = to; /* Although from and endfrom are no longer valid, their difference is * still the amount by which fromOffset has increased */ *fromOffsetP = fromOffset + (endFrom - from);}/*========================================================================= * FUNCTION: getNameAndTypeKey * * OVERVIEW: converts a name and signature (either field or method) to * a 32bit value. * * INTERFACE: * parameters: name: Name of method * type: Field or method signature. * * returns: The unique 32-bit value that represents the name and type. * * We use a structure with two 16-bit values. One 16-bit value encodes the * name using standard name encoding. The other holds the key of the * signature. * * Note that we cannot do the reverse operation. Given a type key, we can't * tell if its a method key or a field key! *=======================================================================*/NameTypeKey getNameAndTypeKey(const char *name, const char *type) { int typeLength = strlen(type); NameTypeKey result; if (INCLUDEDEBUGCODE && (inCurrentHeap(name) || inCurrentHeap(type))) { fatalError(KVM_MSG_BAD_CALL_TO_GETNAMEANDTYPEKEY); } result.nt.nameKey = getUString(name)->key; result.nt.typeKey = ((type)[0] == '(') ? change_MethodSignature_to_Key(&type, 0, typeLength) : change_FieldSignature_to_Key(&type, 0, typeLength); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -