📄 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 should have been already pushed on the stack. * @param element_type type of the array elements */ public void emitNewArray (Type element_type, int dims) { if (popType ().promote () != Type.int_type) throw new Error ("non-int dim. spec. in emitNewArray"); 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 ObjectType) { reserve(3); put1(189); // anewarray putIndex2(getConstants().addClass((ObjectType) element_type)); } else if (element_type instanceof ArrayType) { reserve(4); put1(197); // multianewarray putIndex2 (getConstants ().addClass (new ArrayType (element_type))); if (dims < 1 || dims > 255) throw new Error ("dims out of range in emitNewArray"); put1(dims); while (-- dims > 0) // first dim already popped if (popType ().promote () != Type.int_type) throw new Error ("non-int dim. spec. in emitNewArray"); } else throw new Error ("unimplemented type in emitNewArray"); pushType (new ArrayType (element_type)); } public void emitNewArray (Type element_type) { emitNewArray (element_type, 1); } // We may want to deprecate this, because it depends on popType. 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); } private void emitBinop (int base_code, char sig) { popType(); popType(); emitTypedOp(base_code, sig); pushType(Type.signatureToPrimitive(sig)); } private void emitBinop (int base_code, Type type) { popType(); popType(); emitTypedOp(base_code, type); pushType(type); } // 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(char sig) { emitBinop (96, sig); } public final void emitAdd(PrimType type) { emitBinop (96, type); } /** @deprecated */ public final void emitAdd () { emitBinop (96); } public final void emitSub(char sig) { emitBinop (100, sig); } public final void emitSub(PrimType type) { emitBinop (100, type); } /** @deprecated */ 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 emitShl () { emitShift (120); } public final void emitShr () { emitShift (122); } public final void emitUshr() { emitShift (124); } private void emitShift (int base_code) { Type type2 = popType().promote(); Type type1_raw = popType(); Type type1 = type1_raw.promote(); if (type1 != Type.int_type && type1 != Type.long_type) throw new Error ("the value shifted must be an int or a long"); if (type2 != Type.int_type) throw new Error ("the amount of shift must be an int"); emitTypedOp(base_code, type1); pushType(type1_raw); } public final void emitNot(Type type) { 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); } void emitMaybeWide (int opcode, int index) { if (index >= 256) { put1(196); // wide put1(opcode); put2(index); } else { put1(opcode); put1(index); } } /** * Compile 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 emitMaybeWide(21 + kind, offset); // [ilfda]load 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 "+var +" simple:"+var.isSimple()+", offset: "+offset); Type type = var.getType().promote (); reserve(4); popType(); int kind = adjustTypedOp(type); if (offset <= 3) put1(59 + 4 * kind + offset); // [ilfda]store_[0123] else emitMaybeWide(54 + kind, offset); // [ilfda]store } public void emitInc (Variable var, short inc) { if (var.dead ()) throw new Error ("attempting to increment dead variable"); int offset = var.offset; if (offset < 0 || !var.isSimple ()) throw new Error ("attempting to increment unassigned variable"+var.getName() +" simple:"+var.isSimple()+", offset: "+offset); Type type = var.getType().promote (); reserve(6); if (type != Type.int_type) throw new Error("attempting to increment non-int variable"); boolean wide = offset > 255 || inc > 255 || inc < -256; if (wide) { put1(196); // wide put1(132); // iinc put2(offset); put2(inc); } else { put1(132); // iinc put1(offset); put1(inc); } } 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 } /** Comptes the number of stack words taken by a list of types. */ private int words(Type[] types) { int res = 0; for (int i=types.length; --i >= 0; ) if (types[i].size > 4) res+=2; else res++; return res; } 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(words(method.arg_types)+1); // 1 word for 'this' put1(0); } while (--arg_count >= 0) popType(); if (method.return_type.size != 0) pushType(method.return_type); } public void emitInvoke (Method method) { int opcode; if ((method.access_flags & Access.STATIC) != 0) opcode = 184; // invokestatic else if (method.classfile.isInterface()) opcode = 185; // invokeinterface else if ("<init>".equals(method.getName())) opcode = 183; // invokespecial else opcode = 182; // invokevirtual emitInvokeMethod(method, opcode); } /** 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 } public void emitInvokeInterface (Method method) { emitInvokeMethod(method, 185); // invokeinterface } final void emitTransfer (Label label, int opcode) { fixupAdd(FIXUP_TRANSFER, label); put1(opcode); PC += 2; } /** Compile an unconditional branch (goto). * @param label target of the branch (must be in this method). */ public final void emitGoto (Label label) { fixupAdd(FIXUP_GOTO, label); reserve(3); put1(167); PC += 2; setUnreachable(); } public final void emitJsr (Label label) { fixupAdd(FIXUP_JSR, label); reserve(3); put1(168); PC += 2; } 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); } public final void emitGotoIfCompare2 (Label label, int logop) { if( logop < 153 || logop > 158 ) throw new Error ("emitGotoIfCompare2: logop must be one of ifeq...ifle"); Type type2 = popType().promote(); Type type1 = popType().promote(); reserve(4); char sig1 = type1.getSignature().charAt(0); char sig2 = type2.getSignature().charAt(0); boolean cmpg = (logop == 155 || logop == 158); // iflt,ifle if (sig1 == 'I' && sig2 == 'I') logop += 6; // iflt -> if_icmplt etc. else if (sig1 == 'J' && sig2 == 'J') put1(148); // lcmp else if (sig1 == 'F' && sig2 == 'F') put1(cmpg ? 149 : 150); // fcmpl/fcmpg else if (sig1 == 'D' && sig2 == 'D') put1(cmpg ? 151 : 152); // dcmpl/dcmpg else if ((sig1 == 'L' || sig1 == '[') && (sig2 == 'L' || sig2 == '[') && logop <= 154) logop += 12; // ifeq->if_acmpeq, ifne->if_acmpne else throw new Error ("invalid types to emitGotoIfCompare2"); emitTransfer (label, logop); } // binary comparisons /** @deprecated */ public final void emitGotoIfEq (Label label, boolean invert) { emitGotoIfCompare2(label, invert ? 154 : 153); } /** Compile a conditional transfer if 2 top stack elements are equal. */ public final void emitGotoIfEq (Label label) { emitGotoIfCompare2(label, 153); } /** Compile conditional transfer if 2 top stack elements are not equal. */ public final void emitGotoIfNE (Label label) { emitGotoIfCompare2(label, 154); } public final void emitGotoIfLt(Label label) { emitGotoIfCompare2(label, 155); } public final void emitGotoIfGe(Label label) { emitGotoIfCompare2(label, 156); } public final void emitGotoIfGt(Label label)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -