📄 codeattr.java
字号:
{ emitGotoIfCompare2(label, 157); } public final void emitGotoIfLe(Label label) { emitGotoIfCompare2(label, 158); } /** Compile start of a conditional: * <tt>if (!(<var>x</var> opcode 0)) ...</tt>. * The value of <var>x</var> must already have been pushed. */ public final void emitIfCompare1 (int opcode) { IfState new_if = new IfState(this); if (popType().promote() != Type.int_type) throw new Error ("non-int type to emitIfCompare1"); reserve(3); emitTransfer (new_if.end_label, opcode); new_if.start_stack_size = SP; } /** Compile start of conditional: <tt>if (x != 0) ...</tt>. * Also use this if you have pushed a boolean value: if (b) ... */ public final void emitIfIntNotZero() { emitIfCompare1(153); // ifeq } /** Compile start of conditional: <tt>if (x == 0) ...</tt>. * Also use this if you have pushed a boolean value: if (!b) ... */ public final void emitIfIntEqZero() { emitIfCompare1(154); // ifne } /** Compile start of conditional: <tt>if (x <= 0)</tt>. */ public final void emitIfIntLEqZero() { emitIfCompare1(157); // ifgt } /** Compile start of a conditional: <tt>if (!(x opcode null)) ...</tt>. * The value of <tt>x</tt> must already have been pushed and must be of * reference type. */ public final void emitIfRefCompare1 (int opcode) { IfState new_if = new IfState(this); if (! (popType() instanceof ObjectType)) throw new Error ("non-ref type to emitIfRefCompare1"); reserve(3); emitTransfer (new_if.end_label, opcode); new_if.start_stack_size = SP; } /** Compile start of conditional: if (x != null) */ public final void emitIfNotNull() { emitIfRefCompare1(198); // ifnull } /** Compile start of conditional: if (x == null) */ public final void emitIfNull() { emitIfRefCompare1(199); // ifnonnull } /** Compile start of a conditional: if (!(x OPCODE y)) ... * The value of x and y must already have been pushed. */ public final void emitIfIntCompare(int opcode) { IfState new_if = new IfState(this); popType(); popType(); reserve(3); emitTransfer(new_if.end_label, opcode); new_if.start_stack_size = SP; } /* Compile start of a conditional: if (x < y) ... */ public final void emitIfIntLt() { emitIfIntCompare(162); // if_icmpge } /** Compile start of a conditional: if (x != y) ... * The values of x and y must already have been pushed. */ public final void emitIfNEq () { IfState new_if = new IfState (this); emitGotoIfEq(new_if.end_label); new_if.start_stack_size = SP; } /** Compile start of a conditional: if (x == y) ... * The values of x and y must already have been pushed. */ public final void emitIfEq () { IfState new_if = new IfState (this); emitGotoIfNE(new_if.end_label); new_if.start_stack_size = SP; } /** Compile start of a conditional: if (x < y) ... * The values of x and y must already have been pushed. */ public final void emitIfLt () { IfState new_if = new IfState (this); emitGotoIfGe(new_if.end_label); new_if.start_stack_size = SP; } /** Compile start of a conditional: if (x >= y) ... * The values of x and y must already have been pushed. */ public final void emitIfGe () { IfState new_if = new IfState (this); emitGotoIfLt(new_if.end_label); new_if.start_stack_size = SP; } /** Compile start of a conditional: if (x > y) ... * The values of x and y must already have been pushed. */ public final void emitIfGt () { IfState new_if = new IfState (this); emitGotoIfLe(new_if.end_label); new_if.start_stack_size = SP; } /** Compile start of a conditional: if (x <= y) ... * The values of x and y must already have been pushed. */ public final void emitIfLe () { IfState new_if = new IfState (this); emitGotoIfGt(new_if.end_label); new_if.start_stack_size = SP; } /** Emit a 'ret' instruction. * @param var the variable containing the return address */ public void emitRet (Variable var) { int offset = var.offset; if (offset < 256) { reserve(2); put1(169); // ret put1(offset); } else { reserve(4); put1(196); // wide put1(169); // ret put2(offset); } } public final void emitThen() { if_stack.start_stack_size = SP; } public final void emitIfThen () { new IfState(this, null); } /** Compile start of else clause. */ public final void emitElse () { Label else_label = if_stack.end_label; Label end_label = new Label (this); if_stack.end_label = end_label; if (reachableHere ()) { int growth = SP-if_stack.start_stack_size; if_stack.stack_growth = growth; if (growth > 0) { if_stack.then_stacked_types = new Type[growth]; System.arraycopy (stack_types, if_stack.start_stack_size, if_stack.then_stacked_types, 0, growth); } else if_stack.then_stacked_types = new Type[0]; // ??? emitGoto (end_label); } while (SP > if_stack.start_stack_size) popType(); SP = if_stack.start_stack_size; if (else_label != null) else_label.define (this); if_stack.doing_else = true; } /** Compile end of conditional. */ public final void emitFi () { boolean make_unreachable = false; if (! if_stack.doing_else) { // There was no 'else' clause. if (reachableHere () && SP != if_stack.start_stack_size) throw new Error("at PC "+PC+" then clause grows stack with no else clause"); } else if (if_stack.then_stacked_types != null) { int then_clause_stack_size = if_stack.start_stack_size + if_stack.stack_growth; if (! reachableHere ()) { if (if_stack.stack_growth > 0) System.arraycopy (if_stack.then_stacked_types, 0, stack_types, if_stack.start_stack_size, if_stack.stack_growth); SP = then_clause_stack_size; } else if (SP != then_clause_stack_size) throw new Error("at PC "+PC+": SP at end of 'then' was " + then_clause_stack_size + " while SP at end of 'else' was " + SP); } else if (unreachable_here) make_unreachable = true; if (if_stack.end_label != null) if_stack.end_label.define (this); if (make_unreachable) setUnreachable(); // Pop the if_stack. if_stack = if_stack.previous; } public final void emitConvert (Type from, Type to) { String to_sig = to.getSignature(); String from_sig = from.getSignature(); int op = -1; if (to_sig.length() == 1 || from_sig.length() == 1) { char to_sig0 = to_sig.charAt(0); char from_sig0 = from_sig.charAt(0); if (from_sig0 == to_sig0) return; if (from.size < 4) from_sig0 = 'I'; if (to.size < 4) { emitConvert(from, Type.int_type); from_sig0 = 'I'; } if (from_sig0 == to_sig0) return; switch (from_sig0) { case 'I': switch (to_sig0) { case 'B': op = 145; break; // i2b case 'C': op = 146; break; // i2c case 'S': op = 147; break; // i2s case 'J': op = 133; break; // i2l case 'F': op = 134; break; // i2f case 'D': op = 135; break; // i2d } break; case 'J': switch (to_sig0) { case 'I': op = 136; break; // l2i case 'F': op = 137; break; // l2f case 'D': op = 138; break; // l2d } break; case 'F': switch (to_sig0) { case 'I': op = 139; break; // f2i case 'J': op = 140; break; // f2l case 'D': op = 141; break; // f2d } break; case 'D': switch (to_sig0) { case 'I': op = 142; break; // d2i case 'J': op = 143; break; // d2l case 'F': op = 144; break; // d2f } break; } } if (op < 0) throw new Error ("unsupported CodeAttr.emitConvert"); reserve(1); popType(); put1(op); pushType(to); } private void emitCheckcast (Type type, int opcode) { reserve(3); popType(); put1(opcode); if (type instanceof ArrayType) { ArrayType atype = (ArrayType) type; CpoolUtf8 name = getConstants().addUtf8(atype.signature); putIndex2(getConstants().addClass(name)); } else if (type instanceof ClassType) { putIndex2(getConstants().addClass((ClassType) type)); } else throw new Error ("unimplemented type " + type + " in emitCheckcast/emitInstanceof"); } public void emitCheckcast (Type type) { if (type instanceof ClassType) { Type top = topType(); if (top instanceof ClassType && ((ClassType) top).isSubclass((ClassType) type)) return; } emitCheckcast(type, 192); pushType(type); } public void emitInstanceof (Type type) { emitCheckcast(type, 193); pushType(Type.boolean_type); } public final void emitThrow () { popType(); reserve(1); put1 (191); // athrow setUnreachable(); } public final void emitMonitorEnter () { popType(); reserve(1); put1 (194); // monitorenter } public final void emitMonitorExit () { popType(); reserve(1); put1 (195); // monitorexit } /** Call pending finalizer functions. * @param limit Only call finalizers more recent than this. */ public void doPendingFinalizers (TryState limit) { TryState stack = try_stack; /* If a value is returned, it must be saved to a local variable, to prevent a verification error because of inconsistent stack sizes. */ boolean saveResult = ! getMethod().getReturnType().isVoid(); Variable result = null; while (stack != limit) { if (stack.finally_subr != null // there is a finally block && stack.finally_ret_addr == null) // 'return' is not inside it { if (saveResult && result == null) { result = addLocal(topType()); emitStore(result); } emitJsr(stack.finally_subr); } stack = stack.previous; } if (result != null) emitLoad(result); // We'd like to do freeLocal on the result Variable, but then we risk // it being re-used in a finalizer, which would trash its value. We // don't have any convenient way to to do that (the pending Scope // mechanism is over-kill), we for now we just leak the Variable. } /** * Compile a method return. * If inside a 'catch' clause, first call 'finally' clauses. * The return value (unless the return type is void) must be on the stack, * and have the correct type. */ public final void emitReturn () { doPendingFinalizers(null); if (getMethod().getReturnType().size == 0) { reserve(1); put1(177); // return } else emitTypedOp (172, popType().promote()); setUnreachable(); } /** Add an exception handler. */ public void addHandler (int start_pc, int end_pc, int handler_pc, int catch_type) { int index = 4 * exception_table_length; if (exception_table == null) { exception_table = new short[20]; } else if (exception_table.length <= index) { short[] new_table = new short[2 * exception_table.length]; System.arraycopy(exception_table, 0, new_table, 0, index); exception_table = new_table; } exception_table[index++] = (short) start_pc; exception_table[index++] = (short) end_pc; exception_table[index++] = (short) handler_pc; exception_table[index++] = (short) catch_type; exception_table_length++; } /** Add an exception handler. */ public void addHandler (Label start_try, Label end_try, ClassType catch_type) { ConstantPool constants = getConstants(); int catch_type_index; if (catch_type == null) catch_type_index = 0; else catch_type_index = constants.addClass(catch_type).index; fixupAdd(FIXUP_TRY, start_try); fixupAdd(FIXUP_CATCH, catch_type_index, end_try); } /** Beginning of code that has a cleanup handler. * This is similar to a try-finally, but the cleanup is only * done in the case of an exception. Alternatively, the try clause * has to manually do the cleanup with code duplication. * Equivalent to: <code>try <var>body</var> catch (Throwable ex) { <var>cleanup</var>; throw ex; }</code> * Call <code>emitWithCleanupStart</code> before the <code><var>body</var></code>. */ public void emitWithCleanupStart () { new TryState(this); } /** Called after a <code><var>body</var></code> that has a <code><var>cleanup</var></code> clause. * Followed by the <code><var>cleanup</var></code> code. */ public void emitWithCleanupCatch (Variable catchVar) { emitTryEnd(); try_stack.saved_result = catchVar; int save_SP = SP; emitCatchStart(catchVar); // Don't trash stack_types, and set things up so the SP has the // right value after emitWithCleanupDone (assuming the handler leaves // the stack empty after the throw). The + 1 for the incoming exception. SP = save_SP + 1; } /** Called after generating a <code><var>cleanup</var></code> handler. */ public void emitWithCleanupDone () { Variable catchVar = try_stack.saved_result; try_stack.saved_result = null; if (catchVar != null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -