📄 stackmap.c
字号:
thisIP += 2; case POP2: case LADD: case DADD: case LSUB: case DSUB: case LMUL: case DMUL: case LDIV: case DDIV: case LREM: case DREM: case LAND: case LOR: case LXOR: stackSize -= 2; break; /* These pop two items off, and then push non-pointer */ case IALOAD: case FALOAD: case BALOAD: case CALOAD: case SALOAD: stackSize -= 2; goto pushInt; /* These pop two items off, and then push two non pointers */ case DALOAD: case LALOAD: stackSize -= 2; goto pushDouble; /* These pop three items off the stack. */ case PUTFIELD2_FAST: thisIP += 2; case IASTORE: case FASTORE: case AASTORE: case BASTORE: case CASTORE: case SASTORE: case LCMP: case DCMPL: case DCMPG: stackSize -= 3; break; /* These pop four items off the stack. */ case LASTORE: case DASTORE: stackSize -= 4; break; /* These either load a pointer or an integer */ case LDC: index = *thisIP++; goto handleLoadConstant; case LDC_W: index = getUShort(thisIP); thisIP += 2; handleLoadConstant: if (CONSTANTPOOL_TAG(cp, index) == CONSTANT_String) { goto pushPointer; } else { goto pushInt; } /* These involve doing bit twiddling */ case DUP: getBits(map, stackSize - 1, 1, dupValues); if (dupValues[0]) { goto pushPointer; } else { goto pushInt; } case DUP_X1: getBits(map, stackSize - 2, 2, dupValues + 1); dupValues[0] = dupValues[2]; setBits(map, stackSize - 2, 3, dupValues); stackSize++; break; case DUP_X2: getBits(map, stackSize - 3, 3, dupValues + 1); dupValues[0] = dupValues[3]; setBits(map, stackSize - 3, 4, dupValues); stackSize++; break; case DUP2: getBits(map, stackSize - 2, 2, dupValues); setBits(map, stackSize, 2, dupValues); stackSize += 2; break; case DUP2_X1: getBits(map, stackSize - 3, 3, dupValues + 2); dupValues[0] = dupValues[3]; dupValues[1] = dupValues[4]; setBits(map, stackSize - 3, 5, dupValues); stackSize += 2; break; case DUP2_X2: getBits(map, stackSize - 4, 4, dupValues + 2); dupValues[0] = dupValues[4]; dupValues[1] = dupValues[5]; setBits(map, stackSize - 4, 6, dupValues); stackSize += 2; break; case SWAP: getBits(map, stackSize - 2, 2, dupValues + 1); dupValues[0] = dupValues[2]; setBits(map, stackSize - 2, 2, dupValues); break; /* Get a field. We don't know what type of object we * are getting. */ case GETFIELD: /* Remove the pointer to the object */ stackSize -= 1; case GETSTATIC: index = getUShort(thisIP); thisIP += 2; field = (FIELD)cp->entries[index].cache; if (CONSTANTPOOL_TAG(cp, index) & CP_CACHEBIT) { field = (FIELD)cp->entries[index].cache; } else { fatalError(KVM_MSG_EXPECTED_RESOLVED_FIELD); }#if INCLUDEDEBUGCODE if (tracestackmaps) { fprintf(stdout, "\t\t"); printFieldName(field, stdout); }#endif /* Determine what needs to be pushed onto the stack, * on the basis of the flags in the field */ if (field->accessFlags & ACC_POINTER) { goto pushPointer; } else if (field->accessFlags & ACC_DOUBLE) { goto pushDouble; } else { goto pushInt; } /* Set a field value from the stack */ case PUTFIELD: /* Remove the pointer to the object */ stackSize -= 1; case PUTSTATIC: index = getUShort(thisIP); thisIP += 2; field = (FIELD)cp->entries[index].cache; if (CONSTANTPOOL_TAG(cp, index) & CP_CACHEBIT) { field = (FIELD)cp->entries[index].cache; } else { fatalError(KVM_MSG_EXPECTED_RESOLVED_FIELD); }#if INCLUDEDEBUGCODE if (tracestackmaps) { fprintf(stdout, "\t\t"); printFieldName(field, stdout); }#endif /* We are either removing a single word or two words. We * don't care if it is a pointer or not. */ stackSize -= (field->accessFlags & ACC_DOUBLE) ? 2 : 1; break; /* We remove thisIP[2] dimensions, and then we push * the result */ case MULTIANEWARRAY: case MULTIANEWARRAY_FAST: stackSize -= thisIP[2]; thisIP += 3; goto pushPointer; case WIDE: token = *thisIP++; index = getUShort(thisIP); thisIP += 2; switch (token) { case ILOAD: case FLOAD: goto pushInt; case LLOAD: case DLOAD: goto pushDouble; case ALOAD: goto pushPointer; case LSTORE: case DSTORE: goto storeDouble; case ISTORE: case FSTORE: goto storeInt; case ASTORE: goto storePointer; case IINC: thisIP += 2; break; default: /* RET shouldn't happen! */ fatalError(KVM_MSG_UNEXPECTED_BYTECODE); break; } break;#if ENABLEFASTBYTECODES case INVOKEVIRTUAL_FAST: case INVOKEINTERFACE_FAST: { unsigned int iCacheIndex = getUShort(thisIP); ICACHE thisICache = getInlineCache(iCacheIndex); method = (METHOD)thisICache->contents; thisIP += (token == INVOKEINTERFACE_FAST) ? 4 : 2; goto handleMethodCall; }#endif#if ENABLEFASTBYTECODES case INVOKESPECIAL_FAST: case INVOKESTATIC_FAST:#endif case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKESTATIC: case INVOKEINTERFACE: { unsigned int cpIndex = getUShort(thisIP); CONSTANTPOOL_ENTRY thisEntry = &cp->entries[cpIndex]; thisIP += (token == INVOKEINTERFACE) ? 4 : 2; if (CONSTANTPOOL_TAG(cp, cpIndex) & CP_CACHEBIT) { method = (METHOD)thisEntry->cache; } else { fatalError(KVM_MSG_EXPECTED_RESOLVED_METHOD); } }#if ENABLEFASTBYTECODES handleMethodCall:#endif#if INCLUDEDEBUGCODE if (tracestackmaps) { fprintf(stdout, "\t\t"); printMethodName(method, stdout); }#endif /* Remove the arguments. */ stackSize -= method->argCount; if (INCLUDEDEBUGCODE && stackSize < localsCount) { fatalError(KVM_MSG_ARGUMENT_POPPING_FAILED); } /* Push the return result */ switch (method->accessFlags & (ACC_POINTER | ACC_DOUBLE)) { case ACC_DOUBLE: goto pushDouble; case 0: /* int */ goto pushInt; case ACC_POINTER | ACC_DOUBLE: /* void */ break; case ACC_POINTER: goto pushPointer; } break;#if ENABLE_JAVA_DEBUGGER case BREAKPOINT: token = getVerifierBreakpointOpcode(thisMethod, (unsigned short)((thisIP - 1) - code)); goto again;#endif default: fatalError(KVM_MSG_UNEXPECTED_BYTECODE); } if (stackSize < localsCount) { fatalError(KVM_MSG_ILLEGAL_STACK_SIZE); }#if INCLUDEDEBUGCODE if (tracestackmaps) { extern const char* const byteCodeNames[]; printStackMap(initialIP - thisMethod->u.java.code, byteCodeNames[*initialIP], localsCount, map, stackSize); }#endif } /* end of while */ if (thisIP > targetIP) { fatalError(KVM_MSG_STRANGE_VALUE_OF_THISIP); } return stackSize - localsCount;}/*========================================================================= * FUNCTION: getInitialRegisterMask * TYPE: Important GC function * OVERVIEW: Returns a bitmap indicating the live size of the stack * INTERFACE: * parameters: thisMethod: The current method * targetOffsetP: Pointer to offset into the method for which * we want a stack map * map Map to fill in with the stack map information. * * returns: The stack size. It also fills in *map and *targetOffsetP. * * This function will determine a stack map either for *targetOffsetP or for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -