0001: /*
0002: * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package com.sun.tools.javac.jvm;
0027:
0028: import com.sun.tools.javac.code.*;
0029: import com.sun.tools.javac.code.Symbol.*;
0030: import com.sun.tools.javac.util.*;
0031: import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
0032:
0033: import static com.sun.tools.javac.code.TypeTags.*;
0034: import static com.sun.tools.javac.jvm.ByteCodes.*;
0035: import static com.sun.tools.javac.jvm.UninitializedType.*;
0036: import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
0037:
0038: /** An internal structure that corresponds to the code attribute of
0039: * methods in a classfile. The class also provides some utility operations to
0040: * generate bytecode instructions.
0041: *
0042: * <p><b>This is NOT part of any API supported by Sun Microsystems. If
0043: * you write code that depends on this, you do so at your own risk.
0044: * This code and its internal interfaces are subject to change or
0045: * deletion without notice.</b>
0046: */
0047: @Version("@(#)Code.java 1.69 07/05/05")
0048: public class Code {
0049:
0050: public final boolean debugCode;
0051: public final boolean needStackMap;
0052:
0053: public enum StackMapFormat {
0054: NONE, CLDC {
0055: Name getAttributeName(Name.Table names) {
0056: return names.StackMap;
0057: }
0058: },
0059: JSR202 {
0060: Name getAttributeName(Name.Table names) {
0061: return names.StackMapTable;
0062: }
0063: };
0064: Name getAttributeName(Name.Table names) {
0065: return names.empty;
0066: }
0067: }
0068:
0069: final Types types;
0070: final Symtab syms;
0071:
0072: /*---------- classfile fields: --------------- */
0073:
0074: /** The maximum stack size.
0075: */
0076: public int max_stack = 0;
0077:
0078: /** The maximum number of local variable slots.
0079: */
0080: public int max_locals = 0;
0081:
0082: /** The code buffer.
0083: */
0084: public byte[] code = new byte[64];
0085:
0086: /** the current code pointer.
0087: */
0088: public int cp = 0;
0089:
0090: /** Check the code against VM spec limits; if
0091: * problems report them and return true.
0092: */
0093: public boolean checkLimits(DiagnosticPosition pos, Log log) {
0094: if (cp > ClassFile.MAX_CODE) {
0095: log.error(pos, "limit.code");
0096: return true;
0097: }
0098: if (max_locals > ClassFile.MAX_LOCALS) {
0099: log.error(pos, "limit.locals");
0100: return true;
0101: }
0102: if (max_stack > ClassFile.MAX_STACK) {
0103: log.error(pos, "limit.stack");
0104: return true;
0105: }
0106: return false;
0107: }
0108:
0109: /** A buffer for expression catch data. Each enter is a vector
0110: * of four unsigned shorts.
0111: */
0112: ListBuffer<char[]> catchInfo = new ListBuffer<char[]>();
0113:
0114: /** A buffer for line number information. Each entry is a vector
0115: * of two unsigned shorts.
0116: */
0117: List<char[]> lineInfo = List.nil(); // handled in stack fashion
0118:
0119: /** The CharacterRangeTable
0120: */
0121: public CRTable crt;
0122:
0123: /*---------- internal fields: --------------- */
0124:
0125: /** Are we generating code with jumps >= 32K?
0126: */
0127: public boolean fatcode;
0128:
0129: /** Code generation enabled?
0130: */
0131: private boolean alive = true;
0132:
0133: /** The current machine state (registers and stack).
0134: */
0135: State state;
0136:
0137: /** Is it forbidden to compactify code, because something is
0138: * pointing to current location?
0139: */
0140: private boolean fixedPc = false;
0141:
0142: /** The next available register.
0143: */
0144: public int nextreg = 0;
0145:
0146: /** A chain for jumps to be resolved before the next opcode is emitted.
0147: * We do this lazily to avoid jumps to jumps.
0148: */
0149: Chain pendingJumps = null;
0150:
0151: /** The position of the currently statement, if we are at the
0152: * start of this statement, NOPOS otherwise.
0153: * We need this to emit line numbers lazily, which we need to do
0154: * because of jump-to-jump optimization.
0155: */
0156: int pendingStatPos = Position.NOPOS;
0157:
0158: /** Set true when a stackMap is needed at the current PC. */
0159: boolean pendingStackMap = false;
0160:
0161: /** The stack map format to be generated. */
0162: StackMapFormat stackMap;
0163:
0164: /** Switch: emit variable debug info.
0165: */
0166: boolean varDebugInfo;
0167:
0168: /** Switch: emit line number info.
0169: */
0170: boolean lineDebugInfo;
0171:
0172: /** Emit line number info if map supplied
0173: */
0174: Position.LineMap lineMap;
0175:
0176: /** The constant pool of the current class.
0177: */
0178: final Pool pool;
0179:
0180: final MethodSymbol meth;
0181:
0182: /** Construct a code object, given the settings of the fatcode,
0183: * debugging info switches and the CharacterRangeTable.
0184: */
0185: public Code(MethodSymbol meth, boolean fatcode,
0186: Position.LineMap lineMap, boolean varDebugInfo,
0187: StackMapFormat stackMap, boolean debugCode, CRTable crt,
0188: Symtab syms, Types types, Pool pool) {
0189: this .meth = meth;
0190: this .fatcode = fatcode;
0191: this .lineMap = lineMap;
0192: this .lineDebugInfo = lineMap != null;
0193: this .varDebugInfo = varDebugInfo;
0194: this .crt = crt;
0195: this .syms = syms;
0196: this .types = types;
0197: this .debugCode = debugCode;
0198: this .stackMap = stackMap;
0199: switch (stackMap) {
0200: case CLDC:
0201: case JSR202:
0202: this .needStackMap = true;
0203: break;
0204: default:
0205: this .needStackMap = false;
0206: }
0207: state = new State();
0208: lvar = new LocalVar[20];
0209: this .pool = pool;
0210: }
0211:
0212: /* **************************************************************************
0213: * Typecodes & related stuff
0214: ****************************************************************************/
0215:
0216: /** Given a type, return its type code (used implicitly in the
0217: * JVM architecture).
0218: */
0219: public static int typecode(Type type) {
0220: switch (type.tag) {
0221: case BYTE:
0222: return BYTEcode;
0223: case SHORT:
0224: return SHORTcode;
0225: case CHAR:
0226: return CHARcode;
0227: case INT:
0228: return INTcode;
0229: case LONG:
0230: return LONGcode;
0231: case FLOAT:
0232: return FLOATcode;
0233: case DOUBLE:
0234: return DOUBLEcode;
0235: case BOOLEAN:
0236: return BYTEcode;
0237: case VOID:
0238: return VOIDcode;
0239: case CLASS:
0240: case ARRAY:
0241: case METHOD:
0242: case BOT:
0243: case TYPEVAR:
0244: case UNINITIALIZED_THIS:
0245: case UNINITIALIZED_OBJECT:
0246: return OBJECTcode;
0247: default:
0248: throw new AssertionError("typecode " + type.tag);
0249: }
0250: }
0251:
0252: /** Collapse type code for subtypes of int to INTcode.
0253: */
0254: public static int truncate(int tc) {
0255: switch (tc) {
0256: case BYTEcode:
0257: case SHORTcode:
0258: case CHARcode:
0259: return INTcode;
0260: default:
0261: return tc;
0262: }
0263: }
0264:
0265: /** The width in bytes of objects of the type.
0266: */
0267: public static int width(int typecode) {
0268: switch (typecode) {
0269: case LONGcode:
0270: case DOUBLEcode:
0271: return 2;
0272: case VOIDcode:
0273: return 0;
0274: default:
0275: return 1;
0276: }
0277: }
0278:
0279: public static int width(Type type) {
0280: return type == null ? 1 : width(typecode(type));
0281: }
0282:
0283: /** The total width taken up by a vector of objects.
0284: */
0285: public static int width(List<Type> types) {
0286: int w = 0;
0287: for (List<Type> l = types; l.nonEmpty(); l = l.tail)
0288: w = w + width(l.head);
0289: return w;
0290: }
0291:
0292: /** Given a type, return its code for allocating arrays of that type.
0293: */
0294: public static int arraycode(Type type) {
0295: switch (type.tag) {
0296: case BYTE:
0297: return 8;
0298: case BOOLEAN:
0299: return 4;
0300: case SHORT:
0301: return 9;
0302: case CHAR:
0303: return 5;
0304: case INT:
0305: return 10;
0306: case LONG:
0307: return 11;
0308: case FLOAT:
0309: return 6;
0310: case DOUBLE:
0311: return 7;
0312: case CLASS:
0313: return 0;
0314: case ARRAY:
0315: return 1;
0316: default:
0317: throw new AssertionError("arraycode " + type);
0318: }
0319: }
0320:
0321: /* **************************************************************************
0322: * Emit code
0323: ****************************************************************************/
0324:
0325: /** The current output code pointer.
0326: */
0327: public int curPc() {
0328: if (pendingJumps != null)
0329: resolvePending();
0330: if (pendingStatPos != Position.NOPOS)
0331: markStatBegin();
0332: fixedPc = true;
0333: return cp;
0334: }
0335:
0336: /** Emit a byte of code.
0337: */
0338: private void emit1(int od) {
0339: if (!alive)
0340: return;
0341: if (cp == code.length) {
0342: byte[] newcode = new byte[cp * 2];
0343: System.arraycopy(code, 0, newcode, 0, cp);
0344: code = newcode;
0345: }
0346: code[cp++] = (byte) od;
0347: }
0348:
0349: /** Emit two bytes of code.
0350: */
0351: private void emit2(int od) {
0352: if (!alive)
0353: return;
0354: if (cp + 2 > code.length) {
0355: emit1(od >> 8);
0356: emit1(od);
0357: } else {
0358: code[cp++] = (byte) (od >> 8);
0359: code[cp++] = (byte) od;
0360: }
0361: }
0362:
0363: /** Emit four bytes of code.
0364: */
0365: public void emit4(int od) {
0366: if (!alive)
0367: return;
0368: if (cp + 4 > code.length) {
0369: emit1(od >> 24);
0370: emit1(od >> 16);
0371: emit1(od >> 8);
0372: emit1(od);
0373: } else {
0374: code[cp++] = (byte) (od >> 24);
0375: code[cp++] = (byte) (od >> 16);
0376: code[cp++] = (byte) (od >> 8);
0377: code[cp++] = (byte) od;
0378: }
0379: }
0380:
0381: /** Emit an opcode.
0382: */
0383: private void emitop(int op) {
0384: if (pendingJumps != null)
0385: resolvePending();
0386: if (alive) {
0387: if (pendingStatPos != Position.NOPOS)
0388: markStatBegin();
0389: if (pendingStackMap) {
0390: pendingStackMap = false;
0391: emitStackMap();
0392: }
0393: if (debugCode)
0394: System.err.println("emit@" + cp + " stack="
0395: + state.stacksize + ": " + mnem(op));
0396: emit1(op);
0397: }
0398: }
0399:
0400: void postop() {
0401: assert alive || state.stacksize == 0;
0402: }
0403:
0404: /** Emit a multinewarray instruction.
0405: */
0406: public void emitMultianewarray(int ndims, int type, Type arrayType) {
0407: emitop(multianewarray);
0408: if (!alive)
0409: return;
0410: emit2(type);
0411: emit1(ndims);
0412: state.pop(ndims);
0413: state.push(arrayType);
0414: }
0415:
0416: /** Emit newarray.
0417: */
0418: public void emitNewarray(int elemcode, Type arrayType) {
0419: emitop(newarray);
0420: if (!alive)
0421: return;
0422: emit1(elemcode);
0423: state.pop(1); // count
0424: state.push(arrayType);
0425: }
0426:
0427: /** Emit anewarray.
0428: */
0429: public void emitAnewarray(int od, Type arrayType) {
0430: emitop(anewarray);
0431: if (!alive)
0432: return;
0433: emit2(od);
0434: state.pop(1);
0435: state.push(arrayType);
0436: }
0437:
0438: /** Emit an invokeinterface instruction.
0439: */
0440: public void emitInvokeinterface(int meth, Type mtype) {
0441: int argsize = width(mtype.getParameterTypes());
0442: emitop(invokeinterface);
0443: if (!alive)
0444: return;
0445: emit2(meth);
0446: emit1(argsize + 1);
0447: emit1(0);
0448: state.pop(argsize + 1);
0449: state.push(mtype.getReturnType());
0450: }
0451:
0452: /** Emit an invokespecial instruction.
0453: */
0454: public void emitInvokespecial(int meth, Type mtype) {
0455: int argsize = width(mtype.getParameterTypes());
0456: emitop(invokespecial);
0457: if (!alive)
0458: return;
0459: emit2(meth);
0460: Symbol sym = (Symbol) pool.pool[meth];
0461: state.pop(argsize);
0462: if (sym.isConstructor())
0463: state.markInitialized((UninitializedType) state.peek());
0464: state.pop(1);
0465: state.push(mtype.getReturnType());
0466: }
0467:
0468: /** Emit an invokestatic instruction.
0469: */
0470: public void emitInvokestatic(int meth, Type mtype) {
0471: int argsize = width(mtype.getParameterTypes());
0472: emitop(invokestatic);
0473: if (!alive)
0474: return;
0475: emit2(meth);
0476: state.pop(argsize);
0477: state.push(mtype.getReturnType());
0478: }
0479:
0480: /** Emit an invokevirtual instruction.
0481: */
0482: public void emitInvokevirtual(int meth, Type mtype) {
0483: int argsize = width(mtype.getParameterTypes());
0484: emitop(invokevirtual);
0485: if (!alive)
0486: return;
0487: emit2(meth);
0488: state.pop(argsize + 1);
0489: state.push(mtype.getReturnType());
0490: }
0491:
0492: /** Emit an opcode with no operand field.
0493: */
0494: public void emitop0(int op) {
0495: emitop(op);
0496: if (!alive)
0497: return;
0498: switch (op) {
0499: case aaload: {
0500: state.pop(1);// index
0501: Type a = state.stack[state.stacksize - 1];
0502: state.pop(1);
0503: state.push(types.erasure(types.elemtype(a)));
0504: }
0505: break;
0506: case goto_:
0507: markDead();
0508: break;
0509: case nop:
0510: case ineg:
0511: case lneg:
0512: case fneg:
0513: case dneg:
0514: break;
0515: case aconst_null:
0516: state.push(syms.botType);
0517: break;
0518: case iconst_m1:
0519: case iconst_0:
0520: case iconst_1:
0521: case iconst_2:
0522: case iconst_3:
0523: case iconst_4:
0524: case iconst_5:
0525: case iload_0:
0526: case iload_1:
0527: case iload_2:
0528: case iload_3:
0529: state.push(syms.intType);
0530: break;
0531: case lconst_0:
0532: case lconst_1:
0533: case lload_0:
0534: case lload_1:
0535: case lload_2:
0536: case lload_3:
0537: state.push(syms.longType);
0538: break;
0539: case fconst_0:
0540: case fconst_1:
0541: case fconst_2:
0542: case fload_0:
0543: case fload_1:
0544: case fload_2:
0545: case fload_3:
0546: state.push(syms.floatType);
0547: break;
0548: case dconst_0:
0549: case dconst_1:
0550: case dload_0:
0551: case dload_1:
0552: case dload_2:
0553: case dload_3:
0554: state.push(syms.doubleType);
0555: break;
0556: case aload_0:
0557: state.push(lvar[0].sym.type);
0558: break;
0559: case aload_1:
0560: state.push(lvar[1].sym.type);
0561: break;
0562: case aload_2:
0563: state.push(lvar[2].sym.type);
0564: break;
0565: case aload_3:
0566: state.push(lvar[3].sym.type);
0567: break;
0568: case iaload:
0569: case baload:
0570: case caload:
0571: case saload:
0572: state.pop(2);
0573: state.push(syms.intType);
0574: break;
0575: case laload:
0576: state.pop(2);
0577: state.push(syms.longType);
0578: break;
0579: case faload:
0580: state.pop(2);
0581: state.push(syms.floatType);
0582: break;
0583: case daload:
0584: state.pop(2);
0585: state.push(syms.doubleType);
0586: break;
0587: case istore_0:
0588: case istore_1:
0589: case istore_2:
0590: case istore_3:
0591: case fstore_0:
0592: case fstore_1:
0593: case fstore_2:
0594: case fstore_3:
0595: case astore_0:
0596: case astore_1:
0597: case astore_2:
0598: case astore_3:
0599: case pop:
0600: case lshr:
0601: case lshl:
0602: case lushr:
0603: state.pop(1);
0604: break;
0605: case areturn:
0606: case ireturn:
0607: case freturn:
0608: assert state.nlocks == 0;
0609: state.pop(1);
0610: markDead();
0611: break;
0612: case athrow:
0613: state.pop(1);
0614: markDead();
0615: break;
0616: case lstore_0:
0617: case lstore_1:
0618: case lstore_2:
0619: case lstore_3:
0620: case dstore_0:
0621: case dstore_1:
0622: case dstore_2:
0623: case dstore_3:
0624: case pop2:
0625: state.pop(2);
0626: break;
0627: case lreturn:
0628: case dreturn:
0629: assert state.nlocks == 0;
0630: state.pop(2);
0631: markDead();
0632: break;
0633: case dup:
0634: state.push(state.stack[state.stacksize - 1]);
0635: break;
0636: case return_:
0637: assert state.nlocks == 0;
0638: markDead();
0639: break;
0640: case arraylength:
0641: state.pop(1);
0642: state.push(syms.intType);
0643: break;
0644: case isub:
0645: case iadd:
0646: case imul:
0647: case idiv:
0648: case imod:
0649: case ishl:
0650: case ishr:
0651: case iushr:
0652: case iand:
0653: case ior:
0654: case ixor:
0655: state.pop(1);
0656: // state.pop(1);
0657: // state.push(syms.intType);
0658: break;
0659: case aastore:
0660: state.pop(3);
0661: break;
0662: case land:
0663: case lor:
0664: case lxor:
0665: case lmod:
0666: case ldiv:
0667: case lmul:
0668: case lsub:
0669: case ladd:
0670: state.pop(2);
0671: break;
0672: case lcmp:
0673: state.pop(4);
0674: state.push(syms.intType);
0675: break;
0676: case l2i:
0677: state.pop(2);
0678: state.push(syms.intType);
0679: break;
0680: case i2l:
0681: state.pop(1);
0682: state.push(syms.longType);
0683: break;
0684: case i2f:
0685: state.pop(1);
0686: state.push(syms.floatType);
0687: break;
0688: case i2d:
0689: state.pop(1);
0690: state.push(syms.doubleType);
0691: break;
0692: case l2f:
0693: state.pop(2);
0694: state.push(syms.floatType);
0695: break;
0696: case l2d:
0697: state.pop(2);
0698: state.push(syms.doubleType);
0699: break;
0700: case f2i:
0701: state.pop(1);
0702: state.push(syms.intType);
0703: break;
0704: case f2l:
0705: state.pop(1);
0706: state.push(syms.longType);
0707: break;
0708: case f2d:
0709: state.pop(1);
0710: state.push(syms.doubleType);
0711: break;
0712: case d2i:
0713: state.pop(2);
0714: state.push(syms.intType);
0715: break;
0716: case d2l:
0717: state.pop(2);
0718: state.push(syms.longType);
0719: break;
0720: case d2f:
0721: state.pop(2);
0722: state.push(syms.floatType);
0723: break;
0724: case tableswitch:
0725: case lookupswitch:
0726: state.pop(1);
0727: // the caller is responsible for patching up the state
0728: break;
0729: case dup_x1: {
0730: Type val1 = state.pop1();
0731: Type val2 = state.pop1();
0732: state.push(val1);
0733: state.push(val2);
0734: state.push(val1);
0735: break;
0736: }
0737: case bastore:
0738: state.pop(3);
0739: break;
0740: case int2byte:
0741: case int2char:
0742: case int2short:
0743: break;
0744: case fmul:
0745: case fadd:
0746: case fsub:
0747: case fdiv:
0748: case fmod:
0749: state.pop(1);
0750: break;
0751: case castore:
0752: case iastore:
0753: case fastore:
0754: case sastore:
0755: state.pop(3);
0756: break;
0757: case lastore:
0758: case dastore:
0759: state.pop(4);
0760: break;
0761: case dup2:
0762: if (state.stack[state.stacksize - 1] != null) {
0763: Type value1 = state.pop1();
0764: Type value2 = state.pop1();
0765: state.push(value2);
0766: state.push(value1);
0767: state.push(value2);
0768: state.push(value1);
0769: } else {
0770: Type value = state.pop2();
0771: state.push(value);
0772: state.push(value);
0773: }
0774: break;
0775: case dup2_x1:
0776: if (state.stack[state.stacksize - 1] != null) {
0777: Type value1 = state.pop1();
0778: Type value2 = state.pop1();
0779: Type value3 = state.pop1();
0780: state.push(value2);
0781: state.push(value1);
0782: state.push(value3);
0783: state.push(value2);
0784: state.push(value1);
0785: } else {
0786: Type value1 = state.pop2();
0787: Type value2 = state.pop1();
0788: state.push(value1);
0789: state.push(value2);
0790: state.push(value1);
0791: }
0792: break;
0793: case dup2_x2:
0794: if (state.stack[state.stacksize - 1] != null) {
0795: Type value1 = state.pop1();
0796: Type value2 = state.pop1();
0797: if (state.stack[state.stacksize - 1] != null) {
0798: // form 1
0799: Type value3 = state.pop1();
0800: Type value4 = state.pop1();
0801: state.push(value2);
0802: state.push(value1);
0803: state.push(value4);
0804: state.push(value3);
0805: state.push(value2);
0806: state.push(value1);
0807: } else {
0808: // form 3
0809: Type value3 = state.pop2();
0810: state.push(value2);
0811: state.push(value1);
0812: state.push(value3);
0813: state.push(value2);
0814: state.push(value1);
0815: }
0816: } else {
0817: Type value1 = state.pop2();
0818: if (state.stack[state.stacksize - 1] != null) {
0819: // form 2
0820: Type value2 = state.pop1();
0821: Type value3 = state.pop1();
0822: state.push(value1);
0823: state.push(value3);
0824: state.push(value2);
0825: state.push(value1);
0826: } else {
0827: // form 4
0828: Type value2 = state.pop2();
0829: state.push(value1);
0830: state.push(value2);
0831: state.push(value1);
0832: }
0833: }
0834: break;
0835: case dup_x2: {
0836: Type value1 = state.pop1();
0837: if (state.stack[state.stacksize - 1] != null) {
0838: // form 1
0839: Type value2 = state.pop1();
0840: Type value3 = state.pop1();
0841: state.push(value1);
0842: state.push(value3);
0843: state.push(value2);
0844: state.push(value1);
0845: } else {
0846: // form 2
0847: Type value2 = state.pop2();
0848: state.push(value1);
0849: state.push(value2);
0850: state.push(value1);
0851: }
0852: }
0853: break;
0854: case fcmpl:
0855: case fcmpg:
0856: state.pop(2);
0857: state.push(syms.intType);
0858: break;
0859: case dcmpl:
0860: case dcmpg:
0861: state.pop(4);
0862: state.push(syms.intType);
0863: break;
0864: case swap: {
0865: Type value1 = state.pop1();
0866: Type value2 = state.pop1();
0867: state.push(value1);
0868: state.push(value2);
0869: break;
0870: }
0871: case dadd:
0872: case dsub:
0873: case dmul:
0874: case ddiv:
0875: case dmod:
0876: state.pop(2);
0877: break;
0878: case ret:
0879: markDead();
0880: break;
0881: case wide:
0882: // must be handled by the caller.
0883: return;
0884: case monitorenter:
0885: case monitorexit:
0886: state.pop(1);
0887: break;
0888:
0889: default:
0890: throw new AssertionError(mnem(op));
0891: }
0892: postop();
0893: }
0894:
0895: /** Emit an opcode with a one-byte operand field.
0896: */
0897: public void emitop1(int op, int od) {
0898: emitop(op);
0899: if (!alive)
0900: return;
0901: emit1(od);
0902: switch (op) {
0903: case bipush:
0904: state.push(syms.intType);
0905: break;
0906: case ldc1:
0907: state.push(typeForPool(pool.pool[od]));
0908: break;
0909: default:
0910: throw new AssertionError(mnem(op));
0911: }
0912: postop();
0913: }
0914:
0915: /** The type of a constant pool entry. */
0916: private Type typeForPool(Object o) {
0917: if (o instanceof Integer)
0918: return syms.intType;
0919: if (o instanceof Float)
0920: return syms.floatType;
0921: if (o instanceof String)
0922: return syms.stringType;
0923: if (o instanceof Long)
0924: return syms.longType;
0925: if (o instanceof Double)
0926: return syms.doubleType;
0927: if (o instanceof ClassSymbol)
0928: return syms.classType;
0929: if (o instanceof Type.ArrayType)
0930: return syms.classType;
0931: throw new AssertionError(o);
0932: }
0933:
0934: /** Emit an opcode with a one-byte operand field;
0935: * widen if field does not fit in a byte.
0936: */
0937: public void emitop1w(int op, int od) {
0938: if (od > 0xFF) {
0939: emitop(wide);
0940: emitop(op);
0941: emit2(od);
0942: } else {
0943: emitop(op);
0944: emit1(od);
0945: }
0946: if (!alive)
0947: return;
0948: switch (op) {
0949: case iload:
0950: state.push(syms.intType);
0951: break;
0952: case lload:
0953: state.push(syms.longType);
0954: break;
0955: case fload:
0956: state.push(syms.floatType);
0957: break;
0958: case dload:
0959: state.push(syms.doubleType);
0960: break;
0961: case aload:
0962: state.push(lvar[od].sym.type);
0963: break;
0964: case lstore:
0965: case dstore:
0966: state.pop(2);
0967: break;
0968: case istore:
0969: case fstore:
0970: case astore:
0971: state.pop(1);
0972: break;
0973: case ret:
0974: markDead();
0975: break;
0976: default:
0977: throw new AssertionError(mnem(op));
0978: }
0979: postop();
0980: }
0981:
0982: /** Emit an opcode with two one-byte operand fields;
0983: * widen if either field does not fit in a byte.
0984: */
0985: public void emitop1w(int op, int od1, int od2) {
0986: if (od1 > 0xFF || od2 < -128 || od2 > 127) {
0987: emitop(wide);
0988: emitop(op);
0989: emit2(od1);
0990: emit2(od2);
0991: } else {
0992: emitop(op);
0993: emit1(od1);
0994: emit1(od2);
0995: }
0996: if (!alive)
0997: return;
0998: switch (op) {
0999: case iinc:
1000: break;
1001: default:
1002: throw new AssertionError(mnem(op));
1003: }
1004: }
1005:
1006: /** Emit an opcode with a two-byte operand field.
1007: */
1008: public void emitop2(int op, int od) {
1009: emitop(op);
1010: if (!alive)
1011: return;
1012: emit2(od);
1013: switch (op) {
1014: case getstatic:
1015: state.push(((Symbol) (pool.pool[od])).erasure(types));
1016: break;
1017: case putstatic:
1018: state.pop(((Symbol) (pool.pool[od])).erasure(types));
1019: break;
1020: case new_:
1021: state.push(uninitializedObject(((Symbol) (pool.pool[od]))
1022: .erasure(types), cp - 3));
1023: break;
1024: case sipush:
1025: state.push(syms.intType);
1026: break;
1027: case if_acmp_null:
1028: case if_acmp_nonnull:
1029: case ifeq:
1030: case ifne:
1031: case iflt:
1032: case ifge:
1033: case ifgt:
1034: case ifle:
1035: state.pop(1);
1036: break;
1037: case if_icmpeq:
1038: case if_icmpne:
1039: case if_icmplt:
1040: case if_icmpge:
1041: case if_icmpgt:
1042: case if_icmple:
1043: case if_acmpeq:
1044: case if_acmpne:
1045: state.pop(2);
1046: break;
1047: case goto_:
1048: markDead();
1049: break;
1050: case putfield:
1051: state.pop(((Symbol) (pool.pool[od])).erasure(types));
1052: state.pop(1); // object ref
1053: break;
1054: case getfield:
1055: state.pop(1); // object ref
1056: state.push(((Symbol) (pool.pool[od])).erasure(types));
1057: break;
1058: case checkcast: {
1059: state.pop(1); // object ref
1060: Object o = pool.pool[od];
1061: Type t = (o instanceof Symbol) ? ((Symbol) o)
1062: .erasure(types) : types.erasure(((Type) o));
1063: state.push(t);
1064: break;
1065: }
1066: case ldc2w:
1067: state.push(typeForPool(pool.pool[od]));
1068: break;
1069: case instanceof _:
1070: state.pop(1);
1071: state.push(syms.intType);
1072: break;
1073: case ldc2:
1074: state.push(typeForPool(pool.pool[od]));
1075: break;
1076: case jsr:
1077: break;
1078: default:
1079: throw new AssertionError(mnem(op));
1080: }
1081: // postop();
1082: }
1083:
1084: /** Emit an opcode with a four-byte operand field.
1085: */
1086: public void emitop4(int op, int od) {
1087: emitop(op);
1088: if (!alive)
1089: return;
1090: emit4(od);
1091: switch (op) {
1092: case goto_w:
1093: markDead();
1094: break;
1095: case jsr_w:
1096: break;
1097: default:
1098: throw new AssertionError(mnem(op));
1099: }
1100: // postop();
1101: }
1102:
1103: /** Align code pointer to next `incr' boundary.
1104: */
1105: public void align(int incr) {
1106: if (alive)
1107: while (cp % incr != 0)
1108: emitop0(nop);
1109: }
1110:
1111: /** Place a byte into code at address pc. Pre: pc + 1 <= cp.
1112: */
1113: private void put1(int pc, int op) {
1114: code[pc] = (byte) op;
1115: }
1116:
1117: /** Place two bytes into code at address pc. Pre: pc + 2 <= cp.
1118: */
1119: private void put2(int pc, int od) {
1120: // pre: pc + 2 <= cp
1121: put1(pc, od >> 8);
1122: put1(pc + 1, od);
1123: }
1124:
1125: /** Place four bytes into code at address pc. Pre: pc + 4 <= cp.
1126: */
1127: public void put4(int pc, int od) {
1128: // pre: pc + 4 <= cp
1129: put1(pc, od >> 24);
1130: put1(pc + 1, od >> 16);
1131: put1(pc + 2, od >> 8);
1132: put1(pc + 3, od);
1133: }
1134:
1135: /** Return code byte at position pc as an unsigned int.
1136: */
1137: private int get1(int pc) {
1138: return code[pc] & 0xFF;
1139: }
1140:
1141: /** Return two code bytes at position pc as an unsigned int.
1142: */
1143: private int get2(int pc) {
1144: return (get1(pc) << 8) | get1(pc + 1);
1145: }
1146:
1147: /** Return four code bytes at position pc as an int.
1148: */
1149: public int get4(int pc) {
1150: // pre: pc + 4 <= cp
1151: return (get1(pc) << 24) | (get1(pc + 1) << 16)
1152: | (get1(pc + 2) << 8) | (get1(pc + 3));
1153: }
1154:
1155: /** Is code generation currently enabled?
1156: */
1157: public boolean isAlive() {
1158: return alive || pendingJumps != null;
1159: }
1160:
1161: /** Switch code generation on/off.
1162: */
1163: public void markDead() {
1164: alive = false;
1165: }
1166:
1167: /** Declare an entry point; return current code pointer
1168: */
1169: public int entryPoint() {
1170: int pc = curPc();
1171: alive = true;
1172: pendingStackMap = needStackMap;
1173: return pc;
1174: }
1175:
1176: /** Declare an entry point with initial state;
1177: * return current code pointer
1178: */
1179: public int entryPoint(State state) {
1180: int pc = curPc();
1181: alive = true;
1182: this .state = state.dup();
1183: assert state.stacksize <= max_stack;
1184: if (debugCode)
1185: System.err.println("entry point " + state);
1186: pendingStackMap = needStackMap;
1187: return pc;
1188: }
1189:
1190: /** Declare an entry point with initial state plus a pushed value;
1191: * return current code pointer
1192: */
1193: public int entryPoint(State state, Type pushed) {
1194: int pc = curPc();
1195: alive = true;
1196: this .state = state.dup();
1197: assert state.stacksize <= max_stack;
1198: this .state.push(pushed);
1199: if (debugCode)
1200: System.err.println("entry point " + state);
1201: pendingStackMap = needStackMap;
1202: return pc;
1203: }
1204:
1205: /**************************************************************************
1206: * Stack map generation
1207: *************************************************************************/
1208:
1209: /** An entry in the stack map. */
1210: static class StackMapFrame {
1211: int pc;
1212: Type[] locals;
1213: Type[] stack;
1214: }
1215:
1216: /** A buffer of cldc stack map entries. */
1217: StackMapFrame[] stackMapBuffer = null;
1218:
1219: /** A buffer of compressed StackMapTable entries. */
1220: StackMapTableFrame[] stackMapTableBuffer = null;
1221: int stackMapBufferSize = 0;
1222:
1223: /** The last PC at which we generated a stack map. */
1224: int lastStackMapPC = -1;
1225:
1226: /** The last stack map frame in StackMapTable. */
1227: StackMapFrame lastFrame = null;
1228:
1229: /** The stack map frame before the last one. */
1230: StackMapFrame frameBeforeLast = null;
1231:
1232: /** Emit a stack map entry. */
1233: public void emitStackMap() {
1234: int pc = curPc();
1235: if (!needStackMap)
1236: return;
1237:
1238: switch (stackMap) {
1239: case CLDC:
1240: emitCLDCStackMap(pc, getLocalsSize());
1241: break;
1242: case JSR202:
1243: emitStackMapFrame(pc, getLocalsSize());
1244: break;
1245: default:
1246: throw new AssertionError(
1247: "Should have chosen a stackmap format");
1248: }
1249: // DEBUG code follows
1250: if (debugCode)
1251: state.dump(pc);
1252: }
1253:
1254: private int getLocalsSize() {
1255: int nextLocal = 0;
1256: for (int i = max_locals - 1; i >= 0; i--) {
1257: if (state.defined.isMember(i) && lvar[i] != null) {
1258: nextLocal = i + width(lvar[i].sym.erasure(types));
1259: break;
1260: }
1261: }
1262: return nextLocal;
1263: }
1264:
1265: /** Emit a CLDC stack map frame. */
1266: void emitCLDCStackMap(int pc, int localsSize) {
1267: if (lastStackMapPC == pc) {
1268: // drop existing stackmap at this offset
1269: stackMapBuffer[--stackMapBufferSize] = null;
1270: }
1271: lastStackMapPC = pc;
1272:
1273: if (stackMapBuffer == null) {
1274: stackMapBuffer = new StackMapFrame[20];
1275: } else if (stackMapBuffer.length == stackMapBufferSize) {
1276: StackMapFrame[] newStackMapBuffer = new StackMapFrame[stackMapBufferSize << 1];
1277: System.arraycopy(stackMapBuffer, 0, newStackMapBuffer, 0,
1278: stackMapBufferSize);
1279: stackMapBuffer = newStackMapBuffer;
1280: }
1281: StackMapFrame frame = stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
1282: frame.pc = pc;
1283:
1284: frame.locals = new Type[localsSize];
1285: for (int i = 0; i < localsSize; i++) {
1286: if (state.defined.isMember(i) && lvar[i] != null) {
1287: Type vtype = lvar[i].sym.type;
1288: if (!(vtype instanceof UninitializedType))
1289: vtype = types.erasure(vtype);
1290: frame.locals[i] = vtype;
1291: }
1292: }
1293: frame.stack = new Type[state.stacksize];
1294: for (int i = 0; i < state.stacksize; i++)
1295: frame.stack[i] = state.stack[i];
1296: }
1297:
1298: void emitStackMapFrame(int pc, int localsSize) {
1299: if (lastFrame == null) {
1300: // first frame
1301: lastFrame = getInitialFrame();
1302: } else if (lastFrame.pc == pc) {
1303: // drop existing stackmap at this offset
1304: stackMapTableBuffer[--stackMapBufferSize] = null;
1305: lastFrame = frameBeforeLast;
1306: frameBeforeLast = null;
1307: }
1308:
1309: StackMapFrame frame = new StackMapFrame();
1310: frame.pc = pc;
1311:
1312: int localCount = 0;
1313: Type[] locals = new Type[localsSize];
1314: for (int i = 0; i < localsSize; i++, localCount++) {
1315: if (state.defined.isMember(i) && lvar[i] != null) {
1316: Type vtype = lvar[i].sym.type;
1317: if (!(vtype instanceof UninitializedType))
1318: vtype = types.erasure(vtype);
1319: locals[i] = vtype;
1320: if (width(vtype) > 1)
1321: i++;
1322: }
1323: }
1324: frame.locals = new Type[localCount];
1325: for (int i = 0, j = 0; i < localsSize; i++, j++) {
1326: assert (j < localCount);
1327: frame.locals[j] = locals[i];
1328: if (width(locals[i]) > 1)
1329: i++;
1330: }
1331:
1332: int stackCount = 0;
1333: for (int i = 0; i < state.stacksize; i++) {
1334: if (state.stack[i] != null) {
1335: stackCount++;
1336: }
1337: }
1338: frame.stack = new Type[stackCount];
1339: stackCount = 0;
1340: for (int i = 0; i < state.stacksize; i++) {
1341: if (state.stack[i] != null) {
1342: frame.stack[stackCount++] = state.stack[i];
1343: }
1344: }
1345:
1346: if (stackMapTableBuffer == null) {
1347: stackMapTableBuffer = new StackMapTableFrame[20];
1348: } else if (stackMapTableBuffer.length == stackMapBufferSize) {
1349: StackMapTableFrame[] newStackMapTableBuffer = new StackMapTableFrame[stackMapBufferSize << 1];
1350: System.arraycopy(stackMapTableBuffer, 0,
1351: newStackMapTableBuffer, 0, stackMapBufferSize);
1352: stackMapTableBuffer = newStackMapTableBuffer;
1353: }
1354: stackMapTableBuffer[stackMapBufferSize++] = StackMapTableFrame
1355: .getInstance(frame, lastFrame.pc, lastFrame.locals,
1356: types);
1357:
1358: frameBeforeLast = lastFrame;
1359: lastFrame = frame;
1360: }
1361:
1362: StackMapFrame getInitialFrame() {
1363: StackMapFrame frame = new StackMapFrame();
1364: List<Type> arg_types = ((MethodType) meth.externalType(types)).argtypes;
1365: int len = arg_types.length();
1366: int count = 0;
1367: if (!meth.isStatic()) {
1368: Type this Type = meth.owner.type;
1369: frame.locals = new Type[len + 1];
1370: if (meth.isConstructor() && this Type != syms.objectType) {
1371: frame.locals[count++] = UninitializedType
1372: .uninitializedThis(this Type);
1373: } else {
1374: frame.locals[count++] = types.erasure(this Type);
1375: }
1376: } else {
1377: frame.locals = new Type[len];
1378: }
1379: for (Type arg_type : arg_types) {
1380: frame.locals[count++] = types.erasure(arg_type);
1381: }
1382: frame.pc = -1;
1383: frame.stack = null;
1384: return frame;
1385: }
1386:
1387: /**************************************************************************
1388: * Operations having to do with jumps
1389: *************************************************************************/
1390:
1391: /** A chain represents a list of unresolved jumps. Jump locations
1392: * are sorted in decreasing order.
1393: */
1394: public static class Chain {
1395:
1396: /** The position of the jump instruction.
1397: */
1398: public final int pc;
1399:
1400: /** The machine state after the jump instruction.
1401: * Invariant: all elements of a chain list have the same stacksize
1402: * and compatible stack and register contents.
1403: */
1404: Code.State state;
1405:
1406: /** The next jump in the list.
1407: */
1408: public final Chain next;
1409:
1410: /** Construct a chain from its jump position, stacksize, previous
1411: * chain, and machine state.
1412: */
1413: public Chain(int pc, Chain next, Code.State state) {
1414: this .pc = pc;
1415: this .next = next;
1416: this .state = state;
1417: }
1418: }
1419:
1420: /** Negate a branch opcode.
1421: */
1422: public static int negate(int opcode) {
1423: if (opcode == if_acmp_null)
1424: return if_acmp_nonnull;
1425: else if (opcode == if_acmp_nonnull)
1426: return if_acmp_null;
1427: else
1428: return ((opcode + 1) ^ 1) - 1;
1429: }
1430:
1431: /** Emit a jump instruction.
1432: * Return code pointer of instruction to be patched.
1433: */
1434: public int emitJump(int opcode) {
1435: if (fatcode) {
1436: if (opcode == goto_ || opcode == jsr) {
1437: emitop4(opcode + goto_w - goto_, 0);
1438: } else {
1439: emitop2(negate(opcode), 8);
1440: emitop4(goto_w, 0);
1441: alive = true;
1442: pendingStackMap = needStackMap;
1443: }
1444: return cp - 5;
1445: } else {
1446: emitop2(opcode, 0);
1447: return cp - 3;
1448: }
1449: }
1450:
1451: /** Emit a branch with given opcode; return its chain.
1452: * branch differs from jump in that jsr is treated as no-op.
1453: */
1454: public Chain branch(int opcode) {
1455: Chain result = null;
1456: if (opcode == goto_) {
1457: result = pendingJumps;
1458: pendingJumps = null;
1459: }
1460: if (opcode != dontgoto && isAlive()) {
1461: result = new Chain(emitJump(opcode), result, state.dup());
1462: fixedPc = fatcode;
1463: if (opcode == goto_)
1464: alive = false;
1465: }
1466: return result;
1467: }
1468:
1469: /** Resolve chain to point to given target.
1470: */
1471: public void resolve(Chain chain, int target) {
1472: boolean changed = false;
1473: State newState = state;
1474: for (; chain != null; chain = chain.next) {
1475: assert state != chain.state;
1476: assert target > chain.pc || state.stacksize == 0;
1477: if (target >= cp) {
1478: target = cp;
1479: } else if (get1(target) == goto_) {
1480: if (fatcode)
1481: target = target + get4(target + 1);
1482: else
1483: target = target + get2(target + 1);
1484: }
1485: if (get1(chain.pc) == goto_ && chain.pc + 3 == target
1486: && target == cp && !fixedPc) {
1487: // If goto the next instruction, the jump is not needed:
1488: // compact the code.
1489: cp = cp - 3;
1490: target = target - 3;
1491: if (chain.next == null) {
1492: // This is the only jump to the target. Exit the loop
1493: // without setting new state. The code is reachable
1494: // from the instruction before goto_.
1495: alive = true;
1496: break;
1497: }
1498: } else {
1499: if (fatcode)
1500: put4(chain.pc + 1, target - chain.pc);
1501: else if (target - chain.pc < Short.MIN_VALUE
1502: || target - chain.pc > Short.MAX_VALUE)
1503: fatcode = true;
1504: else
1505: put2(chain.pc + 1, target - chain.pc);
1506: assert !alive
1507: || chain.state.stacksize == newState.stacksize
1508: && chain.state.nlocks == newState.nlocks;
1509: }
1510: fixedPc = true;
1511: if (cp == target) {
1512: changed = true;
1513: if (debugCode)
1514: System.err.println("resolving chain state="
1515: + chain.state);
1516: if (alive) {
1517: newState = chain.state.join(newState);
1518: } else {
1519: newState = chain.state;
1520: alive = true;
1521: }
1522: }
1523: }
1524: assert !changed || state != newState;
1525: if (state != newState) {
1526: setDefined(newState.defined);
1527: state = newState;
1528: pendingStackMap = needStackMap;
1529: }
1530: }
1531:
1532: /** Resolve chain to point to current code pointer.
1533: */
1534: public void resolve(Chain chain) {
1535: assert !alive || chain == null
1536: || state.stacksize == chain.state.stacksize
1537: && state.nlocks == chain.state.nlocks;
1538: pendingJumps = mergeChains(chain, pendingJumps);
1539: }
1540:
1541: /** Resolve any pending jumps.
1542: */
1543: public void resolvePending() {
1544: Chain x = pendingJumps;
1545: pendingJumps = null;
1546: resolve(x, cp);
1547: }
1548:
1549: /** Merge the jumps in of two chains into one.
1550: */
1551: public static Chain mergeChains(Chain chain1, Chain chain2) {
1552: // recursive merge sort
1553: if (chain2 == null)
1554: return chain1;
1555: if (chain1 == null)
1556: return chain2;
1557: assert chain1.state.stacksize == chain2.state.stacksize
1558: && chain1.state.nlocks == chain2.state.nlocks;
1559: if (chain1.pc < chain2.pc)
1560: return new Chain(chain2.pc,
1561: mergeChains(chain1, chain2.next), chain2.state);
1562: return new Chain(chain1.pc, mergeChains(chain1.next, chain2),
1563: chain1.state);
1564: }
1565:
1566: /* **************************************************************************
1567: * Catch clauses
1568: ****************************************************************************/
1569:
1570: /** Add a catch clause to code.
1571: */
1572: public void addCatch(char startPc, char endPc, char handlerPc,
1573: char catchType) {
1574: catchInfo.append(new char[] { startPc, endPc, handlerPc,
1575: catchType });
1576: }
1577:
1578: /* **************************************************************************
1579: * Line numbers
1580: ****************************************************************************/
1581:
1582: /** Add a line number entry.
1583: */
1584: public void addLineNumber(char startPc, char lineNumber) {
1585: if (lineDebugInfo) {
1586: if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc)
1587: lineInfo = lineInfo.tail;
1588: if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber)
1589: lineInfo = lineInfo.prepend(new char[] { startPc,
1590: lineNumber });
1591: }
1592: }
1593:
1594: /** Mark beginning of statement.
1595: */
1596: public void statBegin(int pos) {
1597: if (pos != Position.NOPOS) {
1598: pendingStatPos = pos;
1599: }
1600: }
1601:
1602: /** Force stat begin eagerly
1603: */
1604: public void markStatBegin() {
1605: if (alive && lineDebugInfo) {
1606: int line = lineMap.getLineNumber(pendingStatPos);
1607: char cp1 = (char) cp;
1608: char line1 = (char) line;
1609: if (cp1 == cp && line1 == line)
1610: addLineNumber(cp1, line1);
1611: }
1612: pendingStatPos = Position.NOPOS;
1613: }
1614:
1615: /* **************************************************************************
1616: * Simulated VM machine state
1617: ****************************************************************************/
1618:
1619: class State implements Cloneable {
1620: /** The set of registers containing values. */
1621: Bits defined;
1622:
1623: /** The (types of the) contents of the machine stack. */
1624: Type[] stack;
1625:
1626: /** The first stack position currently unused. */
1627: int stacksize;
1628:
1629: /** The numbers of registers containing locked monitors. */
1630: int[] locks;
1631: int nlocks;
1632:
1633: State() {
1634: defined = new Bits();
1635: stack = new Type[16];
1636: }
1637:
1638: State dup() {
1639: try {
1640: State state = (State) super .clone();
1641: state.defined = defined.dup();
1642: state.stack = stack.clone();
1643: if (locks != null)
1644: state.locks = locks.clone();
1645: if (debugCode) {
1646: System.err.println("duping state " + this );
1647: dump();
1648: }
1649: return state;
1650: } catch (CloneNotSupportedException ex) {
1651: throw new AssertionError(ex);
1652: }
1653: }
1654:
1655: void lock(int register) {
1656: if (locks == null) {
1657: locks = new int[20];
1658: } else if (locks.length == nlocks) {
1659: int[] newLocks = new int[locks.length << 1];
1660: System.arraycopy(locks, 0, newLocks, 0, locks.length);
1661: locks = newLocks;
1662: }
1663: locks[nlocks] = register;
1664: nlocks++;
1665: }
1666:
1667: void unlock(int register) {
1668: nlocks--;
1669: assert locks[nlocks] == register;
1670: locks[nlocks] = -1;
1671: }
1672:
1673: void push(Type t) {
1674: if (debugCode)
1675: System.err.println(" pushing " + t);
1676: switch (t.tag) {
1677: case TypeTags.VOID:
1678: return;
1679: case TypeTags.BYTE:
1680: case TypeTags.CHAR:
1681: case TypeTags.SHORT:
1682: case TypeTags.BOOLEAN:
1683: t = syms.intType;
1684: break;
1685: default:
1686: break;
1687: }
1688: if (stacksize + 2 >= stack.length) {
1689: Type[] newstack = new Type[2 * stack.length];
1690: System.arraycopy(stack, 0, newstack, 0, stack.length);
1691: stack = newstack;
1692: }
1693: stack[stacksize++] = t;
1694: switch (width(t)) {
1695: case 1:
1696: break;
1697: case 2:
1698: stack[stacksize++] = null;
1699: break;
1700: default:
1701: throw new AssertionError(t);
1702: }
1703: if (stacksize > max_stack)
1704: max_stack = stacksize;
1705: }
1706:
1707: Type pop1() {
1708: if (debugCode)
1709: System.err.println(" popping " + 1);
1710: stacksize--;
1711: Type result = stack[stacksize];
1712: stack[stacksize] = null;
1713: assert result != null && width(result) == 1;
1714: return result;
1715: }
1716:
1717: Type peek() {
1718: return stack[stacksize - 1];
1719: }
1720:
1721: Type pop2() {
1722: if (debugCode)
1723: System.err.println(" popping " + 2);
1724: stacksize -= 2;
1725: Type result = stack[stacksize];
1726: stack[stacksize] = null;
1727: assert stack[stacksize + 1] == null;
1728: assert result != null && width(result) == 2;
1729: return result;
1730: }
1731:
1732: void pop(int n) {
1733: if (debugCode)
1734: System.err.println(" popping " + n);
1735: while (n > 0) {
1736: stack[--stacksize] = null;
1737: n--;
1738: }
1739: }
1740:
1741: void pop(Type t) {
1742: pop(width(t));
1743: }
1744:
1745: /** Force the top of the stack to be treated as this supertype
1746: * of its current type. */
1747: void forceStackTop(Type t) {
1748: if (!alive)
1749: return;
1750: switch (t.tag) {
1751: case CLASS:
1752: case ARRAY:
1753: int width = width(t);
1754: Type old = stack[stacksize - width];
1755: assert types.isSubtype(types.erasure(old), types
1756: .erasure(t));
1757: stack[stacksize - width] = t;
1758: break;
1759: default:
1760: }
1761: }
1762:
1763: void markInitialized(UninitializedType old) {
1764: Type newtype = old.initializedType();
1765: for (int i = 0; i < stacksize; i++)
1766: if (stack[i] == old)
1767: stack[i] = newtype;
1768: for (int i = 0; i < lvar.length; i++) {
1769: LocalVar lv = lvar[i];
1770: if (lv != null && lv.sym.type == old) {
1771: VarSymbol sym = lv.sym;
1772: sym = sym.clone(sym.owner);
1773: sym.type = newtype;
1774: LocalVar newlv = lvar[i] = new LocalVar(sym);
1775: // should the following be initialized to cp?
1776: newlv.start_pc = lv.start_pc;
1777: }
1778: }
1779: }
1780:
1781: State join(State other) {
1782: defined = defined.andSet(other.defined);
1783: assert stacksize == other.stacksize;
1784: assert nlocks == other.nlocks;
1785: for (int i = 0; i < stacksize;) {
1786: Type t = stack[i];
1787: Type tother = other.stack[i];
1788: Type result = t == tother ? t : types.isSubtype(t,
1789: tother) ? tother
1790: : types.isSubtype(tother, t) ? t : error();
1791: int w = width(result);
1792: stack[i] = result;
1793: if (w == 2)
1794: assert stack[i + 1] == null;
1795: i += w;
1796: }
1797: return this ;
1798: }
1799:
1800: Type error() {
1801: throw new AssertionError(
1802: "inconsistent stack types at join point");
1803: }
1804:
1805: void dump() {
1806: dump(-1);
1807: }
1808:
1809: void dump(int pc) {
1810: System.err.print("stackMap for " + meth.owner + "." + meth);
1811: if (pc == -1)
1812: System.out.println();
1813: else
1814: System.out.println(" at " + pc);
1815: System.err.println(" stack (from bottom):");
1816: for (int i = 0; i < stacksize; i++)
1817: System.err.println(" " + i + ": " + stack[i]);
1818:
1819: int lastLocal = 0;
1820: for (int i = max_locals - 1; i >= 0; i--) {
1821: if (defined.isMember(i)) {
1822: lastLocal = i;
1823: break;
1824: }
1825: }
1826: if (lastLocal >= 0)
1827: System.err.println(" locals:");
1828: for (int i = 0; i <= lastLocal; i++) {
1829: System.err.print(" " + i + ": ");
1830: if (defined.isMember(i)) {
1831: LocalVar var = lvar[i];
1832: if (var == null) {
1833: System.err.println("(none)");
1834: } else if (var.sym == null)
1835: System.err.println("UNKNOWN!");
1836: else
1837: System.err.println("" + var.sym + " of type "
1838: + var.sym.erasure(types));
1839: } else {
1840: System.err.println("undefined");
1841: }
1842: }
1843: if (nlocks != 0) {
1844: System.err.print(" locks:");
1845: for (int i = 0; i < nlocks; i++) {
1846: System.err.print(" " + locks[i]);
1847: }
1848: System.err.println();
1849: }
1850: }
1851: }
1852:
1853: static Type jsrReturnValue = new Type(TypeTags.INT, null);
1854:
1855: /* **************************************************************************
1856: * Local variables
1857: ****************************************************************************/
1858:
1859: /** A live range of a local variable. */
1860: static class LocalVar {
1861: final VarSymbol sym;
1862: final char reg;
1863: char start_pc = Character.MAX_VALUE;
1864: char length = Character.MAX_VALUE;
1865:
1866: LocalVar(VarSymbol v) {
1867: this .sym = v;
1868: this .reg = (char) v.adr;
1869: }
1870:
1871: public LocalVar dup() {
1872: return new LocalVar(sym);
1873: }
1874:
1875: public String toString() {
1876: return "" + sym + " in register " + ((int) reg)
1877: + " starts at pc=" + ((int) start_pc) + " length="
1878: + ((int) length);
1879: }
1880: };
1881:
1882: /** Local variables, indexed by register. */
1883: LocalVar[] lvar;
1884:
1885: /** Add a new local variable. */
1886: private void addLocalVar(VarSymbol v) {
1887: int adr = v.adr;
1888: if (adr + 1 >= lvar.length) {
1889: int newlength = lvar.length << 1;
1890: if (newlength <= adr)
1891: newlength = adr + 10;
1892: LocalVar[] new_lvar = new LocalVar[newlength];
1893: System.arraycopy(lvar, 0, new_lvar, 0, lvar.length);
1894: lvar = new_lvar;
1895: }
1896: assert lvar[adr] == null;
1897: if (pendingJumps != null)
1898: resolvePending();
1899: lvar[adr] = new LocalVar(v);
1900: state.defined.excl(adr);
1901: }
1902:
1903: /** Set the current variable defined state. */
1904: public void setDefined(Bits newDefined) {
1905: if (alive && newDefined != state.defined) {
1906: Bits diff = state.defined.dup().xorSet(newDefined);
1907: for (int adr = diff.nextBit(0); adr >= 0; adr = diff
1908: .nextBit(adr + 1)) {
1909: if (adr >= nextreg)
1910: state.defined.excl(adr);
1911: else if (state.defined.isMember(adr))
1912: setUndefined(adr);
1913: else
1914: setDefined(adr);
1915: }
1916: }
1917: }
1918:
1919: /** Mark a register as being (possibly) defined. */
1920: public void setDefined(int adr) {
1921: LocalVar v = lvar[adr];
1922: if (v == null) {
1923: state.defined.excl(adr);
1924: } else {
1925: state.defined.incl(adr);
1926: if (cp < Character.MAX_VALUE) {
1927: if (v.start_pc == Character.MAX_VALUE)
1928: v.start_pc = (char) cp;
1929: }
1930: }
1931: }
1932:
1933: /** Mark a register as being undefined. */
1934: public void setUndefined(int adr) {
1935: state.defined.excl(adr);
1936: if (adr < lvar.length && lvar[adr] != null
1937: && lvar[adr].start_pc != Character.MAX_VALUE) {
1938: LocalVar v = lvar[adr];
1939: char length = (char) (curPc() - v.start_pc);
1940: if (length > 0 && length < Character.MAX_VALUE) {
1941: lvar[adr] = v.dup();
1942: v.length = length;
1943: putVar(v);
1944: } else {
1945: v.start_pc = Character.MAX_VALUE;
1946: }
1947: }
1948: }
1949:
1950: /** End the scope of a variable. */
1951: private void endScope(int adr) {
1952: LocalVar v = lvar[adr];
1953: if (v != null) {
1954: lvar[adr] = null;
1955: if (v.start_pc != Character.MAX_VALUE) {
1956: char length = (char) (curPc() - v.start_pc);
1957: if (length < Character.MAX_VALUE) {
1958: v.length = length;
1959: putVar(v);
1960: }
1961: }
1962: }
1963: state.defined.excl(adr);
1964: }
1965:
1966: /** Put a live variable range into the buffer to be output to the
1967: * class file.
1968: */
1969: void putVar(LocalVar var) {
1970: if (!varDebugInfo)
1971: return;
1972: if ((var.sym.flags() & Flags.SYNTHETIC) != 0)
1973: return;
1974: if (varBuffer == null)
1975: varBuffer = new LocalVar[20];
1976: else if (varBufferSize >= varBuffer.length) {
1977: LocalVar[] newVarBuffer = new LocalVar[varBufferSize * 2];
1978: System.arraycopy(varBuffer, 0, newVarBuffer, 0,
1979: varBuffer.length);
1980: varBuffer = newVarBuffer;
1981: }
1982: varBuffer[varBufferSize++] = var;
1983: }
1984:
1985: /** Previously live local variables, to be put into the variable table. */
1986: LocalVar[] varBuffer;
1987: int varBufferSize;
1988:
1989: /** Create a new local variable address and return it.
1990: */
1991: private int newLocal(int typecode) {
1992: int reg = nextreg;
1993: int w = width(typecode);
1994: nextreg = reg + w;
1995: if (nextreg > max_locals)
1996: max_locals = nextreg;
1997: return reg;
1998: }
1999:
2000: private int newLocal(Type type) {
2001: return newLocal(typecode(type));
2002: }
2003:
2004: public int newLocal(VarSymbol v) {
2005: int reg = v.adr = newLocal(v.erasure(types));
2006: addLocalVar(v);
2007: return reg;
2008: }
2009:
2010: /** Start a set of fresh registers.
2011: */
2012: public void newRegSegment() {
2013: nextreg = max_locals;
2014: }
2015:
2016: /** End scopes of all variables with registers >= first.
2017: */
2018: public void endScopes(int first) {
2019: int prevNextReg = nextreg;
2020: nextreg = first;
2021: for (int i = nextreg; i < prevNextReg; i++)
2022: endScope(i);
2023: }
2024:
2025: /**************************************************************************
2026: * static tables
2027: *************************************************************************/
2028:
2029: public static String mnem(int opcode) {
2030: return Mneumonics.mnem[opcode];
2031: }
2032:
2033: private static class Mneumonics {
2034: private final static String[] mnem = new String[ByteCodeCount];
2035: static {
2036: mnem[nop] = "nop";
2037: mnem[aconst_null] = "aconst_null";
2038: mnem[iconst_m1] = "iconst_m1";
2039: mnem[iconst_0] = "iconst_0";
2040: mnem[iconst_1] = "iconst_1";
2041: mnem[iconst_2] = "iconst_2";
2042: mnem[iconst_3] = "iconst_3";
2043: mnem[iconst_4] = "iconst_4";
2044: mnem[iconst_5] = "iconst_5";
2045: mnem[lconst_0] = "lconst_0";
2046: mnem[lconst_1] = "lconst_1";
2047: mnem[fconst_0] = "fconst_0";
2048: mnem[fconst_1] = "fconst_1";
2049: mnem[fconst_2] = "fconst_2";
2050: mnem[dconst_0] = "dconst_0";
2051: mnem[dconst_1] = "dconst_1";
2052: mnem[bipush] = "bipush";
2053: mnem[sipush] = "sipush";
2054: mnem[ldc1] = "ldc1";
2055: mnem[ldc2] = "ldc2";
2056: mnem[ldc2w] = "ldc2w";
2057: mnem[iload] = "iload";
2058: mnem[lload] = "lload";
2059: mnem[fload] = "fload";
2060: mnem[dload] = "dload";
2061: mnem[aload] = "aload";
2062: mnem[iload_0] = "iload_0";
2063: mnem[lload_0] = "lload_0";
2064: mnem[fload_0] = "fload_0";
2065: mnem[dload_0] = "dload_0";
2066: mnem[aload_0] = "aload_0";
2067: mnem[iload_1] = "iload_1";
2068: mnem[lload_1] = "lload_1";
2069: mnem[fload_1] = "fload_1";
2070: mnem[dload_1] = "dload_1";
2071: mnem[aload_1] = "aload_1";
2072: mnem[iload_2] = "iload_2";
2073: mnem[lload_2] = "lload_2";
2074: mnem[fload_2] = "fload_2";
2075: mnem[dload_2] = "dload_2";
2076: mnem[aload_2] = "aload_2";
2077: mnem[iload_3] = "iload_3";
2078: mnem[lload_3] = "lload_3";
2079: mnem[fload_3] = "fload_3";
2080: mnem[dload_3] = "dload_3";
2081: mnem[aload_3] = "aload_3";
2082: mnem[iaload] = "iaload";
2083: mnem[laload] = "laload";
2084: mnem[faload] = "faload";
2085: mnem[daload] = "daload";
2086: mnem[aaload] = "aaload";
2087: mnem[baload] = "baload";
2088: mnem[caload] = "caload";
2089: mnem[saload] = "saload";
2090: mnem[istore] = "istore";
2091: mnem[lstore] = "lstore";
2092: mnem[fstore] = "fstore";
2093: mnem[dstore] = "dstore";
2094: mnem[astore] = "astore";
2095: mnem[istore_0] = "istore_0";
2096: mnem[lstore_0] = "lstore_0";
2097: mnem[fstore_0] = "fstore_0";
2098: mnem[dstore_0] = "dstore_0";
2099: mnem[astore_0] = "astore_0";
2100: mnem[istore_1] = "istore_1";
2101: mnem[lstore_1] = "lstore_1";
2102: mnem[fstore_1] = "fstore_1";
2103: mnem[dstore_1] = "dstore_1";
2104: mnem[astore_1] = "astore_1";
2105: mnem[istore_2] = "istore_2";
2106: mnem[lstore_2] = "lstore_2";
2107: mnem[fstore_2] = "fstore_2";
2108: mnem[dstore_2] = "dstore_2";
2109: mnem[astore_2] = "astore_2";
2110: mnem[istore_3] = "istore_3";
2111: mnem[lstore_3] = "lstore_3";
2112: mnem[fstore_3] = "fstore_3";
2113: mnem[dstore_3] = "dstore_3";
2114: mnem[astore_3] = "astore_3";
2115: mnem[iastore] = "iastore";
2116: mnem[lastore] = "lastore";
2117: mnem[fastore] = "fastore";
2118: mnem[dastore] = "dastore";
2119: mnem[aastore] = "aastore";
2120: mnem[bastore] = "bastore";
2121: mnem[castore] = "castore";
2122: mnem[sastore] = "sastore";
2123: mnem[pop] = "pop";
2124: mnem[pop2] = "pop2";
2125: mnem[dup] = "dup";
2126: mnem[dup_x1] = "dup_x1";
2127: mnem[dup_x2] = "dup_x2";
2128: mnem[dup2] = "dup2";
2129: mnem[dup2_x1] = "dup2_x1";
2130: mnem[dup2_x2] = "dup2_x2";
2131: mnem[swap] = "swap";
2132: mnem[iadd] = "iadd";
2133: mnem[ladd] = "ladd";
2134: mnem[fadd] = "fadd";
2135: mnem[dadd] = "dadd";
2136: mnem[isub] = "isub";
2137: mnem[lsub] = "lsub";
2138: mnem[fsub] = "fsub";
2139: mnem[dsub] = "dsub";
2140: mnem[imul] = "imul";
2141: mnem[lmul] = "lmul";
2142: mnem[fmul] = "fmul";
2143: mnem[dmul] = "dmul";
2144: mnem[idiv] = "idiv";
2145: mnem[ldiv] = "ldiv";
2146: mnem[fdiv] = "fdiv";
2147: mnem[ddiv] = "ddiv";
2148: mnem[imod] = "imod";
2149: mnem[lmod] = "lmod";
2150: mnem[fmod] = "fmod";
2151: mnem[dmod] = "dmod";
2152: mnem[ineg] = "ineg";
2153: mnem[lneg] = "lneg";
2154: mnem[fneg] = "fneg";
2155: mnem[dneg] = "dneg";
2156: mnem[ishl] = "ishl";
2157: mnem[lshl] = "lshl";
2158: mnem[ishr] = "ishr";
2159: mnem[lshr] = "lshr";
2160: mnem[iushr] = "iushr";
2161: mnem[lushr] = "lushr";
2162: mnem[iand] = "iand";
2163: mnem[land] = "land";
2164: mnem[ior] = "ior";
2165: mnem[lor] = "lor";
2166: mnem[ixor] = "ixor";
2167: mnem[lxor] = "lxor";
2168: mnem[iinc] = "iinc";
2169: mnem[i2l] = "i2l";
2170: mnem[i2f] = "i2f";
2171: mnem[i2d] = "i2d";
2172: mnem[l2i] = "l2i";
2173: mnem[l2f] = "l2f";
2174: mnem[l2d] = "l2d";
2175: mnem[f2i] = "f2i";
2176: mnem[f2l] = "f2l";
2177: mnem[f2d] = "f2d";
2178: mnem[d2i] = "d2i";
2179: mnem[d2l] = "d2l";
2180: mnem[d2f] = "d2f";
2181: mnem[int2byte] = "int2byte";
2182: mnem[int2char] = "int2char";
2183: mnem[int2short] = "int2short";
2184: mnem[lcmp] = "lcmp";
2185: mnem[fcmpl] = "fcmpl";
2186: mnem[fcmpg] = "fcmpg";
2187: mnem[dcmpl] = "dcmpl";
2188: mnem[dcmpg] = "dcmpg";
2189: mnem[ifeq] = "ifeq";
2190: mnem[ifne] = "ifne";
2191: mnem[iflt] = "iflt";
2192: mnem[ifge] = "ifge";
2193: mnem[ifgt] = "ifgt";
2194: mnem[ifle] = "ifle";
2195: mnem[if_icmpeq] = "if_icmpeq";
2196: mnem[if_icmpne] = "if_icmpne";
2197: mnem[if_icmplt] = "if_icmplt";
2198: mnem[if_icmpge] = "if_icmpge";
2199: mnem[if_icmpgt] = "if_icmpgt";
2200: mnem[if_icmple] = "if_icmple";
2201: mnem[if_acmpeq] = "if_acmpeq";
2202: mnem[if_acmpne] = "if_acmpne";
2203: mnem[goto_] = "goto_";
2204: mnem[jsr] = "jsr";
2205: mnem[ret] = "ret";
2206: mnem[tableswitch] = "tableswitch";
2207: mnem[lookupswitch] = "lookupswitch";
2208: mnem[ireturn] = "ireturn";
2209: mnem[lreturn] = "lreturn";
2210: mnem[freturn] = "freturn";
2211: mnem[dreturn] = "dreturn";
2212: mnem[areturn] = "areturn";
2213: mnem[return_] = "return_";
2214: mnem[getstatic] = "getstatic";
2215: mnem[putstatic] = "putstatic";
2216: mnem[getfield] = "getfield";
2217: mnem[putfield] = "putfield";
2218: mnem[invokevirtual] = "invokevirtual";
2219: mnem[invokespecial] = "invokespecial";
2220: mnem[invokestatic] = "invokestatic";
2221: mnem[invokeinterface] = "invokeinterface";
2222: // mnem[___unused___] = "___unused___";
2223: mnem[new_] = "new_";
2224: mnem[newarray] = "newarray";
2225: mnem[anewarray] = "anewarray";
2226: mnem[arraylength] = "arraylength";
2227: mnem[athrow] = "athrow";
2228: mnem[checkcast] = "checkcast";
2229: mnem[instanceof _] = "instanceof_";
2230: mnem[monitorenter] = "monitorenter";
2231: mnem[monitorexit] = "monitorexit";
2232: mnem[wide] = "wide";
2233: mnem[multianewarray] = "multianewarray";
2234: mnem[if_acmp_null] = "if_acmp_null";
2235: mnem[if_acmp_nonnull] = "if_acmp_nonnull";
2236: mnem[goto_w] = "goto_w";
2237: mnem[jsr_w] = "jsr_w";
2238: mnem[breakpoint] = "breakpoint";
2239: }
2240: }
2241: }
|