| 1 | /* | 
| 2 |  * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved. | 
| 3 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
| 4 |  * | 
| 5 |  * This code is free software; you can redistribute it and/or modify it | 
| 6 |  * under the terms of the GNU General Public License version 2 only, as | 
| 7 |  * published by the Free Software Foundation.  Sun designates this | 
| 8 |  * particular file as subject to the "Classpath" exception as provided | 
| 9 |  * by Sun in the LICENSE file that accompanied this code. | 
| 10 |  * | 
| 11 |  * This code is distributed in the hope that it will be useful, but WITHOUT | 
| 12 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
| 13 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
| 14 |  * version 2 for more details (a copy is included in the LICENSE file that | 
| 15 |  * accompanied this code). | 
| 16 |  * | 
| 17 |  * You should have received a copy of the GNU General Public License version | 
| 18 |  * 2 along with this work; if not, write to the Free Software Foundation, | 
| 19 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
| 20 |  * | 
| 21 |  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | 
| 22 |  * CA 95054 USA or visit www.sun.com if you need additional information or | 
| 23 |  * have any questions. | 
| 24 |  */ | 
| 25 |   | 
| 26 | package com.sun.tools.javac.jvm; | 
| 27 |   | 
| 28 | import com.sun.tools.javac.code.*; | 
| 29 | import com.sun.tools.javac.code.Symbol.*; | 
| 30 | import com.sun.tools.javac.util.*; | 
| 31 | import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; | 
| 32 |   | 
| 33 | import static com.sun.tools.javac.code.TypeTags.*; | 
| 34 | import static com.sun.tools.javac.jvm.ByteCodes.*; | 
| 35 | import static com.sun.tools.javac.jvm.UninitializedType.*; | 
| 36 | import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame; | 
| 37 |   | 
| 38 | /** An internal structure that corresponds to the code attribute of | 
| 39 |  *  methods in a classfile. The class also provides some utility operations to | 
| 40 |  *  generate bytecode instructions. | 
| 41 |  * | 
| 42 |  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If | 
| 43 |  *  you write code that depends on this, you do so at your own risk. | 
| 44 |  *  This code and its internal interfaces are subject to change or | 
| 45 |  *  deletion without notice.</b> | 
| 46 |  */ | 
| 47 | public class Code { | 
| 48 |   | 
| 49 |     public final boolean debugCode; | 
| 50 |     public final boolean needStackMap; | 
| 51 |   | 
| 52 |     public enum StackMapFormat { | 
| 53 |         NONE, | 
| 54 |         CLDC { | 
| 55 |             Name getAttributeName(Name.Table names) { | 
| 56 |                 return names.StackMap; | 
| 57 |             } | 
| 58 |         }, | 
| 59 |         JSR202 { | 
| 60 |             Name getAttributeName(Name.Table names) { | 
| 61 |                 return names.StackMapTable; | 
| 62 |             } | 
| 63 |         }; | 
| 64 |         Name getAttributeName(Name.Table names) { | 
| 65 |             return names.empty; | 
| 66 |         } | 
| 67 |     } | 
| 68 |   | 
| 69 |     final Types types; | 
| 70 |     final Symtab syms; | 
| 71 |   | 
| 72 | /*---------- classfile fields: --------------- */ | 
| 73 |   | 
| 74 |     /** The maximum stack size. | 
| 75 |      */ | 
| 76 |     public int max_stack = 0; | 
| 77 |   | 
| 78 |     /** The maximum number of local variable slots. | 
| 79 |      */ | 
| 80 |     public int max_locals = 0; | 
| 81 |   | 
| 82 |     /** The code buffer. | 
| 83 |      */ | 
| 84 |     public byte[] code = new byte[64]; | 
| 85 |   | 
| 86 |     /** the current code pointer. | 
| 87 |      */ | 
| 88 |     public int cp = 0; | 
| 89 |   | 
| 90 |     /** Check the code against VM spec limits; if | 
| 91 |      *  problems report them and return true. | 
| 92 |      */ | 
| 93 |     public boolean checkLimits(DiagnosticPosition pos, Log log) { | 
| 94 |         if (cp > ClassFile.MAX_CODE) { | 
| 95 |             log.error(pos, "limit.code"); | 
| 96 |             return true; | 
| 97 |         } | 
| 98 |         if (max_locals > ClassFile.MAX_LOCALS) { | 
| 99 |             log.error(pos, "limit.locals"); | 
| 100 |             return true; | 
| 101 |         } | 
| 102 |         if (max_stack > ClassFile.MAX_STACK) { | 
| 103 |             log.error(pos, "limit.stack"); | 
| 104 |             return true; | 
| 105 |         } | 
| 106 |         return false; | 
| 107 |     } | 
| 108 |   | 
| 109 |     /** A buffer for expression catch data. Each enter is a vector | 
| 110 |      *  of four unsigned shorts. | 
| 111 |      */ | 
| 112 |     ListBuffer<char[]> catchInfo = new ListBuffer<char[]>(); | 
| 113 |   | 
| 114 |     /** A buffer for line number information. Each entry is a vector | 
| 115 |      *  of two unsigned shorts. | 
| 116 |      */ | 
| 117 |     List<char[]> lineInfo = List.nil(); // handled in stack fashion | 
| 118 |   | 
| 119 |     /** The CharacterRangeTable | 
| 120 |      */ | 
| 121 |     public CRTable crt; | 
| 122 |   | 
| 123 | /*---------- internal fields: --------------- */ | 
| 124 |   | 
| 125 |     /** Are we generating code with jumps >= 32K? | 
| 126 |      */ | 
| 127 |     public boolean fatcode; | 
| 128 |   | 
| 129 |     /** Code generation enabled? | 
| 130 |      */ | 
| 131 |     private boolean alive = true; | 
| 132 |   | 
| 133 |     /** The current machine state (registers and stack). | 
| 134 |      */ | 
| 135 |     State state; | 
| 136 |   | 
| 137 |     /** Is it forbidden to compactify code, because something is | 
| 138 |      *  pointing to current location? | 
| 139 |      */ | 
| 140 |     private boolean fixedPc = false; | 
| 141 |   | 
| 142 |     /** The next available register. | 
| 143 |      */ | 
| 144 |     public int nextreg = 0; | 
| 145 |   | 
| 146 |     /** A chain for jumps to be resolved before the next opcode is emitted. | 
| 147 |      *  We do this lazily to avoid jumps to jumps. | 
| 148 |      */ | 
| 149 |     Chain pendingJumps = null; | 
| 150 |   | 
| 151 |     /** The position of the currently statement, if we are at the | 
| 152 |      *  start of this statement, NOPOS otherwise. | 
| 153 |      *  We need this to emit line numbers lazily, which we need to do | 
| 154 |      *  because of jump-to-jump optimization. | 
| 155 |      */ | 
| 156 |     int pendingStatPos = Position.NOPOS; | 
| 157 |   | 
| 158 |     /** Set true when a stackMap is needed at the current PC. */ | 
| 159 |     boolean pendingStackMap = false; | 
| 160 |   | 
| 161 |     /** The stack map format to be generated. */ | 
| 162 |     StackMapFormat stackMap; | 
| 163 |   | 
| 164 |     /** Switch: emit variable debug info. | 
| 165 |      */ | 
| 166 |     boolean varDebugInfo; | 
| 167 |   | 
| 168 |     /** Switch: emit line number info. | 
| 169 |      */ | 
| 170 |     boolean lineDebugInfo; | 
| 171 |   | 
| 172 |     /** Emit line number info if map supplied | 
| 173 |      */ | 
| 174 |     Position.LineMap lineMap; | 
| 175 |   | 
| 176 |     /** The constant pool of the current class. | 
| 177 |      */ | 
| 178 |     final Pool pool; | 
| 179 |   | 
| 180 |     final MethodSymbol meth; | 
| 181 |   | 
| 182 |     /** Construct a code object, given the settings of the fatcode, | 
| 183 |      *  debugging info switches and the CharacterRangeTable. | 
| 184 |      */ | 
| 185 |     public Code(MethodSymbol meth, | 
| 186 |                 boolean fatcode, | 
| 187 |                 Position.LineMap lineMap, | 
| 188 |                 boolean varDebugInfo, | 
| 189 |                 StackMapFormat stackMap, | 
| 190 |                 boolean debugCode, | 
| 191 |                 CRTable crt, | 
| 192 |                 Symtab syms, | 
| 193 |                 Types types, | 
| 194 |                 Pool pool) { | 
| 195 |         this.meth = meth; | 
| 196 |         this.fatcode = fatcode; | 
| 197 |         this.lineMap = lineMap; | 
| 198 |         this.lineDebugInfo = lineMap != null; | 
| 199 |         this.varDebugInfo = varDebugInfo; | 
| 200 |         this.crt = crt; | 
| 201 |         this.syms = syms; | 
| 202 |         this.types = types; | 
| 203 |         this.debugCode = debugCode; | 
| 204 |         this.stackMap = stackMap; | 
| 205 |         switch (stackMap) { | 
| 206 |         case CLDC: | 
| 207 |         case JSR202: | 
| 208 |             this.needStackMap = true; | 
| 209 |             break; | 
| 210 |         default: | 
| 211 |             this.needStackMap = false; | 
| 212 |         } | 
| 213 |         state = new State(); | 
| 214 |         lvar = new LocalVar[20]; | 
| 215 |         this.pool = pool; | 
| 216 |     } | 
| 217 |   | 
| 218 |   | 
| 219 | /* ************************************************************************** | 
| 220 |  * Typecodes & related stuff | 
| 221 |  ****************************************************************************/ | 
| 222 |   | 
| 223 |     /** Given a type, return its type code (used implicitly in the | 
| 224 |      *  JVM architecture). | 
| 225 |      */ | 
| 226 |     public static int typecode(Type type) { | 
| 227 |         switch (type.tag) { | 
| 228 |         case BYTE: return BYTEcode; | 
| 229 |         case SHORT: return SHORTcode; | 
| 230 |         case CHAR: return CHARcode; | 
| 231 |         case INT: return INTcode; | 
| 232 |         case LONG: return LONGcode; | 
| 233 |         case FLOAT: return FLOATcode; | 
| 234 |         case DOUBLE: return DOUBLEcode; | 
| 235 |         case BOOLEAN: return BYTEcode; | 
| 236 |         case VOID: return VOIDcode; | 
| 237 |         case CLASS: | 
| 238 |         case ARRAY: | 
| 239 |         case METHOD: | 
| 240 |         case BOT: | 
| 241 |         case TYPEVAR: | 
| 242 |         case UNINITIALIZED_THIS: | 
| 243 |         case UNINITIALIZED_OBJECT: | 
| 244 |             return OBJECTcode; | 
| 245 |         default: throw new AssertionError("typecode " + type.tag); | 
| 246 |         } | 
| 247 |     } | 
| 248 |   | 
| 249 |     /** Collapse type code for subtypes of int to INTcode. | 
| 250 |      */ | 
| 251 |     public static int truncate(int tc) { | 
| 252 |         switch (tc) { | 
| 253 |         case BYTEcode: case SHORTcode: case CHARcode: return INTcode; | 
| 254 |         default: return tc; | 
| 255 |         } | 
| 256 |     } | 
| 257 |   | 
| 258 |     /** The width in bytes of objects of the type. | 
| 259 |      */ | 
| 260 |     public static int width(int typecode) { | 
| 261 |         switch (typecode) { | 
| 262 |         case LONGcode: case DOUBLEcode: return 2; | 
| 263 |         case VOIDcode: return 0; | 
| 264 |         default: return 1; | 
| 265 |         } | 
| 266 |     } | 
| 267 |   | 
| 268 |     public static int width(Type type) { | 
| 269 |         return type == null ? 1 : width(typecode(type)); | 
| 270 |     } | 
| 271 |   | 
| 272 |     /** The total width taken up by a vector of objects. | 
| 273 |      */ | 
| 274 |     public static int width(List<Type> types) { | 
| 275 |         int w = 0; | 
| 276 |         for (List<Type> l = types; l.nonEmpty(); l = l.tail) | 
| 277 |             w = w + width(l.head); | 
| 278 |         return w; | 
| 279 |     } | 
| 280 |   | 
| 281 |     /** Given a type, return its code for allocating arrays of that type. | 
| 282 |      */ | 
| 283 |     public static int arraycode(Type type) { | 
| 284 |         switch (type.tag) { | 
| 285 |         case BYTE: return 8; | 
| 286 |         case BOOLEAN: return 4; | 
| 287 |         case SHORT: return 9; | 
| 288 |         case CHAR: return 5; | 
| 289 |         case INT: return 10; | 
| 290 |         case LONG: return 11; | 
| 291 |         case FLOAT: return 6; | 
| 292 |         case DOUBLE: return 7; | 
| 293 |         case CLASS: return 0; | 
| 294 |         case ARRAY: return 1; | 
| 295 |         default: throw new AssertionError("arraycode " + type); | 
| 296 |         } | 
| 297 |     } | 
| 298 |   | 
| 299 |   | 
| 300 | /* ************************************************************************** | 
| 301 |  * Emit code | 
| 302 |  ****************************************************************************/ | 
| 303 |   | 
| 304 |     /** The current output code pointer. | 
| 305 |      */ | 
| 306 |     public int curPc() { | 
| 307 |         if (pendingJumps != null) resolvePending(); | 
| 308 |         if (pendingStatPos != Position.NOPOS) markStatBegin(); | 
| 309 |         fixedPc = true; | 
| 310 |         return cp; | 
| 311 |     } | 
| 312 |   | 
| 313 |     /** Emit a byte of code. | 
| 314 |      */ | 
| 315 |     private  void emit1(int od) { | 
| 316 |         if (!alive) return; | 
| 317 |         if (cp == code.length) { | 
| 318 |             byte[] newcode = new byte[cp * 2]; | 
| 319 |             System.arraycopy(code, 0, newcode, 0, cp); | 
| 320 |             code = newcode; | 
| 321 |         } | 
| 322 |         code[cp++] = (byte)od; | 
| 323 |     } | 
| 324 |   | 
| 325 |     /** Emit two bytes of code. | 
| 326 |      */ | 
| 327 |     private void emit2(int od) { | 
| 328 |         if (!alive) return; | 
| 329 |         if (cp + 2 > code.length) { | 
| 330 |             emit1(od >> 8); | 
| 331 |             emit1(od); | 
| 332 |         } else { | 
| 333 |             code[cp++] = (byte)(od >> 8); | 
| 334 |             code[cp++] = (byte)od; | 
| 335 |         } | 
| 336 |     } | 
| 337 |   | 
| 338 |     /** Emit four bytes of code. | 
| 339 |      */ | 
| 340 |     public void emit4(int od) { | 
| 341 |         if (!alive) return; | 
| 342 |         if (cp + 4 > code.length) { | 
| 343 |             emit1(od >> 24); | 
| 344 |             emit1(od >> 16); | 
| 345 |             emit1(od >> 8); | 
| 346 |             emit1(od); | 
| 347 |         } else { | 
| 348 |             code[cp++] = (byte)(od >> 24); | 
| 349 |             code[cp++] = (byte)(od >> 16); | 
| 350 |             code[cp++] = (byte)(od >> 8); | 
| 351 |             code[cp++] = (byte)od; | 
| 352 |         } | 
| 353 |     } | 
| 354 |   | 
| 355 |     /** Emit an opcode. | 
| 356 |      */ | 
| 357 |     private void emitop(int op) { | 
| 358 |         if (pendingJumps != null) resolvePending(); | 
| 359 |         if (alive) { | 
| 360 |             if (pendingStatPos != Position.NOPOS) | 
| 361 |                 markStatBegin(); | 
| 362 |             if (pendingStackMap) { | 
| 363 |                 pendingStackMap = false; | 
| 364 |                 emitStackMap(); | 
| 365 |             } | 
| 366 |             if (debugCode) | 
| 367 |                 System.err.println("emit@" + cp + " stack=" + | 
| 368 |                                    state.stacksize + ": " + | 
| 369 |                                    mnem(op)); | 
| 370 |             emit1(op); | 
| 371 |         } | 
| 372 |     } | 
| 373 |   | 
| 374 |     void postop() { | 
| 375 |         assert alive || state.stacksize == 0; | 
| 376 |     } | 
| 377 |   | 
| 378 |     /** Emit a multinewarray instruction. | 
| 379 |      */ | 
| 380 |     public void emitMultianewarray(int ndims, int type, Type arrayType) { | 
| 381 |         emitop(multianewarray); | 
| 382 |         if (!alive) return; | 
| 383 |         emit2(type); | 
| 384 |         emit1(ndims); | 
| 385 |         state.pop(ndims); | 
| 386 |         state.push(arrayType); | 
| 387 |     } | 
| 388 |   | 
| 389 |     /** Emit newarray. | 
| 390 |      */ | 
| 391 |     public void emitNewarray(int elemcode, Type arrayType) { | 
| 392 |         emitop(newarray); | 
| 393 |         if (!alive) return; | 
| 394 |         emit1(elemcode); | 
| 395 |         state.pop(1); // count | 
| 396 |         state.push(arrayType); | 
| 397 |     } | 
| 398 |   | 
| 399 |     /** Emit anewarray. | 
| 400 |      */ | 
| 401 |     public void emitAnewarray(int od, Type arrayType) { | 
| 402 |         emitop(anewarray); | 
| 403 |         if (!alive) return; | 
| 404 |         emit2(od); | 
| 405 |         state.pop(1); | 
| 406 |         state.push(arrayType); | 
| 407 |     } | 
| 408 |   | 
| 409 |     /** Emit an invokeinterface instruction. | 
| 410 |      */ | 
| 411 |     public void emitInvokeinterface(int meth, Type mtype) { | 
| 412 |         int argsize = width(mtype.getParameterTypes()); | 
| 413 |         emitop(invokeinterface); | 
| 414 |         if (!alive) return; | 
| 415 |         emit2(meth); | 
| 416 |         emit1(argsize + 1); | 
| 417 |         emit1(0); | 
| 418 |         state.pop(argsize + 1); | 
| 419 |         state.push(mtype.getReturnType()); | 
| 420 |     } | 
| 421 |   | 
| 422 |     /** Emit an invokespecial instruction. | 
| 423 |      */ | 
| 424 |     public void emitInvokespecial(int meth, Type mtype) { | 
| 425 |         int argsize = width(mtype.getParameterTypes()); | 
| 426 |         emitop(invokespecial); | 
| 427 |         if (!alive) return; | 
| 428 |         emit2(meth); | 
| 429 |         Symbol sym = (Symbol)pool.pool[meth]; | 
| 430 |         state.pop(argsize); | 
| 431 |         if (sym.isConstructor()) | 
| 432 |             state.markInitialized((UninitializedType)state.peek()); | 
| 433 |         state.pop(1); | 
| 434 |         state.push(mtype.getReturnType()); | 
| 435 |     } | 
| 436 |   | 
| 437 |     /** Emit an invokestatic instruction. | 
| 438 |      */ | 
| 439 |     public void emitInvokestatic(int meth, Type mtype) { | 
| 440 |         int argsize = width(mtype.getParameterTypes()); | 
| 441 |         emitop(invokestatic); | 
| 442 |         if (!alive) return; | 
| 443 |         emit2(meth); | 
| 444 |         state.pop(argsize); | 
| 445 |         state.push(mtype.getReturnType()); | 
| 446 |     } | 
| 447 |   | 
| 448 |     /** Emit an invokevirtual instruction. | 
| 449 |      */ | 
| 450 |     public void emitInvokevirtual(int meth, Type mtype) { | 
| 451 |         int argsize = width(mtype.getParameterTypes()); | 
| 452 |         emitop(invokevirtual); | 
| 453 |         if (!alive) return; | 
| 454 |         emit2(meth); | 
| 455 |         state.pop(argsize + 1); | 
| 456 |         state.push(mtype.getReturnType()); | 
| 457 |     } | 
| 458 |   | 
| 459 |     /** Emit an opcode with no operand field. | 
| 460 |      */ | 
| 461 |     public void emitop0(int op) { | 
| 462 |         emitop(op); | 
| 463 |         if (!alive) return; | 
| 464 |         switch (op) { | 
| 465 |         case aaload: { | 
| 466 |             state.pop(1);// index | 
| 467 |             Type a = state.stack[state.stacksize-1]; | 
| 468 |             state.pop(1); | 
| 469 |             state.push(types.erasure(types.elemtype(a))); } | 
| 470 |             break; | 
| 471 |         case goto_: | 
| 472 |             markDead(); | 
| 473 |             break; | 
| 474 |         case nop: | 
| 475 |         case ineg: | 
| 476 |         case lneg: | 
| 477 |         case fneg: | 
| 478 |         case dneg: | 
| 479 |             break; | 
| 480 |         case aconst_null: | 
| 481 |             state.push(syms.botType); | 
| 482 |             break; | 
| 483 |         case iconst_m1: | 
| 484 |         case iconst_0: | 
| 485 |         case iconst_1: | 
| 486 |         case iconst_2: | 
| 487 |         case iconst_3: | 
| 488 |         case iconst_4: | 
| 489 |         case iconst_5: | 
| 490 |         case iload_0: | 
| 491 |         case iload_1: | 
| 492 |         case iload_2: | 
| 493 |         case iload_3: | 
| 494 |             state.push(syms.intType); | 
| 495 |             break; | 
| 496 |         case lconst_0: | 
| 497 |         case lconst_1: | 
| 498 |         case lload_0: | 
| 499 |         case lload_1: | 
| 500 |         case lload_2: | 
| 501 |         case lload_3: | 
| 502 |             state.push(syms.longType); | 
| 503 |             break; | 
| 504 |         case fconst_0: | 
| 505 |         case fconst_1: | 
| 506 |         case fconst_2: | 
| 507 |         case fload_0: | 
| 508 |         case fload_1: | 
| 509 |         case fload_2: | 
| 510 |         case fload_3: | 
| 511 |             state.push(syms.floatType); | 
| 512 |             break; | 
| 513 |         case dconst_0: | 
| 514 |         case dconst_1: | 
| 515 |         case dload_0: | 
| 516 |         case dload_1: | 
| 517 |         case dload_2: | 
| 518 |         case dload_3: | 
| 519 |             state.push(syms.doubleType); | 
| 520 |             break; | 
| 521 |         case aload_0: | 
| 522 |             state.push(lvar[0].sym.type); | 
| 523 |             break; | 
| 524 |         case aload_1: | 
| 525 |             state.push(lvar[1].sym.type); | 
| 526 |             break; | 
| 527 |         case aload_2: | 
| 528 |             state.push(lvar[2].sym.type); | 
| 529 |             break; | 
| 530 |         case aload_3: | 
| 531 |             state.push(lvar[3].sym.type); | 
| 532 |             break; | 
| 533 |         case iaload: | 
| 534 |         case baload: | 
| 535 |         case caload: | 
| 536 |         case saload: | 
| 537 |             state.pop(2); | 
| 538 |             state.push(syms.intType); | 
| 539 |             break; | 
| 540 |         case laload: | 
| 541 |             state.pop(2); | 
| 542 |             state.push(syms.longType); | 
| 543 |             break; | 
| 544 |         case faload: | 
| 545 |             state.pop(2); | 
| 546 |             state.push(syms.floatType); | 
| 547 |             break; | 
| 548 |         case daload: | 
| 549 |             state.pop(2); | 
| 550 |             state.push(syms.doubleType); | 
| 551 |             break; | 
| 552 |         case istore_0: | 
| 553 |         case istore_1: | 
| 554 |         case istore_2: | 
| 555 |         case istore_3: | 
| 556 |         case fstore_0: | 
| 557 |         case fstore_1: | 
| 558 |         case fstore_2: | 
| 559 |         case fstore_3: | 
| 560 |         case astore_0: | 
| 561 |         case astore_1: | 
| 562 |         case astore_2: | 
| 563 |         case astore_3: | 
| 564 |         case pop: | 
| 565 |         case lshr: | 
| 566 |         case lshl: | 
| 567 |         case lushr: | 
| 568 |             state.pop(1); | 
| 569 |             break; | 
| 570 |         case areturn: | 
| 571 |         case ireturn: | 
| 572 |         case freturn: | 
| 573 |             assert state.nlocks == 0; | 
| 574 |             state.pop(1); | 
| 575 |             markDead(); | 
| 576 |             break; | 
| 577 |         case athrow: | 
| 578 |             state.pop(1); | 
| 579 |             markDead(); | 
| 580 |             break; | 
| 581 |         case lstore_0: | 
| 582 |         case lstore_1: | 
| 583 |         case lstore_2: | 
| 584 |         case lstore_3: | 
| 585 |         case dstore_0: | 
| 586 |         case dstore_1: | 
| 587 |         case dstore_2: | 
| 588 |         case dstore_3: | 
| 589 |         case pop2: | 
| 590 |             state.pop(2); | 
| 591 |             break; | 
| 592 |         case lreturn: | 
| 593 |         case dreturn: | 
| 594 |             assert state.nlocks == 0; | 
| 595 |             state.pop(2); | 
| 596 |             markDead(); | 
| 597 |             break; | 
| 598 |         case dup: | 
| 599 |             state.push(state.stack[state.stacksize-1]); | 
| 600 |             break; | 
| 601 |         case return_: | 
| 602 |             assert state.nlocks == 0; | 
| 603 |             markDead(); | 
| 604 |             break; | 
| 605 |         case arraylength: | 
| 606 |             state.pop(1); | 
| 607 |             state.push(syms.intType); | 
| 608 |             break; | 
| 609 |         case isub: | 
| 610 |         case iadd: | 
| 611 |         case imul: | 
| 612 |         case idiv: | 
| 613 |         case imod: | 
| 614 |         case ishl: | 
| 615 |         case ishr: | 
| 616 |         case iushr: | 
| 617 |         case iand: | 
| 618 |         case ior: | 
| 619 |         case ixor: | 
| 620 |             state.pop(1); | 
| 621 |             // state.pop(1); | 
| 622 |             // state.push(syms.intType); | 
| 623 |             break; | 
| 624 |         case aastore: | 
| 625 |             state.pop(3); | 
| 626 |             break; | 
| 627 |         case land: | 
| 628 |         case lor: | 
| 629 |         case lxor: | 
| 630 |         case lmod: | 
| 631 |         case ldiv: | 
| 632 |         case lmul: | 
| 633 |         case lsub: | 
| 634 |         case ladd: | 
| 635 |             state.pop(2); | 
| 636 |             break; | 
| 637 |         case lcmp: | 
| 638 |             state.pop(4); | 
| 639 |             state.push(syms.intType); | 
| 640 |             break; | 
| 641 |         case l2i: | 
| 642 |             state.pop(2); | 
| 643 |             state.push(syms.intType); | 
| 644 |             break; | 
| 645 |         case i2l: | 
| 646 |             state.pop(1); | 
| 647 |             state.push(syms.longType); | 
| 648 |             break; | 
| 649 |         case i2f: | 
| 650 |             state.pop(1); | 
| 651 |             state.push(syms.floatType); | 
| 652 |             break; | 
| 653 |         case i2d: | 
| 654 |             state.pop(1); | 
| 655 |             state.push(syms.doubleType); | 
| 656 |             break; | 
| 657 |         case l2f: | 
| 658 |             state.pop(2); | 
| 659 |             state.push(syms.floatType); | 
| 660 |             break; | 
| 661 |         case l2d: | 
| 662 |             state.pop(2); | 
| 663 |             state.push(syms.doubleType); | 
| 664 |             break; | 
| 665 |         case f2i: | 
| 666 |             state.pop(1); | 
| 667 |             state.push(syms.intType); | 
| 668 |             break; | 
| 669 |         case f2l: | 
| 670 |             state.pop(1); | 
| 671 |             state.push(syms.longType); | 
| 672 |             break; | 
| 673 |         case f2d: | 
| 674 |             state.pop(1); | 
| 675 |             state.push(syms.doubleType); | 
| 676 |             break; | 
| 677 |         case d2i: | 
| 678 |             state.pop(2); | 
| 679 |             state.push(syms.intType); | 
| 680 |             break; | 
| 681 |         case d2l: | 
| 682 |             state.pop(2); | 
| 683 |             state.push(syms.longType); | 
| 684 |             break; | 
| 685 |         case d2f: | 
| 686 |             state.pop(2); | 
| 687 |             state.push(syms.floatType); | 
| 688 |             break; | 
| 689 |         case tableswitch: | 
| 690 |         case lookupswitch: | 
| 691 |             state.pop(1); | 
| 692 |             // the caller is responsible for patching up the state | 
| 693 |             break; | 
| 694 |         case dup_x1: { | 
| 695 |             Type val1 = state.pop1(); | 
| 696 |             Type val2 = state.pop1(); | 
| 697 |             state.push(val1); | 
| 698 |             state.push(val2); | 
| 699 |             state.push(val1); | 
| 700 |             break; | 
| 701 |         } | 
| 702 |         case bastore: | 
| 703 |             state.pop(3); | 
| 704 |             break; | 
| 705 |         case int2byte: | 
| 706 |         case int2char: | 
| 707 |         case int2short: | 
| 708 |             break; | 
| 709 |         case fmul: | 
| 710 |         case fadd: | 
| 711 |         case fsub: | 
| 712 |         case fdiv: | 
| 713 |         case fmod: | 
| 714 |             state.pop(1); | 
| 715 |             break; | 
| 716 |         case castore: | 
| 717 |         case iastore: | 
| 718 |         case fastore: | 
| 719 |         case sastore: | 
| 720 |             state.pop(3); | 
| 721 |             break; | 
| 722 |         case lastore: | 
| 723 |         case dastore: | 
| 724 |             state.pop(4); | 
| 725 |             break; | 
| 726 |         case dup2: | 
| 727 |             if (state.stack[state.stacksize-1] != null) { | 
| 728 |                 Type value1 = state.pop1(); | 
| 729 |                 Type value2 = state.pop1(); | 
| 730 |                 state.push(value2); | 
| 731 |                 state.push(value1); | 
| 732 |                 state.push(value2); | 
| 733 |                 state.push(value1); | 
| 734 |             } else { | 
| 735 |                 Type value = state.pop2(); | 
| 736 |                 state.push(value); | 
| 737 |                 state.push(value); | 
| 738 |             } | 
| 739 |             break; | 
| 740 |         case dup2_x1: | 
| 741 |             if (state.stack[state.stacksize-1] != null) { | 
| 742 |                 Type value1 = state.pop1(); | 
| 743 |                 Type value2 = state.pop1(); | 
| 744 |                 Type value3 = state.pop1(); | 
| 745 |                 state.push(value2); | 
| 746 |                 state.push(value1); | 
| 747 |                 state.push(value3); | 
| 748 |                 state.push(value2); | 
| 749 |                 state.push(value1); | 
| 750 |             } else { | 
| 751 |                 Type value1 = state.pop2(); | 
| 752 |                 Type value2 = state.pop1(); | 
| 753 |                 state.push(value1); | 
| 754 |                 state.push(value2); | 
| 755 |                 state.push(value1); | 
| 756 |             } | 
| 757 |             break; | 
| 758 |         case dup2_x2: | 
| 759 |             if (state.stack[state.stacksize-1] != null) { | 
| 760 |                 Type value1 = state.pop1(); | 
| 761 |                 Type value2 = state.pop1(); | 
| 762 |                 if (state.stack[state.stacksize-1] != null) { | 
| 763 |                     // form 1 | 
| 764 |                     Type value3 = state.pop1(); | 
| 765 |                     Type value4 = state.pop1(); | 
| 766 |                     state.push(value2); | 
| 767 |                     state.push(value1); | 
| 768 |                     state.push(value4); | 
| 769 |                     state.push(value3); | 
| 770 |                     state.push(value2); | 
| 771 |                     state.push(value1); | 
| 772 |                 } else { | 
| 773 |                     // form 3 | 
| 774 |                     Type value3 = state.pop2(); | 
| 775 |                     state.push(value2); | 
| 776 |                     state.push(value1); | 
| 777 |                     state.push(value3); | 
| 778 |                     state.push(value2); | 
| 779 |                     state.push(value1); | 
| 780 |                 } | 
| 781 |             } else { | 
| 782 |                 Type value1 = state.pop2(); | 
| 783 |                 if (state.stack[state.stacksize-1] != null) { | 
| 784 |                     // form 2 | 
| 785 |                     Type value2 = state.pop1(); | 
| 786 |                     Type value3 = state.pop1(); | 
| 787 |                     state.push(value1); | 
| 788 |                     state.push(value3); | 
| 789 |                     state.push(value2); | 
| 790 |                     state.push(value1); | 
| 791 |                 } else { | 
| 792 |                     // form 4 | 
| 793 |                     Type value2 = state.pop2(); | 
| 794 |                     state.push(value1); | 
| 795 |                     state.push(value2); | 
| 796 |                     state.push(value1); | 
| 797 |                 } | 
| 798 |             } | 
| 799 |             break; | 
| 800 |         case dup_x2: { | 
| 801 |             Type value1 = state.pop1(); | 
| 802 |             if (state.stack[state.stacksize-1] != null) { | 
| 803 |                 // form 1 | 
| 804 |                 Type value2 = state.pop1(); | 
| 805 |                 Type value3 = state.pop1(); | 
| 806 |                 state.push(value1); | 
| 807 |                 state.push(value3); | 
| 808 |                 state.push(value2); | 
| 809 |                 state.push(value1); | 
| 810 |             } else { | 
| 811 |                 // form 2 | 
| 812 |                 Type value2 = state.pop2(); | 
| 813 |                 state.push(value1); | 
| 814 |                 state.push(value2); | 
| 815 |                 state.push(value1); | 
| 816 |             } | 
| 817 |         } | 
| 818 |             break; | 
| 819 |         case fcmpl: | 
| 820 |         case fcmpg: | 
| 821 |             state.pop(2); | 
| 822 |             state.push(syms.intType); | 
| 823 |             break; | 
| 824 |         case dcmpl: | 
| 825 |         case dcmpg: | 
| 826 |             state.pop(4); | 
| 827 |             state.push(syms.intType); | 
| 828 |             break; | 
| 829 |         case swap: { | 
| 830 |             Type value1 = state.pop1(); | 
| 831 |             Type value2 = state.pop1(); | 
| 832 |             state.push(value1); | 
| 833 |             state.push(value2); | 
| 834 |             break; | 
| 835 |         } | 
| 836 |         case dadd: | 
| 837 |         case dsub: | 
| 838 |         case dmul: | 
| 839 |         case ddiv: | 
| 840 |         case dmod: | 
| 841 |             state.pop(2); | 
| 842 |             break; | 
| 843 |         case ret: | 
| 844 |             markDead(); | 
| 845 |             break; | 
| 846 |         case wide: | 
| 847 |             // must be handled by the caller. | 
| 848 |             return; | 
| 849 |         case monitorenter: | 
| 850 |         case monitorexit: | 
| 851 |             state.pop(1); | 
| 852 |             break; | 
| 853 |   | 
| 854 |         default: | 
| 855 |             throw new AssertionError(mnem(op)); | 
| 856 |         } | 
| 857 |         postop(); | 
| 858 |     } | 
| 859 |   | 
| 860 |     /** Emit an opcode with a one-byte operand field. | 
| 861 |      */ | 
| 862 |     public void emitop1(int op, int od) { | 
| 863 |         emitop(op); | 
| 864 |         if (!alive) return; | 
| 865 |         emit1(od); | 
| 866 |         switch (op) { | 
| 867 |         case bipush: | 
| 868 |             state.push(syms.intType); | 
| 869 |             break; | 
| 870 |         case ldc1: | 
| 871 |             state.push(typeForPool(pool.pool[od])); | 
| 872 |             break; | 
| 873 |         default: | 
| 874 |             throw new AssertionError(mnem(op)); | 
| 875 |         } | 
| 876 |         postop(); | 
| 877 |     } | 
| 878 |   | 
| 879 |     /** The type of a constant pool entry. */ | 
| 880 |     private Type typeForPool(Object o) { | 
| 881 |         if (o instanceof Integer) return syms.intType; | 
| 882 |         if (o instanceof Float) return syms.floatType; | 
| 883 |         if (o instanceof String) return syms.stringType; | 
| 884 |         if (o instanceof Long) return syms.longType; | 
| 885 |         if (o instanceof Double) return syms.doubleType; | 
| 886 |         if (o instanceof ClassSymbol) return syms.classType; | 
| 887 |         if (o instanceof Type.ArrayType) return syms.classType; | 
| 888 |         throw new AssertionError(o); | 
| 889 |     } | 
| 890 |   | 
| 891 |     /** Emit an opcode with a one-byte operand field; | 
| 892 |      *  widen if field does not fit in a byte. | 
| 893 |      */ | 
| 894 |     public void emitop1w(int op, int od) { | 
| 895 |         if (od > 0xFF) { | 
| 896 |             emitop(wide); | 
| 897 |             emitop(op); | 
| 898 |             emit2(od); | 
| 899 |         } else { | 
| 900 |             emitop(op); | 
| 901 |             emit1(od); | 
| 902 |         } | 
| 903 |         if (!alive) return; | 
| 904 |         switch (op) { | 
| 905 |         case iload: | 
| 906 |             state.push(syms.intType); | 
| 907 |             break; | 
| 908 |         case lload: | 
| 909 |             state.push(syms.longType); | 
| 910 |             break; | 
| 911 |         case fload: | 
| 912 |             state.push(syms.floatType); | 
| 913 |             break; | 
| 914 |         case dload: | 
| 915 |             state.push(syms.doubleType); | 
| 916 |             break; | 
| 917 |         case aload: | 
| 918 |             state.push(lvar[od].sym.type); | 
| 919 |             break; | 
| 920 |         case lstore: | 
| 921 |         case dstore: | 
| 922 |             state.pop(2); | 
| 923 |             break; | 
| 924 |         case istore: | 
| 925 |         case fstore: | 
| 926 |         case astore: | 
| 927 |             state.pop(1); | 
| 928 |             break; | 
| 929 |         case ret: | 
| 930 |             markDead(); | 
| 931 |             break; | 
| 932 |         default: | 
| 933 |             throw new AssertionError(mnem(op)); | 
| 934 |         } | 
| 935 |         postop(); | 
| 936 |     } | 
| 937 |   | 
| 938 |     /** Emit an opcode with two one-byte operand fields; | 
| 939 |      *  widen if either field does not fit in a byte. | 
| 940 |      */ | 
| 941 |     public void emitop1w(int op, int od1, int od2) { | 
| 942 |         if (od1 > 0xFF || od2 < -128 || od2 > 127) { | 
| 943 |             emitop(wide); | 
| 944 |             emitop(op); | 
| 945 |             emit2(od1); | 
| 946 |             emit2(od2); | 
| 947 |         } else { | 
| 948 |             emitop(op); | 
| 949 |             emit1(od1); | 
| 950 |             emit1(od2); | 
| 951 |         } | 
| 952 |         if (!alive) return; | 
| 953 |         switch (op) { | 
| 954 |         case iinc: | 
| 955 |             break; | 
| 956 |         default: | 
| 957 |             throw new AssertionError(mnem(op)); | 
| 958 |         } | 
| 959 |     } | 
| 960 |   | 
| 961 |     /** Emit an opcode with a two-byte operand field. | 
| 962 |      */ | 
| 963 |     public void emitop2(int op, int od) { | 
| 964 |         emitop(op); | 
| 965 |         if (!alive) return; | 
| 966 |         emit2(od); | 
| 967 |         switch (op) { | 
| 968 |         case getstatic: | 
| 969 |             state.push(((Symbol)(pool.pool[od])).erasure(types)); | 
| 970 |             break; | 
| 971 |         case putstatic: | 
| 972 |             state.pop(((Symbol)(pool.pool[od])).erasure(types)); | 
| 973 |             break; | 
| 974 |         case new_: | 
| 975 |             state.push(uninitializedObject(((Symbol)(pool.pool[od])).erasure(types), cp-3)); | 
| 976 |             break; | 
| 977 |         case sipush: | 
| 978 |             state.push(syms.intType); | 
| 979 |             break; | 
| 980 |         case if_acmp_null: | 
| 981 |         case if_acmp_nonnull: | 
| 982 |         case ifeq: | 
| 983 |         case ifne: | 
| 984 |         case iflt: | 
| 985 |         case ifge: | 
| 986 |         case ifgt: | 
| 987 |         case ifle: | 
| 988 |             state.pop(1); | 
| 989 |             break; | 
| 990 |         case if_icmpeq: | 
| 991 |         case if_icmpne: | 
| 992 |         case if_icmplt: | 
| 993 |         case if_icmpge: | 
| 994 |         case if_icmpgt: | 
| 995 |         case if_icmple: | 
| 996 |         case if_acmpeq: | 
| 997 |         case if_acmpne: | 
| 998 |             state.pop(2); | 
| 999 |             break; | 
| 1000 |         case goto_: | 
| 1001 |             markDead(); | 
| 1002 |             break; | 
| 1003 |         case putfield: | 
| 1004 |             state.pop(((Symbol)(pool.pool[od])).erasure(types)); | 
| 1005 |             state.pop(1); // object ref | 
| 1006 |             break; | 
| 1007 |         case getfield: | 
| 1008 |             state.pop(1); // object ref | 
| 1009 |             state.push(((Symbol)(pool.pool[od])).erasure(types)); | 
| 1010 |             break; | 
| 1011 |         case checkcast: { | 
| 1012 |             state.pop(1); // object ref | 
| 1013 |             Object o = pool.pool[od]; | 
| 1014 |             Type t = (o instanceof Symbol) | 
| 1015 |                 ? ((Symbol)o).erasure(types) | 
| 1016 |                 : types.erasure(((Type)o)); | 
| 1017 |             state.push(t); | 
| 1018 |             break; } | 
| 1019 |         case ldc2w: | 
| 1020 |             state.push(typeForPool(pool.pool[od])); | 
| 1021 |             break; | 
| 1022 |         case instanceof_: | 
| 1023 |             state.pop(1); | 
| 1024 |             state.push(syms.intType); | 
| 1025 |             break; | 
| 1026 |         case ldc2: | 
| 1027 |             state.push(typeForPool(pool.pool[od])); | 
| 1028 |             break; | 
| 1029 |         case jsr: | 
| 1030 |             break; | 
| 1031 |         default: | 
| 1032 |             throw new AssertionError(mnem(op)); | 
| 1033 |         } | 
| 1034 |         // postop(); | 
| 1035 |     } | 
| 1036 |   | 
| 1037 |     /** Emit an opcode with a four-byte operand field. | 
| 1038 |      */ | 
| 1039 |     public void emitop4(int op, int od) { | 
| 1040 |         emitop(op); | 
| 1041 |         if (!alive) return; | 
| 1042 |         emit4(od); | 
| 1043 |         switch (op) { | 
| 1044 |         case goto_w: | 
| 1045 |             markDead(); | 
| 1046 |             break; | 
| 1047 |         case jsr_w: | 
| 1048 |             break; | 
| 1049 |         default: | 
| 1050 |             throw new AssertionError(mnem(op)); | 
| 1051 |         } | 
| 1052 |         // postop(); | 
| 1053 |     } | 
| 1054 |   | 
| 1055 |     /** Align code pointer to next `incr' boundary. | 
| 1056 |      */ | 
| 1057 |     public void align(int incr) { | 
| 1058 |         if (alive) | 
| 1059 |             while (cp % incr != 0) emitop0(nop); | 
| 1060 |     } | 
| 1061 |   | 
| 1062 |     /** Place a byte into code at address pc. Pre: pc + 1 <= cp. | 
| 1063 |      */ | 
| 1064 |     private void put1(int pc, int op) { | 
| 1065 |         code[pc] = (byte)op; | 
| 1066 |     } | 
| 1067 |   | 
| 1068 |     /** Place two bytes into code at address pc. Pre: pc + 2 <= cp. | 
| 1069 |      */ | 
| 1070 |     private void put2(int pc, int od) { | 
| 1071 |         // pre: pc + 2 <= cp | 
| 1072 |         put1(pc, od >> 8); | 
| 1073 |         put1(pc+1, od); | 
| 1074 |     } | 
| 1075 |   | 
| 1076 |     /** Place four  bytes into code at address pc. Pre: pc + 4 <= cp. | 
| 1077 |      */ | 
| 1078 |     public void put4(int pc, int od) { | 
| 1079 |         // pre: pc + 4 <= cp | 
| 1080 |         put1(pc  , od >> 24); | 
| 1081 |         put1(pc+1, od >> 16); | 
| 1082 |         put1(pc+2, od >> 8); | 
| 1083 |         put1(pc+3, od); | 
| 1084 |     } | 
| 1085 |   | 
| 1086 |     /** Return code byte at position pc as an unsigned int. | 
| 1087 |      */ | 
| 1088 |     private int get1(int pc) { | 
| 1089 |         return code[pc] & 0xFF; | 
| 1090 |     } | 
| 1091 |   | 
| 1092 |     /** Return two code bytes at position pc as an unsigned int. | 
| 1093 |      */ | 
| 1094 |     private int get2(int pc) { | 
| 1095 |         return (get1(pc) << 8) | get1(pc+1); | 
| 1096 |     } | 
| 1097 |   | 
| 1098 |     /** Return four code bytes at position pc as an int. | 
| 1099 |      */ | 
| 1100 |     public int get4(int pc) { | 
| 1101 |         // pre: pc + 4 <= cp | 
| 1102 |         return | 
| 1103 |             (get1(pc) << 24) | | 
| 1104 |             (get1(pc+1) << 16) | | 
| 1105 |             (get1(pc+2) << 8) | | 
| 1106 |             (get1(pc+3)); | 
| 1107 |     } | 
| 1108 |   | 
| 1109 |     /** Is code generation currently enabled? | 
| 1110 |      */ | 
| 1111 |     public boolean isAlive() { | 
| 1112 |         return alive || pendingJumps != null; | 
| 1113 |     } | 
| 1114 |   | 
| 1115 |     /** Switch code generation on/off. | 
| 1116 |      */ | 
| 1117 |     public void markDead() { | 
| 1118 |         alive = false; | 
| 1119 |     } | 
| 1120 |   | 
| 1121 |     /** Declare an entry point; return current code pointer | 
| 1122 |      */ | 
| 1123 |     public int entryPoint() { | 
| 1124 |         int pc = curPc(); | 
| 1125 |         alive = true; | 
| 1126 |         pendingStackMap = needStackMap; | 
| 1127 |         return pc; | 
| 1128 |     } | 
| 1129 |   | 
| 1130 |     /** Declare an entry point with initial state; | 
| 1131 |      *  return current code pointer | 
| 1132 |      */ | 
| 1133 |     public int entryPoint(State state) { | 
| 1134 |         int pc = curPc(); | 
| 1135 |         alive = true; | 
| 1136 |         this.state = state.dup(); | 
| 1137 |         assert state.stacksize <= max_stack; | 
| 1138 |         if (debugCode) System.err.println("entry point " + state); | 
| 1139 |         pendingStackMap = needStackMap; | 
| 1140 |         return pc; | 
| 1141 |     } | 
| 1142 |   | 
| 1143 |     /** Declare an entry point with initial state plus a pushed value; | 
| 1144 |      *  return current code pointer | 
| 1145 |      */ | 
| 1146 |     public int entryPoint(State state, Type pushed) { | 
| 1147 |         int pc = curPc(); | 
| 1148 |         alive = true; | 
| 1149 |         this.state = state.dup(); | 
| 1150 |         assert state.stacksize <= max_stack; | 
| 1151 |         this.state.push(pushed); | 
| 1152 |         if (debugCode) System.err.println("entry point " + state); | 
| 1153 |         pendingStackMap = needStackMap; | 
| 1154 |         return pc; | 
| 1155 |     } | 
| 1156 |   | 
| 1157 |   | 
| 1158 | /************************************************************************** | 
| 1159 |  * Stack map generation | 
| 1160 |  *************************************************************************/ | 
| 1161 |   | 
| 1162 |     /** An entry in the stack map. */ | 
| 1163 |     static class StackMapFrame { | 
| 1164 |         int pc; | 
| 1165 |         Type[] locals; | 
| 1166 |         Type[] stack; | 
| 1167 |     } | 
| 1168 |   | 
| 1169 |     /** A buffer of cldc stack map entries. */ | 
| 1170 |     StackMapFrame[] stackMapBuffer = null; | 
| 1171 |   | 
| 1172 |     /** A buffer of compressed StackMapTable entries. */ | 
| 1173 |     StackMapTableFrame[] stackMapTableBuffer = null; | 
| 1174 |     int stackMapBufferSize = 0; | 
| 1175 |   | 
| 1176 |     /** The last PC at which we generated a stack map. */ | 
| 1177 |     int lastStackMapPC = -1; | 
| 1178 |   | 
| 1179 |     /** The last stack map frame in StackMapTable. */ | 
| 1180 |     StackMapFrame lastFrame = null; | 
| 1181 |   | 
| 1182 |     /** The stack map frame before the last one. */ | 
| 1183 |     StackMapFrame frameBeforeLast = null; | 
| 1184 |   | 
| 1185 |     /** Emit a stack map entry.  */ | 
| 1186 |     public void emitStackMap() { | 
| 1187 |         int pc = curPc(); | 
| 1188 |         if (!needStackMap) return; | 
| 1189 |   | 
| 1190 |   | 
| 1191 |   | 
| 1192 |         switch (stackMap) { | 
| 1193 |             case CLDC: | 
| 1194 |                 emitCLDCStackMap(pc, getLocalsSize()); | 
| 1195 |                 break; | 
| 1196 |             case JSR202: | 
| 1197 |                 emitStackMapFrame(pc, getLocalsSize()); | 
| 1198 |                 break; | 
| 1199 |             default: | 
| 1200 |                 throw new AssertionError("Should have chosen a stackmap format"); | 
| 1201 |         } | 
| 1202 |         // DEBUG code follows | 
| 1203 |         if (debugCode) state.dump(pc); | 
| 1204 |     } | 
| 1205 |   | 
| 1206 |     private int getLocalsSize() { | 
| 1207 |         int nextLocal = 0; | 
| 1208 |         for (int i=max_locals-1; i>=0; i--) { | 
| 1209 |             if (state.defined.isMember(i) && lvar[i] != null) { | 
| 1210 |                 nextLocal = i + width(lvar[i].sym.erasure(types)); | 
| 1211 |                 break; | 
| 1212 |             } | 
| 1213 |         } | 
| 1214 |         return nextLocal; | 
| 1215 |     } | 
| 1216 |   | 
| 1217 |     /** Emit a CLDC stack map frame. */ | 
| 1218 |     void emitCLDCStackMap(int pc, int localsSize) { | 
| 1219 |         if (lastStackMapPC == pc) { | 
| 1220 |             // drop existing stackmap at this offset | 
| 1221 |             stackMapBuffer[--stackMapBufferSize] = null; | 
| 1222 |         } | 
| 1223 |         lastStackMapPC = pc; | 
| 1224 |   | 
| 1225 |         if (stackMapBuffer == null) { | 
| 1226 |             stackMapBuffer = new StackMapFrame[20]; | 
| 1227 |         } else if (stackMapBuffer.length == stackMapBufferSize) { | 
| 1228 |             StackMapFrame[] newStackMapBuffer = | 
| 1229 |                 new StackMapFrame[stackMapBufferSize << 1]; | 
| 1230 |             System.arraycopy(stackMapBuffer, 0, newStackMapBuffer, | 
| 1231 |                              0, stackMapBufferSize); | 
| 1232 |             stackMapBuffer = newStackMapBuffer; | 
| 1233 |         } | 
| 1234 |         StackMapFrame frame = | 
| 1235 |             stackMapBuffer[stackMapBufferSize++] = new StackMapFrame(); | 
| 1236 |         frame.pc = pc; | 
| 1237 |   | 
| 1238 |         frame.locals = new Type[localsSize]; | 
| 1239 |         for (int i=0; i<localsSize; i++) { | 
| 1240 |             if (state.defined.isMember(i) && lvar[i] != null) { | 
| 1241 |                 Type vtype = lvar[i].sym.type; | 
| 1242 |                 if (!(vtype instanceof UninitializedType)) | 
| 1243 |                     vtype = types.erasure(vtype); | 
| 1244 |                 frame.locals[i] = vtype; | 
| 1245 |             } | 
| 1246 |         } | 
| 1247 |         frame.stack = new Type[state.stacksize]; | 
| 1248 |         for (int i=0; i<state.stacksize; i++) | 
| 1249 |             frame.stack[i] = state.stack[i]; | 
| 1250 |     } | 
| 1251 |   | 
| 1252 |     void emitStackMapFrame(int pc, int localsSize) { | 
| 1253 |         if (lastFrame == null) { | 
| 1254 |             // first frame | 
| 1255 |             lastFrame = getInitialFrame(); | 
| 1256 |         } else if (lastFrame.pc == pc) { | 
| 1257 |             // drop existing stackmap at this offset | 
| 1258 |             stackMapTableBuffer[--stackMapBufferSize] = null; | 
| 1259 |             lastFrame = frameBeforeLast; | 
| 1260 |             frameBeforeLast = null; | 
| 1261 |         } | 
| 1262 |   | 
| 1263 |         StackMapFrame frame = new StackMapFrame(); | 
| 1264 |         frame.pc = pc; | 
| 1265 |   | 
| 1266 |         int localCount = 0; | 
| 1267 |         Type[] locals = new Type[localsSize]; | 
| 1268 |         for (int i=0; i<localsSize; i++, localCount++) { | 
| 1269 |             if (state.defined.isMember(i) && lvar[i] != null) { | 
| 1270 |                 Type vtype = lvar[i].sym.type; | 
| 1271 |                 if (!(vtype instanceof UninitializedType)) | 
| 1272 |                     vtype = types.erasure(vtype); | 
| 1273 |                 locals[i] = vtype; | 
| 1274 |                 if (width(vtype) > 1) i++; | 
| 1275 |             } | 
| 1276 |         } | 
| 1277 |         frame.locals = new Type[localCount]; | 
| 1278 |         for (int i=0, j=0; i<localsSize; i++, j++) { | 
| 1279 |             assert(j < localCount); | 
| 1280 |             frame.locals[j] = locals[i]; | 
| 1281 |             if (width(locals[i]) > 1) i++; | 
| 1282 |         } | 
| 1283 |   | 
| 1284 |         int stackCount = 0; | 
| 1285 |         for (int i=0; i<state.stacksize; i++) { | 
| 1286 |             if (state.stack[i] != null) { | 
| 1287 |                 stackCount++; | 
| 1288 |             } | 
| 1289 |         } | 
| 1290 |         frame.stack = new Type[stackCount]; | 
| 1291 |         stackCount = 0; | 
| 1292 |         for (int i=0; i<state.stacksize; i++) { | 
| 1293 |             if (state.stack[i] != null) { | 
| 1294 |                 frame.stack[stackCount++] = state.stack[i]; | 
| 1295 |             } | 
| 1296 |         } | 
| 1297 |   | 
| 1298 |         if (stackMapTableBuffer == null) { | 
| 1299 |             stackMapTableBuffer = new StackMapTableFrame[20]; | 
| 1300 |         } else if (stackMapTableBuffer.length == stackMapBufferSize) { | 
| 1301 |             StackMapTableFrame[] newStackMapTableBuffer = | 
| 1302 |                 new StackMapTableFrame[stackMapBufferSize << 1]; | 
| 1303 |             System.arraycopy(stackMapTableBuffer, 0, newStackMapTableBuffer, | 
| 1304 |                              0, stackMapBufferSize); | 
| 1305 |             stackMapTableBuffer = newStackMapTableBuffer; | 
| 1306 |         } | 
| 1307 |         stackMapTableBuffer[stackMapBufferSize++] = | 
| 1308 |                 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types); | 
| 1309 |   | 
| 1310 |         frameBeforeLast = lastFrame; | 
| 1311 |         lastFrame = frame; | 
| 1312 |     } | 
| 1313 |   | 
| 1314 |     StackMapFrame getInitialFrame() { | 
| 1315 |         StackMapFrame frame = new StackMapFrame(); | 
| 1316 |         List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes; | 
| 1317 |         int len = arg_types.length(); | 
| 1318 |         int count = 0; | 
| 1319 |         if (!meth.isStatic()) { | 
| 1320 |             Type thisType = meth.owner.type; | 
| 1321 |             frame.locals = new Type[len+1]; | 
| 1322 |             if (meth.isConstructor() && thisType != syms.objectType) { | 
| 1323 |                 frame.locals[count++] = UninitializedType.uninitializedThis(thisType); | 
| 1324 |             } else { | 
| 1325 |                 frame.locals[count++] = types.erasure(thisType); | 
| 1326 |             } | 
| 1327 |         } else { | 
| 1328 |             frame.locals = new Type[len]; | 
| 1329 |         } | 
| 1330 |         for (Type arg_type : arg_types) { | 
| 1331 |             frame.locals[count++] = types.erasure(arg_type); | 
| 1332 |         } | 
| 1333 |         frame.pc = -1; | 
| 1334 |         frame.stack = null; | 
| 1335 |         return frame; | 
| 1336 |     } | 
| 1337 |   | 
| 1338 |   | 
| 1339 | /************************************************************************** | 
| 1340 |  * Operations having to do with jumps | 
| 1341 |  *************************************************************************/ | 
| 1342 |   | 
| 1343 |     /** A chain represents a list of unresolved jumps. Jump locations | 
| 1344 |      *  are sorted in decreasing order. | 
| 1345 |      */ | 
| 1346 |     public static class Chain { | 
| 1347 |   | 
| 1348 |         /** The position of the jump instruction. | 
| 1349 |          */ | 
| 1350 |         public final int pc; | 
| 1351 |   | 
| 1352 |         /** The machine state after the jump instruction. | 
| 1353 |          *  Invariant: all elements of a chain list have the same stacksize | 
| 1354 |          *  and compatible stack and register contents. | 
| 1355 |          */ | 
| 1356 |         Code.State state; | 
| 1357 |   | 
| 1358 |         /** The next jump in the list. | 
| 1359 |          */ | 
| 1360 |         public final Chain next; | 
| 1361 |   | 
| 1362 |         /** Construct a chain from its jump position, stacksize, previous | 
| 1363 |          *  chain, and machine state. | 
| 1364 |          */ | 
| 1365 |         public Chain(int pc, Chain next, Code.State state) { | 
| 1366 |             this.pc = pc; | 
| 1367 |             this.next = next; | 
| 1368 |             this.state = state; | 
| 1369 |         } | 
| 1370 |     } | 
| 1371 |   | 
| 1372 |     /** Negate a branch opcode. | 
| 1373 |      */ | 
| 1374 |     public static int negate(int opcode) { | 
| 1375 |         if (opcode == if_acmp_null) return if_acmp_nonnull; | 
| 1376 |         else if (opcode == if_acmp_nonnull) return if_acmp_null; | 
| 1377 |         else return ((opcode + 1) ^ 1) - 1; | 
| 1378 |     } | 
| 1379 |   | 
| 1380 |     /** Emit a jump instruction. | 
| 1381 |      *  Return code pointer of instruction to be patched. | 
| 1382 |      */ | 
| 1383 |     public int emitJump(int opcode) { | 
| 1384 |         if (fatcode) { | 
| 1385 |             if (opcode == goto_ || opcode == jsr) { | 
| 1386 |                 emitop4(opcode + goto_w - goto_, 0); | 
| 1387 |             } else { | 
| 1388 |                 emitop2(negate(opcode), 8); | 
| 1389 |                 emitop4(goto_w, 0); | 
| 1390 |                 alive = true; | 
| 1391 |                 pendingStackMap = needStackMap; | 
| 1392 |             } | 
| 1393 |             return cp - 5; | 
| 1394 |         } else { | 
| 1395 |             emitop2(opcode, 0); | 
| 1396 |             return cp - 3; | 
| 1397 |         } | 
| 1398 |     } | 
| 1399 |   | 
| 1400 |     /** Emit a branch with given opcode; return its chain. | 
| 1401 |      *  branch differs from jump in that jsr is treated as no-op. | 
| 1402 |      */ | 
| 1403 |     public Chain branch(int opcode) { | 
| 1404 |         Chain result = null; | 
| 1405 |         if (opcode == goto_) { | 
| 1406 |             result = pendingJumps; | 
| 1407 |             pendingJumps = null; | 
| 1408 |         } | 
| 1409 |         if (opcode != dontgoto && isAlive()) { | 
| 1410 |             result = new Chain(emitJump(opcode), | 
| 1411 |                                result, | 
| 1412 |                                state.dup()); | 
| 1413 |             fixedPc = fatcode; | 
| 1414 |             if (opcode == goto_) alive = false; | 
| 1415 |         } | 
| 1416 |         return result; | 
| 1417 |     } | 
| 1418 |   | 
| 1419 |     /** Resolve chain to point to given target. | 
| 1420 |      */ | 
| 1421 |     public void resolve(Chain chain, int target) { | 
| 1422 |         boolean changed = false; | 
| 1423 |         State newState = state; | 
| 1424 |         for (; chain != null; chain = chain.next) { | 
| 1425 |             assert state != chain.state; | 
| 1426 |             assert target > chain.pc || state.stacksize == 0; | 
| 1427 |             if (target >= cp) { | 
| 1428 |                 target = cp; | 
| 1429 |             } else if (get1(target) == goto_) { | 
| 1430 |                 if (fatcode) target = target + get4(target + 1); | 
| 1431 |                 else target = target + get2(target + 1); | 
| 1432 |             } | 
| 1433 |             if (get1(chain.pc) == goto_ && | 
| 1434 |                 chain.pc + 3 == target && target == cp && !fixedPc) { | 
| 1435 |                 // If goto the next instruction, the jump is not needed: | 
| 1436 |                 // compact the code. | 
| 1437 |                 cp = cp - 3; | 
| 1438 |                 target = target - 3; | 
| 1439 |                 if (chain.next == null) { | 
| 1440 |                     // This is the only jump to the target. Exit the loop | 
| 1441 |                     // without setting new state. The code is reachable | 
| 1442 |                     // from the instruction before goto_. | 
| 1443 |                     alive = true; | 
| 1444 |                     break; | 
| 1445 |                 } | 
| 1446 |             } else { | 
| 1447 |                 if (fatcode) | 
| 1448 |                     put4(chain.pc + 1, target - chain.pc); | 
| 1449 |                 else if (target - chain.pc < Short.MIN_VALUE || | 
| 1450 |                          target - chain.pc > Short.MAX_VALUE) | 
| 1451 |                     fatcode = true; | 
| 1452 |                 else | 
| 1453 |                     put2(chain.pc + 1, target - chain.pc); | 
| 1454 |                 assert !alive || | 
| 1455 |                     chain.state.stacksize == newState.stacksize && | 
| 1456 |                     chain.state.nlocks == newState.nlocks; | 
| 1457 |             } | 
| 1458 |             fixedPc = true; | 
| 1459 |             if (cp == target) { | 
| 1460 |                 changed = true; | 
| 1461 |                 if (debugCode) | 
| 1462 |                     System.err.println("resolving chain state=" + chain.state); | 
| 1463 |                 if (alive) { | 
| 1464 |                     newState = chain.state.join(newState); | 
| 1465 |                 } else { | 
| 1466 |                     newState = chain.state; | 
| 1467 |                     alive = true; | 
| 1468 |                 } | 
| 1469 |             } | 
| 1470 |         } | 
| 1471 |         assert !changed || state != newState; | 
| 1472 |         if (state != newState) { | 
| 1473 |             setDefined(newState.defined); | 
| 1474 |             state = newState; | 
| 1475 |             pendingStackMap = needStackMap; | 
| 1476 |         } | 
| 1477 |     } | 
| 1478 |   | 
| 1479 |     /** Resolve chain to point to current code pointer. | 
| 1480 |      */ | 
| 1481 |     public void resolve(Chain chain) { | 
| 1482 |         assert | 
| 1483 |             !alive || | 
| 1484 |             chain==null || | 
| 1485 |             state.stacksize == chain.state.stacksize && | 
| 1486 |             state.nlocks == chain.state.nlocks; | 
| 1487 |         pendingJumps = mergeChains(chain, pendingJumps); | 
| 1488 |     } | 
| 1489 |   | 
| 1490 |     /** Resolve any pending jumps. | 
| 1491 |      */ | 
| 1492 |     public void resolvePending() { | 
| 1493 |         Chain x = pendingJumps; | 
| 1494 |         pendingJumps = null; | 
| 1495 |         resolve(x, cp); | 
| 1496 |     } | 
| 1497 |   | 
| 1498 |     /** Merge the jumps in of two chains into one. | 
| 1499 |      */ | 
| 1500 |     public static Chain mergeChains(Chain chain1, Chain chain2) { | 
| 1501 |         // recursive merge sort | 
| 1502 |         if (chain2 == null) return chain1; | 
| 1503 |         if (chain1 == null) return chain2; | 
| 1504 |         assert | 
| 1505 |             chain1.state.stacksize == chain2.state.stacksize && | 
| 1506 |             chain1.state.nlocks == chain2.state.nlocks; | 
| 1507 |         if (chain1.pc < chain2.pc) | 
| 1508 |             return new Chain( | 
| 1509 |                 chain2.pc, | 
| 1510 |                 mergeChains(chain1, chain2.next), | 
| 1511 |                 chain2.state); | 
| 1512 |         return new Chain( | 
| 1513 |                 chain1.pc, | 
| 1514 |                 mergeChains(chain1.next, chain2), | 
| 1515 |                 chain1.state); | 
| 1516 |     } | 
| 1517 |   | 
| 1518 |   | 
| 1519 | /* ************************************************************************** | 
| 1520 |  * Catch clauses | 
| 1521 |  ****************************************************************************/ | 
| 1522 |   | 
| 1523 |     /** Add a catch clause to code. | 
| 1524 |      */ | 
| 1525 |     public void addCatch( | 
| 1526 |         char startPc, char endPc, char handlerPc, char catchType) { | 
| 1527 |         catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType}); | 
| 1528 |     } | 
| 1529 |   | 
| 1530 |   | 
| 1531 | /* ************************************************************************** | 
| 1532 |  * Line numbers | 
| 1533 |  ****************************************************************************/ | 
| 1534 |   | 
| 1535 |     /** Add a line number entry. | 
| 1536 |      */ | 
| 1537 |     public void addLineNumber(char startPc, char lineNumber) { | 
| 1538 |         if (lineDebugInfo) { | 
| 1539 |             if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc) | 
| 1540 |                 lineInfo = lineInfo.tail; | 
| 1541 |             if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber) | 
| 1542 |                 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber}); | 
| 1543 |         } | 
| 1544 |     } | 
| 1545 |   | 
| 1546 |     /** Mark beginning of statement. | 
| 1547 |      */ | 
| 1548 |     public void statBegin(int pos) { | 
| 1549 |         if (pos != Position.NOPOS) { | 
| 1550 |             pendingStatPos = pos; | 
| 1551 |         } | 
| 1552 |     } | 
| 1553 |   | 
| 1554 |     /** Force stat begin eagerly | 
| 1555 |      */ | 
| 1556 |     public void markStatBegin() { | 
| 1557 |         if (alive && lineDebugInfo) { | 
| 1558 |             int line = lineMap.getLineNumber(pendingStatPos); | 
| 1559 |             char cp1 = (char)cp; | 
| 1560 |             char line1 = (char)line; | 
| 1561 |             if (cp1 == cp && line1 == line) | 
| 1562 |                 addLineNumber(cp1, line1); | 
| 1563 |         } | 
| 1564 |         pendingStatPos = Position.NOPOS; | 
| 1565 |     } | 
| 1566 |   | 
| 1567 |   | 
| 1568 | /* ************************************************************************** | 
| 1569 |  * Simulated VM machine state | 
| 1570 |  ****************************************************************************/ | 
| 1571 |   | 
| 1572 |     class State implements Cloneable { | 
| 1573 |         /** The set of registers containing values. */ | 
| 1574 |         Bits defined; | 
| 1575 |   | 
| 1576 |         /** The (types of the) contents of the machine stack. */ | 
| 1577 |         Type[] stack; | 
| 1578 |   | 
| 1579 |         /** The first stack position currently unused. */ | 
| 1580 |         int stacksize; | 
| 1581 |   | 
| 1582 |         /** The numbers of registers containing locked monitors. */ | 
| 1583 |         int[] locks; | 
| 1584 |         int nlocks; | 
| 1585 |   | 
| 1586 |         State() { | 
| 1587 |             defined = new Bits(); | 
| 1588 |             stack = new Type[16]; | 
| 1589 |         } | 
| 1590 |   | 
| 1591 |         State dup() { | 
| 1592 |             try { | 
| 1593 |                 State state = (State)super.clone(); | 
| 1594 |                 state.defined = defined.dup(); | 
| 1595 |                 state.stack = stack.clone(); | 
| 1596 |                 if (locks != null) state.locks = locks.clone(); | 
| 1597 |                 if (debugCode) { | 
| 1598 |                     System.err.println("duping state " + this); | 
| 1599 |                     dump(); | 
| 1600 |                 } | 
| 1601 |                 return state; | 
| 1602 |             } catch (CloneNotSupportedException ex) { | 
| 1603 |                 throw new AssertionError(ex); | 
| 1604 |             } | 
| 1605 |         } | 
| 1606 |   | 
| 1607 |         void lock(int register) { | 
| 1608 |             if (locks == null) { | 
| 1609 |                 locks = new int[20]; | 
| 1610 |             } else if (locks.length == nlocks) { | 
| 1611 |                 int[] newLocks = new int[locks.length << 1]; | 
| 1612 |                 System.arraycopy(locks, 0, newLocks, 0, locks.length); | 
| 1613 |                 locks = newLocks; | 
| 1614 |             } | 
| 1615 |             locks[nlocks] = register; | 
| 1616 |             nlocks++; | 
| 1617 |         } | 
| 1618 |   | 
| 1619 |         void unlock(int register) { | 
| 1620 |             nlocks--; | 
| 1621 |             assert locks[nlocks] == register; | 
| 1622 |             locks[nlocks] = -1; | 
| 1623 |         } | 
| 1624 |   | 
| 1625 |         void push(Type t) { | 
| 1626 |             if (debugCode) System.err.println("   pushing " + t); | 
| 1627 |             switch (t.tag) { | 
| 1628 |             case TypeTags.VOID: | 
| 1629 |                 return; | 
| 1630 |             case TypeTags.BYTE: | 
| 1631 |             case TypeTags.CHAR: | 
| 1632 |             case TypeTags.SHORT: | 
| 1633 |             case TypeTags.BOOLEAN: | 
| 1634 |                 t = syms.intType; | 
| 1635 |                 break; | 
| 1636 |             default: | 
| 1637 |                 break; | 
| 1638 |             } | 
| 1639 |             if (stacksize+2 >= stack.length) { | 
| 1640 |                 Type[] newstack = new Type[2*stack.length]; | 
| 1641 |                 System.arraycopy(stack, 0, newstack, 0, stack.length); | 
| 1642 |                 stack = newstack; | 
| 1643 |             } | 
| 1644 |             stack[stacksize++] = t; | 
| 1645 |             switch (width(t)) { | 
| 1646 |             case 1: | 
| 1647 |                 break; | 
| 1648 |             case 2: | 
| 1649 |                 stack[stacksize++] = null; | 
| 1650 |                 break; | 
| 1651 |             default: | 
| 1652 |                 throw new AssertionError(t); | 
| 1653 |             } | 
| 1654 |             if (stacksize > max_stack) | 
| 1655 |                 max_stack = stacksize; | 
| 1656 |         } | 
| 1657 |   | 
| 1658 |         Type pop1() { | 
| 1659 |             if (debugCode) System.err.println("   popping " + 1); | 
| 1660 |             stacksize--; | 
| 1661 |             Type result = stack[stacksize]; | 
| 1662 |             stack[stacksize] = null; | 
| 1663 |             assert result != null && width(result) == 1; | 
| 1664 |             return result; | 
| 1665 |         } | 
| 1666 |   | 
| 1667 |         Type peek() { | 
| 1668 |             return stack[stacksize-1]; | 
| 1669 |         } | 
| 1670 |   | 
| 1671 |         Type pop2() { | 
| 1672 |             if (debugCode) System.err.println("   popping " + 2); | 
| 1673 |             stacksize -= 2; | 
| 1674 |             Type result = stack[stacksize]; | 
| 1675 |             stack[stacksize] = null; | 
| 1676 |             assert stack[stacksize+1] == null; | 
| 1677 |             assert result != null && width(result) == 2; | 
| 1678 |             return result; | 
| 1679 |         } | 
| 1680 |   | 
| 1681 |         void pop(int n) { | 
| 1682 |             if (debugCode) System.err.println("   popping " + n); | 
| 1683 |             while (n > 0) { | 
| 1684 |                 stack[--stacksize] = null; | 
| 1685 |                 n--; | 
| 1686 |             } | 
| 1687 |         } | 
| 1688 |   | 
| 1689 |         void pop(Type t) { | 
| 1690 |             pop(width(t)); | 
| 1691 |         } | 
| 1692 |   | 
| 1693 |         /** Force the top of the stack to be treated as this supertype | 
| 1694 |          *  of its current type. */ | 
| 1695 |         void forceStackTop(Type t) { | 
| 1696 |             if (!alive) return; | 
| 1697 |             switch (t.tag) { | 
| 1698 |             case CLASS: | 
| 1699 |             case ARRAY: | 
| 1700 |                 int width = width(t); | 
| 1701 |                 Type old = stack[stacksize-width]; | 
| 1702 |                 assert types.isSubtype(types.erasure(old), | 
| 1703 |                                        types.erasure(t)); | 
| 1704 |                 stack[stacksize-width] = t; | 
| 1705 |                 break; | 
| 1706 |             default: | 
| 1707 |             } | 
| 1708 |         } | 
| 1709 |   | 
| 1710 |         void markInitialized(UninitializedType old) { | 
| 1711 |             Type newtype = old.initializedType(); | 
| 1712 |             for (int i=0; i<stacksize; i++) | 
| 1713 |                 if (stack[i] == old) stack[i] = newtype; | 
| 1714 |             for (int i=0; i<lvar.length; i++) { | 
| 1715 |                 LocalVar lv = lvar[i]; | 
| 1716 |                 if (lv != null && lv.sym.type == old) { | 
| 1717 |                     VarSymbol sym = lv.sym; | 
| 1718 |                     sym = sym.clone(sym.owner); | 
| 1719 |                     sym.type = newtype; | 
| 1720 |                     LocalVar newlv = lvar[i] = new LocalVar(sym); | 
| 1721 |                     // should the following be initialized to cp? | 
| 1722 |                     newlv.start_pc = lv.start_pc; | 
| 1723 |                 } | 
| 1724 |             } | 
| 1725 |         } | 
| 1726 |   | 
| 1727 |         State join(State other) { | 
| 1728 |             defined = defined.andSet(other.defined); | 
| 1729 |             assert stacksize == other.stacksize; | 
| 1730 |             assert nlocks == other.nlocks; | 
| 1731 |             for (int i=0; i<stacksize; ) { | 
| 1732 |                 Type t = stack[i]; | 
| 1733 |                 Type tother = other.stack[i]; | 
| 1734 |                 Type result = | 
| 1735 |                     t==tother ? t : | 
| 1736 |                     types.isSubtype(t, tother) ? tother : | 
| 1737 |                     types.isSubtype(tother, t) ? t : | 
| 1738 |                     error(); | 
| 1739 |                 int w = width(result); | 
| 1740 |                 stack[i] = result; | 
| 1741 |                 if (w == 2) assert stack[i+1] == null; | 
| 1742 |                 i += w; | 
| 1743 |             } | 
| 1744 |             return this; | 
| 1745 |         } | 
| 1746 |   | 
| 1747 |         Type error() { | 
| 1748 |             throw new AssertionError("inconsistent stack types at join point"); | 
| 1749 |         } | 
| 1750 |   | 
| 1751 |         void dump() { | 
| 1752 |             dump(-1); | 
| 1753 |         } | 
| 1754 |   | 
| 1755 |         void dump(int pc) { | 
| 1756 |             System.err.print("stackMap for " + meth.owner + "." + meth); | 
| 1757 |             if (pc == -1) | 
| 1758 |                 System.out.println(); | 
| 1759 |             else | 
| 1760 |                 System.out.println(" at " + pc); | 
| 1761 |             System.err.println(" stack (from bottom):"); | 
| 1762 |             for (int i=0; i<stacksize; i++) | 
| 1763 |                 System.err.println("  " + i + ": " + stack[i]); | 
| 1764 |   | 
| 1765 |             int lastLocal = 0; | 
| 1766 |             for (int i=max_locals-1; i>=0; i--) { | 
| 1767 |                 if (defined.isMember(i)) { | 
| 1768 |                     lastLocal = i; | 
| 1769 |                     break; | 
| 1770 |                 } | 
| 1771 |             } | 
| 1772 |             if (lastLocal >= 0) | 
| 1773 |                 System.err.println(" locals:"); | 
| 1774 |             for (int i=0; i<=lastLocal; i++) { | 
| 1775 |                 System.err.print("  " + i + ": "); | 
| 1776 |                 if (defined.isMember(i)) { | 
| 1777 |                     LocalVar var = lvar[i]; | 
| 1778 |                     if (var == null) { | 
| 1779 |                         System.err.println("(none)"); | 
| 1780 |                     } else if (var.sym == null) | 
| 1781 |                         System.err.println("UNKNOWN!"); | 
| 1782 |                     else | 
| 1783 |                         System.err.println("" + var.sym + " of type " + | 
| 1784 |                                            var.sym.erasure(types)); | 
| 1785 |                 } else { | 
| 1786 |                     System.err.println("undefined"); | 
| 1787 |                 } | 
| 1788 |             } | 
| 1789 |             if (nlocks != 0) { | 
| 1790 |                 System.err.print(" locks:"); | 
| 1791 |                 for (int i=0; i<nlocks; i++) { | 
| 1792 |                     System.err.print(" " + locks[i]); | 
| 1793 |                 } | 
| 1794 |                 System.err.println(); | 
| 1795 |             } | 
| 1796 |         } | 
| 1797 |     } | 
| 1798 |   | 
| 1799 |     static Type jsrReturnValue = new Type(TypeTags.INT, null); | 
| 1800 |   | 
| 1801 |   | 
| 1802 | /* ************************************************************************** | 
| 1803 |  * Local variables | 
| 1804 |  ****************************************************************************/ | 
| 1805 |   | 
| 1806 |     /** A live range of a local variable. */ | 
| 1807 |     static class LocalVar { | 
| 1808 |         final VarSymbol sym; | 
| 1809 |         final char reg; | 
| 1810 |         char start_pc = Character.MAX_VALUE; | 
| 1811 |         char length = Character.MAX_VALUE; | 
| 1812 |         LocalVar(VarSymbol v) { | 
| 1813 |             this.sym = v; | 
| 1814 |             this.reg = (char)v.adr; | 
| 1815 |         } | 
| 1816 |         public LocalVar dup() { | 
| 1817 |             return new LocalVar(sym); | 
| 1818 |         } | 
| 1819 |         public String toString() { | 
| 1820 |             return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length); | 
| 1821 |         } | 
| 1822 |     }; | 
| 1823 |   | 
| 1824 |     /** Local variables, indexed by register. */ | 
| 1825 |     LocalVar[] lvar; | 
| 1826 |   | 
| 1827 |     /** Add a new local variable. */ | 
| 1828 |     private void addLocalVar(VarSymbol v) { | 
| 1829 |         int adr = v.adr; | 
| 1830 |         if (adr+1 >= lvar.length) { | 
| 1831 |             int newlength = lvar.length << 1; | 
| 1832 |             if (newlength <= adr) newlength = adr + 10; | 
| 1833 |             LocalVar[] new_lvar = new LocalVar[newlength]; | 
| 1834 |             System.arraycopy(lvar, 0, new_lvar, 0, lvar.length); | 
| 1835 |             lvar = new_lvar; | 
| 1836 |         } | 
| 1837 |         assert lvar[adr] == null; | 
| 1838 |         if (pendingJumps != null) resolvePending(); | 
| 1839 |         lvar[adr] = new LocalVar(v); | 
| 1840 |         state.defined.excl(adr); | 
| 1841 |     } | 
| 1842 |   | 
| 1843 |     /** Set the current variable defined state. */ | 
| 1844 |     public void setDefined(Bits newDefined) { | 
| 1845 |         if (alive && newDefined != state.defined) { | 
| 1846 |             Bits diff = state.defined.dup().xorSet(newDefined); | 
| 1847 |             for (int adr = diff.nextBit(0); | 
| 1848 |                  adr >= 0; | 
| 1849 |                  adr = diff.nextBit(adr+1)) { | 
| 1850 |                 if (adr >= nextreg) | 
| 1851 |                     state.defined.excl(adr); | 
| 1852 |                 else if (state.defined.isMember(adr)) | 
| 1853 |                     setUndefined(adr); | 
| 1854 |                 else | 
| 1855 |                     setDefined(adr); | 
| 1856 |             } | 
| 1857 |         } | 
| 1858 |     } | 
| 1859 |   | 
| 1860 |     /** Mark a register as being (possibly) defined. */ | 
| 1861 |     public void setDefined(int adr) { | 
| 1862 |         LocalVar v = lvar[adr]; | 
| 1863 |         if (v == null) { | 
| 1864 |             state.defined.excl(adr); | 
| 1865 |         } else { | 
| 1866 |             state.defined.incl(adr); | 
| 1867 |             if (cp < Character.MAX_VALUE) { | 
| 1868 |                 if (v.start_pc == Character.MAX_VALUE) | 
| 1869 |                     v.start_pc = (char)cp; | 
| 1870 |             } | 
| 1871 |         } | 
| 1872 |     } | 
| 1873 |   | 
| 1874 |     /** Mark a register as being undefined. */ | 
| 1875 |     public void setUndefined(int adr) { | 
| 1876 |         state.defined.excl(adr); | 
| 1877 |         if (adr < lvar.length && | 
| 1878 |             lvar[adr] != null && | 
| 1879 |             lvar[adr].start_pc != Character.MAX_VALUE) { | 
| 1880 |             LocalVar v = lvar[adr]; | 
| 1881 |             char length = (char)(curPc() - v.start_pc); | 
| 1882 |             if (length > 0 && length < Character.MAX_VALUE) { | 
| 1883 |                 lvar[adr] = v.dup(); | 
| 1884 |                 v.length = length; | 
| 1885 |                 putVar(v); | 
| 1886 |             } else { | 
| 1887 |                 v.start_pc = Character.MAX_VALUE; | 
| 1888 |             } | 
| 1889 |         } | 
| 1890 |     } | 
| 1891 |   | 
| 1892 |     /** End the scope of a variable. */ | 
| 1893 |     private void endScope(int adr) { | 
| 1894 |         LocalVar v = lvar[adr]; | 
| 1895 |         if (v != null) { | 
| 1896 |             lvar[adr] = null; | 
| 1897 |             if (v.start_pc != Character.MAX_VALUE) { | 
| 1898 |                 char length = (char)(curPc() - v.start_pc); | 
| 1899 |                 if (length < Character.MAX_VALUE) { | 
| 1900 |                     v.length = length; | 
| 1901 |                     putVar(v); | 
| 1902 |                 } | 
| 1903 |             } | 
| 1904 |         } | 
| 1905 |         state.defined.excl(adr); | 
| 1906 |     } | 
| 1907 |   | 
| 1908 |     /** Put a live variable range into the buffer to be output to the | 
| 1909 |      *  class file. | 
| 1910 |      */ | 
| 1911 |     void putVar(LocalVar var) { | 
| 1912 |         if (!varDebugInfo) return; | 
| 1913 |         if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return; | 
| 1914 |         if (varBuffer == null) | 
| 1915 |             varBuffer = new LocalVar[20]; | 
| 1916 |         else if (varBufferSize >= varBuffer.length) { | 
| 1917 |             LocalVar[] newVarBuffer = new LocalVar[varBufferSize*2]; | 
| 1918 |             System.arraycopy(varBuffer, 0, newVarBuffer, 0, varBuffer.length); | 
| 1919 |             varBuffer = newVarBuffer; | 
| 1920 |         } | 
| 1921 |         varBuffer[varBufferSize++] = var; | 
| 1922 |     } | 
| 1923 |   | 
| 1924 |     /** Previously live local variables, to be put into the variable table. */ | 
| 1925 |     LocalVar[] varBuffer; | 
| 1926 |     int varBufferSize; | 
| 1927 |   | 
| 1928 |     /** Create a new local variable address and return it. | 
| 1929 |      */ | 
| 1930 |     private int newLocal(int typecode) { | 
| 1931 |         int reg = nextreg; | 
| 1932 |         int w = width(typecode); | 
| 1933 |         nextreg = reg + w; | 
| 1934 |         if (nextreg > max_locals) max_locals = nextreg; | 
| 1935 |         return reg; | 
| 1936 |     } | 
| 1937 |   | 
| 1938 |     private int newLocal(Type type) { | 
| 1939 |         return newLocal(typecode(type)); | 
| 1940 |     } | 
| 1941 |   | 
| 1942 |     public int newLocal(VarSymbol v) { | 
| 1943 |         int reg = v.adr = newLocal(v.erasure(types)); | 
| 1944 |         addLocalVar(v); | 
| 1945 |         return reg; | 
| 1946 |     } | 
| 1947 |   | 
| 1948 |     /** Start a set of fresh registers. | 
| 1949 |      */ | 
| 1950 |     public void newRegSegment() { | 
| 1951 |         nextreg = max_locals; | 
| 1952 |     } | 
| 1953 |   | 
| 1954 |     /** End scopes of all variables with registers >= first. | 
| 1955 |      */ | 
| 1956 |     public void endScopes(int first) { | 
| 1957 |         int prevNextReg = nextreg; | 
| 1958 |         nextreg = first; | 
| 1959 |         for (int i = nextreg; i < prevNextReg; i++) endScope(i); | 
| 1960 |     } | 
| 1961 |   | 
| 1962 | /************************************************************************** | 
| 1963 |  * static tables | 
| 1964 |  *************************************************************************/ | 
| 1965 |   | 
| 1966 |     public static String mnem(int opcode) { | 
| 1967 |         return Mneumonics.mnem[opcode]; | 
| 1968 |     } | 
| 1969 |   | 
| 1970 |     private static class Mneumonics { | 
| 1971 |         private final static String[] mnem = new String[ByteCodeCount]; | 
| 1972 |         static { | 
| 1973 |             mnem[nop] = "nop"; | 
| 1974 |             mnem[aconst_null] = "aconst_null"; | 
| 1975 |             mnem[iconst_m1] = "iconst_m1"; | 
| 1976 |             mnem[iconst_0] = "iconst_0"; | 
| 1977 |             mnem[iconst_1] = "iconst_1"; | 
| 1978 |             mnem[iconst_2] = "iconst_2"; | 
| 1979 |             mnem[iconst_3] = "iconst_3"; | 
| 1980 |             mnem[iconst_4] = "iconst_4"; | 
| 1981 |             mnem[iconst_5] = "iconst_5"; | 
| 1982 |             mnem[lconst_0] = "lconst_0"; | 
| 1983 |             mnem[lconst_1] = "lconst_1"; | 
| 1984 |             mnem[fconst_0] = "fconst_0"; | 
| 1985 |             mnem[fconst_1] = "fconst_1"; | 
| 1986 |             mnem[fconst_2] = "fconst_2"; | 
| 1987 |             mnem[dconst_0] = "dconst_0"; | 
| 1988 |             mnem[dconst_1] = "dconst_1"; | 
| 1989 |             mnem[bipush] = "bipush"; | 
| 1990 |             mnem[sipush] = "sipush"; | 
| 1991 |             mnem[ldc1] = "ldc1"; | 
| 1992 |             mnem[ldc2] = "ldc2"; | 
| 1993 |             mnem[ldc2w] = "ldc2w"; | 
| 1994 |             mnem[iload] = "iload"; | 
| 1995 |             mnem[lload] = "lload"; | 
| 1996 |             mnem[fload] = "fload"; | 
| 1997 |             mnem[dload] = "dload"; | 
| 1998 |             mnem[aload] = "aload"; | 
| 1999 |             mnem[iload_0] = "iload_0"; | 
| 2000 |             mnem[lload_0] = "lload_0"; | 
| 2001 |             mnem[fload_0] = "fload_0"; | 
| 2002 |             mnem[dload_0] = "dload_0"; | 
| 2003 |             mnem[aload_0] = "aload_0"; | 
| 2004 |             mnem[iload_1] = "iload_1"; | 
| 2005 |             mnem[lload_1] = "lload_1"; | 
| 2006 |             mnem[fload_1] = "fload_1"; | 
| 2007 |             mnem[dload_1] = "dload_1"; | 
| 2008 |             mnem[aload_1] = "aload_1"; | 
| 2009 |             mnem[iload_2] = "iload_2"; | 
| 2010 |             mnem[lload_2] = "lload_2"; | 
| 2011 |             mnem[fload_2] = "fload_2"; | 
| 2012 |             mnem[dload_2] = "dload_2"; | 
| 2013 |             mnem[aload_2] = "aload_2"; | 
| 2014 |             mnem[iload_3] = "iload_3"; | 
| 2015 |             mnem[lload_3] = "lload_3"; | 
| 2016 |             mnem[fload_3] = "fload_3"; | 
| 2017 |             mnem[dload_3] = "dload_3"; | 
| 2018 |             mnem[aload_3] = "aload_3"; | 
| 2019 |             mnem[iaload] = "iaload"; | 
| 2020 |             mnem[laload] = "laload"; | 
| 2021 |             mnem[faload] = "faload"; | 
| 2022 |             mnem[daload] = "daload"; | 
| 2023 |             mnem[aaload] = "aaload"; | 
| 2024 |             mnem[baload] = "baload"; | 
| 2025 |             mnem[caload] = "caload"; | 
| 2026 |             mnem[saload] = "saload"; | 
| 2027 |             mnem[istore] = "istore"; | 
| 2028 |             mnem[lstore] = "lstore"; | 
| 2029 |             mnem[fstore] = "fstore"; | 
| 2030 |             mnem[dstore] = "dstore"; | 
| 2031 |             mnem[astore] = "astore"; | 
| 2032 |             mnem[istore_0] = "istore_0"; | 
| 2033 |             mnem[lstore_0] = "lstore_0"; | 
| 2034 |             mnem[fstore_0] = "fstore_0"; | 
| 2035 |             mnem[dstore_0] = "dstore_0"; | 
| 2036 |             mnem[astore_0] = "astore_0"; | 
| 2037 |             mnem[istore_1] = "istore_1"; | 
| 2038 |             mnem[lstore_1] = "lstore_1"; | 
| 2039 |             mnem[fstore_1] = "fstore_1"; | 
| 2040 |             mnem[dstore_1] = "dstore_1"; | 
| 2041 |             mnem[astore_1] = "astore_1"; | 
| 2042 |             mnem[istore_2] = "istore_2"; | 
| 2043 |             mnem[lstore_2] = "lstore_2"; | 
| 2044 |             mnem[fstore_2] = "fstore_2"; | 
| 2045 |             mnem[dstore_2] = "dstore_2"; | 
| 2046 |             mnem[astore_2] = "astore_2"; | 
| 2047 |             mnem[istore_3] = "istore_3"; | 
| 2048 |             mnem[lstore_3] = "lstore_3"; | 
| 2049 |             mnem[fstore_3] = "fstore_3"; | 
| 2050 |             mnem[dstore_3] = "dstore_3"; | 
| 2051 |             mnem[astore_3] = "astore_3"; | 
| 2052 |             mnem[iastore] = "iastore"; | 
| 2053 |             mnem[lastore] = "lastore"; | 
| 2054 |             mnem[fastore] = "fastore"; | 
| 2055 |             mnem[dastore] = "dastore"; | 
| 2056 |             mnem[aastore] = "aastore"; | 
| 2057 |             mnem[bastore] = "bastore"; | 
| 2058 |             mnem[castore] = "castore"; | 
| 2059 |             mnem[sastore] = "sastore"; | 
| 2060 |             mnem[pop] = "pop"; | 
| 2061 |             mnem[pop2] = "pop2"; | 
| 2062 |             mnem[dup] = "dup"; | 
| 2063 |             mnem[dup_x1] = "dup_x1"; | 
| 2064 |             mnem[dup_x2] = "dup_x2"; | 
| 2065 |             mnem[dup2] = "dup2"; | 
| 2066 |             mnem[dup2_x1] = "dup2_x1"; | 
| 2067 |             mnem[dup2_x2] = "dup2_x2"; | 
| 2068 |             mnem[swap] = "swap"; | 
| 2069 |             mnem[iadd] = "iadd"; | 
| 2070 |             mnem[ladd] = "ladd"; | 
| 2071 |             mnem[fadd] = "fadd"; | 
| 2072 |             mnem[dadd] = "dadd"; | 
| 2073 |             mnem[isub] = "isub"; | 
| 2074 |             mnem[lsub] = "lsub"; | 
| 2075 |             mnem[fsub] = "fsub"; | 
| 2076 |             mnem[dsub] = "dsub"; | 
| 2077 |             mnem[imul] = "imul"; | 
| 2078 |             mnem[lmul] = "lmul"; | 
| 2079 |             mnem[fmul] = "fmul"; | 
| 2080 |             mnem[dmul] = "dmul"; | 
| 2081 |             mnem[idiv] = "idiv"; | 
| 2082 |             mnem[ldiv] = "ldiv"; | 
| 2083 |             mnem[fdiv] = "fdiv"; | 
| 2084 |             mnem[ddiv] = "ddiv"; | 
| 2085 |             mnem[imod] = "imod"; | 
| 2086 |             mnem[lmod] = "lmod"; | 
| 2087 |             mnem[fmod] = "fmod"; | 
| 2088 |             mnem[dmod] = "dmod"; | 
| 2089 |             mnem[ineg] = "ineg"; | 
| 2090 |             mnem[lneg] = "lneg"; | 
| 2091 |             mnem[fneg] = "fneg"; | 
| 2092 |             mnem[dneg] = "dneg"; | 
| 2093 |             mnem[ishl] = "ishl"; | 
| 2094 |             mnem[lshl] = "lshl"; | 
| 2095 |             mnem[ishr] = "ishr"; | 
| 2096 |             mnem[lshr] = "lshr"; | 
| 2097 |             mnem[iushr] = "iushr"; | 
| 2098 |             mnem[lushr] = "lushr"; | 
| 2099 |             mnem[iand] = "iand"; | 
| 2100 |             mnem[land] = "land"; | 
| 2101 |             mnem[ior] = "ior"; | 
| 2102 |             mnem[lor] = "lor"; | 
| 2103 |             mnem[ixor] = "ixor"; | 
| 2104 |             mnem[lxor] = "lxor"; | 
| 2105 |             mnem[iinc] = "iinc"; | 
| 2106 |             mnem[i2l] = "i2l"; | 
| 2107 |             mnem[i2f] = "i2f"; | 
| 2108 |             mnem[i2d] = "i2d"; | 
| 2109 |             mnem[l2i] = "l2i"; | 
| 2110 |             mnem[l2f] = "l2f"; | 
| 2111 |             mnem[l2d] = "l2d"; | 
| 2112 |             mnem[f2i] = "f2i"; | 
| 2113 |             mnem[f2l] = "f2l"; | 
| 2114 |             mnem[f2d] = "f2d"; | 
| 2115 |             mnem[d2i] = "d2i"; | 
| 2116 |             mnem[d2l] = "d2l"; | 
| 2117 |             mnem[d2f] = "d2f"; | 
| 2118 |             mnem[int2byte] = "int2byte"; | 
| 2119 |             mnem[int2char] = "int2char"; | 
| 2120 |             mnem[int2short] = "int2short"; | 
| 2121 |             mnem[lcmp] = "lcmp"; | 
| 2122 |             mnem[fcmpl] = "fcmpl"; | 
| 2123 |             mnem[fcmpg] = "fcmpg"; | 
| 2124 |             mnem[dcmpl] = "dcmpl"; | 
| 2125 |             mnem[dcmpg] = "dcmpg"; | 
| 2126 |             mnem[ifeq] = "ifeq"; | 
| 2127 |             mnem[ifne] = "ifne"; | 
| 2128 |             mnem[iflt] = "iflt"; | 
| 2129 |             mnem[ifge] = "ifge"; | 
| 2130 |             mnem[ifgt] = "ifgt"; | 
| 2131 |             mnem[ifle] = "ifle"; | 
| 2132 |             mnem[if_icmpeq] = "if_icmpeq"; | 
| 2133 |             mnem[if_icmpne] = "if_icmpne"; | 
| 2134 |             mnem[if_icmplt] = "if_icmplt"; | 
| 2135 |             mnem[if_icmpge] = "if_icmpge"; | 
| 2136 |             mnem[if_icmpgt] = "if_icmpgt"; | 
| 2137 |             mnem[if_icmple] = "if_icmple"; | 
| 2138 |             mnem[if_acmpeq] = "if_acmpeq"; | 
| 2139 |             mnem[if_acmpne] = "if_acmpne"; | 
| 2140 |             mnem[goto_] = "goto_"; | 
| 2141 |             mnem[jsr] = "jsr"; | 
| 2142 |             mnem[ret] = "ret"; | 
| 2143 |             mnem[tableswitch] = "tableswitch"; | 
| 2144 |             mnem[lookupswitch] = "lookupswitch"; | 
| 2145 |             mnem[ireturn] = "ireturn"; | 
| 2146 |             mnem[lreturn] = "lreturn"; | 
| 2147 |             mnem[freturn] = "freturn"; | 
| 2148 |             mnem[dreturn] = "dreturn"; | 
| 2149 |             mnem[areturn] = "areturn"; | 
| 2150 |             mnem[return_] = "return_"; | 
| 2151 |             mnem[getstatic] = "getstatic"; | 
| 2152 |             mnem[putstatic] = "putstatic"; | 
| 2153 |             mnem[getfield] = "getfield"; | 
| 2154 |             mnem[putfield] = "putfield"; | 
| 2155 |             mnem[invokevirtual] = "invokevirtual"; | 
| 2156 |             mnem[invokespecial] = "invokespecial"; | 
| 2157 |             mnem[invokestatic] = "invokestatic"; | 
| 2158 |             mnem[invokeinterface] = "invokeinterface"; | 
| 2159 |             // mnem[___unused___] = "___unused___"; | 
| 2160 |             mnem[new_] = "new_"; | 
| 2161 |             mnem[newarray] = "newarray"; | 
| 2162 |             mnem[anewarray] = "anewarray"; | 
| 2163 |             mnem[arraylength] = "arraylength"; | 
| 2164 |             mnem[athrow] = "athrow"; | 
| 2165 |             mnem[checkcast] = "checkcast"; | 
| 2166 |             mnem[instanceof_] = "instanceof_"; | 
| 2167 |             mnem[monitorenter] = "monitorenter"; | 
| 2168 |             mnem[monitorexit] = "monitorexit"; | 
| 2169 |             mnem[wide] = "wide"; | 
| 2170 |             mnem[multianewarray] = "multianewarray"; | 
| 2171 |             mnem[if_acmp_null] = "if_acmp_null"; | 
| 2172 |             mnem[if_acmp_nonnull] = "if_acmp_nonnull"; | 
| 2173 |             mnem[goto_w] = "goto_w"; | 
| 2174 |             mnem[jsr_w] = "jsr_w"; | 
| 2175 |             mnem[breakpoint] = "breakpoint"; | 
| 2176 |         } | 
| 2177 |     } | 
| 2178 | } |