📄 evmmethodinfo.java
字号:
result = makeOpcodeResult(checkThis, nextReg, opPtr.inStack, 2, opcode, code[pc+1] & 0xff, 0); break; case 3: result = makeOpcodeResult(checkThis, nextReg, opPtr.inStack, 3, opcode, code[pc+1] & 0xff, code[pc+2] & 0xff); break; default: throw new RuntimeException("sysAssert(FALSE);"); // result = NO_INLINE_FLAG; // not reached // break; // not reached } if ((result & NO_INLINE_FLAG) == 0) { if ((opPtr.flags & OpcodeInfoType.CONSTANT_POOL) != 0) result |= SAME_CLASS_FLAG; if (redoInlining) result |= REDO_INLINING_FLAG; } return result; } default: throw new RuntimeException("sysAssert(FALSE);"); case 255: /* random instruction */ return NO_INLINE_FLAG; } /* of switch statement */ } /* end of for loop */ } /* This method is called to create the code that is actually going to * replace the indicated method, when the method does nothing, or when * it simply returns one of its arguments. * * It takes the following arguments: * mb: Method we are examining * checkThis: If true, We must specially check that the first argument * "this" isn't null. * highReg, One greater than the highest register on the stack when * the return or Xreturn is called. * returnSize Size of the return (0 for return, 1 for ireturn, * 2 for lreturn, etc); * * We have to emulate the method call in 3 bytes. At the time the * method is called, the arguments reg[0] . . . reg[mb->args_size - 1] * are pushed on the stack. */ static int[] poppers = { opc_nop, opc_pop, opc_pop2 }; private int makeReturnResult(boolean checkThis, int highReg, int returnSize) { MethodInfo mb = method; int argsSize = mb.argsSize; if (returnSize == 0) { /* Return void */ return MAKE_INLINING(opc_invokeignored_quick, argsSize, (checkThis ? 1 : 0)); } else { /* Return some value from the stack */ int returnReg = highReg - returnSize; int excessArgs = argsSize - returnSize - returnReg; // sysAssert(returnReg >= 0 && returnSize >= 0); if (returnReg == 0) { /* Returning reg0 or reg0/reg1 */ if (checkThis) { /* Must be returning reg0, which is also checked. We * require argsSize >= 2 (which is the same thing as * excessArgs >= 1), because otherwise the "dup" might * overflow the stack. More sophisticated inliners * might see if there is space on the caller's stack. */ // sysAssert(returnSize == 1); if (argsSize < 2) { return NO_INLINE_FLAG; } else if (excessArgs > 2) { return NO_INLINE_FLAG; } else { return MAKE_INLINING(poppers[excessArgs], opc_dup, opc_nonnull_quick); } } else { /* We're returning reg0 or reg0/reg1 which isn't null * checked. We just pop extraneous stuff off the stack * */ return MAKE_INLINING(opc_invokeignored_quick, excessArgs, 0); } } else { /* At this point, returnReg > 0. We're returning something * other than the bottom of the stack. */ if (returnSize == 1 && returnReg == 1) { if (excessArgs > 2) { return NO_INLINE_FLAG; } return MAKE_INLINING(poppers[excessArgs], opc_swap, checkThis ? opc_nonnull_quick : opc_pop); } return NO_INLINE_FLAG; } } } /* This method is called to create the code that is actually going to * replace the indicated method * * makeOpcodeResult is used to create a inlining that can be used anywhere * It takes the following arguments: * * mb: Method we are examining * checkThis: If true, We must specially check that the first argument * "this" isn't null. This condition is >>NOT<< tested by * the generated code. * nextReg: In the emulation, the highest register on the stack is * reg[nextReg - 1]. * icount The number of bytes of instructions that follow. * opcode, op1, op2 * The bytes of instruction. * * We have to emulate the method call in 3 bytes. At the time the * method is called, the arguments reg[0] . . . reg[mb->args_size - 1] * are pushed on the stack. So in three bytes, we have to: * Remove any excess arguments from the stack. * Perform the operation on the indicated stack registers * Remove any objects lower down on the stack (this is hard!) * Make sure that reg[0] is checked for being non-null, if necessary. */ private int makeOpcodeResult(boolean checkThis, int nextReg, int opcodeArgCount, int icount, int opcode, int op1, int op2) { MethodInfo mb = method; int firstReg = (opcodeArgCount == 0) ? 0 : nextReg - opcodeArgCount; // sysAssert(firstReg >= 0 && opcodeArgCount >= 0 && icount > 0); if (firstReg > 0) { /* There are extra registers at the bottom of the stack */ return makePoppingResult(checkThis, firstReg, opcodeArgCount, icount, opcode, op1, op2); } else { /* No extra registers at bottom of stack */ int argsSize = mb.argsSize; int excessArgs = argsSize - opcodeArgCount; /* extra at top */ int popSpace = 3 - icount; /* space to pop args at top */ int result = 0; int i; if (checkThis) { /* Unless this is a constant method that ignores all of its * arguments, we don't really have any way of checking * register 0 if the instructions doesn't. If it is a * constant instruction, deduct one from both popSpace and * from excessArgs, since we are popping that last argument * when an opc_nonnull_quick; */ if (opcodeArgCount > 0 || popSpace == 0) return NO_INLINE_FLAG; popSpace--; excessArgs--; // sysAssert(excessArgs >= 0); } if (excessArgs > 2 * popSpace) return NO_INLINE_FLAG; for (i = 0; i < popSpace; i++) { /* If excessArgs <= popSpace, the following generates excessArgs * "pops" followed by nops. Otherwise, it generates * excessArgs - popSpace pop2's followed by pop's. */ int opcodeTmp = (excessArgs <= i) ? opc_nop : (excessArgs <= popSpace + i) ? opc_pop : opc_pop2; result |= (opcodeTmp << (i << 3)); } if (checkThis) result |= opc_nonnull_quick << ((i++) << 3); // sysAssert(i + icount == 3); switch (icount) { case 3: result |= op2 << ((i + 2) << 3); case 2: result |= op1 << ((i + 1) << 3); case 1: result |= opcode << ((i + 0) << 3); } return result; } } /* * Called by makeOpcodeResult. * Same arguments. But there are extra arguments on the bottom to pop. */ private int makePoppingResult(boolean checkThis, int firstReg, int opcodeArgCount, int icount, int opcode, int op1, int op2) { MethodInfo mb = method; int argsSize = mb.argsSize; int excessArgs = argsSize - opcodeArgCount - firstReg; /* extra on top*/ if (icount > 1) /* We're just not prepared to deal with this. */ return NO_INLINE_FLAG; if (OpcodeInfo[opcode].outStack == 0) { int result = 0; /* Something like an array store, that leaves no value on the stack */ int i = 0; /* We can't deal with checkThis, since it might reverse the order of * an exception. We have a total of two instructions to do all the * pre and post popping. */ if (checkThis || ((excessArgs + 1)/2 + (firstReg + 1)/2) > 2) return NO_INLINE_FLAG; for (; excessArgs > 0; excessArgs -=2) /* pre popping */ result |= (excessArgs == 1 ? opc_pop : opc_pop2) << ((i++) << 3); result |= opcode << ((i++) << 3); for (; firstReg > 0; firstReg -=2) /* post popping */ result |= (firstReg == 1 ? opc_pop : opc_pop2) << ((i++) << 3); while (i < 3) result |= opc_nop << ((i++) << 3); return result; } if (excessArgs > 0 || firstReg > 1) /* We can't both do useful work and remove more than this many * items from the stack. */ return NO_INLINE_FLAG; if (opcodeArgCount == 1) { return MAKE_INLINING(opc_swap, checkThis ? opc_nonnull_quick : opc_pop, opcode); } if ( ((OpcodeInfo[opcode].flags & (OpcodeInfoType.NULL_CHECK | OpcodeInfoType.CAN_ERROR)) == 0) && (OpcodeInfo[opcode].outStack == 1)) { /* The result creates one thing on the stack, and it can't error */ return MAKE_INLINING(opcode, opc_swap, checkThis ? opc_nonnull_quick : opc_pop); } return NO_INLINE_FLAG; } private static boolean isXreturn(int opcode) { return (opcode >= opc_ireturn) && (opcode <= opc_areturn); } private static byte INLINING_WORD1(int simp) { return (byte) (simp & 0xFF); } private static byte INLINING_WORD2(int simp) { return (byte) ((simp >> 8) & 0xFF); } private static byte INLINING_WORD3(int simp) { return (byte) ((simp >> 16) & 0xFF); } private static int MAKE_INLINING(int op1, int op2, int op3) { return (op1 << 0) + (op2 << 8) + (op3 << 16); } private static int REGSIZE(OpcodeInfoType ptr) { return (ptr.inStack); } private static int REGNUM(OpcodeInfoType ptr) { return (ptr.outStack); } static OpcodeInfoType[] OpcodeInfo = { /* { opc_pop <number of words to pop from stack> } * { opc_iadd <words popped from stack> <words pushed to stack> } * { opc_iload <words pushed to stack> } * { opc_iload_0 <words pushed to stack> <implicit register> } * { opc_return <words returned> } * 255 indicates opcode that we can't inline * other values are special opcodes that must be handled specially */ /* nop */ new OpcodeInfoType(opc_pop, 0), /* aconst_null */ new OpcodeInfoType(opc_iadd, 0, 1), /* iconst_m1 */ new OpcodeInfoType(opc_iadd, 0, 1), /* iconst_0 */ new OpcodeInfoType(opc_iadd, 0, 1), /* iconst_1 */ new OpcodeInfoType(opc_iadd, 0, 1), /* iconst_2 */ new OpcodeInfoType(opc_iadd, 0, 1), /* iconst_3 */ new OpcodeInfoType(opc_iadd, 0, 1), /* iconst_4 */ new OpcodeInfoType(opc_iadd, 0, 1), /* iconst_5 */ new OpcodeInfoType(opc_iadd, 0, 1), /* lconst_0 */ new OpcodeInfoType(opc_iadd, 0, 2), /* lconst_1 */ new OpcodeInfoType(opc_iadd, 0, 2), /* fconst_0 */ new OpcodeInfoType(opc_iadd, 0, 1), /* fconst_1 */ new OpcodeInfoType(opc_iadd, 0, 1), /* fconst_2 */ new OpcodeInfoType(opc_iadd, 0, 1), /* dconst_0 */ new OpcodeInfoType(opc_iadd, 0, 2), /* dconst_1 */ new OpcodeInfoType(opc_iadd, 0, 2), /* bipush */ new OpcodeInfoType(opc_iadd, 0, 1), /* sipush */ new OpcodeInfoType(opc_iadd, 0, 1), /* ldc */ new OpcodeInfoType(255), /* ldc_w */ new OpcodeInfoType(255), /* ldc2_w */ new OpcodeInfoType(255), /* iload */ new OpcodeInfoType(opc_iload, 1), /* lload */ new OpcodeInfoType(opc_iload, 2), /* fload */ new OpcodeInfoType(opc_iload, 1), /* dload */ new OpcodeInfoType(opc_iload, 2), /* aload */ new OpcodeInfoType(opc_iload, 1), /* iload_0 */ new OpcodeInfoType(opc_iload_0, 1, 0), /* iload_1 */ new OpcodeInfoType(opc_iload_0, 1, 1), /* iload_2 */ new OpcodeInfoType(opc_iload_0, 1, 2), /* iload_3 */ new OpcodeInfoType(opc_iload_0, 1, 3), /* lload_0 */ new OpcodeInfoType(opc_iload_0, 2, 0), /* lload_1 */ new OpcodeInfoType(opc_iload_0, 2, 1), /* lload_2 */ new OpcodeInfoType(opc_iload_0, 2, 2), /* lload_3 */ new OpcodeInfoType(opc_iload_0, 2, 3), /* fload_0 */ new OpcodeInfoType(opc_iload_0, 1, 0), /* fload_1 */ new OpcodeInfoType(opc_iload_0, 1, 1), /* fload_2 */ new OpcodeInfoType(opc_iload_0, 1, 2), /* fload_3 */ new OpcodeInfoType(opc_iload_0, 1, 3), /* dload_0 */ new OpcodeInfoType(opc_iload_0, 2, 0), /* dload_1 */ new OpcodeInfoType(opc_iload_0, 2, 1), /* dload_2 */ new OpcodeInfoType(opc_iload_0, 2, 2), /* dload_3 */ new OpcodeInfoType(opc_iload_0, 2, 3), /* aload_0 */ new OpcodeInfoType(opc_iload_0, 1, 0), /* aload_1 */ new OpcodeInfoType(opc_iload_0, 1, 1), /* aload_2 */ new OpcodeInfoType(opc_iload_0, 1, 2), /* aload_3 */ new OpcodeInfoType(opc_iload_0, 1, 3), /* iaload */ new OpcodeInfoType(opc_iadd, 2, 1, OpcodeInfoType.NULL_CHECK), /* laload */ new OpcodeInfoType(opc_iadd, 2, 2, OpcodeInfoType.NULL_CHECK), /* faload */ new OpcodeInfoType(opc_iadd, 2, 1, OpcodeInfoType.NULL_CHECK), /* daload */ new OpcodeInfoType(opc_iadd, 2, 2, OpcodeInfoType.NULL_CHECK), /* aaload */ new OpcodeInfoType(opc_iadd, 2, 1, OpcodeInfoType.NULL_CHECK), /* baload */ new OpcodeInfoType(opc_iadd, 2, 1, OpcodeInfoType.NULL_CHECK), /* caload */ new OpcodeInfoType(opc_iadd, 2, 1, OpcodeInfoType.NULL_CHECK), /* saload */ new OpcodeInfoType(opc_iadd, 2, 1, OpcodeInfoType.NULL_CHECK), /* istore */ new OpcodeInfoType(255), /* lstore */ new OpcodeInfoType(255), /* fstore */ new OpcodeInfoType(255), /* dstore */ new OpcodeInfoType(255), /* astore */ new OpcodeInfoType(255), /* istore_0 */ new OpcodeInfoType(255), /* istore_1 */ new OpcodeInfoType(255), /* istore_2 */ new OpcodeInfoType(255), /* istore_3 */ new OpcodeInfoType(255), /* lstore_0 */ new OpcodeInfoType(255), /* lstore_1 */ new OpcodeInfoType(255), /* lstore_2 */ new OpcodeInfoType(255), /* lstore_3 */ new OpcodeInfoType(255), /* fstore_0 */ new OpcodeInfoType(255), /* fstore_1 */ new OpcodeInfoType(255), /* fstore_2 */ new OpcodeInfoType(255), /* fstore_3 */ new OpcodeInfoType(255), /* dstore_0 */ new OpcodeInfoType(255), /* dstore_1 */ new OpcodeInfoType(255), /* dstore_2 */ new OpcodeInfoType(255), /* dstore_3 */ new OpcodeInfoType(255), /* astore_0 */ new OpcodeInfoType(255), /* astore_1 */ new OpcodeInfoType(255), /* astore_2 */ new OpcodeInfoType(255), /* astore_3 */ new OpcodeInfoType(255), /* iastore */ new OpcodeInfoType(opc_iadd, 3, 0, OpcodeInfoType.NULL_CHECK), /* lastore */ new OpcodeInfoType(opc_iadd, 4, 0, OpcodeInfoType.NULL_CHECK), /* fastore */ new OpcodeInfoType(opc_iadd, 3, 0, OpcodeInfoType.NULL_CHECK), /* dastore */ new OpcodeInfoType(opc_iadd, 4, 0, OpcodeInfoType.NULL_CHECK), /* aastore */ new OpcodeInfoType(opc_iadd, 3, 0, OpcodeInfoType.NULL_CHECK), /* bastore */ new OpcodeInfoType(opc_iadd, 3, 0, OpcodeInfoType.NULL_CHECK), /* castore */ new OpcodeInfoType(opc_iadd, 3, 0, OpcodeInfoType.NULL_CHECK), /* sastore */ new OpcodeInfoType(opc_iadd, 3, 0, OpcodeInfoType.NULL_CHECK), /* pop */ new OpcodeInfoType(opc_pop, 1), /* pop2 */ new OpcodeInfoType(opc_pop, 2), /* dup */ new OpcodeInfoType(255), /* dup_x1 */ new OpcodeInfoType(255), /* dup_x2 */ new OpcodeInfoType(255), /* dup2 */ new OpcodeInfoType(255), /* dup2_x1 */ new OpcodeInfoType(255),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -