📄 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 + -