src/share/classes/com/sun/tools/javac/jvm/Code.java

Thu, 25 Sep 2014 17:09:23 -0700

author
vromero
date
Thu, 25 Sep 2014 17:09:23 -0700
changeset 2572
31d2a837676f
parent 2534
71a31843f550
child 2595
1cf5a53613ae
permissions
-rw-r--r--

8058708: java.lang.AssertionError compiling source code
Reviewed-by: jjg

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

mercurial