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

Mon, 10 Jan 2011 15:08:31 -0800

author
jjg
date
Mon, 10 Jan 2011 15:08:31 -0800
changeset 816
7c537f4298fb
parent 798
4868a36f6fd8
child 820
2d5aff89aaa3
permissions
-rw-r--r--

6396503: javac should not require assertions enabled
Reviewed-by: mcimadamore

duke@1 1 /*
jjg@816 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.javac.jvm;
duke@1 27
duke@1 28 import com.sun.tools.javac.code.*;
duke@1 29 import com.sun.tools.javac.code.Symbol.*;
duke@1 30 import com.sun.tools.javac.code.Type.*;
duke@1 31 import com.sun.tools.javac.jvm.Code.*;
duke@1 32 import com.sun.tools.javac.tree.JCTree;
jjg@816 33 import com.sun.tools.javac.util.Assert;
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 *
jjg@581 46 * <p><b>This is NOT part of any supported API.
jjg@581 47 * If 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
jrose@267 142 /** Make an item representing a dynamically invoked method.
jrose@267 143 * @param member The represented symbol.
jrose@267 144 */
jrose@267 145 Item makeDynamicItem(Symbol member) {
jrose@267 146 return new DynamicItem(member);
jrose@267 147 }
jrose@267 148
duke@1 149 /** Make an item representing an instance variable or method.
duke@1 150 * @param member The represented symbol.
duke@1 151 * @param nonvirtual Is the reference not virtual? (true for constructors
duke@1 152 * and private members).
duke@1 153 */
duke@1 154 Item makeMemberItem(Symbol member, boolean nonvirtual) {
duke@1 155 return new MemberItem(member, nonvirtual);
duke@1 156 }
duke@1 157
duke@1 158 /** Make an item representing a literal.
duke@1 159 * @param type The literal's type.
duke@1 160 * @param value The literal's value.
duke@1 161 */
duke@1 162 Item makeImmediateItem(Type type, Object value) {
duke@1 163 return new ImmediateItem(type, value);
duke@1 164 }
duke@1 165
duke@1 166 /** Make an item representing an assignment expression.
duke@1 167 * @param lhs The item representing the assignment's left hand side.
duke@1 168 */
duke@1 169 Item makeAssignItem(Item lhs) {
duke@1 170 return new AssignItem(lhs);
duke@1 171 }
duke@1 172
duke@1 173 /** Make an item representing a conditional or unconditional jump.
duke@1 174 * @param opcode The jump's opcode.
duke@1 175 * @param trueJumps A chain encomassing all jumps that can be taken
duke@1 176 * if the condition evaluates to true.
duke@1 177 * @param falseJumps A chain encomassing all jumps that can be taken
duke@1 178 * if the condition evaluates to false.
duke@1 179 */
duke@1 180 CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
duke@1 181 return new CondItem(opcode, trueJumps, falseJumps);
duke@1 182 }
duke@1 183
duke@1 184 /** Make an item representing a conditional or unconditional jump.
duke@1 185 * @param opcode The jump's opcode.
duke@1 186 */
duke@1 187 CondItem makeCondItem(int opcode) {
duke@1 188 return makeCondItem(opcode, null, null);
duke@1 189 }
duke@1 190
duke@1 191 /** The base class of all items, which implements default behavior.
duke@1 192 */
duke@1 193 abstract class Item {
duke@1 194
duke@1 195 /** The type code of values represented by this item.
duke@1 196 */
duke@1 197 int typecode;
duke@1 198
duke@1 199 Item(int typecode) {
duke@1 200 this.typecode = typecode;
duke@1 201 }
duke@1 202
duke@1 203 /** Generate code to load this item onto stack.
duke@1 204 */
duke@1 205 Item load() {
duke@1 206 throw new AssertionError();
duke@1 207 }
duke@1 208
duke@1 209 /** Generate code to store top of stack into this item.
duke@1 210 */
duke@1 211 void store() {
duke@1 212 throw new AssertionError("store unsupported: " + this);
duke@1 213 }
duke@1 214
duke@1 215 /** Generate code to invoke method represented by this item.
duke@1 216 */
duke@1 217 Item invoke() {
duke@1 218 throw new AssertionError(this);
duke@1 219 }
duke@1 220
duke@1 221 /** Generate code to use this item twice.
duke@1 222 */
duke@1 223 void duplicate() {}
duke@1 224
duke@1 225 /** Generate code to avoid having to use this item.
duke@1 226 */
duke@1 227 void drop() {}
duke@1 228
duke@1 229 /** Generate code to stash a copy of top of stack - of typecode toscode -
duke@1 230 * under this item.
duke@1 231 */
duke@1 232 void stash(int toscode) {
duke@1 233 stackItem[toscode].duplicate();
duke@1 234 }
duke@1 235
duke@1 236 /** Generate code to turn item into a testable condition.
duke@1 237 */
duke@1 238 CondItem mkCond() {
duke@1 239 load();
duke@1 240 return makeCondItem(ifne);
duke@1 241 }
duke@1 242
duke@1 243 /** Generate code to coerce item to given type code.
duke@1 244 * @param targetcode The type code to coerce to.
duke@1 245 */
duke@1 246 Item coerce(int targetcode) {
duke@1 247 if (typecode == targetcode)
duke@1 248 return this;
duke@1 249 else {
duke@1 250 load();
duke@1 251 int typecode1 = Code.truncate(typecode);
duke@1 252 int targetcode1 = Code.truncate(targetcode);
duke@1 253 if (typecode1 != targetcode1) {
duke@1 254 int offset = targetcode1 > typecode1 ? targetcode1 - 1
duke@1 255 : targetcode1;
duke@1 256 code.emitop0(i2l + typecode1 * 3 + offset);
duke@1 257 }
duke@1 258 if (targetcode != targetcode1) {
duke@1 259 code.emitop0(int2byte + targetcode - BYTEcode);
duke@1 260 }
duke@1 261 return stackItem[targetcode];
duke@1 262 }
duke@1 263 }
duke@1 264
duke@1 265 /** Generate code to coerce item to given type.
duke@1 266 * @param targettype The type to coerce to.
duke@1 267 */
duke@1 268 Item coerce(Type targettype) {
duke@1 269 return coerce(Code.typecode(targettype));
duke@1 270 }
duke@1 271
duke@1 272 /** Return the width of this item on stack as a number of words.
duke@1 273 */
duke@1 274 int width() {
duke@1 275 return 0;
duke@1 276 }
duke@1 277
duke@1 278 public abstract String toString();
duke@1 279 }
duke@1 280
duke@1 281 /** An item representing a value on stack.
duke@1 282 */
duke@1 283 class StackItem extends Item {
duke@1 284
duke@1 285 StackItem(int typecode) {
duke@1 286 super(typecode);
duke@1 287 }
duke@1 288
duke@1 289 Item load() {
duke@1 290 return this;
duke@1 291 }
duke@1 292
duke@1 293 void duplicate() {
duke@1 294 code.emitop0(width() == 2 ? dup2 : dup);
duke@1 295 }
duke@1 296
duke@1 297 void drop() {
duke@1 298 code.emitop0(width() == 2 ? pop2 : pop);
duke@1 299 }
duke@1 300
duke@1 301 void stash(int toscode) {
duke@1 302 code.emitop0(
duke@1 303 (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
duke@1 304 }
duke@1 305
duke@1 306 int width() {
duke@1 307 return Code.width(typecode);
duke@1 308 }
duke@1 309
duke@1 310 public String toString() {
duke@1 311 return "stack(" + typecodeNames[typecode] + ")";
duke@1 312 }
duke@1 313 }
duke@1 314
duke@1 315 /** An item representing an indexed expression.
duke@1 316 */
duke@1 317 class IndexedItem extends Item {
duke@1 318
duke@1 319 IndexedItem(Type type) {
duke@1 320 super(Code.typecode(type));
duke@1 321 }
duke@1 322
duke@1 323 Item load() {
duke@1 324 code.emitop0(iaload + typecode);
duke@1 325 return stackItem[typecode];
duke@1 326 }
duke@1 327
duke@1 328 void store() {
duke@1 329 code.emitop0(iastore + typecode);
duke@1 330 }
duke@1 331
duke@1 332 void duplicate() {
duke@1 333 code.emitop0(dup2);
duke@1 334 }
duke@1 335
duke@1 336 void drop() {
duke@1 337 code.emitop0(pop2);
duke@1 338 }
duke@1 339
duke@1 340 void stash(int toscode) {
duke@1 341 code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
duke@1 342 }
duke@1 343
duke@1 344 int width() {
duke@1 345 return 2;
duke@1 346 }
duke@1 347
duke@1 348 public String toString() {
duke@1 349 return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
duke@1 350 }
duke@1 351 }
duke@1 352
duke@1 353 /** An item representing `this' or `super'.
duke@1 354 */
duke@1 355 class SelfItem extends Item {
duke@1 356
duke@1 357 /** Flag which determines whether this item represents `this' or `super'.
duke@1 358 */
duke@1 359 boolean isSuper;
duke@1 360
duke@1 361 SelfItem(boolean isSuper) {
duke@1 362 super(OBJECTcode);
duke@1 363 this.isSuper = isSuper;
duke@1 364 }
duke@1 365
duke@1 366 Item load() {
duke@1 367 code.emitop0(aload_0);
duke@1 368 return stackItem[typecode];
duke@1 369 }
duke@1 370
duke@1 371 public String toString() {
duke@1 372 return isSuper ? "super" : "this";
duke@1 373 }
duke@1 374 }
duke@1 375
duke@1 376 /** An item representing a local variable.
duke@1 377 */
duke@1 378 class LocalItem extends Item {
duke@1 379
duke@1 380 /** The variable's register.
duke@1 381 */
duke@1 382 int reg;
duke@1 383
duke@1 384 /** The variable's type.
duke@1 385 */
duke@1 386 Type type;
duke@1 387
duke@1 388 LocalItem(Type type, int reg) {
duke@1 389 super(Code.typecode(type));
jjg@816 390 Assert.check(reg >= 0);
duke@1 391 this.type = type;
duke@1 392 this.reg = reg;
duke@1 393 }
duke@1 394
duke@1 395 Item load() {
duke@1 396 if (reg <= 3)
duke@1 397 code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
duke@1 398 else
duke@1 399 code.emitop1w(iload + Code.truncate(typecode), reg);
duke@1 400 return stackItem[typecode];
duke@1 401 }
duke@1 402
duke@1 403 void store() {
duke@1 404 if (reg <= 3)
duke@1 405 code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
duke@1 406 else
duke@1 407 code.emitop1w(istore + Code.truncate(typecode), reg);
duke@1 408 code.setDefined(reg);
duke@1 409 }
duke@1 410
duke@1 411 void incr(int x) {
duke@1 412 if (typecode == INTcode && x >= -32768 && x <= 32767) {
duke@1 413 code.emitop1w(iinc, reg, x);
duke@1 414 } else {
duke@1 415 load();
duke@1 416 if (x >= 0) {
duke@1 417 makeImmediateItem(syms.intType, x).load();
duke@1 418 code.emitop0(iadd);
duke@1 419 } else {
duke@1 420 makeImmediateItem(syms.intType, -x).load();
duke@1 421 code.emitop0(isub);
duke@1 422 }
duke@1 423 makeStackItem(syms.intType).coerce(typecode);
duke@1 424 store();
duke@1 425 }
duke@1 426 }
duke@1 427
duke@1 428 public String toString() {
duke@1 429 return "localItem(type=" + type + "; reg=" + reg + ")";
duke@1 430 }
duke@1 431 }
duke@1 432
duke@1 433 /** An item representing a static variable or method.
duke@1 434 */
duke@1 435 class StaticItem extends Item {
duke@1 436
duke@1 437 /** The represented symbol.
duke@1 438 */
duke@1 439 Symbol member;
duke@1 440
duke@1 441 StaticItem(Symbol member) {
duke@1 442 super(Code.typecode(member.erasure(types)));
duke@1 443 this.member = member;
duke@1 444 }
duke@1 445
duke@1 446 Item load() {
duke@1 447 code.emitop2(getstatic, pool.put(member));
duke@1 448 return stackItem[typecode];
duke@1 449 }
duke@1 450
duke@1 451 void store() {
duke@1 452 code.emitop2(putstatic, pool.put(member));
duke@1 453 }
duke@1 454
duke@1 455 Item invoke() {
duke@1 456 MethodType mtype = (MethodType)member.erasure(types);
duke@1 457 int rescode = Code.typecode(mtype.restype);
duke@1 458 code.emitInvokestatic(pool.put(member), mtype);
duke@1 459 return stackItem[rescode];
duke@1 460 }
duke@1 461
duke@1 462 public String toString() {
duke@1 463 return "static(" + member + ")";
duke@1 464 }
duke@1 465 }
duke@1 466
jrose@267 467 /** An item representing a dynamic call site.
jrose@267 468 */
jrose@267 469 class DynamicItem extends StaticItem {
jrose@267 470 DynamicItem(Symbol member) {
jrose@267 471 super(member);
jjg@816 472 Assert.check(member.owner == syms.invokeDynamicType.tsym);
jrose@267 473 }
jrose@267 474
jrose@267 475 Item load() {
jjg@816 476 Assert.error();
jrose@267 477 return null;
jrose@267 478 }
jrose@267 479
jrose@267 480 void store() {
jjg@816 481 Assert.error();
jrose@267 482 }
jrose@267 483
jrose@267 484 Item invoke() {
jrose@267 485 // assert target.hasNativeInvokeDynamic();
jrose@267 486 MethodType mtype = (MethodType)member.erasure(types);
jrose@267 487 int rescode = Code.typecode(mtype.restype);
jrose@267 488 ClassFile.NameAndType descr = new ClassFile.NameAndType(member.name, mtype);
jrose@267 489 code.emitInvokedynamic(pool.put(descr), mtype);
jrose@267 490 return stackItem[rescode];
jrose@267 491 }
jrose@267 492
jrose@267 493 public String toString() {
jrose@267 494 return "dynamic(" + member + ")";
jrose@267 495 }
jrose@267 496 }
jrose@267 497
jrose@267 498
duke@1 499 /** An item representing an instance variable or method.
duke@1 500 */
duke@1 501 class MemberItem extends Item {
duke@1 502
duke@1 503 /** The represented symbol.
duke@1 504 */
duke@1 505 Symbol member;
duke@1 506
duke@1 507 /** Flag that determines whether or not access is virtual.
duke@1 508 */
duke@1 509 boolean nonvirtual;
duke@1 510
duke@1 511 MemberItem(Symbol member, boolean nonvirtual) {
duke@1 512 super(Code.typecode(member.erasure(types)));
duke@1 513 this.member = member;
duke@1 514 this.nonvirtual = nonvirtual;
duke@1 515 }
duke@1 516
duke@1 517 Item load() {
duke@1 518 code.emitop2(getfield, pool.put(member));
duke@1 519 return stackItem[typecode];
duke@1 520 }
duke@1 521
duke@1 522 void store() {
duke@1 523 code.emitop2(putfield, pool.put(member));
duke@1 524 }
duke@1 525
duke@1 526 Item invoke() {
duke@1 527 MethodType mtype = (MethodType)member.externalType(types);
duke@1 528 int rescode = Code.typecode(mtype.restype);
duke@1 529 if ((member.owner.flags() & Flags.INTERFACE) != 0) {
duke@1 530 code.emitInvokeinterface(pool.put(member), mtype);
duke@1 531 } else if (nonvirtual) {
duke@1 532 code.emitInvokespecial(pool.put(member), mtype);
duke@1 533 } else {
duke@1 534 code.emitInvokevirtual(pool.put(member), mtype);
duke@1 535 }
duke@1 536 return stackItem[rescode];
duke@1 537 }
duke@1 538
duke@1 539 void duplicate() {
duke@1 540 stackItem[OBJECTcode].duplicate();
duke@1 541 }
duke@1 542
duke@1 543 void drop() {
duke@1 544 stackItem[OBJECTcode].drop();
duke@1 545 }
duke@1 546
duke@1 547 void stash(int toscode) {
duke@1 548 stackItem[OBJECTcode].stash(toscode);
duke@1 549 }
duke@1 550
duke@1 551 int width() {
duke@1 552 return 1;
duke@1 553 }
duke@1 554
duke@1 555 public String toString() {
duke@1 556 return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
duke@1 557 }
duke@1 558 }
duke@1 559
duke@1 560 /** An item representing a literal.
duke@1 561 */
duke@1 562 class ImmediateItem extends Item {
duke@1 563
duke@1 564 /** The literal's value.
duke@1 565 */
duke@1 566 Object value;
duke@1 567
duke@1 568 ImmediateItem(Type type, Object value) {
duke@1 569 super(Code.typecode(type));
duke@1 570 this.value = value;
duke@1 571 }
duke@1 572
duke@1 573 private void ldc() {
duke@1 574 int idx = pool.put(value);
duke@1 575 if (typecode == LONGcode || typecode == DOUBLEcode) {
duke@1 576 code.emitop2(ldc2w, idx);
duke@1 577 } else if (idx <= 255) {
duke@1 578 code.emitop1(ldc1, idx);
duke@1 579 } else {
duke@1 580 code.emitop2(ldc2, idx);
duke@1 581 }
duke@1 582 }
duke@1 583
duke@1 584 Item load() {
duke@1 585 switch (typecode) {
duke@1 586 case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
duke@1 587 int ival = ((Number)value).intValue();
duke@1 588 if (-1 <= ival && ival <= 5)
duke@1 589 code.emitop0(iconst_0 + ival);
duke@1 590 else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
duke@1 591 code.emitop1(bipush, ival);
duke@1 592 else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
duke@1 593 code.emitop2(sipush, ival);
duke@1 594 else
duke@1 595 ldc();
duke@1 596 break;
duke@1 597 case LONGcode:
duke@1 598 long lval = ((Number)value).longValue();
duke@1 599 if (lval == 0 || lval == 1)
duke@1 600 code.emitop0(lconst_0 + (int)lval);
duke@1 601 else
duke@1 602 ldc();
duke@1 603 break;
duke@1 604 case FLOATcode:
duke@1 605 float fval = ((Number)value).floatValue();
duke@1 606 if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
duke@1 607 code.emitop0(fconst_0 + (int)fval);
duke@1 608 else {
duke@1 609 ldc();
duke@1 610 }
duke@1 611 break;
duke@1 612 case DOUBLEcode:
duke@1 613 double dval = ((Number)value).doubleValue();
duke@1 614 if (isPosZero(dval) || dval == 1.0)
duke@1 615 code.emitop0(dconst_0 + (int)dval);
duke@1 616 else
duke@1 617 ldc();
duke@1 618 break;
duke@1 619 case OBJECTcode:
duke@1 620 ldc();
duke@1 621 break;
duke@1 622 default:
jjg@816 623 Assert.error();
duke@1 624 }
duke@1 625 return stackItem[typecode];
duke@1 626 }
duke@1 627 //where
duke@1 628 /** Return true iff float number is positive 0.
duke@1 629 */
duke@1 630 private boolean isPosZero(float x) {
duke@1 631 return x == 0.0f && 1.0f / x > 0.0f;
duke@1 632 }
duke@1 633 /** Return true iff double number is positive 0.
duke@1 634 */
duke@1 635 private boolean isPosZero(double x) {
duke@1 636 return x == 0.0d && 1.0d / x > 0.0d;
duke@1 637 }
duke@1 638
duke@1 639 CondItem mkCond() {
duke@1 640 int ival = ((Number)value).intValue();
duke@1 641 return makeCondItem(ival != 0 ? goto_ : dontgoto);
duke@1 642 }
duke@1 643
duke@1 644 Item coerce(int targetcode) {
duke@1 645 if (typecode == targetcode) {
duke@1 646 return this;
duke@1 647 } else {
duke@1 648 switch (targetcode) {
duke@1 649 case INTcode:
duke@1 650 if (Code.truncate(typecode) == INTcode)
duke@1 651 return this;
duke@1 652 else
duke@1 653 return new ImmediateItem(
duke@1 654 syms.intType,
duke@1 655 ((Number)value).intValue());
duke@1 656 case LONGcode:
duke@1 657 return new ImmediateItem(
duke@1 658 syms.longType,
duke@1 659 ((Number)value).longValue());
duke@1 660 case FLOATcode:
duke@1 661 return new ImmediateItem(
duke@1 662 syms.floatType,
duke@1 663 ((Number)value).floatValue());
duke@1 664 case DOUBLEcode:
duke@1 665 return new ImmediateItem(
duke@1 666 syms.doubleType,
duke@1 667 ((Number)value).doubleValue());
duke@1 668 case BYTEcode:
duke@1 669 return new ImmediateItem(
duke@1 670 syms.byteType,
duke@1 671 (int)(byte)((Number)value).intValue());
duke@1 672 case CHARcode:
duke@1 673 return new ImmediateItem(
duke@1 674 syms.charType,
duke@1 675 (int)(char)((Number)value).intValue());
duke@1 676 case SHORTcode:
duke@1 677 return new ImmediateItem(
duke@1 678 syms.shortType,
duke@1 679 (int)(short)((Number)value).intValue());
duke@1 680 default:
duke@1 681 return super.coerce(targetcode);
duke@1 682 }
duke@1 683 }
duke@1 684 }
duke@1 685
duke@1 686 public String toString() {
duke@1 687 return "immediate(" + value + ")";
duke@1 688 }
duke@1 689 }
duke@1 690
duke@1 691 /** An item representing an assignment expressions.
duke@1 692 */
duke@1 693 class AssignItem extends Item {
duke@1 694
duke@1 695 /** The item representing the assignment's left hand side.
duke@1 696 */
duke@1 697 Item lhs;
duke@1 698
duke@1 699 AssignItem(Item lhs) {
duke@1 700 super(lhs.typecode);
duke@1 701 this.lhs = lhs;
duke@1 702 }
duke@1 703
duke@1 704 Item load() {
duke@1 705 lhs.stash(typecode);
duke@1 706 lhs.store();
duke@1 707 return stackItem[typecode];
duke@1 708 }
duke@1 709
duke@1 710 void duplicate() {
duke@1 711 load().duplicate();
duke@1 712 }
duke@1 713
duke@1 714 void drop() {
duke@1 715 lhs.store();
duke@1 716 }
duke@1 717
duke@1 718 void stash(int toscode) {
jjg@816 719 Assert.error();
duke@1 720 }
duke@1 721
duke@1 722 int width() {
duke@1 723 return lhs.width() + Code.width(typecode);
duke@1 724 }
duke@1 725
duke@1 726 public String toString() {
duke@1 727 return "assign(lhs = " + lhs + ")";
duke@1 728 }
duke@1 729 }
duke@1 730
duke@1 731 /** An item representing a conditional or unconditional jump.
duke@1 732 */
duke@1 733 class CondItem extends Item {
duke@1 734
duke@1 735 /** A chain encomassing all jumps that can be taken
duke@1 736 * if the condition evaluates to true.
duke@1 737 */
duke@1 738 Chain trueJumps;
duke@1 739
duke@1 740 /** A chain encomassing all jumps that can be taken
duke@1 741 * if the condition evaluates to false.
duke@1 742 */
duke@1 743 Chain falseJumps;
duke@1 744
duke@1 745 /** The jump's opcode.
duke@1 746 */
duke@1 747 int opcode;
duke@1 748
duke@1 749 /*
duke@1 750 * An abstract syntax tree of this item. It is needed
duke@1 751 * for branch entries in 'CharacterRangeTable' attribute.
duke@1 752 */
duke@1 753 JCTree tree;
duke@1 754
duke@1 755 CondItem(int opcode, Chain truejumps, Chain falsejumps) {
duke@1 756 super(BYTEcode);
duke@1 757 this.opcode = opcode;
duke@1 758 this.trueJumps = truejumps;
duke@1 759 this.falseJumps = falsejumps;
duke@1 760 }
duke@1 761
duke@1 762 Item load() {
duke@1 763 Chain trueChain = null;
duke@1 764 Chain falseChain = jumpFalse();
duke@1 765 if (!isFalse()) {
duke@1 766 code.resolve(trueJumps);
duke@1 767 code.emitop0(iconst_1);
duke@1 768 trueChain = code.branch(goto_);
duke@1 769 }
duke@1 770 if (falseChain != null) {
duke@1 771 code.resolve(falseChain);
duke@1 772 code.emitop0(iconst_0);
duke@1 773 }
duke@1 774 code.resolve(trueChain);
duke@1 775 return stackItem[typecode];
duke@1 776 }
duke@1 777
duke@1 778 void duplicate() {
duke@1 779 load().duplicate();
duke@1 780 }
duke@1 781
duke@1 782 void drop() {
duke@1 783 load().drop();
duke@1 784 }
duke@1 785
duke@1 786 void stash(int toscode) {
jjg@816 787 Assert.error();
duke@1 788 }
duke@1 789
duke@1 790 CondItem mkCond() {
duke@1 791 return this;
duke@1 792 }
duke@1 793
duke@1 794 Chain jumpTrue() {
jjg@507 795 if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode));
duke@1 796 // we should proceed further in -Xjcov mode only
duke@1 797 int startpc = code.curPc();
jjg@507 798 Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
duke@1 799 code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc());
duke@1 800 return c;
duke@1 801 }
duke@1 802
duke@1 803 Chain jumpFalse() {
jjg@507 804 if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
duke@1 805 // we should proceed further in -Xjcov mode only
duke@1 806 int startpc = code.curPc();
jjg@507 807 Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
duke@1 808 code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc());
duke@1 809 return c;
duke@1 810 }
duke@1 811
duke@1 812 CondItem negate() {
jjg@507 813 CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps);
duke@1 814 c.tree = tree;
duke@1 815 return c;
duke@1 816 }
duke@1 817
duke@1 818 int width() {
duke@1 819 // a CondItem doesn't have a size on the stack per se.
duke@1 820 throw new AssertionError();
duke@1 821 }
duke@1 822
duke@1 823 boolean isTrue() {
duke@1 824 return falseJumps == null && opcode == goto_;
duke@1 825 }
duke@1 826
duke@1 827 boolean isFalse() {
duke@1 828 return trueJumps == null && opcode == dontgoto;
duke@1 829 }
duke@1 830
duke@1 831 public String toString() {
duke@1 832 return "cond(" + Code.mnem(opcode) + ")";
duke@1 833 }
duke@1 834 }
duke@1 835 }

mercurial