📄 stackmap.c
字号:
/*0601*/
/*0602*//* Helper functions. . . . */
/*0603*/
/*0604*/static void
/*0605*/getRegisterMaskFromMethodSignature(METHOD thisMethod, char *map);
/*0606*/
/*0607*/static unsigned int
/*0608*/getInitialRegisterMask(METHOD thisMethod,
/*0609*/ unsigned int *targetOffsetP, char *map)
/*0610*/{
/*0611*/ unsigned int localsCount = thisMethod->frameSize; /* number of locals */
/*0612*/ unsigned int maxStack = thisMethod->u.java.maxStack;
/*0613*/ unsigned int targetOffset = *targetOffsetP;
/*0614*/ struct stackMapEntryStruct *firstFrame, *thisFrame, *lastFrame;
/*0615*/
/*0616*/ STACKMAP stackMaps = thisMethod->u.java.stackMaps.pointerMap;
/*0617*/
/*0618*/ /* Zero out the map to start with, so we only need to set
/*0619./ * appropriate bits */
/*0620*/ memset(map, 0, (localsCount + maxStack + 7) >> 3);
/*0621*/
/*0622*/ if (stackMaps != NULL) {
/*0623*/ int entryCount = stackMaps->nEntries;
/*0624*/ int mask;
/*0625*/ if (entryCount & STACK_MAP_SHORT_ENTRY_FLAG) {
/*0626*/ entryCount &= STACK_MAP_ENTRY_COUNT_MASK;
/*0627*/ mask = STACK_MAP_SHORT_ENTRY_OFFSET_MASK;
/*0628*/ } else {
/*0629*/ mask = ~0; /* Use whole word */
/*0630*/ }
/*0631*/
/*0632*/ /* Find the first stack map frame with an entry >>larger<< than
/*0633./ * the offset we are seeking */
/*0634*/ firstFrame = &stackMaps->entries[0];
/*0635*/ lastFrame = firstFrame + entryCount;
/*0636*/ for (thisFrame = firstFrame; ; thisFrame++) {
/*0637*/ if (thisFrame == lastFrame ||
/*0638*/ targetOffset < (thisFrame->offset & mask)) {
/*0639*/ if (thisFrame == firstFrame) {
/*0640*/ /* We're smaller than the first offset, so just fall
/*0641./ * through to getting the frame from the signature */
/*0642*/ break;
/*0643*/ }
/*0644*/ thisFrame -= 1;
/*0645*/ *targetOffsetP = thisFrame->offset & mask;
/*0646*/ if (mask == -1) {
/*0647*/ int stackmapLength;
/*0648*/ char *stackmap =
/*0649*/ change_Key_to_Name(thisFrame->stackMapKey,
/*0650*/ &stackmapLength);
/*0651*/ /* The first byte is the size of the stack. The
/*0652./ remaining bytes can just be copied over.
/*0653./ */
/*0654*/ memcpy(map, stackmap + 1, stackmapLength - 1);
/*0655*/ return stackmap[0];
/*0656*/ } else {
/*0657*/ memcpy(map, &thisFrame->stackMapKey, 2);
/*0658*/ return thisFrame->offset >> 12;
/*0659*/ }
/*0660*/ }
/*0661*/ }
/*0662*/ }
/*0663*/
/*0664*/ /* Either no stack map, or else we are less than the first entry in
/*0665./ * the stackmap. So we just get the assumed stack map from the
/*0666./ * signature and offset = 0.
/*0667./ */
/*0668*/ getRegisterMaskFromMethodSignature(thisMethod, map);
/*0669*/ *targetOffsetP = 0;
/*0670*/ return 0; /* no stack */
/*0671*/}
/*0672*/
/*0673*/static void
/*0674*/getRegisterMaskFromMethodSignature(METHOD thisMethod, char *map)
/*0675*/{
/*0676*/ unsigned char *codedSignature = (unsigned char *)
/*0677*/ change_Key_to_Name(thisMethod->nameTypeKey.nt.typeKey, NULL);
/*0678*/ unsigned char *from = codedSignature;
/*0679*/ int localVar, argCount;
/*0680*/
/*0681*/ argCount = *from++; /* the first byte is the arg count */
/*0682*/
/*0683*/ if (thisMethod->accessFlags & ACC_STATIC) {
/*0684*/ localVar = 0;
/*0685*/ } else {
/*0686*/ BIT_SET(0);
/*0687*/ localVar = 1;
/*0688*/ }
/*0689*/ for ( ; argCount > 0; argCount--) {
/*0690*/ unsigned char tag = *from++;
/*0691*/ if (tag == 'L') {
/*0692*/ BIT_SET(localVar);
/*0693*/ localVar++;
/*0694*/ from += 2;
/*0695*/ } else if (tag >= 'A' && tag <= 'Z') {
/*0696*/ localVar += (tag == 'D' || tag == 'J') ? 2 : 1;
/*0697*/ } else {
/*0698*/ BIT_SET(localVar);
/*0699*/ localVar++;
/*0700*/ from++;
/*0701*/ }
/*0702*/ }
/*0703*/}
/*0704*/
/*0705*//*=========================================================================
/*0706./ * FUNCTION: rewriteVerifierStackMapsAsPointerMaps
/*0707./ * TYPE: Important GC function
/*0708./ * OVERVIEW: Converts the stack map from its "verifier" format
/*0709./ * to its pointer map format.
/*0710./ * INTERFACE:
/*0711./ * parameters: thisMethod: The current method
/*0712./ *
/*0713./ * This function converts the stack map from its verifier format (in which
/*0714./ * we need to know the type of every stack location and local variable) to
/*0715./ * pointer map format (in which we just need to know what's a pointer and
/*0716./ * what isn't).
/*0717./ *
/*0718./ * This transformation is performed as the last step of verifying a method.
/*0719./ *=======================================================================*/
/*0720*/
/*0721*/STACKMAP
/*0722*/rewriteVerifierStackMapsAsPointerMaps(METHOD thisMethod) {
/*0723*/ STACKMAP result; /* Holds the result, to be stored in method */
/*0724*/ START_TEMPORARY_ROOTS
/*0725*/ DECLARE_TEMPORARY_ROOT(POINTERLIST, verifierStackMaps,
/*0726*/ thisMethod->u.java.stackMaps.verifierMap);
/*0727*/ unsigned int localsCount = thisMethod->frameSize;
/*0728*/ unsigned int maxStack = thisMethod->u.java.maxStack;
/*0729*/ long stackMapCount = verifierStackMaps->length;
/*0730*/ long stackMapIndex, i;
/*0731*/ bool_t useLongFormat;
/*0732*/ char tempSpace[8]; /* Almost always enough space */
/*0733*/ char *map = tempSpace;
/*0734*/
/*0735*/ unsigned int maxMapLength;
/*0736*/
/*0737*/ int resultSize = sizeof(struct stackMapStruct) +
/*0738*/ (stackMapCount - 1) * sizeof(struct stackMapEntryStruct);
/*0739*/
/*0740*/ result =
/*0741*/ (STACKMAP)callocPermanentObject(ByteSizeToCellSize(resultSize));
/*0742*/ useLongFormat = FALSE;
/*0743*/ for (stackMapIndex = 0; stackMapIndex < stackMapCount; stackMapIndex++){
/*0744*/ short *verifierStackMap =
/*0745*/ (short *)verifierStackMaps->data[stackMapIndex].cellp;
/*0746*/ unsigned short registers = verifierStackMap[0];
/*0747*/ unsigned short stackSize = verifierStackMap[registers + 1];
/*0748*/ unsigned short offset =
/*0749*/ verifierStackMaps->data[stackMapIndex + stackMapCount].cell;
/*0750*/
/*0751*/ if (stackSize > STACK_MAP_SHORT_ENTRY_MAX_STACK_SIZE
/*0752*/ || offset > STACK_MAP_SHORT_ENTRY_MAX_OFFSET
/*0753*/ || (stackSize + localsCount) > 16) {
/*0754*/ useLongFormat = TRUE;
/*0755*/ break;
/*0756*/ }
/*0757*/ }
/*0758*/
/*0759*/ if (useLongFormat) {
/*0760*/ result->nEntries = (unsigned short)stackMapCount;
/*0761*/ maxMapLength = (localsCount + maxStack + 7 + 8) >> 3;
/*0762*/ if (maxMapLength > sizeof(tempSpace)) {
/*0763*/ IS_TEMPORARY_ROOT(map, mallocBytes(maxMapLength));
/*0764*/ }
/*0765*/
/*0766*/ } else {
/*0767*/ result->nEntries = (unsigned short)stackMapCount
/*0768*/ | STACK_MAP_SHORT_ENTRY_FLAG;
/*0769*/ maxMapLength = 4; /* actually, 3 */
/*0770*/ }
/*0771*/
/*0772*/ for (stackMapIndex = 0; stackMapIndex < stackMapCount; stackMapIndex++){
/*0773*/ short *verifierStackMap =
/*0774*/ (short *)verifierStackMaps->data[stackMapIndex].cellp;
/*0775*/ unsigned short offset = (unsigned short)
/*0776*/ verifierStackMaps->data[stackMapIndex + stackMapCount].cell;
/*0777*/ unsigned short registers, stackSize;
/*0778*/
/*0779*/ /* This isn't a duplicate. So calculate the stack map. */
/*0780*/ memset(map, 0, maxMapLength);
/*0781*/
/*0782*/ /* Read the registers and the stack */
/*0783*/ registers = *verifierStackMap++; /* number of registers */
/*0784*/ for (i = 0; i < registers; i++) {
/*0785*/ unsigned short type = *verifierStackMap++;
/*0786*/ if (type > 255 || type == ITEM_InitObject) {
/*0787*/ BIT_SET(8 + i);
/*0788*/ }
/*0789*/ }
/*0790*/ stackSize = *verifierStackMap++;
/*0791*/ for (i = 0; i < stackSize; i++) {
/*0792*/ unsigned short type = *verifierStackMap++;
/*0793*/ if (type > 255 || type == ITEM_InitObject) {
/*0794*/ BIT_SET(8 + i + localsCount);
/*0795*/ }
/*0796*/ }
/*0797*/
/*0798*/ result->entries[stackMapIndex].offset = offset;
/*0799*/ if (useLongFormat) {
/*0800*/ map[0] = stackSize;
/*0801*/ /* We can delete all the zero words at the end, as long as we
/*0802./ * save at least one word at the end.
/*0803./ */
/*0804*/ for (i = maxMapLength - 1; i > 0; i--) {
/*0805*/ if (map[i]) break;
/*0806*/ }
/*0807*/ /* Fill in the key */
/*0808*/ result->entries[stackMapIndex].stackMapKey =
/*0809*/ change_Name_to_Key((CONST_CHAR_HANDLE)&map, 0, i+1);
/*0810*/ } else {
/*0811*/ result->entries[stackMapIndex].offset =
/*0812*/ offset + (stackSize << 12);
/*0813*/ memcpy(&result->entries[stackMapIndex].stackMapKey, map+1, 2);
/*0814*/ }
/*0815*/ }
/*0816*/ END_TEMPORARY_ROOTS
/*0817*/ return result;
/*0818*/}
/*0819*/
/*0820*//*=========================================================================
/*0821./ * FUNCTION: getBits, setbits
/*0822./ * TYPE: private stack map operations
/*0823./ * OVERVIEW: Sets/Gets zero or more bits in a bit map
/*0824./ * INTERFACE:
/*0825./ * parameters: map: A table of bits
/*0826./ * bit: The starting index of bits to set
/*0827./ * count: The number of bits to change
/*0828./ * result/values: Array of bytes. For getBits, the result
/*0829./ * is placed into the array. For setBits, it's the
/*0830./ * value(s) to be put into the bitmap. Non-zero = TRUE
/*0831./ *=======================================================================*/
/*0832*/
/*0833*/static void
/*0834*/getBits(char *map, unsigned int bit, unsigned int count, unsigned char *result)
/*0835*/{
/*0836*/ int i;
/*0837*/ for (i = 0; i < count; i++, bit++) {
/*0838*/ int offset = bit >> 3;
/*0839*/ int mask = (((unsigned)1) << (bit & 7));
/*0840*/ result[i] = map[offset] & mask;
/*0841*/ }
/*0842*/}
/*0843*/
/*0844*/static void
/*0845*/setBits(char *map, unsigned int bit, unsigned int count, unsigned char *values)
/*0846*/{
/*0847*/ int i;
/*0848*/ for (i = 0; i < count; i++, bit++) {
/*0849*/ int offset = bit >> 3;
/*0850*/ int mask = (((unsigned)1) << (bit & 7));
/*0851*/ if (values[i] != 0) {
/*0852*/ map[offset] |= mask;
/*0853*/ } else {
/*0854*/ map[offset] &= ~mask;
/*0855*/ }
/*0856*/ }
/*0857*/}
/*0858*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -