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

Mon, 16 Oct 2017 16:07:48 +0800

author
aoqi
date
Mon, 16 Oct 2017 16:07:48 +0800
changeset 2893
ca5783d9a597
parent 2734
ba758e1ffa69
parent 2702
9ca8d8713094
permissions
-rw-r--r--

merge

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

mercurial