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

Tue, 04 Mar 2008 15:45:20 +0000

author
mcimadamore
date
Tue, 04 Mar 2008 15:45:20 +0000
changeset 8
38bd6375f37d
parent 1
9a66ca7c79fa
child 104
5e89c4ca637c
permissions
-rw-r--r--

6663588: Compiler goes into infinite loop for Cyclic Inheritance test case
Summary: interplay between cyclic inheritance and tvar bounds hangs javac
Reviewed-by: jjg

duke@1 1 /*
duke@1 2 * Copyright 1999-2007 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.util.*;
duke@1 29 import com.sun.tools.javac.code.*;
duke@1 30
duke@1 31 import com.sun.tools.javac.code.Symbol.*;
duke@1 32 import com.sun.tools.javac.code.Type.*;
duke@1 33 import com.sun.tools.javac.jvm.Code.*;
duke@1 34 import com.sun.tools.javac.tree.JCTree;
duke@1 35
duke@1 36 import static com.sun.tools.javac.code.TypeTags.*;
duke@1 37 import static com.sun.tools.javac.jvm.ByteCodes.*;
duke@1 38
duke@1 39 /** A helper class for code generation. Items are objects
duke@1 40 * that stand for addressable entities in the bytecode. Each item
duke@1 41 * supports a fixed protocol for loading the item on the stack, storing
duke@1 42 * into it, converting it into a jump condition, and several others.
duke@1 43 * There are many individual forms of items, such as local, static,
duke@1 44 * indexed, or instance variables, values on the top of stack, the
duke@1 45 * special values this or super, etc. Individual items are represented as
duke@1 46 * inner classes in class Items.
duke@1 47 *
duke@1 48 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
duke@1 49 * you write code that depends on this, you do so at your own risk.
duke@1 50 * This code and its internal interfaces are subject to change or
duke@1 51 * deletion without notice.</b>
duke@1 52 */
duke@1 53 public class Items {
duke@1 54
duke@1 55 /** The current constant pool.
duke@1 56 */
duke@1 57 Pool pool;
duke@1 58
duke@1 59 /** The current code buffer.
duke@1 60 */
duke@1 61 Code code;
duke@1 62
duke@1 63 /** The current symbol table.
duke@1 64 */
duke@1 65 Symtab syms;
duke@1 66
duke@1 67 /** Type utilities. */
duke@1 68 Types types;
duke@1 69
duke@1 70 /** Items that exist only once (flyweight pattern).
duke@1 71 */
duke@1 72 private final Item voidItem;
duke@1 73 private final Item thisItem;
duke@1 74 private final Item superItem;
duke@1 75 private final Item[] stackItem = new Item[TypeCodeCount];
duke@1 76
duke@1 77 public Items(Pool pool, Code code, Symtab syms, Types types) {
duke@1 78 this.code = code;
duke@1 79 this.pool = pool;
duke@1 80 this.types = types;
duke@1 81 voidItem = new Item(VOIDcode) {
duke@1 82 public String toString() { return "void"; }
duke@1 83 };
duke@1 84 thisItem = new SelfItem(false);
duke@1 85 superItem = new SelfItem(true);
duke@1 86 for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i);
duke@1 87 stackItem[VOIDcode] = voidItem;
duke@1 88 this.syms = syms;
duke@1 89 }
duke@1 90
duke@1 91 /** Make a void item
duke@1 92 */
duke@1 93 Item makeVoidItem() {
duke@1 94 return voidItem;
duke@1 95 }
duke@1 96 /** Make an item representing `this'.
duke@1 97 */
duke@1 98 Item makeThisItem() {
duke@1 99 return thisItem;
duke@1 100 }
duke@1 101
duke@1 102 /** Make an item representing `super'.
duke@1 103 */
duke@1 104 Item makeSuperItem() {
duke@1 105 return superItem;
duke@1 106 }
duke@1 107
duke@1 108 /** Make an item representing a value on stack.
duke@1 109 * @param type The value's type.
duke@1 110 */
duke@1 111 Item makeStackItem(Type type) {
duke@1 112 return stackItem[Code.typecode(type)];
duke@1 113 }
duke@1 114
duke@1 115 /** Make an item representing an indexed expression.
duke@1 116 * @param type The expression's type.
duke@1 117 */
duke@1 118 Item makeIndexedItem(Type type) {
duke@1 119 return new IndexedItem(type);
duke@1 120 }
duke@1 121
duke@1 122 /** Make an item representing a local variable.
duke@1 123 * @param v The represented variable.
duke@1 124 */
duke@1 125 LocalItem makeLocalItem(VarSymbol v) {
duke@1 126 return new LocalItem(v.erasure(types), v.adr);
duke@1 127 }
duke@1 128
duke@1 129 /** Make an item representing a local anonymous variable.
duke@1 130 * @param type The represented variable's type.
duke@1 131 * @param reg The represented variable's register.
duke@1 132 */
duke@1 133 private LocalItem makeLocalItem(Type type, int reg) {
duke@1 134 return new LocalItem(type, reg);
duke@1 135 }
duke@1 136
duke@1 137 /** Make an item representing a static variable or method.
duke@1 138 * @param member The represented symbol.
duke@1 139 */
duke@1 140 Item makeStaticItem(Symbol member) {
duke@1 141 return new StaticItem(member);
duke@1 142 }
duke@1 143
duke@1 144 /** Make an item representing an instance variable or method.
duke@1 145 * @param member The represented symbol.
duke@1 146 * @param nonvirtual Is the reference not virtual? (true for constructors
duke@1 147 * and private members).
duke@1 148 */
duke@1 149 Item makeMemberItem(Symbol member, boolean nonvirtual) {
duke@1 150 return new MemberItem(member, nonvirtual);
duke@1 151 }
duke@1 152
duke@1 153 /** Make an item representing a literal.
duke@1 154 * @param type The literal's type.
duke@1 155 * @param value The literal's value.
duke@1 156 */
duke@1 157 Item makeImmediateItem(Type type, Object value) {
duke@1 158 return new ImmediateItem(type, value);
duke@1 159 }
duke@1 160
duke@1 161 /** Make an item representing an assignment expression.
duke@1 162 * @param lhs The item representing the assignment's left hand side.
duke@1 163 */
duke@1 164 Item makeAssignItem(Item lhs) {
duke@1 165 return new AssignItem(lhs);
duke@1 166 }
duke@1 167
duke@1 168 /** Make an item representing a conditional or unconditional jump.
duke@1 169 * @param opcode The jump's opcode.
duke@1 170 * @param trueJumps A chain encomassing all jumps that can be taken
duke@1 171 * if the condition evaluates to true.
duke@1 172 * @param falseJumps A chain encomassing all jumps that can be taken
duke@1 173 * if the condition evaluates to false.
duke@1 174 */
duke@1 175 CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
duke@1 176 return new CondItem(opcode, trueJumps, falseJumps);
duke@1 177 }
duke@1 178
duke@1 179 /** Make an item representing a conditional or unconditional jump.
duke@1 180 * @param opcode The jump's opcode.
duke@1 181 */
duke@1 182 CondItem makeCondItem(int opcode) {
duke@1 183 return makeCondItem(opcode, null, null);
duke@1 184 }
duke@1 185
duke@1 186 /** The base class of all items, which implements default behavior.
duke@1 187 */
duke@1 188 abstract class Item {
duke@1 189
duke@1 190 /** The type code of values represented by this item.
duke@1 191 */
duke@1 192 int typecode;
duke@1 193
duke@1 194 Item(int typecode) {
duke@1 195 this.typecode = typecode;
duke@1 196 }
duke@1 197
duke@1 198 /** Generate code to load this item onto stack.
duke@1 199 */
duke@1 200 Item load() {
duke@1 201 throw new AssertionError();
duke@1 202 }
duke@1 203
duke@1 204 /** Generate code to store top of stack into this item.
duke@1 205 */
duke@1 206 void store() {
duke@1 207 throw new AssertionError("store unsupported: " + this);
duke@1 208 }
duke@1 209
duke@1 210 /** Generate code to invoke method represented by this item.
duke@1 211 */
duke@1 212 Item invoke() {
duke@1 213 throw new AssertionError(this);
duke@1 214 }
duke@1 215
duke@1 216 /** Generate code to use this item twice.
duke@1 217 */
duke@1 218 void duplicate() {}
duke@1 219
duke@1 220 /** Generate code to avoid having to use this item.
duke@1 221 */
duke@1 222 void drop() {}
duke@1 223
duke@1 224 /** Generate code to stash a copy of top of stack - of typecode toscode -
duke@1 225 * under this item.
duke@1 226 */
duke@1 227 void stash(int toscode) {
duke@1 228 stackItem[toscode].duplicate();
duke@1 229 }
duke@1 230
duke@1 231 /** Generate code to turn item into a testable condition.
duke@1 232 */
duke@1 233 CondItem mkCond() {
duke@1 234 load();
duke@1 235 return makeCondItem(ifne);
duke@1 236 }
duke@1 237
duke@1 238 /** Generate code to coerce item to given type code.
duke@1 239 * @param targetcode The type code to coerce to.
duke@1 240 */
duke@1 241 Item coerce(int targetcode) {
duke@1 242 if (typecode == targetcode)
duke@1 243 return this;
duke@1 244 else {
duke@1 245 load();
duke@1 246 int typecode1 = Code.truncate(typecode);
duke@1 247 int targetcode1 = Code.truncate(targetcode);
duke@1 248 if (typecode1 != targetcode1) {
duke@1 249 int offset = targetcode1 > typecode1 ? targetcode1 - 1
duke@1 250 : targetcode1;
duke@1 251 code.emitop0(i2l + typecode1 * 3 + offset);
duke@1 252 }
duke@1 253 if (targetcode != targetcode1) {
duke@1 254 code.emitop0(int2byte + targetcode - BYTEcode);
duke@1 255 }
duke@1 256 return stackItem[targetcode];
duke@1 257 }
duke@1 258 }
duke@1 259
duke@1 260 /** Generate code to coerce item to given type.
duke@1 261 * @param targettype The type to coerce to.
duke@1 262 */
duke@1 263 Item coerce(Type targettype) {
duke@1 264 return coerce(Code.typecode(targettype));
duke@1 265 }
duke@1 266
duke@1 267 /** Return the width of this item on stack as a number of words.
duke@1 268 */
duke@1 269 int width() {
duke@1 270 return 0;
duke@1 271 }
duke@1 272
duke@1 273 public abstract String toString();
duke@1 274 }
duke@1 275
duke@1 276 /** An item representing a value on stack.
duke@1 277 */
duke@1 278 class StackItem extends Item {
duke@1 279
duke@1 280 StackItem(int typecode) {
duke@1 281 super(typecode);
duke@1 282 }
duke@1 283
duke@1 284 Item load() {
duke@1 285 return this;
duke@1 286 }
duke@1 287
duke@1 288 void duplicate() {
duke@1 289 code.emitop0(width() == 2 ? dup2 : dup);
duke@1 290 }
duke@1 291
duke@1 292 void drop() {
duke@1 293 code.emitop0(width() == 2 ? pop2 : pop);
duke@1 294 }
duke@1 295
duke@1 296 void stash(int toscode) {
duke@1 297 code.emitop0(
duke@1 298 (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
duke@1 299 }
duke@1 300
duke@1 301 int width() {
duke@1 302 return Code.width(typecode);
duke@1 303 }
duke@1 304
duke@1 305 public String toString() {
duke@1 306 return "stack(" + typecodeNames[typecode] + ")";
duke@1 307 }
duke@1 308 }
duke@1 309
duke@1 310 /** An item representing an indexed expression.
duke@1 311 */
duke@1 312 class IndexedItem extends Item {
duke@1 313
duke@1 314 IndexedItem(Type type) {
duke@1 315 super(Code.typecode(type));
duke@1 316 }
duke@1 317
duke@1 318 Item load() {
duke@1 319 code.emitop0(iaload + typecode);
duke@1 320 return stackItem[typecode];
duke@1 321 }
duke@1 322
duke@1 323 void store() {
duke@1 324 code.emitop0(iastore + typecode);
duke@1 325 }
duke@1 326
duke@1 327 void duplicate() {
duke@1 328 code.emitop0(dup2);
duke@1 329 }
duke@1 330
duke@1 331 void drop() {
duke@1 332 code.emitop0(pop2);
duke@1 333 }
duke@1 334
duke@1 335 void stash(int toscode) {
duke@1 336 code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
duke@1 337 }
duke@1 338
duke@1 339 int width() {
duke@1 340 return 2;
duke@1 341 }
duke@1 342
duke@1 343 public String toString() {
duke@1 344 return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
duke@1 345 }
duke@1 346 }
duke@1 347
duke@1 348 /** An item representing `this' or `super'.
duke@1 349 */
duke@1 350 class SelfItem extends Item {
duke@1 351
duke@1 352 /** Flag which determines whether this item represents `this' or `super'.
duke@1 353 */
duke@1 354 boolean isSuper;
duke@1 355
duke@1 356 SelfItem(boolean isSuper) {
duke@1 357 super(OBJECTcode);
duke@1 358 this.isSuper = isSuper;
duke@1 359 }
duke@1 360
duke@1 361 Item load() {
duke@1 362 code.emitop0(aload_0);
duke@1 363 return stackItem[typecode];
duke@1 364 }
duke@1 365
duke@1 366 public String toString() {
duke@1 367 return isSuper ? "super" : "this";
duke@1 368 }
duke@1 369 }
duke@1 370
duke@1 371 /** An item representing a local variable.
duke@1 372 */
duke@1 373 class LocalItem extends Item {
duke@1 374
duke@1 375 /** The variable's register.
duke@1 376 */
duke@1 377 int reg;
duke@1 378
duke@1 379 /** The variable's type.
duke@1 380 */
duke@1 381 Type type;
duke@1 382
duke@1 383 LocalItem(Type type, int reg) {
duke@1 384 super(Code.typecode(type));
duke@1 385 assert reg >= 0;
duke@1 386 this.type = type;
duke@1 387 this.reg = reg;
duke@1 388 }
duke@1 389
duke@1 390 Item load() {
duke@1 391 if (reg <= 3)
duke@1 392 code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
duke@1 393 else
duke@1 394 code.emitop1w(iload + Code.truncate(typecode), reg);
duke@1 395 return stackItem[typecode];
duke@1 396 }
duke@1 397
duke@1 398 void store() {
duke@1 399 if (reg <= 3)
duke@1 400 code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
duke@1 401 else
duke@1 402 code.emitop1w(istore + Code.truncate(typecode), reg);
duke@1 403 code.setDefined(reg);
duke@1 404 }
duke@1 405
duke@1 406 void incr(int x) {
duke@1 407 if (typecode == INTcode && x >= -32768 && x <= 32767) {
duke@1 408 code.emitop1w(iinc, reg, x);
duke@1 409 } else {
duke@1 410 load();
duke@1 411 if (x >= 0) {
duke@1 412 makeImmediateItem(syms.intType, x).load();
duke@1 413 code.emitop0(iadd);
duke@1 414 } else {
duke@1 415 makeImmediateItem(syms.intType, -x).load();
duke@1 416 code.emitop0(isub);
duke@1 417 }
duke@1 418 makeStackItem(syms.intType).coerce(typecode);
duke@1 419 store();
duke@1 420 }
duke@1 421 }
duke@1 422
duke@1 423 public String toString() {
duke@1 424 return "localItem(type=" + type + "; reg=" + reg + ")";
duke@1 425 }
duke@1 426 }
duke@1 427
duke@1 428 /** An item representing a static variable or method.
duke@1 429 */
duke@1 430 class StaticItem extends Item {
duke@1 431
duke@1 432 /** The represented symbol.
duke@1 433 */
duke@1 434 Symbol member;
duke@1 435
duke@1 436 StaticItem(Symbol member) {
duke@1 437 super(Code.typecode(member.erasure(types)));
duke@1 438 this.member = member;
duke@1 439 }
duke@1 440
duke@1 441 Item load() {
duke@1 442 code.emitop2(getstatic, pool.put(member));
duke@1 443 return stackItem[typecode];
duke@1 444 }
duke@1 445
duke@1 446 void store() {
duke@1 447 code.emitop2(putstatic, pool.put(member));
duke@1 448 }
duke@1 449
duke@1 450 Item invoke() {
duke@1 451 MethodType mtype = (MethodType)member.erasure(types);
duke@1 452 int argsize = Code.width(mtype.argtypes);
duke@1 453 int rescode = Code.typecode(mtype.restype);
duke@1 454 int sdiff = Code.width(rescode) - argsize;
duke@1 455 code.emitInvokestatic(pool.put(member), mtype);
duke@1 456 return stackItem[rescode];
duke@1 457 }
duke@1 458
duke@1 459 public String toString() {
duke@1 460 return "static(" + member + ")";
duke@1 461 }
duke@1 462 }
duke@1 463
duke@1 464 /** An item representing an instance variable or method.
duke@1 465 */
duke@1 466 class MemberItem extends Item {
duke@1 467
duke@1 468 /** The represented symbol.
duke@1 469 */
duke@1 470 Symbol member;
duke@1 471
duke@1 472 /** Flag that determines whether or not access is virtual.
duke@1 473 */
duke@1 474 boolean nonvirtual;
duke@1 475
duke@1 476 MemberItem(Symbol member, boolean nonvirtual) {
duke@1 477 super(Code.typecode(member.erasure(types)));
duke@1 478 this.member = member;
duke@1 479 this.nonvirtual = nonvirtual;
duke@1 480 }
duke@1 481
duke@1 482 Item load() {
duke@1 483 code.emitop2(getfield, pool.put(member));
duke@1 484 return stackItem[typecode];
duke@1 485 }
duke@1 486
duke@1 487 void store() {
duke@1 488 code.emitop2(putfield, pool.put(member));
duke@1 489 }
duke@1 490
duke@1 491 Item invoke() {
duke@1 492 MethodType mtype = (MethodType)member.externalType(types);
duke@1 493 int rescode = Code.typecode(mtype.restype);
duke@1 494 if ((member.owner.flags() & Flags.INTERFACE) != 0) {
duke@1 495 code.emitInvokeinterface(pool.put(member), mtype);
duke@1 496 } else if (nonvirtual) {
duke@1 497 code.emitInvokespecial(pool.put(member), mtype);
duke@1 498 } else {
duke@1 499 code.emitInvokevirtual(pool.put(member), mtype);
duke@1 500 }
duke@1 501 return stackItem[rescode];
duke@1 502 }
duke@1 503
duke@1 504 void duplicate() {
duke@1 505 stackItem[OBJECTcode].duplicate();
duke@1 506 }
duke@1 507
duke@1 508 void drop() {
duke@1 509 stackItem[OBJECTcode].drop();
duke@1 510 }
duke@1 511
duke@1 512 void stash(int toscode) {
duke@1 513 stackItem[OBJECTcode].stash(toscode);
duke@1 514 }
duke@1 515
duke@1 516 int width() {
duke@1 517 return 1;
duke@1 518 }
duke@1 519
duke@1 520 public String toString() {
duke@1 521 return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
duke@1 522 }
duke@1 523 }
duke@1 524
duke@1 525 /** An item representing a literal.
duke@1 526 */
duke@1 527 class ImmediateItem extends Item {
duke@1 528
duke@1 529 /** The literal's value.
duke@1 530 */
duke@1 531 Object value;
duke@1 532
duke@1 533 ImmediateItem(Type type, Object value) {
duke@1 534 super(Code.typecode(type));
duke@1 535 this.value = value;
duke@1 536 }
duke@1 537
duke@1 538 private void ldc() {
duke@1 539 int idx = pool.put(value);
duke@1 540 if (typecode == LONGcode || typecode == DOUBLEcode) {
duke@1 541 code.emitop2(ldc2w, idx);
duke@1 542 } else if (idx <= 255) {
duke@1 543 code.emitop1(ldc1, idx);
duke@1 544 } else {
duke@1 545 code.emitop2(ldc2, idx);
duke@1 546 }
duke@1 547 }
duke@1 548
duke@1 549 Item load() {
duke@1 550 switch (typecode) {
duke@1 551 case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
duke@1 552 int ival = ((Number)value).intValue();
duke@1 553 if (-1 <= ival && ival <= 5)
duke@1 554 code.emitop0(iconst_0 + ival);
duke@1 555 else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
duke@1 556 code.emitop1(bipush, ival);
duke@1 557 else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
duke@1 558 code.emitop2(sipush, ival);
duke@1 559 else
duke@1 560 ldc();
duke@1 561 break;
duke@1 562 case LONGcode:
duke@1 563 long lval = ((Number)value).longValue();
duke@1 564 if (lval == 0 || lval == 1)
duke@1 565 code.emitop0(lconst_0 + (int)lval);
duke@1 566 else
duke@1 567 ldc();
duke@1 568 break;
duke@1 569 case FLOATcode:
duke@1 570 float fval = ((Number)value).floatValue();
duke@1 571 if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
duke@1 572 code.emitop0(fconst_0 + (int)fval);
duke@1 573 else {
duke@1 574 ldc();
duke@1 575 }
duke@1 576 break;
duke@1 577 case DOUBLEcode:
duke@1 578 double dval = ((Number)value).doubleValue();
duke@1 579 if (isPosZero(dval) || dval == 1.0)
duke@1 580 code.emitop0(dconst_0 + (int)dval);
duke@1 581 else
duke@1 582 ldc();
duke@1 583 break;
duke@1 584 case OBJECTcode:
duke@1 585 ldc();
duke@1 586 break;
duke@1 587 default:
duke@1 588 assert false;
duke@1 589 }
duke@1 590 return stackItem[typecode];
duke@1 591 }
duke@1 592 //where
duke@1 593 /** Return true iff float number is positive 0.
duke@1 594 */
duke@1 595 private boolean isPosZero(float x) {
duke@1 596 return x == 0.0f && 1.0f / x > 0.0f;
duke@1 597 }
duke@1 598 /** Return true iff double number is positive 0.
duke@1 599 */
duke@1 600 private boolean isPosZero(double x) {
duke@1 601 return x == 0.0d && 1.0d / x > 0.0d;
duke@1 602 }
duke@1 603
duke@1 604 CondItem mkCond() {
duke@1 605 int ival = ((Number)value).intValue();
duke@1 606 return makeCondItem(ival != 0 ? goto_ : dontgoto);
duke@1 607 }
duke@1 608
duke@1 609 Item coerce(int targetcode) {
duke@1 610 if (typecode == targetcode) {
duke@1 611 return this;
duke@1 612 } else {
duke@1 613 switch (targetcode) {
duke@1 614 case INTcode:
duke@1 615 if (Code.truncate(typecode) == INTcode)
duke@1 616 return this;
duke@1 617 else
duke@1 618 return new ImmediateItem(
duke@1 619 syms.intType,
duke@1 620 ((Number)value).intValue());
duke@1 621 case LONGcode:
duke@1 622 return new ImmediateItem(
duke@1 623 syms.longType,
duke@1 624 ((Number)value).longValue());
duke@1 625 case FLOATcode:
duke@1 626 return new ImmediateItem(
duke@1 627 syms.floatType,
duke@1 628 ((Number)value).floatValue());
duke@1 629 case DOUBLEcode:
duke@1 630 return new ImmediateItem(
duke@1 631 syms.doubleType,
duke@1 632 ((Number)value).doubleValue());
duke@1 633 case BYTEcode:
duke@1 634 return new ImmediateItem(
duke@1 635 syms.byteType,
duke@1 636 (int)(byte)((Number)value).intValue());
duke@1 637 case CHARcode:
duke@1 638 return new ImmediateItem(
duke@1 639 syms.charType,
duke@1 640 (int)(char)((Number)value).intValue());
duke@1 641 case SHORTcode:
duke@1 642 return new ImmediateItem(
duke@1 643 syms.shortType,
duke@1 644 (int)(short)((Number)value).intValue());
duke@1 645 default:
duke@1 646 return super.coerce(targetcode);
duke@1 647 }
duke@1 648 }
duke@1 649 }
duke@1 650
duke@1 651 public String toString() {
duke@1 652 return "immediate(" + value + ")";
duke@1 653 }
duke@1 654 }
duke@1 655
duke@1 656 /** An item representing an assignment expressions.
duke@1 657 */
duke@1 658 class AssignItem extends Item {
duke@1 659
duke@1 660 /** The item representing the assignment's left hand side.
duke@1 661 */
duke@1 662 Item lhs;
duke@1 663
duke@1 664 AssignItem(Item lhs) {
duke@1 665 super(lhs.typecode);
duke@1 666 this.lhs = lhs;
duke@1 667 }
duke@1 668
duke@1 669 Item load() {
duke@1 670 lhs.stash(typecode);
duke@1 671 lhs.store();
duke@1 672 return stackItem[typecode];
duke@1 673 }
duke@1 674
duke@1 675 void duplicate() {
duke@1 676 load().duplicate();
duke@1 677 }
duke@1 678
duke@1 679 void drop() {
duke@1 680 lhs.store();
duke@1 681 }
duke@1 682
duke@1 683 void stash(int toscode) {
duke@1 684 assert false;
duke@1 685 }
duke@1 686
duke@1 687 int width() {
duke@1 688 return lhs.width() + Code.width(typecode);
duke@1 689 }
duke@1 690
duke@1 691 public String toString() {
duke@1 692 return "assign(lhs = " + lhs + ")";
duke@1 693 }
duke@1 694 }
duke@1 695
duke@1 696 /** An item representing a conditional or unconditional jump.
duke@1 697 */
duke@1 698 class CondItem extends Item {
duke@1 699
duke@1 700 /** A chain encomassing all jumps that can be taken
duke@1 701 * if the condition evaluates to true.
duke@1 702 */
duke@1 703 Chain trueJumps;
duke@1 704
duke@1 705 /** A chain encomassing all jumps that can be taken
duke@1 706 * if the condition evaluates to false.
duke@1 707 */
duke@1 708 Chain falseJumps;
duke@1 709
duke@1 710 /** The jump's opcode.
duke@1 711 */
duke@1 712 int opcode;
duke@1 713
duke@1 714 /*
duke@1 715 * An abstract syntax tree of this item. It is needed
duke@1 716 * for branch entries in 'CharacterRangeTable' attribute.
duke@1 717 */
duke@1 718 JCTree tree;
duke@1 719
duke@1 720 CondItem(int opcode, Chain truejumps, Chain falsejumps) {
duke@1 721 super(BYTEcode);
duke@1 722 this.opcode = opcode;
duke@1 723 this.trueJumps = truejumps;
duke@1 724 this.falseJumps = falsejumps;
duke@1 725 }
duke@1 726
duke@1 727 Item load() {
duke@1 728 Chain trueChain = null;
duke@1 729 Chain falseChain = jumpFalse();
duke@1 730 if (!isFalse()) {
duke@1 731 code.resolve(trueJumps);
duke@1 732 code.emitop0(iconst_1);
duke@1 733 trueChain = code.branch(goto_);
duke@1 734 }
duke@1 735 if (falseChain != null) {
duke@1 736 code.resolve(falseChain);
duke@1 737 code.emitop0(iconst_0);
duke@1 738 }
duke@1 739 code.resolve(trueChain);
duke@1 740 return stackItem[typecode];
duke@1 741 }
duke@1 742
duke@1 743 void duplicate() {
duke@1 744 load().duplicate();
duke@1 745 }
duke@1 746
duke@1 747 void drop() {
duke@1 748 load().drop();
duke@1 749 }
duke@1 750
duke@1 751 void stash(int toscode) {
duke@1 752 assert false;
duke@1 753 }
duke@1 754
duke@1 755 CondItem mkCond() {
duke@1 756 return this;
duke@1 757 }
duke@1 758
duke@1 759 Chain jumpTrue() {
duke@1 760 if (tree == null) return code.mergeChains(trueJumps, code.branch(opcode));
duke@1 761 // we should proceed further in -Xjcov mode only
duke@1 762 int startpc = code.curPc();
duke@1 763 Chain c = code.mergeChains(trueJumps, code.branch(opcode));
duke@1 764 code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc());
duke@1 765 return c;
duke@1 766 }
duke@1 767
duke@1 768 Chain jumpFalse() {
duke@1 769 if (tree == null) return code.mergeChains(falseJumps, code.branch(code.negate(opcode)));
duke@1 770 // we should proceed further in -Xjcov mode only
duke@1 771 int startpc = code.curPc();
duke@1 772 Chain c = code.mergeChains(falseJumps, code.branch(code.negate(opcode)));
duke@1 773 code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc());
duke@1 774 return c;
duke@1 775 }
duke@1 776
duke@1 777 CondItem negate() {
duke@1 778 CondItem c = new CondItem(code.negate(opcode), falseJumps, trueJumps);
duke@1 779 c.tree = tree;
duke@1 780 return c;
duke@1 781 }
duke@1 782
duke@1 783 int width() {
duke@1 784 // a CondItem doesn't have a size on the stack per se.
duke@1 785 throw new AssertionError();
duke@1 786 }
duke@1 787
duke@1 788 boolean isTrue() {
duke@1 789 return falseJumps == null && opcode == goto_;
duke@1 790 }
duke@1 791
duke@1 792 boolean isFalse() {
duke@1 793 return trueJumps == null && opcode == dontgoto;
duke@1 794 }
duke@1 795
duke@1 796 public String toString() {
duke@1 797 return "cond(" + Code.mnem(opcode) + ")";
duke@1 798 }
duke@1 799 }
duke@1 800 }

mercurial