📄 codeattr.java
字号:
public void emitArrayStore (Type element_type) { popType(); // Pop new value popType(); // Pop index popType(); // Pop array reference emitTypedOp(79, element_type); } /** Load an element from an array. * Must already have pushed the array and the index (in that order): * Stack: ..., array, index => ..., value */ public void emitArrayLoad (Type element_type) { popType(); // Pop index popType(); // Pop array reference emitTypedOp(46, element_type); pushType(element_type); } /** * Invoke new on a class type. * Does not call the constructor! * @param type the desired new object type */ public void emitNew (ClassType type) { reserve(3); put1(187); // new putIndex2(getConstants().addClass(type)); pushType(type); } /** Compile code to allocate a new array. * The size shold have been already pushed on the stack. * @param type type of the array elements */ public void emitNewArray (Type element_type) { popType(); if (element_type instanceof PrimType) { int code; switch (element_type.getSignature().charAt(0)) { case 'B': code = 8; break; case 'S': code = 9; break; case 'I': code = 10; break; case 'J': code = 11; break; case 'F': code = 6; break; case 'D': code = 7; break; case 'Z': code = 4; break; case 'C': code = 5; break; default: throw new Error("bad PrimType in emitNewArray"); } emitNewArray(code); } else if (element_type instanceof ClassType) { reserve(3); put1(189); // anewarray putIndex2(getConstants().addClass((ClassType) element_type)); } else throw new Error ("unimplemented type in emitNewArray"); pushType(Type.pointer_type); } private void emitBinop (int base_code) { Type type2 = popType().promote(); Type type1_raw = popType(); Type type1 = type1_raw.promote(); if (type1 != type2 || ! (type1 instanceof PrimType)) throw new Error ("non-matching or bad types in binary operation"); emitTypedOp(base_code, type1); pushType(type1_raw); } // public final void emitIntAdd () { put1(96); popType();} // public final void emitLongAdd () { put1(97); popType();} // public final void emitFloatAdd () { put1(98); popType();} // public final void emitDoubleAdd () { put1(99); popType();} public final void emitAdd () { emitBinop (96); } public final void emitSub () { emitBinop (100); } public final void emitMul () { emitBinop (104); } public final void emitDiv () { emitBinop (108); } public final void emitRem () { emitBinop (112); } public final void emitAnd () { emitBinop (126); } public final void emitIOr () { emitBinop (128); } public final void emitXOr () { emitBinop (130); } public final void emitNot() { Type type = topType(); // Must be int or long. emitPushConstant(1, type); emitAdd(); emitPushConstant(1, type); emitAnd(); } public void emitPrimop (int opcode, int arg_count, Type retType) { reserve(1); while (-- arg_count >= 0) popType(); put1(opcode); pushType(retType); } /** * Comple code to push the contents of a local variable onto the statck. * @param var The variable whose contents we want to push. */ public final void emitLoad (Variable var) { if (var.dead()) throw new Error("attempting to push dead variable"); int offset = var.offset; if (offset < 0 || !var.isSimple()) throw new Error ("attempting to load from unassigned variable "+var +" simple:"+var.isSimple()+", offset: "+offset); Type type = var.getType().promote(); reserve(4); int kind = adjustTypedOp(type); if (offset <= 3) put1(26 + 4 * kind + offset); // [ilfda]load_[0123] else { if (offset >= 256) { put1(196); // wide put1(offset >> 8); } put1(21 + kind); // [ilfda]load put1(offset); } pushType(var.getType()); } public void emitStore (Variable var) { if (var.dead ()) throw new Error ("attempting to push dead variable"); int offset = var.offset; if (offset < 0 || !var.isSimple ()) throw new Error ("attempting to store in unassigned variable"); Type type = var.getType().promote (); reserve(4); popType(); int kind = adjustTypedOp(type); if (offset <= 3) put1(59 + 4 * kind + offset); // [ilfda]store_[0123] else { if (offset >= 256) { put1(196); // wide put1(offset >> 8); } put1(54 + kind); // [ilfda]store put1(offset); } } private final void emitFieldop (Field field, int opcode) { reserve(3); put1(opcode); putIndex2(getConstants().addFieldRef(field)); } /** Compile code to get a static field value. * Stack: ... => ..., value */ public final void emitGetStatic(Field field) { pushType(field.type); emitFieldop (field, 178); // getstatic } /** Compile code to get a non-static field value. * Stack: ..., objectref => ..., value */ public final void emitGetField(Field field) { popType(); pushType(field.type); emitFieldop(field, 180); // getfield } /** Compile code to put a static field value. * Stack: ..., value => ... */ public final void emitPutStatic (Field field) { popType(); emitFieldop(field, 179); // putstatic } /** Compile code to put a non-static field value. * Stack: ..., objectref, value => ... */ public final void emitPutField (Field field) { popType(); popType(); emitFieldop(field, 181); // putfield } public void emitInvokeMethod (Method method, int opcode) { reserve(opcode == 185 ? 5 : 3); int arg_count = method.arg_types.length; boolean is_invokestatic = opcode == 184; if (is_invokestatic != ((method.access_flags & Access.STATIC) != 0)) throw new Error ("emitInvokeXxx static flag mis-match method.flags="+method.access_flags); if (!is_invokestatic) arg_count++; put1(opcode); // invokevirtual, invokespecial, or invokestatic putIndex2(getConstants().addMethodRef(method)); if (opcode == 185) // invokeinterface { put1(arg_count); put1(0); } while (--arg_count >= 0) popType(); if (method.return_type != Type.void_type) pushType(method.return_type); } /** Compile a virtual method call. * The stack contains the 'this' object, followed by the arguments in order. * @param method the method to invoke virtually */ public void emitInvokeVirtual (Method method) { emitInvokeMethod(method, 182); // invokevirtual } public void emitInvokeSpecial (Method method) { emitInvokeMethod(method, 183); // invokespecial } /** Compile a static method call. * The stack contains the the arguments in order. * @param method the static method to invoke */ public void emitInvokeStatic (Method method) { emitInvokeMethod(method, 184); // invokestatic } final void emitTransfer (Label label, int opcode) { put1(opcode); label.emit(this); } /** Compile an unconditional branch (goto) or a jsr. * @param label target of the branch (must be in this method). */ public final void emitGoto (Label label, int opcode) { reserve(5); if (label.defined ()) { readPC = PC; int delta = label.position - PC; if (delta < -32768) { put1(opcode-167); // goto_w or jsr_w put4(delta); } else { put1(opcode); // goto or jsr put2(delta); } } else emitTransfer (label, opcode); // goto label or jsr label } /** Compile an unconditional branch (goto). * @param label target of the branch (must be in this method). */ public final void emitGoto (Label label) { emitGoto(label, 167); unreachable_here = true; } //public final void compile_goto_ifeq (Label label, boolean invert) public final void emitGotoIfEq (Label label, boolean invert) { Type type2 = popType().promote(); Type type1 = popType().promote(); reserve(4); int opcode; char sig1 = type1.getSignature().charAt(0); char sig2 = type2.getSignature().charAt(0); if (sig1 == 'I' && sig2 == 'I') opcode = 159; // if_cmpeq (inverted: if_icmpne) else if (sig1 == 'J' && sig2 == 'J') { put1(148); // lcmp opcode = 153; // ifeq (inverted: ifeq) } else if (sig1 == 'F' && sig2 == 'F') { put1(149); // fcmpl opcode = 153; // ifeq (inverted: ifeq) } else if (sig1 == 'D' && sig2 == 'D') { put1(149); // fcmpl opcode = 153; // ifeq (inverted: ifeq) } else if ((sig1 == 'L' || sig1 == '[') && (sig2 == 'L' || sig2 == '[')) opcode = 165; // if_acmpeq (inverted: if_acmpne) else throw new Error ("non-matching types to compile_goto_ifeq"); if (invert) opcode++; emitTransfer (label, opcode); } /** Compile a conditional transfer if 2 top stack elements are equal. */ public final void emitGotoIfEq (Label label) { emitGotoIfEq(label, false); } /** Compile conditional transfer if 2 top stack elements are not equal. */ public final void emitGotoIfNE (Label label) { emitGotoIfEq(label, true); } public final void emitGotoIfCompare1 (Label label, int opcode) { popType(); reserve(3); emitTransfer (label, opcode); } public final void emitGotoIfIntEqZero(Label label) { emitGotoIfCompare1(label, 153); } public final void emitGotoIfIntNeZero(Label label) { emitGotoIfCompare1(label, 154); } public final void emitGotoIfIntLtZero(Label label) { emitGotoIfCompare1(label, 155); } public final void emitGotoIfIntGeZero(Label label) { emitGotoIfCompare1(label, 156); } public final void emitGotoIfIntGtZero(Label label) { emitGotoIfCompare1(label, 157); } public final void emitGotoIfIntLeZero(Label label) { emitGotoIfCompare1(label, 158); } /** Compile start of a conditional: if (!(x OPCODE 0)) ... * The value of x must already have been pushed. */ public final void emitIfCompare1 (int opcode) { IfState new_if = new IfState(this); popType(); reserve(3); emitTransfer (new_if.end_label, opcode); new_if.start_stack_size = SP; } /** Compile start of conditional: if (x != 0) */ public final void emitIfIntNotZero() { emitIfCompare1(153); // ifeq } /** 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; } /** 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 emitIfThen () { new IfState(this); } /** 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 stack_growth = SP-if_stack.start_stack_size; if_stack.then_stacked_types = new Type[stack_growth]; System.arraycopy (stack_types, if_stack.start_stack_size, if_stack.then_stacked_types, 0, stack_growth); emitGoto (end_label); } while (SP != if_stack.start_stack_size) popType(); 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 ("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.then_stacked_types.length; if (! reachableHere ()) { System.arraycopy (if_stack.then_stacked_types, 0, stack_types, if_stack.start_stack_size, if_stack.then_stacked_types.length); SP = then_clause_stack_size; } else if (SP != then_clause_stack_size) throw new Error ("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_stack.end_label.define (this); if (make_unreachable) unreachable_here = true; // Pop the if_stack. if_stack = if_stack.previous; } /** * Convert the element on top of the stack to requested type */ public final void emitConvert (Type type) { Type from = popType(); pushType(from); emitConvert(from, type); } 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.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 Method.compile_convert"); 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 in emitCheckcast/emitInstanceof"); } public void emitCheckcast (Type type) { emitCheckcast(type, 192);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -