📄 stackmap.c
字号:
* some offset before *targetOffsetP. It will update *targetOffsetP with the * offset that it actually knows about. * * This function has two sources of knowing a stack map for a particular * location. * the method's stackmap field. * the method's signature, if there is no stackmap, or all stackmaps * are for an address after the current one. *=======================================================================*//* Helper functions. . . . */static voidgetRegisterMaskFromMethodSignature(METHOD thisMethod, char *map);static unsigned intgetInitialRegisterMask(METHOD thisMethod, unsigned int *targetOffsetP, char *map){ unsigned int localsCount = thisMethod->frameSize; /* number of locals */ unsigned int maxStack = thisMethod->u.java.maxStack; unsigned int targetOffset = *targetOffsetP; struct stackMapEntryStruct *firstFrame, *thisFrame, *lastFrame; STACKMAP stackMaps = thisMethod->u.java.stackMaps.pointerMap; /* Zero out the map to start with, so we only need to set * appropriate bits */ memset(map, 0, (localsCount + maxStack + 7) >> 3); if (stackMaps != NULL) { int entryCount = stackMaps->nEntries; int mask; if (entryCount & STACK_MAP_SHORT_ENTRY_FLAG) { entryCount &= STACK_MAP_ENTRY_COUNT_MASK; mask = STACK_MAP_SHORT_ENTRY_OFFSET_MASK; } else { mask = ~0; /* Use whole word */ } /* Find the first stack map frame with an entry >>larger<< than * the offset we are seeking */ firstFrame = &stackMaps->entries[0]; lastFrame = firstFrame + entryCount; for (thisFrame = firstFrame; ; thisFrame++) { if (thisFrame == lastFrame || targetOffset < (thisFrame->offset & mask)) { if (thisFrame == firstFrame) { /* We're smaller than the first offset, so just fall * through to getting the frame from the signature */ break; } thisFrame -= 1; *targetOffsetP = thisFrame->offset & mask; if (mask == -1) { int stackmapLength; char *stackmap = change_Key_to_Name(thisFrame->stackMapKey, &stackmapLength); /* The first byte is the size of the stack. The remaining bytes can just be copied over. */ memcpy(map, stackmap + 1, stackmapLength - 1); return stackmap[0]; } else { memcpy(map, &thisFrame->stackMapKey, 2); return thisFrame->offset >> 12; } } } } /* Either no stack map, or else we are less than the first entry in * the stackmap. So we just get the assumed stack map from the * signature and offset = 0. */ getRegisterMaskFromMethodSignature(thisMethod, map); *targetOffsetP = 0; return 0; /* no stack */}static voidgetRegisterMaskFromMethodSignature(METHOD thisMethod, char *map){ unsigned char *codedSignature = (unsigned char *) change_Key_to_Name(thisMethod->nameTypeKey.nt.typeKey, NULL); unsigned char *from = codedSignature; int localVar, argCount; argCount = *from++; /* the first byte is the arg count */ if (thisMethod->accessFlags & ACC_STATIC) { localVar = 0; } else { BIT_SET(0); localVar = 1; } for ( ; argCount > 0; argCount--) { unsigned char tag = *from++; if (tag == 'L') { BIT_SET(localVar); localVar++; from += 2; } else if (tag >= 'A' && tag <= 'Z') { localVar += (tag == 'D' || tag == 'J') ? 2 : 1; } else { BIT_SET(localVar); localVar++; from++; } }}/*========================================================================= * FUNCTION: rewriteVerifierStackMapsAsPointerMaps * TYPE: Important GC function * OVERVIEW: Converts the stack map from its "verifier" format * to its pointer map format. * INTERFACE: * parameters: thisMethod: The current method * * This function converts the stack map from its verifier format (in which * we need to know the type of every stack location and local variable) to * pointer map format (in which we just need to know what's a pointer and * what isn't). * * This transformation is performed as the last step of verifying a method. *=======================================================================*/STACKMAPrewriteVerifierStackMapsAsPointerMaps(METHOD thisMethod) { STACKMAP result; /* Holds the result, to be stored in method */ START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(POINTERLIST, verifierStackMaps, thisMethod->u.java.stackMaps.verifierMap); unsigned int localsCount = thisMethod->frameSize; unsigned int maxStack = thisMethod->u.java.maxStack; long stackMapCount = verifierStackMaps->length; long stackMapIndex, i; bool_t useLongFormat; char tempSpace[8]; /* Almost always enough space */ char *map = tempSpace; unsigned int maxMapLength; int resultSize = sizeof(struct stackMapStruct) + (stackMapCount - 1) * sizeof(struct stackMapEntryStruct); result = (STACKMAP)callocPermanentObject(ByteSizeToCellSize(resultSize)); useLongFormat = FALSE; for (stackMapIndex = 0; stackMapIndex < stackMapCount; stackMapIndex++){ short *verifierStackMap = (short *)verifierStackMaps->data[stackMapIndex].cellp; unsigned short registers = verifierStackMap[0]; unsigned short stackSize = verifierStackMap[registers + 1]; unsigned short offset = verifierStackMaps->data[stackMapIndex + stackMapCount].cell; if (stackSize > STACK_MAP_SHORT_ENTRY_MAX_STACK_SIZE || offset > STACK_MAP_SHORT_ENTRY_MAX_OFFSET || (stackSize + localsCount) > 16) { useLongFormat = TRUE; break; } } if (useLongFormat) { result->nEntries = (unsigned short)stackMapCount; maxMapLength = (localsCount + maxStack + 7 + 8) >> 3; if (maxMapLength > sizeof(tempSpace)) { IS_TEMPORARY_ROOT(map, mallocBytes(maxMapLength)); } } else { result->nEntries = (unsigned short)stackMapCount | STACK_MAP_SHORT_ENTRY_FLAG; maxMapLength = 4; /* actually, 3 */ } for (stackMapIndex = 0; stackMapIndex < stackMapCount; stackMapIndex++){ short *verifierStackMap = (short *)verifierStackMaps->data[stackMapIndex].cellp; unsigned short offset = (unsigned short) verifierStackMaps->data[stackMapIndex + stackMapCount].cell; unsigned short registers, stackSize; /* This isn't a duplicate. So calculate the stack map. */ memset(map, 0, maxMapLength); /* Read the registers and the stack */ registers = *verifierStackMap++; /* number of registers */ for (i = 0; i < registers; i++) { unsigned short type = *verifierStackMap++; if (type > 255 || type == ITEM_InitObject) { BIT_SET(8 + i); } } stackSize = *verifierStackMap++; for (i = 0; i < stackSize; i++) { unsigned short type = *verifierStackMap++; if (type > 255 || type == ITEM_InitObject) { BIT_SET(8 + i + localsCount); } } result->entries[stackMapIndex].offset = offset; if (useLongFormat) { map[0] = stackSize; /* We can delete all the zero words at the end, as long as we * save at least one word at the end. */ for (i = maxMapLength - 1; i > 0; i--) { if (map[i]) break; } /* Fill in the key */ result->entries[stackMapIndex].stackMapKey = change_Name_to_Key((CONST_CHAR_HANDLE)&map, 0, i+1); } else { result->entries[stackMapIndex].offset = offset + (stackSize << 12); memcpy(&result->entries[stackMapIndex].stackMapKey, map+1, 2); } } END_TEMPORARY_ROOTS return result;}/*========================================================================= * FUNCTION: getBits, setbits * TYPE: private stack map operations * OVERVIEW: Sets/Gets zero or more bits in a bit map * INTERFACE: * parameters: map: A table of bits * bit: The starting index of bits to set * count: The number of bits to change * result/values: Array of bytes. For getBits, the result * is placed into the array. For setBits, it's the * value(s) to be put into the bitmap. Non-zero = TRUE *=======================================================================*/static voidgetBits(char *map, unsigned int bit, unsigned int count, unsigned char *result){ int i; for (i = 0; i < count; i++, bit++) { int offset = bit >> 3; int mask = (((unsigned)1) << (bit & 7)); result[i] = map[offset] & mask; }}static voidsetBits(char *map, unsigned int bit, unsigned int count, unsigned char *values){ int i; for (i = 0; i < count; i++, bit++) { int offset = bit >> 3; int mask = (((unsigned)1) << (bit & 7)); if (values[i] != 0) { map[offset] |= mask; } else { map[offset] &= ~mask; } }}/*========================================================================= * FUNCTION: printStackMap * TYPE: debugging/printing operation * OVERVIEW: Print a stack map for debugging purposes * INTERFACE: *=======================================================================*/#if INCLUDEDEBUGCODEstatic voidprintStackMap(long offset, const char *string, unsigned int localsCount, char *map, int stackSize){ unsigned char x[1]; int i; fprintf(stdout, "%4ld %20s: ", offset, string); for (i = 0; i < localsCount; i++) { getBits(map, i, 1, x); fprintf(stdout,x[0] ? "*" : "."); } fprintf(stdout, "//"); for (i = localsCount; i < stackSize; i++) { getBits(map, i, 1, x); fprintf(stdout,x[0] ? "*" : "."); } fprintf(stdout, "\n");}#endif /* INCLUDEDEBUGCODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -