📄 evmmethodinfo.java
字号:
/* dup2_x2 */ new OpcodeInfoType(255), /* swap */ new OpcodeInfoType(255), /* iadd */ new OpcodeInfoType(opc_iadd, 2, 1), /* ladd */ new OpcodeInfoType(opc_iadd, 4, 2), /* fadd */ new OpcodeInfoType(opc_iadd, 2, 1), /* dadd */ new OpcodeInfoType(opc_iadd, 4, 2), /* isub */ new OpcodeInfoType(opc_iadd, 2, 1), /* lsub */ new OpcodeInfoType(opc_iadd, 4, 2), /* fsub */ new OpcodeInfoType(opc_iadd, 2, 1), /* dsub */ new OpcodeInfoType(opc_iadd, 4, 2), /* imul */ new OpcodeInfoType(opc_iadd, 2, 1), /* lmul */ new OpcodeInfoType(opc_iadd, 4, 2), /* fmul */ new OpcodeInfoType(opc_iadd, 2, 1), /* dmul */ new OpcodeInfoType(opc_iadd, 4, 2), /* idiv */ new OpcodeInfoType(opc_iadd, 2, 1, OpcodeInfoType.CAN_ERROR), /* ldiv */ new OpcodeInfoType(opc_iadd, 4, 2, OpcodeInfoType.CAN_ERROR), /* fdiv */ new OpcodeInfoType(opc_iadd, 2, 1), /* ddiv */ new OpcodeInfoType(opc_iadd, 4, 2), /* irem */ new OpcodeInfoType(opc_iadd, 2, 1, OpcodeInfoType.CAN_ERROR), /* lrem */ new OpcodeInfoType(opc_iadd, 4, 2, OpcodeInfoType.CAN_ERROR), /* frem */ new OpcodeInfoType(opc_iadd, 2, 1), /* drem */ new OpcodeInfoType(opc_iadd, 4, 2), /* ineg */ new OpcodeInfoType(opc_iadd, 1, 1), /* lneg */ new OpcodeInfoType(opc_iadd, 2, 2), /* fneg */ new OpcodeInfoType(opc_iadd, 1, 1), /* dneg */ new OpcodeInfoType(opc_iadd, 2, 2), /* ishl */ new OpcodeInfoType(opc_iadd, 2, 1), /* lshl */ new OpcodeInfoType(opc_iadd, 3, 2), /* ishr */ new OpcodeInfoType(opc_iadd, 2, 1), /* lshr */ new OpcodeInfoType(opc_iadd, 3, 2), /* iushr */ new OpcodeInfoType(opc_iadd, 2, 1), /* lushr */ new OpcodeInfoType(opc_iadd, 3, 2), /* iand */ new OpcodeInfoType(opc_iadd, 2, 1), /* land */ new OpcodeInfoType(opc_iadd, 4, 2), /* ior */ new OpcodeInfoType(opc_iadd, 2, 1), /* lor */ new OpcodeInfoType(opc_iadd, 4, 2), /* ixor */ new OpcodeInfoType(opc_iadd, 2, 1), /* lxor */ new OpcodeInfoType(opc_iadd, 4, 2), /* iinc */ new OpcodeInfoType(255), /* i2l */ new OpcodeInfoType(opc_iadd, 1, 2), /* i2f */ new OpcodeInfoType(opc_iadd, 1, 1), /* i2d */ new OpcodeInfoType(opc_iadd, 1, 2), /* l2i */ new OpcodeInfoType(opc_iadd, 2, 1), /* l2f */ new OpcodeInfoType(opc_iadd, 2, 1), /* l2d */ new OpcodeInfoType(opc_iadd, 2, 2), /* f2i */ new OpcodeInfoType(opc_iadd, 1, 1), /* f2l */ new OpcodeInfoType(opc_iadd, 1, 2), /* f2d */ new OpcodeInfoType(opc_iadd, 1, 2), /* d2i */ new OpcodeInfoType(opc_iadd, 2, 1), /* d2l */ new OpcodeInfoType(opc_iadd, 2, 2), /* d2f */ new OpcodeInfoType(opc_iadd, 2, 1), /* i2b */ new OpcodeInfoType(opc_iadd, 1, 1), /* i2c */ new OpcodeInfoType(opc_iadd, 1, 1), /* i2s */ new OpcodeInfoType(opc_iadd, 1, 1), /* lcmp */ new OpcodeInfoType(opc_iadd, 4, 1), /* fcmpl */ new OpcodeInfoType(opc_iadd, 2, 1), /* fcmpg */ new OpcodeInfoType(opc_iadd, 2, 1), /* dcmpl */ new OpcodeInfoType(opc_iadd, 4, 1), /* dcmpg */ new OpcodeInfoType(opc_iadd, 4, 1), /* ifeq */ new OpcodeInfoType(255), /* ifne */ new OpcodeInfoType(255), /* iflt */ new OpcodeInfoType(255), /* ifge */ new OpcodeInfoType(255), /* ifgt */ new OpcodeInfoType(255), /* ifle */ new OpcodeInfoType(255), /* if_icmpeq */ new OpcodeInfoType(255), /* if_icmpne */ new OpcodeInfoType(255), /* if_icmplt */ new OpcodeInfoType(255), /* if_icmpge */ new OpcodeInfoType(255), /* if_icmpgt */ new OpcodeInfoType(255), /* if_icmple */ new OpcodeInfoType(255), /* if_acmpeq */ new OpcodeInfoType(255), /* if_acmpne */ new OpcodeInfoType(255), /* goto */ new OpcodeInfoType(255), /* jsr */ new OpcodeInfoType(255), /* ret */ new OpcodeInfoType(255), /* tableswitch */ new OpcodeInfoType(255), /* lookupswitch */ new OpcodeInfoType(255), /* ireturn */ new OpcodeInfoType(opc_return, 1), /* lreturn */ new OpcodeInfoType(opc_return, 2), /* freturn */ new OpcodeInfoType(opc_return, 1), /* dreturn */ new OpcodeInfoType(opc_return, 2), /* areturn */ new OpcodeInfoType(opc_return, 1), /* return */ new OpcodeInfoType(opc_return, 0), /* getstatic */ new OpcodeInfoType(255), /* putstatic */ new OpcodeInfoType(255), /* getfield */ new OpcodeInfoType(255), /* putfield */ new OpcodeInfoType(255), /* invokevirtual */ new OpcodeInfoType(255), /* invokespecial */ new OpcodeInfoType(255), /* invokestatic */ new OpcodeInfoType(255), /* invokeinterface */ new OpcodeInfoType(255), /* xxxunusedxxx */ new OpcodeInfoType(255), /* new */ new OpcodeInfoType(255), /* newarray */ new OpcodeInfoType(opc_iadd, 1, 1, OpcodeInfoType.CAN_ERROR), /* anewarray */ new OpcodeInfoType(255), /* arraylength */ new OpcodeInfoType(opc_iadd, 1, 1, OpcodeInfoType.NULL_CHECK), /* athrow */ new OpcodeInfoType(opc_iadd, 1, 0, OpcodeInfoType.NULL_CHECK | OpcodeInfoType.CAN_ERROR), /* checkcast */ new OpcodeInfoType(255), /* instanceof */ new OpcodeInfoType(255), /* monitorenter */ new OpcodeInfoType(opc_iadd, 1, 0, OpcodeInfoType.NULL_CHECK | OpcodeInfoType.CAN_ERROR), /* monitorexit */ new OpcodeInfoType(opc_iadd, 1, 0, OpcodeInfoType.NULL_CHECK | OpcodeInfoType.CAN_ERROR), /* wide */ new OpcodeInfoType(255), /* multianewarray */ new OpcodeInfoType(255), /* ifnull */ new OpcodeInfoType(255), /* ifnonnull */ new OpcodeInfoType(255), /* goto_w */ new OpcodeInfoType(255), /* jsr_w */ new OpcodeInfoType(255), /* breakpoint */ new OpcodeInfoType(255) /* XXXX FY: I still need to add more info here */ }; /** * Print the code as Java assembly language instructions */ String disassembleInlining() { byte codeBytes[] = new byte[3]; // Copy inlining into codeBytes[] buffer codeBytes[0] = (byte)(inlining & 0xff); codeBytes[1] = (byte)((inlining >> 8) & 0xff); codeBytes[2] = (byte)((inlining >> 16) & 0xff); return MethodInfo.disassemble(codeBytes, 0, 3); } private String myName; public String toString() { if (myName == null) { myName = method.parent.className + "." + method.name.string + method.type.string; } return myName; } static int total = 0; // After inlining some code, we try to see if we can remove code. For // example, the frequent case of opc_aload_0 invokeingored_quick #1 T can // simply "go away" final boolean compress () { MethodInfo mb = method; boolean rewritten = false; byte[] code = mb.code; int[] stack = new int[mb.stack + 1]; int stackHeight = 0; int nextpc; java.util.BitSet targets = mb.getLabelTargets(); for (int pc = 0; pc < code.length; pc = nextpc) { nextpc = pc + mb.opcodeLength(pc); int opcode = code[pc] & 0xff; int popping = 0; boolean checkThis = false; if (targets.get(pc)) { stackHeight = 0; } stack[stackHeight] = pc; // Invariant. the stackheight at this point is stackHeight or less. // // We can pop n items from the stack (where n <= stackHeight) by // simply deleting all the code from stackHeight[n] to this point // in the code. No side effects are removed. // // Note that instructions that have a side effect should set // stackHeight = 0, to indicate that it can't be deleted. switch (opcode) { case opc_nop: case opc_ineg: case opc_fneg: case opc_i2f: case opc_f2i: case opc_i2b: case opc_i2c: case opc_i2s: case opc_newarray: case opc_anewarray_fast: case opc_instanceof_fast: case opc_lneg: case opc_dneg: case opc_l2d: case opc_d2l: // these don't change stack height, and we know as much about // the stack before as we do after. break; case opc_aconst_null: case opc_iconst_m1: case opc_iconst_0: case opc_iconst_1: case opc_iconst_2: case opc_iconst_3: case opc_iconst_4: case opc_iconst_5: case opc_fconst_0: case opc_fconst_1: case opc_fconst_2: case opc_bipush: case opc_sipush: case opc_iload: case opc_fload: case opc_aload: case opc_iload_0: case opc_iload_1: case opc_iload_2: case opc_iload_3: case opc_fload_0: case opc_fload_1: case opc_fload_2: case opc_fload_3: case opc_aload_0: case opc_aload_1: case opc_aload_2: case opc_aload_3: case opc_getstatic_fast: case opc_dup: // These push some value onto the stack, no matter what was // there before stackHeight += 1; break; case opc_lconst_0: case opc_lconst_1: case opc_dconst_0: case opc_dconst_1: case opc_lload: case opc_dload: case opc_lload_0: case opc_lload_1: case opc_lload_2: case opc_lload_3: case opc_dload_0: case opc_dload_1: case opc_dload_2: case opc_dload_3: case opc_getstatic2_fast: // These push two values onto the stack, no matter what was // there before. stackHeight += 2; break; case opc_i2l: case opc_i2d: case opc_f2l: case opc_f2d: // if we knew the top element of the stack, we know more stackHeight = (stackHeight < 1) ? 0 : stackHeight + 1; break; case opc_iadd: case opc_fadd: case opc_isub: case opc_fsub: case opc_imul: case opc_fmul: case opc_fdiv: case opc_frem: case opc_ishl: case opc_ishr: case opc_iushr: case opc_iand: case opc_ior: case opc_ixor: case opc_l2i: case opc_l2f: case opc_d2i: case opc_d2f: case opc_fcmpl: case opc_fcmpg: // if we knew the top two elements of the stack, the stack // has just shrunk stackHeight = (stackHeight < 2) ? 0 : stackHeight - 1; break; case opc_lshl: case opc_lshr: case opc_lushr: // if we knew the top three elements of the stack, we now // know the top two stackHeight = (stackHeight < 3) ? 0 : stackHeight - 1; break; case opc_lcmp: case opc_dcmpl: case opc_dcmpg: // if we knew the top 4 elements of the stack, we now // know the top element stackHeight = (stackHeight < 4) ? 0 : stackHeight - 3; break; case opc_ladd: case opc_dadd: case opc_lsub: case opc_dsub: case opc_lmul: case opc_dmul: case opc_ddiv: case opc_drem: case opc_land: case opc_lor: case opc_lxor: // if we knew the top 4 elements of the stack, we now // know the top 2 stackHeight = (stackHeight < 4) ? 0 : stackHeight - 2; break; // The dup's (other than opc_dup) deal with the stack in // a way that's not worth the hassle of dealing with. case opc_getfield_fast: case opc_arraylength: // If we throw away the result, then we just need to check that // the value is non-null. if (code[nextpc] == (byte)(opc_pop)) { checkThis = true; nextpc += 1; } else { stackHeight = 0; } break; case opc_pop2: popping++; // fall thru case opc_pop: // We have to be careful. The inliner may produce code that // does correspond to the stack. For example, it might // produce "pop pop2" to remove a double then an int. We need // to deal with series of them at once. if (stackHeight > 0) { popping++; for(;;) { opcode = code[++pc] & 0xFF; if (opcode == opc_pop) popping++; else if (opcode == opc_pop2) popping += 2; else break; } nextpc = pc; } break; case opc_invokeignored_quick: popping = code[pc + 1] & 0xff; if (code[pc + 2] != 0) { checkThis = true; popping--; } break; default: stackHeight = 0; } if (checkThis || (popping > 0 && stackHeight > 0)) { rewritten = true; if (stackHeight >= popping) { stackHeight -= popping; popping = 0; } else { popping -= stackHeight; stackHeight = 0; } int start = stack[stackHeight]; if (checkThis) { if (popping == 0 && (nextpc - start != 3)) { mb.replaceCode(start, nextpc, opc_nonnull_quick); } else { mb.replaceCode(start, nextpc, opc_invokeignored_quick, popping+1, 1); } stackHeight = 0; } else { switch (popping) { case 0: mb.replaceCode(start, nextpc); break; case 1: mb.replaceCode(start, nextpc, opc_pop); break; case 2: mb.replaceCode(start, nextpc, opc_pop2); break; default: mb.replaceCode(start, nextpc, opc_invokeignored_quick, popping, 0); break; } } } } return rewritten; }}/** * Class used for inlining info. See inlining code in MethodInfo */class OpcodeInfoType { int opcode; // really the opcode type int inStack; int outStack; static final int CAN_ERROR = 0x01; /* can give error in addition to NULL_CHECK */ static final int NULL_CHECK = 0x02; /* checks that first arg isn't null */ static final int CONSTANT_POOL = 0x04; /* uses the constant pool */ int flags; OpcodeInfoType(int opcode, int inStack, int outStack, int flags) { this.opcode = opcode; this.inStack = inStack; this.outStack = outStack; this.flags = flags; } OpcodeInfoType(int opcode, int inStack, int outStack) { this(opcode, inStack, outStack, 0); } OpcodeInfoType(int opcode, int inStack) { this(opcode, inStack, 0, 0); } OpcodeInfoType(int opcode) { this(opcode, 0, 0, 0); }};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -