📄 fields.c
字号:
/*0487*/}
/*0488*/
/*0489*//* A helper function used above.
/*0490./ *
/*0491./ * It expects the start of the signature of an argument or return type at
/*0492./ * *fromP. It encodes that single argument. Both fromP, and toP are updated
/*0493./ * to point just past the argument just read/written.
/*0494./ */
/*0495*/static void
/*0496*/change_Key_to_MethodSignatureInternal(unsigned char **fromP, char **toP) {
/*0497*/ unsigned char *from = *fromP;
/*0498*/ char *to = *toP;
/*0499*/ unsigned char tag = *from++;
/*0500*/
/*0501*/ /* normal tags represent themselves */
/*0502*/ if ((tag >= 'A' && tag <= 'Z') && (tag != 'L')) {
/*0503*/ *to++ = (char)tag;
/*0504*/ } else {
/*0505*/ FieldTypeKey classKey;
/*0506*/ if (tag == 'L') {
/*0507*/ tag = *from++;
/*0508*/ }
/*0509*/ classKey = (((int)tag) << 8) + *from++;
/*0510*/ to = change_Key_to_FieldSignature_inBuffer(classKey, to);
/*0511*/ }
/*0512*/ *fromP = from;
/*0513*/ *toP = to;
/*0514*/}
/*0515*/
/*0516*//*=========================================================================
/*0517./ * FUNCTION: change_FieldSignature_to_Key()
/*0518./ *
/*0519./ * TYPE: public instance-level operation on runtime classes
/*0520./ *
/*0521./ * OVERVIEW: Converts a field signature into a unique 16-bit value.
/*0522./ *
/*0523./ * INTERFACE:
/*0524./ * parameters: type: A pointer to the field signature
/*0525./ * length: length of signature
/*0526./ *
/*0527./ * returns: The unique 16-bit key that represents this field type
/*0528./ *
/*0529./ * The encoding is as follows:
/*0530./ * 0 - 255: Primitive types. These use the same encoding as signature.
/*0531./ * For example: int is 'I', boolean is 'Z', etc.
/*0532./ *
/*0533./ * 256 - 0x1FFF Non-array classes. Every class is assigned a unique
/*0534./ * key value when it is created. This value is used.
/*0535./ *
/*0536./ * 0x2000-0xDFFF Arrays of depth 1 - 6. The high three bits represent the
/*0537./ * depth, the low 13-bits (0 - 0x1FFF) represent the type.
/*0538./ *
/*0539./ * 0xE000-0xFFFF Arrays of depth 8 or more. These are specially encoded
/*0540./ * so that the low 13-bits are different that the low 13-bits
/*0541./ * of any other class. The high bits are set so that we'll
/*0542./ * recognize it as an array.
/*0543./ *
/*0544./ * Note that this scheme lets us encode an array class with out actually
/*0545./ * creating it.
/*0546./ *
/*0547./ * The algorithm that gives key codes to classes cooperates with this scheme.
/*0548./ * When an array class is ever created, it is given the appropriate key code.
/*0549./ *
/*0550./ * NOTE! [Sheng 1/30/00] The verifier now uses the 13th bit (0x1000) to
/*0551./ * indicate whether a class instance has been initialized (ITEM_NewObject).
/*0552./ * As a result, only the low 12 bits (0 - 0xFFF) represent the base class
/*0553./ * type.
/*0554./ *
/*0555./ *=======================================================================*/
/*0556*/
/*0557*/FieldTypeKey
/*0558*/change_FieldSignature_to_Key (CONST_CHAR_HANDLE typeH, int offset, int length) {
/*0559*/ CLASS clazz;
/*0560*/ const char *start = unhand(typeH); /* volatile */
/*0561*/ const char *type = start + offset; /* volatile */
/*0562*/ const char *end = type + length; /* volatile */
/*0563*/ const char *p = type; /* volatile */
/*0564*/
/*0565*/ int depth;
/*0566*/
/*0567*/ /* Get the depth, and skip over the initial '[' that indicate the */
/*0568*/
/*0569*/ while (*p == '[') {
/*0570*/ p++;
/*0571*/ }
/*0572*/ depth = p - type;
/*0573*/
/*0574*/ /* Arrays of depth greater than 6 are just handled as if they were real
/*0575./ * classes. They will automatically be assigned */
/*0576*/ if (depth >= MAX_FIELD_KEY_ARRAY_DEPTH) {
/*0577*/ clazz = getRawClassX(typeH, offset, length);
/*0578*/ /* I haven't decided yet whether these classes' keys will actually
/*0579./ * have their 3 high bits set to 7 or not. The following will work
/*0580./ * in either case */
/*0581*/ return (clazz->key) | (short)(MAX_FIELD_KEY_ARRAY_DEPTH
/*0582*/ << FIELD_KEY_ARRAY_SHIFT);
/*0583*/ } else if (*p != 'L') {
/*0584*/ /* We have a primitive type, or an array thereof (depth <
/*0585./ MAX_FIELD_KEY_ARRAY_DEPTH )
/*0586./ */
/*0587*/ return (*(unsigned char *)p) + (depth << FIELD_KEY_ARRAY_SHIFT);
/*0588*/ } else {
/*0589*/ /* We have an object, or an array thereof. With signatures, these
/*0590./ * always have an 'L' at the beginning, and a ';' at the end.
/*0591./ * We're not checking that this is a well-formed signature, but we
/*0592./ * could */
/*0593*/ p++; /* skip over 'L' for non-arrays */
/*0594*/ end--; /* ignore ; at the end */
/*0595*/ clazz = getRawClassX(typeH, p - start, end - p);
/*0596*/ return clazz->key + (depth << FIELD_KEY_ARRAY_SHIFT);
/*0597*/ }
/*0598*/}
/*0599*/
/*0600*//*=========================================================================
/*0601./ * FUNCTION: change_MethodSignature_to_Key()
/*0602./ *
/*0603./ * TYPE: public instance-level operation on runtime classes
/*0604./ *
/*0605./ * OVERVIEW: Converts a method signature into a unique 16-bit value.
/*0606./ *
/*0607./ * INTERFACE:
/*0608./ * parameters: type: A pointer to the method signature
/*0609./ * length: length of signature
/*0610./ *
/*0611./ * returns: The unique 16-bit key that represents this field type
/*0612./ *
/*0613./ * The encoding is as follows:
/*0614./ *
/*0615./ * We first encode the method signature into an "encoded" signature. This
/*0616./ * encoded signature is then treated as it were a name, and that name. We
/*0617./ * call change_Name_to_Key on it.
/*0618./ *
/*0619./ * The character array is created as follows
/*0620./ * 1 byte indicates the number of arguments
/*0621./ * 1 - 3 bytes indicate the first argument
/*0622./ * ..
/*0623./ * 1 - 3 bytes indicate the nth argument
/*0624./ * 1 - 3 bytes indicate the return type.
/*0625./ *
/*0626./ * % If the type is primitive, it is encoded using its signature, like 'I',
/*0627./ * 'B', etc.
/*0628./ * % Otherwise, we get its 16-bit class key.
/*0629./ * . If the high byte is in the range 'A'..'Z', we encode it as the 3
/*0630./ * bytes,: 'L', hi, lo
/*0631./ * . Otherwise, we encode it as the 2 byte, hi, lo
/*0632./ *
/*0633./ * We're saving the whole range 'A'..'Z' since we may want to make 'O' be
/*0634./ * java.lang.Object, or 'X' be java.lang.String. . . .
/*0635./ *
/*0636./ * Note that the first argument indicates slots, not arguments. doubles and
/*0637./ * longs are two slots.
/*0638./ *=======================================================================*/
/*0639*/
/*0640*/FieldTypeKey
/*0641*/change_MethodSignature_to_Key(CONST_CHAR_HANDLE nameH, int offset, int length)
/*0642*/{
/*0643*/
/*0644*/ /* We're first going to encode the signature, as indicated above. */
/*0645*/ unsigned char *buffer = (unsigned char *)str_buffer;/* temporary storage */
/*0646*/
/*0647*/ /* unhand(nameH)[fromOffset] points into signature */
/*0648*/ int fromOffset = offset + 1;
/*0649*/
/*0650*/ unsigned char *to = buffer + 1; /* pointer into encoding */
/*0651*/ int argCount = 0;
/*0652*/ int result;
/*0653*/
/*0654*/ /* Call a helper function to do the actual work. This help function
/*0655./ * converts one field into its encoding. fromOffset and to are updated.
/*0656./ * The function returns the number of slots of its argument */
/*0657*/ while (unhand(nameH)[fromOffset] != ')') {
/*0658*/ /* The following may GC */
/*0659*/ change_MethodSignature_to_KeyInternal(nameH, &fromOffset, &to);
/*0660*/ argCount++;
/*0661*/ }
/*0662*/
/*0663*/ /* Skip over the ')' */
/*0664*/ fromOffset++;
/*0665*/
/*0666*/ /* And interpret the return type, too */
/*0667*/ change_MethodSignature_to_KeyInternal(nameH, &fromOffset, &to);
/*0668*/
/*0669*/ /* Set the slot type. */
/*0670*/ buffer[0] = argCount;
/*0671*/ if (fromOffset != offset + length) {
/*0672*/ /* We should have exactly reached the end of the string */
/*0673*/ fatalError(KVM_MSG_BAD_METHOD_SIGNATURE);
/*0674*/ }
/*0675*/
/*0676*/ /* And get the name key for the encoded signature */
/*0677*/ result = change_Name_to_Key((CONST_CHAR_HANDLE)&buffer, 0, to - buffer);
/*0678*/ return result;
/*0679*/}
/*0680*/
/*0681*//* Helper function used by the above function. It parses the single field
/*0682./ * signature starting at *fromP, and puts the result at *toP. Both are
/*0683./ * updated to just past where they were. The size of the argument is returned.
/*0684./ */
/*0685*/
/*0686*/static void
/*0687*/change_MethodSignature_to_KeyInternal(CONST_CHAR_HANDLE nameH,
/*0688*/ int *fromOffsetP, unsigned char **toP)
/*0689*/{
/*0690*/ const char *start = unhand(nameH);
/*0691*/ const int fromOffset = *fromOffsetP;
/*0692*/ const char *const from = start + fromOffset;
/*0693*/ unsigned char *to = *toP;
/*0694*/ const char *endFrom;
/*0695*/
/*0696*/ switch (*from) {
/*0697*/ default:
/*0698*/ endFrom = from + 1;
/*0699*/ break;
/*0700*/ case 'L':
/*0701*/ endFrom = strchr(from + 1, ';') + 1;
/*0702*/ break;
/*0703*/ case '[':
/*0704*/ endFrom = from + 1;
/*0705*/ while (*endFrom == '[') endFrom++;
/*0706*/ if (*endFrom == 'L') {
/*0707*/ endFrom = strchr(endFrom + 1, ';') + 1;
/*0708*/ } else {
/*0709*/ endFrom++;
/*0710*/ }
/*0711*/ break;
/*0712*/ }
/*0713*/ if (endFrom == from + 1) {
/*0714*/ *to++ = (unsigned char)*from;
/*0715*/ } else {
/*0716*/ FieldTypeKey key = change_FieldSignature_to_Key(nameH, from - start,
/*0717*/ endFrom - from);
/*0718*/ unsigned char hiChar = ((unsigned)key) >> 8;
/*0719*/ unsigned char loChar = key & 0xFF;
/*0720*/ if (hiChar >= 'A' && hiChar <= 'Z') {
/*0721*/ *to++ = 'L';
/*0722*/ }
/*0723*/ *to++ = hiChar;
/*0724*/ *to++ = loChar;
/*0725*/ }
/*0726*/ *to = '\0'; /* always helps debugging */
/*0727*/ *toP = to;
/*0728*/ /* Although from and endfrom are no longer valid, their difference is
/*0729./ * still the amount by which fromOffset has increased
/*0730./ */
/*0731*/ *fromOffsetP = fromOffset + (endFrom - from);
/*0732*/}
/*0733*/
/*0734*//*=========================================================================
/*0735./ * FUNCTION: getNameAndTypeKey
/*0736./ *
/*0737./ * OVERVIEW: converts a name and signature (either field or method) to
/*0738./ * a 32bit value.
/*0739./ *
/*0740./ * INTERFACE:
/*0741./ * parameters: name: Name of method
/*0742./ * type: Field or method signature.
/*0743./ *
/*0744./ * returns: The unique 32-bit value that represents the name and type.
/*0745./ *
/*0746./ * We use a structure with two 16-bit values. One 16-bit value encodes the
/*0747./ * name using standard name encoding. The other holds the key of the
/*0748./ * signature.
/*0749./ *
/*0750./ * Note that we cannot do the reverse operation. Given a type key, we can't
/*0751./ * tell if its a method key or a field key!
/*0752./ *=======================================================================*/
/*0753*/
/*0754*/NameTypeKey
/*0755*/getNameAndTypeKey(const char *name, const char *type) {
/*0756*/ int typeLength = strlen(type);
/*0757*/ NameTypeKey result;
/*0761*/ result.nt.nameKey = getUString(name)->key;
/*0762*/ result.nt.typeKey = ((type)[0] == '(')
/*0763*/ ? change_MethodSignature_to_Key(&type, 0, typeLength)
/*0764*/ : change_FieldSignature_to_Key(&type, 0, typeLength);
/*0765*/ return result;
/*0766*/}
/*0767*/
/*0768*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -