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

Tue, 31 Mar 2009 11:07:55 -0700

author
jjg
date
Tue, 31 Mar 2009 11:07:55 -0700
changeset 256
89f67512b635
parent 117
24a47c3062fe
child 267
e2722bd43f3a
permissions
-rw-r--r--

6817950: refactor ClassReader to improve attribute handling
Reviewed-by: mcimadamore

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

mercurial