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

Fri, 26 Jun 2009 18:51:39 -0700

author
jjg
date
Fri, 26 Jun 2009 18:51:39 -0700
changeset 308
03944ee4fac4
parent 267
e2722bd43f3a
child 310
7c154fdc3547
permissions
-rw-r--r--

6843077: JSR 308: Annotations on types
Reviewed-by: jjg, mcimadamore, darcy
Contributed-by: mernst@cs.washington.edu, mali@csail.mit.edu, mpapi@csail.mit.edu

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

mercurial