📄 code.java
字号:
/** * @(#)Code.java 1.23 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.tools.javac.v8.code;import com.sun.tools.javac.v8.util.*;import com.sun.tools.javac.v8.code.Symbol.*;/** * An internal structure that corresponds to the code attribute of * methods in a classfile. The class also provides some utility operations to * generate bytecode instructions. */public class Code implements ByteCodes, TypeTags { public static final boolean debugCode = false; /** * The maximum stack size. */ public int max_stack = 0; /** * The maximum number of local variable slots. */ public int max_locals = 0; /** * The code buffer. */ public byte[] code = new byte[64]; /** * the current code pointer. */ public int cp = 0; /** * Check the code against VM spec limits; if * problems report them and return true. */ public boolean checkLimits(int pos, Log log) { if (cp > ClassFile.MAX_CODE) { log.error(pos, "limit.code"); return true; } if (max_locals > ClassFile.MAX_LOCALS) { log.error(pos, "limit.locals"); return true; } if (max_stack > ClassFile.MAX_STACK) { log.error(pos, "limit.stack"); return true; } return false; } /** * A buffer for expression catch data. Each enter is a vector * of four unsigned shorts. */ ListBuffer catchInfo = new ListBuffer(); /** * A buffer for line number information. Each entry is a vector * of two unsigned shorts. */ List lineInfo = new List(); /** * The CharacterRangeTable */ public CRTable crt; /** * Are we generating code with jumps >= 32K? */ public boolean fatcode; /** * Code generation enabled? */ private boolean alive = true; /** * The current stacksize. */ public int stacksize = 0; /** * Is it forbidden to compactify code, because something is * pointing to current location? */ private boolean fixedPc = false; /** * The next available register. */ public int nextreg = 0; /** * A chain for jumps to be resolved before the next opcode is emitted. * We do this lazily to avoid jumps to jumps. */ Chain pendingJumps = null; /** * The position of the currently statement, if we are at the * start of this statement, NOPOS otherwise. * We need this to emit line numbers lazily, which we need to do * because of jump-to-jump optimization. */ int pendingStatPos = 0; /** * Switch: emit variable debug info. */ boolean varDebugInfo; /** * Switch: emit line number info. */ boolean lineDebugInfo; /** * Construct a code object, given the settings of the fatcode, * debugging info switches and the CharacterRangeTable. */ public Code(boolean fatcode, boolean lineDebugInfo, boolean varDebugInfo, CRTable crt) { super(); this.fatcode = fatcode; this.lineDebugInfo = lineDebugInfo; this.varDebugInfo = varDebugInfo; this.crt = crt; if (varDebugInfo) { defined = new Bits(); lvar = new LocalVar[20]; } } /** * Given a type, return its type code (used implicitly in the * JVM architecture). */ public static int typecode(Type type) { switch (type.tag) { case BYTE: return BYTEcode; case SHORT: return SHORTcode; case CHAR: return CHARcode; case INT: return INTcode; case LONG: return LONGcode; case FLOAT: return FLOATcode; case DOUBLE: return DOUBLEcode; case BOOLEAN: return BYTEcode; case VOID: return VOIDcode; case CLASS: case ARRAY: case METHOD: case BOT: return OBJECTcode; default: throw new AssertionError("typecode " + type.tag); } } /** * Collapse type code for subtypes of int to INTcode. */ public static int truncate(int tc) { switch (tc) { case BYTEcode: case SHORTcode: case CHARcode: return INTcode; default: return tc; } } /** * The width in bytes of objects of the type. */ public static int width(int typecode) { switch (typecode) { case LONGcode: case DOUBLEcode: return 2; case VOIDcode: return 0; default: return 1; } } public static int width(Type type) { return width(typecode(type)); } /** * The total width taken up by a vector of objects. */ public static int width(List types) { int w = 0; for (List l = types; l.nonEmpty(); l = l.tail) w = w + width((Type) l.head); return w; } /** * Given a type, return its code for allocating arrays of that type. */ public static int arraycode(Type type) { switch (type.tag) { case BYTE: return 8; case BOOLEAN: return 4; case SHORT: return 9; case CHAR: return 5; case INT: return 10; case LONG: return 11; case FLOAT: return 6; case DOUBLE: return 7; case CLASS: return 0; case ARRAY: return 1; default: throw new AssertionError("arraycode " + type); } } /** * The current output code pointer. */ public int curPc() { if (pendingJumps != null) resolvePending(); if (pendingStatPos != Position.NOPOS) markStatBegin(); fixedPc = true; return cp; } /** * Emit a byte of code. */ public void emit1(int od) { if (alive) { if (cp == code.length) { byte[] newcode = new byte[cp * 2]; System.arraycopy(code, 0, newcode, 0, cp); code = newcode; } code[cp++] = (byte) od; } } /** * Emit two bytes of code. */ public void emit2(int od) { if (alive) { if (cp + 2 > code.length) { emit1(od >> 8); emit1(od); } else { code[cp++] = (byte)(od >> 8); code[cp++] = (byte) od; } } } /** * Emit four bytes of code. */ public void emit4(int od) { if (alive) { if (cp + 4 > code.length) { emit1(od >> 24); emit1(od >> 16); emit1(od >> 8); emit1(od); } else { code[cp++] = (byte)(od >> 24); code[cp++] = (byte)(od >> 16); code[cp++] = (byte)(od >> 8); code[cp++] = (byte) od; } } } /** * Emit an opcode, adjust stacksize by sdiff. */ public void emitop(int op, int sdiff) { if (pendingJumps != null) resolvePending(); if (alive) { if (pendingStatPos != Position.NOPOS) markStatBegin(); if (debugCode) System.err.println(cp + ":" + stacksize + ": " + mnem(op)); emit1(op); if (sdiff <= -1000) { stacksize = stacksize + sdiff + 1000; alive = false; assert stacksize == 0; } else { stacksize = stacksize + sdiff; assert stacksize >= 0; if (stacksize > max_stack) max_stack = stacksize; } } } /** * Emit an opcode, adjust stacksize by stackdiff[op]. */ public void emitop(int op) { emitop(op, stackdiff[op]); } /** * Emit an opcode with a one-byte operand field. */ public void emitop1(int op, int od) { emitop(op); emit1(od); } /** * Emit an opcode with a one-byte operand field; * widen if field does not fit in a byte. */ public void emitop1w(int op, int od) { if (od > 255) { emitop(wide); emitop2(op, od); } else { emitop1(op, od); } } /** * Emit an opcode with a two-byte operand field. */ public void emitop2(int op, int od) { emitop(op); emit2(od); } /** * Emit an opcode with a four-byte operand field. */ public void emitop4(int op, int od) { emitop(op); emit4(od); } /** * Align code pointer to next `incr' boundary. */ public void align(int incr) { if (alive) while (cp % incr != 0) emit1(0); } /** * Place a byte into code at address pc. Pre: pc + 1 <= cp. */ public void put1(int pc, int op) { code[pc] = (byte) op; } /** * Place two bytes into code at address pc. Pre: pc + 2 <= cp. */ public void put2(int pc, int od) { put1(pc, od >> 8); put1(pc + 1, od); } /** * Place four bytes into code at address pc. Pre: pc + 4 <= cp. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -